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 (