20 KiB
20 KiB
TODO
- BUG FIX:
- connecting from firefox always get default user — native SPNEGO/Kerberos auth (
[server.kerberos],internal/server/kerberos.go): uopi challenges with401 Negotiateand resolves the user from the validated ticket instead of relying on a proxy header Firefox never triggers; on non-Kerberos hosts (SSSD/LDAP) use standalone built-in HTTP Basic auth — either validated via PAM ([server.basic_auth],internal/pamauth, build withmake backend-pam) or, keeping the static binary, pure-Go LDAP search-then-bind ([server.ldap],internal/ldapauth) — sharinginternal/server/basicauth.go(which also challenges the page load so the browser shows its login dialog) with optional built-in TLS ([server.tls]) - dpi scaling seems not to work on firefox — root font-size now folds in
window.devicePixelRatio(applyZoom= 16×zoom×dpr) withwatchDpr()re-applying on monitor change
- connecting from firefox always get default user — native SPNEGO/Kerberos auth (
- 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...
- 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 apply and save configuration instances from manager
- 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) - live diff: compare a stored instance against current signal values ("Diff vs current" button →
/config/instances/{id}/livediff) - 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) - in logic editor and control loop add nodes to read/write/create/apply config instances
- apply and read config-instance nodes in both control logic (server Go) and panel logic (client TS)
- create / write nodes (mutate versioned instances from automation) in both engines
- 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)
- support for all supported types (number, bools, enums, arrays, string etc)
- ux elements for config set
- the configuration editor should automatically get type and info from signal when possible (type is read-only, auto-derived from the bound signal)
- a slick tree drag and drop editor to order elements and organize in group and sub-groups
- possibility to customise unit, max, min etc
- export / import a config set as JSON
- full-screen config window
- 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
- automatically use the correct setting widget depending on the type (e.g. combo for enum, nubmer input for number):
- add advanced validation / transformation framework to configurations using custom CUE rules:
- backend runs validation / transformation rules (real CUE via
cuelang.org/go;internal/confmgr/cue.go). Rules are a third versionedKindbound to a set; evaluated on instance create/update — violations block the save, concrete derivations transform & persist the values - user can create/edit/delete/compare rules from webui (Rules tab in ConfigManager; git-style versioning + side-by-side/unified source diff)
- integrate syntax highlight (hand-rolled
CueEditor.tsx, mirroringLuaEditor) - 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
- integrate syntax highlight (hand-rolled
- when validation fails the error is propagated to the user (live
/config/rules/checkpanel while editing; save returns the structured violation) - all actions tracked via history (versioned rules) + audit (
config.rule.create/update/delete/promote/fork)
- backend runs validation / transformation rules (real CUE via
- Improve UX:
- Config editor:
- Instance should be filtered by config set (combo box) (
ConfigManager.tsxInstancesManager:setFiltercombo in the instance list head, shown when >1 set; empty-set hint) - Validation rules should also be filtered by config set (combo box) (
ConfigManager.tsxRulesManager:setFiltercombo mirroring instances, shown when >1 set; empty-set hint;Meta.setIdsurfaced viaList) - Validation rules can be enabled / disabled — disabled rules are skipped when an instance is created/updated/applied (
Enabled *bool, nil=enabled for legacy;IsEnabled();rulesForSetskips disabled; UI checkbox + listoffbadge) - 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)
- Instance should be filtered by config set (combo box) (
- Synthetic editor:
- color code the node link by type
- edges color depends on type (e.g. float) including arrays (scalar = slate, array = purple)
- input / outputs are color coded (out port = node's type; in port = accepted type, gray when it accepts either)
- can not connect input / output that are not compatible (definite scalar↔array mismatch blocked; unknown/any always allowed)
- hover on a block in error should show the reason
- add proper array functionality
- add shortcut to add Signals (S) and nodes (N) with HUD
- color code the node link by type
- Panels:
- 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
- toggle switch (
web/src/widgets/Toggle.tsx; read+write bool control, configurable on/off value+label, confirm dialog) - 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
- toggle switch (
- widget panel exposes an editable Widget ID field (default = generated uuid) for easier logic interaction (
PropertiesPane.tsxIdInput;EditMode.renameWidgetIdpropagates the rename toaction.widgetlogic refs + plot-layout leaves; rejects empty/duplicate ids) - add container widgets: labelled/title pane, tab panes, collapsable panes (
web/src/widgets/Container.tsx; decorative grouping frame rendered behind widgets, accent/bg options;panevariant = title + view-mode collapse;tabsvariant = tab bar where each contained widget is assigned a tab via its "Tab" field and only the active tab shows; geometric membership viaweb/src/lib/containers.ts)- 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 (
withContainedWidgetsinweb/src/lib/containers.ts, used byEditCanvasdrag-start +EditModearrow nudge)
- 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 (
- plot pane:
- add toolbar (hover toolbar in
PlotWidget,.plot-toolbar) - add time window selector to toolbar (Auto/15s/30s/1m/5m/15m/1h rolling-window override, live windowed plot types)
- 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) - 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 Δ)
- pause/resume (local toolbar pause, OR'd with panel-logic pause; buffers persist across plot-type/window changes)
- save screenshot (PNG export — uPlot canvas / ECharts getDataURL)
- add toolbar (hover toolbar in
- clean ui:
- create small statusbar where connection widget and other status related info will be placed (bottom
.statusbar: connection chip + current panel name + history indicator) - group advanced items (audit/control loops/config manager etc) in a tool menu or something similar to not fill the toolbar (⋯ Tools ▾ dropdown)
- make the toolbar as clean as possible (toolbar-right now: History · 📖 · zoom · Tools · Edit)
- panel-selection list: the whole row is clickable to open a panel (not just the name text);
onClickmoved to the<li>, action buttonsstopPropagation(InterfaceList.tsx) - panel-selection list: plot vs panel entries shown with distinguishing monochrome inline-SVG icons (line-chart = plot / control-panel = HMI;
KindIcon, currentColor); backendInterfaceMeta.Kindsurfaced from the XMLkindattr,InterfaceListItem.kindin the frontend type (preserved through the list normalizer)
- create small statusbar where connection widget and other status related info will be placed (bottom
- 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). Uniform scope model: each item carries owner + scope ∈ {private,group,global} + scope-groups; empty/unknown scope = global (legacy-safe). Shared Go helper
access.CanSee(internal/access/scope.go) filters list endpoints by the caller; shared frontendweb/src/lib/scope.tsxprovidesbucketOf/filterByScope, the segmented[Mine | Group ▾ | Global]ScopeFilter, and theScopePickercreate/save visibility editor. Visibility is a selector filter, not a hard security boundary (owner always sees own items)- panel tree by user / group / global — scope bucket derived server-side from the panel ACL (
panelScopeininternal/api/api.go: public→global, group grant→group, else→private; unmanaged→global), surfaced onInterfaceListItem.scope/groups;InterfaceList.tsxfilters panels by bucket and hides folders with no in-scope descendants; visibility is edited via the existing Share dialog - signal tree by user / group / global — synthetic
SignalDefgained agroupvisibility mode +Groups[];synVisible(api.go) routes it throughaccess.CanSee;SyntheticGraphEditor.tsxwizard offers panel/user/group/global with group checkboxes - config tree by user / group / global —
ConfigSet/ConfigInstancecarry owner+scope+groups (internal/confmgr), list endpoints filter viafilterConfigMetas/CanSee, owner preserved across updates;ConfigManager.tsxaddsScopeFilter+ScopePickerto both Sets and Instances managers - control sequence by user / group / global — control-logic
Graphgained owner+scope+scopeGroups (internal/controllogic/model.go; namedscopeGroupsto avoid the existing cosmeticGroups []NodeGroup);listControlLogicfilters viaCanSee, create/update stamp/preserve owner;ControlLogicEditor.tsxaddsScopeFilter+ScopePicker(filterByScope(..., g => g.scopeGroups ?? []))
- panel tree by user / group / global — scope bucket derived server-side from the panel ACL (
- Config editor:
- Node editors:
- 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 GoNodeGroupstructs — cosmetic editor metadata, ignored at eval)- opened group should be on top of other nodes (group frame lifted to z-index 1 above loose nodes; member nodes get
.flow-node-groupedat z-index 2 so they stay above their own frame and clickable; applied in all three editors) - node counter should be better padded (
.flow-group-countgained vertical padding so the "N nodes" line isn't cramped against the collapsed-box header)
- opened group should be on top of other nodes (group frame lifted to z-index 1 above loose nodes; member nodes get
- 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
LogicEditoralready had this; added toControlLogicEditor(undo/redo + copy/paste) andSyntheticGraphEditor(copy/paste — it already had undo/redo). Synthetic paste never copies the permanent output node - In all editors: implement zoom in / out, home zoom and fit zoom to help user navigate complex graph (shared
web/src/lib/flowZoom.tsuseFlowZoomhook; CSStransform: scale()on a.flow-canvas-zoomlayer inside the scaled.flow-canvas-inner; toolbar row −/%/+/⤢ in all three editors;toCanvasdivides pointer offsets by zoom)- 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) - fix: zoom value (e.g. 100%) is overflowing, reduce padding and increase the zoom value widget width (
flow-zoom-pctclass on the zoom-value button →flex:1.9so it gets ~2× the width of the single-glyph icon buttons; toolbar font dropped to 0.75rem, gap to 0.25rem,tabular-numsto stop width jitter; all three editors)
- fix: the fit-zoom (⤢) button was clipped outside the fixed-width palette — toolbar buttons now shrink to fit (
- 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,useFlowDebugpoller) + CSS.flow-node-active/.flow-node-badge/.flow-wire-active; a green ◉ toggle in each.flow-palette-toolbar. Per-editor backends: - Syntetic signal editor:
- 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/tracesnapshots live source signals (brokerReadNow) and runsevalSampleTracewith fresh state, returning every node's value; stateful ops (moving_average/rms/lowpass/derivative/integrate/lua) badged~approx
- Implement live / debug mode where value are evaluated online and visualized at human speed (e.g. 0.5s) — server-side stateless single-shot trace:
- Logic editor:
- 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
LogicEnginein newdryRunmode (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
- NOTE: Phase 1 (panel logic, client-side TS) is DONE — array statevars (dynamic/capped/fixed), value-polymorphic expression engine with indexing + array functions,
action.array.*mutation nodes (legacy accumulate/export/clear unified + auto-migrated), panel-XML round-trip, editor declaration form, and widget array modes (plot/table/multi-LED). Phase 2 (server-sideinternal/controllogicGo port, see below) has now landed, so this feature is complete across both engines.
- 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
- Control loop:
- 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 newDebugObserveron the engine (lock-freeatomic.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 — DONE (Phase 2):
Value = float64 | []Valuemodel (internal/controllogic/value.go),Graph.StateVars(number/bool/array with dynamic/capped/fixed sizing) persisted in store JSON, value-polymorphicexpr.go(array literals, negative-wrap indexing, full array-function table), andaction.array.push|set|remove|pop|clearnodes. Lua block stays scalar-only (array local → NaN); CSV export remains panel-logic-only
- 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 (
- 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
- Implement git style versioning for: synthetic variable, panels, control logic:
- possibility to fork any version
- click to view the version
- possibility to view graphical diff between versions (side by side or unified diff)
- simple slick versioning pane:
- vertical tree like
- each version represented by a circle
- active (the one currently view/edited) version has circle bigger then rest
- selected (the one that will be executed/showed by user) version has circle full, not active only border
- unsaved / new version appear with connection line dashed
- Implement admin pane: create / manage groups, set users permits, manage auditors etc
- user manager
- group manager
- 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)
- clients should be distributed to balance load\
- 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