Spaces:
Sleeping
Sleeping
| (function () { | |
| function initBatchProgress() { | |
| var page = document.querySelector('.batch-page'); | |
| if (!page) { | |
| return; | |
| } | |
| var statusUrl = page.dataset.statusUrl; | |
| var pollMs = 1000; | |
| var expectedTotal = parseInt(page.dataset.expectedTotal || '0', 10) || 0; | |
| var cancelUrl = page.dataset.cancelUrl; | |
| var title = document.getElementById('batchTitle'); | |
| var subtitle = document.getElementById('batchSubtitle'); | |
| var queueStatus = document.getElementById('queueStatus'); | |
| var fill = document.getElementById('progressFill'); | |
| var pctLabel = document.getElementById('progressPct'); | |
| var currentFile = document.getElementById('currentFile'); | |
| var statTotal = document.getElementById('statTotal'); | |
| var statProc = document.getElementById('statProcessed'); | |
| var statOK = document.getElementById('statSucceeded'); | |
| var statFail = document.getElementById('statFailed'); | |
| var feedPanel = document.getElementById('feedPanel'); | |
| var feedList = document.getElementById('batchFeed'); | |
| var donePanel = document.getElementById('donePanel'); | |
| var doneSummary = document.getElementById('doneSummary'); | |
| var failPanel = document.getElementById('failPanel'); | |
| var failList = document.getElementById('failList'); | |
| var cancelBtn = document.getElementById('cancelBatch'); | |
| var seenIds = new Set(); | |
| var canceled = false; | |
| if (!statusUrl || !title || !subtitle || !fill || !pctLabel || !currentFile || !statTotal || !statProc || !statOK || !statFail || !feedPanel || !feedList || !donePanel || !doneSummary || !failPanel || !failList) { | |
| return; | |
| } | |
| if (cancelBtn && cancelUrl) { | |
| cancelBtn.addEventListener('click', function () { | |
| if (!confirm('Cancel this batch? Any in-progress file may not complete.')) { | |
| return; | |
| } | |
| cancelBtn.disabled = true; | |
| fetch(cancelUrl, { method: 'POST' }) | |
| .then(function (response) { return response.json(); }) | |
| .then(function () { | |
| canceled = true; | |
| title.textContent = 'Batch Canceled'; | |
| subtitle.textContent = 'The batch was canceled. You can start a new upload anytime.'; | |
| currentFile.textContent = ''; | |
| if (queueStatus) { | |
| queueStatus.textContent = ''; | |
| } | |
| }) | |
| .catch(function () { | |
| cancelBtn.disabled = false; | |
| }); | |
| }); | |
| } | |
| function poll() { | |
| fetch(statusUrl) | |
| .then(function (response) { | |
| return response.json(); | |
| }) | |
| .then(function (data) { | |
| if (canceled) { | |
| return; | |
| } | |
| if (data.total > 0 && expectedTotal === 0) { | |
| expectedTotal = data.total; | |
| } | |
| var total = data.total > 0 ? data.total : expectedTotal; | |
| var pct = total > 0 ? Math.round(data.processed / total * 100) : 0; | |
| statTotal.textContent = total; | |
| statProc.textContent = data.processed; | |
| statOK.textContent = data.succeeded; | |
| statFail.textContent = data.failed_ids ? data.failed_ids.length : 0; | |
| if (queueStatus) { | |
| if (typeof data.queue_size === 'number') { | |
| queueStatus.textContent = 'Queue size: ' + data.queue_size; | |
| } else if (data.status === 'pending') { | |
| queueStatus.textContent = 'Queued for processing...'; | |
| } else { | |
| queueStatus.textContent = ''; | |
| } | |
| } | |
| if (data.status === 'pending' && expectedTotal > 0) { | |
| subtitle.textContent = 'Queued - waiting for a worker. Total files: ' + expectedTotal + '.'; | |
| } | |
| fill.style.width = pct + '%'; | |
| pctLabel.textContent = pct + '%'; | |
| currentFile.textContent = data.current_file ? 'Processing: ' + data.current_file : ''; | |
| if (data.image_ids && data.image_ids.length) { | |
| feedPanel.style.display = 'block'; | |
| data.image_ids.forEach(function (imageId) { | |
| if (!seenIds.has(imageId)) { | |
| seenIds.add(imageId); | |
| var li = document.createElement('li'); | |
| var link = document.createElement('a'); | |
| link.href = '/case/' + imageId; | |
| link.textContent = imageId; | |
| li.appendChild(link); | |
| feedList.insertBefore(li, feedList.firstChild); | |
| while (feedList.children.length > 20) { | |
| var last = feedList.lastChild; | |
| if (!last) { | |
| break; | |
| } | |
| var lastLink = last.querySelector('a'); | |
| if (lastLink && lastLink.textContent) { | |
| seenIds.delete(lastLink.textContent); | |
| } | |
| feedList.removeChild(last); | |
| } | |
| } | |
| }); | |
| } | |
| if (data.status === 'canceled') { | |
| title.textContent = 'Batch Canceled'; | |
| subtitle.textContent = 'The batch was canceled.'; | |
| if (cancelBtn) { | |
| cancelBtn.disabled = true; | |
| } | |
| return; | |
| } | |
| if (data.status === 'completed' || data.status === 'failed') { | |
| title.textContent = 'Batch Complete'; | |
| subtitle.textContent = ''; | |
| if (cancelBtn) { | |
| cancelBtn.disabled = true; | |
| } | |
| donePanel.style.display = 'block'; | |
| var failCount = data.failed_ids ? data.failed_ids.length : 0; | |
| doneSummary.textContent = data.succeeded + ' of ' + total + ' files processed successfully' + (failCount > 0 ? ', ' + failCount + ' failed' : '') + '.'; | |
| if (data.failed_ids && data.failed_ids.length) { | |
| failPanel.style.display = 'block'; | |
| data.failed_ids.forEach(function (failedId) { | |
| var li = document.createElement('li'); | |
| li.textContent = failedId; | |
| failList.appendChild(li); | |
| }); | |
| } | |
| return; | |
| } | |
| setTimeout(poll, pollMs); | |
| }) | |
| .catch(function () { | |
| setTimeout(poll, pollMs * 3); | |
| }); | |
| } | |
| poll(); | |
| } | |
| if (document.readyState === 'loading') { | |
| document.addEventListener('DOMContentLoaded', initBatchProgress); | |
| } else { | |
| initBatchProgress(); | |
| } | |
| })(); | |