From 396ff23d49ccb690e16c6f66b6b3e969871d467d Mon Sep 17 00:00:00 2001 From: Christian Vidal Wolf Date: Wed, 20 May 2026 13:59:35 +0200 Subject: [PATCH] fix dropbox load fallback --- src/App.tsx | 99 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 74 insertions(+), 25 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 06d5b65..b233aae 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,6 +1,7 @@ import React, { useState, useMemo, useEffect } from 'react'; import * as XLSX from 'xlsx'; import { X } from 'lucide-react'; +import defaultWorkbookUrl from '../data (3).xlsx?url'; import { cn } from './lib/utils'; import { AppState, ExcelRow, resolveColumnIndices, COLUMNS } from './types'; import { ColumnsProvider } from './contexts/ColumnsContext'; @@ -85,6 +86,31 @@ function readStoredBcSyncQueue(): BcSyncQueue { } } +async function loadWorkbookFromUrl(url: string) { + const response = await fetch(url, { cache: 'no-store' }); + if (!response.ok) { + throw new Error(`HTTP ${response.status}`); + } + + const arrayBuffer = await response.arrayBuffer(); + if (arrayBuffer.byteLength < 100) { + throw new Error('File too small'); + } + + const wb = XLSX.read(arrayBuffer, { type: 'array' }); + const wsname = wb.SheetNames[0]; + const ws = wb.Sheets[wsname]; + const allData = XLSX.utils.sheet_to_json(ws, { header: 1 }); + const rows = allData.slice(1); + const headers = allData.slice(0, 1)[0] || []; + + return { + headers, + rows, + fileMeta: { rev: url, size: arrayBuffer.byteLength }, + }; +} + export default function App() { const [session, setSession] = useState(() => getStoredSession()); @@ -201,22 +227,31 @@ export default function App() { const cacheBuster = `t_${Date.now()}`; const fileUrl = `/dropbox-file/scl/fi/usa8me7ywgylrij2bt6hj/Data-Matrix.xlsx?rlkey=tsec8csrhye54u1fdvk15ped1&dl=1&${cacheBuster}=${Date.now()}`; console.log('Fetching Data-Matrix.xlsx from Dropbox (hard refresh)...'); - const response = await fetch(fileUrl, { cache: 'no-store' }); - if (!response.ok) throw new Error(`HTTP ${response.status}`); - - const contentType = response.headers.get('content-type'); - if (contentType && contentType.includes('text/html')) { - throw new Error('Dropbox returned an HTML page instead of the Excel file. This usually means the sharing link has expired or requires manual interaction. Please generate a new "Copy Link" from Dropbox.'); + try { + const response = await fetch(fileUrl, { cache: 'no-store' }); + if (!response.ok) throw new Error(`HTTP ${response.status}`); + + const contentType = response.headers.get('content-type'); + if (contentType && contentType.includes('text/html')) { + throw new Error('Dropbox returned an HTML page instead of the Excel file.'); + } + + const arrayBuffer = await response.arrayBuffer(); + if (arrayBuffer.byteLength < 100) throw new Error('File too small'); + + const wb = XLSX.read(arrayBuffer, { type: 'array' }); + const wsname = wb.SheetNames[0]; + const ws = wb.Sheets[wsname]; + allData = XLSX.utils.sheet_to_json(ws, { header: 1 }); + rows = allData.slice(1); + fileMeta = { rev: 'dev', size: arrayBuffer.byteLength }; + } catch (devErr) { + console.warn('Dropbox dev load failed, using bundled workbook fallback:', devErr); + const fallback = await loadWorkbookFromUrl(defaultWorkbookUrl); + allData = [fallback.headers, ...fallback.rows]; + rows = fallback.rows; + fileMeta = fallback.fileMeta; } - const arrayBuffer = await response.arrayBuffer(); - if (arrayBuffer.byteLength < 100) throw new Error('File too small'); - - const wb = XLSX.read(arrayBuffer, { type: 'array' }); - const wsname = wb.SheetNames[0]; - const ws = wb.Sheets[wsname]; - allData = XLSX.utils.sheet_to_json(ws, { header: 1 }); - rows = allData.slice(1); - fileMeta = { rev: 'dev', size: arrayBuffer.byteLength }; } else { console.log('Fetching file info from Dropbox...'); const infoRes = await fetch('/api/dropbox-proxy?info=1'); @@ -226,16 +261,30 @@ export default function App() { } console.log('Fetching Data-Matrix.xlsx from proxy (hard refresh)...'); - const response = await fetch('/api/dropbox-proxy', { cache: 'no-store' }); - if (!response.ok) throw new Error(`HTTP ${response.status}`); - const arrayBuffer = await response.arrayBuffer(); - if (arrayBuffer.byteLength < 100) throw new Error('File too small'); - - const wb = XLSX.read(arrayBuffer, { type: 'array' }); - const wsname = wb.SheetNames[0]; - const ws = wb.Sheets[wsname]; - allData = XLSX.utils.sheet_to_json(ws, { header: 1 }); - rows = allData.slice(1); + try { + const response = await fetch('/api/dropbox-proxy', { cache: 'no-store' }); + if (!response.ok) throw new Error(`HTTP ${response.status}`); + + const contentType = response.headers.get('content-type'); + if (contentType && contentType.includes('text/html')) { + throw new Error('Dropbox returned an HTML page instead of the Excel file.'); + } + + const arrayBuffer = await response.arrayBuffer(); + if (arrayBuffer.byteLength < 100) throw new Error('File too small'); + + const wb = XLSX.read(arrayBuffer, { type: 'array' }); + const wsname = wb.SheetNames[0]; + const ws = wb.Sheets[wsname]; + allData = XLSX.utils.sheet_to_json(ws, { header: 1 }); + rows = allData.slice(1); + } catch (prodErr) { + console.warn('Dropbox prod load failed, using bundled workbook fallback:', prodErr); + const fallback = await loadWorkbookFromUrl(defaultWorkbookUrl); + allData = [fallback.headers, ...fallback.rows]; + rows = fallback.rows; + fileMeta = fallback.fileMeta; + } } if (rows.length > 0) {