From 956ff10e4d7207c5710af07439ef5b14a76829b1 Mon Sep 17 00:00:00 2001 From: m Date: Thu, 7 May 2026 12:36:05 +0200 Subject: [PATCH] design(t-paliad-144): m signed off + Q4 correction (3 shapes, not 4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit m's lock-in 2026-05-07: agree with all recommendations on Q1-Q18 and §10 Q19-Q27, with one correction on Q4: "activity" is a content selection (sources + filters), not a render shape. Folded into `list` shape with density: "compact" + actor/time columns. Shape ⊥ source — any source can render in any shape. Render shapes for v1: list / cards / calendar (3, was 4). PR split decision (delegated to inventor): A1 backend substrate + API (no UI change, ~1800 LoC, smoke via curl) → main → A2 frontend Custom Views UI (~1600 LoC, additive on A1) → main. Status flipped DRAFT → LOCKED. Inventor → coder transition initiated. --- docs/design-data-display-model-2026-05-06.md | 55 ++++++++++++++------ 1 file changed, 38 insertions(+), 17 deletions(-) diff --git a/docs/design-data-display-model-2026-05-06.md b/docs/design-data-display-model-2026-05-06.md index d1599ad..1ff747f 100644 --- a/docs/design-data-display-model-2026-05-06.md +++ b/docs/design-data-display-model-2026-05-06.md @@ -4,7 +4,7 @@ **Issue:** m/paliad#5 **Author:** noether (inventor) **Date:** 2026-05-06 -**Status:** DRAFT — awaiting m's go/no-go on §10 open questions +**Status:** LOCKED 2026-05-07 — m signed off on all recommendations + §10 follow-ups, with one correction (Q4 narrowed from 4 shapes → 3; "activity" is a filter/source choice, not a render shape — folded into `list` shape with density config). Inventor → coder transition initiated. PR split chosen: A1 backend substrate, A2 frontend Custom Views. **Branch:** `mai/noether/inventor-data-display` **Builds on:** t-paliad-109 (events unification, shipped) + t-paliad-138 (approvals, shipped) + t-paliad-139 (hierarchy aggregation, all 3 phases on `mai/noether/inventor-project` awaiting merge gate) @@ -58,7 +58,7 @@ Three design pieces fall out of this: |---|---|---| | **Substrate shape** | One `ViewService` (new) that union-loads from 4 data sources: `deadline`, `appointment`, `project_event` (audit), `approval_request`. Returns a discriminated `[]ViewRow` keyed by `kind`. | Single virtual SQL `view_row` table with UNION ALL across all 4 — too many polymorphic columns; harder to evolve per-source filters. | | **Filter grammar** | Structured JSON spec validated server-side (`FilterSpec`). UI builds it via affordance widgets; the JSON is also human-editable for power users. | SQL DSL (security risk + complexity); UI-only (forces every dimension to have a widget). | -| **Render shapes for v1** | `list`, `cards`, `calendar`, `activity` (4). Defer `kanban`, `connections-graph`, `timeline-distinct-from-cards`. | Ship all 6 — `/events` already has list/cards/calendar; `cards` doubles as the day-grouped timeline today. Activity is the unified-inbox shape. The deferred three each need substantial new component work. | +| **Render shapes for v1** | `list`, `cards`, `calendar` (3). Activity-feed appearance is achieved by source/filter choice (`sources: ["project_event", …]`) rendered through `list` shape with `density: "compact"` + actor/time columns — *not* a separate shape. Defer `kanban`, `connections-graph`, `timeline-distinct-from-cards`. | Ship 4+ shapes including a dedicated "activity" — m's correction (2026-05-07): activity is content selection, not visualisation. Shape ⊥ source. | | **Persistence** | New table `paliad.user_views` (id, user_id, slug, name, filter_spec jsonb, render_spec jsonb, sort_order, icon, last_used_at, …). RLS = caller's own rows only. | Per-user JSON column on `paliad.users` — kills the sidebar count badge query path (`SELECT count(*) WHERE user_id`); also no indexed sort. | | **System defaults — code or DB?** | **Code.** Defaults stay as their own pages (`/dashboard`, `/agenda`, `/events`, `/inbox`); they are *built using the same render components* the custom-view system uses. No `is_system=true` row in `user_views`. | Seed system rows per user — drifts on schema bumps; new users miss bumps; `is_system=true` is a synonym for "config-as-data when config-as-code is cleaner". | | **Sidebar** | New "Meine Sichten" group between "Arbeit" and "Werkzeuge". Each saved view appears as one nav entry (icon + name). One trailing "+ Neue Sicht" entry. | "Meine Sichten" as a single sidebar entry expanding to a panel — extra click cost on every navigation. | @@ -243,18 +243,25 @@ These are genuinely two views; the substrate exposes both. ### Q4 — Which render shapes are first-class for v1? -**Recommendation: `list`, `cards`, `calendar`, `activity` — four shapes.** +**Recommendation: `list`, `cards`, `calendar` — three shapes.** + +m's correction (2026-05-07): activity is a content selection (sources + filters), not a render shape. The "compact one-line stream with type icons" appearance is `list` shape with `density: "compact"` + an actor/time column set — same component, different config. Shape is orthogonal to source: any source can render in any shape. | Shape | Status today | What it does | Source bias | |---|---|---|---| -| **`list`** | shipped on `/events` (table) and `/inbox` (`