From 7636a00e24c7b1dfd3a65086e486aeaffd2cf483 Mon Sep 17 00:00:00 2001 From: Oliver Kieselbach Date: Thu, 6 Aug 2026 14:39:51 +0200 Subject: [PATCH] =?UTF-8?q?web:=20fix=20lint=20regression=20from=20Load-al?= =?UTF-8?q?l=20=E2=80=94=20lift=20sweep=20state=20into=20useDashboardSessi?= =?UTF-8?q?ons?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Load-all button reconstructed 'sweep running' locally via a set-state-in-effect on loadingMore, adding a 116th react-hooks warning over the 115 cap. The hook already knows loadMore vs loadAll apart, so expose loadingAll from useDashboardSessions and drop the local state and effect entirely. Co-Authored-By: Claude Fable 5 --- .../app/dashboard/components/SessionTable.tsx | 11 +++-------- .../app/dashboard/hooks/useDashboardSessions.ts | 7 +++++++ src/Web/autopilot-monitor-web/app/dashboard/page.tsx | 3 ++- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Web/autopilot-monitor-web/app/dashboard/components/SessionTable.tsx b/src/Web/autopilot-monitor-web/app/dashboard/components/SessionTable.tsx index be3ad235..eff9df82 100644 --- a/src/Web/autopilot-monitor-web/app/dashboard/components/SessionTable.tsx +++ b/src/Web/autopilot-monitor-web/app/dashboard/components/SessionTable.tsx @@ -77,6 +77,7 @@ interface SessionTableProps { onSessionsPerPageChange: (value: number) => void; hasMore: boolean; loadingMore: boolean; + loadingAll: boolean; onLoadAll: () => void; adminMode: boolean; globalAdminMode: boolean; @@ -127,6 +128,7 @@ export function SessionTable({ onSessionsPerPageChange, hasMore, loadingMore, + loadingAll, onLoadAll, adminMode, globalAdminMode, @@ -158,12 +160,6 @@ export function SessionTable({ const searchDropdownRef = useRef(null); const [showSearchSuggestions, setShowSearchSuggestions] = useState(false); const [searchSelectedIndex, setSearchSelectedIndex] = useState(-1); - // Distinguishes a running "Load all" sweep from a single Next-click batch — - // both surface as loadingMore, but only the sweep should relabel the button. - const [loadAllActive, setLoadAllActive] = useState(false); - useEffect(() => { - if (!loadingMore) setLoadAllActive(false); - }, [loadingMore]); // Fuzzy-match sessions by multiple fields for search dropdown (two-phase: exact then Levenshtein) interface SearchSuggestion { @@ -741,14 +737,13 @@ export function SessionTable({ )} diff --git a/src/Web/autopilot-monitor-web/app/dashboard/hooks/useDashboardSessions.ts b/src/Web/autopilot-monitor-web/app/dashboard/hooks/useDashboardSessions.ts index 6ec35369..735660ec 100644 --- a/src/Web/autopilot-monitor-web/app/dashboard/hooks/useDashboardSessions.ts +++ b/src/Web/autopilot-monitor-web/app/dashboard/hooks/useDashboardSessions.ts @@ -68,6 +68,7 @@ export interface UseDashboardSessionsReturn { loading: boolean; hasMore: boolean; loadingMore: boolean; + loadingAll: boolean; refetch: () => void; refetchWith: (tenantIdOverride: string) => void; loadMore: () => void; @@ -102,6 +103,9 @@ export function useDashboardSessions({ const [loading, setLoading] = useState(true); const [hasMore, setHasMore] = useState(false); const [loadingMore, setLoadingMore] = useState(false); + // True only while the progressive loadAll() sweep runs — loadMore() sets just + // loadingMore. Lets the UI label a full sweep differently from a single batch. + const [loadingAll, setLoadingAll] = useState(false); const [continuation, setContinuation] = useState(null); // Refs for SignalR handlers to access current filter state without restarting subscriptions @@ -343,6 +347,7 @@ export function useDashboardSessions({ fetchLockRef.current = true; const myToken = ++loadAllTokenRef.current; setLoadingMore(true); + setLoadingAll(true); try { let currentContinuation: string | null = continuationRef.current; while (currentContinuation && loadAllTokenRef.current === myToken) { @@ -357,6 +362,7 @@ export function useDashboardSessions({ } finally { fetchLockRef.current = false; setLoadingMore(false); + setLoadingAll(false); } }, [fetchSessionsBatch, continuationRef]); @@ -523,6 +529,7 @@ export function useDashboardSessions({ loading, hasMore, loadingMore, + loadingAll, refetch, refetchWith, loadMore, diff --git a/src/Web/autopilot-monitor-web/app/dashboard/page.tsx b/src/Web/autopilot-monitor-web/app/dashboard/page.tsx index 34739ab5..a22c88a4 100644 --- a/src/Web/autopilot-monitor-web/app/dashboard/page.tsx +++ b/src/Web/autopilot-monitor-web/app/dashboard/page.tsx @@ -128,7 +128,7 @@ function HomeContent() { } = useBlockDevice(getAccessToken, addNotification, adminMode, crossTenant); const { - sessions, loading, hasMore, loadingMore, + sessions, loading, hasMore, loadingMore, loadingAll, refetch, refetchWith, loadMore, loadAll, removeSession, } = useDashboardSessions({ user, tenantId, globalAdminMode: crossTenant, joinGlobalAdmins, tenantIdFilter, adminMode, @@ -478,6 +478,7 @@ function HomeContent() { onSessionsPerPageChange={handleSessionsPerPageChange} hasMore={hasMore} loadingMore={loadingMore} + loadingAll={loadingAll} onLoadAll={loadAll} adminMode={adminMode} globalAdminMode={crossTenant}