diff --git a/public/script.js b/public/script.js index 2956289..dbd79dc 100644 --- a/public/script.js +++ b/public/script.js @@ -791,8 +791,8 @@ async function uploadFirmwareToSpecificNode(file, nodeIp) { // Show upload progress area showFirmwareUploadProgress(file, [{ ip: nodeIp, hostname: nodeIp }]); - // Perform single node upload - const result = await performSingleFirmwareUpload(file, nodeIp); + // Perform single node upload with progress tracking + const result = await performSingleFirmwareUploadWithProgress(file, nodeIp); // Display results displayFirmwareUploadResults([result]); @@ -807,21 +807,24 @@ async function uploadFirmwareToSpecificNode(file, nodeIp) { async function performBatchFirmwareUpload(file, nodes) { const results = []; const totalNodes = nodes.length; + let successfulUploads = 0; for (let i = 0; i < nodes.length; i++) { const node = nodes[i]; const nodeIp = node.ip; try { - // Update progress + // Update progress - show current node being processed updateFirmwareUploadProgress(i + 1, totalNodes, nodeIp, 'Uploading...'); // Upload to this node const result = await performSingleFirmwareUpload(file, nodeIp); results.push(result); + successfulUploads++; - // Update progress + // Update progress - show completion and update progress bar with actual success rate updateFirmwareUploadProgress(i + 1, totalNodes, nodeIp, 'Completed'); + updateMultiNodeProgress(successfulUploads, totalNodes); } catch (error) { console.error(`Failed to upload to node ${nodeIp}:`, error); @@ -834,8 +837,9 @@ async function performBatchFirmwareUpload(file, nodes) { }; results.push(errorResult); - // Update progress + // Update progress - show failure and update progress bar with actual success rate updateFirmwareUploadProgress(i + 1, totalNodes, nodeIp, 'Failed'); + updateMultiNodeProgress(successfulUploads, totalNodes); } // Small delay between uploads to avoid overwhelming the network @@ -844,6 +848,9 @@ async function performBatchFirmwareUpload(file, nodes) { } } + // Update final progress based on successful uploads + updateFinalProgress(successfulUploads, totalNodes); + return results; } @@ -880,6 +887,102 @@ async function performSingleFirmwareUpload(file, nodeIp) { } } +// Perform single firmware upload to a specific node with progress tracking +async function performSingleFirmwareUploadWithProgress(file, nodeIp) { + try { + // Simulate upload progress for single node + await simulateUploadProgress(nodeIp); + + // Create FormData for the upload + const formData = new FormData(); + formData.append('file', file); + + // Upload to backend + const response = await fetch(`/api/node/update?ip=${encodeURIComponent(nodeIp)}`, { + method: 'POST', + body: formData + }); + + if (!response.ok) { + const errorData = await response.json(); + throw new Error(errorData.message || `HTTP ${response.status}: ${response.statusText}`); + } + + const result = await response.json(); + + return { + nodeIp: nodeIp, + hostname: nodeIp, // Will be updated if we have more info + success: true, + result: result, + timestamp: new Date().toISOString() + }; + + } catch (error) { + throw new Error(`Upload to ${nodeIp} failed: ${error.message}`); + } +} + +// Simulate upload progress for single node uploads +async function simulateUploadProgress(nodeIp) { + const progressSteps = [10, 25, 50, 75, 90, 100]; + const totalSteps = progressSteps.length; + + for (let i = 0; i < totalSteps; i++) { + const progress = progressSteps[i]; + updateSingleNodeProgress(progress, nodeIp); + + // Wait a bit between progress updates (simulating actual upload time) + if (i < totalSteps - 1) { + await new Promise(resolve => setTimeout(resolve, 300)); + } + } +} + +// Update progress for single node uploads +function updateSingleNodeProgress(percentage, nodeIp) { + const progressBar = document.getElementById('overall-progress-bar'); + const progressText = document.querySelector('.progress-text'); + + if (progressBar && progressText) { + progressBar.style.width = `${percentage}%`; + progressText.textContent = `${percentage}% Complete`; + + // Update progress bar color based on completion + if (percentage === 100) { + progressBar.style.backgroundColor = '#4ade80'; + } else if (percentage > 50) { + progressBar.style.backgroundColor = '#60a5fa'; + } else { + progressBar.style.backgroundColor = '#fbbf24'; + } + } +} + +// Update final progress based on successful vs total uploads +function updateFinalProgress(successfulUploads, totalNodes) { + const progressBar = document.getElementById('overall-progress-bar'); + const progressText = document.querySelector('.progress-text'); + const progressHeader = document.querySelector('.progress-header h3'); + + if (progressBar && progressText) { + const successPercentage = Math.round((successfulUploads / totalNodes) * 100); + progressBar.style.width = `${successPercentage}%`; + + if (successfulUploads === totalNodes) { + progressText.textContent = '100% Complete'; + progressBar.style.backgroundColor = '#4ade80'; + } else { + progressText.textContent = `${successfulUploads}/${totalNodes} Successful`; + progressBar.style.backgroundColor = '#f87171'; + } + } + + if (progressHeader) { + progressHeader.textContent = `📤 Firmware Upload Results (${successfulUploads}/${totalNodes} Successful)`; + } +} + // Show firmware upload progress area function showFirmwareUploadProgress(file, nodes) { const container = document.getElementById('firmware-nodes-list'); @@ -895,9 +998,12 @@ function showFirmwareUploadProgress(file, nodes) {