From 23c670442392af1c75b935b3296ae2fc4fd094ba Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Mon, 23 Mar 2026 08:59:35 +0000 Subject: 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 --- internal/api/google_calendar.go | 5 +++++ internal/api/google_tasks.go | 5 +++++ internal/api/interfaces.go | 2 ++ internal/handlers/handlers.go | 34 ++++++++++++++++++++++++++++++++ internal/handlers/timeline_logic_test.go | 10 ++++++++++ 5 files changed, 56 insertions(+) (limited to 'internal') 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{ -- cgit v1.2.3