generated from coulomb/repo-seed
Improve consistency for server-discovered documents
- Separate "Has Errors" section for erroneous server documents (already uploaded but have validation errors) - "Ready to Upload" section now only shows truly local documents - Erroneous server docs show only "Delete from server" button (no retry) - Improved metadata display: show document ID for server docs, hide unknown file size - Clean up verbose debug logging Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -316,13 +316,10 @@ async function loadPDFQueue() {
|
|||||||
*/
|
*/
|
||||||
async function syncWithServer() {
|
async function syncWithServer() {
|
||||||
if (!currentCredentials) {
|
if (!currentCredentials) {
|
||||||
console.log('[Popup] No credentials, skipping server sync');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log('[Popup] Syncing with Binect server...');
|
|
||||||
|
|
||||||
// Get list of documents from server
|
// Get list of documents from server
|
||||||
const result = await chrome.runtime.sendMessage({
|
const result = await chrome.runtime.sendMessage({
|
||||||
action: 'listServerDocuments',
|
action: 'listServerDocuments',
|
||||||
@@ -330,8 +327,6 @@ async function syncWithServer() {
|
|||||||
password: currentCredentials.password
|
password: currentCredentials.password
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('[Popup] listServerDocuments result:', result);
|
|
||||||
|
|
||||||
if (!result.success || !result.documents) {
|
if (!result.success || !result.documents) {
|
||||||
console.warn('[Popup] Failed to list server documents:', result.error);
|
console.warn('[Popup] Failed to list server documents:', result.error);
|
||||||
return;
|
return;
|
||||||
@@ -347,15 +342,11 @@ async function syncWithServer() {
|
|||||||
errorDetails?: string;
|
errorDetails?: string;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
console.log('[Popup] Found', serverDocs.length, 'documents on server');
|
console.log('[Popup] Syncing', serverDocs.length, 'server documents');
|
||||||
for (const doc of serverDocs) {
|
|
||||||
console.log('[Popup] Server doc:', doc.id, doc.filename, 'status:', doc.status, doc.statusText);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sync each server document to local proxy
|
// Sync each server document to local proxy
|
||||||
for (const doc of serverDocs) {
|
for (const doc of serverDocs) {
|
||||||
console.log('[Popup] Syncing doc', doc.id, 'to local proxy...');
|
await chrome.runtime.sendMessage({
|
||||||
const syncResult = await chrome.runtime.sendMessage({
|
|
||||||
action: 'syncFromServer',
|
action: 'syncFromServer',
|
||||||
binectDocumentId: doc.id,
|
binectDocumentId: doc.id,
|
||||||
filename: doc.filename,
|
filename: doc.filename,
|
||||||
@@ -365,10 +356,7 @@ async function syncWithServer() {
|
|||||||
recipientAddress: doc.recipientAddress,
|
recipientAddress: doc.recipientAddress,
|
||||||
errorDetails: doc.errorDetails
|
errorDetails: doc.errorDetails
|
||||||
});
|
});
|
||||||
console.log('[Popup] Sync result for doc', doc.id, ':', syncResult);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('[Popup] Server sync complete');
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[Popup] Server sync error:', error);
|
console.error('[Popup] Server sync error:', error);
|
||||||
}
|
}
|
||||||
@@ -444,13 +432,20 @@ function renderPDFList() {
|
|||||||
</div>`;
|
</div>`;
|
||||||
} else {
|
} else {
|
||||||
// Live view - group by Binect status
|
// Live view - group by Binect status
|
||||||
const pendingUpload = pdfQueue.filter(p => p.binectStatus === 'pending' || p.binectStatus === 'uploading' || p.binectStatus === 'failed');
|
// Separate truly local pending uploads from server documents with errors
|
||||||
|
const pendingUpload = pdfQueue.filter(p =>
|
||||||
|
(p.binectStatus === 'pending' || p.binectStatus === 'uploading') ||
|
||||||
|
(p.binectStatus === 'failed' && !p.binectDocumentId) // Local failed uploads
|
||||||
|
);
|
||||||
|
const erroneous = pdfQueue.filter(p =>
|
||||||
|
p.binectStatus === 'failed' && p.binectDocumentId // Server documents with errors
|
||||||
|
);
|
||||||
const inBasket = pdfQueue.filter(p => p.binectStatus === 'in_basket' || p.binectStatus === 'ordering');
|
const inBasket = pdfQueue.filter(p => p.binectStatus === 'in_basket' || p.binectStatus === 'ordering');
|
||||||
const inProduction = pdfQueue.filter(p => p.binectStatus === 'in_production');
|
const inProduction = pdfQueue.filter(p => p.binectStatus === 'in_production');
|
||||||
const completed = pdfQueue.filter(p => p.binectStatus === 'sent' || p.binectStatus === 'canceled');
|
const completed = pdfQueue.filter(p => p.binectStatus === 'sent' || p.binectStatus === 'canceled');
|
||||||
|
|
||||||
// Count actionable items
|
// Count actionable items
|
||||||
const actionableCount = pendingUpload.length + inBasket.length;
|
const actionableCount = pendingUpload.length + erroneous.length + inBasket.length;
|
||||||
|
|
||||||
// Update count
|
// Update count
|
||||||
if (actionableCount > 0) {
|
if (actionableCount > 0) {
|
||||||
@@ -470,6 +465,13 @@ function renderPDFList() {
|
|||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (erroneous.length > 0) {
|
||||||
|
html += `<div class="pdf-section">
|
||||||
|
<div class="pdf-section-header">Has Errors</div>
|
||||||
|
${erroneous.map(pdf => renderPDFItem(pdf, 'erroneous')).join('')}
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
if (inBasket.length > 0) {
|
if (inBasket.length > 0) {
|
||||||
html += `<div class="pdf-section">
|
html += `<div class="pdf-section">
|
||||||
<div class="pdf-section-header">In Basket</div>
|
<div class="pdf-section-header">In Basket</div>
|
||||||
@@ -504,7 +506,7 @@ function renderPDFList() {
|
|||||||
/**
|
/**
|
||||||
* Render a single PDF item
|
* Render a single PDF item
|
||||||
*/
|
*/
|
||||||
function renderPDFItem(pdf: DocumentProxy, section: 'pending' | 'basket' | 'production' | 'completed' | 'archived'): string {
|
function renderPDFItem(pdf: DocumentProxy, section: 'pending' | 'erroneous' | 'basket' | 'production' | 'completed' | 'archived'): string {
|
||||||
const statusClass = getStatusClass(pdf.binectStatus);
|
const statusClass = getStatusClass(pdf.binectStatus);
|
||||||
const statusText = getStatusText(pdf);
|
const statusText = getStatusText(pdf);
|
||||||
const priceText = pdf.price ? `${(pdf.price / 100).toFixed(2)} €` : '';
|
const priceText = pdf.price ? `${(pdf.price / 100).toFixed(2)} €` : '';
|
||||||
@@ -522,10 +524,13 @@ function renderPDFItem(pdf: DocumentProxy, section: 'pending' | 'basket' | 'prod
|
|||||||
<button class="btn-send-item" data-id="${escapeHtml(pdf.id)}" ${pdf.binectStatus === 'uploading' ? 'disabled' : ''}>
|
<button class="btn-send-item" data-id="${escapeHtml(pdf.id)}" ${pdf.binectStatus === 'uploading' ? 'disabled' : ''}>
|
||||||
${pdf.binectStatus === 'uploading' ? 'Uploading...' : (pdf.binectStatus === 'failed' ? 'Retry' : 'Upload')}
|
${pdf.binectStatus === 'uploading' ? 'Uploading...' : (pdf.binectStatus === 'failed' ? 'Retry' : 'Upload')}
|
||||||
</button>
|
</button>
|
||||||
${canDeleteFromServer
|
<button class="btn-archive" data-id="${escapeHtml(pdf.id)}">Archive</button>
|
||||||
? `<button class="btn-delete-server" data-id="${escapeHtml(pdf.id)}">Delete from server</button>`
|
`;
|
||||||
: `<button class="btn-archive" data-id="${escapeHtml(pdf.id)}">Archive</button>`
|
break;
|
||||||
}
|
case 'erroneous':
|
||||||
|
// Server documents with errors - can only delete from server
|
||||||
|
actionsHtml = `
|
||||||
|
<button class="btn-delete-server" data-id="${escapeHtml(pdf.id)}">Delete from server</button>
|
||||||
`;
|
`;
|
||||||
break;
|
break;
|
||||||
case 'basket':
|
case 'basket':
|
||||||
@@ -563,6 +568,20 @@ function renderPDFItem(pdf: DocumentProxy, section: 'pending' | 'basket' | 'prod
|
|||||||
// Show detailed error info for erroneous documents
|
// Show detailed error info for erroneous documents
|
||||||
const hasErrorDetails = pdf.binectStatus === 'failed' && pdf.errorMessage && pdf.binectStatusCode === 7;
|
const hasErrorDetails = pdf.binectStatus === 'failed' && pdf.errorMessage && pdf.binectStatusCode === 7;
|
||||||
|
|
||||||
|
// Build metadata parts - only include what we have
|
||||||
|
const metaParts: string[] = [];
|
||||||
|
if (pdf.size > 0) {
|
||||||
|
metaParts.push(formatFileSize(pdf.size));
|
||||||
|
}
|
||||||
|
if (pdf.sourceDomain && pdf.sourceDomain !== 'binect.de') {
|
||||||
|
metaParts.push(escapeHtml(pdf.sourceDomain));
|
||||||
|
} else if (pdf.binectDocumentId && pdf.sourceDomain === 'binect.de') {
|
||||||
|
metaParts.push(`ID: ${pdf.binectDocumentId}`);
|
||||||
|
}
|
||||||
|
if (priceText) {
|
||||||
|
metaParts.push(`<span class="pdf-price">${priceText}</span>`);
|
||||||
|
}
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="pdf-list-item ${statusClass}" data-id="${escapeHtml(pdf.id)}">
|
<div class="pdf-list-item ${statusClass}" data-id="${escapeHtml(pdf.id)}">
|
||||||
<div class="pdf-item-icon">${getStatusIcon(pdf.binectStatus)}</div>
|
<div class="pdf-item-icon">${getStatusIcon(pdf.binectStatus)}</div>
|
||||||
@@ -571,10 +590,7 @@ function renderPDFItem(pdf: DocumentProxy, section: 'pending' | 'basket' | 'prod
|
|||||||
${escapeHtml(displayFilename)}
|
${escapeHtml(displayFilename)}
|
||||||
${isLocalOnly ? '<span class="tag-local">local</span>' : ''}
|
${isLocalOnly ? '<span class="tag-local">local</span>' : ''}
|
||||||
</div>
|
</div>
|
||||||
<div class="pdf-item-meta">
|
${metaParts.length > 0 ? `<div class="pdf-item-meta">${metaParts.join(' · ')}</div>` : ''}
|
||||||
${formatFileSize(pdf.size)} · ${escapeHtml(pdf.sourceDomain)}
|
|
||||||
${priceText ? ` · <span class="pdf-price">${priceText}</span>` : ''}
|
|
||||||
</div>
|
|
||||||
${pdf.recipientAddress ? `<div class="pdf-item-recipient">${escapeHtml(pdf.recipientAddress.split('\n')[0])}</div>` : ''}
|
${pdf.recipientAddress ? `<div class="pdf-item-recipient">${escapeHtml(pdf.recipientAddress.split('\n')[0])}</div>` : ''}
|
||||||
<div class="pdf-item-status ${statusClass}">${statusText}</div>
|
<div class="pdf-item-status ${statusClass}">${statusText}</div>
|
||||||
${hasErrorDetails ? `<div class="pdf-item-error">${escapeHtml(pdf.errorMessage!)}</div>` : ''}
|
${hasErrorDetails ? `<div class="pdf-item-error">${escapeHtml(pdf.errorMessage!)}</div>` : ''}
|
||||||
|
|||||||
@@ -500,23 +500,17 @@ export async function listServerDocuments(
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Get shippable documents (status 2)
|
// Get shippable documents (status 2)
|
||||||
console.log('[Binect API] Fetching shippable documents...');
|
|
||||||
const shippableResponse = await client.documents.list();
|
const shippableResponse = await client.documents.list();
|
||||||
console.log('[Binect API] Shippable response:', JSON.stringify(shippableResponse));
|
|
||||||
const shippable = shippableResponse.items || [];
|
const shippable = shippableResponse.items || [];
|
||||||
console.log('[Binect API] Found', shippable.length, 'shippable documents');
|
|
||||||
|
|
||||||
// Get erroneous documents (status 7)
|
// Get erroneous documents (status 7)
|
||||||
console.log('[Binect API] Fetching erroneous documents...');
|
|
||||||
const errorsResponse = await client.documents.listErrors();
|
const errorsResponse = await client.documents.listErrors();
|
||||||
console.log('[Binect API] Errors response:', JSON.stringify(errorsResponse));
|
|
||||||
const erroneous = errorsResponse.items || [];
|
const erroneous = errorsResponse.items || [];
|
||||||
console.log('[Binect API] Found', erroneous.length, 'erroneous documents');
|
|
||||||
|
|
||||||
// Combine and map to our format
|
// Combine and map to our format
|
||||||
const allDocs = [...shippable, ...erroneous];
|
const allDocs = [...shippable, ...erroneous];
|
||||||
|
|
||||||
console.log('[Binect API] Total documents on server:', allDocs.length);
|
console.log('[Binect API] Found', allDocs.length, 'documents on server (', shippable.length, 'shippable,', erroneous.length, 'erroneous)');
|
||||||
|
|
||||||
return allDocs.map(doc => {
|
return allDocs.map(doc => {
|
||||||
let errorDetails: string | undefined;
|
let errorDetails: string | undefined;
|
||||||
|
|||||||
Reference in New Issue
Block a user