Widget panel: settings for the bar, icon, forecast and chart axis title
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
Compose Smoke Test / test-compose (push) Canceled after 0s
Playwright Tests / merge-reports (push) Canceled after 0s

The four widget types added this round had renderers but no way to configure
them. The panel now offers a bar's nested reading, unit and range (no step —
that is a slider's), the forecast's item count on the agenda's field, a chart's
y axis title beside its y range, and the icon's mapping editor: a value, a
glyph and a colour per row, first match wins, with a fallback glyph below.

Adds tests/widgets.spec.ts, which asserts each of them on /view: the nested bar
inside its outer fill, the glyph following the message, five forecast columns
fading outwards, a clock that reads the wall without being flagged unbound,
a segmented control and a latching button reading back what they published,
and an unbound tile that says so instead of taking the page down. The axis
title is drawn into uPlot's canvas, so it is checked by panel round-trip.
mobile.spec.ts grows a bar and a forecast so the width check covers them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HTsT1isxUjw5gtkJk8WhuA
This commit is contained in:
2026-08-20 09:48:42 +02:00
co-authored by Claude Opus 5
parent a00b4eaec2
commit 85098eb0dc
4 changed files with 549 additions and 25 deletions
+12 -23
View File
@@ -15,30 +15,33 @@ should reopen it.
- BUG/UI when enlarging the code editor of a node, the code editor should enlarge to the left (node settings remain on the right) so that the code editor fills the center of the screen with the node properties available next to it
- BUG/UX the console/log panel does not show print output of nodes
- BUG/UI loop-lag in home view can't have a value when there are no flows (push back if I'm wrong here)
- BUG/UI brain view in the home view should be hidden when there are no flows/nodes
- CHORE/UI: loop lag on Home reads a real number with no flows, and that is right — `LoopWatchdog` times how late `asyncio.sleep(1.0)` wakes on the API's event loop and is started unconditionally, so it measures the engine process rather than any flow, and it is what turns the health badge `degraded`. Nothing to fix; recorded so it is not reopened.
- FEAT/UI in addition to the two issues above we should introduce a default flow and dashboard for every new user. These should be very minimal to quickly understand what's happening but still show off most of the features of the application. We could make this optional by offering a "Create Demo" button showing at the location of the brain view if there are no existing flows. This demo could then also serve as a demo.fluksio.com site later to play around without signup
- BUG/UI auto node placement on flows should be improved in regards to least crossing edges and a more vertical layout on mobile devices
- BUG/UI when opening a flow, the graph should enlarge from the center (same animation as the brain view). Currently it swipes in from the side
- BUG/UI dots and rings of nodes in the brain graph are not pixel-perfect centered
- BUG/UI rings of ndoes in the brain graph should be come a bit thinner and edges a bit thicker. Also ensure that trigger animations of nodes are still visible. We could use make the ring pulse instead of the existing effect
- BUG/UI HEALTH section shows 1 flow(s) cannot run but boxes below show e.g. 5/5 flows running
- FEAT/UI we should highlight failing nodes accordingly in the flow view to facilitate easier tracking of mis-configurations
- BUG/UI when a dashboard widget is selected, the border does not cleanly draw on the left side of the widget (like it is obscured by the widget)
- BUG/UI: `FlowEditor` wires `onNodesChange` but no `onEdgesChange`, so React Flow's selection change never reaches the edge state and no edge in the flow editor ever carries `.selected`. Both `.react-flow__edge.selected { --edge-rest: var(--primary) }` and `LiveEdge`'s selected stroke are therefore unreachable; clicking an edge only opens the `EdgeInspector`.
- INFRA: ensure that all the packages/ dependencies needed to run fluksio are available on arm to make this software runnable on e.g. raspbian
- INFRA: merge the philosophy statement at the beginning of vision.md into the rest of the document. Dissolve the decision dates and fold the decisions into a clean structure
- CHORE/INFRA: `bunx playwright test` from the host is unsafe against this stack — `app.fluksio.com` and `api.fluksio.com` resolve to production, and `--host-resolver-rules` steers only Chromium while `page.request.*` resolves through Node, so setup and teardown write to the live instance. Run the specs in a container on the `proxy` network with `--add-host` pointing both names at Traefik.
- CHORE/INFRA: `make test-backend` reads `app/.env`, so a checkout configured for a deployment fails two tests that assume the development defaults — `test_private.py::test_create_user` (the `/private` router is off unless `ENVIRONMENT=local`) and `test_mcp_http.py::test_an_agent_can_list_and_call_tools` (the MCP host allow-list is built from `DOMAIN` while the test speaks to `api.localhost`). Both pass under `ENVIRONMENT=local DOMAIN=localhost`; the suite should pin its own environment rather than inherit the deployment's.
- BUG/INFRA: `tests/utils/user.ts`'s `logInUser` still waits for a `Hi, …` heading on Home, which was removed in `449a147`, so both `admin.spec.ts` cases fail on login. Pick an anchor the current Home actually renders.
- CHORE/DOCS: `app/development.md` is still the upstream template's text — `compose.override.yml`, `localhost.tiangolo.com` — and says nothing about the Playwright suite. The containerised run above is what it should carry.
- FEAT/UI add a loading animation for the initial app load and when loading individual pages; make sure that elements e.g. in the home dashboard load independently to ensure a fast loading of the initial site but figures charts, tables, graph etc. follow after that
- FEAT/UI introduce a graph panel which renders at the top right next to the graph view (to make more use of the horizontal space) and which allows (de-) selecting flows to be excluded from the graph view or search for individual nodes where only the flows containing this node should be shown (like slicing the brain)
- FEAT/UI durations are written as a shortened number beside a fixed unit, so a slow run reads "1.2k ms" rather than "1.2 s". A duration formatter that steps the unit itself (µs/ms/s/min) would read better wherever `si` is followed by "ms"
- FEAT/UI the brain's activity falloff is session-observed: a page just opened shows every neuron and connection at the same neutral base, and only sorts itself out as values arrive. A "last published" timestamp per node from the backend would let it open already sorted.
- FEAT/UI labels in flows (indicating dashboard widget connections) naturally can't pulse. Instead add an animation (enlightning fade) from either ltr or rtl depending if the label is in- or outbound
- CHORE/UI: `layoutGraph` treats every node as 220×56 rather than measuring, because feeding a measurement back into the layout oscillates. A node wider than that crowds its neighbours; take the sizes from `node.measured` once they have settled if it shows.
- FEAT/UI/MOBILE: a rank of many nodes — a connector feeding eight dashboard tiles — is thousands of pixels wide however the graph is turned, so on a phone the fit shrinks it past reading. The layout is right and the flow is simply too big for the screen; a "one rank at a time" reading mode, or wrapping a wide rank, is what would make it legible.
- CHORE/UI: an edge's value chip sits at the bezier midpoint while the layout reserves its room at dagre's label rank. The two agree closely enough today; if chips ever pile up, take the position from the layout instead.
- CHORE/UI: the bar widget's nested fill is `--chart-5` against a `--primary` outer fill, which measures 2.53:1 in light mode — under the 3:1 guideline for non-text. The `inset-y-1` gutter supplies the edge, and every other slot of the ramp collapses in dark mode instead.
- CHORE/UI: a streaming edge's dashes sit inside the `prefers-reduced-motion: no-preference` guard, so a reduced-motion user gets no streaming indicator at all. Lifting `stroke-dasharray` alone out of the guard keeps the static signal without the motion.
- CHORE/UI: only node-to-node edges carry the streaming dash. `endpoints.ts` builds a dashboard endpoint's edges without the producing port's `stream` flag, so a training loss feeding a chart — the case the march was drawn for — is still a plain line.
- CHORE/UI: the Home flow-activity table's name cell is `max-w-0` with nothing setting a floor, so `demo_training` reads as "demo⋯" at 1440px while the row has slack to spare. The cap is what keeps the table from widening the page; it wants a minimum beside it.
- CHORE/UI: `.node-pulse`'s `inset: -3px` resolves against the padding box, so on a thick border it lands inside the outer edge and paints over the status ring rather than sitting one ring outward as its comment claims. Measured on a 9px border — the comment and the geometry disagree.
- FEAT/UI (deferred until MCP lands): add a "bot" icon button to the home view (graph panel) which opens a chat window (reuse general concept of a side panel like in flows/nodes to make it a chat panel which can open on any screen (stacks below any other existing panel -> introduce stacking) to give support on errors/write code, generate dashboards etc) to explain the error(s)
- FEAT/UI make the header (Fluksio - YEAR) and the logo in the sidebar link to the main page (fluksio.com)
- FEAT/UI consider adding a diagram to the Home view which shows a histogram of the different classes of nodes and which time it takes to execute (logarithmic scale); this should give a hint on the load and help to detect bottle necks/hotspots
- FEAT/UI streaming edges should get animated (moving dashs) to indicate this type of output visually
### Persistence and databases
@@ -133,21 +136,6 @@ Decisions taken up front, because most items below depend on them:
- CHORE/FLOW: one request/answer pair per InfluxDB node — the first input
carrying a `flux` key is the request and the answer leaves on the first output
port. A second query stream through one node needs a second node.
- FEAT/UI: bar/level widget — a horizontal bar with its value written on it, and
a nested bar for a quantity contained in another (PV inside inverter input).
The arc gauge is the only level display today.
- FEAT/UI: latching toggle button (pressed state read back from a bool message)
and exclusive button group (one of N, the active one read back). The current
button is fire-and-forget and the switch is a lone bool, so a set of room light
modes cannot be expressed.
- FEAT/UI: icon-by-value widget — a mapping from value or range to a lucide icon
and a colour token. Carries both the weather condition icon and derived hints
such as "indoor dewpoint above outdoor, open a window".
- FEAT/UI: forecast strip widget over a `list` message — N columns of label,
icon and value, with the later columns drawn progressively dimmer.
- FEAT/UI: clock widget — local time and date, bound to nothing.
- FEAT/UI: chart axis titles. The unit, the fixed y range and the per-series
label are in; a named axis is not.
- FEAT/UI: the slider offers `step` now, but no tick labels — the `datalist`
marks are unlabelled and drop out past fifty steps.
- FEAT/API: a kiosk credential for `/view/{name}`, so a panel is not a
@@ -172,6 +160,7 @@ as an em dash.
### Dashboard follow-ups
- BUG/UI: ensure dashboard wallpanel (read-only) links hot reload automatically on dashboard changes
- CHORE/UI: an icon rule stores a `label` — the widget draws it under the glyph and uses it as the glyph's accessible name — but the mapping editor offers no field for it, so it can only be set through the API.
- BUG/UI: shrinking the canvas silently clips whatever now falls past its bottom edge. `maxRows` only constrains a new drag, not a stored placement, so nothing warns and nothing offers to reflow.
- CHORE/UX: dropping a widget also selects it, which opens its panel — which rescales the canvas the instant you let go. Correct, but it lurches; either leave the panel closed on a drag-release or animate the scale.
- 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.