From 8b17b82b78569ecb7b2da9df4902fa69a7d77cf3 Mon Sep 17 00:00:00 2001 From: Oliver Kieselbach Date: Tue, 24 Feb 2026 21:34:56 +0100 Subject: [PATCH] route diagnostics SAS expiry warnings to notification bell Instead of inline banners on the settings page, expired or near-expiry SAS URLs now fire a persistent warning/error notification to the bell icon. The notification includes a direct "View" link to /settings#diagnostics. NotificationContext: added optional href field to Notification; addNotification signature extended with href parameter for both keyed and unkeyed paths. Navbar: notifications with href render a "View" link that marks the notification as read and navigates to the target anchor. Settings: removed inline SAS warning banners; addNotification called on config load when expiry <= 7 days (warning) or expired (error); diagnostics section gets id="diagnostics" anchor for deep-linking. Co-Authored-By: Claude Sonnet 4.6 --- .../app/settings/page.tsx | 46 ++++++++----------- .../components/Navbar.tsx | 13 +++++- .../contexts/NotificationContext.tsx | 8 +++- 3 files changed, 36 insertions(+), 31 deletions(-) diff --git a/src/Web/autopilot-monitor-web/app/settings/page.tsx b/src/Web/autopilot-monitor-web/app/settings/page.tsx index f636ea54..2b7cada9 100644 --- a/src/Web/autopilot-monitor-web/app/settings/page.tsx +++ b/src/Web/autopilot-monitor-web/app/settings/page.tsx @@ -5,6 +5,7 @@ import { useRouter } from "next/navigation"; import { ProtectedRoute } from "../../components/ProtectedRoute"; import { useTenant } from "../../contexts/TenantContext"; import { useAuth } from "../../contexts/AuthContext"; +import { useNotifications } from "../../contexts/NotificationContext"; import { API_BASE_URL } from "@/lib/config"; interface TenantConfiguration { @@ -65,6 +66,7 @@ export default function SettingsPage() { const router = useRouter(); const { tenantId } = useTenant(); const { getAccessToken, user, logout } = useAuth(); + const { addNotification } = useNotifications(); const [config, setConfig] = useState(null); const [admins, setAdmins] = useState([]); const [loading, setLoading] = useState(true); @@ -115,7 +117,6 @@ export default function SettingsPage() { const [diagnosticsBlobSasUrl, setDiagnosticsBlobSasUrl] = useState(""); const [diagnosticsUploadMode, setDiagnosticsUploadMode] = useState("Off"); const [diagnosticsSasExpiry, setDiagnosticsSasExpiry] = useState(null); - const [diagnosticsSasWarning, setDiagnosticsSasWarning] = useState(null); // Fetch configuration useEffect(() => { @@ -167,7 +168,7 @@ export default function SettingsPage() { setDiagnosticsBlobSasUrl(sasUrl); setDiagnosticsUploadMode(data.diagnosticsUploadMode ?? "Off"); - // Parse SAS expiry and set warning/error notifications + // Parse SAS expiry and fire notification to bell if needed if (sasUrl) { const expiry = parseSasExpiry(sasUrl); setDiagnosticsSasExpiry(expiry); @@ -175,11 +176,21 @@ export default function SettingsPage() { const now = new Date(); const daysRemaining = Math.ceil((expiry.getTime() - now.getTime()) / (1000 * 60 * 60 * 24)); if (daysRemaining <= 0) { - setDiagnosticsSasWarning("error"); + addNotification( + 'error', + 'Diagnostics SAS URL Expired', + `The Diagnostics SAS URL expired on ${expiry.toLocaleDateString()}. Diagnostics upload is non-functional.`, + 'diagnostics-sas-expiry', + '/settings#diagnostics' + ); } else if (daysRemaining <= 7) { - setDiagnosticsSasWarning("warning"); - } else { - setDiagnosticsSasWarning(null); + addNotification( + 'warning', + 'Diagnostics SAS URL Expiring Soon', + `The Diagnostics SAS URL expires on ${expiry.toLocaleDateString()} (${daysRemaining} day${daysRemaining === 1 ? '' : 's'} remaining). Please update it soon.`, + 'diagnostics-sas-expiry', + '/settings#diagnostics' + ); } } } @@ -656,27 +667,6 @@ export default function SettingsPage() { )} - {/* Diagnostics SAS URL expiry notifications */} - {diagnosticsSasWarning === "error" && ( -
- - - - - Diagnostics SAS URL has expired. Diagnostics upload is non-functional. Please update the SAS URL in the Diagnostics Package section. - -
- )} - {diagnosticsSasWarning === "warning" && diagnosticsSasExpiry && ( -
- - - - - Diagnostics SAS URL expires on {diagnosticsSasExpiry.toLocaleDateString()} — please update it soon to avoid interruption. - -
- )} {/* Autopilot Device Validation */}
@@ -1277,7 +1267,7 @@ export default function SettingsPage() {
{/* Diagnostics Package */} -
+
diff --git a/src/Web/autopilot-monitor-web/components/Navbar.tsx b/src/Web/autopilot-monitor-web/components/Navbar.tsx index c0bac3a7..137852d9 100644 --- a/src/Web/autopilot-monitor-web/components/Navbar.tsx +++ b/src/Web/autopilot-monitor-web/components/Navbar.tsx @@ -261,7 +261,18 @@ export default function Navbar() {

{notification.title}

{notification.message}

-

{formatTime(notification.timestamp)}

+
+

{formatTime(notification.timestamp)}

+ {notification.href && ( + { e.stopPropagation(); markAsRead(notification.id); }} + className="text-[10px] text-blue-600 hover:text-blue-800 font-medium underline" + > + View + + )} +