From ee42dee3669cf8eeaf97bb32101331bebefe659f Mon Sep 17 00:00:00 2001 From: MacRimi Date: Mon, 20 Oct 2025 22:40:37 +0200 Subject: [PATCH] Update virtual-machines.tsx --- AppImage/components/virtual-machines.tsx | 633 ++++++++++++++--------- 1 file changed, 382 insertions(+), 251 deletions(-) diff --git a/AppImage/components/virtual-machines.tsx b/AppImage/components/virtual-machines.tsx index c63075c..c2e7e20 100644 --- a/AppImage/components/virtual-machines.tsx +++ b/AppImage/components/virtual-machines.tsx @@ -18,6 +18,9 @@ import { RotateCcw, StopCircle, Container, + X, + Info, + ArrowLeft, } from "lucide-react" import useSWR from "swr" import { MetricsView } from "./metrics-dialog" @@ -187,6 +190,7 @@ export function VirtualMachines() { const [vmConfigs, setVmConfigs] = useState>({}) const [currentView, setCurrentView] = useState<"main" | "metrics">("main") const [selectedMetric, setSelectedMetric] = useState<"cpu" | "memory" | "disk" | "network" | null>(null) + const [showDetailsModal, setShowDetailsModal] = useState(false) useEffect(() => { const fetchLXCIPs = async () => { @@ -724,74 +728,89 @@ export function VirtualMachines() { {currentView === "main" ? ( <> - - {/* Desktop layout */} -
-
- - {selectedVM?.name} - ID: {selectedVM?.vmid} -
- {selectedVM && ( - <> - - {getTypeBadge(selectedVM.type).icon} - {getTypeBadge(selectedVM.type).label} - - - {selectedVM.status.toUpperCase()} - - {selectedVM.status === "running" && ( - - Uptime: {formatUptime(selectedVM.uptime)} - - )} - - )} -
- - {/* Mobile layout */} -
-
- - {selectedVM?.name} - ID: {selectedVM?.vmid} -
- {selectedVM && ( -
- - {getTypeBadge(selectedVM.type).icon} - {getTypeBadge(selectedVM.type).label} - - - {selectedVM.status.toUpperCase()} - - {selectedVM.status === "running" && ( - - Uptime: {formatUptime(selectedVM.uptime)} - - )} +
+ + {/* Desktop layout */} +
+
+ + {selectedVM?.name} + ID: {selectedVM?.vmid}
- )} -
-
+ {selectedVM && ( + <> + + {getTypeBadge(selectedVM.type).icon} + {getTypeBadge(selectedVM.type).label} + + + {selectedVM.status.toUpperCase()} + + {selectedVM.status === "running" && ( + + Uptime: {formatUptime(selectedVM.uptime)} + + )} + + )} +
+ + {/* Mobile layout */} +
+
+ + {selectedVM?.name} + ID: {selectedVM?.vmid} +
+ {selectedVM && ( +
+ + {getTypeBadge(selectedVM.type).icon} + {getTypeBadge(selectedVM.type).label} + + + {selectedVM.status.toUpperCase()} + + {selectedVM.status === "running" && ( + + Uptime: {formatUptime(selectedVM.uptime)} + + )} +
+ )} +
+ + +
{selectedVM && ( <> -
-

- Basic Information -

-
-
-
CPU Usage
-
handleMetricClick("cpu")} - > +
+ {/* CPU & Memory Card */} + + + + CPU & Memory + + + +
handleMetricClick("cpu")}> +
CPU Usage
{(selectedVM.cpu * 100).toFixed(1)}%
@@ -800,13 +819,8 @@ export function VirtualMachines() { className={`h-1.5 ${getModalProgressColor(selectedVM.cpu * 100)}`} />
-
-
-
Memory
-
handleMetricClick("memory")} - > +
handleMetricClick("memory")}> +
Memory
@@ -818,13 +832,19 @@ export function VirtualMachines() { className={`h-1.5 ${getModalProgressColor((selectedVM.mem / selectedVM.maxmem) * 100)}`} />
-
-
-
Disk
-
handleMetricClick("disk")} - > + + + + {/* Disk Usage Card */} + + + + Disk Usage + + + +
handleMetricClick("disk")}> +
Storage
@@ -836,192 +856,121 @@ export function VirtualMachines() { className={`h-1.5 ${getModalProgressColor((selectedVM.disk / selectedVM.maxdisk) * 100)}`} />
-
-
-
Disk I/O
-
handleMetricClick("disk")} - > -
- - {((selectedVM.diskread || 0) / 1024 ** 2).toFixed(2)} MB -
-
- - {((selectedVM.diskwrite || 0) / 1024 ** 2).toFixed(2)} MB -
-
-
-
-
Network I/O
-
handleMetricClick("network")} - > -
- - {((selectedVM.netin || 0) / 1024 ** 2).toFixed(2)} MB -
-
- - {((selectedVM.netout || 0) / 1024 ** 2).toFixed(2)} MB -
-
-
-
-
+ + -
-

- Resources -

-
- {vmDetails?.config.cores && ( -
-
CPU Cores
-
{vmDetails.config.cores}
-
- )} - {vmDetails?.config.sockets && ( -
-
CPU Sockets
-
{vmDetails.config.sockets}
-
- )} - {vmDetails?.config.memory && ( -
-
Memory
-
{vmDetails.config.memory} MB
-
- )} - {vmDetails?.config.swap && ( -
-
Swap
-
{vmDetails.config.swap} MB
-
- )} - {vmDetails?.config.rootfs && ( -
-
Root Filesystem
-
- {vmDetails.config.rootfs} -
-
- )} - {Object.keys(vmDetails?.config || {}) - .filter((key) => key.match(/^(scsi|sata|ide|virtio)\d+$/)) - .map((diskKey) => ( -
-
- {diskKey.toUpperCase().replace(/(\d+)/, " $1")} + {/* Disk I/O Card */} + + + + Disk I/O + + + +
handleMetricClick("disk")}> +
+
+ Read + + {((selectedVM.diskread || 0) / 1024 ** 2).toFixed(2)} MB +
-
- {vmDetails?.config[diskKey]} +
+ Write + + {((selectedVM.diskwrite || 0) / 1024 ** 2).toFixed(2)} MB +
- ))} -
-
+
+ + -
-

- Network -

-
- {Object.keys(vmDetails?.config || {}) - .filter((key) => key.match(/^net\d+$/)) - .map((netKey) => ( -
-
- Network Interface {netKey.replace("net", "")} + {/* Network I/O Card */} + + + + Network I/O + + + +
handleMetricClick("network")}> +
+
+ Download + + {((selectedVM.netin || 0) / 1024 ** 2).toFixed(2)} MB +
-
- {vmDetails?.config[netKey]} +
+ Upload + + {((selectedVM.netout || 0) / 1024 ** 2).toFixed(2)} MB +
- ))} - {vmDetails?.config.nameserver && ( -
-
DNS Nameserver
-
{vmDetails.config.nameserver}
- )} - {vmDetails?.config.searchdomain && ( -
-
Search Domain
-
{vmDetails.config.searchdomain}
-
- )} - {vmDetails?.config.hostname && ( -
-
Hostname
-
{vmDetails.config.hostname}
-
- )} -
-
+
+
-
-

- Options -

-
- {vmDetails?.config.onboot !== undefined && ( -
-
Start on Boot
- + + + Resources +
- )} - {vmDetails?.config.unprivileged !== undefined && ( -
-
Unprivileged
- - {vmDetails.config.unprivileged ? "Yes" : "No"} - -
- )} - {vmDetails?.config.ostype && ( -
-
OS Type
-
{vmDetails.config.ostype}
-
- )} - {vmDetails?.config.arch && ( -
-
Architecture
-
{vmDetails.config.arch}
-
- )} - {vmDetails?.config.boot && ( -
-
Boot Order
-
{vmDetails.config.boot}
-
- )} - {vmDetails?.config.features && ( -
-
Features
-
{vmDetails.config.features}
-
- )} -
+ + More Info + + + + + {vmDetails?.config.cores && ( +
+ CPU Cores + {vmDetails.config.cores} +
+ )} + {vmDetails?.config.sockets && ( +
+ CPU Sockets + {vmDetails.config.sockets} +
+ )} + {vmDetails?.config.memory && ( +
+ Memory + + {vmDetails.config.memory} MB + +
+ )} + {vmDetails?.config.swap && ( +
+ Swap + {vmDetails.config.swap} MB +
+ )} + {selectedVM.type === "lxc" && vmDetails?.config && ( +
+ IP Address + + {extractIPFromConfig(vmDetails.config)} + +
+ )} +
+
)} @@ -1069,7 +1018,6 @@ export function VirtualMachines() {
) : ( - /* Render metrics view when currentView is "metrics" */ selectedVM && selectedMetric && ( + + + + +
+ + + {selectedVM?.type === "lxc" ? "Container" : "Virtual Machine"} Configuration + + +
+
+ +
+
+ {/* Hardware/Resources Section */} +
+

+ {selectedVM?.type === "lxc" ? "Resources" : "Hardware"} +

+
+ {vmDetails?.config.cores && ( +
+
CPU Cores
+
{vmDetails.config.cores}
+
+ )} + {vmDetails?.config.sockets && ( +
+
CPU Sockets
+
{vmDetails.config.sockets}
+
+ )} + {vmDetails?.config.memory && ( +
+
Memory
+
{vmDetails.config.memory} MB
+
+ )} + {vmDetails?.config.swap && ( +
+
Swap
+
{vmDetails.config.swap} MB
+
+ )} + {vmDetails?.config.rootfs && ( +
+
Root Filesystem
+
+ {vmDetails.config.rootfs} +
+
+ )} + {Object.keys(vmDetails?.config || {}) + .filter((key) => key.match(/^(scsi|sata|ide|virtio)\d+$/)) + .map((diskKey) => ( +
+
+ {diskKey.toUpperCase().replace(/(\d+)/, " $1")} +
+
+ {vmDetails?.config[diskKey]} +
+
+ ))} +
+
+ + {/* Network Section */} +
+

Network

+
+ {Object.keys(vmDetails?.config || {}) + .filter((key) => key.match(/^net\d+$/)) + .map((netKey) => ( +
+
+ Network Interface {netKey.replace("net", "")} +
+
+ {vmDetails?.config[netKey]} +
+
+ ))} + {vmDetails?.config.nameserver && ( +
+
DNS Nameserver
+
{vmDetails.config.nameserver}
+
+ )} + {vmDetails?.config.searchdomain && ( +
+
Search Domain
+
{vmDetails.config.searchdomain}
+
+ )} + {vmDetails?.config.hostname && ( +
+
Hostname
+
{vmDetails.config.hostname}
+
+ )} +
+
+ + {/* Options Section */} +
+

Options

+
+ {vmDetails?.config.onboot !== undefined && ( +
+
Start on Boot
+ + {vmDetails.config.onboot ? "Yes" : "No"} + +
+ )} + {vmDetails?.config.unprivileged !== undefined && ( +
+
Unprivileged
+ + {vmDetails.config.unprivileged ? "Yes" : "No"} + +
+ )} + {vmDetails?.config.ostype && ( +
+
OS Type
+
{vmDetails.config.ostype}
+
+ )} + {vmDetails?.config.arch && ( +
+
Architecture
+
{vmDetails.config.arch}
+
+ )} + {vmDetails?.config.boot && ( +
+
Boot Order
+
{vmDetails.config.boot}
+
+ )} + {vmDetails?.config.features && ( +
+
Features
+
{vmDetails.config.features}
+
+ )} +
+
+
+
+
+
) }