diff --git a/public/script.js b/public/script.js index dbd79dc..edd23e0 100644 --- a/public/script.js +++ b/public/script.js @@ -1116,63 +1116,49 @@ function updateMultiNodeProgress(successfulUploads, totalNodes) { // Display firmware upload results function displayFirmwareUploadResults(results) { - const container = document.getElementById('firmware-nodes-list'); + // No need to display separate results widget - the progress area already shows all the information + // Just update the progress area to show final status + const progressHeader = document.querySelector('.progress-header h3'); + const progressSummary = document.getElementById('progress-summary'); - const successCount = results.filter(r => r.success).length; - const failureCount = results.filter(r => !r.success).length; - - const resultsHTML = ` -
-
-

📊 Upload Results

-
- ✅ ${successCount} Successful - ❌ ${failureCount} Failed - 📊 ${results.length} Total -
-
-
- ${results.map(result => ` -
-
- ${result.hostname || result.nodeIp} - ${result.nodeIp} -
-
- ${result.success ? '✅ Success' : '❌ Failed'} -
-
- ${result.success ? - `Uploaded successfully at ${new Date(result.timestamp).toLocaleTimeString()}` : - `Error: ${result.error}` - } -
-
- `).join('')} -
-
- - -
-
- `; - - // Append results below the progress area instead of replacing everything - // First, check if there's already a results section and remove it - const existingResults = container.querySelector('#firmware-upload-results'); - if (existingResults) { - existingResults.remove(); + if (progressHeader && progressSummary) { + const successCount = results.filter(r => r.success).length; + const totalCount = results.length; + const successRate = Math.round((successCount / totalCount) * 100); + + if (successCount === totalCount) { + progressHeader.textContent = `📤 Firmware Upload Complete (${successCount}/${totalCount} Successful)`; + progressSummary.innerHTML = `✅ All uploads completed successfully at ${new Date().toLocaleTimeString()}`; + } else { + progressHeader.textContent = `📤 Firmware Upload Results (${successCount}/${totalCount} Successful)`; + progressSummary.innerHTML = `⚠️ Upload completed with ${totalCount - successCount} failure(s) at ${new Date().toLocaleTimeString()}`; + } } - - // Append the new results below the progress area - container.insertAdjacentHTML('beforeend', resultsHTML); } // Clear firmware upload results function clearFirmwareResults() { - const resultsSection = document.getElementById('firmware-upload-results'); - if (resultsSection) { - resultsSection.remove(); + const container = document.getElementById('firmware-nodes-list'); + container.innerHTML = ''; +} + +// Add refresh button to progress area +function addRefreshButtonToProgress() { + const progressHeader = document.querySelector('.progress-header'); + if (progressHeader && !progressHeader.querySelector('.progress-refresh-btn')) { + const refreshBtn = document.createElement('button'); + refreshBtn.className = 'progress-refresh-btn'; + refreshBtn.innerHTML = ` + + + + + `; + refreshBtn.title = 'Refresh firmware view'; + refreshBtn.onclick = refreshFirmwareView; + + // Add the refresh button to the header + progressHeader.appendChild(refreshBtn); } } @@ -1203,6 +1189,7 @@ function populateNodeSelect() { function refreshFirmwareView() { updateFirmwareStats(); populateNodeSelect(); + addRefreshButtonToProgress(); // Add refresh button after populating nodes } // Update firmware statistics diff --git a/public/styles.css b/public/styles.css index fd6c68c..d23bf86 100644 --- a/public/styles.css +++ b/public/styles.css @@ -1132,6 +1132,37 @@ p { font-weight: 600; } +.progress-header { + position: relative; +} + +.progress-refresh-btn { + position: absolute; + top: 0; + right: 0; + background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.05) 100%); + border: 1px solid rgba(255, 255, 255, 0.15); + color: rgba(255, 255, 255, 0.9); + padding: 0.5rem; + border-radius: 8px; + cursor: pointer; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + display: flex; + align-items: center; + justify-content: center; +} + +.progress-refresh-btn:hover { + background: linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.08) 100%); + border-color: rgba(255, 255, 255, 0.25); + transform: translateY(-1px); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); +} + +.progress-refresh-btn:active { + transform: translateY(0); +} + .progress-info, .results-summary { display: flex;