Update spec: Perspective pivot, current project status

- Replace AG Grid pivot references with Perspective throughout
- Document pivot interaction flow, default layout, slice extraction,
  incremental row streaming
- Add Project Status section: what's working, known UX issues,
  branch status

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Paul Trowbridge 2026-04-15 07:24:20 -04:00
parent 4c71049bf0
commit 9084a87ea5

View File

@ -10,7 +10,7 @@ A web application for building named forecast scenarios against any PostgreSQL t
- **Backend:** Node.js / Express - **Backend:** Node.js / Express
- **Database:** PostgreSQL — isolated `pf` schema, installs into any existing DB - **Database:** PostgreSQL — isolated `pf` schema, installs into any existing DB
- **Frontend:** Vanilla JS + AG Grid (pivot mode) - **Frontend:** Vanilla JS + AG Grid (sources/versions/log grids) + Perspective (forecast pivot)
- **Pattern:** Follows fc_webapp (shell) + pivot_forecast (operations) - **Pattern:** Follows fc_webapp (shell) + pivot_forecast (operations)
--- ---
@ -259,7 +259,7 @@ Source registration, col_meta configuration, SQL generation, version creation, a
|--------|-------|-------------| |--------|-------|-------------|
| GET | `/api/versions/:id/data` | Return all rows for this version (all iters including reference) | | GET | `/api/versions/:id/data` | Return all rows for this version (all iters including reference) |
Returns flat array. AG Grid pivot runs client-side on this data. Returns flat array. Perspective pivot runs client-side on this data.
### Forecast Operations ### Forecast Operations
@ -358,6 +358,7 @@ All operations share a common request envelope:
- Left: DB table browser (like fc_webapp) — all tables with row counts, preview on click - Left: DB table browser (like fc_webapp) — all tables with row counts, preview on click
- Right: Registered sources list — click to open col_meta editor - Right: Registered sources list — click to open col_meta editor
- Col_meta editor: AG Grid editable table — set role per column, toggle is_key, set label - Col_meta editor: AG Grid editable table — set role per column, toggle is_key, set label
- AG Grid is used for all admin grids (tables browser, sources list, col_meta editor, versions list, log)
- "Generate SQL" button — triggers generate-sql route, shows confirmation - "Generate SQL" button — triggers generate-sql route, shows confirmation
- Must generate SQL before versions can be created against this source - Must generate SQL before versions can be created against this source
@ -443,38 +444,44 @@ Note: segment 2 has no date filter — any filter combination is valid as long a
**Layout:** **Layout:**
``` ```
┌──────────────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────────────
│ [Source: sales] [Version: FY2024 v1 — open] [Refresh] │ [Version label] [Refresh] [Save layout] [Reset layout]
├────────────────────────┬─────────────────────────────────┤ ├──────────────────────────────────────┬──────────────────────────┤
│ │ │ │ │ │
│ Pivot Grid │ Operation Panel │ Perspective Viewer │ Operation Panel
│ (AG Grid pivot mode) │ (active when slice selected) │ (interactive pivot web component) │ (active when slice set)
│ │ │ │ │ │
│ │ Slice: │ │ │ Slice: │
│ │ channel = WHS │ │ │ channel = WHS │
│ │ geography = WEST │ │ │ geography = WEST │
│ │ │ │ │ │
│ │ [ Scale ] [ Recode ] [ Clone ] │ │ │ [ Scale ] [ Recode ] │
│ │ [ Clone ] │
│ │ │ │ │ │
│ │ ... operation form ... │ │ │ ... operation form ... │
│ │ │ │ │ │
│ │ [ Submit ] │ │ │ [ Submit ] │
│ │ │ │ │ │
└────────────────────────┴─────────────────────────────────┘ └──────────────────────────────────────┴──────────────────────────┘
``` ```
**Interaction flow:** **Pivot control:** [Perspective](https://perspective.finos.org/) 4.4.0, loaded from CDN at runtime. All rows from `GET /api/versions/:id/data` are loaded into an in-browser Perspective worker. Supports grouping, splitting, filtering, sorting, and charting interactively. Layout (group_by, split_by, filters, plugin) is saved per version to `localStorage` via Save layout / Reset layout buttons.
1. Select cells in pivot — selected dimension values populate Operation Panel as slice
2. Pick operation tab, fill in parameters
3. Submit → POST to API → response shows rows affected
4. Grid refreshes (re-fetch `get_data`)
**Reference rows** shown in pivot (for context) but visually distinguished (e.g., muted color). Operations never affect them. **Interaction flow:**
1. Click a cell or row in the pivot — the `perspective-click` event fires
2. `detail.config.filter` from the event is parsed: only `==` filters on `role = dimension` columns are extracted as the slice
3. Slice populates the Operation Panel — pick operation tab, fill in parameters
4. Submit → POST to API → new rows returned via `RETURNING *` are streamed directly into the Perspective table (`pspTable.update(rows)`) — no full reload needed
5. For recode, both the negative offset rows and positive replacement rows are returned and streamed
**Pivot default layout:** built from col_meta — first two `dimension` columns as `group_by`, `date` column as `split_by`. User can rearrange in Perspective settings panel and save.
**Reference rows** (`pf_iter = 'reference'`) are visible in the pivot for comparison context. Operations never affect them (enforced by `exclude_iters` in the version).
### Log View ### Log View
AG Grid list of log entries — user, timestamp, operation, slice, note, rows affected. AG Grid list of log entries — user, timestamp, operation, slice, note, rows affected.
"Undo" button per row → `DELETE /api/log/:logid` → grid and pivot refresh. "Undo" button per row → `DELETE /api/log/:logid` → grid and pivot refresh (full reload of Perspective table).
--- ---
@ -661,3 +668,24 @@ DELETE FROM pf.log WHERE id = {{logid}};
- **Version comparison** — side-by-side view of two versions (facilitated by isolated tables via UNION) - **Version comparison** — side-by-side view of two versions (facilitated by isolated tables via UNION)
- **Multi-DB sources** — currently assumes same DB; cross-DB would need connection config per source - **Multi-DB sources** — currently assumes same DB; cross-DB would need connection config per source
---
## Project Status — 2026-04-15
### What's working
- Full backend: source registration, col_meta, SQL generation, versions, baseline segments, reference load, scale, recode, clone, undo
- Perspective pivot in Forecast view: loads all version rows, interactive group/split/filter/chart, layout saved per version
- Slice extraction from `perspective-click` event feeds operation panel directly
- Incremental row streaming: operation results (`RETURNING *`) stream into Perspective table without full reload
- Baseline workbench: multi-segment additive baseline with WHERE clause editor and offset
### Known UX issues — next focus area
- Navigation flow is clunky: user is forced to start at Sources even when a version already exists; context (source/version) is lost between views; getting to Forecast requires too many steps
- No clear "current version" concept — user has to re-select source → version each session
- Operation panel feedback is minimal (row count only, no before/after summary)
- Perspective computed date columns (Month, YearDate) extracted via split_by don't filter back to raw rows when used as slice — only native dimension columns work for slice extraction
### Branch status
- `baseline-workbench` — merged to origin, stable
- `perspective-forecast` — active development branch; Perspective pivot working, UI flow improvements pending