mirror of
https://github.com/THU-MAIC/OpenMAIC.git
synced 2026-10-12 04:39:39 +08:00
fix(courses): inherit folder context when importing from inside a folder
Per review (wyuc, CHANGES_REQUESTED on 37be4716):
[P1] Courses imported from inside a folder were silently placed at the
root. The import contract now carries the new stageId to the success
callback; the page captures the active folder when the file picker opens
(not when the async import resolves) and files the imported course into
that folder before the list refresh, so the card appears immediately and
the folder count increments. Root imports remain ungrouped. A failed
folder assignment surfaces an explicit error toast instead of silently
falling back.
This commit is contained in:
+26
-6
@@ -246,11 +246,31 @@ function HomePage() {
|
||||
}
|
||||
};
|
||||
|
||||
const { importing, fileInputRef, triggerFileSelect, handleFileChange } = useImportClassroom(
|
||||
() => {
|
||||
loadClassrooms();
|
||||
},
|
||||
);
|
||||
// Capture the active folder when an import starts so the imported course
|
||||
// lands in that folder, not whichever folder is active when the async import
|
||||
// resolves (the user may have navigated away in the meantime).
|
||||
const importFolderRef = useRef<string | undefined>(undefined);
|
||||
const handleImportSuccess = async (importedStageId: string) => {
|
||||
const folderId = importFolderRef.current;
|
||||
importFolderRef.current = undefined;
|
||||
// File the imported course into the folder that was active when the
|
||||
// import began, before refreshing the list so the card appears in place.
|
||||
if (folderId) {
|
||||
try {
|
||||
await setStageFolder(importedStageId, folderId);
|
||||
} catch (err) {
|
||||
log.error('Failed to assign imported course to folder:', err);
|
||||
toast.error(t('classroom.moveFailed'));
|
||||
}
|
||||
}
|
||||
await loadClassrooms();
|
||||
};
|
||||
const { importing, fileInputRef, triggerFileSelect, handleFileChange } =
|
||||
useImportClassroom(handleImportSuccess);
|
||||
const triggerImport = () => {
|
||||
importFolderRef.current = currentFolderId;
|
||||
triggerFileSelect();
|
||||
};
|
||||
|
||||
const {
|
||||
importing: pptxImporting,
|
||||
@@ -1035,7 +1055,7 @@ function HomePage() {
|
||||
</AnimatePresence>
|
||||
|
||||
<button
|
||||
onClick={triggerFileSelect}
|
||||
onClick={triggerImport}
|
||||
disabled={importing}
|
||||
className="group/import grid grid-cols-[auto_0fr] hover:grid-cols-[auto_1fr] items-center gap-1 rounded-full px-1.5 py-0.5 text-[12px] text-muted-foreground/35 hover:text-muted-foreground/70 hover:bg-muted/50 transition-all duration-200 cursor-pointer"
|
||||
>
|
||||
|
||||
@@ -26,7 +26,7 @@ export type ImportPhase =
|
||||
| 'writingCourse'
|
||||
| 'done';
|
||||
|
||||
export function useImportClassroom(onSuccess?: () => void) {
|
||||
export function useImportClassroom(onSuccess?: (importedStageId: string) => void) {
|
||||
const [importing, setImporting] = useState(false);
|
||||
const [phase, setPhase] = useState<ImportPhase>('idle');
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
@@ -236,7 +236,7 @@ export function useImportClassroom(onSuccess?: () => void) {
|
||||
// 6. Done
|
||||
setPhase('done');
|
||||
toast.success(t('import.success'), { id: toastId });
|
||||
onSuccess?.();
|
||||
onSuccess?.(newStageId);
|
||||
} catch (error) {
|
||||
log.error('Classroom ZIP import failed:', error);
|
||||
// Media files are a separate legacy domain and cannot join the document transaction.
|
||||
|
||||
Reference in New Issue
Block a user