Implement data models for Checkvist API entities
Add models.go with all data structures: - Checklist struct with fields for ID, Name, Public, Archived, etc. - Task struct with full task data including status, priority, due dates - TaskStatus enum (StatusOpen, StatusClosed, StatusInvalidated) - Note struct for task comments - User struct for user information - Tags type as map[string]bool for efficient lookup - DueDate struct with smart syntax support and constructors (DueAt, DueString, DueInDays) and constants (DueToday, DueTomorrow, DueNextWeek, DueNextMonth) Closes checkvist-api-e9p
This commit is contained in:
parent
7af39edcd1
commit
61431dfaeb
2 changed files with 162 additions and 1 deletions
|
|
@ -16,7 +16,7 @@
|
|||
{"id":"checkvist-api-br3","title":"Core API Operations","description":"Phase 2: Implement CRUD operations for Checklists, Tasks, and Notes. All P0 (must-have) features for the library.","status":"open","priority":0,"issue_type":"epic","owner":"mail@oliverjakoubek.de","created_at":"2026-01-14T12:30:53.20627925+01:00","created_by":"Oliver Jakoubek","updated_at":"2026-01-14T12:30:53.20627925+01:00"}
|
||||
{"id":"checkvist-api-c2k","title":"Implement Checklist operations","description":"Create checklists.go with ChecklistService:\n- client.Checklists() returns ChecklistService\n- List(ctx) ([]Checklist, error) - GET /checklists.json\n- Get(ctx, id) (*Checklist, error) - GET /checklists/{id}.json\n- Create(ctx, name) (*Checklist, error) - POST /checklists.json\n- Update(ctx, id, name) (*Checklist, error) - PUT /checklists/{id}.json\n- Delete(ctx, id) error - DELETE /checklists/{id}.json\n- Support archived filter in List\nContext support for all methods.","status":"open","priority":0,"issue_type":"feature","owner":"mail@oliverjakoubek.de","created_at":"2026-01-14T12:30:53.566197933+01:00","created_by":"Oliver Jakoubek","updated_at":"2026-01-14T12:30:53.566197933+01:00","dependencies":[{"issue_id":"checkvist-api-c2k","depends_on_id":"checkvist-api-8u6","type":"blocks","created_at":"2026-01-14T12:32:54.533462004+01:00","created_by":"Oliver Jakoubek"},{"issue_id":"checkvist-api-c2k","depends_on_id":"checkvist-api-lpn","type":"blocks","created_at":"2026-01-14T12:32:54.859645166+01:00","created_by":"Oliver Jakoubek"}]}
|
||||
{"id":"checkvist-api-cb8","title":"Extended Features","description":"Phase 3: Implement P1 (should-have) features including client-side filtering and builder patterns for fluent interfaces.","status":"open","priority":1,"issue_type":"epic","owner":"mail@oliverjakoubek.de","created_at":"2026-01-14T12:30:55.624242123+01:00","created_by":"Oliver Jakoubek","updated_at":"2026-01-14T12:30:55.624242123+01:00"}
|
||||
{"id":"checkvist-api-e9p","title":"Implement data models","description":"Create models.go with all data structures:\n- Checklist struct (ID, Name, Public, Archived, ReadOnly, TaskCount, TaskCompleted, Tags, TagsAsText, UpdatedAt)\n- Task struct (ID, ChecklistID, ParentID, Content, Status, Position, Priority, Tags, TagsAsText, DueDateRaw, DueDate, AssigneeIDs, CommentsCount, UpdateLine, UpdatedAt, CreatedAt, Children, Notes)\n- TaskStatus enum (StatusOpen=0, StatusClosed=1, StatusInvalidated=2)\n- Note struct (ID, TaskID, Comment, UpdatedAt, CreatedAt)\n- Tags type (map[string]bool)\n- User struct (ID, Username, Email)\n- DueDate struct with constructors (DueAt, DueString, DueInDays) and constants (DueToday, DueTomorrow, DueNextWeek, DueNextMonth)","status":"open","priority":0,"issue_type":"task","owner":"mail@oliverjakoubek.de","created_at":"2026-01-14T12:31:06.900391036+01:00","created_by":"Oliver Jakoubek","updated_at":"2026-01-14T12:31:06.900391036+01:00","dependencies":[{"issue_id":"checkvist-api-e9p","depends_on_id":"checkvist-api-5wr","type":"blocks","created_at":"2026-01-14T12:32:46.433908937+01:00","created_by":"Oliver Jakoubek"}]}
|
||||
{"id":"checkvist-api-e9p","title":"Implement data models","description":"Create models.go with all data structures:\n- Checklist struct (ID, Name, Public, Archived, ReadOnly, TaskCount, TaskCompleted, Tags, TagsAsText, UpdatedAt)\n- Task struct (ID, ChecklistID, ParentID, Content, Status, Position, Priority, Tags, TagsAsText, DueDateRaw, DueDate, AssigneeIDs, CommentsCount, UpdateLine, UpdatedAt, CreatedAt, Children, Notes)\n- TaskStatus enum (StatusOpen=0, StatusClosed=1, StatusInvalidated=2)\n- Note struct (ID, TaskID, Comment, UpdatedAt, CreatedAt)\n- Tags type (map[string]bool)\n- User struct (ID, Username, Email)\n- DueDate struct with constructors (DueAt, DueString, DueInDays) and constants (DueToday, DueTomorrow, DueNextWeek, DueNextMonth)","status":"closed","priority":0,"issue_type":"task","owner":"mail@oliverjakoubek.de","created_at":"2026-01-14T12:31:06.900391036+01:00","created_by":"Oliver Jakoubek","updated_at":"2026-01-14T13:22:22.273934664+01:00","closed_at":"2026-01-14T13:22:22.273934664+01:00","close_reason":"Closed","dependencies":[{"issue_id":"checkvist-api-e9p","depends_on_id":"checkvist-api-5wr","type":"blocks","created_at":"2026-01-14T12:32:46.433908937+01:00","created_by":"Oliver Jakoubek"}]}
|
||||
{"id":"checkvist-api-lpn","title":"Implement authentication with auto token renewal","description":"Add to client.go:\n- Authenticate(ctx context.Context) error - explicit login\n- refreshToken(ctx context.Context) error - token renewal\n- ensureAuthenticated(ctx context.Context) error - auto-auth before requests\n- CurrentUser(ctx context.Context) (*User, error) - get logged in user\n- Token management: store token and expiry, auto-refresh before expiry\n- Thread-safe token access using mutex\n- Support for optional 2FA token\nAPI endpoints:\n- POST /auth/login.json?version=2 (login)\n- POST /auth/refresh_token.json?version=2 (refresh)\n- GET /auth/curr_user.json (current user)\nToken sent via X-Client-Token header","status":"open","priority":0,"issue_type":"task","owner":"mail@oliverjakoubek.de","created_at":"2026-01-14T12:31:08.358878117+01:00","created_by":"Oliver Jakoubek","updated_at":"2026-01-14T12:31:08.358878117+01:00","dependencies":[{"issue_id":"checkvist-api-lpn","depends_on_id":"checkvist-api-ymg","type":"blocks","created_at":"2026-01-14T12:32:47.656124681+01:00","created_by":"Oliver Jakoubek"}]}
|
||||
{"id":"checkvist-api-mnh","title":"Implement error types and sentinel errors","description":"Create errors.go with:\n- APIError struct (StatusCode, Message, RequestID, Err) with Error() and Unwrap() methods\n- Sentinel errors: ErrUnauthorized, ErrNotFound, ErrRateLimited, ErrBadRequest, ErrServerError\n- Helper function to create APIError from HTTP response","status":"open","priority":0,"issue_type":"task","owner":"mail@oliverjakoubek.de","created_at":"2026-01-14T12:31:07.619359293+01:00","created_by":"Oliver Jakoubek","updated_at":"2026-01-14T12:31:07.619359293+01:00","dependencies":[{"issue_id":"checkvist-api-mnh","depends_on_id":"checkvist-api-5wr","type":"blocks","created_at":"2026-01-14T12:32:46.754134799+01:00","created_by":"Oliver Jakoubek"}]}
|
||||
{"id":"checkvist-api-nrk","title":"Create README with quickstart","description":"Create README.md (in English) with:\n- Project description\n- Installation: go get code.beautifulmachines.dev/jakoubek/checkvist-api\n- Quick start example (init client, list checklists, create task)\n- API overview (Checklists, Tasks, Notes, Filters)\n- Builder pattern examples\n- Error handling examples\n- Configuration options\n- Link to GoDoc\n- License (MIT)","status":"open","priority":0,"issue_type":"task","owner":"mail@oliverjakoubek.de","created_at":"2026-01-14T12:31:38.724338606+01:00","created_by":"Oliver Jakoubek","updated_at":"2026-01-14T12:31:38.724338606+01:00","dependencies":[{"issue_id":"checkvist-api-nrk","depends_on_id":"checkvist-api-c2k","type":"blocks","created_at":"2026-01-14T12:33:15.785698203+01:00","created_by":"Oliver Jakoubek"},{"issue_id":"checkvist-api-nrk","depends_on_id":"checkvist-api-rl9","type":"blocks","created_at":"2026-01-14T12:33:16.125115134+01:00","created_by":"Oliver Jakoubek"}]}
|
||||
|
|
|
|||
161
models.go
161
models.go
|
|
@ -1,4 +1,165 @@
|
|||
package checkvist
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// models.go contains data structures for Checkvist entities:
|
||||
// Checklist, Task, Note, User, Tags, TaskStatus, and DueDate.
|
||||
|
||||
// TaskStatus represents the status of a task.
|
||||
type TaskStatus int
|
||||
|
||||
const (
|
||||
// StatusOpen indicates the task is open/incomplete.
|
||||
StatusOpen TaskStatus = 0
|
||||
// StatusClosed indicates the task is completed.
|
||||
StatusClosed TaskStatus = 1
|
||||
// StatusInvalidated indicates the task has been invalidated.
|
||||
StatusInvalidated TaskStatus = 2
|
||||
)
|
||||
|
||||
// String returns the string representation of the TaskStatus.
|
||||
func (s TaskStatus) String() string {
|
||||
switch s {
|
||||
case StatusOpen:
|
||||
return "open"
|
||||
case StatusClosed:
|
||||
return "closed"
|
||||
case StatusInvalidated:
|
||||
return "invalidated"
|
||||
default:
|
||||
return fmt.Sprintf("unknown(%d)", s)
|
||||
}
|
||||
}
|
||||
|
||||
// Tags represents a set of tags as a map for efficient lookup.
|
||||
type Tags map[string]bool
|
||||
|
||||
// Checklist represents a Checkvist checklist.
|
||||
type Checklist struct {
|
||||
// ID is the unique identifier of the checklist.
|
||||
ID int `json:"id"`
|
||||
// Name is the title of the checklist.
|
||||
Name string `json:"name"`
|
||||
// Public indicates whether the checklist is publicly accessible.
|
||||
Public bool `json:"public"`
|
||||
// Archived indicates whether the checklist is archived.
|
||||
Archived bool `json:"archived"`
|
||||
// ReadOnly indicates whether the checklist is read-only for the current user.
|
||||
ReadOnly bool `json:"read_only"`
|
||||
// TaskCount is the total number of tasks in the checklist.
|
||||
TaskCount int `json:"task_count"`
|
||||
// TaskCompleted is the number of completed tasks in the checklist.
|
||||
TaskCompleted int `json:"task_completed"`
|
||||
// Tags contains the parsed tags from TagsAsText.
|
||||
Tags Tags `json:"-"`
|
||||
// TagsAsText is the raw tags string from the API.
|
||||
TagsAsText string `json:"tags_as_text"`
|
||||
// UpdatedAt is the timestamp of the last update.
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// Task represents a task within a Checkvist checklist.
|
||||
type Task struct {
|
||||
// ID is the unique identifier of the task.
|
||||
ID int `json:"id"`
|
||||
// ChecklistID is the ID of the checklist this task belongs to.
|
||||
ChecklistID int `json:"checklist_id"`
|
||||
// ParentID is the ID of the parent task, or 0 if this is a root task.
|
||||
ParentID int `json:"parent_id"`
|
||||
// Content is the text content of the task.
|
||||
Content string `json:"content"`
|
||||
// Status is the current status of the task (open, closed, invalidated).
|
||||
Status TaskStatus `json:"status"`
|
||||
// Position is the position of the task within its siblings.
|
||||
Position int `json:"position"`
|
||||
// Priority is the priority level (1 = highest, 2 = high, 0 = normal).
|
||||
Priority int `json:"priority"`
|
||||
// Tags contains the parsed tags from TagsAsText.
|
||||
Tags Tags `json:"-"`
|
||||
// TagsAsText is the raw tags string from the API.
|
||||
TagsAsText string `json:"tags_as_text"`
|
||||
// DueDateRaw is the raw due date string from the API.
|
||||
DueDateRaw string `json:"due"`
|
||||
// DueDate is the parsed due date, if available in ISO format.
|
||||
DueDate *time.Time `json:"-"`
|
||||
// AssigneeIDs contains the IDs of users assigned to this task.
|
||||
AssigneeIDs []int `json:"assignee_ids"`
|
||||
// CommentsCount is the number of notes/comments on this task.
|
||||
CommentsCount int `json:"comments_count"`
|
||||
// UpdateLine contains brief update information.
|
||||
UpdateLine string `json:"update_line"`
|
||||
// UpdatedAt is the timestamp of the last update.
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
// CreatedAt is the timestamp when the task was created.
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
// Children contains nested child tasks (when fetched with tree structure).
|
||||
Children []*Task `json:"tasks,omitempty"`
|
||||
// Notes contains the comments/notes attached to this task.
|
||||
Notes []Note `json:"notes,omitempty"`
|
||||
}
|
||||
|
||||
// Note represents a comment/note on a task.
|
||||
type Note struct {
|
||||
// ID is the unique identifier of the note.
|
||||
ID int `json:"id"`
|
||||
// TaskID is the ID of the task this note belongs to.
|
||||
TaskID int `json:"task_id"`
|
||||
// Comment is the text content of the note.
|
||||
Comment string `json:"comment"`
|
||||
// UpdatedAt is the timestamp of the last update.
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
// CreatedAt is the timestamp when the note was created.
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// User represents a Checkvist user.
|
||||
type User struct {
|
||||
// ID is the unique identifier of the user.
|
||||
ID int `json:"id"`
|
||||
// Username is the user's display name.
|
||||
Username string `json:"username"`
|
||||
// Email is the user's email address.
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
// DueDate represents a due date for task creation using Checkvist's smart syntax.
|
||||
type DueDate struct {
|
||||
value string
|
||||
}
|
||||
|
||||
// Common due date constants using Checkvist's smart syntax.
|
||||
var (
|
||||
// DueToday sets the due date to today.
|
||||
DueToday = DueDate{value: "^today"}
|
||||
// DueTomorrow sets the due date to tomorrow.
|
||||
DueTomorrow = DueDate{value: "^tomorrow"}
|
||||
// DueNextWeek sets the due date to next week.
|
||||
DueNextWeek = DueDate{value: "^next week"}
|
||||
// DueNextMonth sets the due date to next month.
|
||||
DueNextMonth = DueDate{value: "^next month"}
|
||||
)
|
||||
|
||||
// DueAt creates a DueDate from a Go time.Time value.
|
||||
func DueAt(t time.Time) DueDate {
|
||||
return DueDate{value: "^" + t.Format("2006-01-02")}
|
||||
}
|
||||
|
||||
// DueString creates a DueDate from a raw smart syntax string.
|
||||
// The string should use Checkvist's smart syntax (e.g., "^2026-02-01", "^friday").
|
||||
func DueString(s string) DueDate {
|
||||
return DueDate{value: s}
|
||||
}
|
||||
|
||||
// DueInDays creates a DueDate for n days from now.
|
||||
func DueInDays(n int) DueDate {
|
||||
t := time.Now().AddDate(0, 0, n)
|
||||
return DueDate{value: "^" + t.Format("2006-01-02")}
|
||||
}
|
||||
|
||||
// String returns the smart syntax string for the due date.
|
||||
func (d DueDate) String() string {
|
||||
return d.value
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue