generated from coulomb/repo-seed
docs(wp): IHUB-WP-0018 personal dashboard framework
Some checks failed
Build and Deploy / build-push-deploy (push) Has been cancelled
Some checks failed
Build and Deploy / build-push-deploy (push) Has been cancelled
Four-task research-first workplan: T01 surveys Grafana/Kibana/Retool/ Linear/Notion/Observable/Metabase/Streamlit for transplantable patterns; T02 produces a PRS (4 personas, MoSCoW, perf NFRs, IHF governance fit); T03 produces an FDD (schema, 8-panel catalogue, 12-col grid layout, server-rendered pipeline, edit flow, default seeding); T04 breaks the FDD into IHUB-WP-0019 implementation tasks. Design constraints: server-first, type-safe PanelConfig ADT, IHF widget envelope on every panel, Tailwind + CSS Grid, minimal JS. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
292
workplans/IHUB-WP-0018-personal-dashboard-framework.md
Normal file
292
workplans/IHUB-WP-0018-personal-dashboard-framework.md
Normal file
@@ -0,0 +1,292 @@
|
||||
---
|
||||
id: IHUB-WP-0018
|
||||
type: workplan
|
||||
title: "Personal Dashboard Framework"
|
||||
domain: inter-hub
|
||||
status: todo
|
||||
owner: tegwick
|
||||
created: "2026-05-03"
|
||||
updated: "2026-05-03"
|
||||
phase: 13
|
||||
---
|
||||
|
||||
# Personal Dashboard Framework
|
||||
|
||||
## Goal
|
||||
|
||||
Design and implement a personal dashboard framework that allows individual users to
|
||||
compose, configure, and persist a view of the inter-hub platform tailored to their
|
||||
role and focus. The dashboard is the post-login landing page and the primary daily
|
||||
driver surface for hub operators, governance reviewers, and AI orchestrators.
|
||||
|
||||
## Motivation
|
||||
|
||||
The current post-login experience drops the user on a raw Hubs list. As inter-hub
|
||||
grows to 12+ phases of functionality, users need a curated, role-aware entry point
|
||||
that surfaces the signals that matter to them without requiring manual navigation.
|
||||
The dashboard is also the natural home for cross-cutting observability (recent
|
||||
decisions, open candidates, outcome signals) that cuts across the current
|
||||
controller-per-entity navigation.
|
||||
|
||||
---
|
||||
|
||||
## Tasks
|
||||
|
||||
### T01 — Research: Dashboard frameworks and patterns for inspiration
|
||||
|
||||
```task
|
||||
id: IHUB-WP-0018-T01
|
||||
status: todo
|
||||
priority: high
|
||||
```
|
||||
|
||||
Survey existing dashboard systems to extract patterns that are re-implementable in
|
||||
Haskell / IHP / Tailwind under inter-hub's design constraints (server-rendered,
|
||||
type-safe, governed).
|
||||
|
||||
**Research targets:**
|
||||
|
||||
| System | What to extract |
|
||||
|---|---|
|
||||
| **Grafana** | Panel/grid layout model; datasource abstraction; variable-driven filtering |
|
||||
| **Kibana (dashboards)** | Saved-search panels; time-range awareness; role-based visibility |
|
||||
| **Retool / Appsmith** | Widget catalogue approach; drag-grid layout; data binding model |
|
||||
| **Linear (home view)** | Flat "My Work" aggregation across entities; priority surfacing |
|
||||
| **Notion (linked databases)** | Filter/sort persistence per user; view types (table, board, calendar) |
|
||||
| **Observable Framework** | Reactive cell model; markdown + code co-location |
|
||||
| **Metabase** | Question-as-unit; dashboard as ordered collection of questions |
|
||||
| **Streamlit** | Declarative layout (columns, expanders); pure functional rendering loop |
|
||||
|
||||
**Questions to answer per system:**
|
||||
1. How is a dashboard persisted? (JSON blob, relational rows, code-as-config?)
|
||||
2. How is a widget/panel parameterised? (datasource, filter, display options)
|
||||
3. How is layout described? (fixed grid, CSS grid, drag-and-drop, responsive breakpoints)
|
||||
4. How is per-user state separated from shared/team state?
|
||||
5. What is the update model? (full-page reload, WebSocket push, polling, partial HTMX swap)
|
||||
6. How are access controls expressed at panel level?
|
||||
|
||||
**IHP/Haskell-specific constraints to keep in mind:**
|
||||
- Server-rendered by default; AutoRefresh (WebSocket) available for live data
|
||||
- No client-side state management library; JS must be minimal
|
||||
- Type safety from DB schema → view layer is a first-class constraint
|
||||
- Tailwind CSS; no component library
|
||||
|
||||
**Exit criteria:** Research notes written in `docs/research/dashboard-frameworks.md`.
|
||||
|
||||
---
|
||||
|
||||
### T02 — Product Requirements Specification (PRS)
|
||||
|
||||
```task
|
||||
id: IHUB-WP-0018-T02
|
||||
status: todo
|
||||
priority: high
|
||||
depends_on: T01
|
||||
```
|
||||
|
||||
Produce a formal PRS for the Personal Dashboard Framework based on T01 findings and
|
||||
inter-hub's design principles.
|
||||
|
||||
**Required sections:**
|
||||
|
||||
1. **Problem statement** — who uses the dashboard, what decisions they make with it,
|
||||
what pain the current flat-nav approach causes
|
||||
|
||||
2. **User personas**
|
||||
- Hub Operator: monitors activity within their hub; wants recent events, open candidates
|
||||
- Governance Reviewer: triages candidates, reviews decisions; needs queue and signal views
|
||||
- AI Orchestrator: monitors agent proposals, outcome correlations; needs performance panels
|
||||
- Platform Admin: watches system health, API usage, learning throughput
|
||||
|
||||
3. **Core requirements (MoSCoW)**
|
||||
- Must: per-user dashboard persisted in DB; selectable panels from a catalogue;
|
||||
layout preserved across sessions; role-aware default layout on first login
|
||||
- Should: panel-level filtering (by hub, by time range); live-update via AutoRefresh
|
||||
for signal panels; keyboard-navigable
|
||||
- Could: drag-and-drop layout editing; shared/team dashboards; dashboard templates
|
||||
- Won't (Phase 13): mobile-native layout; client-side data fetching; external datasources
|
||||
|
||||
4. **Non-functional requirements**
|
||||
- First paint < 500 ms (server-rendered, no JS data fetching)
|
||||
- Dashboard save/load < 100 ms
|
||||
- Each panel query < 200 ms (indexed, bounded result sets)
|
||||
- Zero JS frameworks; AutoRefresh WebSocket for live panels only
|
||||
|
||||
5. **Governance fit** — dashboard widgets are themselves `Widget` records in the IHF
|
||||
sense; `InteractionEvent`s recorded on dashboard interactions; annotations possible
|
||||
on any panel
|
||||
|
||||
**Exit criteria:** `docs/prs/dashboard-framework-prs.md` reviewed and accepted.
|
||||
|
||||
---
|
||||
|
||||
### T03 — Functional Design Document (FDD)
|
||||
|
||||
```task
|
||||
id: IHUB-WP-0018-T03
|
||||
status: todo
|
||||
priority: high
|
||||
depends_on: T02
|
||||
```
|
||||
|
||||
Translate the PRS into a concrete functional design covering schema, component model,
|
||||
rendering pipeline, and layout system. This is the authoritative reference for implementation.
|
||||
|
||||
**Required sections:**
|
||||
|
||||
#### 3.1 Data model
|
||||
|
||||
```sql
|
||||
-- A user's named dashboard
|
||||
CREATE TABLE dashboards (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
user_id UUID NOT NULL REFERENCES users(id),
|
||||
name TEXT NOT NULL,
|
||||
is_default BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- An instance of a panel type on a dashboard, with position
|
||||
CREATE TABLE dashboard_panels (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
dashboard_id UUID NOT NULL REFERENCES dashboards(id) ON DELETE CASCADE,
|
||||
panel_type TEXT NOT NULL, -- FK to panel_type_registry
|
||||
config JSONB NOT NULL DEFAULT '{}',
|
||||
col INT NOT NULL DEFAULT 0,
|
||||
row INT NOT NULL DEFAULT 0,
|
||||
col_span INT NOT NULL DEFAULT 1,
|
||||
row_span INT NOT NULL DEFAULT 1,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- Registry of available panel types
|
||||
CREATE TABLE panel_type_registry (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
label TEXT NOT NULL,
|
||||
description TEXT,
|
||||
default_config JSONB NOT NULL DEFAULT '{}',
|
||||
requires_hub BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
live_update BOOLEAN NOT NULL DEFAULT FALSE
|
||||
);
|
||||
```
|
||||
|
||||
#### 3.2 Panel catalogue (Phase 13 scope)
|
||||
|
||||
| Panel type name | Label | Description | Live? |
|
||||
|---|---|---|---|
|
||||
| `recent-interactions` | Recent Activity | Latest interaction events across watched hubs | Yes |
|
||||
| `open-candidates` | Open Candidates | Requirement candidates awaiting triage | No |
|
||||
| `decision-queue` | Decision Queue | Decisions pending review | No |
|
||||
| `outcome-signals` | Outcome Signals | Recent outcome signal summary | Yes |
|
||||
| `hub-health` | Hub Health | Health snapshot per hub | No |
|
||||
| `agent-proposals` | Agent Proposals | Open AI agent proposals | No |
|
||||
| `learning-digest` | Learning Digest | Latest institutional knowledge entries | No |
|
||||
| `my-annotations` | My Annotations | Annotations by the current user | No |
|
||||
|
||||
#### 3.3 Layout system
|
||||
|
||||
12-column CSS grid; panels occupy `col_span` columns and `row_span` rows.
|
||||
Row height fixed at 240px. No drag-and-drop in Phase 13; layout edited via
|
||||
form fields (col, row, span). Responsive: collapse to single column below 768px.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ [Recent Activity ×6] [Decision Queue ×3] [Hub ×3]│
|
||||
│ │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ [Open Candidates ×4] [Outcome Signals ×4] [My ×4] │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### 3.4 Rendering pipeline
|
||||
|
||||
```
|
||||
GET /Dashboard
|
||||
→ DashboardController#show
|
||||
→ fetch dashboard + panels (ordered by row, col)
|
||||
→ for each panel: dispatch to panel renderer (panelHtml panelType config)
|
||||
→ embed in DashboardView with CSS grid layout
|
||||
→ AutoRefresh wraps live panels only
|
||||
```
|
||||
|
||||
Each panel renderer is a Haskell function:
|
||||
```haskell
|
||||
type PanelRenderer = PanelConfig -> ModelContext -> IO Html
|
||||
renderPanel :: Text -> PanelConfig -> ModelContext -> IO Html
|
||||
renderPanel "recent-interactions" = renderRecentInteractions
|
||||
renderPanel "open-candidates" = renderOpenCandidates
|
||||
...
|
||||
```
|
||||
|
||||
#### 3.5 Edit flow
|
||||
|
||||
`GET /Dashboard/Edit` → grid with inline forms per panel (col/row/span inputs) +
|
||||
"Add Panel" dropdown from `panel_type_registry`. `POST /Dashboard` saves layout.
|
||||
No JavaScript needed for basic edit; optional HTMX for panel preview.
|
||||
|
||||
#### 3.6 Default dashboard on first login
|
||||
|
||||
`afterLoginRedirectPath` (in `SessionsControllerConfig`) redirects to `/Dashboard`.
|
||||
On first visit, `DashboardController` checks for an existing dashboard; if absent,
|
||||
creates a default one seeded from the user's role (determined by a `role` field
|
||||
to be added to `users`, or a simple heuristic based on existing data).
|
||||
|
||||
**Exit criteria:** FDD reviewed; schema migrations drafted; panel catalogue agreed.
|
||||
|
||||
---
|
||||
|
||||
### T04 — Implementation workplan
|
||||
|
||||
```task
|
||||
id: IHUB-WP-0018-T04
|
||||
status: todo
|
||||
priority: medium
|
||||
depends_on: T03
|
||||
```
|
||||
|
||||
Break T03's FDD into a detailed, sequenced task list suitable for execution as a new
|
||||
workplan (IHUB-WP-0019). Each task must have a clear entry/exit criterion and fit within
|
||||
the 8k token soft budget.
|
||||
|
||||
**Expected task structure of IHUB-WP-0019:**
|
||||
|
||||
```
|
||||
T01 Schema migration: dashboards, dashboard_panels, panel_type_registry
|
||||
T02 Seed: default panel types in panel_type_registry
|
||||
T03 DashboardController — show action (fetch + render)
|
||||
T04 Panel renderers — first 3 panels (recent-interactions, open-candidates, decision-queue)
|
||||
T05 DashboardView — CSS grid layout
|
||||
T06 Panel renderers — remaining 5 panels
|
||||
T07 Dashboard edit flow (layout form, add/remove panels)
|
||||
T08 Default dashboard seeding on first login
|
||||
T09 afterLoginRedirectPath → /Dashboard
|
||||
T10 AutoRefresh for live panels (recent-interactions, outcome-signals)
|
||||
T11 Role-aware default layout
|
||||
T12 Smoke tests
|
||||
```
|
||||
|
||||
**Exit criteria:** IHUB-WP-0019 workplan file committed; T01–T12 each have
|
||||
entry/exit criteria; ready for execution.
|
||||
|
||||
---
|
||||
|
||||
## Exit Criteria Summary
|
||||
|
||||
| Task | Deliverable | Status |
|
||||
|---|---|---|
|
||||
| T01 | `docs/research/dashboard-frameworks.md` | todo |
|
||||
| T02 | `docs/prs/dashboard-framework-prs.md` | todo |
|
||||
| T03 | `docs/fdd/dashboard-framework-fdd.md` | todo |
|
||||
| T04 | `workplans/IHUB-WP-0019-personal-dashboard-impl.md` | todo |
|
||||
|
||||
## Design Principles (binding throughout)
|
||||
|
||||
- **Server-first**: every panel renders in a single round-trip. No client-side data fetching.
|
||||
- **Type-safe config**: `PanelConfig` is a Haskell ADT, not an opaque JSON blob at runtime.
|
||||
- **IHF governed**: each rendered panel is a `Widget` with a `widgetEnvelope`; interactions
|
||||
are recorded; annotations can be attached.
|
||||
- **Tailwind only**: no external component library. Layout via CSS Grid with inline style for
|
||||
structural properties (lessons learned from sidebar nav).
|
||||
- **Minimal JS**: AutoRefresh WebSocket for live panels; vanilla JS for any UX enhancement.
|
||||
No framework, no bundler beyond the existing IHP asset pipeline.
|
||||
Reference in New Issue
Block a user