From dc6813d55372afecb7bbe9fe51e3d0992bc79753 Mon Sep 17 00:00:00 2001 From: "courtmanr@gmail.com" Date: Wed, 28 May 2025 13:37:28 +0100 Subject: [PATCH] Fix multiple PBS instances display issue after merge - Enhanced backup source detection to handle both PBS and PVE backups - Added support for mixed backup sources (PBS + PVE) - Improved tooltip information for multiple PBS instances - Preserves snapshot functionality from the feature branch --- src/public/js/ui/backups.js | 91 +++++++++++++++++++++++++++++++++---- 1 file changed, 83 insertions(+), 8 deletions(-) diff --git a/src/public/js/ui/backups.js b/src/public/js/ui/backups.js index 1b0173d4c..4ea40c772 100644 --- a/src/public/js/ui/backups.js +++ b/src/public/js/ui/backups.js @@ -244,18 +244,91 @@ PulseApp.ui.backups = (() => { return dailyStatus; }); - // Determine backup source and location + // Determine backup source and location with support for multiple PBS instances let backupSource = 'N/A'; + let backupSourceTitle = ''; let backupLocation = 'N/A'; + let backupLocationTitle = ''; - if (latestSnapshot || latestTask) { - const source = latestSnapshot?.source || latestTask?.source; + if (guestSnapshots && guestSnapshots.length > 0) { + // Separate PBS and PVE snapshots + const pbsSnapshots = guestSnapshots.filter(s => s.source === 'pbs'); + const pveSnapshots = guestSnapshots.filter(s => s.source === 'pve'); + + if (pbsSnapshots.length > 0 && pveSnapshots.length > 0) { + // Mixed sources + backupSource = `Mixed (PBS+PVE)`; + backupSourceTitle = `${pbsSnapshots.length} PBS backups, ${pveSnapshots.length} PVE backups`; + + // For location, show both PBS datastores and PVE storages + const pbsDatastores = [...new Set(pbsSnapshots.map(s => s.datastoreName).filter(Boolean))]; + const pveStorages = [...new Set(pveSnapshots.map(s => s.storage).filter(Boolean))]; + const allLocations = [...pbsDatastores, ...pveStorages]; + + if (allLocations.length === 1) { + backupLocation = allLocations[0]; + } else if (allLocations.length > 1) { + backupLocation = `Multiple (${allLocations.length})`; + backupLocationTitle = allLocations.join(', '); + } + } else if (pbsSnapshots.length > 0) { + // Only PBS backups - use enhanced PBS logic + const pbsInstances = [...new Set(pbsSnapshots.map(s => s.pbsInstanceName).filter(Boolean))]; + const datastores = [...new Set(pbsSnapshots.map(s => s.datastoreName).filter(Boolean))]; + + // Group backups by PBS instance for detailed info + const backupsByPbs = {}; + pbsSnapshots.forEach(snap => { + if (snap.pbsInstanceName) { + if (!backupsByPbs[snap.pbsInstanceName]) { + backupsByPbs[snap.pbsInstanceName] = { count: 0, datastores: new Set() }; + } + backupsByPbs[snap.pbsInstanceName].count++; + if (snap.datastoreName) { + backupsByPbs[snap.pbsInstanceName].datastores.add(snap.datastoreName); + } + } + }); + + if (pbsInstances.length === 1) { + backupSource = pbsInstances[0]; + } else if (pbsInstances.length > 1) { + backupSource = `Multiple PBS (${pbsInstances.length})`; + const details = pbsInstances.map(pbs => { + const info = backupsByPbs[pbs]; + return `${pbs}: ${info.count} backups`; + }).join(', '); + backupSourceTitle = details; + } + + if (datastores.length === 1) { + backupLocation = datastores[0]; + } else if (datastores.length > 1) { + backupLocation = `Multiple (${datastores.length})`; + backupLocationTitle = datastores.join(', '); + } + } else if (pveSnapshots.length > 0) { + // Only PVE backups + backupSource = 'PVE'; + const storages = [...new Set(pveSnapshots.map(s => s.storage).filter(Boolean))]; + + if (storages.length === 1) { + backupLocation = storages[0]; + } else if (storages.length > 1) { + backupLocation = `Multiple (${storages.length})`; + backupLocationTitle = storages.join(', '); + } else { + backupLocation = 'Local'; + } + } + } else if (latestTask) { + // Fallback to task data if no snapshots + const source = latestTask.source; if (source === 'pbs') { - backupSource = latestSnapshot?.pbsInstanceName || latestTask?.pbsInstanceName || 'PBS'; - backupLocation = latestSnapshot?.datastoreName || 'N/A'; + backupSource = latestTask.pbsInstanceName || 'PBS'; } else if (source === 'pve') { backupSource = 'PVE'; - backupLocation = latestSnapshot?.storage || latestTask?.node || 'Local'; + backupLocation = latestTask.node || 'Local'; } } @@ -267,7 +340,9 @@ PulseApp.ui.backups = (() => { guestPveStatus: guest.status, latestBackupTime: displayTimestamp, pbsInstanceName: backupSource, + pbsInstanceTitle: backupSourceTitle, datastoreName: backupLocation, + datastoreTitle: backupLocationTitle, totalBackups: totalBackups, backupHealthStatus: healthStatus, last7DaysBackupStatus: last7DaysBackupStatus, @@ -359,8 +434,8 @@ PulseApp.ui.backups = (() => { ${typeIcon} ${guestStatus.node} ${latestBackupFormatted} - ${guestStatus.pbsInstanceName} - ${guestStatus.datastoreName} + ${guestStatus.pbsInstanceName} + ${guestStatus.datastoreName} ${guestStatus.totalBackups} ${snapshotCell} ${sevenDayDots}