diff --git a/AppImage/components/network-metrics.tsx b/AppImage/components/network-metrics.tsx index b17739a..7bd97f7 100644 --- a/AppImage/components/network-metrics.tsx +++ b/AppImage/components/network-metrics.tsx @@ -8,9 +8,8 @@ import { Wifi, Globe, Shield, Activity, Network, Router, AlertCircle, Zap } from import useSWR from "swr" interface NetworkData { - physical_interfaces?: NetworkInterface[] // Separated physical interfaces - bridge_interfaces?: NetworkInterface[] // Separated bridge interfaces - interfaces?: NetworkInterface[] // Keep for backward compatibility + physical_interfaces?: NetworkInterface[] + bridge_interfaces?: NetworkInterface[] vm_lxc_interfaces?: NetworkInterface[] traffic: { bytes_sent: number @@ -19,15 +18,11 @@ interface NetworkData { packets_recv?: number packet_loss_in?: number packet_loss_out?: number - dropin?: number - dropout?: number } - physical_active_count?: number // Physical interfaces active count - physical_total_count?: number // Physical interfaces total count - bridge_active_count?: number // Bridge interfaces active count - bridge_total_count?: number // Bridge interfaces total count - active_count?: number // Keep for backward compatibility - total_count?: number // Keep for backward compatibility + physical_active_count?: number + physical_total_count?: number + bridge_active_count?: number + bridge_total_count?: number vm_lxc_active_count?: number vm_lxc_total_count?: number } @@ -74,10 +69,6 @@ const getInterfaceTypeBadge = (type: string) => { return { color: "bg-purple-500/10 text-purple-500 border-purple-500/20", label: "Bond" } case "vlan": return { color: "bg-cyan-500/10 text-cyan-500 border-cyan-500/20", label: "VLAN" } - case "vm_lxc": - return { color: "bg-orange-500/10 text-orange-500 border-orange-500/20", label: "Virtual" } - case "virtual": - return { color: "bg-orange-500/10 text-orange-500 border-orange-500/20", label: "Virtual" } default: return { color: "bg-gray-500/10 text-gray-500 border-gray-500/20", label: "Unknown" } } @@ -107,7 +98,10 @@ const formatSpeed = (speed: number): string => { } const fetcher = async (url: string): Promise => { - const response = await fetch(url, { + const baseUrl = typeof window !== "undefined" ? `${window.location.protocol}//${window.location.hostname}:8008` : "" + const fullUrl = `${baseUrl}${url}` + + const response = await fetch(fullUrl, { method: "GET", headers: { "Content-Type": "application/json", @@ -128,7 +122,7 @@ export function NetworkMetrics() { error, isLoading, } = useSWR("/api/network", fetcher, { - refreshInterval: 30000, // Refresh every 30 seconds + refreshInterval: 30000, revalidateOnFocus: false, revalidateOnReconnect: true, }) @@ -257,6 +251,7 @@ export function NetworkMetrics() { + {/* Physical Interfaces */} {physicalInterfaces.length > 0 && ( @@ -264,26 +259,25 @@ export function NetworkMetrics() { Physical Interfaces - {networkData.physical_active_count ?? 0} / {networkData.physical_total_count ?? 0} Active + {networkData.physical_active_count ?? 0}/{networkData.physical_total_count ?? 0} Active
- {physicalInterfaces.map((interface_, index) => { - const typeBadge = getInterfaceTypeBadge(interface_.type) + {physicalInterfaces.map((iface, index) => { + const typeBadge = getInterfaceTypeBadge(iface.type) return (
setSelectedInterface(interface_)} + onClick={() => setSelectedInterface(iface)} > - {/* First row: Icon, Name, Type Badge, Status */}
-
{interface_.name}
+
{iface.name}
{typeBadge.label} @@ -291,21 +285,20 @@ export function NetworkMetrics() { - {interface_.status.toUpperCase()} + {iface.status.toUpperCase()}
- {/* Second row: Details - Responsive layout */}
IP Address
- {interface_.addresses.length > 0 ? interface_.addresses[0].ip : "N/A"} + {iface.addresses.length > 0 ? iface.addresses[0].ip : "N/A"}
@@ -313,24 +306,24 @@ export function NetworkMetrics() {
Speed
- {formatSpeed(interface_.speed)} + {formatSpeed(iface.speed)}
Traffic
- ↓ {formatBytes(interface_.bytes_recv)} + ↓ {formatBytes(iface.bytes_recv)} {" / "} - ↑ {formatBytes(interface_.bytes_sent)} + ↑ {formatBytes(iface.bytes_sent)}
- {interface_.mac_address && ( + {iface.mac_address && (
MAC
- {interface_.mac_address} + {iface.mac_address}
)} @@ -343,6 +336,7 @@ export function NetworkMetrics() { )} + {/* Bridge Interfaces */} {bridgeInterfaces.length > 0 && ( @@ -350,25 +344,25 @@ export function NetworkMetrics() { Bridge Interfaces - {networkData.bridge_active_count ?? 0} / {networkData.bridge_total_count ?? 0} Active + {networkData.bridge_active_count ?? 0}/{networkData.bridge_total_count ?? 0} Active
- {bridgeInterfaces.map((interface_, index) => { - const typeBadge = getInterfaceTypeBadge(interface_.type) + {bridgeInterfaces.map((iface, index) => { + const typeBadge = getInterfaceTypeBadge(iface.type) return (
setSelectedInterface(interface_)} + onClick={() => setSelectedInterface(iface)} >
-
{interface_.name}
+
{iface.name}
{typeBadge.label} @@ -376,12 +370,12 @@ export function NetworkMetrics() { - {interface_.status.toUpperCase()} + {iface.status.toUpperCase()}
@@ -389,7 +383,7 @@ export function NetworkMetrics() {
IP Address
- {interface_.addresses.length > 0 ? interface_.addresses[0].ip : "N/A"} + {iface.addresses.length > 0 ? iface.addresses[0].ip : "N/A"}
@@ -397,24 +391,24 @@ export function NetworkMetrics() {
Speed
- {formatSpeed(interface_.speed)} + {formatSpeed(iface.speed)}
Traffic
- ↓ {formatBytes(interface_.bytes_recv)} + ↓ {formatBytes(iface.bytes_recv)} {" / "} - ↑ {formatBytes(interface_.bytes_sent)} + ↑ {formatBytes(iface.bytes_sent)}
- {interface_.mac_address && ( + {iface.mac_address && (
MAC
- {interface_.mac_address} + {iface.mac_address}
)} @@ -435,74 +429,72 @@ export function NetworkMetrics() { VM & LXC Network Interfaces - {networkData.vm_lxc_active_count ?? 0} / {networkData.vm_lxc_total_count ?? 0} Active + {networkData.vm_lxc_active_count ?? 0}/{networkData.vm_lxc_total_count ?? 0} Active
- {vmLxcInterfaces.map((interface_, index) => { - const vmTypeBadge = getVMTypeBadge(interface_.vm_type) + {vmLxcInterfaces.map((iface, index) => { + const vmTypeBadge = getVMTypeBadge(iface.vm_type) return (
setSelectedInterface(interface_)} + onClick={() => setSelectedInterface(iface)} > - {/* First row: Icon, Name, VM/LXC Badge, VM Name, Status */}
-
{interface_.name}
+
{iface.name}
{vmTypeBadge.label} - {interface_.vm_name && ( -
→ {interface_.vm_name}
+ {iface.vm_name && ( +
→ {iface.vm_name}
)}
- {interface_.status.toUpperCase()} + {iface.status.toUpperCase()}
- {/* Second row: Details - Responsive layout */}
VMID
-
{interface_.vmid ?? "N/A"}
+
{iface.vmid ?? "N/A"}
Speed
- {formatSpeed(interface_.speed)} + {formatSpeed(iface.speed)}
Traffic
- ↓ {formatBytes(interface_.bytes_recv)} + ↓ {formatBytes(iface.bytes_recv)} {" / "} - ↑ {formatBytes(interface_.bytes_sent)} + ↑ {formatBytes(iface.bytes_sent)}
- {interface_.mac_address && ( + {iface.mac_address && (
MAC
- {interface_.mac_address} + {iface.mac_address}
)} @@ -515,6 +507,7 @@ export function NetworkMetrics() { )} + {/* Interface Details Dialog */} setSelectedInterface(null)}>