Update AppImage

This commit is contained in:
MacRimi
2025-10-25 22:10:08 +02:00
parent 6bf5bd97b5
commit a229231c0c
2 changed files with 131 additions and 106 deletions

View File

@@ -640,20 +640,22 @@ export function NetworkMetrics() {
<Router className="h-5 w-5" /> <Router className="h-5 w-5" />
{selectedInterface?.name} - Interface Details {selectedInterface?.name} - Interface Details
</DialogTitle> </DialogTitle>
<div className="flex justify-end pt-2"> {selectedInterface?.status.toLowerCase() === "up" && selectedInterface?.vm_type !== "vm" && (
<Select value={modalTimeframe} onValueChange={(value: any) => setModalTimeframe(value)}> <div className="flex justify-end pt-2">
<SelectTrigger className="w-[140px] bg-card border-border"> <Select value={modalTimeframe} onValueChange={(value: any) => setModalTimeframe(value)}>
<SelectValue /> <SelectTrigger className="w-[140px] bg-card border-border">
</SelectTrigger> <SelectValue />
<SelectContent> </SelectTrigger>
<SelectItem value="hour">1 Hour</SelectItem> <SelectContent>
<SelectItem value="day">24 Hours</SelectItem> <SelectItem value="hour">1 Hour</SelectItem>
<SelectItem value="week">7 Days</SelectItem> <SelectItem value="day">24 Hours</SelectItem>
<SelectItem value="month">30 Days</SelectItem> <SelectItem value="week">7 Days</SelectItem>
<SelectItem value="year">1 Year</SelectItem> <SelectItem value="month">30 Days</SelectItem>
</SelectContent> <SelectItem value="year">1 Year</SelectItem>
</Select> </SelectContent>
</div> </Select>
</div>
)}
</DialogHeader> </DialogHeader>
{selectedInterface && ( {selectedInterface && (
@@ -789,99 +791,122 @@ export function NetworkMetrics() {
</div> </div>
)} )}
<div> {/* Network Traffic Statistics - Only show if interface is UP and NOT a VM interface */}
<h3 className="text-sm font-semibold text-muted-foreground mb-4"> {selectedInterface.status.toLowerCase() === "up" && selectedInterface.vm_type !== "vm" ? (
Network Traffic Statistics ( <div>
{modalTimeframe === "hour" <h3 className="text-sm font-semibold text-muted-foreground mb-4">
? "Last Hour" Network Traffic Statistics (
: modalTimeframe === "day" {modalTimeframe === "hour"
? "Last 24 Hours" ? "Last Hour"
: modalTimeframe === "week" : modalTimeframe === "day"
? "Last 7 Days" ? "Last 24 Hours"
: modalTimeframe === "month" : modalTimeframe === "week"
? "Last 30 Days" ? "Last 7 Days"
: "Last Year"} : modalTimeframe === "month"
) ? "Last 30 Days"
</h3> : "Last Year"}
<div className="space-y-4"> )
{/* Traffic Data - Top Row */} </h3>
<div className="space-y-4">
{/* Traffic Data - Top Row */}
<div className="grid grid-cols-2 gap-4">
<div>
<div className="text-sm text-muted-foreground">Bytes Received</div>
<div className="font-medium text-green-500 text-lg">
{formatStorage(interfaceTotals.received * 1024 * 1024 * 1024)}
</div>
</div>
<div>
<div className="text-sm text-muted-foreground">Bytes Sent</div>
<div className="font-medium text-blue-500 text-lg">
{formatStorage(interfaceTotals.sent * 1024 * 1024 * 1024)}
</div>
</div>
</div>
{/* Network Traffic Chart - Full Width Below */}
<div className="bg-muted/30 rounded-lg p-4">
<NetworkTrafficChart
timeframe={modalTimeframe}
interfaceName={selectedInterface.name}
onTotalsCalculated={setInterfaceTotals}
/>
</div>
</div>
</div>
) : selectedInterface.status.toLowerCase() === "up" && selectedInterface.vm_type === "vm" ? (
<div className="bg-muted/30 rounded-lg p-6 text-center">
<AlertCircle className="h-12 w-12 text-muted-foreground mx-auto mb-3" />
<h3 className="text-lg font-semibold text-foreground mb-2">Historical Metrics Not Available</h3>
<p className="text-sm text-muted-foreground">
Proxmox does not store historical network metrics for individual VM interfaces. Only cumulative
statistics since last boot are available below.
</p>
</div>
) : (
<div className="bg-muted/30 rounded-lg p-6 text-center">
<AlertCircle className="h-12 w-12 text-muted-foreground mx-auto mb-3" />
<h3 className="text-lg font-semibold text-foreground mb-2">Interface Inactive</h3>
<p className="text-sm text-muted-foreground">
This interface is currently down. Network traffic statistics are not available.
</p>
</div>
)}
{/* Cumulative Statistics - Only show if interface is UP */}
{selectedInterface.status.toLowerCase() === "up" && (
<div>
<h3 className="text-sm font-semibold text-muted-foreground mb-4">
Cumulative Statistics (Since Last Boot)
</h3>
<div className="grid grid-cols-2 gap-4"> <div className="grid grid-cols-2 gap-4">
<div> <div>
<div className="text-sm text-muted-foreground">Bytes Received</div> <div className="text-sm text-muted-foreground">Packets Received</div>
<div className="font-medium text-green-500 text-lg"> <div className="font-medium">{selectedInterface.packets_recv?.toLocaleString() || "N/A"}</div>
{formatStorage(interfaceTotals.received * 1024 * 1024 * 1024)}
</div>
</div> </div>
<div> <div>
<div className="text-sm text-muted-foreground">Bytes Sent</div> <div className="text-sm text-muted-foreground">Packets Sent</div>
<div className="font-medium text-blue-500 text-lg"> <div className="font-medium">{selectedInterface.packets_sent?.toLocaleString() || "N/A"}</div>
{formatStorage(interfaceTotals.sent * 1024 * 1024 * 1024)}
</div>
</div> </div>
</div> <div>
<div className="text-sm text-muted-foreground">Errors In</div>
{/* Network Traffic Chart - Full Width Below */} <div className="font-medium text-red-500">{selectedInterface.errors_in || 0}</div>
<div className="bg-muted/30 rounded-lg p-4"> </div>
<NetworkTrafficChart <div>
timeframe={modalTimeframe} <div className="text-sm text-muted-foreground">Errors Out</div>
interfaceName={selectedInterface.name} <div className="font-medium text-red-500">{selectedInterface.errors_out || 0}</div>
onTotalsCalculated={setInterfaceTotals} </div>
/> <div>
<div className="text-sm text-muted-foreground">Drops In</div>
<div className="font-medium text-yellow-500">{selectedInterface.drops_in || 0}</div>
</div>
<div>
<div className="text-sm text-muted-foreground">Drops Out</div>
<div className="font-medium text-yellow-500">{selectedInterface.drops_out || 0}</div>
</div>
{selectedInterface.packet_loss_in !== undefined && (
<div>
<div className="text-sm text-muted-foreground">Packet Loss In</div>
<div
className={`font-medium ${selectedInterface.packet_loss_in > 1 ? "text-red-500" : "text-green-500"}`}
>
{selectedInterface.packet_loss_in}%
</div>
</div>
)}
{selectedInterface.packet_loss_out !== undefined && (
<div>
<div className="text-sm text-muted-foreground">Packet Loss Out</div>
<div
className={`font-medium ${selectedInterface.packet_loss_out > 1 ? "text-red-500" : "text-green-500"}`}
>
{selectedInterface.packet_loss_out}%
</div>
</div>
)}
</div> </div>
</div> </div>
</div> )}
<div>
<h3 className="text-sm font-semibold text-muted-foreground mb-4">
Cumulative Statistics (Since Last Boot)
</h3>
<div className="grid grid-cols-2 gap-4">
<div>
<div className="text-sm text-muted-foreground">Packets Received</div>
<div className="font-medium">{selectedInterface.packets_recv?.toLocaleString() || "N/A"}</div>
</div>
<div>
<div className="text-sm text-muted-foreground">Packets Sent</div>
<div className="font-medium">{selectedInterface.packets_sent?.toLocaleString() || "N/A"}</div>
</div>
<div>
<div className="text-sm text-muted-foreground">Errors In</div>
<div className="font-medium text-red-500">{selectedInterface.errors_in || 0}</div>
</div>
<div>
<div className="text-sm text-muted-foreground">Errors Out</div>
<div className="font-medium text-red-500">{selectedInterface.errors_out || 0}</div>
</div>
<div>
<div className="text-sm text-muted-foreground">Drops In</div>
<div className="font-medium text-yellow-500">{selectedInterface.drops_in || 0}</div>
</div>
<div>
<div className="text-sm text-muted-foreground">Drops Out</div>
<div className="font-medium text-yellow-500">{selectedInterface.drops_out || 0}</div>
</div>
{selectedInterface.packet_loss_in !== undefined && (
<div>
<div className="text-sm text-muted-foreground">Packet Loss In</div>
<div
className={`font-medium ${selectedInterface.packet_loss_in > 1 ? "text-red-500" : "text-green-500"}`}
>
{selectedInterface.packet_loss_in}%
</div>
</div>
)}
{selectedInterface.packet_loss_out !== undefined && (
<div>
<div className="text-sm text-muted-foreground">Packet Loss Out</div>
<div
className={`font-medium ${selectedInterface.packet_loss_out > 1 ? "text-red-500" : "text-green-500"}`}
>
{selectedInterface.packet_loss_out}%
</div>
</div>
)}
</div>
</div>
{/* Bond Information */} {/* Bond Information */}
{selectedInterface.type === "bond" && selectedInterface.bond_slaves && ( {selectedInterface.type === "bond" && selectedInterface.bond_slaves && (

View File

@@ -183,7 +183,7 @@ export function NetworkTrafficChart({ timeframe, interfaceName, onTotalsCalculat
if (loading) { if (loading) {
return ( return (
<div className="flex items-center justify-center h-[200px]"> <div className="flex items-center justify-center h-[300px]">
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" /> <Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
</div> </div>
) )
@@ -191,7 +191,7 @@ export function NetworkTrafficChart({ timeframe, interfaceName, onTotalsCalculat
if (error) { if (error) {
return ( return (
<div className="flex flex-col items-center justify-center h-[200px] gap-2"> <div className="flex flex-col items-center justify-center h-[300px] gap-2">
<p className="text-muted-foreground text-sm">Network metrics not available yet</p> <p className="text-muted-foreground text-sm">Network metrics not available yet</p>
<p className="text-xs text-red-500">{error}</p> <p className="text-xs text-red-500">{error}</p>
</div> </div>
@@ -200,15 +200,15 @@ export function NetworkTrafficChart({ timeframe, interfaceName, onTotalsCalculat
if (data.length === 0) { if (data.length === 0) {
return ( return (
<div className="flex items-center justify-center h-[200px]"> <div className="flex items-center justify-center h-[300px]">
<p className="text-muted-foreground text-sm">No network metrics available</p> <p className="text-muted-foreground text-sm">No network metrics available</p>
</div> </div>
) )
} }
return ( return (
<ResponsiveContainer width="100%" height={200}> <ResponsiveContainer width="100%" height={300}>
<AreaChart data={data} margin={{ bottom: 40, left: 10, right: 10 }}> <AreaChart data={data} margin={{ bottom: 80, left: 10 }}>
<CartesianGrid strokeDasharray="3 3" stroke="currentColor" className="text-border" /> <CartesianGrid strokeDasharray="3 3" stroke="currentColor" className="text-border" />
<XAxis <XAxis
dataKey="time" dataKey="time"
@@ -217,7 +217,7 @@ export function NetworkTrafficChart({ timeframe, interfaceName, onTotalsCalculat
tick={{ fill: "currentColor", fontSize: 12 }} tick={{ fill: "currentColor", fontSize: 12 }}
angle={-45} angle={-45}
textAnchor="end" textAnchor="end"
height={40} height={60}
interval={tickInterval} interval={tickInterval}
/> />
<YAxis <YAxis