From e6c0acc14a77a853de9a194e0fbd0a2ab2c83964 Mon Sep 17 00:00:00 2001 From: Abhishekrajpurohit Date: Tue, 16 Jun 2026 23:26:50 +0530 Subject: [PATCH 1/3] fix(dashboard): use 'openwa' as upstream host to match dev compose service name --- dashboard/nginx.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dashboard/nginx.conf b/dashboard/nginx.conf index 5f30d18b..09058120 100644 --- a/dashboard/nginx.conf +++ b/dashboard/nginx.conf @@ -15,7 +15,7 @@ server { # Proxy API requests to backend location /api/ { - proxy_pass http://openwa-api:2785; + proxy_pass http://openwa:2785; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; @@ -25,7 +25,7 @@ server { # WebSocket proxy location /socket.io/ { - proxy_pass http://openwa-api:2785; + proxy_pass http://openwa:2785; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; From c531560913a8104c7f28598ef899dacf639b5e17 Mon Sep 17 00:00:00 2001 From: Abhishekrajpurohit Date: Tue, 16 Jun 2026 23:26:54 +0530 Subject: [PATCH 2/3] fix(dashboard): mount local nginx.conf in dev compose to avoid rebuilding --- docker-compose.dev.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 5b4bc186..3ef07c94 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -72,6 +72,8 @@ services: container_name: openwa-dashboard ports: - '${BIND_HOST:-127.0.0.1}:2886:80' + volumes: + - ./dashboard/nginx.conf:/etc/nginx/conf.d/default.conf:ro depends_on: openwa: condition: service_healthy From a6403c0cc7544896b94049e09c8be53c7d53b50c Mon Sep 17 00:00:00 2001 From: Abhishekrajpurohit Date: Thu, 18 Jun 2026 11:25:42 +0530 Subject: [PATCH 3/3] fix(dashboard): stop QR polling for connected sessions; correct nginx upstream name --- dashboard/nginx.conf | 4 ++-- dashboard/src/pages/Sessions.tsx | 28 +++++++++++++++++++--------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/dashboard/nginx.conf b/dashboard/nginx.conf index 09058120..5f30d18b 100644 --- a/dashboard/nginx.conf +++ b/dashboard/nginx.conf @@ -15,7 +15,7 @@ server { # Proxy API requests to backend location /api/ { - proxy_pass http://openwa:2785; + proxy_pass http://openwa-api:2785; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; @@ -25,7 +25,7 @@ server { # WebSocket proxy location /socket.io/ { - proxy_pass http://openwa:2785; + proxy_pass http://openwa-api:2785; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; diff --git a/dashboard/src/pages/Sessions.tsx b/dashboard/src/pages/Sessions.tsx index 18cf4198..122e74c9 100644 --- a/dashboard/src/pages/Sessions.tsx +++ b/dashboard/src/pages/Sessions.tsx @@ -26,13 +26,15 @@ export function Sessions() { const [selectedSession, setSelectedSession] = useState(null); const [deleteConfirmId, setDeleteConfirmId] = useState(null); - const fetchSessions = useCallback(async () => { + const fetchSessions = useCallback(async (): Promise => { try { setLoading(true); const data = await sessionApi.list(); setSessions(data); + return data; } catch (err) { setError(err instanceof Error ? err.message : t('sessions.create.errorDefault')); + return []; } finally { setLoading(false); } @@ -75,6 +77,13 @@ export function Sessions() { const currentSessionName = useRef(''); const fetchQR = useCallback(async (sessionId: string) => { + // Guard: if session is already connected, stop polling immediately. + const currentSession = sessions.find(s => s.id === sessionId); + if (currentSession?.status === 'ready') { + setQrData(null); + currentSessionName.current = ''; + return; + } try { const qr = await sessionApi.getQR(sessionId); setQrData({ sessionId, sessionName: currentSessionName.current, qrCode: qr.qrCode }); @@ -86,16 +95,16 @@ export function Sessions() { } catch { // Keep qrData alive so the polling interval keeps retrying until the QR // is ready. Only stop polling if the session itself has failed. - const currentSession = await sessionApi.get(sessionId).catch(() => null); - const stillInitializing = currentSession && - ['initializing', 'connecting', 'qr_ready'].includes(currentSession.status); + const updated = await sessionApi.get(sessionId).catch(() => null); + const stillInitializing = updated && + ['initializing', 'connecting', 'qr_ready'].includes(updated.status); if (!stillInitializing) { setQrData(null); currentSessionName.current = ''; fetchSessions(); } } - }, []); + }, [sessions]); useEffect(() => { if (qrData) { @@ -159,15 +168,16 @@ export function Sessions() { handleShowQR(id); } catch (err) { console.error('Failed to start:', err); - await fetchSessions(); - if (err instanceof Error && err.message.includes('already started')) { - handleShowQR(id); - } + const fresh = await fetchSessions(); + const current = fresh.find(s => s.id === id); + if (current?.status !== 'ready') handleShowQR(id); } }; const handleShowQR = async (id: string) => { const session = sessions.find(s => s.id === id); + // Nothing to show for an already-connected session. + if (session?.status === 'ready') return; const sessionName = session?.name || ''; // Show loading state immediately so the modal opens and polling starts // even before Chromium has finished initializing.