diff --git a/pf_spec.md b/pf_spec.md index 501dc1f..313b608 100644 --- a/pf_spec.md +++ b/pf_spec.md @@ -10,7 +10,7 @@ A web application for building named forecast scenarios against any PostgreSQL t - **Backend:** Node.js / Express - **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) --- @@ -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) | -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 @@ -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 - 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 +- 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 - 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:** ``` -┌──────────────────────────────────────────────────────────┐ -│ [Source: sales] [Version: FY2024 v1 — open] [Refresh] │ -├────────────────────────┬─────────────────────────────────┤ -│ │ │ -│ Pivot Grid │ Operation Panel │ -│ (AG Grid pivot mode) │ (active when slice selected) │ -│ │ │ -│ │ Slice: │ -│ │ channel = WHS │ -│ │ geography = WEST │ -│ │ │ -│ │ [ Scale ] [ Recode ] [ Clone ] │ -│ │ │ -│ │ ... operation form ... │ -│ │ │ -│ │ [ Submit ] │ -│ │ │ -└────────────────────────┴─────────────────────────────────┘ +┌─────────────────────────────────────────────────────────────────┐ +│ [Version label] [Refresh] [Save layout] [Reset layout] │ +├──────────────────────────────────────┬──────────────────────────┤ +│ │ │ +│ Perspective Viewer │ Operation Panel │ +│ (interactive pivot web component) │ (active when slice set) │ +│ │ │ +│ │ Slice: │ +│ │ channel = WHS │ +│ │ geography = WEST │ +│ │ │ +│ │ [ Scale ] [ Recode ] │ +│ │ [ Clone ] │ +│ │ │ +│ │ ... operation form ... │ +│ │ │ +│ │ [ Submit ] │ +│ │ │ +└──────────────────────────────────────┴──────────────────────────┘ ``` -**Interaction flow:** -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`) +**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. -**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 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) - **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 +