diff --git a/docs/plans/2026-06-18-m10-uiux-platform.md b/docs/plans/2026-06-18-m10-uiux-platform.md index 0ca117ac..d79d8fee 100644 --- a/docs/plans/2026-06-18-m10-uiux-platform.md +++ b/docs/plans/2026-06-18-m10-uiux-platform.md @@ -459,15 +459,15 @@ Markup: two `` with `id="@(IdPrefix)-from"`/`-to`, ## Deferred / out of scope (log as FOLLOWUPs at INT) - Unified offset+keyset pagination framework (blocked by total-count mismatch). - `Deployments.razor` PagerWindow → OffsetPager (different windowed UX; intentionally left). -- Complex `TemplateEdit` page-embedded modals → host migration. -- TreeView arrow-key navigation (R7). +- ~~Complex `TemplateEdit` page-embedded modals → host migration.~~ **DONE 2026-08-01.** +- ~~TreeView arrow-key navigation (R7).~~ **DONE 2026-08-01.** - Theme-package side-rail dark theming, IF the spike verdict is "rail stays light" (coordination follow-up). ## Follow-ups logged at delivery (INT findings) - **#207 — FIXED (2026-08-01 bookkeeping sync).** ~~(pre-existing, open since M6/K14):~~ `QueryStringDrillInTests` now registers the `IKpiHistoryQueryService` substitute in its fixture (lines ~165-167), so the 3 `SiteCallsReport` drill-in tests are green. - **#163 (pre-existing):** `InstanceConfigureListOverrideTests` codec roundtrip red; pre-dates M10. -- **NotificationReport `OffsetPager` always-visible:** pager is now always visible when results exist (previously hidden on sub-page-size sets); buttons are correctly disabled on a single page — product decision whether to re-add an `@if (_totalCount > _pageSize)` guard. +- **NotificationReport `OffsetPager` always-visible — DECIDED + DONE (2026-08-01).** A pager whose only controls are permanently disabled is noise, so the conventional behaviour ships: the bar is hidden on a provably single page. Implemented **reusably but opt-in** — `OffsetPager.HideWhenSinglePage` (default `false`, so no consumer changes behaviour implicitly), set `true` at the `NotificationReport` call site. It is NOT defaulted on because the pager's summary span doubles as the "N total" result-count readout on `ConfigurationAuditLog`, which has no other place to show it (and whose Playwright fixture asserts `3 total` on a 3-row single page). The guard only fires when single-page-ness is *positively* established (`PageCount <= 1` **and** `Page <= 1` **and** `!HasNextPage`), so a null `TotalCount` still renders the bar. - **`Deployments.razor` PagerWindow intentionally kept:** windowed numbered-button UX is deliberate; NOT migrated to `OffsetPager`. -- **`TemplateEdit` inline modals NOT migrated:** the page-embedded modals (wave-3 T34c already tokenized their backdrops); full migration to the host is deferred. -- **TreeView full arrow-key navigation (R7) still deferred.** -- **Full-app `bg-light`/`bg-white` → theme-aware utility sweep deferred:** only the bounded modal-surface offenders were addressed in T34c; INT dark-mode smoke may surface additional instances. +- **`TemplateEdit` inline modals — MIGRATED (2026-08-01).** All four page-embedded modals (Attribute, Alarm, Native Alarm Source, Script) now open through `IDialogService.ShowAsync`, so the host owns the backdrop, focus trap, Escape and focus restoration. Each body was extracted to its own component next to the page — `TemplateAttributeDialog`, `TemplateAlarmDialog`, `TemplateNativeAlarmSourceDialog`, `TemplateScriptDialog` — following the `MoveDataConnectionDialog` pattern: the body owns the form state and renders validation/server errors INLINE while staying open, closing with `Close(true)` only on a successful save. Persistence stayed on the page (it owns `TemplateService` and the inherited-member rules) and is reached through an `OnSaveAsync` delegate returning `null` on success or the message to display. The script dialog keeps all four tab panels mounted (Monaco/JSONJoy must not tear down on tab switch) and hosts the Test Run panel, which needs the live unsaved buffer. Extraction moved markup that three structural source-scanning tests pinned (`TemplateNativeAlarmSourceEditorTests`, `AttributeListEditorTests`, `TestRunWarningTests`) — all three were repointed at the new files. +- **~~TreeView full arrow-key navigation (R7) still deferred.~~ DONE 2026-08-01** — the WAI-ARIA tree pattern (roving tabindex, Arrow/Home/End movement, Enter/Space activation, `aria-level`) now ships on `TreeView`; see `docs/components/TreeView.md`. +- **Full-app `bg-light`/`bg-white` → theme-aware utility sweep — DONE 2026-08-01.** 35 class swaps across 19 Central UI files: surfaces/`
`/`` `bg-light` → `bg-body-secondary`, panel `bg-white` → `bg-body`, neutral `badge bg-light text-dark` → `badge bg-secondary-subtle text-secondary-emphasis`, `bg-light text-muted border` → `bg-body-secondary text-body-secondary border`. **Deliberately left** (7 sites): the neutral member of a *status-badge* switch/ternary whose siblings are all solid non-theme-aware colours (`bg-success`/`bg-danger`/`bg-warning`), where swapping only the neutral one breaks the set's visual weight — `Topology.razor:513,588`, `InstanceConfigure.razor:1520`, `NotificationReport.razor` `StatusBadgeClass` fallback, `TransportImport.razor` ConflictKind fallback, `SecuredWrites.razor` `text-bg-light` fallback, `Health.razor:377`. `SchemaBuilder.razor:88` was already `bg-light-subtle` (theme-aware). `bg-dark text-light` console panels and `site.css`/`#reconnect-modal` are intentional fixed colours.
diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditEventDetail.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditEventDetail.razor
index 437ccc4a..dafa5285 100644
--- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditEventDetail.razor
+++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditEventDetail.razor
@@ -67,7 +67,7 @@
         }
         @if (!string.IsNullOrEmpty(Event.ErrorDetail))
         {
-            
@Event.ErrorDetail
+
@Event.ErrorDetail
} } @@ -119,7 +119,7 @@ {
Extra
-
@PrettyPrintJson(Event.Extra!)
+
@PrettyPrintJson(Event.Extra!)
} diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Dialogs/NodeBrowserDialog.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Dialogs/NodeBrowserDialog.razor index 8c59e376..de0fc5b5 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Dialogs/NodeBrowserDialog.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Dialogs/NodeBrowserDialog.razor @@ -56,7 +56,7 @@ @match.Path @if (!string.IsNullOrEmpty(node.DataType)) { - @node.DataType + @node.DataType } } diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Dialogs/TreeRow.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Dialogs/TreeRow.razor index 4d862a6c..1fb006a2 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Dialogs/TreeRow.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Dialogs/TreeRow.razor @@ -21,7 +21,7 @@ @if (!string.IsNullOrEmpty(Node.DataType)) { - @Node.DataType + @Node.DataType } } else diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Forms/OpcUaEndpointEditor.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Forms/OpcUaEndpointEditor.razor index 8cedaacd..b63ed1b0 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Forms/OpcUaEndpointEditor.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Forms/OpcUaEndpointEditor.razor @@ -79,7 +79,7 @@ @if (result.FailureKind == VerifyFailureKind.UntrustedCertificate && result.Cert is { } cert) { -
+
Untrusted server certificate
Subject
diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/ConfigurationAuditLog.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/ConfigurationAuditLog.razor index 59017d60..72cf86d8 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/ConfigurationAuditLog.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/ConfigurationAuditLog.razor @@ -155,7 +155,7 @@ { -
@FormatJson(entry.AfterStateJson!)
+
@FormatJson(entry.AfterStateJson!)
} @@ -179,7 +179,7 @@
@@ -325,7 +325,7 @@
@preview
- Timeout @m.TimeoutSeconds s + Timeout @m.TimeoutSeconds s diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/SharedScriptForm.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/SharedScriptForm.razor index 6ae24e39..9f9ffacf 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/SharedScriptForm.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/SharedScriptForm.razor @@ -141,9 +141,9 @@ {
-
@_runResult.ReturnValueJson
+
@_runResult.ReturnValueJson
} else diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/SharedScripts.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/SharedScripts.razor index 21064e8d..88aab9be 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/SharedScripts.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/SharedScripts.razor @@ -87,8 +87,8 @@ title="@s.Code">@preview
- @paramCount params - + @paramCount params + @(returnLabel == "void" ? "void" : $"returns {returnLabel}")
diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Monitoring/ParkedMessages.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Monitoring/ParkedMessages.razor index 22b0cc8d..11332d3a 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Monitoring/ParkedMessages.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Monitoring/ParkedMessages.razor @@ -295,7 +295,7 @@
Error
-
@_drawerMessage.ErrorMessage
+
@_drawerMessage.ErrorMessage