diff --git a/static/app.js b/static/app.js index 50b038b..ddd681c 100644 --- a/static/app.js +++ b/static/app.js @@ -216,6 +216,8 @@ function initStatusPage(jobId, initialStatus) { var terminalStates = ['COMPLETED', 'FAILED', 'CANCELLED']; var pollInterval = null; var previewInterval = null; + var consecutiveFailures = 0; + var connectionLostIndicator = null; if (!progressFill) return; @@ -224,6 +226,8 @@ function initStatusPage(jobId, initialStatus) { fetch('/api/jobs/' + jobId) .then(function (res) { return res.json(); }) .then(function (data) { + consecutiveFailures = 0; + if (connectionLostIndicator) { connectionLostIndicator.style.display = 'none'; } updateProgressBar(data.progress || 0); updateStatusBadge(data.status); updateModelName(data.current_model); @@ -242,7 +246,14 @@ function initStatusPage(jobId, initialStatus) { } }) .catch(function () { - /* network hiccup — keep polling */ + consecutiveFailures++; + if (consecutiveFailures >= 5 && !connectionLostIndicator) { + connectionLostIndicator = document.createElement('div'); + connectionLostIndicator.className = 'card'; + connectionLostIndicator.style.cssText = 'padding:0.75rem 1rem;color:#b91c1c;background:#fef2f2;border-left:3px solid #b91c1c;font-size:0.875rem;'; + connectionLostIndicator.textContent = 'Connection lost. Retrying...'; + progressFill.closest('.card').parentNode.insertBefore(connectionLostIndicator, progressFill.closest('.card').nextSibling); + } }); } @@ -310,10 +321,10 @@ function initStatusPage(jobId, initialStatus) { '
' + 'Batches: ' + r.batch_count + '' + 'Frames: ' + r.frame_count + '' + - 'Duration: ' + r.duration_seconds.toFixed(1) + 's' + + 'Duration: ' + (r.duration_seconds || 0).toFixed(1) + 's' + '
'; if (r.output_path) { - card.innerHTML += 'Download'; + card.innerHTML += 'Download'; } resultsGrid.appendChild(card); }); diff --git a/templates/status.html b/templates/status.html index e1efcd4..b602a84 100644 --- a/templates/status.html +++ b/templates/status.html @@ -29,7 +29,7 @@ {% endif %} -
+

Live Preview

Annotated frame from processing