Commit Graph

33 Commits

Author SHA1 Message Date
Joseph Doherty a4cdedc31c fix(adminui): confirm equipment-page and script deletes (R04 H1)
The equipment page's Remove reference / Delete virtual tag / Delete alarm row
buttons and the ScriptEdit Delete ran on the first click. They now go through
RawConfirmDialog, the same confirm /raw uses. The ScriptEdit change is limited
to the delete button and its dialog.

Refs #745
Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT
2026-10-22 17:53:06 -04:00
Joseph Doherty 1475991fd6 fix(adminui,client): error boundary inside the interactive scope, stale-commit OnSaved, AbCip browse delay emit, DisposeBridge cancel (review R3)
M1: PageErrorBoundary wraps the body of every InteractiveServer page; the inert layout boundary is removed.
m1: DisposeBridge cancels its CTS when the 5 s wait times out.
m2: a CSV import that commits after the modal closed still raises OnSaved.
m3: document SecurityMode=None no-fallback in Client.CLI.md / Client.UI.md.
m4: browsePageDelayMs written only when loaded or changed; negative flagged.

Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
2026-10-08 07:31:19 -04:00
Joseph Doherty 4cbd03bd21 ui(equipment): adopt panel idiom on tab bodies + bound RawPath column (§1d Task 3) 2026-08-10 18:00:20 -04:00
Joseph Doherty 30345c2941 style(adminui): group UNS page + modal buttons into btn-groups
Task 3 of the AdminUI UI sweep. Behavior-preserving markup only:

- GlobalUns: Expand/Collapse pair -> btn-group btn-group-sm (Import stays
  separate); delete-confirm footer Cancel+Delete -> btn-group.
- Area/Line/ScriptedAlarm/VirtualTag/AddReference/ImportEquipment modal
  footers: Cancel + primary -> btn-group.
- EquipmentPage: the three text-end action cells (Save name/Remove,
  Edit/Delete x2) -> btn-group btn-group-sm, me-1 spacers dropped.
- UnsTree: per-node actions become real small buttons (outline-secondary,
  outline-danger for destructive) and adjacent runs of >=2 group into
  btn-group btn-group-sm; the genuine navigation links (cluster settings,
  equipment Open) stay links. Expander/leaf placeholder adopt .tree-twist
  in place of the inline width:18px.
2026-08-10 16:31:55 -04:00
Joseph Doherty 1a1dbc3f00 fix(uns): enforce the UNS segment rule on every authoring path (#535)
v2-ci / build (push) Successful in 4m30s
v2-ci / unit-tests (push) Failing after 16m11s
An area or line could be named "Packaging" or "Line 1", save cleanly, and then
fail the NEXT deployment with UnsSegmentInvalid. Because a deployment snapshots
the whole database, one badly-named area blocked EVERY cluster's deploy - and
whoever hit that was usually not whoever typed the name. Only the equipment form
carried the rule; the deploy gate held its own private copy.

The rule now lives once, on Configuration.Validation.UnsSegment, and both ends
call it. DraftValidator no longer restates it.

Enforced in UnsTreeService, not just on the forms:
- Create/Update Area, Line and Equipment reject an invalid name before touching
  the row.
- The CSV import reports a bad name as an ERROR, not a skip - a skip means "you
  already have this row", which would tell the operator the equipment exists
  when it does not. Good rows in the same batch still insert.

A form attribute could never have covered the import, and with no bUnit in this
repo a rule only a form enforces is also a rule no test can reach. The forms
keep an attribute for the immediate message, but it now references the shared
pattern rather than restating it - a second copy is how these drifted apart.

One behaviour change beyond the fix: UnsSegment.AttributePattern admits
"_default", which the equipment form's hand-written literal rejected. The form
was stricter than the gate it was mirroring, so a _default row was uneditable
through the AdminUI.

Tests: 41, falsified with three production mutations - dropping the CreateArea
guard reds exactly the CreateArea rejections, turning the import error back into
a skip reds only the import test, and narrowing AttributePattern reds only the
attribute/IsValid agreement. Every rejection is paired with a name that must
still be accepted, or a guard that refused everything would pass.

Live-verified on docker-dev: the area modal now refuses "Packaging" in place
with the rule spelled out, "packaging-b" saves, and a CSV import of two rows
reports Inserted 1 / Skipped 0 / Errors 1 naming the offending row - the path no
form attribute reaches. Rig cleaned up and a further deployment sealed.

Claude-Session: https://claude.ai/code/session_015p7wGqy3YpZNCpDzTpGMKo
2026-08-01 11:53:58 -04:00
Joseph Doherty 77bc010ba9 v3 Batch 3 WP1: UNS Equipment Tags tab → reference list + raw-tag picker
Replace the Batch-1-stubbed authored-tag flow with a UnsTagReference list on the
equipment page's Tags tab (v3 reference-only equipment): columns are effective name,
computed raw path, inherited datatype/access (read-only), display-name override
(editable), and remove. The retired equipment-authored-tag editor (TagModal.razor)
is deleted; the VirtualTag and ScriptedAlarm flows are untouched.

- "+ Add reference" opens a new AddReferenceModal that reuses RawTree in a new opt-in
  PickerMode (Tag-leaf checkboxes + Device/TagGroup "select all tags below"), scoped
  structurally to the equipment's cluster via LoadReferencePickerRootAsync (a single
  cluster root — cross-cluster tags are unreachable, not merely hidden). Default /raw
  usage is byte-unchanged (PickerMode defaults false).
- UnsTreeService (+ IUnsTreeService) gain the reference mutations:
  LoadReferencesForEquipmentAsync (computes each RawPath via the shared RawPathResolver),
  AddReferencesAsync (cluster-checked, all-or-nothing), RemoveReferenceAsync,
  SetReferenceOverrideAsync, plus the picker helpers LoadReferencePickerRootAsync /
  LoadDescendantTagIdsAsync.
- Consume IEffectiveNameGuard (constructor-injected, no-op fallback when unregistered):
  AddReferences, SetReferenceOverride, and the VirtualTag + ScriptedAlarm create/update
  mutations now call CheckAsync before persisting and surface a collision as the failure.
  WP2 supplies the implementation + DI registration.
- Drop the retired equipment↔driver binding: remove DriverInstanceId from EquipmentInput,
  the ImportEquipmentModal CSV column, the EquipmentPage Details driver select, and the
  dead decision-#122 driver-cluster guard.

Tests: new UnsTreeServiceReferenceTests (add/remove/override, cross-cluster + duplicate
rejection, guard-consumed rejection via a fake guard, RawPath projection, picker helpers);
Equipment/Import test suites rewritten to drop the retired driver-guard cases. AdminUI
suite green (639 passed, 3 skipped); full solution builds 0 errors.

Claude-Session: https://claude.ai/code/session_01LVneM3eh1UtJxEisFXgmox
2026-07-16 06:15:51 -04:00
Joseph Doherty b5bf4b73ff fix(adminui): gate every page with named policies — ConfigEditor on the mutating surface (R2-05, 04/C-1) 2026-07-13 09:56:08 -04:00
Joseph Doherty 23f353e79b test(adminui): close Phase 6 review test-gaps + Enterprise-delete warning 2026-06-16 17:10:40 -04:00
Joseph Doherty 526eebb3bb feat(adminui): UNS-tree delete for Cluster + Enterprise (refuse-if-children, no rowversion) 2026-06-16 16:35:07 -04:00
Joseph Doherty 0945f19a50 feat(adminui): wire Galaxy live-browse picker into the standard TagModal 2026-06-12 22:09:22 -04:00
Joseph Doherty 5dfb797817 refactor(adminui): strip alias/relay machinery from UnsTreeService + EquipmentPage; Galaxy tags use standard TagModal 2026-06-12 21:28:13 -04:00
Joseph Doherty ca2698949b refactor(adminui): delete alias-tag/relay-converter files (build red until spine stripped) 2026-06-12 21:20:41 -04:00
Joseph Doherty e77fd3eec0 fix(adminui): converter UI — try/catch + confirm + FleetAdmin gate on per-equipment convert (review) 2026-06-11 21:54:21 -04:00
Joseph Doherty 7682d185fb feat(adminui): relay->alias converter UI (per-equipment + fleet-wide /uns/convert-relays) 2026-06-11 21:49:43 -04:00
Joseph Doherty 299eaa461c fix(adminui): gate Galaxy picker so it doesn't clobber alias FullName on edit; refresh gateways (review) 2026-06-11 21:45:55 -04:00
Joseph Doherty 4af27ea173 feat(adminui): AliasTagModal + Tags-tab Add-alias (Galaxy picker) 2026-06-11 21:37:04 -04:00
Joseph Doherty 80b19d6fc8 chore(uns): create-redirect null guard + alarm isolation test + alarm-authoring doc (final review) 2026-06-11 15:23:06 -04:00
Joseph Doherty f1c4392b0d refactor(uns): drop dead LoadEquipmentChildrenAsync + LinesForCluster; fix stale comment 2026-06-11 15:11:28 -04:00
Joseph Doherty 826ffdc1a0 feat(uns): equipment is a tree leaf linking to the detail page; drop EquipmentModal 2026-06-11 15:01:10 -04:00
Joseph Doherty 773c073d0e feat(uns): Alarms tab + ScriptedAlarmModal on the equipment page 2026-06-11 14:53:03 -04:00
Joseph Doherty 1294fb6ee5 fix(uns): surface stale-row edits + dismiss modal on delete + @key rows (code-review) 2026-06-11 14:49:23 -04:00
Joseph Doherty 61ad5ab8cc feat(uns): wire Tags + Virtual Tags tabs on the equipment page (reuse modals) 2026-06-11 14:44:35 -04:00
Joseph Doherty 7fbfeca451 feat(uns): equipment detail page shell + Details tab + create-redirect 2026-06-11 14:36:48 -04:00
Joseph Doherty d9dbd7917a feat(uns): surface DriverType to the TagModal driver dropdown (F-uns-1 T1) 2026-06-09 09:16:07 -04:00
Joseph Doherty b87d877270 refactor(uns): modal-polish nits on the global UNS page (task #137)
Low-severity review nits, no behaviour change to the happy path:
- CloseModals() now also resets the leftover _*ModalIsNew / parent-id fields
  (area ClusterId, line AreaId, equipment LineId, tag/vtag) for symmetry —
  harmless today (always set before a modal opens) but consistent.
- HandleAddChild / HandleAddVirtualTag / HandleEdit gain a _modalBusy guard
  (try/finally) so a rapid double-action can't race two service loads into the
  same modal state. The switch bodies are re-indented under the try block.
- VirtualTagModal DataType is now an InputSelect over the standard OPC UA type
  list (the same set TagModal uses) instead of free-text InputText.
- RefreshEquipmentChildrenAsync documents that callers own StateHasChanged()
  and the full-reload fallback is spelled out as a block with a comment.

Build clean; AdminUI.Tests 216/216.
2026-06-09 08:18:15 -04:00
Joseph Doherty 14b469291a fix(uns): bind _filter + modal parent-ids as Razor expressions, not literals
v2-ci / build (push) Failing after 40s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped
GlobalUns passed string component params without an @ prefix
(Filter="_filter", ClusterId="_areaModalClusterId", etc.). Razor treats a
string-typed component-parameter value without @ as a LITERAL, so UnsTree.Filter
became the literal "_filter" and the modals received literal field-name strings
as their parent ids. The non-empty literal filter matched no node, so the tree
never rendered children beyond the enterprise roots; the modals would have created
children under a bogus cluster/area/line/equipment id.

Add @ to the six string-param bindings. Verified live in docker-dev: the full
Enterprise->Cluster->Area->Line->Equipment tree renders and an area created via the
modal persists with the correct ClusterId (MAIN). No unit test added — this is a
Razor binding issue not reachable without bUnit (not used in this project).
2026-06-08 15:15:46 -04:00
Joseph Doherty 7db9a24403 feat(uns): equipment CSV import folded into the tree toolbar 2026-06-08 13:56:01 -04:00
Joseph Doherty c0346f14ce feat(uns): tag + virtual-tag modals wired into the tree 2026-06-08 13:47:34 -04:00
Joseph Doherty 2beaa43d60 feat(uns): equipment modal wired into the tree 2026-06-08 13:31:14 -04:00
Joseph Doherty 0abd1d8fc2 fix(uns): delete-confirm reports not-available instead of false success for unwired kinds (review) 2026-06-08 13:25:15 -04:00
Joseph Doherty a4a9dc912a feat(uns): area + line modals wired into the tree 2026-06-08 13:20:25 -04:00
Joseph Doherty 4a32edef1a fix(uns): re-entrancy guard + clear stale error + PageTitle on GlobalUns (review) 2026-06-08 12:39:23 -04:00
Joseph Doherty c9f59e4bd2 feat(uns): GlobalUns page with browsable tree 2026-06-08 12:34:37 -04:00