From 37c10ae0a6ab56594eca2af0ba2cf87b80f70d39 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Fri, 3 Apr 2026 11:01:29 +0200 Subject: [PATCH] feat: manual refresh on sidebar navigation when LIVE mode is off When autoRefresh is disabled, sidebar clicks now invalidate all queries (queryClient.invalidateQueries()), triggering a re-fetch. This gives users "click to refresh" behavior instead of stale data. When LIVE mode is on, queries already poll at intervals, so no invalidation is needed. Co-Authored-By: Claude Opus 4.6 (1M context) --- ui/src/components/LayoutShell.tsx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/ui/src/components/LayoutShell.tsx b/ui/src/components/LayoutShell.tsx index c583917b..cfb2bdbd 100644 --- a/ui/src/components/LayoutShell.tsx +++ b/ui/src/components/LayoutShell.tsx @@ -16,6 +16,7 @@ import { } from '@cameleer/design-system'; import type { SearchResult, SidebarTreeNode } from '@cameleer/design-system'; import { Box, Settings, FileText, ChevronRight, Square, Pause, Star, X } from 'lucide-react'; +import { useQueryClient } from '@tanstack/react-query'; import { useRouteCatalog } from '../api/queries/catalog'; import { useAgents } from '../api/queries/agents'; import { useSearchExecutions, useAttributeKeys } from '../api/queries/executions'; @@ -270,7 +271,8 @@ const SK_COLLAPSED = 'sidebar:collapsed'; function LayoutContent() { const navigate = useNavigate(); const location = useLocation(); - const { timeRange } = useGlobalFilters(); + const queryClient = useQueryClient(); + const { timeRange, autoRefresh } = useGlobalFilters(); const { data: catalog } = useRouteCatalog(timeRange.start.toISOString(), timeRange.end.toISOString()); const { data: agents } = useAgents(); const { data: attributeKeys } = useAttributeKeys(); @@ -329,12 +331,13 @@ function LayoutContent() { } if (appsOpen) { // Already open — navigate to all applications + if (!autoRefresh) queryClient.invalidateQueries(); navigate(`/${scope.tab}`); } else { setAppsOpen(true); writeCollapsed(SK_APPS, true); } - }, [isAdminPage, appsOpen, navigate, scope.tab]); + }, [isAdminPage, appsOpen, navigate, scope.tab, autoRefresh, queryClient]); const toggleAdmin = useCallback(() => { if (!isAdminPage) { @@ -557,6 +560,11 @@ function LayoutContent() { const handleSidebarNavigate = useCallback((path: string) => { const state = { sidebarReveal: path }; + // When not auto-refreshing, treat navigation as a manual refresh + if (!autoRefresh) { + queryClient.invalidateQueries(); + } + const appMatch = path.match(/^\/apps\/([^/]+)(?:\/(.+))?$/); if (appMatch) { const [, sAppId, sRouteId] = appMatch; @@ -572,7 +580,7 @@ function LayoutContent() { } navigate(path, { state }); - }, [navigate, scope.tab]); + }, [navigate, scope.tab, autoRefresh, queryClient]); // --- Render ------------------------------------------------------- const camelLogo = (