feat: extend search filtering to Storage and Backups tabs

- Node tables now dynamically update based on search in all tabs
- Storage tab filters nodes to show only those with matching storage
- Backups tab filters nodes to show only those with matching backups
- Counts update to reflect filtered items in each tab
- Consistent search experience across Dashboard, Storage, and Backups
This commit is contained in:
Pulse Monitor
2025-08-26 11:32:37 +00:00
parent ef95e9d717
commit fd768c6eb1
4 changed files with 49 additions and 13 deletions
@@ -790,6 +790,8 @@ const UnifiedBackups: Component = () => {
setIsSearchLocked(false);
}
}}
filteredBackups={filteredData()}
searchTerm={searchTerm()}
/>
{/* Removed old PBS table */}
@@ -194,6 +194,8 @@ const Storage: Component = () => {
<UnifiedNodeSelector
currentTab="storage"
onNodeSelect={handleNodeSelect}
filteredStorage={sortedStorage()}
searchTerm={searchTerm()}
/>
{/* Storage Filter */}
@@ -13,30 +13,54 @@ interface PVENodeTableProps {
selectedNode: string | null;
onNodeClick: (nodeId: string) => void;
searchTerm?: string;
filteredBackups?: any[];
}
export const PVENodeTable: Component<PVENodeTableProps> = (props) => {
// Check if we have active filtering (receiving filtered guests)
// Check if we have active filtering
const hasActiveFilter = createMemo(() => {
// If vms or containers props are explicitly passed, we're filtering
return props.vms !== undefined || props.containers !== undefined;
// Check based on current tab
switch (props.currentTab) {
case 'dashboard':
return props.vms !== undefined || props.containers !== undefined;
case 'storage':
return props.storage !== undefined;
case 'backups':
return props.filteredBackups !== undefined;
default:
return false;
}
});
// Filter and sort nodes - only show nodes with matching guests when filtering
// Filter and sort nodes based on current tab
const sortedNodes = createMemo(() => {
if (!props.nodes) return [];
let nodes = [...props.nodes];
// If we have filtered guests, only show nodes that have at least one matching guest
if (hasActiveFilter() && props.currentTab === 'dashboard') {
const nodesWithGuests = new Set<string>();
props.vms?.forEach(vm => nodesWithGuests.add(vm.node));
props.containers?.forEach(ct => nodesWithGuests.add(ct.node));
// Filter nodes based on the current tab and filtered data
if (hasActiveFilter()) {
const nodesWithItems = new Set<string>();
// Only show nodes that have filtered guests
if (nodesWithGuests.size > 0) {
nodes = nodes.filter(node => nodesWithGuests.has(node.name));
switch (props.currentTab) {
case 'dashboard':
// Filter based on VMs and containers
props.vms?.forEach(vm => nodesWithItems.add(vm.node));
props.containers?.forEach(ct => nodesWithItems.add(ct.node));
break;
case 'storage':
// Filter based on storage
props.storage?.forEach(s => nodesWithItems.add(s.node));
break;
case 'backups':
// Filter based on backups
props.filteredBackups?.forEach(b => nodesWithItems.add(b.node));
break;
}
// Only show nodes that have filtered items
if (nodesWithItems.size > 0) {
nodes = nodes.filter(node => nodesWithItems.has(node.name));
}
}
@@ -71,6 +95,11 @@ export const PVENodeTable: Component<PVENodeTableProps> = (props) => {
const storageCount = props.storage?.filter(s => s.node === node.name).length || 0;
return [storageCount];
case 'backups':
// If we have filtered backups, count those; otherwise use the provided counts
if (props.filteredBackups !== undefined) {
const backupCount = props.filteredBackups.filter(b => b.node === node.name).length;
return [backupCount];
}
return [props.backupCounts?.[node.name] || 0];
default:
return [];
@@ -8,6 +8,8 @@ interface UnifiedNodeSelectorProps {
onNodeSelect?: (nodeId: string | null, nodeType: 'pve' | 'pbs' | null) => void;
filteredVms?: any[];
filteredContainers?: any[];
filteredStorage?: any[];
filteredBackups?: any[];
searchTerm?: string;
}
@@ -86,12 +88,13 @@ export const UnifiedNodeSelector: Component<UnifiedNodeSelectorProps> = (props)
nodes={state.nodes}
vms={props.filteredVms !== undefined ? props.filteredVms : state.vms}
containers={props.filteredContainers !== undefined ? props.filteredContainers : state.containers}
storage={state.storage}
storage={props.filteredStorage !== undefined ? props.filteredStorage : state.storage}
backupCounts={backupCounts()}
currentTab={props.currentTab}
selectedNode={selectedNode()}
onNodeClick={handlePVENodeClick}
searchTerm={props.searchTerm}
filteredBackups={props.filteredBackups}
/>
</Show>
<Show when={props.currentTab === 'backups' && state.pbs && state.pbs.length > 0}>