mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-25 23:28:33 -06:00
working on context menu
This commit is contained in:
@@ -74,3 +74,21 @@ export const POST = async (
|
|||||||
});
|
});
|
||||||
return Response.json({});
|
return Response.json({});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const DELETE = async (
|
||||||
|
_request: Request,
|
||||||
|
{
|
||||||
|
params: { courseName, moduleName, assignmentName },
|
||||||
|
}: {
|
||||||
|
params: { courseName: string; moduleName: string; assignmentName: string };
|
||||||
|
}
|
||||||
|
) =>
|
||||||
|
await withErrorHandling(async () => {
|
||||||
|
fileStorageService.assignments.delete({
|
||||||
|
courseName,
|
||||||
|
moduleName,
|
||||||
|
assignmentName,
|
||||||
|
});
|
||||||
|
|
||||||
|
return Response.json({});
|
||||||
|
});
|
||||||
|
|||||||
@@ -61,3 +61,18 @@ export const POST = async (
|
|||||||
);
|
);
|
||||||
return Response.json({});
|
return Response.json({});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const DELETE = async (
|
||||||
|
_request: Request,
|
||||||
|
{
|
||||||
|
params: { courseName, moduleName, pageName },
|
||||||
|
}: { params: { courseName: string; moduleName: string; pageName: string } }
|
||||||
|
) =>
|
||||||
|
await withErrorHandling(async () => {
|
||||||
|
fileStorageService.pages.delete({
|
||||||
|
courseName,
|
||||||
|
moduleName,
|
||||||
|
pageName,
|
||||||
|
});
|
||||||
|
return Response.json({});
|
||||||
|
});
|
||||||
|
|||||||
@@ -40,8 +40,7 @@ export const PUT = async (
|
|||||||
if (
|
if (
|
||||||
previousModuleName &&
|
previousModuleName &&
|
||||||
previousQuizName &&
|
previousQuizName &&
|
||||||
(quiz.name !== previousQuizName ||
|
(quiz.name !== previousQuizName || moduleName !== previousModuleName)
|
||||||
moduleName !== previousModuleName)
|
|
||||||
) {
|
) {
|
||||||
fileStorageService.quizzes.delete({
|
fileStorageService.quizzes.delete({
|
||||||
courseName,
|
courseName,
|
||||||
@@ -68,3 +67,18 @@ export const POST = async (
|
|||||||
);
|
);
|
||||||
return Response.json({});
|
return Response.json({});
|
||||||
});
|
});
|
||||||
|
export const DELETE = async (
|
||||||
|
_request: Request,
|
||||||
|
{
|
||||||
|
params: { courseName, moduleName, quizName },
|
||||||
|
}: { params: { courseName: string; moduleName: string; quizName: string } }
|
||||||
|
) =>
|
||||||
|
await withErrorHandling(async () => {
|
||||||
|
fileStorageService.quizzes.delete({
|
||||||
|
courseName,
|
||||||
|
moduleName,
|
||||||
|
quizName,
|
||||||
|
});
|
||||||
|
|
||||||
|
return Response.json({});
|
||||||
|
});
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import { getLectureUrl } from "@/services/urlUtils";
|
|||||||
import DropTargetStyling from "../../../../../components/DropTargetStyling";
|
import DropTargetStyling from "../../../../../components/DropTargetStyling";
|
||||||
import { ItemInDay } from "./ItemInDay";
|
import { ItemInDay } from "./ItemInDay";
|
||||||
import { useTodaysItems } from "./useTodaysItems";
|
import { useTodaysItems } from "./useTodaysItems";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { DayContextMenu } from "./DayContextMenu";
|
||||||
|
|
||||||
export default function Day({ day, month }: { day: string; month: number }) {
|
export default function Day({ day, month }: { day: string; month: number }) {
|
||||||
const dayAsDate = getDateFromStringOrThrow(
|
const dayAsDate = getDateFromStringOrThrow(
|
||||||
@@ -24,6 +26,9 @@ export default function Day({ day, month }: { day: string; month: number }) {
|
|||||||
|
|
||||||
const { data: settings } = useLocalCourseSettingsQuery();
|
const { data: settings } = useLocalCourseSettingsQuery();
|
||||||
const { itemDropOnDay } = useDraggingContext();
|
const { itemDropOnDay } = useDraggingContext();
|
||||||
|
const [contextCoordinates, setContextCoordinates] = useState<
|
||||||
|
{ x: number; y: number } | undefined
|
||||||
|
>();
|
||||||
|
|
||||||
const { todaysAssignments, todaysQuizzes, todaysPages } = useTodaysItems(day);
|
const { todaysAssignments, todaysQuizzes, todaysPages } = useTodaysItems(day);
|
||||||
|
|
||||||
@@ -43,8 +48,17 @@ export default function Day({ day, month }: { day: string; month: number }) {
|
|||||||
className={" rounded-lg m-1 min-h-10 " + meetingClasses + monthClass}
|
className={" rounded-lg m-1 min-h-10 " + meetingClasses + monthClass}
|
||||||
onDrop={(e) => itemDropOnDay(e, day)}
|
onDrop={(e) => itemDropOnDay(e, day)}
|
||||||
onDragOver={(e) => e.preventDefault()}
|
onDragOver={(e) => e.preventDefault()}
|
||||||
|
onContextMenu={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setContextCoordinates({ x: e.pageX, y: e.pageY });
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<DropTargetStyling draggingClassName="bg-slate-900 shadow-[0_0px_10px_0px] shadow-blue-800/50 ">
|
<DropTargetStyling draggingClassName="bg-slate-900 shadow-[0_0px_10px_0px] shadow-blue-800/50 ">
|
||||||
|
<DayContextMenu
|
||||||
|
day={day}
|
||||||
|
coordinates={contextCoordinates}
|
||||||
|
hideContextMenu={() => setContextCoordinates(undefined)}
|
||||||
|
/>
|
||||||
<DayTitle day={day} dayAsDate={dayAsDate} />
|
<DayTitle day={day} dayAsDate={dayAsDate} />
|
||||||
<div>
|
<div>
|
||||||
{todaysAssignments.map(
|
{todaysAssignments.map(
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import Modal from "@/components/Modal";
|
||||||
|
import React, { FC, useEffect, useRef } from "react";
|
||||||
|
import NewItemForm from "../../modules/NewItemForm";
|
||||||
|
|
||||||
|
export const DayContextMenu: FC<{
|
||||||
|
coordinates?: { x: number; y: number };
|
||||||
|
hideContextMenu: () => void;
|
||||||
|
day: string;
|
||||||
|
}> = ({ coordinates, hideContextMenu, day }) => {
|
||||||
|
const menuRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
// const handleContextMenu = (event: MouseEvent) => {
|
||||||
|
// event.preventDefault();
|
||||||
|
// setPosition({ x: event.pageX, y: event.pageY });
|
||||||
|
// setVisible(true);
|
||||||
|
// };
|
||||||
|
|
||||||
|
const handleClick = (event: MouseEvent) => {
|
||||||
|
if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
|
||||||
|
hideContextMenu();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
document.addEventListener("click", handleClick);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener("click", handleClick);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={
|
||||||
|
"absolute z-10 border bg-slate-900 border-slate-300 rounded shadow-lg w-48 " +
|
||||||
|
(!coordinates && "hidden")
|
||||||
|
}
|
||||||
|
style={{ top: coordinates?.y, left: coordinates?.x }}
|
||||||
|
onMouseDown={(e) => {
|
||||||
|
console.log(e.target);
|
||||||
|
e.stopPropagation();
|
||||||
|
hideContextMenu();
|
||||||
|
}}
|
||||||
|
ref={menuRef}
|
||||||
|
>
|
||||||
|
<Modal buttonText="Add Module Item">
|
||||||
|
{({ closeModal }) => (
|
||||||
|
<div>
|
||||||
|
<NewItemForm
|
||||||
|
creationDate={day}
|
||||||
|
onCreate={() => {
|
||||||
|
closeModal();
|
||||||
|
hideContextMenu();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<br />
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
closeModal();
|
||||||
|
hideContextMenu();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
close
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Modal>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -1,30 +1,55 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import ButtonSelect from "@/components/ButtonSelect";
|
import ButtonSelect from "@/components/ButtonSelect";
|
||||||
|
import SelectInput from "@/components/form/SelectInput";
|
||||||
import TextInput from "@/components/form/TextInput";
|
import TextInput from "@/components/form/TextInput";
|
||||||
import { Spinner } from "@/components/Spinner";
|
import { Spinner } from "@/components/Spinner";
|
||||||
import { useCreateAssignmentMutation } from "@/hooks/localCourse/assignmentHooks";
|
import { useCreateAssignmentMutation } from "@/hooks/localCourse/assignmentHooks";
|
||||||
|
import { useModuleNamesQuery } from "@/hooks/localCourse/localCourseModuleHooks";
|
||||||
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
||||||
import { useCreatePageMutation } from "@/hooks/localCourse/pageHooks";
|
import { useCreatePageMutation } from "@/hooks/localCourse/pageHooks";
|
||||||
import { useCreateQuizMutation } from "@/hooks/localCourse/quizHooks";
|
import { useCreateQuizMutation } from "@/hooks/localCourse/quizHooks";
|
||||||
import { AssignmentSubmissionType } from "@/models/local/assignment/assignmentSubmissionType";
|
import { AssignmentSubmissionType } from "@/models/local/assignment/assignmentSubmissionType";
|
||||||
import { LocalAssignmentGroup } from "@/models/local/assignment/localAssignmentGroup";
|
import { LocalAssignmentGroup } from "@/models/local/assignment/localAssignmentGroup";
|
||||||
import { dateToMarkdownString } from "@/models/local/timeUtils";
|
import {
|
||||||
|
dateToMarkdownString,
|
||||||
|
getDateFromString,
|
||||||
|
} from "@/models/local/timeUtils";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
|
||||||
export default function NewItemForm({
|
export default function NewItemForm({
|
||||||
moduleName,
|
moduleName: defaultModuleName,
|
||||||
onCreate = () => {},
|
onCreate = () => {},
|
||||||
|
creationDate,
|
||||||
}: {
|
}: {
|
||||||
moduleName: string;
|
moduleName?: string;
|
||||||
|
creationDate?: string;
|
||||||
onCreate?: () => void;
|
onCreate?: () => void;
|
||||||
}) {
|
}) {
|
||||||
|
const { data: settings } = useLocalCourseSettingsQuery();
|
||||||
|
const { data: modules } = useModuleNamesQuery();
|
||||||
const [type, setType] = useState<"Assignment" | "Quiz" | "Page">(
|
const [type, setType] = useState<"Assignment" | "Quiz" | "Page">(
|
||||||
"Assignment"
|
"Assignment"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [moduleName, setModuleName] = useState<string | undefined>(
|
||||||
|
defaultModuleName
|
||||||
|
);
|
||||||
|
|
||||||
const [name, setName] = useState("");
|
const [name, setName] = useState("");
|
||||||
|
|
||||||
|
const defaultDate = getDateFromString(
|
||||||
|
creationDate ? creationDate : dateToMarkdownString(new Date())
|
||||||
|
);
|
||||||
|
defaultDate?.setMinutes(settings.defaultDueTime.minute);
|
||||||
|
defaultDate?.setHours(settings.defaultDueTime.hour);
|
||||||
|
defaultDate?.setSeconds(0);
|
||||||
|
|
||||||
|
const [dueDate, setDueDate] = useState(
|
||||||
|
dateToMarkdownString(defaultDate ?? new Date())
|
||||||
|
);
|
||||||
const [assignmentGroup, setAssignmentGroup] =
|
const [assignmentGroup, setAssignmentGroup] =
|
||||||
useState<LocalAssignmentGroup>();
|
useState<LocalAssignmentGroup>();
|
||||||
const { data: settings } = useLocalCourseSettingsQuery();
|
|
||||||
const createAssignment = useCreateAssignmentMutation();
|
const createAssignment = useCreateAssignmentMutation();
|
||||||
const createPage = useCreatePageMutation();
|
const createPage = useCreatePageMutation();
|
||||||
const createQuiz = useCreateQuizMutation();
|
const createQuiz = useCreateQuizMutation();
|
||||||
@@ -37,8 +62,15 @@ export default function NewItemForm({
|
|||||||
className="flex flex-col gap-3"
|
className="flex flex-col gap-3"
|
||||||
onSubmit={(e) => {
|
onSubmit={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const dueAt = dateToMarkdownString(new Date());
|
const dueAt =
|
||||||
|
dueDate === ""
|
||||||
|
? dueDate
|
||||||
|
: dateToMarkdownString(defaultDate ?? new Date());
|
||||||
|
|
||||||
console.log("submitting");
|
console.log("submitting");
|
||||||
|
if (!moduleName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (type === "Assignment") {
|
if (type === "Assignment") {
|
||||||
createAssignment.mutate({
|
createAssignment.mutate({
|
||||||
assignment: {
|
assignment: {
|
||||||
@@ -84,6 +116,22 @@ export default function NewItemForm({
|
|||||||
onCreate();
|
onCreate();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<div>
|
||||||
|
<TextInput
|
||||||
|
label={type + " due date"}
|
||||||
|
value={dueDate ?? ""}
|
||||||
|
setValue={setDueDate}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<SelectInput
|
||||||
|
value={moduleName}
|
||||||
|
setValue={(m) => setModuleName(m)}
|
||||||
|
label={"Module"}
|
||||||
|
options={modules}
|
||||||
|
getOptionName={(m) => m}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<ButtonSelect<"Assignment" | "Quiz" | "Page">
|
<ButtonSelect<"Assignment" | "Quiz" | "Page">
|
||||||
options={["Assignment", "Quiz", "Page"]}
|
options={["Assignment", "Quiz", "Page"]}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
|
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
|
||||||
|
import Modal from "@/components/Modal";
|
||||||
import { Spinner } from "@/components/Spinner";
|
import { Spinner } from "@/components/Spinner";
|
||||||
import {
|
import {
|
||||||
useCanvasPagesQuery,
|
useCanvasPagesQuery,
|
||||||
@@ -7,10 +8,14 @@ import {
|
|||||||
useUpdateCanvasPageMutation,
|
useUpdateCanvasPageMutation,
|
||||||
} from "@/hooks/canvas/canvasPageHooks";
|
} from "@/hooks/canvas/canvasPageHooks";
|
||||||
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
||||||
import { usePageQuery } from "@/hooks/localCourse/pageHooks";
|
import {
|
||||||
|
useDeletePageMutation,
|
||||||
|
usePageQuery,
|
||||||
|
} from "@/hooks/localCourse/pageHooks";
|
||||||
import { baseCanvasUrl } from "@/services/canvas/canvasServiceUtils";
|
import { baseCanvasUrl } from "@/services/canvas/canvasServiceUtils";
|
||||||
import { getCourseUrl } from "@/services/urlUtils";
|
import { getCourseUrl } from "@/services/urlUtils";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export default function EditPageButtons({
|
export default function EditPageButtons({
|
||||||
@@ -20,6 +25,7 @@ export default function EditPageButtons({
|
|||||||
pageName: string;
|
pageName: string;
|
||||||
moduleName: string;
|
moduleName: string;
|
||||||
}) {
|
}) {
|
||||||
|
const router = useRouter();
|
||||||
const { courseName } = useCourseContext();
|
const { courseName } = useCourseContext();
|
||||||
const { data: settings } = useLocalCourseSettingsQuery();
|
const { data: settings } = useLocalCourseSettingsQuery();
|
||||||
const { data: page } = usePageQuery(moduleName, pageName);
|
const { data: page } = usePageQuery(moduleName, pageName);
|
||||||
@@ -27,6 +33,7 @@ export default function EditPageButtons({
|
|||||||
const createPageInCanvas = useCreateCanvasPageMutation();
|
const createPageInCanvas = useCreateCanvasPageMutation();
|
||||||
const updatePageInCanvas = useUpdateCanvasPageMutation();
|
const updatePageInCanvas = useUpdateCanvasPageMutation();
|
||||||
const deletePageInCanvas = useDeleteCanvasPageMutation();
|
const deletePageInCanvas = useDeleteCanvasPageMutation();
|
||||||
|
const deletePageLocal = useDeletePageMutation();
|
||||||
|
|
||||||
const pageInCanvas = canvasPages?.find((p) => p.title === pageName);
|
const pageInCanvas = canvasPages?.find((p) => p.title === pageName);
|
||||||
|
|
||||||
@@ -77,6 +84,36 @@ export default function EditPageButtons({
|
|||||||
Delete from Canvas
|
Delete from Canvas
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{!pageInCanvas && (
|
||||||
|
<Modal
|
||||||
|
buttonText="Delete Localy"
|
||||||
|
buttonClass="btn-danger"
|
||||||
|
modalWidth="w-1/5"
|
||||||
|
>
|
||||||
|
{({ closeModal }) => (
|
||||||
|
<div>
|
||||||
|
<div className="text-center">
|
||||||
|
Are you sure you want to delete this page locally?
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<div className="flex justify-around gap-3">
|
||||||
|
<button
|
||||||
|
onClick={async () => {
|
||||||
|
deletePageLocal
|
||||||
|
.mutateAsync({ moduleName, pageName })
|
||||||
|
.then(() => router.push(getCourseUrl(courseName)));
|
||||||
|
}}
|
||||||
|
className="btn-danger"
|
||||||
|
>
|
||||||
|
Yes
|
||||||
|
</button>
|
||||||
|
<button onClick={closeModal}>No</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Modal>
|
||||||
|
)}
|
||||||
<Link className="btn" href={getCourseUrl(courseName)} shallow={true}>
|
<Link className="btn" href={getCourseUrl(courseName)} shallow={true}>
|
||||||
Go Back
|
Go Back
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ export default function EditQuiz({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full flex flex-col align-middle px-1">
|
<div className="h-full flex flex-col align-middle px-1">
|
||||||
<div className={"min-h-96 flex flex-row w-full"}>
|
<div className={"min-h-96 h-full flex flex-row w-full"}>
|
||||||
{showHelp && (
|
{showHelp && (
|
||||||
<pre className=" max-w-96">
|
<pre className=" max-w-96">
|
||||||
<code>{helpString}</code>
|
<code>{helpString}</code>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
|
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
|
||||||
|
import Modal from "@/components/Modal";
|
||||||
import { Spinner } from "@/components/Spinner";
|
import { Spinner } from "@/components/Spinner";
|
||||||
import {
|
import {
|
||||||
useCanvasQuizzesQuery,
|
useCanvasQuizzesQuery,
|
||||||
@@ -6,10 +7,14 @@ import {
|
|||||||
useDeleteQuizFromCanvasMutation,
|
useDeleteQuizFromCanvasMutation,
|
||||||
} from "@/hooks/canvas/canvasQuizHooks";
|
} from "@/hooks/canvas/canvasQuizHooks";
|
||||||
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
||||||
import { useQuizQuery } from "@/hooks/localCourse/quizHooks";
|
import {
|
||||||
|
useDeleteQuizMutation,
|
||||||
|
useQuizQuery,
|
||||||
|
} from "@/hooks/localCourse/quizHooks";
|
||||||
import { baseCanvasUrl } from "@/services/canvas/canvasServiceUtils";
|
import { baseCanvasUrl } from "@/services/canvas/canvasServiceUtils";
|
||||||
import { getCourseUrl } from "@/services/urlUtils";
|
import { getCourseUrl } from "@/services/urlUtils";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
|
||||||
export function QuizButtons({
|
export function QuizButtons({
|
||||||
moduleName,
|
moduleName,
|
||||||
@@ -20,12 +25,14 @@ export function QuizButtons({
|
|||||||
moduleName: string;
|
moduleName: string;
|
||||||
toggleHelp: () => void;
|
toggleHelp: () => void;
|
||||||
}) {
|
}) {
|
||||||
|
const router = useRouter();
|
||||||
const { courseName } = useCourseContext();
|
const { courseName } = useCourseContext();
|
||||||
const { data: settings } = useLocalCourseSettingsQuery();
|
const { data: settings } = useLocalCourseSettingsQuery();
|
||||||
const { data: canvasQuizzes } = useCanvasQuizzesQuery();
|
const { data: canvasQuizzes } = useCanvasQuizzesQuery();
|
||||||
const { data: quiz } = useQuizQuery(moduleName, quizName);
|
const { data: quiz } = useQuizQuery(moduleName, quizName);
|
||||||
const addToCanvas = useAddQuizToCanvasMutation();
|
const addToCanvas = useAddQuizToCanvasMutation();
|
||||||
const deleteFromCanvas = useDeleteQuizFromCanvasMutation();
|
const deleteFromCanvas = useDeleteQuizFromCanvasMutation();
|
||||||
|
const deleteLocal = useDeleteQuizMutation();
|
||||||
|
|
||||||
const quizInCanvas = canvasQuizzes.find((c) => c.title === quizName);
|
const quizInCanvas = canvasQuizzes.find((c) => c.title === quizName);
|
||||||
|
|
||||||
@@ -65,6 +72,35 @@ export function QuizButtons({
|
|||||||
Delete from Canvas
|
Delete from Canvas
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
{!quizInCanvas && (
|
||||||
|
<Modal
|
||||||
|
buttonText="Delete Localy"
|
||||||
|
buttonClass="btn-danger"
|
||||||
|
modalWidth="w-1/5"
|
||||||
|
>
|
||||||
|
{({ closeModal }) => (
|
||||||
|
<div>
|
||||||
|
<div className="text-center">
|
||||||
|
Are you sure you want to delete this quiz locally?
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<div className="flex justify-around gap-3">
|
||||||
|
<button
|
||||||
|
onClick={async () => {
|
||||||
|
deleteLocal
|
||||||
|
.mutateAsync({ moduleName, quizName })
|
||||||
|
.then(() => router.push(getCourseUrl(courseName)));
|
||||||
|
}}
|
||||||
|
className="btn-danger"
|
||||||
|
>
|
||||||
|
Yes
|
||||||
|
</button>
|
||||||
|
<button onClick={closeModal}>No</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Modal>
|
||||||
|
)}
|
||||||
|
|
||||||
<Link className="btn" href={getCourseUrl(courseName)} shallow={true}>
|
<Link className="btn" href={getCourseUrl(courseName)} shallow={true}>
|
||||||
Go Back
|
Go Back
|
||||||
|
|||||||
@@ -5,10 +5,12 @@ export default function Modal({
|
|||||||
children,
|
children,
|
||||||
buttonText,
|
buttonText,
|
||||||
buttonClass = "",
|
buttonClass = "",
|
||||||
|
modalWidth = "w-1/3",
|
||||||
}: {
|
}: {
|
||||||
children: (props: { closeModal: () => void }) => ReactNode;
|
children: (props: { closeModal: () => void }) => ReactNode;
|
||||||
buttonText: string;
|
buttonText: string;
|
||||||
buttonClass?: string;
|
buttonClass?: string;
|
||||||
|
modalWidth?: string;
|
||||||
}) {
|
}) {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
@@ -35,7 +37,8 @@ export default function Modal({
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
}}
|
}}
|
||||||
className={
|
className={
|
||||||
` bg-slate-800 p-6 rounded-lg shadow-lg w-1/3 ` +
|
` bg-slate-800 p-6 rounded-lg shadow-lg ` +
|
||||||
|
modalWidth +
|
||||||
` transition-all duration-400 ` +
|
` transition-all duration-400 ` +
|
||||||
` ${isOpen ? "opacity-100" : "opacity-0"}`
|
` ${isOpen ? "opacity-100" : "opacity-0"}`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,9 +133,9 @@ export const useUpdatePageMutation = () => {
|
|||||||
queryClient.invalidateQueries({
|
queryClient.invalidateQueries({
|
||||||
queryKey: localCourseKeys.page(courseName, moduleName, pageName),
|
queryKey: localCourseKeys.page(courseName, moduleName, pageName),
|
||||||
});
|
});
|
||||||
// queryClient.invalidateQueries({
|
queryClient.invalidateQueries({
|
||||||
// queryKey: localCourseKeys.pageNames(courseName, moduleName),
|
queryKey: localCourseKeys.pageNames(courseName, moduleName),
|
||||||
// });
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -176,3 +176,41 @@ export const useCreatePageMutation = () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useDeletePageMutation = () => {
|
||||||
|
const { courseName } = useCourseContext();
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: async ({
|
||||||
|
moduleName,
|
||||||
|
pageName,
|
||||||
|
}: {
|
||||||
|
moduleName: string;
|
||||||
|
pageName: string;
|
||||||
|
}) => {
|
||||||
|
queryClient.removeQueries({
|
||||||
|
queryKey: localCourseKeys.page(courseName, moduleName, pageName),
|
||||||
|
});
|
||||||
|
queryClient.removeQueries({
|
||||||
|
queryKey: localCourseKeys.pageNames(courseName, moduleName),
|
||||||
|
});
|
||||||
|
const url =
|
||||||
|
"/api/courses/" +
|
||||||
|
encodeURIComponent(courseName) +
|
||||||
|
"/modules/" +
|
||||||
|
encodeURIComponent(moduleName) +
|
||||||
|
"/pages/" +
|
||||||
|
encodeURIComponent(pageName);
|
||||||
|
await axiosClient.delete(url);
|
||||||
|
|
||||||
|
},
|
||||||
|
onSuccess: (_, { moduleName, pageName }) => {
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: localCourseKeys.pageNames(courseName, moduleName),
|
||||||
|
});
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: localCourseKeys.page(courseName, moduleName, pageName),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -173,3 +173,37 @@ export const useCreateQuizMutation = () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useDeleteQuizMutation = () => {
|
||||||
|
const { courseName } = useCourseContext();
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: async ({
|
||||||
|
moduleName,
|
||||||
|
quizName,
|
||||||
|
}: {
|
||||||
|
moduleName: string;
|
||||||
|
quizName: string;
|
||||||
|
}) => {
|
||||||
|
const url =
|
||||||
|
"/api/courses/" +
|
||||||
|
encodeURIComponent(courseName) +
|
||||||
|
"/modules/" +
|
||||||
|
encodeURIComponent(moduleName) +
|
||||||
|
"/quizzes/" +
|
||||||
|
encodeURIComponent(quizName);
|
||||||
|
await axiosClient.delete(url);
|
||||||
|
queryClient.removeQueries({
|
||||||
|
queryKey: localCourseKeys.quizNames(courseName, moduleName),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onSuccess: async (_, { moduleName, quizName }) => {
|
||||||
|
await queryClient.invalidateQueries({
|
||||||
|
queryKey: localCourseKeys.quizNames(courseName, moduleName),
|
||||||
|
});
|
||||||
|
await queryClient.invalidateQueries({
|
||||||
|
queryKey: localCourseKeys.quiz(courseName, moduleName, quizName),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user