Move refresh to global header button

- Add refresh button in header (before help button)
- Refresh updates all uploaded documents at once (in_basket, in_production)
- Remove individual refresh buttons from production items
- Add spinning animation while refresh is in progress
- Show count of refreshed documents in status message

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-16 13:28:16 +01:00
parent 468473f03b
commit 5cb0194533
3 changed files with 85 additions and 12 deletions

View File

@@ -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;

View File

@@ -10,7 +10,16 @@
<!-- Header -->
<div class="header">
<h1>BinectChrome</h1>
<button id="helpBtn" class="icon-btn" aria-label="Help and tracking info" title="Help & Info">?</button>
<div class="header-actions">
<button id="refreshBtn" class="icon-btn" aria-label="Refresh status from server" title="Refresh status">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="23 4 23 10 17 10"></polyline>
<polyline points="1 20 1 14 7 14"></polyline>
<path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path>
</svg>
</button>
<button id="helpBtn" class="icon-btn" aria-label="Help and tracking info" title="Help & Info">?</button>
</div>
</div>
<!-- Authentication View -->

View File

@@ -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 = `
<button class="btn-refresh-item" data-id="${escapeHtml(pdf.id)}">Refresh</button>
`;
// 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
*/