Files
lmxopcua/docs/plans/2026-08-10-adminui-ui-sweeps.md
T

48 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AdminUI UI Sweeps Implementation Plan
**Goal:** Apply the ignitionoee router's UI-sweep taxonomy (2026-08-05, `~/Desktop/ignitionoee/docs/plans/2026-08-05-router-ui-sweeps.md`) to the OtOpcUa AdminUI: button grouping/sizing, row-action normalization, instructional-prose removal (including five actively-wrong/stale claims), and the two AdminUI-specific foundation defects the discovery sweep found. Tree tables were evaluated and **rejected** — see Discovery below.
**Architecture:** One foundation task (site.css + App.razor + doc relocations) plus five per-batch passes over disjoint file sets, all parallelizable (foundation classes are referenced by name only — CSS class names are not compile-checked, so batches build independently and compose at merge). Orchestrator merges `--no-ff` (foundation first), runs the full build + AdminUI.Tests on the merged tree, then live-verifies on the docker-dev rig (`http://localhost:9200`, login disabled) — mandatory because the AdminUI has no bUnit and this change is almost entirely markup.
**Tech stack:** .NET 10 Blazor Server, Bootstrap 5.3.3 self-hosted, ZB.MOM.WW.Theme 0.3.1 (light-only), xUnit (AdminUI.Tests baseline ~1,499 — no markup coverage).
---
## Discovery evidence (2026-08-10, four parallel read-only sweeps)
- **The router's ghost-layout-class defect does NOT exist here** — all 111 razor files use only classes that Theme 0.3.1/Bootstrap/site.css actually ship. But two same-class defects do:
1. **The scoped-CSS bundle is never linked.** `ContextMenu.razor.css` builds and serves (`_content/ZB.MOM.WW.OtOpcUa.AdminUI/ZB.MOM.WW.OtOpcUa.AdminUI.bundle.scp.css` returns 200 on the rig) but `App.razor` links only bootstrap → ThemeHead → site.css, so all 8 `.ctx-*` rules no-op: context menus render in-flow (no `position:fixed`), the backdrop has no viewport coverage.
2. **Phantom tokens:** `var(--alert)` ×13 (defined nowhere; the theme's red is `--bad`) — intended red error tints silently stay amber; `var(--surface-2)` (Scripts.razor:47) likewise dead. `var(--surface-raised,#fff)` (DriverStatusPanel:174) carries a fallback — harmless.
- **Button sizing:** no `.btn` rule anywhere; 187 raw Bootstrap buttons (zero TechButton, zero `btn-group` in the whole app — the idiom is `d-flex gap-2`); 121 carry `btn-sm`, 66 are full-size 1rem against the 0.9rem body (mostly modal feet + `DriverFormShell`). No adjacent same-group size mismatches — the convention is consistent, just unsized at the foundation.
- **Prose:** 17 DELETE items (5 carrying stale/wrong claims: `Authentication:Ldap` should be `Security:Ldap` on Account + RoleGrants; ClusterRedundancy describes pre-Phase-6 redundancy and dead-links `/docs/v2/Architecture-v2.md`; ScriptLog says "F8/F9 pending" for shipped features; Certificates/ClusterAudit carry F-milestone labels), 2 RELOCATE items (driver-health per-instance-not-per-member keying → `docs/Telemetry.md`; audit EventId/CorrelationId dedup → `docs/Configuration.md` — its only current home is the historical `docs/v2/AdminUI-rebuild-plan.md:93`), and stale "arriving in v3 Batch 2/3" phrasing on the two namespace placeholder pages.
- **Tree tables: REJECTED.** All 23 data tables are flat entity lists, time-ordered logs (a tree destroys ordering), or already grouped per parent (Hosts driver instances, Certificates per-store). Hierarchical data lives in four purpose-built lazy nav/picker trees (RawTree, AclScopeTree, UnsTree, DriverBrowseTree) that the flat-list TreeTable model cannot serve (lazy loading, no columns). Porting the router's TreeTable would create an orphan. The four trees' duplicated expander scaffolding is nav-tree duplication — left alone per AclScopeTree's documented no-bUnit separate-components decision.
## Execution rules
- Six Opus subagents in isolated worktrees, one per task below; disjoint files; each builds the AdminUI project + runs `tests/Server/ZB.MOM.WW.OtOpcUa.AdminUI.Tests` green before committing on its own branch.
- Orchestrator merges (foundation first), full-solution build, AdminUI.Tests on the merged tree (the parallel-worktrees-compose-only-at-full-build rule), then docker-dev live verification (rebuild BOTH central images — `:9200` round-robins).
- Confirm-step (arm → confirm) flows are restyle-only — behavior must be untouched: Certificates pending-action, ClusterRedundancy failover, DriverStatusPanel restart, RawBrowseModal rebirth, RawCsvImportModal all-or-nothing commit, GlobalUns delete modal.
- Genuine navigation stays links (ClusterOverview:75,104, ClusterAcls:134, Scripts:45, UnsTree ⚙/Open); DriverBrowseTree labels stay buttons (blazor.web.js interceptor comment).
## Task F — foundation
Files: `Components/App.razor`, `wwwroot/css/site.css`, `docs/Telemetry.md`, `docs/Configuration.md`, `Components/Shared/ContextMenu.razor.css` (comment only).
1. Link the scoped bundle in App.razor after site.css.
2. site.css: the router's `--bs-btn-*` sizing block (`.btn` .85rem/.35rem/.8rem, `.btn-sm` .78rem/.25rem/.6rem — variable overrides only, never box properties; header-comment as ZB.MOM.WW.Theme upstreaming candidates); `.notice-alert` (red tint from the theme's `--bad*` tokens, mirroring `.chip-alert`); `.tree-twist { flex: 0 0 18px; width: 18px; }` for the four trees' repeated inline `width:18px`.
3. Relocate the two orphaned facts into `docs/Telemetry.md` (driver-health channel) and `docs/Configuration.md` (audit-log subsection) — must land before the page copies are deleted (Tasks 1–2).
4. Fix ContextMenu.razor.css's aspirational "light and dark" comment (theme is light-only).
## Tasks 1–5 — per-batch passes (disjoint files, parallel)
Each applies to its files: (a) `btn-group` wrapping of adjacent related buttons (modal/form feet, confirm pairs, toolbar pairs, row-action runs ≥2); (b) action-styled `btn-link` → `btn btn-sm btn-outline-secondary` (destructive → `btn-outline-danger`); (c) its prose DELETE/stale-fix items; (d) inline `var(--alert)` tints → `.notice-alert`; (e) tree files adopt `.tree-twist`.
- **Task 1 — Clusters pages:** ClusterOverview, ClusterEdit, NodeEdit, NewCluster, AclEdit, ClusterAcls, ClusterRedundancy, ClustersList, ClusterAudit, ClusterNamespaces, NamespaceEdit. Includes the AclEdit `·`-separated preset run → grouped small buttons; the ClusterAcls/AclEdit duplicated ~35-line ACL mode walkthrough deletion (keep the `unresolved`-chip decoder at ClusterAcls:66-71); the stale redundancy block + dead link; namespace placeholders → past tense.
- **Task 2 — Top-level ops pages:** Alerts, ScriptLog, Hosts, Fleet, Deployments, Certificates, ApiKeys, RoleGrants, Scripts, ScriptEdit, Account, Reservations, AlarmsHistorian. Includes the Alerts ack/shelve cell (two `btn-group-sm`s split by the minutes input); RoleGrants Delete link → outline-danger; the `Security:Ldap` key corrections; the Hosts/ClusterAudit deletions whose facts Task F relocated; ScriptLog F8/F9 + Certificates F13a stale fixes; Scripts:47 `--surface-2` → a shipped token.
- **Task 3 — UNS:** GlobalUns, EquipmentPage, UnsTree, AreaModal, LineModal, VirtualTagModal, AddReferenceModal, ImportEquipmentModal, ScriptedAlarmModal (+ TagEditors noted no-op). UnsTree per-node action links → compact grouped buttons (Deletes danger; ⚙/Open stay links); GlobalUns Expand/Collapse pair; six modal feet; EquipmentPage row-action pairs.
- **Task 4 — Shared/Raw:** RawBrowseModal, RawCsvImportModal, RawCsvExportModal, RawManualTagEntryModal, RawTagModal, RawNameDialog, RawDriverTypeDialog, RawConfirmDialog, RawStubModal, RawTree. Seven modal feet + the mixed button/anchor export foot; browse-toolbar and rebirth-confirm pairs; drop the `py-0` hack; RawTree adopts `.tree-twist`.
- **Task 5 — Shared/Drivers + Acls:** DriverFormShell (the 13-form lever), CollectionEditor (foot + row actions), DriverConfigModal, DeviceModal, DriverTagPicker, DriverStatusPanel, AclScopePickerModal, AclScopeTree, DriverBrowseTree, six address-picker browse toolbars (Galaxy/FOCAS/AbCip/TwinCAT/OpcUaClient/Sql), MqttDriverForm/MTConnectDriverForm/MqttDeviceForm (tint swaps). MonacoEditor btn-link toolbar left as-is.
## Task 6 — integration (orchestrator)
Merge F then 1–5 `--no-ff`; full build zero errors; AdminUI.Tests green; review the merged diff for KEEP-prose accidentally deleted / broken handlers / groups around non-adjacent elements; docker-dev live pass (context menu now positioned, red notice tint, button sizing, grouped feet, confirm flows still two-step); memory update. No push without an explicit request.