Upload folder using huggingface_hub
Browse files
client/src/pages/TutorialTasks.tsx
CHANGED
|
@@ -890,30 +890,26 @@ const TutorialTasks: React.FC = () => {
|
|
| 890 |
return { ...prev, [taskId]: next };
|
| 891 |
});
|
| 892 |
|
| 893 |
-
// Defer state updates
|
| 894 |
-
|
| 895 |
-
|
| 896 |
-
|
| 897 |
-
|
| 898 |
-
|
| 899 |
-
React.startTransition(() => {
|
| 900 |
-
setTranslationText({ ...translationText, [taskId]: '' });
|
| 901 |
-
setSelectedGroups({ ...selectedGroups, [taskId]: 0 });
|
| 902 |
-
api.get(`/api/submissions/by-source/${taskId}`).then(r => {
|
| 903 |
-
const list = (r.data && r.data.submissions) || [];
|
| 904 |
-
setUserSubmissions(prev => ({ ...prev, [taskId]: list }));
|
| 905 |
-
requestAnimationFrame(() => setSpacerHeights(prev => ({ ...prev, [taskId]: 0 })));
|
| 906 |
-
}).catch(() => {
|
| 907 |
-
requestAnimationFrame(() => setSpacerHeights(prev => ({ ...prev, [taskId]: 0 })));
|
| 908 |
-
});
|
| 909 |
-
});
|
| 910 |
-
});
|
| 911 |
-
} else {
|
| 912 |
React.startTransition(() => {
|
| 913 |
setTranslationText({ ...translationText, [taskId]: '' });
|
| 914 |
setSelectedGroups({ ...selectedGroups, [taskId]: 0 });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 915 |
});
|
| 916 |
-
}
|
| 917 |
} else {
|
| 918 |
console.error('Failed to submit translation:', response.data);
|
| 919 |
}
|
|
@@ -989,8 +985,8 @@ const TutorialTasks: React.FC = () => {
|
|
| 989 |
|
| 990 |
if (response.status === 200) {
|
| 991 |
|
| 992 |
-
// Optimistic removal
|
| 993 |
-
if (taskId) {
|
| 994 |
setUserSubmissions(prev => {
|
| 995 |
const list = prev[taskId] || [];
|
| 996 |
const next = list.filter(s => s._id !== submissionId);
|
|
@@ -998,28 +994,28 @@ const TutorialTasks: React.FC = () => {
|
|
| 998 |
});
|
| 999 |
}
|
| 1000 |
|
| 1001 |
-
// Defer refetch
|
| 1002 |
-
if (
|
| 1003 |
-
|
| 1004 |
-
|
| 1005 |
-
|
| 1006 |
-
|
| 1007 |
-
|
| 1008 |
-
|
| 1009 |
-
|
| 1010 |
-
|
| 1011 |
-
|
| 1012 |
-
|
| 1013 |
-
|
| 1014 |
-
|
| 1015 |
-
|
| 1016 |
-
|
| 1017 |
-
|
| 1018 |
-
|
| 1019 |
-
|
| 1020 |
-
}
|
| 1021 |
});
|
| 1022 |
-
}
|
| 1023 |
} else {
|
| 1024 |
|
| 1025 |
}
|
|
|
|
| 890 |
return { ...prev, [taskId]: next };
|
| 891 |
});
|
| 892 |
|
| 893 |
+
// Defer state updates and minimal refetch
|
| 894 |
+
// Measure grid height and set spacer before refetch to keep layout height constant
|
| 895 |
+
const gridEl = submissionsGridRefs.current[taskId];
|
| 896 |
+
const gridHeight = gridEl ? gridEl.getBoundingClientRect().height : 0;
|
| 897 |
+
if (gridHeight > 0) setSpacerHeights(prev => ({ ...prev, [taskId]: gridHeight }));
|
| 898 |
+
withPreservedCardOffset(taskId, () => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 899 |
React.startTransition(() => {
|
| 900 |
setTranslationText({ ...translationText, [taskId]: '' });
|
| 901 |
setSelectedGroups({ ...selectedGroups, [taskId]: 0 });
|
| 902 |
+
// Narrow refetch: only this task's submissions
|
| 903 |
+
api.get(`/api/submissions/by-source/${taskId}`).then(r => {
|
| 904 |
+
const list = (r.data && r.data.submissions) || [];
|
| 905 |
+
setUserSubmissions(prev => ({ ...prev, [taskId]: list }));
|
| 906 |
+
// Release spacer one frame after list update to avoid jump
|
| 907 |
+
requestAnimationFrame(() => setSpacerHeights(prev => ({ ...prev, [taskId]: 0 })));
|
| 908 |
+
}).catch(() => {
|
| 909 |
+
requestAnimationFrame(() => setSpacerHeights(prev => ({ ...prev, [taskId]: 0 })));
|
| 910 |
+
});
|
| 911 |
});
|
| 912 |
+
});
|
| 913 |
} else {
|
| 914 |
console.error('Failed to submit translation:', response.data);
|
| 915 |
}
|
|
|
|
| 985 |
|
| 986 |
if (response.status === 200) {
|
| 987 |
|
| 988 |
+
// Optimistic removal (disabled on Safari to prevent multi-phase jumps)
|
| 989 |
+
if (taskId && !isSafari) {
|
| 990 |
setUserSubmissions(prev => {
|
| 991 |
const list = prev[taskId] || [];
|
| 992 |
const next = list.filter(s => s._id !== submissionId);
|
|
|
|
| 994 |
});
|
| 995 |
}
|
| 996 |
|
| 997 |
+
// Defer refetch to prevent UI jumping and preserve scroll around DOM updates
|
| 998 |
+
if (taskId) lockCardHeightById(taskId);
|
| 999 |
+
withPreservedCardOffset(taskId || '', () => {
|
| 1000 |
+
React.startTransition(() => {
|
| 1001 |
+
// Narrow refetch: only this task's submissions
|
| 1002 |
+
if (taskId) {
|
| 1003 |
+
const gridEl = submissionsGridRefs.current[taskId];
|
| 1004 |
+
const gridHeight = gridEl ? gridEl.getBoundingClientRect().height : 0;
|
| 1005 |
+
if (gridHeight > 0) setSpacerHeights(prev => ({ ...prev, [taskId]: gridHeight }));
|
| 1006 |
+
api.get(`/api/submissions/by-source/${taskId}`).then(r => {
|
| 1007 |
+
const list = (r.data && r.data.submissions) || [];
|
| 1008 |
+
setUserSubmissions(prev => ({ ...prev, [taskId]: list }));
|
| 1009 |
+
requestAnimationFrame(() => setSpacerHeights(prev => ({ ...prev, [taskId]: 0 })));
|
| 1010 |
+
}).catch(() => {
|
| 1011 |
+
requestAnimationFrame(() => setSpacerHeights(prev => ({ ...prev, [taskId]: 0 })));
|
| 1012 |
+
});
|
| 1013 |
+
} else {
|
| 1014 |
+
// Fallback
|
| 1015 |
+
requestAnimationFrame(() => requestAnimationFrame(() => fetchUserSubmissions(tutorialTasks)));
|
| 1016 |
+
}
|
| 1017 |
});
|
| 1018 |
+
});
|
| 1019 |
} else {
|
| 1020 |
|
| 1021 |
}
|