From 049eccb8723b9e15dd79e075493a3be674094879 Mon Sep 17 00:00:00 2001 From: MacRimi Date: Mon, 29 Sep 2025 18:27:09 +0200 Subject: [PATCH] Update AppImage --- AppImage/app/api/flask/route.ts | 45 ------ AppImage/app/api/system-info/route.ts | 42 ----- AppImage/app/api/system/route.ts | 48 ------ AppImage/app/api/vms/route.ts | 31 ---- AppImage/components/system-overview.tsx | 200 +++++++++++++++++------- 5 files changed, 147 insertions(+), 219 deletions(-) delete mode 100644 AppImage/app/api/flask/route.ts delete mode 100644 AppImage/app/api/system-info/route.ts delete mode 100644 AppImage/app/api/system/route.ts delete mode 100644 AppImage/app/api/vms/route.ts diff --git a/AppImage/app/api/flask/route.ts b/AppImage/app/api/flask/route.ts deleted file mode 100644 index 5029624..0000000 --- a/AppImage/app/api/flask/route.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { type NextRequest, NextResponse } from "next/server" - -export async function GET(request: NextRequest) { - const { searchParams } = new URL(request.url) - const endpoint = searchParams.get("endpoint") - - console.log(`[v0] Flask bridge API called for endpoint: ${endpoint}`) - - try { - const flaskUrl = `http://localhost:8008/api/${endpoint || "info"}` - - const response = await fetch(flaskUrl, { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - signal: AbortSignal.timeout(10000), - }) - - if (!response.ok) { - throw new Error(`Flask server responded with status: ${response.status}`) - } - - const data = await response.json() - console.log(`[v0] Successfully fetched data from Flask endpoint ${endpoint}:`, data) - - return NextResponse.json({ - ...data, - source: "flask", - endpoint: endpoint, - }) - } catch (error) { - console.error(`[v0] Failed to fetch from Flask server endpoint ${endpoint}:`, error) - - return NextResponse.json( - { - error: "Flask server unavailable", - endpoint: endpoint, - message: error instanceof Error ? error.message : "Unknown error", - source: "error", - }, - { status: 503 }, - ) - } -} diff --git a/AppImage/app/api/system-info/route.ts b/AppImage/app/api/system-info/route.ts deleted file mode 100644 index 96b5345..0000000 --- a/AppImage/app/api/system-info/route.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { type NextRequest, NextResponse } from "next/server" - -export async function GET(request: NextRequest) { - console.log("[v0] API route /api/system-info called") - - try { - const response = await fetch("http://localhost:8008/api/system-info", { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - signal: AbortSignal.timeout(5000), - }) - - if (!response.ok) { - throw new Error(`Flask server responded with status: ${response.status}`) - } - - const systemInfo = await response.json() - console.log("[v0] Successfully fetched real system info from Flask:", systemInfo) - - return NextResponse.json({ - ...systemInfo, - source: "flask", - }) - } catch (error) { - console.error("[v0] Failed to fetch system info from Flask server:", error) - - const fallbackData = { - hostname: "proxmox-server", - node_id: "pve-node", - pve_version: "PVE Unknown", - status: "offline", - timestamp: new Date().toISOString(), - source: "fallback", - error: "Flask server unavailable", - } - - console.log("[v0] Returning fallback system info:", fallbackData) - return NextResponse.json(fallbackData, { status: 503 }) - } -} diff --git a/AppImage/app/api/system/route.ts b/AppImage/app/api/system/route.ts deleted file mode 100644 index c4d7da7..0000000 --- a/AppImage/app/api/system/route.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { type NextRequest, NextResponse } from "next/server" - -export async function GET(request: NextRequest) { - console.log("[v0] API route /api/system called") - - try { - const response = await fetch("http://localhost:8008/api/system", { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - // Add timeout to prevent hanging - signal: AbortSignal.timeout(5000), - }) - - if (!response.ok) { - throw new Error(`Flask server responded with status: ${response.status}`) - } - - const systemData = await response.json() - console.log("[v0] Successfully fetched real system data from Flask:", systemData) - - return NextResponse.json({ - ...systemData, - source: "flask", - }) - } catch (error) { - console.error("[v0] Failed to fetch from Flask server:", error) - - const fallbackData = { - cpu_usage: 0, - memory_usage: 0, - memory_total: 0, - memory_used: 0, - temperature: 0, - uptime: "Unknown", - load_average: [0, 0, 0], - hostname: "proxmox-server", - node_id: "pve-node", - timestamp: new Date().toISOString(), - source: "fallback", - error: "Flask server unavailable", - } - - console.log("[v0] Returning fallback data:", fallbackData) - return NextResponse.json(fallbackData, { status: 503 }) - } -} diff --git a/AppImage/app/api/vms/route.ts b/AppImage/app/api/vms/route.ts deleted file mode 100644 index 748ea4a..0000000 --- a/AppImage/app/api/vms/route.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { type NextRequest, NextResponse } from "next/server" - -export async function GET(request: NextRequest) { - console.log("[v0] API route /api/vms called") - - try { - const response = await fetch("http://localhost:8008/api/vms", { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - signal: AbortSignal.timeout(5000), - }) - - if (!response.ok) { - throw new Error(`Flask server responded with status: ${response.status}`) - } - - const vmData = await response.json() - console.log("[v0] Successfully fetched real VM data from Flask:", vmData) - - return NextResponse.json(vmData) - } catch (error) { - console.error("[v0] Failed to fetch VM data from Flask server:", error) - - const fallbackData = [] - - console.log("[v0] Returning fallback VM data:", fallbackData) - return NextResponse.json(fallbackData, { status: 503 }) - } -} diff --git a/AppImage/components/system-overview.tsx b/AppImage/components/system-overview.tsx index 130c5a9..7312cf2 100644 --- a/AppImage/components/system-overview.tsx +++ b/AppImage/components/system-overview.tsx @@ -5,7 +5,7 @@ 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 } from "recharts" -import { Cpu, MemoryStick, Thermometer, Users, Activity, Server, Zap } from "lucide-react" +import { Cpu, MemoryStick, Thermometer, Users, Activity, Server, Zap, AlertCircle } from "lucide-react" interface SystemData { cpu_usage: number @@ -32,7 +32,7 @@ interface VMData { uptime: number } -const generateRealtimeData = () => ({ +const generateDemoSystemData = (): SystemData => ({ cpu_usage: Math.floor(Math.random() * 20) + 60, // 60-80% memory_usage: Math.floor(Math.random() * 10) + 45, // 45-55% memory_total: 32.0, @@ -40,12 +40,12 @@ const generateRealtimeData = () => ({ temperature: Math.floor(Math.random() * 8) + 48, // 48-56°C uptime: "15d 7h 23m", load_average: [1.23, 1.45, 1.67], - hostname: "proxmox-01", - node_id: "pve-node-01", + hostname: "proxmox-demo", + node_id: "pve-demo-node", timestamp: new Date().toISOString(), }) -const staticVMData: VMData[] = [ +const demVMData: VMData[] = [ { vmid: 100, name: "web-server-01", @@ -79,34 +79,76 @@ const staticVMData: VMData[] = [ maxdisk: 21474836480, uptime: 0, }, - { - vmid: 103, - name: "test-server", - status: "stopped", - cpu: 0, - mem: 0, - maxmem: 2147483648, - disk: 5368709120, - maxdisk: 10737418240, - uptime: 0, - }, ] -const generateChartData = () => { +const fetchSystemData = async (): Promise<{ data: SystemData | null; isDemo: boolean }> => { + try { + console.log("[v0] Attempting to fetch system data from Flask server...") + const response = await fetch("http://localhost:8008/api/system", { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + signal: AbortSignal.timeout(3000), // Reduced timeout for faster fallback + }) + + if (!response.ok) { + throw new Error(`Flask server responded with status: ${response.status}`) + } + + const data = await response.json() + console.log("[v0] Successfully fetched real system data from Flask:", data) + return { data, isDemo: false } + } catch (error) { + console.log("[v0] Flask server not available, using demo data for development") + return { data: generateDemoSystemData(), isDemo: true } + } +} + +const fetchVMData = async (): Promise<{ data: VMData[]; isDemo: boolean }> => { + try { + console.log("[v0] Attempting to fetch VM data from Flask server...") + const response = await fetch("http://localhost:8008/api/vms", { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + signal: AbortSignal.timeout(3000), // Reduced timeout for faster fallback + }) + + if (!response.ok) { + 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 { data: data.vms || [], isDemo: false } + } catch (error) { + console.log("[v0] Flask server not available, using demo VM data") + return { data: demVMData, isDemo: true } + } +} + +const generateChartData = (systemData?: SystemData) => { const cpuData = [] const memoryData = [] for (let i = 0; i < 24; i += 4) { const time = `${i.toString().padStart(2, "0")}:00` + // Use real CPU data as base if available, otherwise use random data + const baseCpu = systemData?.cpu_usage || 60 cpuData.push({ time, - value: Math.floor(Math.random() * 40) + 40, // 40-80% + value: Math.max(0, Math.min(100, baseCpu + (Math.random() - 0.5) * 20)), }) + // Use real memory data as base if available + const baseMemory = systemData?.memory_used || 15.8 + const totalMemory = systemData?.memory_total || 32 memoryData.push({ time, - used: 12 + Math.random() * 8, // 12-20 GB - available: 32 - (12 + Math.random() * 8), // Resto disponible + used: Math.max(0, baseMemory + (Math.random() - 0.5) * 4), + available: Math.max(0, totalMemory - (baseMemory + (Math.random() - 0.5) * 4)), }) } @@ -114,43 +156,63 @@ const generateChartData = () => { } export function SystemOverview() { - const [systemData, setSystemData] = useState(generateRealtimeData()) - const [vmData, setVmData] = useState(staticVMData) + const [systemData, setSystemData] = useState(null) + const [vmData, setVmData] = useState([]) const [chartData, setChartData] = useState(generateChartData()) const [loading, setLoading] = useState(true) + const [isDemo, setIsDemo] = useState(false) // Added demo mode state useEffect(() => { - const timer = setTimeout(() => { - setLoading(false) - }, 1000) + const fetchData = async () => { + try { + setLoading(true) + + const [systemResult, vmResult] = await Promise.all([fetchSystemData(), fetchVMData()]) + + setSystemData(systemResult.data) + setVmData(vmResult.data) + setIsDemo(systemResult.isDemo || vmResult.isDemo) // Set demo mode if either fetch is demo + + if (systemResult.data) { + setChartData(generateChartData(systemResult.data)) + } + } catch (err) { + console.error("[v0] Error fetching data:", err) + const fallbackData = generateDemoSystemData() + setSystemData(fallbackData) + setVmData(demVMData) + setChartData(generateChartData(fallbackData)) + setIsDemo(true) + } finally { + setLoading(false) + } + } + + fetchData() const interval = setInterval(() => { - setSystemData(generateRealtimeData()) - setChartData(generateChartData()) - }, 5000) // Actualizar cada 5 segundos + if (!isDemo) { + fetchData() + } else { + // In demo mode, just update with new random data + const newDemoData = generateDemoSystemData() + setSystemData(newDemoData) + setChartData(generateChartData(newDemoData)) + } + }, 5000) // Update every 5 seconds instead of 30 return () => { - clearTimeout(timer) clearInterval(interval) } - }, []) - - const vmStats = { - total: vmData.length, - running: vmData.filter((vm) => vm.status === "running").length, - stopped: vmData.filter((vm) => vm.status === "stopped").length, - lxc: 0, - } - - const getTemperatureStatus = (temp: number) => { - if (temp < 60) return { status: "Normal", color: "bg-green-500/10 text-green-500 border-green-500/20" } - if (temp < 75) return { status: "Warm", color: "bg-yellow-500/10 text-yellow-500 border-yellow-500/20" } - return { status: "Hot", color: "bg-red-500/10 text-red-500 border-red-500/20" } - } + }, [isDemo]) if (loading) { return (
+
+
Connecting to ProxMenux Monitor...
+
Fetching real-time system data
+
{[...Array(4)].map((_, i) => ( @@ -167,10 +229,39 @@ export function SystemOverview() { ) } + if (!systemData) return null + + const vmStats = { + total: vmData.length, + running: vmData.filter((vm) => vm.status === "running").length, + stopped: vmData.filter((vm) => vm.status === "stopped").length, + lxc: 0, + } + + const getTemperatureStatus = (temp: number) => { + if (temp < 60) return { status: "Normal", color: "bg-green-500/10 text-green-500 border-green-500/20" } + if (temp < 75) return { status: "Warm", color: "bg-yellow-500/10 text-yellow-500 border-yellow-500/20" } + return { status: "Hot", color: "bg-red-500/10 text-red-500 border-red-500/20" } + } + const tempStatus = getTemperatureStatus(systemData.temperature) return (
+ {isDemo && ( + + +
+ + + Demo Mode: Flask server not available. Showing simulated data for development. In the + AppImage, this will connect to the real Flask server. + +
+
+
+ )} + {/* Key Metrics Cards */}
@@ -182,7 +273,7 @@ export function SystemOverview() {
{systemData.cpu_usage}%

- ↓ 2.1% from last hour + {isDemo ? "Simulated data" : "Real-time data from Flask server"}

@@ -198,8 +289,7 @@ export function SystemOverview() {

- {systemData.memory_usage.toFixed(1)}% of {systemData.memory_total} GB •{" "} - ↑ 1.2 GB + {systemData.memory_usage.toFixed(1)}% of {systemData.memory_total} GB

@@ -216,7 +306,9 @@ export function SystemOverview() { {tempStatus.status}
-

Max: 78°C • Avg: 48°C

+

+ {isDemo ? "Simulated temperature" : "Live temperature reading"} +

@@ -322,16 +414,18 @@ export function SystemOverview() { {systemData.hostname}
- Version: - PVE 8.1.3 + Uptime: + {systemData.uptime}
- Kernel: - 6.5.11-7-pve + Node ID: + {systemData.node_id}
- Architecture: - x86_64 + Last Update: + + {new Date(systemData.timestamp).toLocaleTimeString()} +