Skip to content

feat(workspace): backend dashboard read model#555

Closed
david-engelmann wants to merge 1 commit into
dohooo:mainfrom
david-engelmann:feature/dashboard-read-model
Closed

feat(workspace): backend dashboard read model#555
david-engelmann wants to merge 1 commit into
dohooo:mainfrom
david-engelmann:feature/dashboard-read-model

Conversation

@david-engelmann
Copy link
Copy Markdown
Contributor

Summary

  • Adds a typed load_dashboard_snapshot command that groups workspaces into kanban lanes (in-progress / review / done / backlog / canceled / archived) with a live isStreaming overlay per card.
  • Reuses the same load_workspace_records + load_archived_workspace_records queries the sidebar already runs, so the dashboard never disagrees with the sidebar about a row's status / PR metadata / message counts.
  • New workspace::dashboard module + DashboardSnapshot / DashboardLane / DashboardCard / DashboardLaneId types, mirrored on the frontend in src/lib/api.ts.
  • Bridge handler invalidates the dashboardSnapshot query on WorkspaceListChanged / WorkspaceChanged / ActiveStreamsChanged so the dashboard stays in lockstep with the sidebar.

Why

Closes #482 (backend slice — UI is the next PR in this track). The issue asks for a kanban view that groups existing workspaces by status; the data already exists on the workspace row, this PR just exposes it in the shape a dashboard card grid wants.

Scope boundary

Included:

  • workspace::dashboard module + build_dashboard_snapshot / assemble_snapshot (the second is a pure shaping helper so tests don't need to spin up the DB pool).
  • DashboardLaneId kebab-case enum mirroring WorkspaceStatus plus an Archived lane; six lanes always returned in stable display order so the frontend renders columns in iteration order.
  • DashboardCard flattens WorkspaceSummary and adds isStreaming: bool from ActiveStreams::snapshot_for_ui. Frontend never has to cross-reference listActiveStreams for the busy badge.
  • load_dashboard_snapshot Tauri command + loadDashboardSnapshot TS wrapper + dashboardSnapshotQueryOptions factory.
  • UI sync bridge: dashboard invalidates on the same events the sidebar listens for, plus on ActiveStreamsChanged so the streaming overlay stays live.

Deferred (intentionally out of scope):

  • Dashboard UI rendering — that's the next PR in track E.
  • Git change-line counts per workspace — those come from the heavy workspace_action_status path (one git subprocess per workspace). Better to fetch lazily per card on hover or per visible card.
  • Project filtering server-side — every card already carries repoId, so the filter is a one-liner on the frontend.
  • Drag-and-drop / status mutation / new task-management state — explicitly called out in the plan's review boundary.

Test plan

  • cd src-tauri && cargo nextest run — 1158 / 1158 pass (4 new dashboard tests).
  • cd src-tauri && cargo test --doc — clean.
  • cd src-tauri && cargo fmt --all -- --check — clean.
  • bun run lint — biome + clippy -D warnings clean.
  • bun run typecheck — clean (new DashboardSnapshot / DashboardLane / DashboardCard / DashboardLaneId TS types).
  • bun run test:frontend — 1113 / 1113 pass (existing tests unchanged; new query options + bridge handler additions are tree-shaken from non-dashboard surfaces).

Coverage added

New tests:

  • workspace::dashboard::tests::snapshot_always_returns_all_six_lanes_in_stable_order
  • workspace::dashboard::tests::workspaces_are_grouped_by_status_and_archived_split_into_own_lane
  • workspace::dashboard::tests::is_streaming_overlays_active_workspaces_only
  • workspace::dashboard::tests::lane_id_kebab_case_serialization_matches_workspace_status

The streaming test deliberately includes a defensive case for the rare boot race where an ActiveStreamSummary has workspace_id: None — the snapshot should treat those entries as unmatched rather than panic on .unwrap().

Follow-up

This is PR E1 in the dashboard track. E2 wires the actual UI: a route, a card grid using dashboardSnapshotQueryOptions, and a project filter chip set powered by repoId on each card.

Add a typed `load_dashboard_snapshot` command that groups workspaces
into kanban lanes (in-progress / review / done / backlog / canceled /
archived) with a live `isStreaming` overlay, so the upcoming dashboard
view (dohooo#482) can render cards without rewriting the sidebar's
aggregate queries.

Reuses `load_workspace_records` + `load_archived_workspace_records`
so the dashboard never disagrees with the sidebar about a row's
status / PR metadata / message counts. Six lanes always returned in
stable display order — the frontend renders columns in iteration
order and never needs to sort. Empty lanes ship as empty `cards`
arrays so the dashboard can paint placeholders consistently.

`isStreaming` is computed from a single `ActiveStreams::snapshot_for_ui`
call per request; the bridge handler also invalidates the
`dashboardSnapshot` query on `ActiveStreamsChanged` so the busy
badge stays live without polling.

Explicitly out of scope for this slice:
- Dashboard UI rendering (Track E / PR E2).
- Git change-line counts per workspace (those come from the heavy
  `workspace_action_status` path — defer to per-card lazy fetches).
- Project filtering server-side — the frontend already has every
  card's repoId, filtering is a one-liner there.
- No drag-and-drop, no status mutation, no new task-management state.

Tests:
- 4 Rust unit tests covering empty-board lane shape, status-driven
  bucketing with archived-lane split, streaming overlay (with the
  orphan-workspace-id defensive case), and the kebab-case wire format
  for `DashboardLaneId`.

Closes dohooo#482 (the backend slice — UI is the next PR in track E).
@vercel
Copy link
Copy Markdown

vercel Bot commented May 15, 2026

@david-engelmann is attempting to deploy a commit to the Caspian's Team Team on Vercel.

A member of the Team first needs to authorize it.

@taroj1205
Copy link
Copy Markdown
Contributor

@david-engelmann I feel like if this only includes the backend changes, then it shouldn't close the issue yet

@david-engelmann
Copy link
Copy Markdown
Contributor Author

@taroj1205 meant to open as a draft in my fork, sorry about that

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.

Add dashboard view for workspace status overview

2 participants