summaryrefslogtreecommitdiff
path: root/internal/handlers/widget_test.go
AgeCommit message (Collapse)Author
2026-07-16Surface budget_status on GET /api/widget when tracked tasks existPeter Stone
Wires ComputeBudgetPeriod together with availability blocks, tracked project/label sets, calendar events, and native tasks into a new computeBudgetStatus helper on *Handler. HandleWidgetGet now populates WidgetResponse.BudgetStatus with today/week periods, but only when at least one incomplete budget-tracked task exists in the rolling week window -- otherwise the field is omitted entirely so unconfigured users see no new UI. Errors are logged and swallowed, matching the existing resilience pattern for this widget endpoint. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PQaPGQVSfmKUiHXB87qRTC
2026-07-16test(tasks): add tests for project color threadingPeter Stone
Tests verify ProjectColor is populated in BuildTimeline and copied to WidgetItem.
2026-07-16test(tasks): add test cases for project and label endpointsPeter Stone
Tests for HandleWidgetProjectsGet, HandleWidgetProjectsCreate, HandleWidgetTaskProject, HandleWidgetTaskLabels, HandleWidgetLabelsGet, HandleWidgetLabelsColorSet, and the extended HandleWidgetTaskDetail response with project and labels fields. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-16fix(tasks): return ErrNativeTaskNotFound from UpdateNativeTask on stale idPeter Stone
HandleWidgetTaskUpdate now returns 404 instead of silently succeeding when the widget's cached task id no longer exists, matching every other native_tasks mutator's checkRowsAffected pattern. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
2026-07-16feat(tasks): add HTTP endpoints for task detail, update, and recurrencePeter Stone
GET /api/widget/task, POST /api/widget/task/update, POST /api/widget/task/recurrence, POST /api/widget/task/next-date. Doot-only; the recurrence/next-date fields are null in the detail response for a non-recurring task.
2026-07-16fix(widget): forward End for all-day multi-day calendar eventsPeter Stone
A genuine all-day Google Calendar event spanning multiple days (e.g. a 3-day conference) never got its EndTime forwarded to the widget client, since the conversion only set End when !IsAllDay. The client has no way to detect a multi-day span without both Start and End.
2026-07-16feat(widget): tap event to open its source directly, drop detail popupPeter Stone
Tapping a calendar event (or any event-type item) now opens the event's URL (Google Calendar, Plan to Eat, etc.) directly instead of showing an intermediate popup with an "Open in Calendar" button. Removes EventDetailActivity and the recurrence-schedule lookup it was the only consumer of: WidgetRepository.getRecurrence, the Go /api/widget/recurrence endpoint, HandleWidgetRecurrence, GoogleCalendarAPI.GetRecurrenceRule, and formatRecurrence, plus their tests. RecurringEventID itself stays -- it's general calendar-sync metadata used elsewhere in the timeline pipeline, not exclusive to the removed popup.
2026-07-13Merge github/master: reconcile with parallel widget workPeter Stone
Another session pushed 27 commits in parallel covering quick-add, event detail popups, recurrence display, overdue badges, a manual refresh button, and its own fix for the same overdue-tasks bug (via a separate GetOverdueNativeTasks fetch folded into BuildTimeline, rather than widening GetNativeTasksByDateRange's bound directly). Reconciled rather than blindly taking one side: - Reverted GetNativeTasksByDateRange to its original bounded query and kept upstream's GetOverdueNativeTasks + BuildTimeline fold-in as the sole overdue mechanism for native tasks, to avoid double-counting overdue items (my widened query + their separate fetch would have both returned them). Re-pointed the regression test at the now-correct contract and added a store-level test for GetOverdueNativeTasks directly. - Kept my GetGoogleTasksByDateRange fix as-is (single unbounded query) -- upstream never touched Google Tasks overdue handling, so there's no duplication risk there. - Rewove WidgetRoot's LazyColumn structure (added for scrolling) around upstream's new header buttons, pinned all-day event rows, and the enhanced TomorrowSection, none of which were written LazyColumn-aware since that work landed on this side only. - Combined both sides' additions to TaskDetailActivity/TaskDetailSheet (description-edit detail popup + due-date reschedule label) and WidgetRepository/Actions (optimistic local removal + refresh button wiring) -- these were independent, non-overlapping features that both needed to survive. - Renumbered the migration collision: both sides independently added a migration numbered 022. Card-description was already applied to the live production DB under that filename earlier this session (migrations are tracked by filename), so it keeps 022; the recurring-event-id migration, never deployed under any name here, moves to 023. Verified: go build clean, full test suite passes (only the two pre-existing agent-handler failures and the pre-existing models package build error remain, both confirmed unrelated via git stash before this session began), and a dry run against a copy of the live production database applies both migrations cleanly with no re-run conflicts. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL
2026-07-13feat(widget): editable task details, scrollable list, and overdue-task fixesPeter Stone
- Add description editing to the widget's task detail popup for doot/gtasks/trello, backed by new GET /api/widget/detail and POST /api/widget/update endpoints - Make Google Tasks and Trello cards completable via the widget (Trello completion archives the card); fix Trello description never being fetched, which meant saving could silently wipe a card's real desc - Fix google_tasks.due_date/updated_at (TEXT columns) never round-tripping through sql.NullTime, which broke cached Google Tasks reads whenever the cache was valid - Fix native-task and Google-Task date-range queries excluding anything due before the window start, which dropped incomplete tasks off the widget the moment their due day passed (the "overdue tasks disappeared" bug) - Fix native task description edits blanking the task's title - Make the widget's day list scroll (LazyColumn) instead of clipping - Optimistically remove a task from the widget immediately on completion, ahead of the authoritative background refresh Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL
2026-07-12feat(widget): add recurrence lookup endpoint (GET /api/widget/recurrence)Peter Stone
2026-07-12feat(widget): capture and forward RecurringEventID for calendar eventsPeter Stone
2026-07-12feat(widget): add POST /api/widget/add for quick-addPeter Stone
2026-07-12feat(widget): add DueDate field for doot tasks to the widget APIPeter Stone
2026-07-12feat(widget): forward IsOverdue from TimelineItem to WidgetItem APIPeter Stone
2026-07-12fix(widget): pin all-day calendar events to the top instead of losing themPeter Stone
WidgetItem.isAllDay was carried by the client's data model but nothing ever read it. All-day events had no Start at all, so they fell into the same floating-task queue as ordinary untimed tasks; if enough tasks were ahead of one in the queue, SlotPacker could assign it an hour slot past the visible grid range entirely -- not merely unpinned, actually invisible. Server: TimelineItemToWidgetItem now populates Start for all-day CALENDAR EVENTS specifically (their real event date), while leaving undated doot/gtask tasks -- also flagged IsAllDay as a "no specific time" fallback, a different concept -- on the existing nil-Start floating behavior. Client: all-day events are filtered out of the hourly grid/floating-task pipeline entirely, bucketed by day using the new Start date, and rendered in a new pinned AllDayRow section right after the TODAY/TOMORROW headers.
2026-07-12fix(widget): surface unmatched task IDs instead of silently no-oppingPeter Stone
CompleteNativeTask/UncompleteNativeTask/RescheduleNativeTask ran a plain UPDATE ... WHERE id = ? and returned whatever error Exec gave back -- which is nil even when 0 rows match, since that's not a SQL error. A stale or wrong id from the widget looked identical to a real completion: HTTP 200, nothing changed in the database. Real incident: 1 of 3 widget completeTask taps silently no-opped this way. Now checks RowsAffected() and returns ErrNativeTaskNotFound (mirrors the existing pattern in sqlite.go's ApproveAgentSession/DenyAgentSession). HandleWidgetComplete and HandleWidgetReschedule surface this as 404 instead of a fake 200, so the widget can tell 'nothing changed' apart from 'it worked.'
2026-07-06feat: remove Todoist integration entirelyDoot Agent
Native tasks (native_tasks table) fully replace Todoist. All Todoist API code, store functions, handlers, routes, templates, and tests have been removed. Migration 021 drops the now-unused tasks cache table. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05fix: native tasks missing from Tasks tab and blank title on completionDoot Agent
Bug 1: BuildUnifiedAtomList never called GetNativeTasks(), so doot-sourced tasks were absent from the web Tasks tab. Added GetNativeTasks() fetch and NativeTaskToAtom conversion (new model helper, SourceDoot constant). Bug 2: handleAtomToggle called getAtomDetails after CompleteNativeTask, but GetNativeTasks filters WHERE completed=0, so the task was already gone and the title came back blank. Moved getAtomDetails call to before the completion switch so all sources (including doot) capture title/dueDate first. Also fixed widget_test.go compile error: TestHandleWidgetComplete_NonTodoist called HandleWidgetComplete as a package-level function but it is a method on *Handler. Rewrote the file as package handlers (internal) and construct &Handler{} directly. Regression tests added for both bugs in atoms_test.go and handlers_test.go. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29fix: widget handler timezone, auth guard, and type switch clarityPeter Stone
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29feat: add widget HTTP handlers with bearer token authPeter Stone
Implements WidgetAuthMiddleware (static bearer token), TimelineItemToWidgetItem (conversion helper), HandleWidgetGet (today's items as JSON), and HandleWidgetComplete (proxies task completion to Todoist). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>