From 7b39b7be4dc5a7c214303b1a0750ece8512b1eab Mon Sep 17 00:00:00 2001 From: Bobban Rydh Date: Thu, 17 Sep 2026 20:50:16 +0200 Subject: [PATCH] Split Proxmox node card into system info (left) / storage (right) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Was a single stacked column (uptime/CPU/memory/swap, then the storage table below); now a two-column layout within the card body — system stats on the left, storage table (or the missing-permission hint) on the right — so the card reads more like a dashboard tile at a glance. Co-Authored-By: Claude Sonnet 5 --- web/src/pages/Proxmox.tsx | 114 +++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 56 deletions(-) diff --git a/web/src/pages/Proxmox.tsx b/web/src/pages/Proxmox.tsx index c57ea53..3fdbd22 100644 --- a/web/src/pages/Proxmox.tsx +++ b/web/src/pages/Proxmox.tsx @@ -186,68 +186,70 @@ export default function Proxmox({ user }: { user: CurrentUser }) {
{n.error &&
{n.error}
}
-
-
Uptime
-
{formatUptime(n.uptime)}
-
-
-
CPU
-
- {n.cpuUsagePercent !== null ? `${n.cpuUsagePercent.toFixed(1)}%` : "—"} - {n.cpuCores ? ({n.cpuCores} cores) : null} +
+
+
Uptime
+
{formatUptime(n.uptime)}
- {n.loadAverage && ( -
Load: {n.loadAverage.map((l) => l.toFixed(2)).join(", ")}
+
+
CPU
+
+ {n.cpuUsagePercent !== null ? `${n.cpuUsagePercent.toFixed(1)}%` : "—"} + {n.cpuCores ? ({n.cpuCores} cores) : null} +
+ {n.loadAverage && ( +
Load: {n.loadAverage.map((l) => l.toFixed(2)).join(", ")}
+ )} +
+
+
Memory
+
+ {formatBytes(n.memUsedBytes)} / {formatBytes(n.memTotalBytes)} +
+ {usageBar(n.memUsedBytes, n.memTotalBytes)} +
+ {!!n.swapTotalBytes && ( +
+
Swap
+
+ {formatBytes(n.swapUsedBytes)} / {formatBytes(n.swapTotalBytes)} +
+ {usageBar(n.swapUsedBytes, n.swapTotalBytes)} +
)}
-
-
Memory
-
- {formatBytes(n.memUsedBytes)} / {formatBytes(n.memTotalBytes)} -
- {usageBar(n.memUsedBytes, n.memTotalBytes)} -
- {!!n.swapTotalBytes && ( -
-
Swap
-
- {formatBytes(n.swapUsedBytes)} / {formatBytes(n.swapTotalBytes)} -
- {usageBar(n.swapUsedBytes, n.swapTotalBytes)} -
- )} -
- {n.storages.length > 0 ? ( -
+
Storage
- - - {n.storages.map((s) => ( - - - - - - ))} - -
- {s.id} - {!s.active && Inactive} - {s.type} - {formatBytes(s.usedBytes)} / {formatBytes(s.totalBytes)} - {usageBar(s.usedBytes, s.totalBytes)} -
+ {n.storages.length > 0 ? ( + + + {n.storages.map((s) => ( + + + + + + ))} + +
+ {s.id} + {!s.active && Inactive} + {s.type} + {formatBytes(s.usedBytes)} / {formatBytes(s.totalBytes)} + {usageBar(s.usedBytes, s.totalBytes)} +
+ ) : ( + !n.error && ( +
+ No storage visible to this API token. Proxmox filters the storage list + per-token — grant it Datastore.Audit (e.g. on{" "} + /storage) to see disk usage here. +
+ ) + )}
- ) : ( - !n.error && ( -
- No storage visible to this API token. Proxmox filters the storage list per-token — - grant it Datastore.Audit (e.g. on /storage) to see disk - usage here. -
- ) - )} +