Skip to content

Phase 2 (Milestone 2): Dashboards#14

Closed
kosminus wants to merge 2 commits into
feat/phase2-durable-artifactsfrom
feat/phase2-dashboards
Closed

Phase 2 (Milestone 2): Dashboards#14
kosminus wants to merge 2 commits into
feat/phase2-durable-artifactsfrom
feat/phase2-dashboards

Conversation

@kosminus

@kosminus kosminus commented Jun 8, 2026

Copy link
Copy Markdown
Owner

Summary

Milestone 2 of Phase 2 — composes the M1 saved queries/charts into workspace-shared dashboards: a draggable tile grid with per-tile refresh and dashboard-level filters that flow into every tile's SQL.

Stacked on #13 (M1). This PR's base is feat/phase2-durable-artifacts, so the diff shows only the M2 changes. Merge #13 first (or retarget to main after it merges).

Backend

  • Models Dashboard + DashboardTile — the first workspace-scoped artifact (workspace_id, not connection-scoped); migration 006.
  • dashboard_service: _assert_access (workspace scope + role, mirrors connection_service), CRUD, tile CRUD, bulk update_layout, and run_tile. Tiles run through saved_query_service.run_saved_query, so they authorize via the saved query's connection and reuse the M1 result cache.
  • Filters reuse the saved-query param system: dashboard filter values are passed as supplied params; render_sql only consumes the {{name}}s a tile's SQL references and ignores the rest — no per-tile wiring.
  • _finalize refreshes server-side onupdate timestamps after UPDATEs to avoid a lazy-load (MissingGreenlet) during async response serialization.
  • Endpoints under /dashboards (workspace-scoped via get_org_context, like teams.py); registered in router.py.

Frontend (react-grid-layout)

  • Dashboards list + detail page (draggable/resizable grid), tile cards rendering a chart (reusing ChartView) or table with a cached/fresh badge and optional auto-refresh, a filters bar, add-tile and dashboard-form modals.
  • Extracted a shared ParamInputs component (used by both the M1 saved-query run drawer and the dashboard filters bar); routes + nav item.

Notable decisions

  • Dashboards are workspace-scoped (compose tiles across connections); saved queries/charts remain connection-scoped.
  • Filters chosen to reuse the param system rather than a separate mechanism — minimal surface, and tile authorization + caching come for free.
  • Tile = saved query (data) + optional chart (viz; null = table). Deleting a saved query cascades to its tiles.

Verification

  • Backend: full pytest 155 passed (9 new: _assert_access scope/role rules + filter passthrough); ruff clean.
  • Live (Docker + real Postgres): migration 005→006 ran on startup; created a dashboard with a {{min_stage}} filter, added a chart tile + a table tile, ran both (filter value changes the row count → confirms filters reach the SQL), confirmed M1 cache reuse on re-run, and verified drag/resize layout persistence across reload. All update paths (dashboard/tile/layout) return 200 after the _finalize fix.
  • Frontend: ESLint clean; tsc -b && vite build succeeds (react-grid-layout compiles with React 19).

Notes

  • Frontend container needs npm install (or image rebuild) to pick up react-grid-layout — same anonymous-node_modules-volume caveat as recharts in M1.
  • AuthZ (viewer-denied writes, cross-workspace 404, private hiding) is covered by unit tests since DISABLE_AUTH=true makes the local container act as admin.

🤖 Generated with Claude Code

cosmin chauciuc and others added 2 commits June 8, 2026 12:19
Composes saved queries/charts into workspace-shared dashboards: a draggable
tile grid with per-tile refresh and dashboard-level filters that flow into
each tile's SQL.

Backend:
- Models Dashboard + DashboardTile (workspace-scoped — the first artifact
  scoped by workspace_id rather than connection); migration 006.
- dashboard_service: _assert_access (workspace scope + role, mirrors
  connection_service), CRUD, tile CRUD, bulk layout update, and run_tile.
  Tiles run via saved_query_service.run_saved_query, so they authorize through
  the saved query's connection and reuse the M1 result cache.
- Filters reuse the saved-query param system: dashboard filter values are
  passed as supplied params; render_sql only consumes the ones a tile's SQL
  references and ignores the rest — no per-tile wiring.
- _finalize refreshes server-side onupdate timestamps after UPDATEs to avoid
  a lazy-load (MissingGreenlet) during async response serialization.
- Endpoints registered under /dashboards (get_org_context, like teams.py).

Frontend (react-grid-layout):
- Dashboards list + detail (draggable/resizable grid), tile cards that render
  a chart (reusing ChartView) or table with a cached/fresh badge and optional
  auto-refresh, a filters bar, add-tile and dashboard-form modals.
- Extracted shared ParamInputs (used by the saved-query run drawer and the
  dashboard filters bar); routes + nav item.

Verified: 155 backend tests pass (9 new for access rules + filter passthrough);
ruff clean; frontend lint + build pass; live Docker run confirmed migration
005->6, dashboard/tile CRUD, filters driving tile results, cache reuse, and
layout persistence.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add saved queries, charts, result cache/snapshots, export, and dashboards to
the changelog (under 2.0.0), the README (features, project structure, API
reference), and CLAUDE.md (project overview, key directories, a Phase 2
architecture section).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kosminus kosminus deleted the branch feat/phase2-durable-artifacts June 8, 2026 09:36
@kosminus kosminus closed this Jun 8, 2026
@kosminus kosminus deleted the feat/phase2-dashboards branch June 8, 2026 09:39
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.

1 participant