diff --git a/AppImage/components/system-overview.tsx b/AppImage/components/system-overview.tsx index f5fa70f..01dc435 100644 --- a/AppImage/components/system-overview.tsx +++ b/AppImage/components/system-overview.tsx @@ -4,8 +4,7 @@ import { useState, useEffect } from "react" import { Card, CardContent, CardHeader, CardTitle } from "./ui/card" import { Progress } from "./ui/progress" import { Badge } from "./ui/badge" -import { XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, AreaChart, Area, Legend } from "recharts" -import { Cpu, MemoryStick, Thermometer, Activity, Server, Zap, AlertCircle } from "lucide-react" +import { Cpu, MemoryStick, Thermometer, Server, Zap, AlertCircle, HardDrive, Network } from "lucide-react" interface SystemData { cpu_usage: number @@ -37,23 +36,38 @@ interface VMData { type?: string } -interface HistoricalData { - timestamp: string - cpu_usage: number - memory_used: number - memory_total: number +interface StorageData { + total: number + used: number + available: number + disks: Array<{ + name: string + mountpoint: string + total: number + used: number + available: number + usage_percent: number + }> } -const historicalDataStore: HistoricalData[] = [] -const MAX_HISTORICAL_POINTS = 144 // Store 144 data points for 24h view +interface NetworkData { + interfaces: Array<{ + name: string + status: string + addresses: Array<{ ip: string; netmask: string }> + }> + traffic: { + bytes_sent: number + bytes_recv: number + packets_sent: number + packets_recv: number + } +} const fetchSystemData = async (): Promise => { try { - console.log("[v0] Fetching system data from Flask server...") - const baseUrl = typeof window !== "undefined" ? `${window.location.protocol}//${window.location.hostname}:8008` : "" const apiUrl = `${baseUrl}/api/system` - console.log("[v0] Fetching from URL:", apiUrl) const response = await fetch(apiUrl, { method: "GET", @@ -63,62 +77,22 @@ const fetchSystemData = async (): Promise => { cache: "no-store", }) - console.log("[v0] Response status:", response.status) - console.log("[v0] Response ok:", response.ok) - console.log("[v0] Response headers:", Object.fromEntries(response.headers.entries())) - if (!response.ok) { - const errorText = await response.text() - console.error("[v0] Flask server error response:", errorText) throw new Error(`Flask server responded with status: ${response.status}`) } - const responseText = await response.text() - console.log("[v0] Raw response text:", responseText) - console.log("[v0] Response text length:", responseText.length) - console.log("[v0] First 100 chars:", responseText.substring(0, 100)) - - // Try to parse the JSON - let data - try { - data = JSON.parse(responseText) - console.log("[v0] Successfully parsed JSON:", data) - } catch (parseError) { - console.error("[v0] JSON parse error:", parseError) - console.error("[v0] Failed to parse response as JSON") - throw new Error("Invalid JSON response from server") - } - - // Store historical data - historicalDataStore.push({ - timestamp: data.timestamp, - cpu_usage: data.cpu_usage, - memory_used: data.memory_used, - memory_total: data.memory_total, - }) - - // Keep only last MAX_HISTORICAL_POINTS - if (historicalDataStore.length > MAX_HISTORICAL_POINTS) { - historicalDataStore.shift() - } - + const data = await response.json() return data } catch (error) { - console.error("[v0] Failed to fetch system data from Flask server:", error) - console.error("[v0] Error type:", error instanceof Error ? error.constructor.name : typeof error) - console.error("[v0] Error message:", error instanceof Error ? error.message : String(error)) - console.error("[v0] Error stack:", error instanceof Error ? error.stack : "No stack trace") + console.error("[v0] Failed to fetch system data:", error) return null } } const fetchVMData = async (): Promise => { try { - console.log("[v0] Fetching VM data from Flask server...") - const baseUrl = typeof window !== "undefined" ? `${window.location.protocol}//${window.location.hostname}:8008` : "" const apiUrl = `${baseUrl}/api/vms` - console.log("[v0] Fetching from URL:", apiUrl) const response = await fetch(apiUrl, { method: "GET", @@ -128,48 +102,73 @@ const fetchVMData = async (): Promise => { cache: "no-store", }) - console.log("[v0] VM Response status:", response.status) - if (!response.ok) { - const errorText = await response.text() - console.error("[v0] Flask server error response:", errorText) throw new Error(`Flask server responded with status: ${response.status}`) } const data = await response.json() - console.log("[v0] Successfully fetched VM data from Flask:", data) return Array.isArray(data) ? data : data.vms || [] } catch (error) { - console.error("[v0] Failed to fetch VM data from Flask server:", error) - console.error("[v0] Error type:", error instanceof Error ? error.constructor.name : typeof error) - console.error("[v0] Error message:", error instanceof Error ? error.message : String(error)) + console.error("[v0] Failed to fetch VM data:", error) return [] } } -const generateChartData = () => { - if (historicalDataStore.length === 0) { - return { cpuData: [], memoryData: [] } +const fetchStorageData = async (): Promise => { + try { + const baseUrl = typeof window !== "undefined" ? `${window.location.protocol}//${window.location.hostname}:8008` : "" + const apiUrl = `${baseUrl}/api/storage` + + const response = await fetch(apiUrl, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + cache: "no-store", + }) + + if (!response.ok) { + throw new Error(`Flask server responded with status: ${response.status}`) + } + + const data = await response.json() + return data + } catch (error) { + console.error("[v0] Failed to fetch storage data:", error) + return null } +} - const cpuData = historicalDataStore.map((point) => ({ - time: new Date(point.timestamp).toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit" }), - value: point.cpu_usage, - })) +const fetchNetworkData = async (): Promise => { + try { + const baseUrl = typeof window !== "undefined" ? `${window.location.protocol}//${window.location.hostname}:8008` : "" + const apiUrl = `${baseUrl}/api/network` - const memoryData = historicalDataStore.map((point) => ({ - time: new Date(point.timestamp).toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit" }), - used: point.memory_used, - available: point.memory_total - point.memory_used, - })) + const response = await fetch(apiUrl, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + cache: "no-store", + }) - return { cpuData, memoryData } + if (!response.ok) { + throw new Error(`Flask server responded with status: ${response.status}`) + } + + const data = await response.json() + return data + } catch (error) { + console.error("[v0] Failed to fetch network data:", error) + return null + } } export function SystemOverview() { const [systemData, setSystemData] = useState(null) const [vmData, setVmData] = useState([]) - const [chartData, setChartData] = useState(generateChartData()) + const [storageData, setStorageData] = useState(null) + const [networkData, setNetworkData] = useState(null) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) @@ -179,7 +178,12 @@ export function SystemOverview() { setLoading(true) setError(null) - const [systemResult, vmResult] = await Promise.all([fetchSystemData(), fetchVMData()]) + const [systemResult, vmResult, storageResult, networkResult] = await Promise.all([ + fetchSystemData(), + fetchVMData(), + fetchStorageData(), + fetchNetworkData(), + ]) if (!systemResult) { setError("Flask server not available. Please ensure the server is running.") @@ -189,7 +193,8 @@ export function SystemOverview() { setSystemData(systemResult) setVmData(vmResult) - setChartData(generateChartData()) + setStorageData(storageResult) + setNetworkData(networkResult) } catch (err) { console.error("[v0] Error fetching data:", err) setError("Failed to connect to Flask server. Please check your connection.") @@ -202,7 +207,7 @@ export function SystemOverview() { const interval = setInterval(() => { fetchData() - }, 30000) // Update every 30 seconds + }, 60000) // Update every 60 seconds instead of 30 return () => { clearInterval(interval) @@ -244,14 +249,6 @@ export function SystemOverview() {
{error || "Unable to connect to the Flask server. Please ensure the server is running and try again."}
-
- Troubleshooting: -
    -
  • Check if the Flask server is running on the correct port
  • -
  • Verify network connectivity
  • -
  • Check server logs for errors
  • -
-
@@ -351,100 +348,92 @@ export function SystemOverview() { - {/* Charts Section */}
+ {/* Storage Summary */} - - CPU Usage (Last 24h) + + Storage Overview - {chartData.cpuData.length > 0 ? ( - - - - - - - - - - ) : ( -
- Collecting data... Check back in a few minutes + {storageData ? ( +
+
+ Total Storage: + {storageData.total} GB +
+
+ Used: + {storageData.used} GB +
+
+ Available: + {storageData.available} GB +
+ +
+

+ {storageData.disks.length} disk{storageData.disks.length !== 1 ? "s" : ""} configured +

+
+ ) : ( +
Storage data not available
)} + {/* Network Summary */} - - Memory Usage (Last 24h) + + Network Overview - {chartData.memoryData.length > 0 ? ( - - - - - - - - - - - - ) : ( -
- Collecting data... Check back in a few minutes + {networkData ? ( +
+
+ Active Interfaces: + + {networkData.interfaces.filter((i) => i.status === "up").length} + +
+
+ Data Sent: + + {(networkData.traffic.bytes_sent / 1024 ** 3).toFixed(2)} GB + +
+
+ Data Received: + + {(networkData.traffic.bytes_recv / 1024 ** 3).toFixed(2)} GB + +
+
+ {networkData.interfaces.slice(0, 3).map((iface) => ( +
+ {iface.name}: + + {iface.status} + +
+ ))} +
+ ) : ( +
Network data not available
)}