diff --git a/src/popup/popup.css b/src/popup/popup.css index 083c9ff..6f0c39e 100644 --- a/src/popup/popup.css +++ b/src/popup/popup.css @@ -93,6 +93,30 @@ body { outline-offset: 2px; } +.icon-btn svg { + display: block; +} + +.icon-btn.refreshing svg { + animation: spin 1s linear infinite; +} + +@keyframes spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +/* Header actions */ +.header-actions { + display: flex; + gap: var(--spacing-sm); + align-items: center; +} + /* Views */ .view { flex: 1; diff --git a/src/popup/popup.html b/src/popup/popup.html index 84ffd17..e20321c 100644 --- a/src/popup/popup.html +++ b/src/popup/popup.html @@ -10,7 +10,16 @@

BinectChrome

- +
+ + +
diff --git a/src/popup/popup.ts b/src/popup/popup.ts index a7adbf3..0fa30c5 100644 --- a/src/popup/popup.ts +++ b/src/popup/popup.ts @@ -25,6 +25,7 @@ const loginBtn = document.getElementById('loginBtn') as HTMLButtonElement; const authError = document.getElementById('authError')!; const logoutBtn = document.getElementById('logoutBtn')!; +const refreshBtn = document.getElementById('refreshBtn')!; const helpBtn = document.getElementById('helpBtn')!; const togglePasswordBtn = document.getElementById('togglePassword') as HTMLButtonElement; const eyeIcon = document.getElementById('eyeIcon')!; @@ -75,6 +76,7 @@ async function init() { function setupEventListeners() { loginForm.addEventListener('submit', handleLogin); logoutBtn.addEventListener('click', handleLogout); + refreshBtn.addEventListener('click', handleRefreshAll); helpBtn.addEventListener('click', handleHelp); togglePasswordBtn.addEventListener('click', handleTogglePassword); } @@ -336,9 +338,8 @@ function renderPDFItem(pdf: PDFQueueEntry, section: 'pending' | 'basket' | 'prod `; break; case 'production': - actionsHtml = ` - - `; + // No individual actions - use global refresh button in header + actionsHtml = ''; break; case 'completed': actionsHtml = ` @@ -386,14 +387,6 @@ function setupPDFListEventListeners() { }); }); - // Refresh buttons - pdfList.querySelectorAll('.btn-refresh-item').forEach(btn => { - btn.addEventListener('click', (e) => { - const id = (e.target as HTMLElement).dataset.id; - if (id) handleRefreshStatus(id); - }); - }); - // Dismiss/Cancel/Remove buttons pdfList.querySelectorAll('.btn-dismiss').forEach(btn => { btn.addEventListener('click', (e) => { @@ -685,6 +678,53 @@ async function handleOrderPDF(id: string) { } } +/** + * Handle refresh all documents that have been uploaded to server + */ +async function handleRefreshAll() { + if (!currentCredentials) { + return; + } + + // Find all documents that have been uploaded and are still visible + const uploadedDocs = pdfQueue.filter(p => + p.binectDocumentId && + (p.status === 'in_basket' || p.status === 'in_production') + ); + + if (uploadedDocs.length === 0) { + showStatus('No documents to refresh', 'success'); + setTimeout(() => hideStatus(), 2000); + return; + } + + // Disable refresh button during refresh + refreshBtn.classList.add('refreshing'); + showStatus(`Refreshing ${uploadedDocs.length} document${uploadedDocs.length > 1 ? 's' : ''}...`, 'uploading'); + + let successCount = 0; + let errorCount = 0; + + for (const pdf of uploadedDocs) { + try { + await handleRefreshStatus(pdf.id); + successCount++; + } catch { + errorCount++; + } + } + + refreshBtn.classList.remove('refreshing'); + + if (errorCount === 0) { + showStatus(`Refreshed ${successCount} document${successCount > 1 ? 's' : ''}`, 'success'); + } else { + showStatus(`Refreshed ${successCount}, ${errorCount} failed`, 'error'); + } + + setTimeout(() => hideStatus(), 3000); +} + /** * Handle refresh document status */