From 5a23783e074ae200b1daeabdf81f6ed71baaab14 Mon Sep 17 00:00:00 2001 From: kawa Date: Tue, 2 Jun 2026 11:16:01 +0200 Subject: [PATCH] Fix GUI polish issues across auth modal, theme, and 404 - Add missing modal CSS (.modal-overlay/.modal-dialog/.modal-header): the "Connect to Microsoft" auth modal was rendering unstyled inline at the bottom of the page. Now a centered dialog with backdrop. - Surface OAuth connect errors in the modal instead of silently reopening it with no explanation. - MainLayout: implement IDisposable so event handlers are actually unsubscribed (Dispose existed but was never invoked). - Wire up the Settings theme selector (was a dead control): drop the unsupported Dark option, call sptb.setTheme on save and on load, resolve System via prefers-color-scheme. - Add branded 404 page via UseStatusCodePagesWithReExecute + Routes (blank white page before). - Add .progress-fill.indeterminate animation and .progress-panel. - Home: replace inline JS hover handlers with a .feature-card CSS class. - Define missing --surface-2 variable referenced by MainLayout. Co-Authored-By: Claude Opus 4.8 (1M context) --- Components/Layout/MainLayout.razor | 18 +++++++- Components/Pages/Home.razor | 4 +- Components/Pages/NotFound.razor | 10 +++++ Components/Pages/Settings.razor | 8 ++-- Components/Routes.razor | 9 ++++ .../Shared/SessionCredentialsModal.razor | 14 +++---- Program.cs | 3 ++ wwwroot/app.css | 42 +++++++++++++++++++ wwwroot/js/app.js | 7 +++- 9 files changed, 101 insertions(+), 14 deletions(-) create mode 100644 Components/Pages/NotFound.razor diff --git a/Components/Layout/MainLayout.razor b/Components/Layout/MainLayout.razor index add1d0e..14a000d 100644 --- a/Components/Layout/MainLayout.razor +++ b/Components/Layout/MainLayout.razor @@ -1,12 +1,15 @@ @inherits LayoutComponentBase +@implements IDisposable @inject IUserSessionService Session @inject IUserContextAccessor UserContext @inject ISessionCredentialStore CredStore @inject ISessionManager SessionManager @inject NavigationManager Nav +@inject IJSRuntime JS @inject SharepointToolbox.Web.Services.OAuth.IOAuthFlowCache OAuthCache @using Microsoft.AspNetCore.Components.Authorization @using Microsoft.AspNetCore.WebUtilities +@using Microsoft.JSInterop @using SharepointToolbox.Web.Core.Models @using SharepointToolbox.Web.Services.Session @@ -160,6 +163,9 @@ { if (!firstRender) return; + // Apply persisted theme preference + await ApplyThemeAsync(); + // Pick up token_key from OAuth callback redirect before checking credential state await HandleOAuthCallbackAsync(); await RefreshCredentialState(); @@ -172,7 +178,8 @@ Nav.NavigateTo(uri.GetLeftPart(UriPartial.Path), replace: true); if (_credModal is not null) { - await _credModal.ShowAsync(); + // Surface the failure reason instead of silently reopening the modal + await _credModal.ShowAsync(err!); } } @@ -234,6 +241,15 @@ }); } + private async Task ApplyThemeAsync() + { + try + { + await JS.InvokeVoidAsync("sptb.setTheme", Session.Settings.Theme); + } + catch (JSException) { /* best-effort; JS not yet available */ } + } + private void ToggleSidebar() => _sidebarCollapsed = !_sidebarCollapsed; private static string RoleChipClass(UserRole role) => role switch diff --git a/Components/Pages/Home.razor b/Components/Pages/Home.razor index 2af34ac..7d90778 100644 --- a/Components/Pages/Home.razor +++ b/Components/Pages/Home.razor @@ -29,8 +29,8 @@ else
@foreach (var feature in _features) { - -
+ +
@feature.Icon
@feature.Title
@feature.Description
diff --git a/Components/Pages/NotFound.razor b/Components/Pages/NotFound.razor new file mode 100644 index 0000000..0fa25d5 --- /dev/null +++ b/Components/Pages/NotFound.razor @@ -0,0 +1,10 @@ +@page "/not-found" +@attribute [Microsoft.AspNetCore.Authorization.AllowAnonymous] + +Page not found — SharePoint Toolbox + +
diff --git a/Components/Pages/Settings.razor b/Components/Pages/Settings.razor index c68d9c3..26a48b5 100644 --- a/Components/Pages/Settings.razor +++ b/Components/Pages/Settings.razor @@ -1,7 +1,9 @@ @page "/settings" @attribute [Authorize] @inject IUserSessionService Session +@inject IJSRuntime JS @rendermode InteractiveServer +@using Microsoft.JSInterop

Settings

@@ -19,7 +21,6 @@
@@ -44,14 +45,15 @@ { var s = Session.Settings; _lang = s.Lang; - _theme = s.Theme; + _theme = s.Theme is "System" or "Light" ? s.Theme : "System"; _autoTakeOwnership = s.AutoTakeOwnership; } - private void Save() + private async Task Save() { Session.UpdateSettings(new AppSettings { Lang = _lang, Theme = _theme, AutoTakeOwnership = _autoTakeOwnership }); SharepointToolbox.Web.Localization.TranslationSource.Instance.SetCulture(_lang); + await JS.InvokeVoidAsync("sptb.setTheme", _theme); _saved = true; StateHasChanged(); _ = Task.Delay(2000).ContinueWith(_ => { _saved = false; InvokeAsync(StateHasChanged); }); diff --git a/Components/Routes.razor b/Components/Routes.razor index 66cae57..a14545b 100644 --- a/Components/Routes.razor +++ b/Components/Routes.razor @@ -18,5 +18,14 @@ + + +
+

Page not found

+

The page you requested doesn't exist.

+ Back to Home +
+
+
diff --git a/Components/Shared/SessionCredentialsModal.razor b/Components/Shared/SessionCredentialsModal.razor index aa748a3..c878eca 100644 --- a/Components/Shared/SessionCredentialsModal.razor +++ b/Components/Shared/SessionCredentialsModal.razor @@ -7,10 +7,10 @@ @if (_visible) { -