mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2025-11-18 19:46:18 +00:00
Update AppImage
This commit is contained in:
@@ -20,6 +20,7 @@ import {
|
||||
Container,
|
||||
} from "lucide-react"
|
||||
import useSWR from "swr"
|
||||
import { MetricsDialog } from "./metrics-dialog"
|
||||
|
||||
interface VMData {
|
||||
vmid: number
|
||||
@@ -184,6 +185,8 @@ export function VirtualMachines() {
|
||||
const [controlLoading, setControlLoading] = useState(false)
|
||||
const [detailsLoading, setDetailsLoading] = useState(false)
|
||||
const [vmConfigs, setVmConfigs] = useState<Record<number, string>>({})
|
||||
const [metricsDialogOpen, setMetricsDialogOpen] = useState(false)
|
||||
const [selectedMetric, setSelectedMetric] = useState<"cpu" | "memory" | "disk" | "network" | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
const fetchLXCIPs = async () => {
|
||||
@@ -540,7 +543,16 @@ export function VirtualMachines() {
|
||||
<div className="grid grid-cols-2 md:grid-cols-5 gap-3">
|
||||
<div>
|
||||
<div className="text-xs text-muted-foreground mb-1">CPU Usage</div>
|
||||
<div className={`text-sm font-semibold mb-1 ${getUsageColor(Number.parseFloat(cpuPercent))}`}>
|
||||
<div
|
||||
className="cursor-pointer hover:opacity-80 transition-opacity"
|
||||
onClick={() => {
|
||||
setSelectedMetric("cpu")
|
||||
setMetricsDialogOpen(true)
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={`text-sm font-semibold mb-1 ${getUsageColor(Number.parseFloat(cpuPercent))}`}
|
||||
>
|
||||
{cpuPercent}%
|
||||
</div>
|
||||
<Progress
|
||||
@@ -548,10 +560,20 @@ export function VirtualMachines() {
|
||||
className={`h-1.5 ${getProgressColor(Number.parseFloat(cpuPercent))}`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="text-xs text-muted-foreground mb-1">Memory</div>
|
||||
<div className={`text-sm font-semibold mb-1 ${getUsageColor(Number.parseFloat(memPercent))}`}>
|
||||
<div
|
||||
className="cursor-pointer hover:opacity-80 transition-opacity"
|
||||
onClick={() => {
|
||||
setSelectedMetric("memory")
|
||||
setMetricsDialogOpen(true)
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={`text-sm font-semibold mb-1 ${getUsageColor(Number.parseFloat(memPercent))}`}
|
||||
>
|
||||
{memGB} / {maxMemGB} GB
|
||||
</div>
|
||||
<Progress
|
||||
@@ -559,9 +581,17 @@ export function VirtualMachines() {
|
||||
className={`h-1.5 ${getProgressColor(Number.parseFloat(memPercent))}`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="text-xs text-muted-foreground mb-1">Disk Usage</div>
|
||||
<div
|
||||
className="cursor-pointer hover:opacity-80 transition-opacity"
|
||||
onClick={() => {
|
||||
setSelectedMetric("disk")
|
||||
setMetricsDialogOpen(true)
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={`text-sm font-semibold mb-1 ${getUsageColor(Number.parseFloat(diskPercent))}`}
|
||||
>
|
||||
@@ -572,6 +602,7 @@ export function VirtualMachines() {
|
||||
className={`h-1.5 ${getProgressColor(Number.parseFloat(diskPercent))}`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="hidden md:block">
|
||||
<div className="text-xs text-muted-foreground mb-1">Disk I/O</div>
|
||||
@@ -718,6 +749,13 @@ export function VirtualMachines() {
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-xs text-muted-foreground mb-1">CPU Usage</div>
|
||||
<div
|
||||
className="cursor-pointer hover:opacity-80 transition-opacity"
|
||||
onClick={() => {
|
||||
setSelectedMetric("cpu")
|
||||
setMetricsDialogOpen(true)
|
||||
}}
|
||||
>
|
||||
<div className={`font-semibold mb-1 ${getUsageColor(selectedVM.cpu * 100)}`}>
|
||||
{(selectedVM.cpu * 100).toFixed(1)}%
|
||||
</div>
|
||||
@@ -726,8 +764,16 @@ export function VirtualMachines() {
|
||||
className={`h-1.5 ${getModalProgressColor(selectedVM.cpu * 100)}`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-xs text-muted-foreground mb-1">Memory</div>
|
||||
<div
|
||||
className="cursor-pointer hover:opacity-80 transition-opacity"
|
||||
onClick={() => {
|
||||
setSelectedMetric("memory")
|
||||
setMetricsDialogOpen(true)
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={`font-semibold mb-1 ${getUsageColor((selectedVM.mem / selectedVM.maxmem) * 100)}`}
|
||||
>
|
||||
@@ -738,41 +784,67 @@ export function VirtualMachines() {
|
||||
className={`h-1.5 ${getModalProgressColor((selectedVM.mem / selectedVM.maxmem) * 100)}`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-xs text-muted-foreground mb-1">Disk</div>
|
||||
<div
|
||||
className="cursor-pointer hover:opacity-80 transition-opacity"
|
||||
onClick={() => {
|
||||
setSelectedMetric("disk")
|
||||
setMetricsDialogOpen(true)
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={`font-semibold mb-1 ${getUsageColor((selectedVM.disk / selectedVM.maxdisk) * 100)}`}
|
||||
>
|
||||
{(selectedVM.disk / 1024 ** 3).toFixed(1)} / {(selectedVM.maxdisk / 1024 ** 3).toFixed(1)} GB
|
||||
{(selectedVM.disk / 1024 ** 3).toFixed(1)} / {(selectedVM.maxdisk / 1024 ** 3).toFixed(1)}{" "}
|
||||
GB
|
||||
</div>
|
||||
<Progress
|
||||
value={(selectedVM.disk / selectedVM.maxdisk) * 100}
|
||||
className={`h-1.5 ${getModalProgressColor((selectedVM.disk / selectedVM.maxdisk) * 100)}`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-xs text-muted-foreground mb-1">Uptime</div>
|
||||
<div className="font-semibold text-foreground">{formatUptime(selectedVM.uptime)}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-xs text-muted-foreground mb-1">Disk I/O</div>
|
||||
<div className="text-sm font-semibold">
|
||||
<div className="flex items-center gap-1">
|
||||
<span className="text-green-500">↓ {formatBytes(selectedVM.diskread)}</span>
|
||||
<div
|
||||
className="cursor-pointer hover:opacity-80 transition-opacity"
|
||||
onClick={() => {
|
||||
setSelectedMetric("disk")
|
||||
setMetricsDialogOpen(true)
|
||||
}}
|
||||
>
|
||||
<div className="text-sm text-green-500 flex items-center gap-1">
|
||||
<span>↓</span>
|
||||
<span>{((selectedVM.diskread || 0) / 1024 ** 2).toFixed(2)} MB</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<span className="text-blue-500">↑ {formatBytes(selectedVM.diskwrite)}</span>
|
||||
<div className="text-sm text-blue-500 flex items-center gap-1">
|
||||
<span>↑</span>
|
||||
<span>{((selectedVM.diskwrite || 0) / 1024 ** 2).toFixed(2)} MB</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-xs text-muted-foreground mb-1">Network I/O</div>
|
||||
<div className="text-sm font-semibold">
|
||||
<div className="flex items-center gap-1">
|
||||
<span className="text-green-500">↓ {formatBytes(selectedVM.netin)}</span>
|
||||
<div
|
||||
className="cursor-pointer hover:opacity-80 transition-opacity"
|
||||
onClick={() => {
|
||||
setSelectedMetric("network")
|
||||
setMetricsDialogOpen(true)
|
||||
}}
|
||||
>
|
||||
<div className="text-sm text-green-500 flex items-center gap-1">
|
||||
<span>↓</span>
|
||||
<span>{((selectedVM.netin || 0) / 1024 ** 2).toFixed(2)} MB</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<span className="text-blue-500">↑ {formatBytes(selectedVM.netout)}</span>
|
||||
<div className="text-sm text-blue-500 flex items-center gap-1">
|
||||
<span>↑</span>
|
||||
<span>{((selectedVM.netout || 0) / 1024 ** 2).toFixed(2)} MB</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -978,18 +1050,25 @@ export function VirtualMachines() {
|
||||
<StopCircle className="h-4 w-4 mr-2" />
|
||||
Force Stop
|
||||
</Button>
|
||||
<Button
|
||||
className="w-full col-span-2 bg-purple-600 hover:bg-purple-700 text-white"
|
||||
disabled={controlLoading}
|
||||
onClick={() => selectedVM && handleDownloadLogs(selectedVM.vmid, selectedVM.name)}
|
||||
>
|
||||
<HardDrive className="h-4 w-4 mr-2" />
|
||||
Download Logs
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
{/* MetricsDialog component usage */}
|
||||
{selectedVM && selectedMetric && (
|
||||
<MetricsDialog
|
||||
open={metricsDialogOpen}
|
||||
onClose={() => {
|
||||
setMetricsDialogOpen(false)
|
||||
setSelectedMetric(null)
|
||||
}}
|
||||
vmid={selectedVM.vmid}
|
||||
vmName={selectedVM.name}
|
||||
vmType={selectedVM.type}
|
||||
metricType={selectedMetric}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 8.4 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.9 KiB |
Reference in New Issue
Block a user