refactoring quiz data fetching to simplify

This commit is contained in:
2024-11-04 11:26:50 -07:00
parent 09597c55f8
commit 3f4d665dd2
15 changed files with 62 additions and 110 deletions

View File

@@ -14,7 +14,8 @@ export default function CourseList() {
shallow={true} shallow={true}
className=" className="
font-bold text-xl block font-bold text-xl block
transition-all hover:scale-105 hover:underline transition-all hover:scale-105 hover:underline hover:text-slate-200
mb-3
" "
> >
{settings.name} {settings.name}

View File

@@ -6,7 +6,6 @@ import {
} from "@/hooks/localCourse/lectureHooks"; } from "@/hooks/localCourse/lectureHooks";
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks"; import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
import { useUpdatePageMutation } from "@/hooks/localCourse/pageHooks"; import { useUpdatePageMutation } from "@/hooks/localCourse/pageHooks";
import { useUpdateQuizMutation } from "@/hooks/localCourse/quizHooks";
import { LocalAssignment } from "@/models/local/assignment/localAssignment"; import { LocalAssignment } from "@/models/local/assignment/localAssignment";
import { Lecture } from "@/models/local/lecture"; import { Lecture } from "@/models/local/lecture";
import { getLectureForDay } from "@/models/local/lectureUtils"; import { getLectureForDay } from "@/models/local/lectureUtils";
@@ -20,6 +19,7 @@ import {
import { Dispatch, SetStateAction, useCallback, DragEvent } from "react"; import { Dispatch, SetStateAction, useCallback, DragEvent } from "react";
import { DraggableItem } from "./draggingContext"; import { DraggableItem } from "./draggingContext";
import { getNewLockDate } from "./getNewLockDate"; import { getNewLockDate } from "./getNewLockDate";
import { useUpdateItemMutation } from "@/hooks/localCourse/courseItemHooks";
export function useItemDropOnDay({ export function useItemDropOnDay({
setIsDragging, setIsDragging,
@@ -36,7 +36,7 @@ export function useItemDropOnDay({
}) { }) {
const { data: settings } = useLocalCourseSettingsQuery(); const { data: settings } = useLocalCourseSettingsQuery();
const { data: weeks } = useLecturesByWeekQuery(); const { data: weeks } = useLecturesByWeekQuery();
const updateQuizMutation = useUpdateQuizMutation(); const updateQuizMutation = useUpdateItemMutation("Quiz");
const updateLectureMutation = useLectureUpdateMutation(); const updateLectureMutation = useLectureUpdateMutation();
const updateAssignmentMutation = useUpdateAssignmentMutation(); const updateAssignmentMutation = useUpdateAssignmentMutation();
const updatePageMutation = useUpdatePageMutation(); const updatePageMutation = useUpdatePageMutation();

View File

@@ -1,19 +1,19 @@
"use client"; "use client";
import { useUpdateAssignmentMutation } from "@/hooks/localCourse/assignmentHooks"; import { useUpdateAssignmentMutation } from "@/hooks/localCourse/assignmentHooks";
import { useUpdatePageMutation } from "@/hooks/localCourse/pageHooks"; import { useUpdatePageMutation } from "@/hooks/localCourse/pageHooks";
import { useUpdateQuizMutation } from "@/hooks/localCourse/quizHooks";
import { LocalAssignment } from "@/models/local/assignment/localAssignment"; import { LocalAssignment } from "@/models/local/assignment/localAssignment";
import { LocalCoursePage } from "@/models/local/page/localCoursePage"; import { LocalCoursePage } from "@/models/local/page/localCoursePage";
import { LocalQuiz } from "@/models/local/quiz/localQuiz"; import { LocalQuiz } from "@/models/local/quiz/localQuiz";
import { Dispatch, SetStateAction, useCallback, DragEvent } from "react"; import { Dispatch, SetStateAction, useCallback, DragEvent } from "react";
import { DraggableItem } from "./draggingContext"; import { DraggableItem } from "./draggingContext";
import { useUpdateItemMutation } from "@/hooks/localCourse/courseItemHooks";
export function useItemDropOnModule({ export function useItemDropOnModule({
setIsDragging, setIsDragging,
}: { }: {
setIsDragging: Dispatch<SetStateAction<boolean>>; setIsDragging: Dispatch<SetStateAction<boolean>>;
}) { }) {
const updateQuizMutation = useUpdateQuizMutation(); const updateQuizMutation = useUpdateItemMutation("Quiz");
const updateAssignmentMutation = useUpdateAssignmentMutation(); const updateAssignmentMutation = useUpdateAssignmentMutation();
const updatePageMutation = useUpdatePageMutation(); const updatePageMutation = useUpdatePageMutation();

View File

@@ -10,7 +10,7 @@ export default function LecturePreview({ lecture }: { lecture: Lecture }) {
</section> </section>
<section> <section>
<div <div
className="markdownPreview" className="markdownPreview text-xl"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: markdownToHTMLSafe(lecture.content), __html: markdownToHTMLSafe(lecture.content),
}} }}

View File

@@ -2,7 +2,7 @@
import { useLecturesByWeekQuery } from "@/hooks/localCourse/lectureHooks"; import { useLecturesByWeekQuery } from "@/hooks/localCourse/lectureHooks";
import LecturePreview from "../LecturePreview"; import LecturePreview from "../LecturePreview";
import { getLectureUrl } from "@/services/urlUtils"; import { getCourseUrl, getLectureUrl } from "@/services/urlUtils";
import { useCourseContext } from "../../../context/courseContext"; import { useCourseContext } from "../../../context/courseContext";
import Link from "next/link"; import Link from "next/link";
@@ -22,18 +22,29 @@ export default function LecturePreviewPage({
} }
return ( return (
<div className="flex h-full xl:flex-row flex-col "> <div className="flex h-full xl:flex-row flex-col ">
<div className="flex-shrink flex-1 pb-1 ms-3 xl:ms-0"> <div className="flex-shrink flex-1 pb-1 ms-3 xl:ms-0 flex flex-row flex-wrap gap-3 content-start ">
<Link className="btn" href={getLectureUrl(courseName, lectureDay)}> <div className="">
Edit Page <Link
</Link> className="btn"
href={getLectureUrl(courseName, lectureDay)}
shallow={true}
>
Edit Page
</Link>
</div>
<div className="">
<Link className="btn" href={getCourseUrl(courseName)} shallow={true}>
Course Calendar
</Link>
</div>
</div> </div>
<div className="flex justify-center min-h-0 px-2"> <div className="flex justify-center min-h-0 px-2">
<div <div
className=" className="
w-full max-w-screen-lg w-full max-w-screen-lg
border-slate-700 border-4 rounded-md border-slate-700 border-4 rounded-md
p-3 overflow-auto p-3 overflow-auto
" "
> >
<LecturePreview lecture={lecture} /> <LecturePreview lecture={lecture} />
</div> </div>

View File

@@ -1,7 +1,6 @@
"use client"; "use client";
import { useAssignmentsQueries } from "@/hooks/localCourse/assignmentHooks"; import { useAssignmentsQueries } from "@/hooks/localCourse/assignmentHooks";
import { usePagesQueries } from "@/hooks/localCourse/pageHooks"; import { usePagesQueries } from "@/hooks/localCourse/pageHooks";
import { useQuizzesQueries } from "@/hooks/localCourse/quizHooks";
import { IModuleItem } from "@/models/local/IModuleItem"; import { IModuleItem } from "@/models/local/IModuleItem";
import { import {
getDateFromString, getDateFromString,
@@ -20,6 +19,7 @@ import { getModuleItemUrl } from "@/services/urlUtils";
import { useCourseContext } from "../context/courseContext"; import { useCourseContext } from "../context/courseContext";
import { Expandable } from "../../../../components/Expandable"; import { Expandable } from "../../../../components/Expandable";
import { useDragStyleContext } from "../context/drag/dragStyleContext"; import { useDragStyleContext } from "../context/drag/dragStyleContext";
import { useItemsQueries } from "@/hooks/localCourse/courseItemHooks";
export default function ExpandableModule({ export default function ExpandableModule({
moduleName, moduleName,
@@ -29,7 +29,7 @@ export default function ExpandableModule({
const { itemDropOnModule } = useDraggingContext(); const { itemDropOnModule } = useDraggingContext();
const { data: assignments } = useAssignmentsQueries(moduleName); const { data: assignments } = useAssignmentsQueries(moduleName);
const { data: quizzes } = useQuizzesQueries(moduleName); const { data: quizzes } = useItemsQueries(moduleName, "Quiz");
const { data: pages } = usePagesQueries(moduleName); const { data: pages } = usePagesQueries(moduleName);
const modal = useModal(); const modal = useModal();

View File

@@ -4,11 +4,10 @@ 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 { useCreateItemMutation } from "@/hooks/localCourse/courseItemHooks";
import { useModuleNamesQuery } from "@/hooks/localCourse/localCourseModuleHooks"; 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 { AssignmentSubmissionType } from "@/models/local/assignment/assignmentSubmissionType";
import { LocalAssignmentGroup } from "@/models/local/assignment/localAssignmentGroup"; import { LocalAssignmentGroup } from "@/models/local/assignment/localAssignmentGroup";
import { import {
dateToMarkdownString, dateToMarkdownString,
@@ -53,7 +52,7 @@ export default function NewItemForm({
const createAssignment = useCreateAssignmentMutation(); const createAssignment = useCreateAssignmentMutation();
const createPage = useCreatePageMutation(); const createPage = useCreatePageMutation();
const createQuiz = useCreateQuizMutation(); const createQuiz = useCreateItemMutation("Quiz");
const isPending = const isPending =
createAssignment.isPending || createPage.isPending || createQuiz.isPending; createAssignment.isPending || createPage.isPending || createQuiz.isPending;

View File

@@ -1,9 +1,5 @@
"use client"; "use client";
import { MonacoEditor } from "@/components/editor/MonacoEditor"; import { MonacoEditor } from "@/components/editor/MonacoEditor";
import {
useQuizQuery,
useUpdateQuizMutation,
} from "@/hooks/localCourse/quizHooks";
import { quizMarkdownUtils } from "@/models/local/quiz/utils/quizMarkdownUtils"; import { quizMarkdownUtils } from "@/models/local/quiz/utils/quizMarkdownUtils";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import QuizPreview from "./QuizPreview"; import QuizPreview from "./QuizPreview";
@@ -13,6 +9,7 @@ import { SuspenseAndErrorHandling } from "@/components/SuspenseAndErrorHandling"
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { getModuleItemUrl } from "@/services/urlUtils"; import { getModuleItemUrl } from "@/services/urlUtils";
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext"; import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
import { useItemQuery, useUpdateItemMutation } from "@/hooks/localCourse/courseItemHooks";
const helpString = `QUESTION REFERENCE const helpString = `QUESTION REFERENCE
--- ---
@@ -64,8 +61,8 @@ export default function EditQuiz({
}) { }) {
const router = useRouter(); const router = useRouter();
const { courseName } = useCourseContext(); const { courseName } = useCourseContext();
const { data: quiz } = useQuizQuery(moduleName, quizName); const { data: quiz } = useItemQuery(moduleName, quizName, "Quiz");
const updateQuizMutation = useUpdateQuizMutation(); const updateQuizMutation = useUpdateItemMutation("Quiz");
const [quizText, setQuizText] = useState(quizMarkdownUtils.toMarkdown(quiz)); const [quizText, setQuizText] = useState(quizMarkdownUtils.toMarkdown(quiz));
const [error, setError] = useState(""); const [error, setError] = useState("");
const [showHelp, setShowHelp] = useState(false); const [showHelp, setShowHelp] = useState(false);
@@ -111,7 +108,15 @@ export default function EditQuiz({
return () => { return () => {
clearTimeout(handler); clearTimeout(handler);
}; };
}, [courseName, moduleName, quiz, quizName, quizText, router, updateQuizMutation]); }, [
courseName,
moduleName,
quiz,
quizName,
quizText,
router,
updateQuizMutation,
]);
return ( return (
<div className="h-full flex flex-col align-middle px-1"> <div className="h-full flex flex-col align-middle px-1">

View File

@@ -6,11 +6,8 @@ import {
useAddQuizToCanvasMutation, useAddQuizToCanvasMutation,
useDeleteQuizFromCanvasMutation, useDeleteQuizFromCanvasMutation,
} from "@/hooks/canvas/canvasQuizHooks"; } from "@/hooks/canvas/canvasQuizHooks";
import { useDeleteItemMutation, useItemQuery } from "@/hooks/localCourse/courseItemHooks";
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks"; import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
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";
@@ -29,10 +26,10 @@ export function QuizButtons({
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 } = useItemQuery(moduleName, quizName, "Quiz");
const addToCanvas = useAddQuizToCanvasMutation(); const addToCanvas = useAddQuizToCanvasMutation();
const deleteFromCanvas = useDeleteQuizFromCanvasMutation(); const deleteFromCanvas = useDeleteQuizFromCanvasMutation();
const deleteLocal = useDeleteQuizMutation(); const deleteLocal = useDeleteItemMutation("Quiz");
const modal = useModal(); const modal = useModal();
const quizInCanvas = canvasQuizzes.find((c) => c.title === quizName); const quizInCanvas = canvasQuizzes.find((c) => c.title === quizName);

View File

@@ -1,11 +1,9 @@
import CheckIcon from "@/components/icons/CheckIcon"; import CheckIcon from "@/components/icons/CheckIcon";
import { useQuizQuery } from "@/hooks/localCourse/quizHooks"; import { useItemQuery } from "@/hooks/localCourse/courseItemHooks";
import { LocalQuiz } from "@/models/local/quiz/localQuiz";
import { import {
LocalQuizQuestion, LocalQuizQuestion,
QuestionType, QuestionType,
} from "@/models/local/quiz/localQuizQuestion"; } from "@/models/local/quiz/localQuizQuestion";
import { quizQuestionMarkdownUtils } from "@/models/local/quiz/utils/quizQuestionMarkdownUtils";
import { markdownToHTMLSafe } from "@/services/htmlMarkdownUtils"; import { markdownToHTMLSafe } from "@/services/htmlMarkdownUtils";
export default function QuizPreview({ export default function QuizPreview({
@@ -15,7 +13,7 @@ export default function QuizPreview({
quizName: string; quizName: string;
moduleName: string; moduleName: string;
}) { }) {
const { data: quiz } = useQuizQuery(moduleName, quizName); const { data: quiz } = useItemQuery(moduleName, quizName, "Quiz");
return ( return (
<div style={{ overflow: "scroll", height: "100%" }}> <div style={{ overflow: "scroll", height: "100%" }}>
<div className="columns-2"> <div className="columns-2">

View File

@@ -8,6 +8,7 @@ export function makeQueryClient() {
// above 0 to avoid refetching immediately on the client // above 0 to avoid refetching immediately on the client
// staleTime: 60_000, // staleTime: 60_000,
staleTime: 1000 * 60 * 60, // 1 hour staleTime: 1000 * 60 * 60, // 1 hour
// refetchInterval: 5000, // debug only
refetchOnWindowFocus: false, refetchOnWindowFocus: false,
retry: 0, retry: 0,
refetchOnMount: false, refetchOnMount: false,

View File

@@ -20,11 +20,13 @@ export default function OneCourseLectures() {
href={getLecturePreviewUrl(courseName, dayAsString)} href={getLecturePreviewUrl(courseName, dayAsString)}
className=" className="
border-4 rounded-lg border-slate-500 border-4 rounded-lg border-slate-500
p-3 m-3 block text-end px-3 py-1 m-3 block text-end
bg-slate-950 bg-slate-950
transition-all hover:scale-110 hover:shadow-md transition-all hover:scale-110 hover:shadow-md
" "
> >
<span className="text-end text-slate-500">lecture</span>
<br />
<span className="font-bold text-xl">{todaysLecture?.name}</span> <span className="font-bold text-xl">{todaysLecture?.name}</span>
<br /> <br />
<span className="text-slate-500">{courseName}</span> <span className="text-slate-500">{courseName}</span>

View File

@@ -33,8 +33,15 @@ export async function getAllItemsFromServer<T extends CourseItemType>({
); );
return quizzes as CourseItemReturnType<T>[]; return quizzes as CourseItemReturnType<T>[];
} }
const pages = await fileStorageService.pages.getPages(courseName, moduleName); if (type === "Page") {
return pages as CourseItemReturnType<T>[]; const pages = await fileStorageService.pages.getPages(
courseName,
moduleName
);
return pages as CourseItemReturnType<T>[];
}
throw Error(`cannot get item from server, invalid type: ${type}`)
} }
export async function getItemFromServer<T extends CourseItemType>({ export async function getItemFromServer<T extends CourseItemType>({

View File

@@ -7,7 +7,6 @@ import {
} from "@tanstack/react-query"; } from "@tanstack/react-query";
import { localCourseKeys } from "./localCourseKeys"; import { localCourseKeys } from "./localCourseKeys";
import { getAllAssignmentsQueryConfig } from "./assignmentHooks"; import { getAllAssignmentsQueryConfig } from "./assignmentHooks";
import { getAllQuizzesQueryConfig } from "./quizHooks";
import { getAllItemsQueryConfig } from "./courseItemHooks"; import { getAllItemsQueryConfig } from "./courseItemHooks";
import { import {
createModuleOnServer, createModuleOnServer,
@@ -39,36 +38,6 @@ export const useCreateModuleMutation = () => {
}); });
}; };
// // dangerous? really slowed down page...
// // maybe it only slowed down with react query devtools...
// export const useModuleDataQuery = (moduleName: string) => {
// console.log("running");
// const { data: assignmentNames } = useAssignmentNamesQuery(moduleName);
// const { data: quizNames } = useQuizNamesQuery(moduleName);
// const { data: pageNames } = usePageNamesQuery(moduleName);
// const { data: assignments } = useAssignmentsQueries(
// moduleName,
// assignmentNames
// );
// const { data: quizzes } = useQuizzesQueries(moduleName, quizNames);
// const { data: pages } = usePagesQueries(moduleName, pageNames);
// return {
// assignments,
// quizzes,
// pages,
// };
// // return useMemo(
// // () => ({
// // assignments,
// // quizzes,
// // pages,
// // }),
// // [assignments, pages, quizzes]
// // );
// };
export const useAllCourseDataQuery = () => { export const useAllCourseDataQuery = () => {
const { courseName } = useCourseContext(); const { courseName } = useCourseContext();
const { data: moduleNames } = useModuleNamesQuery(); const { data: moduleNames } = useModuleNamesQuery();
@@ -90,7 +59,7 @@ export const useAllCourseDataQuery = () => {
const { data: quizzesAndModules } = useSuspenseQueries({ const { data: quizzesAndModules } = useSuspenseQueries({
queries: moduleNames.map((moduleName) => queries: moduleNames.map((moduleName) =>
getAllQuizzesQueryConfig(courseName, moduleName) getAllItemsQueryConfig(courseName, moduleName, "Quiz")
), ),
combine: (results) => ({ combine: (results) => ({
data: results.flatMap((r, i) => data: results.flatMap((r, i) =>

View File

@@ -1,38 +0,0 @@
"use client";
import {
getAllItemsQueryConfig,
getItemQueryConfig,
useCreateItemMutation,
useDeleteItemMutation,
useItemQuery,
useItemsQueries,
useUpdateItemMutation,
} from "./courseItemHooks";
export function getAllQuizzesQueryConfig(
courseName: string,
moduleName: string
) {
return getAllItemsQueryConfig(courseName, moduleName, "Quiz");
}
export function getQuizQueryConfig(
courseName: string,
moduleName: string,
quizName: string
) {
return getItemQueryConfig(courseName, moduleName, quizName, "Quiz");
}
export const useQuizQuery = (moduleName: string, quizName: string) =>
useItemQuery(moduleName, quizName, "Quiz");
export const useQuizzesQueries = (moduleName: string) =>
useItemsQueries(moduleName, "Quiz");
export const useUpdateQuizMutation = () => useUpdateItemMutation("Quiz")
export const useCreateQuizMutation = () => useCreateItemMutation("Quiz")
export const useDeleteQuizMutation = () =>
useDeleteItemMutation("Quiz");