48 lines
8.4 KiB
Markdown
48 lines
8.4 KiB
Markdown
# 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.
|