From a4e51b49c8fc6260bf0281444febb91fce5afa4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20G=C3=B6pel?= Date: Wed, 8 Jul 2026 19:57:16 +0800 Subject: [PATCH] feat: apply AndreGoepel.Design.Blazor design system (infra + shell) Adopt the extracted design system in the management frontend. - Add the AndreGoepel.Design.Blazor 1.0.0 package and bump AndreGoepel.Marten.Identity.Blazor 1.2.0 -> 1.3.0 (which now carries the design). - Host App.razor loads the design fonts, design.css (after Radzen material-base), and the theme + off-canvas nav scripts. - Replace the RadzenLayout-based MainLayout with the design AppShell (brand, NavMenu sidebar slot, ThemeToggle + profile menu in the topbar, copyright footer). - Flatten NavMenu from RadzenPanelMenu to ag-nav-section / ag-nav-item. - Fix references for the 1.3.0 move of the feature-flag types and the feature-gate extension into the ...Blazor.Features namespace. --- Directory.Packages.props | 3 +- .../Components/App.razor | 7 ++ .../Initialization.cs | 1 + .../packages.lock.json | 31 ++++-- .../AndreGoepel.AppFoundation.csproj | 1 + .../Components/Layout/MainLayout.razor | 95 ++++++------------- .../Components/Layout/NavMenu.razor | 80 ++++++++-------- .../Components/_Imports.razor | 2 + ...ntityFeatureServiceCollectionExtensions.cs | 2 +- .../Identity/MartenIdentityFeatureProvider.cs | 2 +- .../packages.lock.json | 28 ++++-- .../packages.lock.json | 33 ++++--- 12 files changed, 148 insertions(+), 137 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index f551386..7618b7d 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -19,7 +19,8 @@ - + + diff --git a/samples/AndreGoepel.AppFoundation.Sample/Components/App.razor b/samples/AndreGoepel.AppFoundation.Sample/Components/App.razor index 10a3fb2..e5d9fbb 100644 --- a/samples/AndreGoepel.AppFoundation.Sample/Components/App.razor +++ b/samples/AndreGoepel.AppFoundation.Sample/Components/App.razor @@ -5,9 +5,16 @@ + + + + + + + diff --git a/src/AndreGoepel.AppFoundation.Hosting/Initialization.cs b/src/AndreGoepel.AppFoundation.Hosting/Initialization.cs index 478a480..d95fb0f 100644 --- a/src/AndreGoepel.AppFoundation.Hosting/Initialization.cs +++ b/src/AndreGoepel.AppFoundation.Hosting/Initialization.cs @@ -4,6 +4,7 @@ using AndreGoepel.AppFoundation.MailService; using AndreGoepel.Marten.Identity; using AndreGoepel.Marten.Identity.Blazor; +using AndreGoepel.Marten.Identity.Blazor.Features; using AndreGoepel.Marten.Identity.Users; using JasperFx; using Marten; diff --git a/src/AndreGoepel.AppFoundation.Hosting/packages.lock.json b/src/AndreGoepel.AppFoundation.Hosting/packages.lock.json index ca28592..ee9c161 100644 --- a/src/AndreGoepel.AppFoundation.Hosting/packages.lock.json +++ b/src/AndreGoepel.AppFoundation.Hosting/packages.lock.json @@ -4,11 +4,12 @@ "net10.0": { "AndreGoepel.Marten.Identity.Blazor": { "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "9333mUhD6RIWdimln+ex5suLnY51DcafY+LHU4jVmfKngTKi5J0WTgNBau5+3lPi5+3PjUjnLaHq6pUPFUn48Q==", + "requested": "[1.3.0, )", + "resolved": "1.3.0", + "contentHash": "eULYGyNNGITdasW3nOmaAcUnOjl8fy0rrhEFYTxsUU+F6bJtfLNjGsMDLhFIpc+uS8DRGfhbSGjd7VHOJs9i4w==", "dependencies": { - "AndreGoepel.Marten.Identity": "1.2.0", + "AndreGoepel.Design.Blazor": "1.0.0", + "AndreGoepel.Marten.Identity": "1.3.0", "Marten": "9.12.0", "Radzen.Blazor": "11.1.0" } @@ -59,10 +60,10 @@ }, "AndreGoepel.Marten.Identity": { "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "zfvSm4io9gcCjQCFyWThZlbSOwfGoH+Idbp2l/gReR3OcyoUf4VPHiECdBmWGkxIS8mczBiaiI3blL0nuKChQQ==", + "resolved": "1.3.0", + "contentHash": "F/QEiI0rJ7CGXoMDKvmJW9/IU8UB3LaMb4peL2DZzsmtadXmLrqjI1E/ZoVxt5QhiW7gFRBa1cDBiDk551aA8w==", "dependencies": { - "AndreGoepel.Marten.Identity.Abstractions": "1.2.0", + "AndreGoepel.Marten.Identity.Abstractions": "1.3.0", "Marten": "9.12.0", "Marten.AspNetCore": "9.12.0", "Quartz.Extensions.Hosting": "3.18.2" @@ -70,8 +71,8 @@ }, "AndreGoepel.Marten.Identity.Abstractions": { "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "CYj9qrcXogO6kciAF7rQfuiERBdXm8T7e4DY4pc5qSEufWyhUAC7DqJksedigQ4NBpsdoT1AXE9KBxWTMnHPkA==" + "resolved": "1.3.0", + "contentHash": "/mYBlD9bHJae05zDL4xBpddmL2OpHpdVsJSm9rUTAEG2wS+4EGgcRYkq1/yOC98TcO9CABNua9J69HT6XII5hg==" }, "BouncyCastle.Cryptography": { "type": "Transitive", @@ -546,7 +547,8 @@ "type": "Project", "dependencies": { "AndreGoepel.AppFoundation.MailService": "[1.1.0, )", - "AndreGoepel.Marten.Identity.Blazor": "[1.2.0, )", + "AndreGoepel.Design.Blazor": "[1.0.0, )", + "AndreGoepel.Marten.Identity.Blazor": "[1.3.0, )", "Marten": "[9.12.0, )", "Radzen.Blazor": "[11.1.0, )", "WolverineFx.Marten": "[6.16.0, )" @@ -572,6 +574,15 @@ "OpenTelemetry.Instrumentation.Runtime": "[1.15.1, )" } }, + "AndreGoepel.Design.Blazor": { + "type": "CentralTransitive", + "requested": "[1.0.0, )", + "resolved": "1.0.0", + "contentHash": "2Sz0LwsyzW0T2RLqdPPza6l/RfVvHkdUt1rKEiQoJQGXmdng+Lw8ehvtQ99M6zMWuT46HQlusbIB5LOK1cyXcQ==", + "dependencies": { + "Radzen.Blazor": "11.1.0" + } + }, "MailKit": { "type": "CentralTransitive", "requested": "[4.17.0, )", diff --git a/src/AndreGoepel.AppFoundation/AndreGoepel.AppFoundation.csproj b/src/AndreGoepel.AppFoundation/AndreGoepel.AppFoundation.csproj index d367f0b..d555a51 100644 --- a/src/AndreGoepel.AppFoundation/AndreGoepel.AppFoundation.csproj +++ b/src/AndreGoepel.AppFoundation/AndreGoepel.AppFoundation.csproj @@ -30,6 +30,7 @@ + diff --git a/src/AndreGoepel.AppFoundation/Components/Layout/MainLayout.razor b/src/AndreGoepel.AppFoundation/Components/Layout/MainLayout.razor index 814c6a6..c07a21c 100644 --- a/src/AndreGoepel.AppFoundation/Components/Layout/MainLayout.razor +++ b/src/AndreGoepel.AppFoundation/Components/Layout/MainLayout.razor @@ -7,75 +7,45 @@ @inject NavigationManager NavigationManager @inject Microsoft.Extensions.Options.IOptions LayoutOptions +@* Radzen overlay hosts (dialog/notification/tooltip/context-menu) for interactive pages. *@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + @if (!string.IsNullOrWhiteSpace(Layout.Copyright)) { - - - + @Layout.Copyright } - - - - - @Body - - + - + + @Body + +
An unhandled error has occurred. @@ -84,7 +54,6 @@
@code { - private bool sidebarExpanded = true; private string? currentUserName; private AppFoundationLayoutOptions Layout => LayoutOptions.Value; @@ -95,8 +64,6 @@ currentUserName = authState.User.Identity?.Name; } - void SidebarToggleClick() => sidebarExpanded = !sidebarExpanded; - void OnProfileMenuClick(RadzenProfileMenuItem item) { if (item.Text == "Logout") diff --git a/src/AndreGoepel.AppFoundation/Components/Layout/NavMenu.razor b/src/AndreGoepel.AppFoundation/Components/Layout/NavMenu.razor index 14d978e..9943e5f 100644 --- a/src/AndreGoepel.AppFoundation/Components/Layout/NavMenu.razor +++ b/src/AndreGoepel.AppFoundation/Components/Layout/NavMenu.razor @@ -2,7 +2,7 @@ @using AndreGoepel.Marten.Identity @using AndreGoepel.Marten.Identity.Blazor -@using Radzen.Blazor +@using AndreGoepel.Marten.Identity.Blazor.Features @using global::Marten @inject IQuerySession QuerySession @@ -12,51 +12,51 @@ @if (SetupComplete) { - - + ⌂  Home - @if (Layout.Menu is not null) - { - - } + @* Host-contributed entries. Contributed menus should render ag-nav-item / + ag-nav-section markup to match the design shell. *@ + @if (Layout.Menu is not null) + { + + } - - - - - - - @if (twoFactorEnabled) - { - - } - @if (passkeyEnabled) - { - - } - - - - + + +
ACCOUNT
+
+ Profile + Email + Password + @if (twoFactorEnabled) + { + Two-factor authentication + } + @if (passkeyEnabled) + { + Passkeys + } + Personal data +
+
+
- - - - - - - - - - - -
+ + +
ADMINISTRATION
+
+ User cleanup + Users + Roles + Login features + Email settings +
+
+
} else { - - - + Setup } @code { diff --git a/src/AndreGoepel.AppFoundation/Components/_Imports.razor b/src/AndreGoepel.AppFoundation/Components/_Imports.razor index 816f3bd..77c6ef5 100644 --- a/src/AndreGoepel.AppFoundation/Components/_Imports.razor +++ b/src/AndreGoepel.AppFoundation/Components/_Imports.razor @@ -15,6 +15,8 @@ @using AndreGoepel.Marten.Identity.Blazor.Components.Account @using AndreGoepel.Marten.Identity.Blazor.Components.Account.Shared @using AndreGoepel.Marten.Identity.Blazor.Components.Layout +@using AndreGoepel.Design.Blazor +@using AndreGoepel.Design.Blazor.Components @using AndreGoepel.AppFoundation @using AndreGoepel.AppFoundation.Components @using AndreGoepel.AppFoundation.Components.Layout diff --git a/src/AndreGoepel.AppFoundation/Identity/IdentityFeatureServiceCollectionExtensions.cs b/src/AndreGoepel.AppFoundation/Identity/IdentityFeatureServiceCollectionExtensions.cs index 095db47..3f1ce15 100644 --- a/src/AndreGoepel.AppFoundation/Identity/IdentityFeatureServiceCollectionExtensions.cs +++ b/src/AndreGoepel.AppFoundation/Identity/IdentityFeatureServiceCollectionExtensions.cs @@ -1,5 +1,5 @@ using AndreGoepel.AppFoundation.Identity; -using AndreGoepel.Marten.Identity.Blazor; +using AndreGoepel.Marten.Identity.Blazor.Features; namespace Microsoft.Extensions.DependencyInjection; diff --git a/src/AndreGoepel.AppFoundation/Identity/MartenIdentityFeatureProvider.cs b/src/AndreGoepel.AppFoundation/Identity/MartenIdentityFeatureProvider.cs index af7f888..71a7e3e 100644 --- a/src/AndreGoepel.AppFoundation/Identity/MartenIdentityFeatureProvider.cs +++ b/src/AndreGoepel.AppFoundation/Identity/MartenIdentityFeatureProvider.cs @@ -1,4 +1,4 @@ -using AndreGoepel.Marten.Identity.Blazor; +using AndreGoepel.Marten.Identity.Blazor.Features; namespace AndreGoepel.AppFoundation.Identity; diff --git a/src/AndreGoepel.AppFoundation/packages.lock.json b/src/AndreGoepel.AppFoundation/packages.lock.json index c05fcc6..4c2f0c2 100644 --- a/src/AndreGoepel.AppFoundation/packages.lock.json +++ b/src/AndreGoepel.AppFoundation/packages.lock.json @@ -2,13 +2,23 @@ "version": 2, "dependencies": { "net10.0": { + "AndreGoepel.Design.Blazor": { + "type": "Direct", + "requested": "[1.0.0, )", + "resolved": "1.0.0", + "contentHash": "2Sz0LwsyzW0T2RLqdPPza6l/RfVvHkdUt1rKEiQoJQGXmdng+Lw8ehvtQ99M6zMWuT46HQlusbIB5LOK1cyXcQ==", + "dependencies": { + "Radzen.Blazor": "11.1.0" + } + }, "AndreGoepel.Marten.Identity.Blazor": { "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "9333mUhD6RIWdimln+ex5suLnY51DcafY+LHU4jVmfKngTKi5J0WTgNBau5+3lPi5+3PjUjnLaHq6pUPFUn48Q==", + "requested": "[1.3.0, )", + "resolved": "1.3.0", + "contentHash": "eULYGyNNGITdasW3nOmaAcUnOjl8fy0rrhEFYTxsUU+F6bJtfLNjGsMDLhFIpc+uS8DRGfhbSGjd7VHOJs9i4w==", "dependencies": { - "AndreGoepel.Marten.Identity": "1.2.0", + "AndreGoepel.Design.Blazor": "1.0.0", + "AndreGoepel.Marten.Identity": "1.3.0", "Marten": "9.12.0", "Radzen.Blazor": "11.1.0" } @@ -43,10 +53,10 @@ }, "AndreGoepel.Marten.Identity": { "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "zfvSm4io9gcCjQCFyWThZlbSOwfGoH+Idbp2l/gReR3OcyoUf4VPHiECdBmWGkxIS8mczBiaiI3blL0nuKChQQ==", + "resolved": "1.3.0", + "contentHash": "F/QEiI0rJ7CGXoMDKvmJW9/IU8UB3LaMb4peL2DZzsmtadXmLrqjI1E/ZoVxt5QhiW7gFRBa1cDBiDk551aA8w==", "dependencies": { - "AndreGoepel.Marten.Identity.Abstractions": "1.2.0", + "AndreGoepel.Marten.Identity.Abstractions": "1.3.0", "Marten": "9.12.0", "Marten.AspNetCore": "9.12.0", "Quartz.Extensions.Hosting": "3.18.2" @@ -54,8 +64,8 @@ }, "AndreGoepel.Marten.Identity.Abstractions": { "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "CYj9qrcXogO6kciAF7rQfuiERBdXm8T7e4DY4pc5qSEufWyhUAC7DqJksedigQ4NBpsdoT1AXE9KBxWTMnHPkA==" + "resolved": "1.3.0", + "contentHash": "/mYBlD9bHJae05zDL4xBpddmL2OpHpdVsJSm9rUTAEG2wS+4EGgcRYkq1/yOC98TcO9CABNua9J69HT6XII5hg==" }, "BouncyCastle.Cryptography": { "type": "Transitive", diff --git a/tests/AndreGoepel.AppFoundation.Tests/packages.lock.json b/tests/AndreGoepel.AppFoundation.Tests/packages.lock.json index c2166cd..157a4c0 100644 --- a/tests/AndreGoepel.AppFoundation.Tests/packages.lock.json +++ b/tests/AndreGoepel.AppFoundation.Tests/packages.lock.json @@ -4,11 +4,12 @@ "net10.0": { "AndreGoepel.Marten.Identity.Blazor": { "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "9333mUhD6RIWdimln+ex5suLnY51DcafY+LHU4jVmfKngTKi5J0WTgNBau5+3lPi5+3PjUjnLaHq6pUPFUn48Q==", + "requested": "[1.3.0, )", + "resolved": "1.3.0", + "contentHash": "eULYGyNNGITdasW3nOmaAcUnOjl8fy0rrhEFYTxsUU+F6bJtfLNjGsMDLhFIpc+uS8DRGfhbSGjd7VHOJs9i4w==", "dependencies": { - "AndreGoepel.Marten.Identity": "1.2.0", + "AndreGoepel.Design.Blazor": "1.0.0", + "AndreGoepel.Marten.Identity": "1.3.0", "Marten": "9.12.0", "Radzen.Blazor": "11.1.0" } @@ -68,10 +69,10 @@ }, "AndreGoepel.Marten.Identity": { "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "zfvSm4io9gcCjQCFyWThZlbSOwfGoH+Idbp2l/gReR3OcyoUf4VPHiECdBmWGkxIS8mczBiaiI3blL0nuKChQQ==", + "resolved": "1.3.0", + "contentHash": "F/QEiI0rJ7CGXoMDKvmJW9/IU8UB3LaMb4peL2DZzsmtadXmLrqjI1E/ZoVxt5QhiW7gFRBa1cDBiDk551aA8w==", "dependencies": { - "AndreGoepel.Marten.Identity.Abstractions": "1.2.0", + "AndreGoepel.Marten.Identity.Abstractions": "1.3.0", "Marten": "9.12.0", "Marten.AspNetCore": "9.12.0", "Quartz.Extensions.Hosting": "3.18.2" @@ -79,8 +80,8 @@ }, "AndreGoepel.Marten.Identity.Abstractions": { "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "CYj9qrcXogO6kciAF7rQfuiERBdXm8T7e4DY4pc5qSEufWyhUAC7DqJksedigQ4NBpsdoT1AXE9KBxWTMnHPkA==" + "resolved": "1.3.0", + "contentHash": "/mYBlD9bHJae05zDL4xBpddmL2OpHpdVsJSm9rUTAEG2wS+4EGgcRYkq1/yOC98TcO9CABNua9J69HT6XII5hg==" }, "AngleSharp": { "type": "Transitive", @@ -731,7 +732,8 @@ "type": "Project", "dependencies": { "AndreGoepel.AppFoundation.MailService": "[1.1.0, )", - "AndreGoepel.Marten.Identity.Blazor": "[1.2.0, )", + "AndreGoepel.Design.Blazor": "[1.0.0, )", + "AndreGoepel.Marten.Identity.Blazor": "[1.3.0, )", "Marten": "[9.12.0, )", "Radzen.Blazor": "[11.1.0, )", "WolverineFx.Marten": "[6.16.0, )" @@ -743,7 +745,7 @@ "AndreGoepel.AppFoundation": "[1.1.0, )", "AndreGoepel.AppFoundation.MailService": "[1.1.0, )", "AndreGoepel.AppFoundation.ServiceDefaults": "[1.1.0, )", - "AndreGoepel.Marten.Identity.Blazor": "[1.2.0, )", + "AndreGoepel.Marten.Identity.Blazor": "[1.3.0, )", "Marten": "[9.12.0, )", "Microsoft.AspNetCore.HeaderPropagation": "[10.0.9, )", "Radzen.Blazor": "[11.1.0, )", @@ -771,6 +773,15 @@ "OpenTelemetry.Instrumentation.Runtime": "[1.15.1, )" } }, + "AndreGoepel.Design.Blazor": { + "type": "CentralTransitive", + "requested": "[1.0.0, )", + "resolved": "1.0.0", + "contentHash": "2Sz0LwsyzW0T2RLqdPPza6l/RfVvHkdUt1rKEiQoJQGXmdng+Lw8ehvtQ99M6zMWuT46HQlusbIB5LOK1cyXcQ==", + "dependencies": { + "Radzen.Blazor": "11.1.0" + } + }, "MailKit": { "type": "CentralTransitive", "requested": "[4.17.0, )",