Skip to content

Commit 2013ca8

Browse files
committed
fix: address PR review issues in upload and save features
- Replace deprecated substr() with substring() in UploadContext - Fix broken error handling that checked stale task status - Fix missing useEffect dependency in UploadStatus - Fix CSS class conflict in progress bar styling - Add error recovery for save state in Editor (reset on failure) - Use .finally() instead of .then() to ensure refresh on upload failure - Fix inconsistent indentation in UploadContext
1 parent 02f3572 commit 2013ca8

4 files changed

Lines changed: 33 additions & 41 deletions

File tree

frontend/src/components/UploadStatus.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export const UploadStatus: React.FC = () => {
1010

1111
// Auto-open when upload starts
1212
useEffect(() => {
13-
if (isUploading && !isOpen) {
13+
if (isUploading) {
1414
setIsOpen(true);
1515
}
1616
}, [isUploading]);
@@ -84,8 +84,7 @@ export const UploadStatus: React.FC = () => {
8484
<div
8585
className={clsx(
8686
"h-full transition-all duration-300 ease-out rounded-full",
87-
task.status === 'error' ? "bg-rose-500" : "bg-indigo-600",
88-
task.status === 'success' && "bg-emerald-500"
87+
task.status === 'error' ? "bg-rose-500" : task.status === 'success' ? "bg-emerald-500" : "bg-indigo-600"
8988
)}
9089
style={{ width: `${task.progress}%` }}
9190
/>

frontend/src/context/UploadContext.tsx

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -48,42 +48,34 @@ export const UploadProvider: React.FC<{ children: ReactNode }> = ({ children })
4848

4949
const uploadFiles = useCallback(async (files: File[], targetCollectionId: string | null) => {
5050
const newTasks: UploadTask[] = files.map(f => ({
51-
id: Math.random().toString(36).substr(2, 9),
51+
id: Math.random().toString(36).substring(2, 11),
5252
fileName: f.name,
5353
status: 'pending',
5454
progress: 0
5555
}));
5656

5757
setTasks(prev => [...newTasks, ...prev]);
5858

59-
// Process files
60-
// Note: We are using a modified importDrawings that will be updated to accept onProgress
61-
// We map the tasks to the files for the callback
62-
const fileTaskMap = new Map<string, string>(); // fileName -> taskId
59+
// Map file names to task IDs for progress callbacks
60+
const fileTaskMap = new Map<string, string>();
6361
newTasks.forEach(t => fileTaskMap.set(t.fileName, t.id));
6462

65-
// We start all uploads. The Utils will handle the actual async work.
66-
// For now we assume sequential or parallel is handled by util, but we need to pass a callback per file or a global one.
67-
6863
const handleProgress = (fileName: string, status: UploadStatus, progress: number, error?: string) => {
69-
const taskId = fileTaskMap.get(fileName);
70-
if (taskId) {
71-
updateTask(taskId, { status, progress, error });
72-
}
64+
const taskId = fileTaskMap.get(fileName);
65+
if (taskId) {
66+
updateTask(taskId, { status, progress, error });
67+
}
7368
};
7469

7570
try {
76-
await importDrawings(files, targetCollectionId, undefined, handleProgress);
71+
await importDrawings(files, targetCollectionId, undefined, handleProgress);
7772
} catch (e) {
78-
console.error("Global upload error", e);
79-
// Mark pending as error if something crashed completely
80-
newTasks.forEach(t => {
81-
if (t.status === 'pending' || t.status === 'uploading') {
82-
updateTask(t.id, { status: 'error', error: 'Upload failed unexpectedly' });
83-
}
84-
});
73+
console.error("Global upload error", e);
74+
// Mark all new tasks as error if something crashed completely
75+
newTasks.forEach(t => {
76+
updateTask(t.id, { status: 'error', error: 'Upload failed unexpectedly' });
77+
});
8578
}
86-
8779
}, [updateTask]);
8880

8981
return (

frontend/src/pages/Dashboard.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -307,10 +307,9 @@ export const Dashboard: React.FC = () => {
307307
const targetCollectionId = selectedCollectionId === undefined ? null : selectedCollectionId;
308308

309309
// Use the global upload context
310-
uploadFiles(fileArray, targetCollectionId).then(() => {
311-
// Refresh after upload is presumably done or started
312-
// Since uploadFiles waits for all, we can refresh here.
313-
refreshData();
310+
uploadFiles(fileArray, targetCollectionId).finally(() => {
311+
// Refresh after all uploads complete (success or failure)
312+
refreshData();
314313
});
315314
};
316315

@@ -534,8 +533,8 @@ export const Dashboard: React.FC = () => {
534533

535534
const drawingFiles = files.filter(f => !f.name.endsWith('.excalidrawlib'));
536535
if (drawingFiles.length > 0) {
537-
uploadFiles(drawingFiles, targetCollectionId).then(() => {
538-
refreshData();
536+
uploadFiles(drawingFiles, targetCollectionId).finally(() => {
537+
refreshData();
539538
});
540539
}
541540

frontend/src/pages/Editor.tsx

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -593,26 +593,28 @@ export const Editor: React.FC = () => {
593593

594594
const handleBackClick = async () => {
595595
if (isSavingOnLeave) return; // Prevent double clicks
596-
596+
597597
setIsSavingOnLeave(true);
598598

599599
// Save drawing and generate preview before navigating
600-
if (excalidrawAPI.current && saveDataRef.current && savePreviewRef.current) {
601-
const elements = excalidrawAPI.current.getSceneElementsIncludingDeleted();
602-
const appState = excalidrawAPI.current.getAppState();
603-
const files = excalidrawAPI.current.getFiles() || {};
604-
latestElementsRef.current = elements;
605-
latestFilesRef.current = files;
606-
607-
try {
600+
try {
601+
if (excalidrawAPI.current && saveDataRef.current && savePreviewRef.current) {
602+
const elements = excalidrawAPI.current.getSceneElementsIncludingDeleted();
603+
const appState = excalidrawAPI.current.getAppState();
604+
const files = excalidrawAPI.current.getFiles() || {};
605+
latestElementsRef.current = elements;
606+
latestFilesRef.current = files;
607+
608608
await Promise.all([
609609
saveDataRef.current(elements, appState),
610610
savePreviewRef.current(elements, appState, files)
611611
]);
612612
console.log("[Editor] Saved on back navigation", { drawingId: id });
613-
} catch (err) {
614-
console.error('Failed to save on back navigation', err);
615613
}
614+
} catch (err) {
615+
console.error('Failed to save on back navigation', err);
616+
} finally {
617+
setIsSavingOnLeave(false);
616618
}
617619
navigate('/');
618620
};

0 commit comments

Comments
 (0)