Skip to content

Commit 4a1d97f

Browse files
committed
feat(filters): add auto-refresh functionality to user filters and improve loading state handling
1 parent 90cdf38 commit 4a1d97f

File tree

2 files changed

+30
-8
lines changed

2 files changed

+30
-8
lines changed

dashboard/src/components/users/filters.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,47 +77,49 @@ interface FiltersProps {
7777
}
7878
onFilterChange: (filters: Partial<FiltersProps['filters']>) => void
7979
refetch?: (options?: RefetchOptions) => Promise<unknown>
80+
autoRefetch?: (options?: RefetchOptions) => Promise<unknown>
8081
advanceSearchOnOpen: (status: boolean) => void
8182
onClearAdvanceSearch?: () => void
8283
handleSort?: (column: string, fromDropdown?: boolean) => void
8384
}
8485

85-
export const Filters = ({ filters, onFilterChange, refetch, advanceSearchOnOpen, onClearAdvanceSearch, handleSort }: FiltersProps) => {
86+
export const Filters = ({ filters, onFilterChange, refetch, autoRefetch, advanceSearchOnOpen, onClearAdvanceSearch, handleSort }: FiltersProps) => {
8687
const { t } = useTranslation()
8788
const dir = useDirDetection()
8889
const [search, setSearch] = useState(filters.search || '')
8990
const [isRefreshing, setIsRefreshing] = useState(false)
9091
const [autoRefreshInterval, setAutoRefreshInterval] = useState<number>(() => getUsersAutoRefreshIntervalSeconds())
9192
const { refetch: queryRefetch } = useGetUsers(filters)
92-
const refetchUsers = useCallback(async (showLoading = false) => {
93+
const refetchUsers = useCallback(async (showLoading = false, isAutoRefresh = false) => {
9394
if (showLoading) {
9495
setIsRefreshing(true)
9596
}
9697
try {
97-
const refetchFn = refetch ?? queryRefetch
98+
// Use autoRefetch for auto refresh, otherwise use manual refetch
99+
const refetchFn = isAutoRefresh ? (autoRefetch ?? queryRefetch) : (refetch ?? queryRefetch)
98100
await refetchFn()
99101
} finally {
100102
if (showLoading) {
101103
setIsRefreshing(false)
102104
}
103105
}
104-
}, [refetch, queryRefetch])
106+
}, [refetch, autoRefetch, queryRefetch])
105107
useEffect(() => {
106108
const persistedValue = getUsersAutoRefreshIntervalSeconds()
107109
setAutoRefreshInterval(prev => (prev === persistedValue ? prev : persistedValue))
108110
}, [])
109111
useEffect(() => {
110112
if (!autoRefreshInterval) return
111113
const intervalId = setInterval(() => {
112-
refetchUsers(true) // Show loading spinner on auto refresh
114+
refetchUsers(true, true) // Show loading spinner on auto refresh, mark as auto refresh
113115
}, autoRefreshInterval * 1000)
114116
return () => clearInterval(intervalId)
115117
}, [autoRefreshInterval, refetchUsers])
116118
useEffect(() => {
117119
if (typeof document === 'undefined') return
118120
const handleVisibilityChange = () => {
119121
if (document.visibilityState === 'visible' && autoRefreshInterval > 0) {
120-
refetchUsers(true) // Show loading spinner on visibility change refresh
122+
refetchUsers(true, true) // Show loading spinner on visibility change refresh, mark as auto refresh
121123
}
122124
}
123125
document.addEventListener('visibilitychange', handleVisibilityChange)
@@ -174,7 +176,7 @@ export const Filters = ({ filters, onFilterChange, refetch, advanceSearchOnOpen,
174176

175177
// Handle refresh with loading state
176178
const handleRefreshClick = async () => {
177-
await refetchUsers(true) // Show loading spinner on manual refresh
179+
await refetchUsers(true, false) // Show loading spinner on manual refresh, mark as manual refresh
178180
}
179181

180182
const handleAutoRefreshChange = (seconds: number) => {

dashboard/src/components/users/users-table.tsx

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ const UsersTable = memo(() => {
2626
const [isAdvanceSearchOpen, setIsAdvanceSearchOpen] = useState(false)
2727
const [isSorting, setIsSorting] = useState(false)
2828
const isFirstLoadRef = useRef(true)
29+
const isAutoRefreshingRef = useRef(false)
2930
const { admin } = useAdmin()
3031
const isSudo = admin?.is_sudo || false
3132

@@ -152,6 +153,13 @@ const UsersTable = memo(() => {
152153
}
153154
}, [usersData])
154155

156+
// Reset auto refresh flag when fetching completes
157+
useEffect(() => {
158+
if (!isFetching && isAutoRefreshingRef.current) {
159+
isAutoRefreshingRef.current = false
160+
}
161+
}, [isFetching])
162+
155163
// Remove automatic refetch on filter change to prevent lag
156164
// Filters will trigger new queries automatically
157165

@@ -257,12 +265,23 @@ const UsersTable = memo(() => {
257265
}, [])
258266

259267
const handleManualRefresh = async () => {
268+
// Mark as manual refresh (not auto refresh)
269+
isAutoRefreshingRef.current = false
260270
// Invalidate queries to ensure fresh data
261271
queryClient.invalidateQueries({ queryKey: ['getUsers'] })
262272
// Then refetch
263273
return refetch()
264274
}
265275

276+
const handleAutoRefresh = async () => {
277+
// Mark as auto refresh
278+
isAutoRefreshingRef.current = true
279+
// Invalidate queries to ensure fresh data
280+
queryClient.invalidateQueries({ queryKey: ['getUsers'] })
281+
// Then refetch - flag will be reset by useEffect when isFetching becomes false
282+
return refetch()
283+
}
284+
266285
const handlePageChange = (newPage: number) => {
267286
if (newPage === currentPage || isChangingPage) return
268287

@@ -331,6 +350,7 @@ const UsersTable = memo(() => {
331350
onFilterChange={handleFilterChange}
332351
advanceSearchOnOpen={setIsAdvanceSearchOpen}
333352
refetch={handleManualRefresh}
353+
autoRefetch={handleAutoRefresh}
334354
handleSort={handleSort}
335355
onClearAdvanceSearch={() => {
336356
advanceSearchForm.reset({
@@ -350,7 +370,7 @@ const UsersTable = memo(() => {
350370
setCurrentPage(0)
351371
}}
352372
/>
353-
<DataTable columns={columns} data={usersData?.users || []} isLoading={showLoadingSpinner} isFetching={isFetching && !isFirstLoadRef.current} onEdit={handleEdit} />
373+
<DataTable columns={columns} data={usersData?.users || []} isLoading={showLoadingSpinner} isFetching={isFetching && !isFirstLoadRef.current && !isAutoRefreshingRef.current} onEdit={handleEdit} />
354374
<PaginationControls
355375
currentPage={currentPage}
356376
totalPages={totalPages}

0 commit comments

Comments
 (0)