reassigning modules works

This commit is contained in:
2024-09-20 13:11:09 -06:00
parent 4f8360164d
commit 71ffe61715
12 changed files with 304 additions and 88 deletions

View File

@@ -28,11 +28,13 @@ export const PUT = async (
} }
) => ) =>
await withErrorHandling(async () => { await withErrorHandling(async () => {
const { const { assignment, previousModuleName, previousAssignmentName } =
assignment, (await request.json()) as {
previousModuleName, assignment: LocalAssignment;
}: { assignment: LocalAssignment; previousModuleName?: string } = previousModuleName?: string;
await request.json(); previousAssignmentName?: string;
};
await fileStorageService.assignments.updateOrCreateAssignment({ await fileStorageService.assignments.updateOrCreateAssignment({
courseName, courseName,
moduleName, moduleName,
@@ -40,9 +42,17 @@ export const PUT = async (
assignment, assignment,
}); });
if(previousModuleName !== moduleName) if (
{ previousModuleName &&
fileStorageService.assignments. previousAssignmentName &&
(assignment.name !== previousAssignmentName ||
moduleName !== previousModuleName)
) {
fileStorageService.assignments.delete({
courseName,
moduleName: previousModuleName,
assignmentName: previousAssignmentName,
});
} }
return Response.json({}); return Response.json({});

View File

@@ -1,3 +1,4 @@
import { LocalQuiz } from "@/models/local/quiz/localQuiz";
import { fileStorageService } from "@/services/fileStorage/fileStorageService"; import { fileStorageService } from "@/services/fileStorage/fileStorageService";
import { withErrorHandling } from "@/services/withErrorHandling"; import { withErrorHandling } from "@/services/withErrorHandling";
@@ -23,13 +24,31 @@ export const PUT = async (
}: { params: { courseName: string; moduleName: string; quizName: string } } }: { params: { courseName: string; moduleName: string; quizName: string } }
) => ) =>
await withErrorHandling(async () => { await withErrorHandling(async () => {
const quiz = await request.json(); const { quiz, previousModuleName, previousQuizName } =
(await request.json()) as {
quiz: LocalQuiz;
previousModuleName?: string;
previousQuizName?: string;
};
await fileStorageService.quizzes.updateQuiz( await fileStorageService.quizzes.updateQuiz(
courseName, courseName,
moduleName, moduleName,
quizName, quizName,
quiz quiz
); );
if (
previousModuleName &&
previousQuizName &&
(quiz.name !== previousQuizName ||
moduleName !== previousModuleName)
) {
fileStorageService.quizzes.delete({
courseName,
moduleName: previousModuleName,
quizName: previousQuizName,
});
}
return Response.json({}); return Response.json({});
}); });

View File

@@ -3,7 +3,7 @@ import {
getDateFromStringOrThrow, getDateFromStringOrThrow,
getDateOnlyMarkdownString, getDateOnlyMarkdownString,
} from "@/models/local/timeUtils"; } from "@/models/local/timeUtils";
import { useDraggingContext } from "../context/draggingContext"; import { DraggableItem, useDraggingContext } from "../context/draggingContext";
import { useCalendarItemsContext } from "../context/calendarItemsContext"; import { useCalendarItemsContext } from "../context/calendarItemsContext";
import { useCourseContext } from "../context/courseContext"; import { useCourseContext } from "../context/courseContext";
import Link from "next/link"; import Link from "next/link";
@@ -40,7 +40,7 @@ export default function Day({ day, month }: { day: string; month: number }) {
const meetingClasses = classOnThisDay ? " bg-slate-900 " : " "; const meetingClasses = classOnThisDay ? " bg-slate-900 " : " ";
const monthClass = isInSameMonth const monthClass = isInSameMonth
? isToday ? isToday
? " border border-blue-700 border-[3px] shadow-[0_0px_10px_0px] shadow-blue-500/50 " ? " border border-blue-700 shadow-[0_0px_10px_0px] shadow-blue-500/50 "
: " border border-slate-700 " : " border border-slate-700 "
: " "; : " ";
@@ -50,7 +50,7 @@ export default function Day({ day, month }: { day: string; month: number }) {
onDrop={(e) => itemDropOnDay(e, day)} onDrop={(e) => itemDropOnDay(e, day)}
onDragOver={(e) => e.preventDefault()} onDragOver={(e) => e.preventDefault()}
> >
<DropTargetStyling draggingClassName="bg-slate-800 shadow-2xl "> <DropTargetStyling draggingClassName="bg-slate-900 shadow-[0_0px_10px_0px] shadow-blue-800/50 ">
<DayTitle day={day} dayAsDate={dayAsDate} /> <DayTitle day={day} dayAsDate={dayAsDate} />
<div> <div>
{todaysAssignments.map(({ assignment, moduleName, status }) => ( {todaysAssignments.map(({ assignment, moduleName, status }) => (
@@ -192,8 +192,8 @@ function DraggableListItem({
href={getModuleItemUrl(courseName, moduleName, type, item.name)} href={getModuleItemUrl(courseName, moduleName, type, item.name)}
shallow={true} shallow={true}
className={ className={
" border rounded-sm px-1 mx-1 break-all mb-1 " + " border rounded-sm px-1 mx-1 break-words mb-1 " +
" bg-slate-800 " + " bg-slate-800 " +
" block " + " block " +
(status === "localOnly" && " text-slate-500 border-slate-600 ") + (status === "localOnly" && " text-slate-500 border-slate-600 ") +
(status === "unPublished" && " border-rose-900 ") + (status === "unPublished" && " border-rose-900 ") +
@@ -202,14 +202,12 @@ function DraggableListItem({
role="button" role="button"
draggable="true" draggable="true"
onDragStart={(e) => { onDragStart={(e) => {
e.dataTransfer.setData( const draggableItem: DraggableItem = {
"draggableItem", type,
JSON.stringify({ item,
type, sourceModuleName: moduleName,
item, };
sourceModuleName: moduleName, e.dataTransfer.setData("draggableItem", JSON.stringify(draggableItem));
})
);
dragStart(); dragStart();
}} }}
> >

View File

@@ -1,6 +1,6 @@
"use client"; "use client";
import { ReactNode, useCallback, DragEvent, useState } from "react"; import { ReactNode, useCallback, DragEvent, useState, useEffect } from "react";
import { DraggingContext } from "./draggingContext"; import { DraggableItem, DraggingContext } from "./draggingContext";
import { useUpdateQuizMutation } from "@/hooks/localCourse/quizHooks"; import { useUpdateQuizMutation } from "@/hooks/localCourse/quizHooks";
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks"; import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
import { LocalQuiz } from "@/models/local/quiz/localQuiz"; import { LocalQuiz } from "@/models/local/quiz/localQuiz";
@@ -24,12 +24,29 @@ export default function DraggingContextProvider({
const { data: settings } = useLocalCourseSettingsQuery(); const { data: settings } = useLocalCourseSettingsQuery();
const [isDragging, setIsDragging] = useState(false); const [isDragging, setIsDragging] = useState(false);
useEffect(() => {
const handleDrop = () => {
console.log("drop on window");
setIsDragging(false);
};
const preventDefault = (e: globalThis.DragEvent) => e.preventDefault();
if (typeof window !== "undefined") {
window.addEventListener("drop", handleDrop);
window.addEventListener("dragover", preventDefault);
}
return () => {
window.removeEventListener("drop", handleDrop);
window.addEventListener("dragover", preventDefault);
};
}, []);
const dragStart = useCallback(() => setIsDragging(true), []); const dragStart = useCallback(() => setIsDragging(true), []);
const itemDropOnModule = useCallback( const itemDropOnModule = useCallback(
(e: DragEvent<HTMLDivElement>, moduleName: string) => { (e: DragEvent<HTMLDivElement>, dropModuleName: string) => {
console.log("dropping on module");
const rawData = e.dataTransfer.getData("draggableItem"); const rawData = e.dataTransfer.getData("draggableItem");
const itemBeingDragged = JSON.parse(rawData); const itemBeingDragged: DraggableItem = JSON.parse(rawData);
if (itemBeingDragged) { if (itemBeingDragged) {
if (itemBeingDragged.type === "quiz") { if (itemBeingDragged.type === "quiz") {
@@ -42,17 +59,45 @@ export default function DraggingContextProvider({
} }
setIsDragging(false); setIsDragging(false);
function updateQuiz() {} function updateQuiz() {
function updateAssignment() {} const quiz = itemBeingDragged.item as LocalQuiz;
function updatePage() {}
updateQuizMutation.mutate({
quiz: quiz,
quizName: quiz.name,
moduleName: dropModuleName,
previousModuleName: itemBeingDragged.sourceModuleName,
previousQuizName: quiz.name,
});
}
function updateAssignment() {
const assignment = itemBeingDragged.item as LocalAssignment;
updateAssignmentMutation.mutate({
assignment,
previousModuleName: itemBeingDragged.sourceModuleName,
moduleName: dropModuleName,
assignmentName: assignment.name,
previousAssignmentName: assignment.name,
});
}
function updatePage() {
const page = itemBeingDragged.item as LocalCoursePage;
updatePageMutation.mutate({
page,
moduleName: dropModuleName,
pageName: page.name,
previousPageName: page.name,
previousModuleName: itemBeingDragged.sourceModuleName,
});
}
}, },
[] [updateAssignmentMutation, updatePageMutation, updateQuizMutation]
); );
const itemDropOnDay = useCallback( const itemDropOnDay = useCallback(
(e: DragEvent<HTMLDivElement>, day: string) => { (e: DragEvent<HTMLDivElement>, day: string) => {
const rawData = e.dataTransfer.getData("draggableItem"); const rawData = e.dataTransfer.getData("draggableItem");
const itemBeingDragged = JSON.parse(rawData); const itemBeingDragged: DraggableItem = JSON.parse(rawData);
if (itemBeingDragged) { if (itemBeingDragged) {
const dayAsDate = getDateWithDefaultDueTime(); const dayAsDate = getDateWithDefaultDueTime();
@@ -85,6 +130,8 @@ export default function DraggingContextProvider({
quiz: quiz, quiz: quiz,
quizName: quiz.name, quizName: quiz.name,
moduleName: itemBeingDragged.sourceModuleName, moduleName: itemBeingDragged.sourceModuleName,
previousModuleName: itemBeingDragged.sourceModuleName,
previousQuizName: quiz.name,
}); });
} }
function updatePage(dayAsDate: Date) { function updatePage(dayAsDate: Date) {
@@ -97,6 +144,8 @@ export default function DraggingContextProvider({
page, page,
moduleName: itemBeingDragged.sourceModuleName, moduleName: itemBeingDragged.sourceModuleName,
pageName: page.name, pageName: page.name,
previousPageName: page.name,
previousModuleName: itemBeingDragged.sourceModuleName,
}); });
} }
function updateAssignment(dayAsDate: Date) { function updateAssignment(dayAsDate: Date) {
@@ -115,8 +164,10 @@ export default function DraggingContextProvider({
}; };
updateAssignmentMutation.mutate({ updateAssignmentMutation.mutate({
assignment, assignment,
previousModuleName: itemBeingDragged.sourceModuleName,
moduleName: itemBeingDragged.sourceModuleName, moduleName: itemBeingDragged.sourceModuleName,
assignmentName: assignment.name, assignmentName: assignment.name,
previousAssignmentName: assignment.name,
}); });
} }
}, },

View File

@@ -13,7 +13,6 @@ import {
} from "@/hooks/localCourse/quizHooks"; } from "@/hooks/localCourse/quizHooks";
import { IModuleItem } from "@/models/local/IModuleItem"; import { IModuleItem } from "@/models/local/IModuleItem";
import { import {
dateToMarkdownString,
getDateFromString, getDateFromString,
getDateFromStringOrThrow, getDateFromStringOrThrow,
getDateOnlyMarkdownString, getDateOnlyMarkdownString,
@@ -24,6 +23,8 @@ import NewItemForm from "./NewItemForm";
import { ModuleCanvasStatus } from "./ModuleCanvasStatus"; import { ModuleCanvasStatus } from "./ModuleCanvasStatus";
import ClientOnly from "@/components/ClientOnly"; import ClientOnly from "@/components/ClientOnly";
import ExpandIcon from "../../../../components/icons/ExpandIcon"; import ExpandIcon from "../../../../components/icons/ExpandIcon";
import { useDraggingContext } from "../context/draggingContext";
import DropTargetStyling from "../calendar/DropTargetStyling";
export default function ExpandableModule({ export default function ExpandableModule({
moduleName, moduleName,
@@ -33,6 +34,7 @@ export default function ExpandableModule({
const { data: assignmentNames } = useAssignmentNamesQuery(moduleName); const { data: assignmentNames } = useAssignmentNamesQuery(moduleName);
const { data: quizNames } = useQuizNamesQuery(moduleName); const { data: quizNames } = useQuizNamesQuery(moduleName);
const { data: pageNames } = usePageNamesQuery(moduleName); const { data: pageNames } = usePageNamesQuery(moduleName);
const { itemDropOnModule } = useDraggingContext();
const { data: assignments } = useAssignmentsQueries( const { data: assignments } = useAssignmentsQueries(
moduleName, moduleName,
@@ -74,56 +76,63 @@ export default function ExpandableModule({
const expandRef = useRef<HTMLDivElement | null>(null); const expandRef = useRef<HTMLDivElement | null>(null);
return ( return (
<div className="bg-slate-800 rounded-lg p-3 border border-slate-600 mb-3"> <div
<div className="bg-slate-800 rounded-lg border border-slate-600 mb-3"
className="font-bold flex flex-row justify-between " onDrop={(e) => itemDropOnModule(e, moduleName)}
role="button" onDragOver={(e) => e.preventDefault()}
onClick={() => setExpanded((e) => !e)} >
> <DropTargetStyling draggingClassName="shadow-[0_0px_10px_0px] shadow-blue-500/50 ">
<div>{moduleName}</div> <div className=" p-3 ">
<div className="flex flex-row"> <div
<ClientOnly> className="font-bold flex flex-row justify-between "
<ModuleCanvasStatus moduleName={moduleName} /> role="button"
</ClientOnly> onClick={() => setExpanded((e) => !e)}
<ExpandIcon >
style={{ <div>{moduleName}</div>
...(expanded ? { rotate: "-90deg" } : {}), <div className="flex flex-row">
}} <ClientOnly>
/> <ModuleCanvasStatus moduleName={moduleName} />
</div> </ClientOnly>
</div> <ExpandIcon
<div style={{
ref={expandRef} ...(expanded ? { rotate: "-90deg" } : {}),
className={` overflow-hidden transition-all `} }}
style={{ />
maxHeight: expanded ? expandRef?.current?.scrollHeight : "0",
}}
>
<Modal buttonText="New Item">
{({ closeModal }) => (
<div>
<NewItemForm moduleName={moduleName} onCreate={closeModal} />
<br />
<button onClick={closeModal}>close</button>
</div> </div>
)} </div>
</Modal> <div
<div className="grid grid-cols-[auto_1fr]"> ref={expandRef}
className={` overflow-hidden transition-all `}
style={{
maxHeight: expanded ? expandRef?.current?.scrollHeight : "0",
}}
>
<Modal buttonText="New Item">
{({ closeModal }) => (
<div>
<NewItemForm moduleName={moduleName} onCreate={closeModal} />
<br />
<button onClick={closeModal}>close</button>
</div>
)}
</Modal>
<div className="grid grid-cols-[auto_1fr]">
{moduleItems.map(({ type, item }) => {
const date = getDateFromString(item.dueAt);
{moduleItems.map(({ type, item }) => { return (
const date = getDateFromString(item.dueAt); <Fragment key={item.name + type}>
<div className="text-end text-slate-500 me-2">
return ( {date && getDateOnlyMarkdownString(date)}
<Fragment key={item.name + type}> </div>
<div className="text-end text-slate-500 me-2"> <div className="">{item.name}</div>
{date && getDateOnlyMarkdownString(date)} </Fragment>
</div> );
<div className="">{item.name}</div> })}
</Fragment> </div>
); </div>
})}
</div> </div>
</div> </DropTargetStyling>
</div> </div>
); );
} }

View File

@@ -56,6 +56,8 @@ export default function EditAssignment({
assignment: updatedAssignment, assignment: updatedAssignment,
moduleName, moduleName,
assignmentName, assignmentName,
previousModuleName: moduleName,
previousAssignmentName: assignment.name,
}); });
} }
setError(""); setError("");

View File

@@ -95,13 +95,36 @@ export const useUpdateAssignmentMutation = () => {
assignment, assignment,
moduleName, moduleName,
previousModuleName, previousModuleName,
previousAssignmentName,
assignmentName, assignmentName,
}: { }: {
assignment: LocalAssignment; assignment: LocalAssignment;
moduleName: string; moduleName: string;
previousModuleName: string; previousModuleName: string;
previousAssignmentName: string;
assignmentName: string; assignmentName: string;
}) => { }) => {
if (
previousAssignmentName &&
previousModuleName &&
(previousAssignmentName !== assignment.name ||
previousModuleName !== moduleName)
) {
queryClient.removeQueries({
queryKey: localCourseKeys.assignment(
courseName,
previousModuleName,
previousAssignmentName
),
});
queryClient.removeQueries({
queryKey: localCourseKeys.assignmentNames(
courseName,
previousModuleName
),
});
}
queryClient.setQueryData( queryClient.setQueryData(
localCourseKeys.assignment(courseName, moduleName, assignmentName), localCourseKeys.assignment(courseName, moduleName, assignmentName),
assignment assignment
@@ -113,7 +136,11 @@ export const useUpdateAssignmentMutation = () => {
encodeURIComponent(moduleName) + encodeURIComponent(moduleName) +
"/assignments/" + "/assignments/" +
encodeURIComponent(assignmentName); encodeURIComponent(assignmentName);
await axiosClient.put(url, { assignment, previousModuleName }); await axiosClient.put(url, {
assignment,
previousModuleName,
previousAssignmentName,
});
}, },
onSuccess: (_, { moduleName, assignmentName }) => { onSuccess: (_, { moduleName, assignmentName }) => {
queryClient.invalidateQueries({ queryClient.invalidateQueries({

View File

@@ -87,11 +87,31 @@ export const useUpdatePageMutation = () => {
page, page,
moduleName, moduleName,
pageName, pageName,
previousModuleName,
previousPageName,
}: { }: {
page: LocalCoursePage; page: LocalCoursePage;
moduleName: string; moduleName: string;
pageName: string; pageName: string;
previousModuleName: string;
previousPageName: string;
}) => { }) => {
if (
previousPageName &&
previousModuleName &&
(previousPageName !== page.name || previousModuleName !== moduleName)
) {
queryClient.removeQueries({
queryKey: localCourseKeys.page(
courseName,
previousModuleName,
previousPageName
),
});
queryClient.removeQueries({
queryKey: localCourseKeys.pageNames(courseName, moduleName),
});
}
queryClient.setQueryData( queryClient.setQueryData(
localCourseKeys.page(courseName, moduleName, pageName), localCourseKeys.page(courseName, moduleName, pageName),
page page
@@ -116,7 +136,6 @@ export const useUpdatePageMutation = () => {
}); });
}; };
export const useCreatePageMutation = () => { export const useCreatePageMutation = () => {
const { courseName } = useCourseContext(); const { courseName } = useCourseContext();
const queryClient = useQueryClient(); const queryClient = useQueryClient();

View File

@@ -10,12 +10,15 @@ import { localCourseKeys } from "./localCourseKeys";
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext"; import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
import { axiosClient } from "@/services/axiosUtils"; import { axiosClient } from "@/services/axiosUtils";
export function getQuizNamesQueryConfig(
export function getQuizNamesQueryConfig(courseName: string, moduleName: string) { courseName: string,
moduleName: string
) {
return { return {
queryKey: localCourseKeys.quizNames(courseName, moduleName), queryKey: localCourseKeys.quizNames(courseName, moduleName),
queryFn: async (): Promise<string[]> => { queryFn: async (): Promise<string[]> => {
const url = "/api/courses/" + const url =
"/api/courses/" +
encodeURIComponent(courseName) + encodeURIComponent(courseName) +
"/modules/" + "/modules/" +
encodeURIComponent(moduleName) + encodeURIComponent(moduleName) +
@@ -77,11 +80,31 @@ export const useUpdateQuizMutation = () => {
quiz, quiz,
moduleName, moduleName,
quizName, quizName,
previousModuleName,
previousQuizName,
}: { }: {
quiz: LocalQuiz; quiz: LocalQuiz;
moduleName: string; moduleName: string;
quizName: string; quizName: string;
previousModuleName: string;
previousQuizName: string;
}) => { }) => {
if (
previousQuizName &&
previousModuleName &&
(previousQuizName !== quiz.name || previousModuleName !== moduleName)
) {
queryClient.removeQueries({
queryKey: localCourseKeys.quiz(
courseName,
previousModuleName,
previousQuizName
),
});
queryClient.removeQueries({
queryKey: localCourseKeys.quizNames(courseName, previousModuleName),
});
}
queryClient.setQueryData( queryClient.setQueryData(
localCourseKeys.quiz(courseName, moduleName, quizName), localCourseKeys.quiz(courseName, moduleName, quizName),
quiz quiz
@@ -93,7 +116,15 @@ export const useUpdateQuizMutation = () => {
encodeURIComponent(moduleName) + encodeURIComponent(moduleName) +
"/quizzes/" + "/quizzes/" +
encodeURIComponent(quizName); encodeURIComponent(quizName);
await axiosClient.put(url, quiz); await axiosClient.put(url, {
quiz,
previousModuleName,
previousQuizName,
});
// queryClient.fetchQuery(
// getQuizNamesQueryConfig(courseName, previousModuleName)
// );
}, },
onSuccess: (_, { moduleName, quizName }) => { onSuccess: (_, { moduleName, quizName }) => {
queryClient.invalidateQueries({ queryClient.invalidateQueries({
@@ -106,7 +137,6 @@ export const useUpdateQuizMutation = () => {
}); });
}; };
export const useCreateQuizMutation = () => { export const useCreateQuizMutation = () => {
const { courseName } = useCourseContext(); const { courseName } = useCourseContext();
const queryClient = useQueryClient(); const queryClient = useQueryClient();

View File

@@ -1,4 +1,7 @@
import { verifyDateOrThrow, verifyDateStringOrUndefined } from "../../timeUtils"; import {
verifyDateOrThrow,
verifyDateStringOrUndefined,
} from "../../timeUtils";
import { LocalQuiz } from "../localQuiz"; import { LocalQuiz } from "../localQuiz";
import { quizQuestionMarkdownUtils } from "./quizQuestionMarkdownUtils"; import { quizQuestionMarkdownUtils } from "./quizQuestionMarkdownUtils";
@@ -76,7 +79,6 @@ const getQuizWithOnlySettings = (settings: string): LocalQuiz => {
const rawDueAt = extractLabelValue(settings, "DueAt"); const rawDueAt = extractLabelValue(settings, "DueAt");
const dueAt = verifyDateOrThrow(rawDueAt, "DueAt"); const dueAt = verifyDateOrThrow(rawDueAt, "DueAt");
const rawLockAt = extractLabelValue(settings, "LockAt"); const rawLockAt = extractLabelValue(settings, "LockAt");
const lockAt = verifyDateStringOrUndefined(rawLockAt); const lockAt = verifyDateStringOrUndefined(rawLockAt);
@@ -104,6 +106,16 @@ const getQuizWithOnlySettings = (settings: string): LocalQuiz => {
export const quizMarkdownUtils = { export const quizMarkdownUtils = {
toMarkdown(quiz: LocalQuiz): string { toMarkdown(quiz: LocalQuiz): string {
if (!quiz) {
throw Error(`quiz was undefined, cannot parse markdown`);
}
if (
typeof quiz.questions === "undefined" ||
typeof quiz.oneQuestionAtATime === "undefined"
) {
console.log("quiz is probably not a quiz", quiz);
throw Error(`quiz ${quiz.name} is probably not a quiz`);
}
const questionMarkdownArray = quiz.questions.map((q) => const questionMarkdownArray = quiz.questions.map((q) =>
quizQuestionMarkdownUtils.toMarkdown(q) quizQuestionMarkdownUtils.toMarkdown(q)
); );

View File

@@ -65,4 +65,24 @@ export const assignmentsFileStorageService = {
console.log(`Saving assignment ${filePath}`); console.log(`Saving assignment ${filePath}`);
await fs.writeFile(filePath, assignmentMarkdown); await fs.writeFile(filePath, assignmentMarkdown);
}, },
async delete({
courseName,
moduleName,
assignmentName,
}: {
courseName: string;
moduleName: string;
assignmentName: string;
}) {
const filePath = path.join(
basePath,
courseName,
moduleName,
"assignments",
assignmentName + ".md"
);
console.log("removing assignment", filePath);
await fs.unlink(filePath)
}
}; };

View File

@@ -55,4 +55,23 @@ export const quizFileStorageService = {
console.log(`Saving quiz ${filePath}`); console.log(`Saving quiz ${filePath}`);
await fs.writeFile(filePath, quizMarkdown); await fs.writeFile(filePath, quizMarkdown);
}, },
async delete({
courseName,
moduleName,
quizName,
}: {
courseName: string;
moduleName: string;
quizName: string;
}) {
const filePath = path.join(
basePath,
courseName,
moduleName,
"quizzes",
quizName + ".md"
);
console.log("removing quiz", filePath);
await fs.unlink(filePath)
}
}; };