feat(logs): integrate useLocalStorage for auto-refresh and filter states

This commit is contained in:
Supra4E8C
2026-04-29 23:57:41 +08:00
parent 0546f43337
commit c27707cbd1
3 changed files with 37 additions and 19 deletions
+17 -10
View File
@@ -2,7 +2,7 @@
* LocalStorage Hook
*/
import { useState } from 'react';
import { useCallback, useState } from 'react';
export function useLocalStorage<T>(
key: string,
@@ -18,15 +18,22 @@ export function useLocalStorage<T>(
}
});
const setValue = (value: T | ((val: T) => T)) => {
try {
const valueToStore = value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
window.localStorage.setItem(key, JSON.stringify(valueToStore));
} catch (error) {
console.error(`Error setting localStorage key "${key}":`, error);
}
};
const setValue = useCallback(
(value: T | ((val: T) => T)) => {
setStoredValue((currentValue) => {
const valueToStore = value instanceof Function ? value(currentValue) : value;
try {
window.localStorage.setItem(key, JSON.stringify(valueToStore));
} catch (error) {
console.error(`Error setting localStorage key "${key}":`, error);
}
return valueToStore;
});
},
[key]
);
return [storedValue, setValue];
}
+6 -3
View File
@@ -78,11 +78,14 @@ export function LogsPage() {
const [logState, setLogState] = useState<LogState>({ buffer: [], visibleFrom: 0 });
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
const [autoRefresh, setAutoRefresh] = useState(false);
const [autoRefresh, setAutoRefresh] = useLocalStorage('logsPage.autoRefresh', false);
const [searchQuery, setSearchQuery] = useState('');
const deferredSearchQuery = useDeferredValue(searchQuery);
const [hideManagementLogs, setHideManagementLogs] = useState(true);
const [showRawLogs, setShowRawLogs] = useState(false);
const [hideManagementLogs, setHideManagementLogs] = useLocalStorage(
'logsPage.hideManagementLogs',
true
);
const [showRawLogs, setShowRawLogs] = useLocalStorage('logsPage.showRawLogs', false);
const [structuredFiltersExpanded, setStructuredFiltersExpanded] = useLocalStorage(
'logsPage.structuredFiltersExpanded',
true
+14 -6
View File
@@ -1,4 +1,5 @@
import { useEffect, useMemo, useState } from 'react';
import { useEffect, useMemo } from 'react';
import { useLocalStorage } from '@/hooks/useLocalStorage';
import type { HttpMethod, ParsedLogLine, StatusGroup } from './logTypes';
import { resolveStatusGroup } from './logTypes';
@@ -28,9 +29,15 @@ interface UseLogFiltersReturn {
export function useLogFilters(options: UseLogFiltersOptions): UseLogFiltersReturn {
const { parsedLines } = options;
const [methodFilters, setMethodFilters] = useState<HttpMethod[]>([]);
const [statusFilters, setStatusFilters] = useState<StatusGroup[]>([]);
const [pathFilters, setPathFilters] = useState<string[]>([]);
const [methodFilters, setMethodFilters] = useLocalStorage<HttpMethod[]>(
'logsPage.methodFilters',
[]
);
const [statusFilters, setStatusFilters] = useLocalStorage<StatusGroup[]>(
'logsPage.statusFilters',
[]
);
const [pathFilters, setPathFilters] = useLocalStorage<string[]>('logsPage.pathFilters', []);
const methodFilterSet = useMemo(() => new Set(methodFilters), [methodFilters]);
const statusFilterSet = useMemo(() => new Set(statusFilters), [statusFilters]);
@@ -70,14 +77,15 @@ export function useLogFilters(options: UseLogFiltersOptions): UseLogFiltersRetur
}, [parsedLines]);
useEffect(() => {
if (parsedLines.length === 0) return;
const validPathSet = new Set(pathOptions.map((item) => item.path));
// eslint-disable-next-line react-hooks/set-state-in-effect
setPathFilters((prev) => {
if (prev.length === 0) return prev;
const next = prev.filter((path) => validPathSet.has(path));
return next.length === prev.length ? prev : next;
});
}, [pathOptions]);
}, [parsedLines.length, pathOptions, setPathFilters]);
const toggleMethodFilter = (method: HttpMethod) => {
setMethodFilters((prev) =>