diff --git a/frontend-modern/src/components/Dashboard/CompactNodeCard.tsx b/frontend-modern/src/components/Dashboard/CompactNodeCard.tsx index 8f1c434c3..fdcad7b0a 100644 --- a/frontend-modern/src/components/Dashboard/CompactNodeCard.tsx +++ b/frontend-modern/src/components/Dashboard/CompactNodeCard.tsx @@ -8,6 +8,8 @@ import { useWebSocket } from '@/App'; interface CompactNodeCardProps { node: Node; variant: 'compact' | 'ultra-compact'; + onClick?: () => void; + isSelected?: boolean; } const CompactNodeCard: Component = (props) => { @@ -55,11 +57,14 @@ const CompactNodeCard: Component = (props) => { if (props.variant === 'ultra-compact') { // Single line format for 10+ nodes return ( -
+
{/* Status dot */} @@ -101,11 +106,14 @@ const CompactNodeCard: Component = (props) => { // Compact bar format for 5-9 nodes return ( -
+
diff --git a/frontend-modern/src/components/Dashboard/Dashboard.tsx b/frontend-modern/src/components/Dashboard/Dashboard.tsx index 0a821e834..271aff721 100644 --- a/frontend-modern/src/components/Dashboard/Dashboard.tsx +++ b/frontend-modern/src/components/Dashboard/Dashboard.tsx @@ -355,7 +355,33 @@ export function Dashboard(props: DashboardProps) { {(node) => ( - + { + const currentSearch = search(); + const nodeFilter = `node:${node.name}`; + + // Check if this node filter is already in the search + if (currentSearch.includes(nodeFilter)) { + // Remove the node filter + setSearch(currentSearch.replace(nodeFilter, '').trim().replace(/,\s*,/g, ',').replace(/^,|,$/g, '')); + setIsSearchLocked(false); + } else { + // Clear any existing node: filters and add the new one + const cleanedSearch = currentSearch.replace(/node:\w+/g, '').trim().replace(/,\s*,/g, ',').replace(/^,|,$/g, ''); + const newSearch = cleanedSearch ? `${cleanedSearch}, ${nodeFilter}` : nodeFilter; + setSearch(newSearch); + setIsSearchLocked(true); + + // Expand filters if collapsed + if (!showFilters()) { + setShowFilters(true); + } + } + }} + /> )} @@ -368,7 +394,33 @@ export function Dashboard(props: DashboardProps) { {(node) => ( - + { + const currentSearch = search(); + const nodeFilter = `node:${node.name}`; + + // Check if this node filter is already in the search + if (currentSearch.includes(nodeFilter)) { + // Remove the node filter + setSearch(currentSearch.replace(nodeFilter, '').trim().replace(/,\s*,/g, ',').replace(/^,|,$/g, '')); + setIsSearchLocked(false); + } else { + // Clear any existing node: filters and add the new one + const cleanedSearch = currentSearch.replace(/node:\w+/g, '').trim().replace(/,\s*,/g, ',').replace(/^,|,$/g, ''); + const newSearch = cleanedSearch ? `${cleanedSearch}, ${nodeFilter}` : nodeFilter; + setSearch(newSearch); + setIsSearchLocked(true); + + // Expand filters if collapsed + if (!showFilters()) { + setShowFilters(true); + } + } + }} + /> )}