diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-03-23 08:59:35 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-03-23 08:59:35 +0000 |
| commit | 23c670442392af1c75b935b3296ae2fc4fd094ba (patch) | |
| tree | 3137ff26aa5ed14ff8acb77007d4bc6ec2fff217 | |
| parent | 92c784dd057d8f110c677516909162c4cd4d00da (diff) | |
fix: support multiple enabled Google Task lists and Calendars
- Update Google API interfaces with setters for list/calendar IDs
- Update fetchCalendarEvents and fetchGoogleTasks to use enabled IDs from source_configs
- Update timeline logic tests to reflect interface changes and seed config data
- Ensure dashboard respects user-selected lists from settings
| -rw-r--r-- | .agent/worklog.md | 2 | ||||
| -rw-r--r-- | internal/api/google_calendar.go | 5 | ||||
| -rw-r--r-- | internal/api/google_tasks.go | 5 | ||||
| -rw-r--r-- | internal/api/interfaces.go | 2 | ||||
| -rw-r--r-- | internal/handlers/handlers.go | 34 | ||||
| -rw-r--r-- | internal/handlers/timeline_logic_test.go | 10 |
6 files changed, 57 insertions, 1 deletions
diff --git a/.agent/worklog.md b/.agent/worklog.md index ad751bb..563ce18 100644 --- a/.agent/worklog.md +++ b/.agent/worklog.md @@ -4,7 +4,7 @@ Cleaned Backlog ## Recently Completed -- **Google Tasks Unification** — implemented SQLite caching layer for Google Tasks, integrated with unified `Atoms` loop (now showing in Tasks tab), updated Planning tab to include Google Tasks, and enhanced Quick Add form with Todoist project selector. +- **Google Tasks Unification & Multi-List Support** — implemented SQLite caching layer for Google Tasks, integrated with unified `Atoms` loop (now showing in Tasks tab), updated Planning tab to include Google Tasks, and enhanced Quick Add form with Todoist project selector. Fixed issue where only the default list was shown; now respects all enabled task lists and calendars from settings. - **Agent Context API Phase 2 & 3** — Write operations (complete, uncomplete, update due, update task), create operations (task, shopping), and management UI in settings. Fixed SQLite timestamp scanning issue. - **Sync log + clear cache feedback** — migration `016_sync_log.sql`, store methods `AddSyncLogEntry`/`GetRecentSyncLog`, handler changes, template partial `sync-log.html` - `HandleClearCache` now renders sync log HTML (replaces `hx-swap="none"`) diff --git a/internal/api/google_calendar.go b/internal/api/google_calendar.go index 68d423b..8bb3143 100644 --- a/internal/api/google_calendar.go +++ b/internal/api/google_calendar.go @@ -176,6 +176,11 @@ func (c *GoogleCalendarClient) GetEventsByDateRange(ctx context.Context, start, return deduplicateEvents(allEvents), nil } +// SetCalendarIDs updates the calendar IDs used by the client +func (c *GoogleCalendarClient) SetCalendarIDs(ids []string) { + c.calendarIDs = ids +} + // GetCalendarList returns all calendars accessible to the user func (c *GoogleCalendarClient) GetCalendarList(ctx context.Context) ([]models.CalendarInfo, error) { list, err := c.srv.CalendarList.List().Do() diff --git a/internal/api/google_tasks.go b/internal/api/google_tasks.go index 8a6488e..da3cd3b 100644 --- a/internal/api/google_tasks.go +++ b/internal/api/google_tasks.go @@ -175,6 +175,11 @@ func (c *GoogleTasksClient) UncompleteTask(ctx context.Context, listID, taskID s return nil } +// SetTaskListID updates the task list ID(s) used by the client +func (c *GoogleTasksClient) SetTaskListID(id string) { + c.tasklistID = id +} + // GetTaskLists returns all task lists accessible to the user func (c *GoogleTasksClient) GetTaskLists(ctx context.Context) ([]models.TaskListInfo, error) { list, err := c.srv.Tasklists.List().Context(ctx).Do() diff --git a/internal/api/interfaces.go b/internal/api/interfaces.go index cec64be..99701a1 100644 --- a/internal/api/interfaces.go +++ b/internal/api/interfaces.go @@ -39,6 +39,7 @@ type GoogleCalendarAPI interface { GetUpcomingEvents(ctx context.Context, maxResults int) ([]models.CalendarEvent, error) GetEventsByDateRange(ctx context.Context, start, end time.Time) ([]models.CalendarEvent, error) GetCalendarList(ctx context.Context) ([]models.CalendarInfo, error) + SetCalendarIDs(ids []string) } // GoogleTasksAPI defines the interface for Google Tasks operations @@ -48,6 +49,7 @@ type GoogleTasksAPI interface { CompleteTask(ctx context.Context, listID, taskID string) error UncompleteTask(ctx context.Context, listID, taskID string) error GetTaskLists(ctx context.Context) ([]models.TaskListInfo, error) + SetTaskListID(id string) } // Ensure concrete types implement interfaces diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go index 8abd4d7..fa97be0 100644 --- a/internal/handlers/handlers.go +++ b/internal/handlers/handlers.go @@ -373,6 +373,24 @@ func (h *Handler) fetchCalendarEvents(ctx context.Context, forceRefresh bool) ([ if h.googleCalendarClient == nil { return nil, nil } + + // Get enabled calendars from store + configs, _ := h.store.GetSourceConfigsBySource("gcal") + var enabledIDs []string + for _, cfg := range configs { + if cfg.Enabled { + enabledIDs = append(enabledIDs, cfg.ItemID) + } + } + + // If none enabled but we have a default from config, use that as a fallback + // (or if we want to respect the toggle strictly, we should only use enabled ones) + if len(enabledIDs) == 0 { + return nil, nil + } + + h.googleCalendarClient.SetCalendarIDs(enabledIDs) + fetcher := &CacheFetcher[models.CalendarEvent]{ Store: h.store, CacheKey: store.CacheKeyGoogleCalendar, @@ -389,6 +407,22 @@ func (h *Handler) fetchGoogleTasks(ctx context.Context, forceRefresh bool) ([]mo if h.googleTasksClient == nil { return nil, nil } + + // Get enabled task lists from store + configs, _ := h.store.GetSourceConfigsBySource("gtasks") + var enabledIDs []string + for _, cfg := range configs { + if cfg.Enabled { + enabledIDs = append(enabledIDs, cfg.ItemID) + } + } + + if len(enabledIDs) == 0 { + return nil, nil + } + + h.googleTasksClient.SetTaskListID(strings.Join(enabledIDs, ",")) + fetcher := &CacheFetcher[models.GoogleTask]{ Store: h.store, CacheKey: store.CacheKeyGoogleTasks, diff --git a/internal/handlers/timeline_logic_test.go b/internal/handlers/timeline_logic_test.go index d6959da..03bc291 100644 --- a/internal/handlers/timeline_logic_test.go +++ b/internal/handlers/timeline_logic_test.go @@ -33,6 +33,8 @@ func (m *MockCalendarClient) GetCalendarList(ctx context.Context) ([]models.Cale return nil, m.Err } +func (m *MockCalendarClient) SetCalendarIDs(ids []string) {} + func setupTestStore(t *testing.T) *store.Store { t.Helper() tempDir := t.TempDir() @@ -398,6 +400,14 @@ func TestFetchCalendarEvents_CacheFallbackOnAPIError(t *testing.T) { t.Fatalf("Failed to update cache metadata: %v", err) } + // Enable the calendar in config + err = db.SyncSourceConfigs("gcal", "calendar", []models.SourceConfig{ + {Source: "gcal", ItemType: "calendar", ItemID: "e-cached", ItemName: "Cached", Enabled: true}, + }) + if err != nil { + t.Fatalf("Failed to seed calendar config: %v", err) + } + // Create handler with a failing calendar client failingCal := &MockCalendarClient{Err: fmt.Errorf("API unavailable")} h := &Handler{ |
