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
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:
+29
-23
@@ -12,9 +12,31 @@ Deferring because out of scope is fine, but don't mention deferring than.
|
|||||||
|
|
||||||
### To be sorted
|
### To be sorted
|
||||||
|
|
||||||
- CHORE/UI: no affordance for `POST /panels/{id}/unpair`. The panels dialog can pair a
|
- CHORE/DEMO: `seed_demo.py` still writes the Home dashboard as three titled sections
|
||||||
device but not re-pair one; `PanelsService.unpairPanel({ panelId })` is generated and
|
("Right now", "Energy and comfort", "Yield model"). The editor and the panel now read a
|
||||||
the docs already describe it. Invalidate `panelKeys.all` after.
|
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
|
- 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.
|
`--primary` ring, so a control selected in edit mode and one mid-publish look the same.
|
||||||
Only visible while editing.
|
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
|
- 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
|
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.
|
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/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
|
- 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
|
`.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.
|
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.
|
which reads like a test failure and is not one.
|
||||||
(tests/flows.spec.ts, tests/admin.spec.ts)". There are nine.
|
(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/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.
|
- 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: 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.
|
- 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
|
### 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.
|
- 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 have no UI and need none — a panel carries
|
||||||
- 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.
|
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/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/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.
|
- 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.
|
||||||
|
|||||||
Reference in New Issue
Block a user