mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2025-11-19 03:56:18 +00:00
Update AppImage
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
import { Card, CardContent } from "./ui/card"
|
||||
import { Badge } from "./ui/badge"
|
||||
import { Wifi, Zap } from "lucide-react"
|
||||
import { Wifi, Zap } from 'lucide-react'
|
||||
import { useState, useEffect } from "react"
|
||||
import { fetchApi } from "../lib/api-config"
|
||||
|
||||
@@ -83,15 +83,79 @@ const formatStorage = (bytes: number): string => {
|
||||
return `${value.toFixed(decimals)} ${sizes[i]}`
|
||||
}
|
||||
|
||||
const getUnitsSettings = () => {
|
||||
if (typeof window === 'undefined') return { networkUnit: 'Bytes' as const }
|
||||
|
||||
try {
|
||||
const settings = localStorage.getItem('unitsSettings')
|
||||
if (settings) {
|
||||
const parsed = JSON.parse(settings)
|
||||
return { networkUnit: parsed.networkUnit || 'Bytes' }
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[v0] Error reading units settings:', e)
|
||||
}
|
||||
|
||||
return { networkUnit: 'Bytes' as const }
|
||||
}
|
||||
|
||||
const formatNetworkTraffic = (sizeInGB: number, unit: "Bytes" | "Bits" = "Bytes"): string => {
|
||||
if (unit === "Bits") {
|
||||
// Convert GB to Gb (Gigabits)
|
||||
const sizeInGb = sizeInGB * 8
|
||||
|
||||
if (sizeInGb < 0.001) {
|
||||
// Less than 0.001 Gb, show in Mb
|
||||
return `${(sizeInGb * 1024).toFixed(1)} Mb`
|
||||
} else if (sizeInGb < 1) {
|
||||
// Less than 1 Gb, show in Mb
|
||||
return `${(sizeInGb * 1024).toFixed(1)} Mb`
|
||||
} else if (sizeInGb < 1024) {
|
||||
// Less than 1024 Gb, show in Gb
|
||||
return `${sizeInGb.toFixed(1)} Gb`
|
||||
} else {
|
||||
// 1024 Gb or more, show in Tb
|
||||
return `${(sizeInGb / 1024).toFixed(1)} Tb`
|
||||
}
|
||||
} else {
|
||||
// Bytes mode (existing behavior)
|
||||
if (sizeInGB < 1) {
|
||||
// Less than 1 GB, show in MB
|
||||
return `${(sizeInGB * 1024).toFixed(1)} MB`
|
||||
} else if (sizeInGB < 1024) {
|
||||
// Less than 1024 GB, show in GB
|
||||
return `${sizeInGB.toFixed(1)} GB`
|
||||
} else {
|
||||
// 1024 GB or more, show in TB
|
||||
return `${(sizeInGB / 1024).toFixed(1)} TB`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function NetworkCard({ interface_, timeframe, onClick }: NetworkCardProps) {
|
||||
const typeBadge = getInterfaceTypeBadge(interface_.type)
|
||||
const vmTypeBadge = interface_.vm_type ? getVMTypeBadge(interface_.vm_type) : null
|
||||
|
||||
const [networkUnit, setNetworkUnit] = useState<"Bytes" | "Bits">("Bytes")
|
||||
|
||||
const [trafficData, setTrafficData] = useState<{ received: number; sent: number }>({
|
||||
received: 0,
|
||||
sent: 0,
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
const settings = getUnitsSettings()
|
||||
setNetworkUnit(settings.networkUnit as "Bytes" | "Bits")
|
||||
|
||||
const handleStorageChange = () => {
|
||||
const settings = getUnitsSettings()
|
||||
setNetworkUnit(settings.networkUnit as "Bytes" | "Bits")
|
||||
}
|
||||
|
||||
window.addEventListener('storage', handleStorageChange)
|
||||
return () => window.removeEventListener('storage', handleStorageChange)
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
const fetchTrafficData = async () => {
|
||||
try {
|
||||
@@ -207,9 +271,9 @@ export function NetworkCard({ interface_, timeframe, onClick }: NetworkCardProps
|
||||
<div className="font-medium text-foreground text-xs">
|
||||
{interface_.status.toLowerCase() === "up" && interface_.vm_type !== "vm" ? (
|
||||
<>
|
||||
<span className="text-green-500">↓ {formatStorage(trafficData.received * 1024 * 1024 * 1024)}</span>
|
||||
<span className="text-green-500">↓ {formatNetworkTraffic(trafficData.received, networkUnit)}</span>
|
||||
{" / "}
|
||||
<span className="text-blue-500">↑ {formatStorage(trafficData.sent * 1024 * 1024 * 1024)}</span>
|
||||
<span className="text-blue-500">↑ {formatNetworkTraffic(trafficData.sent, networkUnit)}</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
|
||||
@@ -28,6 +28,41 @@ import { MetricsView } from "./metrics-dialog"
|
||||
import { formatStorage } from "@/lib/utils" // Import formatStorage utility
|
||||
import { fetchApi } from "../lib/api-config"
|
||||
|
||||
const getUnitsSettings = () => {
|
||||
if (typeof window === 'undefined') return { networkUnit: 'Bytes' as const }
|
||||
|
||||
try {
|
||||
const settings = localStorage.getItem('unitsSettings')
|
||||
if (settings) {
|
||||
const parsed = JSON.parse(settings)
|
||||
return { networkUnit: parsed.networkUnit || 'Bytes' }
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[v0] Error reading units settings:', e)
|
||||
}
|
||||
|
||||
return { networkUnit: 'Bytes' as const }
|
||||
}
|
||||
|
||||
const formatBytes = (bytes: number | undefined, unit: "Bytes" | "Bits" = "Bytes"): string => {
|
||||
if (!bytes || bytes === 0) return unit === "Bits" ? "0 b" : "0 B"
|
||||
|
||||
if (unit === "Bits") {
|
||||
// Convert bytes to bits (*8)
|
||||
const bits = bytes * 8
|
||||
const k = 1000 // Use decimal for bits (networking standard)
|
||||
const sizes = ["b", "Kb", "Mb", "Gb", "Tb"]
|
||||
const i = Math.floor(Math.log(bits) / Math.log(k))
|
||||
return `${(bits / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`
|
||||
} else {
|
||||
// Bytes mode (existing behavior)
|
||||
const k = 1024
|
||||
const sizes = ["B", "KB", "MB", "GB", "TB"]
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
||||
return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`
|
||||
}
|
||||
}
|
||||
|
||||
interface VMData {
|
||||
vmid: number
|
||||
name: string
|
||||
@@ -272,6 +307,20 @@ export function VirtualMachines() {
|
||||
const [selectedMetric, setSelectedMetric] = useState<string | null>(null)
|
||||
const [ipsLoaded, setIpsLoaded] = useState(false)
|
||||
const [loadingIPs, setLoadingIPs] = useState(false)
|
||||
const [networkUnit, setNetworkUnit] = useState<"Bytes" | "Bits">("Bytes")
|
||||
|
||||
useEffect(() => {
|
||||
const settings = getUnitsSettings()
|
||||
setNetworkUnit(settings.networkUnit as "Bytes" | "Bits")
|
||||
|
||||
const handleStorageChange = () => {
|
||||
const settings = getUnitsSettings()
|
||||
setNetworkUnit(settings.networkUnit as "Bytes" | "Bits")
|
||||
}
|
||||
|
||||
window.addEventListener('storage', handleStorageChange)
|
||||
return () => window.removeEventListener('storage', handleStorageChange)
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
const fetchLXCIPs = async () => {
|
||||
@@ -938,11 +987,11 @@ export function VirtualMachines() {
|
||||
<div className="text-sm font-semibold space-y-0.5">
|
||||
<div className="flex items-center gap-1">
|
||||
<Network className="h-3 w-3 text-green-500" />
|
||||
<span className="text-green-500">↓ {formatBytes(vm.netin)}</span>
|
||||
<span className="text-green-500">↓ {formatBytes(vm.netin, networkUnit)}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<Network className="h-3 w-3 text-blue-500" />
|
||||
<span className="text-blue-500">↑ {formatBytes(vm.netout)}</span>
|
||||
<span className="text-blue-500">↑ {formatBytes(vm.netout, networkUnit)}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1152,11 +1201,11 @@ export function VirtualMachines() {
|
||||
<div className="space-y-1">
|
||||
<div className="text-sm text-green-500 flex items-center gap-1">
|
||||
<span>↓</span>
|
||||
<span>{((selectedVM.diskread || 0) / 1024 ** 2).toFixed(2)} MB</span>
|
||||
<span>{formatBytes(selectedVM.diskread || 0, "Bytes")}</span>
|
||||
</div>
|
||||
<div className="text-sm text-blue-500 flex items-center gap-1">
|
||||
<span>↑</span>
|
||||
<span>{((selectedVM.diskwrite || 0) / 1024 ** 2).toFixed(2)} MB</span>
|
||||
<span>{formatBytes(selectedVM.diskwrite || 0, "Bytes")}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1167,11 +1216,11 @@ export function VirtualMachines() {
|
||||
<div className="space-y-1">
|
||||
<div className="text-sm text-green-500 flex items-center gap-1">
|
||||
<span>↓</span>
|
||||
<span>{((selectedVM.netin || 0) / 1024 ** 2).toFixed(2)} MB</span>
|
||||
<span>{formatBytes(selectedVM.netin || 0, networkUnit)}</span>
|
||||
</div>
|
||||
<div className="text-sm text-blue-500 flex items-center gap-1">
|
||||
<span>↑</span>
|
||||
<span>{((selectedVM.netout || 0) / 1024 ** 2).toFixed(2)} MB</span>
|
||||
<span>{formatBytes(selectedVM.netout || 0, networkUnit)}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user