diff --git a/AppImage/components/proxmox-dashboard.tsx b/AppImage/components/proxmox-dashboard.tsx index 4d415e7..edea424 100644 --- a/AppImage/components/proxmox-dashboard.tsx +++ b/AppImage/components/proxmox-dashboard.tsx @@ -455,7 +455,7 @@ export function ProxmoxDashboard() { - + diff --git a/AppImage/components/system-logs.tsx b/AppImage/components/system-logs.tsx index f92e40c..c349e54 100644 --- a/AppImage/components/system-logs.tsx +++ b/AppImage/components/system-logs.tsx @@ -95,7 +95,13 @@ interface CombinedLogEntry { sortTimestamp: number } -export function SystemLogs() { +// ADDED: Props interface +interface SystemLogsProps { + nodeName?: string +} + +// MODIFIED: Added props destructuring +export function SystemLogs({ nodeName }: SystemLogsProps = {}) { const [logs, setLogs] = useState([]) const [backups, setBackups] = useState([]) const [events, setEvents] = useState([]) @@ -121,14 +127,18 @@ export function SystemLogs() { const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false) - const [dateFilter, setDateFilter] = useState("30") // Changed from "now" to "30" to load all recent logs by default + const [dateFilter, setDateFilter] = useState("1") const [customDays, setCustomDays] = useState("1") const getApiUrl = (endpoint: string) => { if (typeof window !== "undefined") { - return `${window.location.protocol}//${window.location.hostname}:8008${endpoint}` + // MODIFIED: Appended nodeName to URL if provided + const baseUrl = `${window.location.protocol}//${window.location.hostname}:8008${endpoint}` + return nodeName ? `${baseUrl}?node=${nodeName}` : baseUrl } - return `http://localhost:8008${endpoint}` + // MODIFIED: Appended nodeName to URL if provided + const baseUrl = `http://localhost:8008${endpoint}` + return nodeName ? `${baseUrl}?node=${nodeName}` : baseUrl } useEffect(() => { @@ -152,7 +162,7 @@ export function SystemLogs() { console.error("[v0] Error loading logs:", err) setLoading(false) }) - }, [dateFilter, customDays]) + }, [dateFilter, customDays, nodeName]) // Added nodeName dependency useEffect(() => { console.log("[v0] Level or service filter changed:", levelFilter, serviceFilter) @@ -174,16 +184,19 @@ export function SystemLogs() { console.error("[v0] Error loading logs:", err) setLoading(false) }) - }, [levelFilter, serviceFilter]) + }, [levelFilter, serviceFilter, nodeName]) // Added nodeName dependency const fetchAllData = async () => { try { setLoading(true) setError(null) + // Similar to how /api/vms filters VMs/LXCs by node. This ensures that in a cluster + // environment, only backups from the current node are displayed. const [logsRes, backupsRes, eventsRes, notificationsRes] = await Promise.all([ fetchSystemLogs(), - fetch(getApiUrl("/api/backups")), + // MODIFIED: getApiUrl will now include nodeName if provided + fetch(getApiUrl("/api/backups")), // Backend should filter by node fetch(getApiUrl("/api/events?limit=50")), fetch(getApiUrl("/api/notifications")), ]) @@ -295,8 +308,8 @@ export function SystemLogs() { if (searchTerm) { filters.push("searched") } - - const filename = `proxmox_logs_${filters.length > 0 ? filters.join("_") + "_" : ""}${new Date().toISOString().split("T")[0]}.txt` + // MODIFIED: Include nodeName in filename if available + const filename = `proxmox_logs${nodeName ? `_${nodeName}` : ""}_${filters.length > 0 ? filters.join("_") + "_" : ""}${new Date().toISOString().split("T")[0]}.txt` // Generate log content const logContent = [ @@ -309,6 +322,8 @@ export function SystemLogs() { `- Level: ${levelFilter === "all" ? "All Levels" : levelFilter}`, `- Service: ${serviceFilter === "all" ? "All Services" : serviceFilter}`, `- Search: ${searchTerm || "None"}`, + // MODIFIED: Include Node in filters if available + nodeName && `- Node: ${nodeName}`, ``, `${"=".repeat(80)}`, ``, @@ -352,6 +367,7 @@ export function SystemLogs() { if (upid) { // Try to fetch the complete task log from Proxmox try { + // MODIFIED: getApiUrl will now include nodeName if provided const response = await fetch(getApiUrl(`/api/task-log/${encodeURIComponent(upid)}`)) if (response.ok) { @@ -439,7 +455,10 @@ export function SystemLogs() { const matchesLevel = levelFilter === "all" || log.level === levelFilter const matchesService = serviceFilter === "all" || log.service === serviceFilter - return matchesSearch && matchesLevel && matchesService + // MODIFIED: Filter by nodeName if provided + const matchesNode = !nodeName || log.source.includes(`Node: ${nodeName}`) + + return matchesSearch && matchesLevel && matchesService && matchesNode }) const displayedLogs = filteredCombinedLogs.slice(0, displayedLogsCount) @@ -536,7 +555,10 @@ export function SystemLogs() { info: logs.filter((log) => ["info", "notice", "debug"].includes(log.level)).length, } - const uniqueServices = [...new Set(logs.map((log) => log.service))] + // MODIFIED: Filter uniqueServices by nodeName if provided + const uniqueServices = [ + ...new Set(logs.filter((log) => !nodeName || log.source.includes(`Node: ${nodeName}`)).map((log) => log.service)), + ] const getBackupType = (volid: string): "vm" | "lxc" => { if (volid.includes("/vm/") || volid.includes("vzdump-qemu")) { @@ -578,14 +600,16 @@ export function SystemLogs() { return type === "pbs" ? "PBS" : "PVE" } + // MODIFIED: Filter backups by nodeName if provided + const filteredBackups = nodeName ? backups.filter((b) => b.storage.includes(nodeName)) : backups const backupStats = { - total: backups.length, - totalSize: backups.reduce((sum, b) => sum + b.size, 0), - qemu: backups.filter((b) => { + total: filteredBackups.length, + totalSize: filteredBackups.reduce((sum, b) => sum + b.size, 0), + qemu: filteredBackups.filter((b) => { // Check if volid contains /vm/ for QEMU or vzdump-qemu for PVE return b.volid.includes("/vm/") || b.volid.includes("vzdump-qemu") }).length, - lxc: backups.filter((b) => { + lxc: filteredBackups.filter((b) => { // Check if volid contains /ct/ for LXC or vzdump-lxc for PVE return b.volid.includes("/ct/") || b.volid.includes("vzdump-lxc") }).length, @@ -629,7 +653,8 @@ export function SystemLogs() { } } - if (loading && logs.length === 0 && events.length === 0) { + // MODIFIED: Conditionally render loading state based on nodeName + if (loading && logs.length === 0 && events.length === 0 && backups.length === 0 && notifications.length === 0) { return (
@@ -639,7 +664,7 @@ export function SystemLogs() { return (
- {loading && (logs.length > 0 || events.length > 0) && ( + {loading && (logs.length > 0 || events.length > 0 || backups.length > 0 || notifications.length > 0) && (
@@ -705,6 +730,8 @@ export function SystemLogs() { System Logs & Events + {/* MODIFIED: Display nodeName if provided */} + {nodeName && ({nodeName})}