From 28eb30cb9a496b874fea58846e1a1c62c8faaeb7 Mon Sep 17 00:00:00 2001 From: rcourtman Date: Thu, 22 Jan 2026 00:42:56 +0000 Subject: [PATCH] fix(ui): refresh alert config on WebSocket reconnection Fixes issue where alert toggle appears disabled after connection loss. - Add websocket_reconnected event to event bus - Emit event when WebSocket successfully reconnects - App subscribes and refreshes alert activation state on reconnection --- frontend-modern/src/App.tsx | 13 ++++++++++++- frontend-modern/src/stores/events.ts | 4 +++- frontend-modern/src/stores/websocket.ts | 9 +++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/frontend-modern/src/App.tsx b/frontend-modern/src/App.tsx index 992f241d0..8870bd2c5 100644 --- a/frontend-modern/src/App.tsx +++ b/frontend-modern/src/App.tsx @@ -486,15 +486,26 @@ function App() { } }; - // Subscribe to theme change events + // Handle WebSocket reconnection - refresh alert config to restore activation state + // This fixes issue where alert toggle appears disabled after connection loss + const handleWebSocketReconnected = () => { + logger.info('WebSocket reconnected, refreshing alert configuration'); + void alertsActivation.refreshConfig(); + void alertsActivation.refreshActiveAlerts(); + }; + + // Subscribe to events eventBus.on('theme_changed', handleThemeChange); + eventBus.on('websocket_reconnected', handleWebSocketReconnected); // Cleanup on unmount onCleanup(() => { eventBus.off('theme_changed', handleThemeChange); + eventBus.off('websocket_reconnected', handleWebSocketReconnected); }); }); + // Check auth on mount onMount(async () => { logger.debug('[App] Starting auth check...'); diff --git a/frontend-modern/src/stores/events.ts b/frontend-modern/src/stores/events.ts index 63f019d99..44ffb098d 100644 --- a/frontend-modern/src/stores/events.ts +++ b/frontend-modern/src/stores/events.ts @@ -6,7 +6,8 @@ export type EventType = | 'refresh_nodes' | 'discovery_updated' | 'discovery_status' - | 'theme_changed'; + | 'theme_changed' + | 'websocket_reconnected'; // Event data types export interface NodeAutoRegisteredData { @@ -51,6 +52,7 @@ export type EventDataMap = { discovery_updated: DiscoveryUpdatedData; discovery_status: DiscoveryStatusData; theme_changed: string; // 'light' or 'dark' + websocket_reconnected: void; // Emitted when WebSocket successfully reconnects }; // Generic event handler diff --git a/frontend-modern/src/stores/websocket.ts b/frontend-modern/src/stores/websocket.ts index efbb51251..3505e08e8 100644 --- a/frontend-modern/src/stores/websocket.ts +++ b/frontend-modern/src/stores/websocket.ts @@ -308,6 +308,7 @@ export function createWebSocketStore(url: string) { ws.onopen = () => { logger.debug('connect'); + const wasReconnecting = reconnectAttempt > 0; setConnected(true); setReconnecting(false); // Clear reconnecting state reconnectAttempt = 0; // Reset reconnect attempts on successful connection @@ -329,9 +330,17 @@ export function createWebSocketStore(url: string) { } }, heartbeatIntervalMs); + // Emit reconnection event so App can refresh alert config + // This ensures the alert activation state is re-fetched after connection loss + if (wasReconnecting) { + logger.info('WebSocket reconnected, emitting event for config refresh'); + eventBus.emit('websocket_reconnected'); + } + // Alerts will come with the initial state broadcast }; + ws.onmessage = (event) => { let data; try {