diff --git a/src/public/app.js b/src/public/app.js index a4ebb719b..bcc556bc8 100644 --- a/src/public/app.js +++ b/src/public/app.js @@ -1720,7 +1720,7 @@ document.addEventListener('DOMContentLoaded', function() { const getPbsGcStatusText = (gcStatus) => { // Handle falsy values, 'unknown', or literal 'N/A' string if (!gcStatus || gcStatus === 'unknown' || gcStatus === 'N/A') { - return 'Unknown'; + return '-'; // Changed from "Unknown" } // Determine color based on known status keywords let colorClass = 'text-gray-600 dark:text-gray-400'; @@ -1768,80 +1768,141 @@ document.addEventListener('DOMContentLoaded', function() { } } - // --- NEW Function to Populate a PBS Task Table --- // MOVED UP & MODIFIED + // ---> ADDED: Helper to parse PBS task target string <--- + const parsePbsTaskTarget = (task) => { + const workerId = task.worker_id || task.id || ''; // e.g., guests:ct/103/681078F1 or hosts:host/bkp-2024-05-15 or guests::ct/103 + const taskType = task.worker_type || task.type || ''; // e.g., backup, verify, prune, garbage_collection + + // Default + let displayTarget = workerId; + + if (taskType === 'backup' || taskType === 'verify') { + // Format: datastore:type/id/snapshot or datastore:host/id + const parts = workerId.split(':'); + if (parts.length >= 2) { + const targetPart = parts[1]; // e.g., ct/103/681078F1 or host/bkp-2024-05-15 + const targetSubParts = targetPart.split('/'); + if (targetSubParts.length >= 2) { + // Try to get guest type and ID (e.g., ct/103 -> type=ct, id=103) + const guestType = targetSubParts[0]; // ct or vm or host + const guestId = targetSubParts[1]; // 103 or bkp-2024-05-15 + displayTarget = `${guestType}/${guestId}`; + } + } + } else if (taskType === 'prune' || taskType === 'garbage_collection') { + // Format: datastore::group or datastore:group + const parts = workerId.split('::'); // Try double colon first for prune groups + if (parts.length === 2) { + displayTarget = `Prune ${parts[0]} (${parts[1]})`; // e.g., Prune guests (ct/103) + } else { + const singleColonParts = workerId.split(':'); // Fallback for GC datastore + if (singleColonParts.length === 1 && workerId !== '') { // GC often just has datastore name + displayTarget = `GC ${workerId}`; + } else if (singleColonParts.length >= 2) { + displayTarget = `Prune ${singleColonParts[0]} (${singleColonParts[1]})` // Fallback prune format? + } + } + } else if (taskType === 'sync') { + // Often just job id? Example: job_id + displayTarget = `Sync Job: ${workerId}`; + } + + // TODO: Add guest name lookup here in the future if possible + // Maybe: find guest name from vmsData/containersData based on parsed type/id + + return displayTarget; // Return the parsed or original string + }; + // ---> END ADDED <--- + + // Function to populate a specific PBS task table function populatePbsTaskTable(parentSectionElement, fullTasksArray) { if (!parentSectionElement) { - console.error("Parent section element not provided to populatePbsTaskTable."); + console.warn('[PBS UI] Parent element not found for task table'); return; } - // Find elements relative to the parent section - const tbody = parentSectionElement.querySelector('.pbs-task-tbody'); - const buttonContainer = parentSectionElement.querySelector('.pbs-toggle-button-container'); + const tableBody = parentSectionElement.querySelector('tbody'); + const showMoreButton = parentSectionElement.querySelector('.pbs-show-more'); + const noTasksMessage = parentSectionElement.querySelector('.pbs-no-tasks'); - if (!tbody || !buttonContainer) { - // If elements aren't found *within the parent*, log an error - console.error(`Required child elements (.pbs-task-tbody or .pbs-toggle-button-container) not found within provided parent section.`, parentSectionElement); - return; + if (!tableBody) { + console.warn('[PBS UI] Table body not found within', parentSectionElement); + return; // Exit if table body doesn't exist } - // Ensure tbody has an ID if it doesn't (needed for button linking) - if (!tbody.id) { - const table = parentSectionElement.querySelector('table'); - tbody.id = table && table.id ? table.id.replace('-table-', '-tbody-') : `pbs-tbody-${Date.now()}-${Math.random()}`; - console.warn(`Assigned dynamic ID to tbody: ${tbody.id}`); - } - - tbody.innerHTML = ''; // Clear previous content - buttonContainer.innerHTML = ''; // Clear previous button + // Clear previous rows + tableBody.innerHTML = ''; const tasks = fullTasksArray || []; // Ensure tasks is an array - const totalTasks = tasks.length; - const limit = INITIAL_PBS_TASK_LIMIT; - const isCurrentlyExpanded = tbody.dataset.isExpanded === 'true'; // Check current state + let displayedTasks = tasks.slice(0, INITIAL_PBS_TASK_LIMIT); - const tasksToDisplay = isCurrentlyExpanded ? tasks : tasks.slice(0, limit); - - // Store full data and state on the tbody - tbody.dataset.fullTasks = JSON.stringify(tasks); // Store all tasks - tbody.dataset.initialLimit = limit; - tbody.dataset.isExpanded = isCurrentlyExpanded ? 'true' : 'false'; - - if (tasksToDisplay.length === 0) { - tbody.innerHTML = `