# TODO - [ ] **MAJOR** Implement configuration manager: - configuration is a set of signals (that can be organized in group and subgroup) that are used to configure a system or a sub system - with configuration manager user should be able to: - Define and manage configuration sets: delete (keep server side copy of deleted config), create (specifying default to parameters, mandatory, optional etc), edit (with versioning git style) and compare set - user can fork an existing config instance to create a new one - user can compare two instances: show unified diff or side by side diff - etc... - Create, delete (keep server cache), edit (git style versioning) and compare configuration instances: meaning set actual value to a configuration set - user can fork an existing config instance to create a new one - user can compare two instances: show unified diff or side by side diff - etc... - [x] user can apply and save configuration instances from manager - [x] **instance snapshot**: create a new instance from the current live value of all of a set's target signals (optional label, else auto name) — exposed in the config editor (⎙ Snapshot), control loop (`action.config.snapshot`) and logic editor (`action.config.snapshot`) - [x] **live diff**: compare a stored instance against current signal values ("Diff vs current" button → `/config/instances/{id}/livediff`) - [x] git-style versioning for config sets and instances: fork any revision, click to view, promote to current, with unified / side-by-side diff (shared `VersionTree`) - [x] in logic editor and control loop add nodes to read/write/create/apply config instances - [x] **apply** and **read** config-instance nodes in both control logic (server Go) and panel logic (client TS) - [x] **create / write** nodes (mutate versioned instances from automation) in both engines - [x] **Config Selector** panel widget: operator picks an instance of a chosen set (optionally a subset) from a combo, writing its id to a panel-local string variable; apply/read/write panel-logic nodes can read their instance dynamically from that variable ("From variable" source) - [x] support for all supported types (number, bools, enums, arrays, string etc) - [x] ux elements for config set - [x] the configuration editor should automatically get type and info from signal when possible (type is read-only, auto-derived from the bound signal) - [x] a slick tree drag and drop editor to order elements and organize in group and sub-groups - [x] possibility to customise unit, max, min etc - [x] export / import a config set as JSON - [x] full-screen config window - [x] ux elements for config instances: - automatically use the correct setting widget depending on the type (e.g. combo for enum, nubmer input for number): - for arrays: import csv option, display points as mini plot (+ open dialog plot with more info), manual enter points via table like interface - automatically fill with default or existing values (when forking an existing instance) - explicity show errors/missing info and give additional info on hover - [x] add advanced validation / transformation framework to configurations using custom CUE rules: - [x] backend runs validation / transformation rules (real CUE via `cuelang.org/go`; `internal/confmgr/cue.go`). Rules are a third versioned `Kind` bound to a set; evaluated on instance create/update — violations block the save, concrete derivations transform & persist the values - [x] user can create/edit/delete/compare rules from webui (Rules tab in ConfigManager; git-style versioning + side-by-side/unified source diff) - [x] integrate syntax highlight (hand-rolled `CueEditor.tsx`, mirroring `LuaEditor`) - [x] integrate autocomplete for signals names and cue grammars (param keys + target signals + CUE keywords/types; Ctrl+Space) - [ ] ~~integrate cue lsp~~ — descoped: a separate language-server process does not fit the no-npm / single portable-binary architecture - [x] when validation fails the error is propagated to the user (live `/config/rules/check` panel while editing; save returns the structured violation) - [x] all actions tracked via history (versioned rules) + audit (`config.rule.create/update/delete/promote/fork`) - [ ] Improve UX: - Config editor: - [x] Instance should be filtered by config set (combo box) (`ConfigManager.tsx` InstancesManager: `setFilter` combo in the instance list head, shown when >1 set; empty-set hint) - [x] Validation rules should also be filtered by config set (combo box) (`ConfigManager.tsx` RulesManager: `setFilter` combo mirroring instances, shown when >1 set; empty-set hint; `Meta.setId` surfaced via `List`) - [x] Validation rules can be enabled / disabled — disabled rules are skipped when an instance is created/updated/applied (`Enabled *bool`, nil=enabled for legacy; `IsEnabled()`; `rulesForSet` skips disabled; UI checkbox + list `off` badge) - [x] Rule editor preview button — runs the working (unsaved) source against a live signal snapshot of the set without persisting it, showing the input snapshot JSON and processed output JSON (`POST /config/rules/preview` → `previewConfigRule`; `RulePreviewView`) - [ ] Synthetic editor: - [x] color code the node link by type - [x] edges color depends on type (e.g. float) including arrays (scalar = slate, array = purple) - [x] input / outputs are color coded (out port = node's type; in port = accepted type, gray when it accepts either) - [x] can not connect input / output that are not compatible (definite scalar↔array mismatch blocked; unknown/any always allowed) - [x] hover on a block in error should show the reason - [x] add proper array functionality - [x] add shortcut to add Signals (S) and nodes (N) with HUD - [ ] Panels: - [x] in view mode the widgets should have no border/bg but blend with background - [ ] add widgets such as toggle switch, table and other industrial hmi widgets - [x] toggle switch (`web/src/widgets/Toggle.tsx`; read+write bool control, configurable on/off value+label, confirm dialog) - [x] table widget (`web/src/widgets/TableWidget.tsx`; multi-signal value table, one row per bound signal, configurable columns name/value/unit/status/time, optional header + title, per-signal value format + row-label overrides; blends in view mode) - [ ] other industrial hmi widgets - [x] widget panel exposes an editable Widget ID field (default = generated uuid) for easier logic interaction (`PropertiesPane.tsx` `IdInput`; `EditMode.renameWidgetId` propagates the rename to `action.widget` logic refs + plot-layout leaves; rejects empty/duplicate ids) - [x] add container widgets: labelled/title pane, tab panes, collapsable panes (`web/src/widgets/Container.tsx`; decorative grouping frame rendered behind widgets, accent/bg options; `pane` variant = title + view-mode collapse; `tabs` variant = tab bar where each contained widget is assigned a tab via its "Tab" field and only the active tab shows; geometric membership via `web/src/lib/containers.ts`) - [x] moving container widget should move the widgets on it — starting a move (drag or arrow nudge) on a container snapshots the widgets geometrically inside it (centre-inside, transitive through nested containers) and moves them by the same delta; membership is captured at move start so widgets never re-parent mid-move (`withContainedWidgets` in `web/src/lib/containers.ts`, used by `EditCanvas` drag-start + `EditMode` arrow nudge) - [x] plot pane: - [x] add toolbar (hover toolbar in `PlotWidget`, `.plot-toolbar`) - [x] add time window selector to toolbar (Auto/15s/30s/1m/5m/15m/1h rolling-window override, live windowed plot types) - [x] plot x-axis synchronised (shared uPlot cursor crosshair across all linked timeseries plots + zoom/pan range sync in historical mode; per-plot 🔗 link/unlink toolbar toggle; `web/src/lib/plotSync.ts`) - [x] cursors and measuraments (📏 measure mode: click cursor A then B → on-canvas A/B lines + readout panel with Δt/rate and per-signal value@A→value@B and Δ) - [x] pause/resume (local toolbar pause, OR'd with panel-logic pause; buffers persist across plot-type/window changes) - [x] save screenshot (PNG export — uPlot canvas / ECharts getDataURL) - [x] clean ui: - [x] create small statusbar where connection widget and other status related info will be placed (bottom `.statusbar`: connection chip + current panel name + history indicator) - [x] group advanced items (audit/control loops/config manager etc) in a tool menu or something similar to not fill the toolbar (⋯ Tools ▾ dropdown) - [x] make the toolbar as clean as possible (toolbar-right now: History · 📖 · zoom · Tools · Edit) - [x] panel-selection list: the whole row is clickable to open a panel (not just the name text); `onClick` moved to the `
  • `, action buttons `stopPropagation` (`InterfaceList.tsx`) - [x] panel-selection list: plot vs panel entries shown with distinguishing monochrome inline-SVG icons (line-chart = plot / control-panel = HMI; `KindIcon`, currentColor); backend `InterfaceMeta.Kind` surfaced from the XML `kind` attr, `InterfaceListItem.kind` in the frontend type (preserved through the list normalizer) - [ ] implement proper grouping strategy, in all selector tree the options should be filtered by user (private config), group (combo to select group if user in multiple groups), global (public config) - [ ] panel tree by user / group / global - [ ] signal tree by user / group / global - [ ] config tree by user / group / global - [ ] control sequence by user / group / global - [ ] Node editors: - [x] In all editors, implement node grouping and collapsing feature (with optional group label) (Shift+click multi-select → G/⊞ to group; editable label; ▾/▸ collapse to a compact box that reroutes crossing wires; Delete ungroups; shared `web/src/lib/nodeGroups.ts`; persisted in panel-logic XML + control-logic/synthetic JSON via Go `NodeGroup` structs — cosmetic editor metadata, ignored at eval) - [x] opened group should be on top of other nodes (group frame lifted to z-index 1 above loose nodes; member nodes get `.flow-node-grouped` at z-index 2 so they stay above their own frame and clickable; applied in all three editors) - [x] node counter should be better padded (`.flow-group-count` gained vertical padding so the "N nodes" line isn't cramped against the collapsed-box header) - [x] In all editors: undo / redo + copy / paste with shortcuts (Ctrl+Z / Ctrl+Shift+Z / Ctrl+Y undo-redo; Ctrl+C / Ctrl+V copy-paste of the selection, multi-select aware, internal wires preserved, ids remapped, pasted +offset; ref-based 50-deep history + clipboard scoped per editor; toolbar ↩/↪ buttons). Panel `LogicEditor` already had this; added to `ControlLogicEditor` (undo/redo + copy/paste) and `SyntheticGraphEditor` (copy/paste — it already had undo/redo). Synthetic paste never copies the permanent output node - [x] In all editors: implement zoom in / out, home zoom and fit zoom to help user navigate complex graph (shared `web/src/lib/flowZoom.ts` `useFlowZoom` hook; CSS `transform: scale()` on a `.flow-canvas-zoom` layer inside the scaled `.flow-canvas-inner`; toolbar row −/%/+/⤢ in all three editors; `toCanvas` divides pointer offsets by zoom) - [x] fix: the fit-zoom (⤢) button was clipped outside the fixed-width palette — toolbar buttons now shrink to fit (`min-width:0`, zero side padding in `.flow-palette-toolbar .toolbar-btn`) - [x] fix: zoom value (e.g. 100%) is overflowing, reduce padding and increase the zoom value widget width (`flow-zoom-pct` class on the zoom-value button → `flex:1.9` so it gets ~2× the width of the single-glyph icon buttons; toolbar font dropped to 0.75rem, gap to 0.25rem, `tabular-nums` to stop width jitter; all three editors) - [x] Live / debug mode in all three node editors — evaluate the graph online and badge each node's value at human speed (~0.5 s). Shared frontend `web/src/lib/flowDebug.ts` (badge/active classes, `useFlowDebug` poller) + CSS `.flow-node-active`/`.flow-node-badge`/`.flow-wire-active`; a green ◉ toggle in each `.flow-palette-toolbar`. Per-editor backends: - [ ] Syntetic signal editor: - [x] Implement live / debug mode where value are evaluated online and visualized at human speed (e.g. 0.5s) — server-side stateless single-shot trace: `POST /api/v1/synthetic/trace` snapshots live source signals (broker `ReadNow`) and runs `evalSampleTrace` with fresh state, returning every node's value; stateful ops (moving_average/rms/lowpass/derivative/integrate/lua) badged `~approx` - [ ] Logic editor: - [x] Implement live / debug mode where value are evaluated online and visualized at human speed (e.g. 0.5s) — editor spins up a second client-side `LogicEngine` in new `dryRun` mode (real writes/config/dialogs suppressed) loaded with the edited graph; per-node values polled into the shared badges; the view-mode singleton is untouched - add full suppor to local array values: dynamic, dynamic but capped max, fixed size etc: - array functions should work with new local array - [ ] Control loop: - [x] Implement live / debug mode where value are evaluated online and visualized at human speed (e.g. 0.5s) — server pushes per-node events over the WS (`debugSubscribe`/`debugNode`) via a new `DebugObserver` on the engine (lock-free `atomic.Value`, gated by a per-graph watch set) + `internal/server/debughub.go` (drop-on-full fan-out). Two modes share one message shape: **Live** observes the running enabled graph; **Simulate** dry-runs the unsaved edits in a throwaway sandbox (`StartSimulate`, side effects suppressed). Live/Sim sub-toggle in the editor - add full support to server side array values - [x] Implement git style versioning for: synthetic variable, panels, control logic: - [x] possibility to fork any version - [x] click to view the version - [x] possibility to view graphical diff between versions (side by side or unified diff) - [x] simple slick versioning pane: - [x] vertical tree like - [x] each version represented by a circle - [x] active (the one currently view/edited) version has circle bigger then rest - [x] selected (the one that will be executed/showed by user) version has circle full, not active only border - [x] unsaved / new version appear with connection line dashed - [x] Implement admin pane: create / manage groups, set users permits, manage auditors etc - [x] user manager - [x] group manager - [x] server statistics: load, conenctions, observed signals, average latency, other statistics - [ ] Implement new datasources: - [ ] Finalize alarm service - [ ] modbus tcp - [ ] scpi tcp / VXI-11 protocol - [ ] udp? other? - [ ] **MAJOR** Implement proper distributed server side nodes to balance load and have redundancy (if a node is not available anymore all its clients migrate seamelessly to another) - [ ] clients should be distributed to balance load\ - same user should be (if possible) connect to only one service to simplify synch issue - [ ] control sequences should be executed in only in one server instance but with backups ones to take over if the active service stop or die - [ ] sync config between service - [ ] manage conflict - [ ] avoid incorrect - [ ] ensure that the system can survive with up to only one instance alive - [ ] advance admin panel: - [ ] should have info about service topology and statistics of each server - [ ] admin should deploy new instances via ssh to target machines directly from the admin panel - [ ] for phisical connect datasource (e.g. modbus) pin the service to a specific machine or deploy specific datasource only service to a machine: user can setup backup instances (e.g. machine in the same sub-network that can be switched on in case primary fail) - [ ] QA and CI - [ ] coverage of service 90+% - [ ] coverage of client 80+% - [ ] add integrated tests with interface simulations - [ ] update doc and keep user manual up to date - [ ] add code example for lua scripts - [ ] add tutorial