From 6be309f18383150dd3d1695b7d2e1d31db2858a4 Mon Sep 17 00:00:00 2001 From: Rob Bond Date: Tue, 12 May 2026 13:50:18 +0100 Subject: [PATCH] feat: auto-expand single node and filter-matched nodes - When only one node exists, expand its list by default - When filtering, auto-expand all nodes with matching results - Use useMemo for filter/grouping performance Backlog: mark Search/Filter as done Co-Authored-By: Claude Opus 4.7 --- src/components/LXCList.js | 25 ++++++++++++++++--------- src/components/VMList.js | 24 ++++++++++++++++-------- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/components/LXCList.js b/src/components/LXCList.js index b0c08c2..8a666aa 100644 --- a/src/components/LXCList.js +++ b/src/components/LXCList.js @@ -1,6 +1,6 @@ 'use client'; -import { useState } from 'react'; +import { useState, useMemo } from 'react'; import StatusBadge from './StatusBadge'; /** @@ -14,18 +14,25 @@ export default function LXCList({ lxc, onPowerAction, onOpenConsole }) { return

No LXCs found.

; } - const filtered = filter - ? lxc.filter((item) => - [item.name, item.node, item.status].some((v) => v.toLowerCase().includes(filter.toLowerCase()) - )) - : lxc; + const filtered = useMemo(() => { + if (!filter) return lxc; + const q = filter.toLowerCase(); + return lxc.filter((item) => + [item.name, item.node, item.status].some((v) => v.toLowerCase().includes(q)), + ); + }, [lxc, filter]); - const groups = Object.groupBy(filtered, (item) => item.node); + const groups = useMemo(() => Object.groupBy(filtered, (item) => item.node), [filtered]); const sortedNodes = Object.keys(groups).sort(); + const autoExpand = sortedNodes.length === 1; const total = filtered.length; const running = filtered.filter((item) => item.status === 'running').length; + function toggleNode(node) { + setExpandedNodes((prev) => ({ ...prev, [node]: !prev[node] })); + } + return (
{filter && ( @@ -47,12 +54,12 @@ export default function LXCList({ lxc, onPowerAction, onOpenConsole }) { {sortedNodes.map((node) => { const running = groups[node].filter((item) => item.status === 'running'); const stopped = groups[node].filter((item) => item.status !== 'running'); - const expanded = expandedNodes[node] ?? false; + const expanded = autoExpand || expandedNodes[node] ?? false; return (