From dd993e989c892fa18580bef00ee21c8ead3478d6 Mon Sep 17 00:00:00 2001 From: Paul Trowbridge Date: Sat, 25 Apr 2026 14:56:29 -0400 Subject: [PATCH] Add UX mockup and update spec with navigation direction - HTML mockup with collapsible side nav, 3-step flow (Setup/Baseline/Forecast) - Canvas-based timeline preview in baseline segment form - Table peek modal, status bar, help popovers - Spec updated: 3-step mental model, AG Grid replacement note Co-Authored-By: Claude Sonnet 4.6 --- pf_spec.md | 17 +- pf_ux_mockup.md | 112 ++++++ public/mockup.html | 888 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1016 insertions(+), 1 deletion(-) create mode 100644 pf_ux_mockup.md create mode 100644 public/mockup.html diff --git a/pf_spec.md b/pf_spec.md index 313b608..1b63543 100644 --- a/pf_spec.md +++ b/pf_spec.md @@ -662,6 +662,7 @@ DELETE FROM pf.log WHERE id = {{logid}}; ## Open Questions / Future Scope - **Baseline replay** — re-execute change log against a restated baseline (`replay: true`); v1 returns 501 +- **Arrow IPC for initial data load** — at large row counts (1M+) the `/versions/:id/data` JSON response becomes a bottleneck. Option: serve Arrow IPC binary instead of JSON; Perspective's `worker.table()` accepts Arrow buffers natively. Incremental operation rows (scale/recode/clone) can stay as JSON fed to `table.update()` since they're always small. Could be implemented with `pg` + `apache-arrow` in Node, or by adding a server-side DuckDB instance (Postgres scanner → Arrow IPC) if a caching layer is also needed. - **Approval workflow** — user submits, admin approves before changes are visible to others (deferred) - **Territory filtering** — restrict what a user can see/edit by dimension value (deferred) - **Export** — download forecast as CSV or push results to a reporting table @@ -680,10 +681,24 @@ DELETE FROM pf.log WHERE id = {{logid}}; - 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 + +**Primary: overall interaction is not intuitive — needs a clearer 3-step flow** + +The app should present itself as three distinct phases in order: + +1. **Setup source** — register a table, configure col_meta, generate SQL. One-time admin task. Once done, user should never need to return here. +2. **Build baseline** — create a version, load baseline segments, optionally load reference. Also largely a one-time setup per version. +3. **Do edits** — the Forecast view; the primary ongoing working mode. Pivot + operation panel. + +Current 5-tab nav (Sources / Versions / Baseline / Forecast / Log) obscures this progression. Users have to discover the order themselves, and context (which source, which version) is lost between tabs. + +**Direction:** Redesign navigation around the 3-step mental model. Steps 1 and 2 should feel like "setup" that gets out of the way; step 3 is the main working surface. Consider a wizard/stepper for first-time setup, with the Forecast view as the default landing once a version exists. + +**Other issues:** - 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 +- AG Grid watermark (community edition) and non-intuitive interaction on admin grids — replace with plain `` + Tailwind, same pattern used in dataflow (`/opt/dataflow/ui/src/pages/`) ### Branch status - `baseline-workbench` — merged to origin, stable diff --git a/pf_ux_mockup.md b/pf_ux_mockup.md new file mode 100644 index 0000000..1c6c2ce --- /dev/null +++ b/pf_ux_mockup.md @@ -0,0 +1,112 @@ +# Pivot Forecast — UX Mockup + +``` +┌─────────────────────────────────────────────────────────────────────┐ +│ Pivot Forecast │ +│ ① Setup ② Baseline ③ Forecast ◀ (default landing) │ +└─────────────────────────────────────────────────────────────────────┘ + + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + ① SETUP +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +┌──── All Tables ──────────────┐ ┌──── Registered Sources ─────────┐ +│ schema table rows │ │ │ +│ ────── ────────── ────── │ │ sales_orders ✓ SQL ready │ +│ public sales_orders 48,291 │◀─│ invoices ✓ SQL ready │ +│ public invoices 12,004 │ │ + Register table │ +│ public products 891 │ └──────────────────────────────────┘ +│ rpt summary_mv 3,442 │ +└──────────────────────────────┘ ┌──── Col Meta: sales_orders ─────┐ + │ column role key label│ + │ ────────── ──────── ─── ─── │ + │ customer dimension ✓ │ + │ channel dimension ✓ │ + │ part dimension │ + │ geography dimension │ + │ order_date date │ + │ ship_date filter │ + │ status filter │ + │ units units │ + │ revenue value │ + │ internal_id ignore │ + │ │ + │ [Generate SQL ▶] │ + └──────────────────────────────────┘ + + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + ② BASELINE +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + Source [sales_orders ▾] Version [FY2026 Plan ▾] [+ New version] + +┌──── Segments ──────────────────────────────────────────────────────┐ +│ # description rows by date │ +│ ─ ──────────────────────────── ────── ────── ────────────── │ +│ 1 FY25 actuals +1yr 41,204 paul Apr 24 │ +│ 2 Open orders 3,109 paul Apr 24 [Undo] │ +│ │ +│ Total baseline rows: 44,313 [Clear all baseline] │ +└────────────────────────────────────────────────────────────────────┘ + +┌──── Add Segment ────────────────────────────────────────────────────┐ +│ │ +│ Description [ ] │ +│ │ +│ Filters [+ Add filter] │ +│ ┌─────────────────┬──────────┬─────────────────────┬───┐ │ +│ │ order_date │ BETWEEN │ 2025-01-01 2025-12-31│ x │ │ +│ └─────────────────┴──────────┴─────────────────────┴───┘ │ +│ │ +│ Date offset [1] yr [0] mo │ +│ │ +│ ·───────────────────────────· source │ +│ Jan 2025 Dec 2025 │ +│ ·───────────────────────────· projected (+1 yr) │ +│ Jan 2026 Dec 2026 │ +│ │ +│ Note [ ] [Load Segment] │ +└────────────────────────────────────────────────────────────────────┘ + +┌──── Reference (optional) ──────────────────────────────────────────┐ +│ Load prior-period rows for comparison in the pivot │ +│ Date range [2024-01-01] to [2024-12-31] │ +│ Note [ ] [Load Ref] │ +└────────────────────────────────────────────────────────────────────┘ + + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + ③ FORECAST source: sales_orders +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + Version [FY2026 Plan ▾] [Refresh] [Save layout] [Reset layout] + +┌──── Pivot ───────────────────────────────┐ ┌──── Operations ───────┐ +│ │ │ │ +│ (Perspective viewer) │ │ Slice │ +│ │ │ channel = WHS │ +│ channel │ Jan 2026 │ Feb 2026 │ ... │ │ geo = WEST │ +│ ──────────┼──────────┼──────────┼─── │ │ │ +│ DIR │ 412,000 │ 388,000 │ │ │ [Scale][Recode] │ +│ WHS ◀ │ 290,000 │ 310,000 │ │ │ [Clone] │ +│ ──────── │ │ │ │ │ ─────────────────── │ +│ Total │ 702,000 │ 698,000 │ │ │ Value incr [ ] │ +│ │ │ Units incr [ ] │ +│ │ │ Pct? [ ] │ +│ │ │ │ +│ │ │ Note [ ] │ +│ │ │ │ +│ │ │ [Submit] │ +└──────────────────────────────────────────┘ └───────────────────────┘ + + ▼ Change log (12 entries) + ┌────┬───────────┬──────────┬─────────────────────────┬────────────┐ + │ id │ operation │ by │ slice │ │ + │ ── │ ───────── │ ──────── │ ───────────────────── ─ │ │ + │ 12 │ scale │ paul │ channel=WHS geo=WEST │ [Undo] │ + │ 11 │ recode │ paul │ part=OLD-SKU │ [Undo] │ + │ 10 │ scale │ paul │ channel=DIR │ [Undo] │ + └────┴───────────┴──────────┴─────────────────────────┴────────────┘ +``` diff --git a/public/mockup.html b/public/mockup.html new file mode 100644 index 0000000..34a996b --- /dev/null +++ b/public/mockup.html @@ -0,0 +1,888 @@ + + + + + + Pivot Forecast — Mockup + + + + + + + +
+ +
+ + + + +
+ + +
+ Source + sales_orders + | + Version + FY2026 Plan + | + Baseline + 44,313 rows + | + Status + open +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
schematablerows
publicsales_orders48,291
publicinvoices12,004
publicproducts891
rptsummary_mv3,442
+ + + + +
+ +
+
+ Registered Sources + +
+ + + + + + + + + + + + + +
sales_orders✓ SQL readypublic
invoices✓ SQL readypublic
+
+ +
+
+ Col Meta — sales_orders + +
+
+ + + + + + + + + + + + + + + + + + + + + +
columnrolekeylabel
customerdimension
channeldimension
partdimension
geographydimension
order_datedate
ship_datefilter
statusfilter
unitsunits
revenuevalue
internal_idignore
+
+
+ +
+ + + + + + + + + + + +