diff --git a/frontend-modern/src/components/Backups/UnifiedBackups.tsx b/frontend-modern/src/components/Backups/UnifiedBackups.tsx index 5a0065e84..c39c79e69 100644 --- a/frontend-modern/src/components/Backups/UnifiedBackups.tsx +++ b/frontend-modern/src/components/Backups/UnifiedBackups.tsx @@ -43,6 +43,7 @@ interface DateGroup { const UnifiedBackups: Component = () => { const { state } = useWebSocket(); const [searchTerm, setSearchTerm] = createSignal(''); + const [selectedNode, setSelectedNode] = createSignal(null); const [typeFilter, setTypeFilter] = createSignal<'all' | FilterableGuestType>('all'); const [backupTypeFilter, setBackupTypeFilter] = createSignal<'all' | BackupType>('all'); const [groupByMode, setGroupByMode] = createSignal<'date' | 'guest'>('date'); @@ -354,6 +355,7 @@ const UnifiedBackups: Component = () => { const type = typeFilter(); const backupType = backupTypeFilter(); const dateRange = selectedDateRange(); + const nodeFilter = selectedNode(); // Date range filter if (dateRange) { @@ -362,6 +364,11 @@ const UnifiedBackups: Component = () => { ); } + // Node selection filter + if (nodeFilter) { + data = data.filter(item => item.node.toLowerCase() === nodeFilter.toLowerCase()); + } + // Search filter - with advanced filtering support like Dashboard if (search) { // Check for special PBS namespace filter format first @@ -592,6 +599,7 @@ const UnifiedBackups: Component = () => { // Reset filters const resetFilters = () => { setSearchTerm(''); + setSelectedNode(null); setIsSearchLocked(false); setTypeFilter('all'); setBackupTypeFilter('all'); @@ -619,7 +627,7 @@ const UnifiedBackups: Component = () => { // Escape key behavior if (e.key === 'Escape') { // Clear search and reset filters - if (searchTerm().trim() || typeFilter() !== 'all' || backupTypeFilter() !== 'all' || + if (searchTerm().trim() || selectedNode() || typeFilter() !== 'all' || backupTypeFilter() !== 'all' || selectedDateRange() !== null || sortKey() !== 'backupTime' || sortDirection() !== 'desc') { resetFilters(); @@ -888,14 +896,8 @@ const UnifiedBackups: Component = () => { { - if (nodeId) { - const nodeFilter = `node:${nodeId}`; - setSearchTerm(nodeFilter); - setIsSearchLocked(true); - } else { - setSearchTerm(''); - setIsSearchLocked(false); - } + setSelectedNode(nodeId); + setIsSearchLocked(!!nodeId); }} onNamespaceSelect={(namespaceFilter) => { setSearchTerm(namespaceFilter); diff --git a/frontend-modern/src/components/Storage/Storage.tsx b/frontend-modern/src/components/Storage/Storage.tsx index 6afaab51a..88d28996a 100644 --- a/frontend-modern/src/components/Storage/Storage.tsx +++ b/frontend-modern/src/components/Storage/Storage.tsx @@ -13,6 +13,7 @@ const Storage: Component = () => { const { state, connected, activeAlerts, initialDataReceived } = useWebSocket(); const [viewMode, setViewMode] = createSignal<'node' | 'storage'>('node'); const [searchTerm, setSearchTerm] = createSignal(''); + const [selectedNode, setSelectedNode] = createSignal(null); // TODO: Implement sorting in sortedStorage function // const [sortKey, setSortKey] = createSignal('name'); // const [sortDirection, setSortDirection] = createSignal<'asc' | 'desc'>('asc'); @@ -59,23 +60,23 @@ const Storage: Component = () => { const sortedStorage = createMemo(() => { let storage = [...filteredStorage()]; + // Apply node selection filter + const nodeFilter = selectedNode(); + if (nodeFilter) { + storage = storage.filter(s => s.node.toLowerCase() === nodeFilter.toLowerCase()); + } + // Apply search filter const search = searchTerm().toLowerCase(); if (search) { - // Check if it's a node filter - if (search.startsWith('node:')) { - const nodeName = search.substring(5).trim(); - storage = storage.filter(s => s.node.toLowerCase() === nodeName.toLowerCase()); - } else { - // Regular search - storage = storage.filter(s => - s.name.toLowerCase().includes(search) || - s.node.toLowerCase().includes(search) || - s.type.toLowerCase().includes(search) || - s.content?.toLowerCase().includes(search) || - (s.status && s.status.toLowerCase().includes(search)) - ); - } + // Regular search + storage = storage.filter(s => + s.name.toLowerCase().includes(search) || + s.node.toLowerCase().includes(search) || + s.type.toLowerCase().includes(search) || + s.content?.toLowerCase().includes(search) || + (s.status && s.status.toLowerCase().includes(search)) + ); } // Always sort by name alphabetically for consistent order @@ -116,6 +117,7 @@ const Storage: Component = () => { const resetFilters = () => { setSearchTerm(''); + setSelectedNode(null); setViewMode('node'); // setSortKey('name'); // setSortDirection('asc'); @@ -151,7 +153,7 @@ const Storage: Component = () => { // Escape key behavior if (e.key === 'Escape') { // Clear search and reset filters - if (searchTerm().trim() || viewMode() !== 'node') { + if (searchTerm().trim() || selectedNode() || viewMode() !== 'node') { resetFilters(); // Blur the search input if it's focused @@ -173,14 +175,7 @@ const Storage: Component = () => { }); const handleNodeSelect = (nodeId: string | null) => { - if (nodeId) { - // Set search to filter by node - const nodeFilter = `node:${nodeId}`; - setSearchTerm(nodeFilter); - } else { - // Clear node filter from search - setSearchTerm(''); - } + setSelectedNode(nodeId); }; return ( diff --git a/frontend-modern/src/components/shared/NodeSummaryTable.tsx b/frontend-modern/src/components/shared/NodeSummaryTable.tsx index c59d56c38..bbd192c41 100644 --- a/frontend-modern/src/components/shared/NodeSummaryTable.tsx +++ b/frontend-modern/src/components/shared/NodeSummaryTable.tsx @@ -173,7 +173,7 @@ export const NodeSummaryTable: Component = (props) => { return (