feat(tasks): a row says what is underneath it, and what is attached

A task with three sub-tasks looked exactly like one without, and so did a task
with a drawing on it. The whole reason to attach something is that somebody
should find it.

Counted in the same query as the tasks, as correlated subqueries: a list of fifty
would otherwise be a hundred more lookups, and the point is that you see this
without asking.

Said as a fraction rather than a total. "3" tells you something is there; "1/3"
tells you whether there is anything left to do, which is the question a list is
for. All-done goes accent-coloured, because "3/3" and "1/3" are the two answers
you actually look for and only one of them is good news.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kristian Wind
2026-08-18 09:05:18 +02:00
co-authored by Claude Opus 5
parent eaff890860
commit 101ca33069
+13 -6
View File
@@ -33,9 +33,14 @@ type taskJSON struct {
Completed bool `json:"completed"`
CompletedAt string `json:"completed_at,omitempty"`
CreatedBy string `json:"created_by"`
SortOrder float64 `json:"sort_order"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
// What the row can say without being opened. Sent with every task rather than
// fetched when one is opened, because the point is that you see it in the list.
SubtaskCount int `json:"subtask_count,omitempty"`
SubtaskDone int `json:"subtask_done,omitempty"`
AttachmentCount int `json:"attachment_count,omitempty"`
SortOrder float64 `json:"sort_order"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
func toTaskJSON(t store.Task) taskJSON {
@@ -45,9 +50,11 @@ func toTaskJSON(t store.Task) taskJSON {
DueDate: t.DueDate, DurationMin: t.DurationMin, Recurrence: t.RecurrenceRule,
RepeatText: recurrence.Describe(t.RecurrenceRule),
AssigneeID: t.AssigneeID, Completed: t.Completed(), CreatedBy: t.CreatedBy,
SortOrder: t.SortOrder,
CreatedAt: t.CreatedAt.Format(time.RFC3339),
UpdatedAt: t.UpdatedAt.Format(time.RFC3339),
SubtaskCount: t.SubtaskCount, SubtaskDone: t.SubtaskDone,
AttachmentCount: t.AttachmentCount,
SortOrder: t.SortOrder,
CreatedAt: t.CreatedAt.Format(time.RFC3339),
UpdatedAt: t.UpdatedAt.Format(time.RFC3339),
// Never nil: a client iterating labels should not have to null-check first.
Labels: t.Labels,
}