Implement entity structs for Kanboard API responses
Add all entity structs matching Kanboard's JSON-RPC API format: Entity structs: - Project, Task, Column, Category, Comment - TaskLink, TaskFile, Tag - TaskStatus enum (StatusActive, StatusInactive) Request structs: - CreateTaskRequest with omitempty for optional fields - UpdateTaskRequest with pointer fields for zero-value distinction Custom JSON types for Kanboard's string-encoded values: - StringBool - handles "0"/"1" string booleans - StringInt - handles string-encoded integers - StringInt64 - handles string-encoded int64 values All structs properly handle Kanboard's quirky JSON format where numeric fields are often returned as quoted strings. Closes: kanboard-api-cyc
This commit is contained in:
parent
dbac08ac1e
commit
a38e62e77a
3 changed files with 779 additions and 1 deletions
257
types.go
Normal file
257
types.go
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
package kanboard
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// TaskStatus represents the status of a task.
|
||||
type TaskStatus int
|
||||
|
||||
const (
|
||||
// StatusActive represents an open/active task.
|
||||
StatusActive TaskStatus = 1
|
||||
// StatusInactive represents a closed/inactive task.
|
||||
StatusInactive TaskStatus = 0
|
||||
)
|
||||
|
||||
// StringBool is a bool that can be unmarshaled from a string "0" or "1".
|
||||
type StringBool bool
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler.
|
||||
func (b *StringBool) UnmarshalJSON(data []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(data, &s); err != nil {
|
||||
// Try as raw bool
|
||||
var boolVal bool
|
||||
if err := json.Unmarshal(data, &boolVal); err != nil {
|
||||
return err
|
||||
}
|
||||
*b = StringBool(boolVal)
|
||||
return nil
|
||||
}
|
||||
*b = s == "1" || s == "true"
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON implements json.Marshaler.
|
||||
func (b StringBool) MarshalJSON() ([]byte, error) {
|
||||
if b {
|
||||
return []byte(`"1"`), nil
|
||||
}
|
||||
return []byte(`"0"`), nil
|
||||
}
|
||||
|
||||
// StringInt is an int that can be unmarshaled from a JSON string.
|
||||
type StringInt int
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler.
|
||||
func (i *StringInt) UnmarshalJSON(data []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(data, &s); err != nil {
|
||||
// Try as raw int
|
||||
var intVal int
|
||||
if err := json.Unmarshal(data, &intVal); err != nil {
|
||||
return err
|
||||
}
|
||||
*i = StringInt(intVal)
|
||||
return nil
|
||||
}
|
||||
if s == "" {
|
||||
*i = 0
|
||||
return nil
|
||||
}
|
||||
val, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*i = StringInt(val)
|
||||
return nil
|
||||
}
|
||||
|
||||
// StringInt64 is an int64 that can be unmarshaled from a JSON string.
|
||||
type StringInt64 int64
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler.
|
||||
func (i *StringInt64) UnmarshalJSON(data []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(data, &s); err != nil {
|
||||
// Try as raw int64
|
||||
var intVal int64
|
||||
if err := json.Unmarshal(data, &intVal); err != nil {
|
||||
return err
|
||||
}
|
||||
*i = StringInt64(intVal)
|
||||
return nil
|
||||
}
|
||||
if s == "" {
|
||||
*i = 0
|
||||
return nil
|
||||
}
|
||||
val, err := strconv.ParseInt(s, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*i = StringInt64(val)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Project represents a Kanboard project (board).
|
||||
type Project struct {
|
||||
ID StringInt `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
IsActive StringBool `json:"is_active"`
|
||||
Token string `json:"token"`
|
||||
LastModified Timestamp `json:"last_modified"`
|
||||
IsPublic StringBool `json:"is_public"`
|
||||
IsPrivate StringBool `json:"is_private"`
|
||||
DefaultSwimlane string `json:"default_swimlane"`
|
||||
ShowDefaultSwimlane StringBool `json:"show_default_swimlane"`
|
||||
Identifier string `json:"identifier"`
|
||||
StartDate Timestamp `json:"start_date"`
|
||||
EndDate Timestamp `json:"end_date"`
|
||||
OwnerID StringInt `json:"owner_id"`
|
||||
PriorityDefault StringInt `json:"priority_default"`
|
||||
PriorityStart StringInt `json:"priority_start"`
|
||||
PriorityEnd StringInt `json:"priority_end"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
// Task represents a Kanboard task.
|
||||
type Task struct {
|
||||
ID StringInt `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
DateCreation Timestamp `json:"date_creation"`
|
||||
DateModification Timestamp `json:"date_modification"`
|
||||
DateCompleted Timestamp `json:"date_completed"`
|
||||
DateStarted Timestamp `json:"date_started"`
|
||||
DateDue Timestamp `json:"date_due"`
|
||||
ColorID string `json:"color_id"`
|
||||
ProjectID StringInt `json:"project_id"`
|
||||
ColumnID StringInt `json:"column_id"`
|
||||
OwnerID StringInt `json:"owner_id"`
|
||||
CreatorID StringInt `json:"creator_id"`
|
||||
Position StringInt `json:"position"`
|
||||
IsActive StringBool `json:"is_active"`
|
||||
Score StringInt `json:"score"`
|
||||
CategoryID StringInt `json:"category_id"`
|
||||
SwimlaneID StringInt `json:"swimlane_id"`
|
||||
Priority StringInt `json:"priority"`
|
||||
Reference string `json:"reference"`
|
||||
RecurrenceStatus StringInt `json:"recurrence_status"`
|
||||
RecurrenceTrigger StringInt `json:"recurrence_trigger"`
|
||||
RecurrenceFactor StringInt `json:"recurrence_factor"`
|
||||
RecurrenceTimeframe StringInt `json:"recurrence_timeframe"`
|
||||
RecurrenceBasedate StringInt `json:"recurrence_basedate"`
|
||||
RecurrenceParent StringInt `json:"recurrence_parent"`
|
||||
RecurrenceChild StringInt `json:"recurrence_child"`
|
||||
}
|
||||
|
||||
// Column represents a Kanboard column.
|
||||
type Column struct {
|
||||
ID StringInt `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Position StringInt `json:"position"`
|
||||
ProjectID StringInt `json:"project_id"`
|
||||
TaskLimit StringInt `json:"task_limit"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// Category represents a Kanboard category.
|
||||
type Category struct {
|
||||
ID StringInt `json:"id"`
|
||||
Name string `json:"name"`
|
||||
ProjectID StringInt `json:"project_id"`
|
||||
ColorID string `json:"color_id"`
|
||||
}
|
||||
|
||||
// Comment represents a Kanboard comment.
|
||||
type Comment struct {
|
||||
ID StringInt `json:"id"`
|
||||
TaskID StringInt `json:"task_id"`
|
||||
UserID StringInt `json:"user_id"`
|
||||
DateCreation Timestamp `json:"date_creation"`
|
||||
Content string `json:"comment"`
|
||||
Username string `json:"username"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
AvatarPath string `json:"avatar_path"`
|
||||
}
|
||||
|
||||
// TaskLink represents a link between two tasks.
|
||||
type TaskLink struct {
|
||||
ID StringInt `json:"id"`
|
||||
LinkID StringInt `json:"link_id"`
|
||||
TaskID StringInt `json:"task_id"`
|
||||
OppositeTaskID StringInt `json:"opposite_task_id"`
|
||||
Label string `json:"label"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
// TaskFile represents a file attached to a task.
|
||||
type TaskFile struct {
|
||||
ID StringInt `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
IsImage StringBool `json:"is_image"`
|
||||
TaskID StringInt `json:"task_id"`
|
||||
DateCreation Timestamp `json:"date_creation"`
|
||||
UserID StringInt `json:"user_id"`
|
||||
Size StringInt64 `json:"size"`
|
||||
}
|
||||
|
||||
// Tag represents a Kanboard tag.
|
||||
type Tag struct {
|
||||
ID StringInt `json:"id"`
|
||||
Name string `json:"name"`
|
||||
ProjectID StringInt `json:"project_id"`
|
||||
ColorID string `json:"color_id"`
|
||||
}
|
||||
|
||||
// CreateTaskRequest is the request payload for creating a task.
|
||||
type CreateTaskRequest struct {
|
||||
Title string `json:"title"`
|
||||
ProjectID int `json:"project_id"`
|
||||
Description string `json:"description,omitempty"`
|
||||
ColumnID int `json:"column_id,omitempty"`
|
||||
OwnerID int `json:"owner_id,omitempty"`
|
||||
CreatorID int `json:"creator_id,omitempty"`
|
||||
ColorID string `json:"color_id,omitempty"`
|
||||
CategoryID int `json:"category_id,omitempty"`
|
||||
DateDue int64 `json:"date_due,omitempty"`
|
||||
Score int `json:"score,omitempty"`
|
||||
SwimlaneID int `json:"swimlane_id,omitempty"`
|
||||
Priority int `json:"priority,omitempty"`
|
||||
Reference string `json:"reference,omitempty"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
DateStarted int64 `json:"date_started,omitempty"`
|
||||
RecurrenceStatus int `json:"recurrence_status,omitempty"`
|
||||
RecurrenceTrigger int `json:"recurrence_trigger,omitempty"`
|
||||
RecurrenceFactor int `json:"recurrence_factor,omitempty"`
|
||||
RecurrenceTimeframe int `json:"recurrence_timeframe,omitempty"`
|
||||
RecurrenceBasedate int `json:"recurrence_basedate,omitempty"`
|
||||
}
|
||||
|
||||
// UpdateTaskRequest is the request payload for updating a task.
|
||||
// Pointer fields allow distinguishing between "not set" and "set to zero value".
|
||||
type UpdateTaskRequest struct {
|
||||
ID int `json:"id"`
|
||||
Title *string `json:"title,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
ColorID *string `json:"color_id,omitempty"`
|
||||
OwnerID *int `json:"owner_id,omitempty"`
|
||||
CategoryID *int `json:"category_id,omitempty"`
|
||||
DateDue *int64 `json:"date_due,omitempty"`
|
||||
Score *int `json:"score,omitempty"`
|
||||
Priority *int `json:"priority,omitempty"`
|
||||
Reference *string `json:"reference,omitempty"`
|
||||
DateStarted *int64 `json:"date_started,omitempty"`
|
||||
RecurrenceStatus *int `json:"recurrence_status,omitempty"`
|
||||
RecurrenceTrigger *int `json:"recurrence_trigger,omitempty"`
|
||||
RecurrenceFactor *int `json:"recurrence_factor,omitempty"`
|
||||
RecurrenceTimeframe *int `json:"recurrence_timeframe,omitempty"`
|
||||
RecurrenceBasedate *int `json:"recurrence_basedate,omitempty"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue