Skip to content

feat: add GitHub-style activity calendar heatmap to Overview - #136

Merged
jschloman merged 1 commit into
mainfrom
pr/activity-calendar-heatmap
Jul 13, 2026
Merged

jschloman merged 1 commit into
mainfrom
pr/activity-calendar-heatmap

Conversation

@jschloman

Copy link
Copy Markdown
Collaborator

Summary

  • Adds get_daily_activity(df, swarm_df=None, source="all") to analysis_utils.py — computes zero-filled per-calendar-day activity counts across Last.fm scrobbles and/or Swarm check-ins, using the exact date-normalization patterns already established elsewhere in this codebase.
  • Adds a GitHub-contribution-graph-style calendar heatmap to the Overview page (_build_calendar_heatmap_figure() + render_activity_calendar()), with an inline source selector ("All activity" / "Music" / "Check-ins") shown only when Swarm data is actually loaded.
  • Rejected the issue's suggested plotly-calplot dependency — confirmed unmaintained (no repo activity in the last month, maintainer stepped away) — in favor of a hand-rolled go.Heatmap using only plotly/pandas, both already declared dependencies. Zero new packages added.
  • The selector intentionally omits "Fitness"/"Films" options from the issue's original draft — pages/fitness.py and pages/culture.py are still stub pages with no real backing data source, so those options would be dead UI.
  • New CALENDAR_HEATMAP_SCALE constant in components/theme.py (the exact 4-stop indigo→cyan scale from the issue), reused rather than hardcoded inline.
  • Zero-fill guarantee: every day in range renders as a real 0-valued cell (not a gap/NaN), so the calendar always looks complete even on sparse data.

Test plan

  • New unit tests for get_daily_activity(): zero-fill across internal gaps, multi-source summation, source isolation, None/empty input handling, invalid-source ValueError, tz-naive output guarantee (tests/test_analysis_utils.py)
  • New tests asserting directly on the constructed Plotly trace (colorscale, zero-fill z-grid values, hovertemplate) rather than just "a chart rendered" — first such precedent in this codebase (tests/test_overview.py)
  • New tests for all 3 source-selector branches, the no-radio-when-no-swarm-data case, and graceful st.info degradation on an empty result
  • Full root suite: pytest -n auto → 1048 passed
  • Full packages/localizer suite: pytest -n auto → 431 passed
  • ruff check . / ruff format --check . — clean
  • mypy — clean

Closes #27

Adds get_daily_activity() (analysis_utils.py) to compute zero-filled
per-day activity counts across Last.fm scrobbles and Swarm check-ins,
and wires a hand-rolled go.Heatmap calendar into the Overview page with
an inline source selector (All activity/Music/Check-ins). Rejected the
issue's suggested plotly-calplot dependency (unmaintained) in favor of
a zero-new-dependency implementation using only already-declared
plotly/pandas. The selector omits Fitness/Films options since those
pages have no real backing data source yet.

Closes #27

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4VmTCuiAVzu9ftLjocP6d
@jschloman
jschloman merged commit f8a88e8 into main Jul 13, 2026
2 checks passed
@jschloman
jschloman deleted the pr/activity-calendar-heatmap branch July 13, 2026 18:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: activity calendar heatmap (GitHub-style)

1 participant