From 3cc2d353cda7c78057b7413f5961bc3bc5dac309 Mon Sep 17 00:00:00 2001 From: stroblme Date: Sat, 22 Aug 2026 12:24:56 +0200 Subject: [PATCH] NOTEPAD: clear what wave 2 closed, record what it left --- NOTEPAD.md | 52 +++++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/NOTEPAD.md b/NOTEPAD.md index e359e0b..1fe89c7 100644 --- a/NOTEPAD.md +++ b/NOTEPAD.md @@ -12,9 +12,31 @@ Deferring because out of scope is fine, but don't mention deferring than. ### To be sorted -- CHORE/UI: no affordance for `POST /panels/{id}/unpair`. The panels dialog can pair a - device but not re-pair one; `PanelsService.unpairPanel({ panelId })` is generated and - the docs already describe it. Invalidate `panelKeys.all` after. +- CHORE/DEMO: `seed_demo.py` still writes the Home dashboard as three titled sections + ("Right now", "Energy and comfort", "Yield model"). The editor and the panel now read a + page's sections as one grid, so those headings are no longer drawn and the first editor + save collapses them into one section. Re-author `PAGES` as a single section, and decide + whether the three headings come back as markdown widgets or go for good. +- CHORE/UI: the widget-side segmented control in `widgets.tsx` (`DropdownWidget`, + `style: "segmented"`) and `Common/RangePicker.tsx` still carry their own copy of the shape + now in `ui/segmented.tsx`. Pointing them there needs a size prop first — the widget one is + a full-width pill with a 44px touch target, the editor one is `w-fit`/`text-xs`. +- CHORE/UI: `IconPicker` in `panels.tsx` has no filter field; the grid shows all of `ICONS` + at once. Add one when the map outgrows a popover. +- CHORE/UI: the delete-panel button in `PanelsDialog` has no confirmation, while unpairing — + the strictly less destructive action — now does. +- CHORE/UI: `DashboardMosaic.blocksOf` offsets sections unconditionally, while + `DashboardView.flatWidgets` skips the offset for an unarranged document. Cosmetic, in the + schematic preview only; the two want to be one function once the mosaic may import the + dashboard chunk. +- FEAT/API: `DashboardSummary` carries no `icon`, so the panels dialog cannot show which + glyph each assigned dashboard draws on the rail — the icon is only visible from that + dashboard's own settings panel. Setting it from the panels dialog would need a decision + about publishing an icon change on its own, since that dialog has no draft concept. +- CHORE/TEST: nothing guards "a dashboard with two pages or sections survives an editor + save". Verified by hand; the only runner is Playwright, so it wants a spec that PUTs a + two-page document, opens the editor, drags one widget and asserts the second page came + back untouched. - CHORE/UI: the transmit pulse and the editor's selection ring are both a 2px inset `--primary` ring, so a control selected in edit mode and one mid-publish look the same. Only visible while editing. @@ -61,24 +83,7 @@ Deferring because out of scope is fine, but don't mention deferring than. - CHORE/API: `save_dashboard` still catches `DashboardNotFound` from `write_draft`, which can no longer raise it. Harmless, and the same shape `saveFlow` has: a PUT to an unknown name now creates that dashboard's first draft rather than answering 404. -- CHORE/UI: the editor-side `ModePicker` and `StylePicker` in `panels.tsx` are still the older - flex row with a jumping `bg-accent` fill, while the widget-side segmented control and - `RangePicker` now slide one thumb over equal grid tracks. Two shapes for one control. -- CHORE/UI: an icon set on a dashboard cannot be cleared from the UI — Radix forbids an empty - `SelectItem` value, so neither the rail-icon select nor the existing "Otherwise" select - offers a "none". Both would need the same affordance. - FEAT/UX add an option to the settings of an installation to configure automatic updates. If enabled, the installation would send a request e.g. every 1h to the hub at fluksio.com and the hub then checks if a new version is available. The settings should include a second toggle for automatically installing an update (which might cause a short outage). Later this mechanism should be extended to check if updating would cause things to break. -- FEAT/UI allow setting icons for multi-page dashboard (when configuring a panel, we could simply add an icon picker there) -- BUG/UI hovering the sidebar where we can switch dashboards on a multi-page dashboard shows a horizontal scrollbar. We should remove that; no scrollbars at all should be shown in this type of sidebar -- CHORE/UI: `.u-legend` is styled in the dashboard's own CSS chunk, so a uPlot legend on a - Health or Home page renders unstyled until a dashboard has been visited in that session. - `RangePicker` already side-effect-imports `dashboard.css` for the segmented thumb; the - legend rules want the same treatment, or a shared chart stylesheet. -- CHORE/UI: the bar widget's readout swaps between an inline `right` and an inline `left` as - the value crosses 30%, and the side it stops setting resets to `auto`, which does not - interpolate — so the label jumps once at that threshold while everything else animates. - Positioning it always by `left` plus a `translateX(-100%)` would put the whole travel on - one property. - CHORE/UI: two of the mobile-overflow floors are over-determined. Removing `.widget-grid { min-width: 0 }`, or the segmented fieldset's `min-w-0`, leaves the mobile suite green — the grid tracks are already `minmax(0, 1fr)` and the fieldset became a grid. @@ -93,7 +98,6 @@ Deferring because out of scope is fine, but don't mention deferring than. which reads like a test failure and is not one. (tests/flows.spec.ts, tests/admin.spec.ts)". There are nine. - BUG/UI in the brain view: make the chasing circle animation running entirely in the gap between the ring and the node (using the full width) -- BUG when clicking "edit" in the "Home" dashboard of the demo on hub.fluksio.com, most of the panels disappear (only a handfull is left for actual edit) - CHORE/UI: the edge popover shows the same value twice — `MessageSparkline` falls through to a collapsed `ValuePreview` for a non-numeric value, and `EdgeInspector` then renders its own `ValuePreview defaultOpen` below it. Cosmetic; one of the two is redundant. - FEAT/UI: a settings-and-inputs overview page, so what every node of an installation is configured with can be read and searched in one place rather than one panel at a time. - FEAT/UI: an input endpoint opens the flow panel, which is right for editing but not for reading one value. A panel of its own — the declaration, the current value, its history — is what clicking a label wants to give. @@ -235,8 +239,10 @@ as an em dash. ### Dashboard follow-ups - FEAT/NODE: the hosted demo places six of the fifteen built-in node types (`python`, `inject`, `change`, `join`, `rbe`, `trigger`); it does cover all fifteen dashboard widget types. `switch` and `delay` are the awkward ones — a `switch` branch needs either a dead-end port or trivial nodes to turn a branch back into a label, and neither reads as something a person would hang — while the I/O types (`mqtt`, `http`, `influxdb`, `exec`, `file`, `ntfy`, `mlp`) are unplaced because the demo has nothing real to talk to. Worth revisiting when the demo grows a second page. -- CHORE/UI: `ROW_HEIGHT` is a fixed 80px while column width follows the canvas, so a 1920-wide panel at 12 columns has 160×80 cells. If that reads too wide, the row height could derive from the canvas too. -- CHORE/UI: multi-page and multi-section dashboards still have no UI, and now need none — a panel carries several whole dashboards instead, each with its own canvas and its own publish. `PageDef`/`SectionDef` stay in the schema and the editor still edits `sectionsOf(page)[0]`, so the page `Tabs` in `DashboardEditor` are dead until something writes a second page through the API. +- CHORE/UI: multi-page and multi-section dashboards have no UI and need none — a panel carries + several whole dashboards instead, each with its own canvas and its own publish. `PageDef`/ + `SectionDef` stay in the schema and still round-trip; the editor and the panel both read a + page's sections as one grid, and section headings are no longer drawn. Recorded, not open. - CHORE/API: a panel paired through the portal is revoked here the moment the panel is deleted — `_panel_may` finds nothing and answers 401 — but the hub's copy of the token stays valid until it expires or the installation's generation counter is bumped ("New code"). The hub has no per-panel revocation, and giving it one means telling it which panels exist, which is exactly what this design avoids. The generation bump is the lever; it is blunt, cutting every credential the portal minted for the installation. The per-panel nonce does not reach it either: `pnc` is only checked on a token this installation signed. - CHORE/UI: the device line under a pairing code is the raw user agent plus the address the request came from. Both are self-reported and neither is proof; it is there so an admin can tell the screen they just hung from one they were not expecting, not to authenticate anything. - CHORE/API: `POST /panels/pair` is reachable from the internet once an installation is enrolled — the hub forwards it without a session, since a device with no credential is the point of it. Bounded three ways (the hub's per-installation and per-address limits, and the fifty-code cap here), but it is the first unauthenticated surface this installation exposes outward.