From c9fdcc3ea689c97ebf2644a525e529a0ca9035f3 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Thu, 8 Oct 2026 14:21:20 -0400 Subject: [PATCH 1/2] fix(adminui): clear stale one-time key banner on delete; modal backdrop no longer overruns viewport (#631) Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe --- .../Components/Pages/ApiKeys.razor | 7 +++++++ .../wwwroot/css/site.css | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/ApiKeys.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/ApiKeys.razor index ec88539f..bbf436e8 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/ApiKeys.razor +++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/ApiKeys.razor @@ -142,6 +142,13 @@ try { _keys = await Keys.ListAsync(default); + // The one-time banner is only meaningful while its key exists; the credential is + // otua__, so drop it once no listed key matches (deleted here or elsewhere). + if (_created is not null + && !_keys.Any(k => _created.StartsWith($"otua_{k.ApiKeyId}_", StringComparison.Ordinal))) + { + _created = null; + } } catch (Exception ex) { diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/wwwroot/css/site.css b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/wwwroot/css/site.css index 3e5c1edb..b9c3edd7 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/wwwroot/css/site.css +++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/wwwroot/css/site.css @@ -48,3 +48,22 @@ flex: 0 0 18px; width: 18px; } + +/* Modal sizing (#631). Bootstrap sizes .modal-backdrop with 100vw/100vh, and 100vw includes the + scrollbar gutter, so on a tall form (Configure driver / Modbus) the backdrop overran the viewport + and produced a page-level horizontal scrollbar. Pin it with inset:0 instead (no vw/vh), and keep + the dialog inside the viewport. These modals are hand-rolled (display:block, no Bootstrap JS). */ +.modal-backdrop { + inset: 0; + width: auto; + height: auto; +} + +.modal { + overflow-x: hidden; + overflow-y: auto; +} + +.modal-dialog { + max-width: min(var(--bs-modal-width, 500px), calc(100vw - 2rem)); +} From da203d5d7e04b47ccddda74c0aa9aafd37cc2333 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Thu, 8 Oct 2026 14:22:32 -0400 Subject: [PATCH 2/2] fix(adminui): modal backdrop offset came from .rise's retained transform, not 100vw (#631) Live-measured on docker-dev: the backdrop was viewport-wide (1911px) but started at the panel's left edge (241px) because the theme's .rise animation (fill-mode both) leaves an identity transform on section.panel, re-basing position:fixed descendants. Override the fill mode to backwards; drops the speculative backdrop/dialog sizing overrides. Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe --- .../wwwroot/css/site.css | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/wwwroot/css/site.css b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/wwwroot/css/site.css index b9c3edd7..9da4e982 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/wwwroot/css/site.css +++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/wwwroot/css/site.css @@ -49,21 +49,13 @@ width: 18px; } -/* Modal sizing (#631). Bootstrap sizes .modal-backdrop with 100vw/100vh, and 100vw includes the - scrollbar gutter, so on a tall form (Configure driver / Modbus) the backdrop overran the viewport - and produced a page-level horizontal scrollbar. Pin it with inset:0 instead (no vw/vh), and keep - the dialog inside the viewport. These modals are hand-rolled (display:block, no Bootstrap JS). */ -.modal-backdrop { - inset: 0; - width: auto; - height: auto; -} - -.modal { - overflow-x: hidden; - overflow-y: auto; -} - -.modal-dialog { - max-width: min(var(--bs-modal-width, 500px), calc(100vw - 2rem)); +/* Modal backdrop overran the viewport on /raw (#631). The theme's `.rise` entrance animation runs with + `animation-fill-mode: both`, which keeps its final keyframe's transform applied for good — and ANY + transform (even the identity it leaves) makes that section the containing block for position:fixed + descendants. A modal rendered inside a `.panel.rise` therefore had its fixed backdrop offset by the + panel's left edge, so it ran 240px past the viewport and the page grew a horizontal scrollbar. + `backwards` keeps the hidden start state during the stagger delay but drops the transform once the + animation ends. (Upstream fix belongs in ZB.MOM.WW.Theme's theme.css.) */ +.rise { + animation-fill-mode: backwards; }