From 0c5b796e2e9cd695adf5f5634e35354d3aab4669 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Wed, 3 Jun 2026 03:49:34 -0400 Subject: [PATCH] feat(dashboard): split MainLayout into ZB.MOM.WW.Theme ThemeShell + kit nav --- .../Components/Layout/MainLayout.razor | 246 +++--------------- .../Components/Layout/NavSection.razor | 35 --- 2 files changed, 38 insertions(+), 243 deletions(-) delete mode 100644 src/ZB.MOM.WW.MxGateway.Server/Dashboard/Components/Layout/NavSection.razor diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Components/Layout/MainLayout.razor b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Components/Layout/MainLayout.razor index 8b093e0..3d365f8 100644 --- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Components/Layout/MainLayout.razor +++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Components/Layout/MainLayout.razor @@ -1,210 +1,40 @@ -@using System.Linq -@using Microsoft.AspNetCore.Components.Routing -@using Microsoft.JSInterop -@implements IDisposable @inherits LayoutComponentBase -@inject NavigationManager Navigation -@inject IJSRuntime JS -
- @* Hamburger toggle: visible only on viewports
- -@code { - // Sections whose collapsed/expanded state we persist. Acts as the allow-list - // when parsing the cookie so stale or attacker-supplied ids are ignored. - private static readonly string[] SectionIds = { "runtime", "galaxy", "admin" }; - - // The currently-expanded sections. Populated from the cookie on first - // render; mutated by ToggleAsync and by navigating into a section. - private readonly HashSet _expanded = new(StringComparer.Ordinal); - - protected override void OnInitialized() - { - Navigation.LocationChanged += OnLocationChanged; - } - - protected override async Task OnAfterRenderAsync(bool firstRender) - { - if (!firstRender) - { - return; - } - - // Hydrate from the cookie. Until this completes the sidebar paints - // collapsed, matching the CentralUI behaviour. - string saved; - try - { - saved = await JS.InvokeAsync("navState.get") ?? string.Empty; - } - catch (JSDisconnectedException) - { - return; - } - - foreach (var id in saved.Split( - ',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)) - { - if (Array.IndexOf(SectionIds, id) >= 0) - { - _expanded.Add(id); - } - } - - // The section of the page we loaded on is always expanded. - if (EnsureCurrentSectionExpanded()) - { - await PersistAsync(); - } - - StateHasChanged(); - } - - private void OnLocationChanged(object? sender, LocationChangedEventArgs e) - { - if (EnsureCurrentSectionExpanded()) - { - _ = PersistAsync(); - _ = InvokeAsync(StateHasChanged); - } - } - - private async Task ToggleAsync(string id) - { - if (!_expanded.Remove(id)) - { - _expanded.Add(id); - } - - await PersistAsync(); - } - - // Adds the current page's section to _expanded; returns true if it changed. - private bool EnsureCurrentSectionExpanded() - { - var section = CurrentSection(); - return section is not null && _expanded.Add(section); - } - - // Maps the current URL's first path segment to a section id, or null for - // sectionless pages (Dashboard, Login). - private string? CurrentSection() - { - var relative = Navigation.ToBaseRelativePath(Navigation.Uri); - var firstSegment = relative.Split('?', '#')[0] - .Split('/', StringSplitOptions.RemoveEmptyEntries) - .FirstOrDefault(); - - return firstSegment switch - { - "sessions" or "workers" or "events" or "alarms" => "runtime", - "galaxy" or "browse" => "galaxy", - "apikeys" or "settings" => "admin", - _ => null, - }; - } - - private async Task PersistAsync() - { - try - { - await JS.InvokeVoidAsync("navState.set", string.Join(',', _expanded)); - } - catch (JSDisconnectedException) - { - // The circuit is gone — nothing to persist to. - } - } - - public void Dispose() - { - Navigation.LocationChanged -= OnLocationChanged; - } -} +@* Thin layout: delegates the side-rail chassis (hamburger, brand, responsive + collapse) to the shared ZB.MOM.WW.Theme . The nav is reproduced + with the kit's NavRailSection / NavRailItem; section expand-state persistence + is owned by the kit's
+ ThemeScripts (no JS interop here). *@ + + + + + + @authState.User.Identity?.Name +
+ + + +
+ + Sign In + +
+
+ @Body +
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Components/Layout/NavSection.razor b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Components/Layout/NavSection.razor deleted file mode 100644 index 2700093..0000000 --- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Components/Layout/NavSection.razor +++ /dev/null @@ -1,35 +0,0 @@ -@* A collapsible sidebar nav section. The header is a full-width button that - toggles ChildContent visibility. Pattern lifted from ScadaLink CentralUI - (Components/Layout/NavSection.razor) — see [[project-deployed-service]]. *@ - - -@if (Expanded) -{ - @ChildContent -} - -@code { - /// Section label shown in the header (e.g. "Runtime"). - [Parameter, EditorRequired] - public string Title { get; set; } = string.Empty; - - /// Whether the section is expanded — its items rendered. - [Parameter] - public bool Expanded { get; set; } - - /// Raised when the header button is clicked. - [Parameter] - public EventCallback OnToggle { get; set; } - - /// The section's nav items, rendered only while expanded. - [Parameter] - public RenderFragment? ChildContent { get; set; } -}