Update AppImage

This commit is contained in:
MacRimi
2025-10-26 22:30:14 +01:00
parent 2d4833d199
commit 87f9b2b72c
3 changed files with 78 additions and 29 deletions

View File

@@ -63,9 +63,14 @@ export function ProxmoxDashboard() {
const [lastScrollY, setLastScrollY] = useState(0) const [lastScrollY, setLastScrollY] = useState(0)
const fetchSystemData = useCallback(async () => { const fetchSystemData = useCallback(async () => {
console.log("[v0] Fetching system data from Flask server...")
console.log("[v0] Current window location:", window.location.href)
const baseUrl = typeof window !== "undefined" ? `${window.location.protocol}//${window.location.hostname}:8008` : "" const baseUrl = typeof window !== "undefined" ? `${window.location.protocol}//${window.location.hostname}:8008` : ""
const apiUrl = `${baseUrl}/api/system` const apiUrl = `${baseUrl}/api/system`
console.log("[v0] API URL:", apiUrl)
try { try {
const response = await fetch(apiUrl, { const response = await fetch(apiUrl, {
method: "GET", method: "GET",
@@ -74,12 +79,14 @@ export function ProxmoxDashboard() {
}, },
cache: "no-store", cache: "no-store",
}) })
console.log("[v0] Response status:", response.status)
if (!response.ok) { if (!response.ok) {
throw new Error(`Server responded with status: ${response.status}`) throw new Error(`Server responded with status: ${response.status}`)
} }
const data: FlaskSystemData = await response.json() const data: FlaskSystemData = await response.json()
console.log("[v0] System data received:", data)
let status: "healthy" | "warning" | "critical" = "healthy" let status: "healthy" | "warning" | "critical" = "healthy"
if (data.cpu_usage > 90 || data.memory_usage > 90) { if (data.cpu_usage > 90 || data.memory_usage > 90) {
@@ -97,6 +104,13 @@ export function ProxmoxDashboard() {
}) })
setIsServerConnected(true) setIsServerConnected(true)
} catch (error) { } catch (error) {
console.error("[v0] Failed to fetch system data from Flask server:", error)
console.error("[v0] Error details:", {
message: error instanceof Error ? error.message : "Unknown error",
apiUrl,
windowLocation: window.location.href,
})
setIsServerConnected(false) setIsServerConnected(false)
setSystemStatus((prev) => ({ setSystemStatus((prev) => ({
...prev, ...prev,
@@ -234,7 +248,9 @@ export function ProxmoxDashboard() {
<header className="border-b border-border bg-card sticky top-0 z-50 shadow-sm"> <header className="border-b border-border bg-card sticky top-0 z-50 shadow-sm">
<div className="container mx-auto px-4 md:px-6 py-4 md:py-4"> <div className="container mx-auto px-4 md:px-6 py-4 md:py-4">
{/* Logo and Title */}
<div className="flex items-start justify-between gap-3"> <div className="flex items-start justify-between gap-3">
{/* Logo and Title */}
<div className="flex items-center space-x-2 md:space-x-3 min-w-0"> <div className="flex items-center space-x-2 md:space-x-3 min-w-0">
<div className="w-16 h-16 md:w-10 md:h-10 relative flex items-center justify-center bg-primary/10 flex-shrink-0"> <div className="w-16 h-16 md:w-10 md:h-10 relative flex items-center justify-center bg-primary/10 flex-shrink-0">
<Image <Image
@@ -245,6 +261,7 @@ export function ProxmoxDashboard() {
className="object-contain md:w-10 md:h-10" className="object-contain md:w-10 md:h-10"
priority priority
onError={(e) => { onError={(e) => {
console.log("[v0] Logo failed to load, using fallback icon")
const target = e.target as HTMLImageElement const target = e.target as HTMLImageElement
target.style.display = "none" target.style.display = "none"
const fallback = target.parentElement?.querySelector(".fallback-icon") const fallback = target.parentElement?.querySelector(".fallback-icon")
@@ -265,6 +282,7 @@ export function ProxmoxDashboard() {
</div> </div>
</div> </div>
{/* Desktop Actions */}
<div className="hidden lg:flex items-center space-x-4"> <div className="hidden lg:flex items-center space-x-4">
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<Server className="h-4 w-4 text-muted-foreground" /> <Server className="h-4 w-4 text-muted-foreground" />
@@ -294,6 +312,7 @@ export function ProxmoxDashboard() {
<ThemeToggle /> <ThemeToggle />
</div> </div>
{/* Mobile Actions */}
<div className="flex lg:hidden items-center gap-2"> <div className="flex lg:hidden items-center gap-2">
<Badge variant="outline" className={`${statusColor} text-xs px-2`}> <Badge variant="outline" className={`${statusColor} text-xs px-2`}>
{statusIcon} {statusIcon}
@@ -308,6 +327,7 @@ export function ProxmoxDashboard() {
</div> </div>
</div> </div>
{/* Mobile Server Info */}
<div className="lg:hidden mt-2 flex items-center justify-end text-xs text-muted-foreground"> <div className="lg:hidden mt-2 flex items-center justify-end text-xs text-muted-foreground">
<span className="whitespace-nowrap">Uptime: {systemStatus.uptime}</span> <span className="whitespace-nowrap">Uptime: {systemStatus.uptime}</span>
</div> </div>

View File

@@ -109,12 +109,13 @@ const fetchSystemData = async (): Promise<SystemData | null> => {
}) })
if (!response.ok) { if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`) throw new Error(`Flask server responded with status: ${response.status}`)
} }
const data = await response.json() const data = await response.json()
return data return data
} catch (error) { } catch (error) {
console.error("[v0] Failed to fetch system data:", error)
return null return null
} }
} }
@@ -133,12 +134,13 @@ const fetchVMData = async (): Promise<VMData[]> => {
}) })
if (!response.ok) { if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`) throw new Error(`Flask server responded with status: ${response.status}`)
} }
const data = await response.json() const data = await response.json()
return data.vms || [] return Array.isArray(data) ? data : data.vms || []
} catch (error) { } catch (error) {
console.error("[v0] Failed to fetch VM data:", error)
return [] return []
} }
} }
@@ -157,12 +159,40 @@ const fetchStorageData = async (): Promise<StorageData | null> => {
}) })
if (!response.ok) { if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`) console.log("[v0] Storage API not available (this is normal if not configured)")
return null
} }
const data = await response.json() const data = await response.json()
return data return data
} catch (error) { } catch (error) {
console.log("[v0] Storage data unavailable:", error instanceof Error ? error.message : "Unknown error")
return null
}
}
const fetchNetworkData = async (): Promise<NetworkData | null> => {
try {
const baseUrl = typeof window !== "undefined" ? `${window.location.protocol}//${window.location.hostname}:8008` : ""
const apiUrl = `${baseUrl}/api/network`
const response = await fetch(apiUrl, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
cache: "no-store",
})
if (!response.ok) {
console.log("[v0] Network API not available (this is normal if not configured)")
return null
}
const data = await response.json()
return data
} catch (error) {
console.log("[v0] Network data unavailable:", error instanceof Error ? error.message : "Unknown error")
return null return null
} }
} }
@@ -193,30 +223,6 @@ const fetchProxmoxStorageData = async (): Promise<ProxmoxStorageData | null> =>
} }
} }
const fetchNetworkData = async (): Promise<NetworkData | null> => {
try {
const baseUrl = typeof window !== "undefined" ? `${window.location.protocol}//${window.location.hostname}:8008` : ""
const apiUrl = `${baseUrl}/api/network`
const response = await fetch(apiUrl, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
cache: "no-store",
})
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
const data = await response.json()
return data
} catch (error) {
return null
}
}
export function SystemOverview() { export function SystemOverview() {
const [systemData, setSystemData] = useState<SystemData | null>(null) const [systemData, setSystemData] = useState<SystemData | null>(null)
const [vmData, setVmData] = useState<VMData[]>([]) const [vmData, setVmData] = useState<VMData[]>([])

View File

@@ -1087,7 +1087,7 @@ def get_smart_data(disk_name):
smart_data['media_wearout_indicator'] = wear_used smart_data['media_wearout_indicator'] = wear_used
smart_data['ssd_life_left'] = max(0, 100 - wear_used) smart_data['ssd_life_left'] = max(0, 100 - wear_used)
print(f"[v0] Media Wearout Indicator (ID 230): {smart_data['media_wearout_indicator']}% used, {smart_data['ssd_life_left']}% life left") print(f"[v0] Media Wearout Indicator (ID 230): {wear_used}% used, {smart_data['ssd_life_left']}% life left")
except Exception as e: except Exception as e:
print(f"[v0] Error parsing Media_Wearout_Indicator (ID 230): {e}") print(f"[v0] Error parsing Media_Wearout_Indicator (ID 230): {e}")
elif attr_id == '233': # Media_Wearout_Indicator (Intel/Samsung SSD) elif attr_id == '233': # Media_Wearout_Indicator (Intel/Samsung SSD)
@@ -2806,6 +2806,26 @@ def get_detailed_gpu_info(gpu):
detailed_info['utilization_memory'] = round(mem_util, 1) detailed_info['utilization_memory'] = round(mem_util, 1)
print(f"[v0] Memory Utilization: {detailed_info['utilization_memory']}%", flush=True) print(f"[v0] Memory Utilization: {detailed_info['utilization_memory']}%", flush=True)
# Parse GRBM (Graphics Register Bus Manager) for engine utilization
if 'GRBM' in device:
grbm = device['GRBM']
# Graphics Pipe (similar to Render/3D)
if 'Graphics Pipe' in grbm:
gfx_pipe = grbm['Graphics Pipe']
if 'value' in gfx_pipe:
detailed_info['engine_render'] = f"{gfx_pipe['value']:.1f}%"
# Parse GRBM2 for additional engine info
if 'GRBM2' in device:
grbm2 = device['GRBM2']
# Texture Cache (similar to Blitter)
if 'Texture Cache' in grbm2:
tex_cache = grbm2['Texture Cache']
if 'value' in tex_cache:
detailed_info['engine_blitter'] = f"{tex_cache['value']:.1f}%"
# Parse processes (fdinfo) # Parse processes (fdinfo)
if 'fdinfo' in device: if 'fdinfo' in device:
fdinfo = device['fdinfo'] fdinfo = device['fdinfo']
@@ -3871,11 +3891,14 @@ def api_network_interface_metrics(interface_name):
print(f"[v0] ===== NETWORK INTERFACE METRICS REQUEST EXCEPTION =====") print(f"[v0] ===== NETWORK INTERFACE METRICS REQUEST EXCEPTION =====")
return jsonify({'error': str(e)}), 500 return jsonify({'error': str(e)}), 500
# ... existing code ...
@app.route('/api/vms', methods=['GET']) @app.route('/api/vms', methods=['GET'])
def api_vms(): def api_vms():
"""Get virtual machine information""" """Get virtual machine information"""
return jsonify(get_proxmox_vms()) return jsonify(get_proxmox_vms())
# Add the new api_vm_metrics endpoint here
@app.route('/api/vms/<int:vmid>/metrics', methods=['GET']) @app.route('/api/vms/<int:vmid>/metrics', methods=['GET'])
def api_vm_metrics(vmid): def api_vm_metrics(vmid):
"""Get historical metrics (RRD data) for a specific VM/LXC""" """Get historical metrics (RRD data) for a specific VM/LXC"""