NOTEPAD: clear what wave 2 closed, record what it left
Docs / docs (push) Canceled after 0s
Playwright Tests / test-playwright (1, 2) (push) Canceled after 0s
Playwright Tests / test-playwright (2, 2) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Test Backend / test-backend (push) Canceled after 0s
Compose Smoke Test / test-compose (push) Canceled after 0s
Playwright Tests / merge-reports (push) Canceled after 0s

This commit is contained in:
2026-08-22 12:24:56 +02:00
parent eb2e6bf6d2
commit 3cc2d353cd
+29 -23
View File
@@ -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.