diff --git a/frontend-modern/src/components/Dashboard/GuestRow.tsx b/frontend-modern/src/components/Dashboard/GuestRow.tsx index fbef9e6..6394b7f 100644 --- a/frontend-modern/src/components/Dashboard/GuestRow.tsx +++ b/frontend-modern/src/components/Dashboard/GuestRow.tsx @@ -12,7 +12,8 @@ import { logger } from '@/utils/logger'; type Guest = VM | Container; -const drawerState = new Map(); +// Global state for currently expanded drawer (only one drawer open at a time) +const [currentlyExpandedGuestId, setCurrentlyExpandedGuestId] = createSignal(null); // Global editing state - use a signal so all components react const [currentlyEditingGuestId, setCurrentlyEditingGuestId] = createSignal(null); // Store the editing value globally so it survives re-renders @@ -67,7 +68,7 @@ export function GuestRow(props: GuestRowProps) { const [customUrl, setCustomUrl] = createSignal(props.customUrl); const [shouldAnimateIcon, setShouldAnimateIcon] = createSignal(false); - const [drawerOpen, setDrawerOpen] = createSignal(drawerState.get(initialGuestId) ?? false); + const drawerOpen = createMemo(() => currentlyExpandedGuestId() === guestId()); const editingUrlValue = createMemo(() => { editingValuesVersion(); // Subscribe to changes return editingValues.get(guestId()) || ''; @@ -148,23 +149,9 @@ export function GuestRow(props: GuestRowProps) { ); const canShowDrawer = createMemo(() => hasDrawerContent() || hasFallbackContent()); - createEffect(on(guestId, (id) => { - const stored = drawerState.get(id); - if (stored !== undefined) { - setDrawerOpen(stored); - } else { - setDrawerOpen(false); - } - })); - - createEffect(() => { - drawerState.set(guestId(), drawerOpen()); - }); - createEffect(() => { if (!canShowDrawer() && drawerOpen()) { - setDrawerOpen(false); - drawerState.set(guestId(), false); + setCurrentlyExpandedGuestId(null); } }); @@ -174,7 +161,8 @@ export function GuestRow(props: GuestRowProps) { if (target.closest('a, button, input, [data-prevent-toggle]')) { return; } - setDrawerOpen((prev) => !prev); + // Toggle: if this guest is currently expanded, close it; otherwise open it (closing any other) + setCurrentlyExpandedGuestId(prev => prev === guestId() ? null : guestId()); }; const startEditingUrl = (event: MouseEvent) => { @@ -674,7 +662,7 @@ export function GuestRow(props: GuestRowProps) { +
Guest details unavailable
@@ -700,7 +688,7 @@ export function GuestRow(props: GuestRowProps) { > <> 0}> -
+
Guest Overview
@@ -730,7 +718,10 @@ export function GuestRow(props: GuestRowProps) {
{(ip) => ( - + {ip} )} @@ -742,7 +733,7 @@ export function GuestRow(props: GuestRowProps) { 0}> -
+
Memory
{(line) =>
{line}
}
@@ -751,7 +742,7 @@ export function GuestRow(props: GuestRowProps) { 0}> -
+
Filesystems
{(ip) => ( - + {ip} )} diff --git a/frontend-modern/src/components/Docker/DockerUnifiedTable.tsx b/frontend-modern/src/components/Docker/DockerUnifiedTable.tsx index ced68f5..b41d528 100644 --- a/frontend-modern/src/components/Docker/DockerUnifiedTable.tsx +++ b/frontend-modern/src/components/Docker/DockerUnifiedTable.tsx @@ -77,7 +77,8 @@ interface DockerUnifiedTableProps { onCustomUrlUpdate?: (resourceId: string, url: string) => void; } -const rowExpandState = new Map(); +// Global state for currently expanded drawer (only one drawer open at a time) +const [currentlyExpandedRowId, setCurrentlyExpandedRowId] = createSignal(null); // Global editing state for Docker resource URLs const [currentlyEditingDockerResourceId, setCurrentlyEditingDockerResourceId] = createSignal(null); @@ -577,7 +578,7 @@ const DockerContainerRow: Component<{ const [customUrl, setCustomUrl] = createSignal(props.customUrl); const [shouldAnimateIcon, setShouldAnimateIcon] = createSignal(false); - const [expanded, setExpanded] = createSignal(rowExpandState.get(rowId) ?? false); + const expanded = createMemo(() => currentlyExpandedRowId() === rowId); const editingUrlValue = createMemo(() => { dockerEditingValuesVersion(); // Subscribe to changes return dockerEditingValues.get(resourceId()) || ''; @@ -684,11 +685,8 @@ const DockerContainerRow: Component<{ if (!hasDrawerContent()) return; const target = event.target as HTMLElement; if (target.closest('a, button, input, [data-prevent-toggle]')) return; - setExpanded((prev) => { - const next = !prev; - rowExpandState.set(rowId, next); - return next; - }); + // Toggle: if this row is currently expanded, close it; otherwise open it (closing any other) + setCurrentlyExpandedRowId(prev => prev === rowId ? null : rowId); }; const startEditingUrl = (event: MouseEvent) => { @@ -1062,7 +1060,7 @@ const DockerContainerRow: Component<{
-
+
Summary
@@ -1191,7 +1189,7 @@ const DockerContainerRow: Component<{
0}> -
+
Ports
@@ -1211,7 +1209,7 @@ const DockerContainerRow: Component<{ 0}> -
+
Networks
@@ -1238,7 +1236,7 @@ const DockerContainerRow: Component<{ -
+
Podman Metadata
@@ -1272,7 +1270,7 @@ const DockerContainerRow: Component<{ -
+
Block I/O
@@ -1379,12 +1377,18 @@ const DockerContainerRow: Component<{ Labels
- {Object.entries(container.labels!).map(([key, value]) => ( - - {key} - : {value} - - ))} + {Object.entries(container.labels!).map(([key, value]) => { + const fullLabel = value ? `${key}: ${value}` : key; + return ( + + {key} + : {value} + + ); + })}
@@ -1409,7 +1413,7 @@ const DockerServiceRow: Component<{ const [customUrl, setCustomUrl] = createSignal(props.customUrl); const [shouldAnimateIcon, setShouldAnimateIcon] = createSignal(false); - const [expanded, setExpanded] = createSignal(rowExpandState.get(rowId) ?? false); + const expanded = createMemo(() => currentlyExpandedRowId() === rowId); const editingUrlValue = createMemo(() => { dockerEditingValuesVersion(); // Subscribe to changes return dockerEditingValues.get(resourceId()) || ''; @@ -1446,11 +1450,8 @@ const DockerServiceRow: Component<{ if (!hasTasks()) return; const target = event.target as HTMLElement; if (target.closest('a, button, input, [data-prevent-toggle]')) return; - setExpanded((prev) => { - const next = !prev; - rowExpandState.set(rowId, next); - return next; - }); + // Toggle: if this row is currently expanded, close it; otherwise open it (closing any other) + setCurrentlyExpandedRowId(prev => prev === rowId ? null : rowId); }; const startEditingUrl = (event: MouseEvent) => {