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 = `
-
-
-
- ${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('')}
-
-
- Clear Results
- Refresh View
-
-
- `;
-
- // 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;