docs(plan): AdminUI density sweep — §1d scan findings + 3-task execution plan
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
# AdminUI density/layout sweep (§1d follow-through) — 2026-08-10
|
||||
|
||||
Follow-through of the `/hosts` density rework: the §1d scan (four parallel read-only agents,
|
||||
62 files) applied to the rest of the AdminUI. Playbook: `../scadaproj/admin_ui_cleanup.md`
|
||||
§1d + §2 "Density fixes". Prior context: `2026-08-10-adminui-ui-sweeps.md` (structure sweep)
|
||||
and the `/hosts` rework commit `34d60c41`.
|
||||
|
||||
## Scan verdict
|
||||
|
||||
- **Zero unguarded `[..N]` slices** anywhere (all existing slices are length-guarded or Guid-fixed).
|
||||
- Cluster pages: no A/B/D defects at all; 3 C items.
|
||||
- The dominant class is **C — unbounded backend/free text** (~17 sites), concentrated on the
|
||||
fault-triage surfaces (`/alerts`, `/fleet`, `/script-log`, alarms-historian, DriverStatusPanel).
|
||||
- Two structural defects: `Scripts.razor` (inline `<details>` source dump + identity slam — the
|
||||
/hosts shape) and `EquipmentPage.razor` (only authoring page with no panel idiom + bare RawPath
|
||||
column).
|
||||
- Deliberate designs kept: `RawManualTagEntryModal` colspan config sub-row (documented, inside
|
||||
`modal-xl` — a fix means stacked modals), `VirtualTagModal` inline Monaco card (collapsed by
|
||||
default, own card boundary).
|
||||
- Style-only residual (not §1d, not in this sweep): `Deployments.razor` is off the panel idiom
|
||||
(bare `<h1>` + Bootstrap table).
|
||||
|
||||
## Task 1 — mechanical truncation sweep (Abbreviate + title)
|
||||
|
||||
All `DisplayText.Abbreviate(value, N)` + full text on `title`; behavior byte-for-byte.
|
||||
|
||||
| File:line | Value | N |
|
||||
|---|---|---|
|
||||
| `Pages/Alerts.razor:84` | alarm `Message` | 80 |
|
||||
| `Pages/Fleet.razor:92` | `FailureReason` | 80 |
|
||||
| `Pages/ScriptLog.razor:71` | log `Message` (mono) | 120 |
|
||||
| `Pages/AlarmsHistorian.razor:41` | drain `LastError` | 80 |
|
||||
| `Shared/Drivers/DriverStatusPanel.razor` | op-result chip — truncate in `ShowOpResult` choke point, `title` on chip; also `:41` SignalR `_error` | 60 |
|
||||
| `Pages/Certificates.razor:77-78` | Subject / Issuer DNs | 48 |
|
||||
| `Pages/RoleGrants.razor:65,96,24` | LDAP group DNs, SearchBase | 48 |
|
||||
| `Pages/Clusters/ClusterAcls.razor:88` | ACL `Notes` | 60 |
|
||||
| `Pages/Clusters/ClusterOverview.razor:49,100,102` | cluster `Notes` (120), `Host` (30), `ApplicationUri` (40) | — |
|
||||
| `Pages/Clusters/ClusterRedundancy.razor:128` | `ApplicationUri` | 40 |
|
||||
| `Pages/Account.razor:63` | group-DN chips | 40 |
|
||||
| `Pages/Clusters/ClusterAudit.razor:55-57` | add `title` to the already-ellipsized DetailsJson cell | — |
|
||||
| `Shared/Drivers/Pickers/SqlAddressPickerBody.razor:208-211` | composed TagConfig JSON `<code>` | 64 |
|
||||
| `Shared/Drivers/Pickers/SqlAddressPickerBody.razor:159-162` | `_openError` → adopt the sibling truncated-chip + `title` pattern | 60 |
|
||||
| `Shared/Drivers/DriverTagPicker.razor:19-22` | footer `CurrentAddress` | 60 |
|
||||
| Picker Result `<code>` lines (AbCip:75, TwinCAT:64, OpcUaClient:57, Galaxy:95, FOCAS:109) | browsed address | 64 |
|
||||
|
||||
## Task 2 — Scripts page: `<details>` expander → source dialog + two-line identity
|
||||
|
||||
`Pages/Scripts.razor`: replace the per-row inline `<details>`/`<pre>` source dump with the
|
||||
Bootstrap modal pattern (`modal-backdrop fade show` + `modal fade show d-block`, `modal-lg`,
|
||||
one at a time); list rows get the stacked identity (name first line, mono id + hash beneath,
|
||||
chips with the name). Hold only the open row's `ScriptId`; re-resolve from current data every
|
||||
render (self-closes if the script vanishes).
|
||||
|
||||
## Task 3 — EquipmentPage: adopt the panel idiom + bound the RawPath column
|
||||
|
||||
`Pages/Uns/EquipmentPage.razor`: wrap each tab body in `<section class="panel">` +
|
||||
`panel-head` (Details tab: Identity and OPC 40010 as two panels, dropping the `<hr>`),
|
||||
matching ScriptEdit's shells; `Abbreviate(r.RawPath, 48)` + `title` at :166. Behavior
|
||||
byte-for-byte — tab switching, all bindings, buttons, modals unchanged.
|
||||
|
||||
## Verification
|
||||
|
||||
Merged-tree full build + AdminUI.Tests; live gate on docker-dev (both centrals rebuilt) with
|
||||
at least one faulted/erroring row on screen (§1d realistic-data rule): /alerts, /fleet,
|
||||
/scripts dialog open/close, equipment page tabs, Sql picker footer.
|
||||
Reference in New Issue
Block a user