mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-25 23:28:33 -06:00
pushing state down with contexts
This commit is contained in:
@@ -2,8 +2,7 @@
|
|||||||
|
|
||||||
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
||||||
|
|
||||||
|
export default function CourseSettings() {
|
||||||
export default function CourseSettings({ courseName }: { courseName: string }) {
|
const { data: settings } = useLocalCourseSettingsQuery();
|
||||||
const { data: settings } = useLocalCourseSettingsQuery(courseName);
|
|
||||||
return <div>{settings.name}</div>;
|
return <div>{settings.name}</div>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ function CalendarWeek({
|
|||||||
week,
|
week,
|
||||||
monthNumber,
|
monthNumber,
|
||||||
}: {
|
}: {
|
||||||
week: Date[];
|
week: string[]; //date strings
|
||||||
monthNumber: number;
|
monthNumber: number;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { getDateFromStringOrThrow } from "@/models/local/timeUtils";
|
import { getDateFromStringOrThrow } from "@/models/local/timeUtils";
|
||||||
import { useCourseContext } from "../context/courseContext";
|
|
||||||
import { getMonthsBetweenDates } from "./calendarMonthUtils";
|
import { getMonthsBetweenDates } from "./calendarMonthUtils";
|
||||||
import { CalendarMonth } from "./CalendarMonth";
|
import { CalendarMonth } from "./CalendarMonth";
|
||||||
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
|
|
||||||
export default function CourseCalendar() {
|
export default function CourseCalendar() {
|
||||||
const { courseName } = useCourseContext();
|
const { data: settings } = useLocalCourseSettingsQuery();
|
||||||
const { data: settings } = useLocalCourseSettingsQuery(courseName);
|
|
||||||
|
|
||||||
const startDateTime = useMemo(
|
const startDateTime = useMemo(
|
||||||
() => getDateFromStringOrThrow(settings.startDate, "course start date"),
|
() => getDateFromStringOrThrow(settings.startDate, "course start date"),
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { useCourseContext } from "../context/courseContext";
|
|
||||||
import { useModuleNamesQuery } from "@/hooks/localCourse/localCoursesHooks";
|
import { useModuleNamesQuery } from "@/hooks/localCourse/localCoursesHooks";
|
||||||
import DayItemsInModule from "./DayItemsInModule";
|
import DayItemsInModule from "./DayItemsInModule";
|
||||||
|
import { getDateFromStringOrThrow } from "@/models/local/timeUtils";
|
||||||
|
import { useDraggingContext } from "../context/DraggingContext";
|
||||||
|
|
||||||
export default function Day({ day, month }: { day: Date; month: number }) {
|
export default function Day({ day, month }: { day: string; month: number }) {
|
||||||
const { courseName, itemDrop } = useCourseContext();
|
const { data: moduleNames } = useModuleNamesQuery();
|
||||||
const { data: moduleNames } = useModuleNamesQuery(courseName);
|
|
||||||
const isInSameMonth = day.getMonth() + 1 != month;
|
const dayAsDate = getDateFromStringOrThrow(day, "calculating same month in day")
|
||||||
|
const isInSameMonth =
|
||||||
|
dayAsDate.getMonth() + 1 !=
|
||||||
|
month;
|
||||||
const backgroundClass = isInSameMonth ? "" : "bg-slate-900";
|
const backgroundClass = isInSameMonth ? "" : "bg-slate-900";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -15,16 +19,23 @@ export default function Day({ day, month }: { day: Date; month: number }) {
|
|||||||
"border border-slate-600 rounded-lg p-2 pb-4 m-1 " + backgroundClass
|
"border border-slate-600 rounded-lg p-2 pb-4 m-1 " + backgroundClass
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{day.getDate()}
|
{dayAsDate.getDate()}
|
||||||
{moduleNames.map((moduleName) => (
|
{moduleNames.map((moduleName) => (
|
||||||
<div
|
<ModuleInDay
|
||||||
key={"" + day + month + moduleName}
|
key={"" + day + month + moduleName}
|
||||||
onDrop={() => itemDrop(day)}
|
moduleName={moduleName}
|
||||||
onDragOver={(e) => e.preventDefault()}
|
day={day}
|
||||||
>
|
/>
|
||||||
<DayItemsInModule day={day} moduleName={moduleName} />
|
|
||||||
</div>
|
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ModuleInDay({ moduleName, day }: { moduleName: string; day: string }) {
|
||||||
|
const { itemDrop } = useDraggingContext();
|
||||||
|
return (
|
||||||
|
<div onDrop={() => itemDrop(day)} onDragOver={(e) => e.preventDefault()}>
|
||||||
|
<DayItemsInModule day={day} moduleName={moduleName} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,20 +7,20 @@ import Link from "next/link";
|
|||||||
import { LocalAssignment } from "@/models/local/assignmnet/localAssignment";
|
import { LocalAssignment } from "@/models/local/assignmnet/localAssignment";
|
||||||
import { LocalQuiz } from "@/models/local/quiz/localQuiz";
|
import { LocalQuiz } from "@/models/local/quiz/localQuiz";
|
||||||
import { LocalCoursePage } from "@/models/local/page/localCoursePage";
|
import { LocalCoursePage } from "@/models/local/page/localCoursePage";
|
||||||
|
import { useDraggingContext } from "../context/DraggingContext";
|
||||||
|
|
||||||
export default function DayItemsInModule({
|
export default function DayItemsInModule({
|
||||||
day,
|
day,
|
||||||
moduleName,
|
moduleName,
|
||||||
}: {
|
}: {
|
||||||
day: Date;
|
day: string;
|
||||||
moduleName: string;
|
moduleName: string;
|
||||||
}) {
|
}) {
|
||||||
const { courseName, endItemDrag, startItemDrag } = useCourseContext();
|
const { courseName } = useCourseContext();
|
||||||
|
const { endItemDrag, startItemDrag } = useDraggingContext();
|
||||||
const { assignments, quizzes, pages } = useModuleDataQuery(
|
const { assignments, quizzes, pages } = useModuleDataQuery(
|
||||||
courseName,
|
|
||||||
moduleName
|
moduleName
|
||||||
);
|
);
|
||||||
|
|
||||||
const todaysAssignments = useMemo(
|
const todaysAssignments = useMemo(
|
||||||
() =>
|
() =>
|
||||||
assignments.filter((a) => {
|
assignments.filter((a) => {
|
||||||
@@ -28,10 +28,14 @@ export default function DayItemsInModule({
|
|||||||
a.dueAt,
|
a.dueAt,
|
||||||
"due at for assignment in day"
|
"due at for assignment in day"
|
||||||
);
|
);
|
||||||
|
const dayAsDate = getDateFromStringOrThrow(
|
||||||
|
day,
|
||||||
|
"in assignment in DayItemsInModule"
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
dueDate.getFullYear() === day.getFullYear() &&
|
dueDate.getFullYear() === dayAsDate.getFullYear() &&
|
||||||
dueDate.getMonth() === day.getMonth() &&
|
dueDate.getMonth() === dayAsDate.getMonth() &&
|
||||||
dueDate.getDate() === day.getDate()
|
dueDate.getDate() === dayAsDate.getDate()
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
[assignments, day]
|
[assignments, day]
|
||||||
@@ -43,10 +47,14 @@ export default function DayItemsInModule({
|
|||||||
q.dueAt,
|
q.dueAt,
|
||||||
"due at for quiz in day"
|
"due at for quiz in day"
|
||||||
);
|
);
|
||||||
|
const dayAsDate = getDateFromStringOrThrow(
|
||||||
|
day,
|
||||||
|
"in quizzes in DayItemsInModule"
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
dueDate.getFullYear() === day.getFullYear() &&
|
dueDate.getFullYear() === dayAsDate.getFullYear() &&
|
||||||
dueDate.getMonth() === day.getMonth() &&
|
dueDate.getMonth() === dayAsDate.getMonth() &&
|
||||||
dueDate.getDate() === day.getDate()
|
dueDate.getDate() === dayAsDate.getDate()
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
[day, quizzes]
|
[day, quizzes]
|
||||||
@@ -58,10 +66,14 @@ export default function DayItemsInModule({
|
|||||||
p.dueAt,
|
p.dueAt,
|
||||||
"due at for page in day"
|
"due at for page in day"
|
||||||
);
|
);
|
||||||
|
const dayAsDate = getDateFromStringOrThrow(
|
||||||
|
day,
|
||||||
|
"in pages in DayItemsInModule"
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
dueDate.getFullYear() === day.getFullYear() &&
|
dueDate.getFullYear() === dayAsDate.getFullYear() &&
|
||||||
dueDate.getMonth() === day.getMonth() &&
|
dueDate.getMonth() === dayAsDate.getMonth() &&
|
||||||
dueDate.getDate() === day.getDate()
|
dueDate.getDate() === dayAsDate.getDate()
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
[day, pages]
|
[day, pages]
|
||||||
@@ -128,6 +140,7 @@ export default function DayItemsInModule({
|
|||||||
role="button"
|
role="button"
|
||||||
draggable="true"
|
draggable="true"
|
||||||
onDragStart={starPageDrag(p)}
|
onDragStart={starPageDrag(p)}
|
||||||
|
onDragEnd={endItemDrag}
|
||||||
>
|
>
|
||||||
{p.name}
|
{p.name}
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
|
import {
|
||||||
|
dateToMarkdownString,
|
||||||
|
getDateFromStringOrThrow,
|
||||||
|
} from "@/models/local/timeUtils";
|
||||||
|
|
||||||
export interface CalendarMonthModel {
|
export interface CalendarMonthModel {
|
||||||
year: number;
|
year: number;
|
||||||
month: number;
|
month: number;
|
||||||
weeks: number[][];
|
weeks: number[][];
|
||||||
daysByWeek: (Date)[][];
|
daysByWeek: string[][]; //iso date is memo-izable
|
||||||
}
|
}
|
||||||
|
|
||||||
function weeksInMonth(year: number, month: number): number {
|
function weeksInMonth(year: number, month: number): number {
|
||||||
@@ -27,17 +33,25 @@ function createCalendarMonth(year: number, month: number): CalendarMonthModel {
|
|||||||
const daysByWeek = Array.from({ length: weeksNumber }).map((_, weekIndex) =>
|
const daysByWeek = Array.from({ length: weeksNumber }).map((_, weekIndex) =>
|
||||||
Array.from({ length: 7 }).map((_, dayIndex) => {
|
Array.from({ length: 7 }).map((_, dayIndex) => {
|
||||||
if (weekIndex === 0 && dayIndex < firstDayOfMonth) {
|
if (weekIndex === 0 && dayIndex < firstDayOfMonth) {
|
||||||
return new Date(year, month - 1, dayIndex - firstDayOfMonth + 1);
|
return dateToMarkdownString(
|
||||||
|
new Date(year, month - 1, dayIndex - firstDayOfMonth + 1)
|
||||||
|
);
|
||||||
} else if (currentDay <= daysInMonth) {
|
} else if (currentDay <= daysInMonth) {
|
||||||
return new Date(year, month - 1, currentDay++);
|
return dateToMarkdownString(new Date(year, month - 1, currentDay++));
|
||||||
} else {
|
} else {
|
||||||
currentDay++;
|
currentDay++;
|
||||||
return new Date(year, month, currentDay - daysInMonth - 1);
|
return dateToMarkdownString(
|
||||||
|
new Date(year, month, currentDay - daysInMonth - 1)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const weeks = daysByWeek.map((week) => week.map((day) => day.getDate()));
|
const weeks = daysByWeek.map((week) =>
|
||||||
|
week.map((day) =>
|
||||||
|
getDateFromStringOrThrow(day, "calculating weeks").getDate()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return { year, month, weeks, daysByWeek };
|
return { year, month, weeks, daysByWeek };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { ReactNode, useCallback, useState } from "react";
|
import { ReactNode, useCallback, useState } from "react";
|
||||||
import { CourseContext, DraggableItem } from "./courseContext";
|
import { CourseContext } from "./courseContext";
|
||||||
|
import { DraggableItem } from "./DraggingContext";
|
||||||
import { LocalQuiz } from "@/models/local/quiz/localQuiz";
|
import { LocalQuiz } from "@/models/local/quiz/localQuiz";
|
||||||
import {
|
import {
|
||||||
dateToMarkdownString,
|
dateToMarkdownString,
|
||||||
@@ -16,60 +17,10 @@ export default function CourseContextProvider({
|
|||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
localCourseName: string;
|
localCourseName: string;
|
||||||
}) {
|
}) {
|
||||||
const updateQuizMutation = useUpdateQuizMutation(localCourseName);
|
|
||||||
const { data: settings } = useLocalCourseSettingsQuery(localCourseName);
|
|
||||||
const [itemBeingDragged, setItemBeingDragged] = useState<
|
|
||||||
DraggableItem | undefined
|
|
||||||
>();
|
|
||||||
|
|
||||||
const itemDrop = useCallback(
|
|
||||||
(day: Date | undefined) => {
|
|
||||||
if (itemBeingDragged && day) {
|
|
||||||
day.setHours(settings.defaultDueTime.hour);
|
|
||||||
day.setHours(settings.defaultDueTime.minute);
|
|
||||||
if (itemBeingDragged.type === "quiz") {
|
|
||||||
const previousQuiz = itemBeingDragged.item as LocalQuiz;
|
|
||||||
|
|
||||||
const quiz: LocalQuiz = {
|
|
||||||
...previousQuiz,
|
|
||||||
dueAt: dateToMarkdownString(day),
|
|
||||||
lockAt:
|
|
||||||
previousQuiz.lockAt &&
|
|
||||||
(getDateFromStringOrThrow(previousQuiz.lockAt, "lockAt date") >
|
|
||||||
day
|
|
||||||
? previousQuiz.lockAt
|
|
||||||
: dateToMarkdownString(day)),
|
|
||||||
};
|
|
||||||
updateQuizMutation.mutate({
|
|
||||||
quiz: quiz,
|
|
||||||
quizName: quiz.name,
|
|
||||||
moduleName: itemBeingDragged.sourceModuleName,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setItemBeingDragged(undefined);
|
|
||||||
},
|
|
||||||
[
|
|
||||||
itemBeingDragged,
|
|
||||||
settings.defaultDueTime.hour,
|
|
||||||
settings.defaultDueTime.minute,
|
|
||||||
updateQuizMutation,
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
const startItemDrag = useCallback((d: DraggableItem) => {
|
|
||||||
setItemBeingDragged(d);
|
|
||||||
}, []);
|
|
||||||
const endItemDrag = useCallback(() => {
|
|
||||||
setItemBeingDragged(undefined);
|
|
||||||
}, []);
|
|
||||||
return (
|
return (
|
||||||
<CourseContext.Provider
|
<CourseContext.Provider
|
||||||
value={{
|
value={{
|
||||||
courseName: localCourseName,
|
courseName: localCourseName,
|
||||||
startItemDrag: startItemDrag,
|
|
||||||
endItemDrag: endItemDrag,
|
|
||||||
itemDrop,
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
"use client";
|
||||||
|
import { IModuleItem } from "@/models/local/IModuleItem";
|
||||||
|
import { createContext, useContext } from "react";
|
||||||
|
|
||||||
|
export interface DraggableItem {
|
||||||
|
item: IModuleItem;
|
||||||
|
sourceModuleName: string;
|
||||||
|
type: "quiz" | "assignment" | "page";
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DraggingContextInterface {
|
||||||
|
startItemDrag: (dragging: DraggableItem) => void;
|
||||||
|
endItemDrag: () => void;
|
||||||
|
itemDrop: (droppedOnDay?: string) => void;
|
||||||
|
}
|
||||||
|
const defaultDraggingValue: DraggingContextInterface = {
|
||||||
|
startItemDrag: () => { },
|
||||||
|
endItemDrag: () => { },
|
||||||
|
itemDrop: () => { },
|
||||||
|
};
|
||||||
|
export const DraggingContext = createContext<DraggingContextInterface>(defaultDraggingValue);
|
||||||
|
|
||||||
|
export function useDraggingContext() {
|
||||||
|
return useContext(DraggingContext);
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
"use client";
|
||||||
|
import { ReactNode, useCallback, useState } from "react";
|
||||||
|
import { DraggableItem, DraggingContext } from "./DraggingContext";
|
||||||
|
import { LocalQuiz } from "@/models/local/quiz/localQuiz";
|
||||||
|
import {
|
||||||
|
dateToMarkdownString,
|
||||||
|
getDateFromStringOrThrow,
|
||||||
|
} from "@/models/local/timeUtils";
|
||||||
|
import { useUpdateQuizMutation } from "@/hooks/localCourse/quizHooks";
|
||||||
|
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
||||||
|
|
||||||
|
export default function DraggingContextProvider({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: ReactNode;
|
||||||
|
localCourseName: string;
|
||||||
|
}) {
|
||||||
|
const updateQuizMutation = useUpdateQuizMutation();
|
||||||
|
const { data: settings } = useLocalCourseSettingsQuery();
|
||||||
|
const [itemBeingDragged, setItemBeingDragged] = useState<
|
||||||
|
DraggableItem | undefined
|
||||||
|
>();
|
||||||
|
|
||||||
|
const itemDrop = useCallback(
|
||||||
|
(day: string | undefined) => {
|
||||||
|
if (itemBeingDragged && day) {
|
||||||
|
const dayAsDate = getDateFromStringOrThrow(day, "in drop callback");
|
||||||
|
dayAsDate.setHours(settings.defaultDueTime.hour);
|
||||||
|
dayAsDate.setHours(settings.defaultDueTime.minute);
|
||||||
|
if (itemBeingDragged.type === "quiz") {
|
||||||
|
console.log("dropping quiz");
|
||||||
|
const previousQuiz = itemBeingDragged.item as LocalQuiz;
|
||||||
|
|
||||||
|
const quiz: LocalQuiz = {
|
||||||
|
...previousQuiz,
|
||||||
|
dueAt: dateToMarkdownString(dayAsDate),
|
||||||
|
lockAt:
|
||||||
|
previousQuiz.lockAt &&
|
||||||
|
(getDateFromStringOrThrow(previousQuiz.lockAt, "lockAt date") >
|
||||||
|
dayAsDate
|
||||||
|
? previousQuiz.lockAt
|
||||||
|
: dateToMarkdownString(dayAsDate)),
|
||||||
|
};
|
||||||
|
updateQuizMutation.mutate({
|
||||||
|
quiz: quiz,
|
||||||
|
quizName: quiz.name,
|
||||||
|
moduleName: itemBeingDragged.sourceModuleName,
|
||||||
|
});
|
||||||
|
} else if (itemBeingDragged.type === "assignment") {
|
||||||
|
console.log("dropped assignment");
|
||||||
|
} else if (itemBeingDragged.type === "page") {
|
||||||
|
console.log("dropped page");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setItemBeingDragged(undefined);
|
||||||
|
},
|
||||||
|
[
|
||||||
|
itemBeingDragged,
|
||||||
|
settings.defaultDueTime.hour,
|
||||||
|
settings.defaultDueTime.minute,
|
||||||
|
updateQuizMutation,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
const startItemDrag = useCallback((d: DraggableItem) => {
|
||||||
|
setItemBeingDragged(d);
|
||||||
|
}, []);
|
||||||
|
const endItemDrag = useCallback(() => {
|
||||||
|
setItemBeingDragged(undefined);
|
||||||
|
}, []);
|
||||||
|
return (
|
||||||
|
<DraggingContext.Provider
|
||||||
|
value={{
|
||||||
|
startItemDrag: startItemDrag,
|
||||||
|
endItemDrag: endItemDrag,
|
||||||
|
itemDrop,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</DraggingContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,25 +1,12 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { IModuleItem } from "@/models/local/IModuleItem";
|
|
||||||
import { createContext, useContext } from "react";
|
import { createContext, useContext } from "react";
|
||||||
|
|
||||||
export interface DraggableItem {
|
|
||||||
item: IModuleItem;
|
|
||||||
sourceModuleName: string;
|
|
||||||
type: "quiz" | "assignment" | "page";
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CourseContextInterface {
|
export interface CourseContextInterface {
|
||||||
courseName: string;
|
courseName: string;
|
||||||
startItemDrag: (dragging: DraggableItem) => void;
|
|
||||||
endItemDrag: () => void;
|
|
||||||
itemDrop: (droppedOnDay?: Date) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultValue: CourseContextInterface = {
|
const defaultValue: CourseContextInterface = {
|
||||||
startItemDrag: () => { },
|
courseName: "",
|
||||||
endItemDrag: () => { },
|
|
||||||
itemDrop: () => { },
|
|
||||||
courseName: ""
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CourseContext =
|
export const CourseContext =
|
||||||
@@ -28,3 +15,4 @@ export const CourseContext =
|
|||||||
export function useCourseContext() {
|
export function useCourseContext() {
|
||||||
return useContext(CourseContext);
|
return useContext(CourseContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,7 @@ export default function ExpandableModule({
|
|||||||
}: {
|
}: {
|
||||||
moduleName: string;
|
moduleName: string;
|
||||||
}) {
|
}) {
|
||||||
const { courseName } = useCourseContext();
|
|
||||||
const { assignments, quizzes, pages } = useModuleDataQuery(
|
const { assignments, quizzes, pages } = useModuleDataQuery(
|
||||||
courseName,
|
|
||||||
moduleName
|
moduleName
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ import { useCourseContext } from "../context/courseContext";
|
|||||||
import ExpandableModule from "./ExpandableModule";
|
import ExpandableModule from "./ExpandableModule";
|
||||||
|
|
||||||
export default function ModuleList() {
|
export default function ModuleList() {
|
||||||
const { courseName } = useCourseContext();
|
const { data: moduleNames } = useModuleNamesQuery();
|
||||||
const { data: moduleNames } = useModuleNamesQuery(courseName);
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{moduleNames.map((m) => (
|
{moduleNames.map((m) => (
|
||||||
|
|||||||
@@ -3,15 +3,13 @@ import MonacoEditor from "@/components/MonacoEditor";
|
|||||||
import { useQuizQuery } from "@/hooks/localCourse/quizHooks";
|
import { useQuizQuery } from "@/hooks/localCourse/quizHooks";
|
||||||
|
|
||||||
export default function EditQuiz({
|
export default function EditQuiz({
|
||||||
courseName,
|
|
||||||
moduleName,
|
moduleName,
|
||||||
quizName,
|
quizName,
|
||||||
}: {
|
}: {
|
||||||
courseName: string;
|
|
||||||
quizName: string;
|
quizName: string;
|
||||||
moduleName: string;
|
moduleName: string;
|
||||||
}) {
|
}) {
|
||||||
const { data: quiz } = useQuizQuery(courseName, moduleName, quizName);
|
const { data: quiz } = useQuizQuery(moduleName, quizName);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -2,15 +2,9 @@ import React from "react";
|
|||||||
import EditQuiz from "./EditQuiz";
|
import EditQuiz from "./EditQuiz";
|
||||||
|
|
||||||
export default async function Page({
|
export default async function Page({
|
||||||
params: { courseName, moduleName, quizName },
|
params: { moduleName, quizName },
|
||||||
}: {
|
}: {
|
||||||
params: { courseName: string; quizName: string; moduleName: string };
|
params: { quizName: string; moduleName: string };
|
||||||
}) {
|
}) {
|
||||||
return (
|
return <EditQuiz quizName={quizName} moduleName={moduleName} />;
|
||||||
<EditQuiz
|
|
||||||
courseName={courseName}
|
|
||||||
quizName={quizName}
|
|
||||||
moduleName={moduleName}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import CourseContextProvider from "./context/CourseContextProvider";
|
|||||||
import CourseCalendar from "./calendar/CourseCalendar";
|
import CourseCalendar from "./calendar/CourseCalendar";
|
||||||
import CourseSettings from "./CourseSettings";
|
import CourseSettings from "./CourseSettings";
|
||||||
import ModuleList from "./modules/ModuleList";
|
import ModuleList from "./modules/ModuleList";
|
||||||
|
import DraggingContextProvider from "./context/DraggingContextProvider";
|
||||||
|
|
||||||
export default async function CoursePage({
|
export default async function CoursePage({
|
||||||
params: { courseName },
|
params: { courseName },
|
||||||
@@ -11,14 +12,16 @@ export default async function CoursePage({
|
|||||||
return (
|
return (
|
||||||
<CourseContextProvider localCourseName={courseName}>
|
<CourseContextProvider localCourseName={courseName}>
|
||||||
<div className="h-full flex flex-col">
|
<div className="h-full flex flex-col">
|
||||||
<CourseSettings courseName={courseName} />
|
<CourseSettings />
|
||||||
<div className="flex flex-row min-h-0">
|
<div className="flex flex-row min-h-0">
|
||||||
<div className="flex-1 min-h-0">
|
<DraggingContextProvider localCourseName={courseName}>
|
||||||
<CourseCalendar />
|
<div className="flex-1 min-h-0">
|
||||||
</div>
|
<CourseCalendar />
|
||||||
<div className="w-96 p-3">
|
</div>
|
||||||
<ModuleList />
|
<div className="w-96 p-3">
|
||||||
</div>
|
<ModuleList />
|
||||||
|
</div>
|
||||||
|
</DraggingContextProvider>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</CourseContextProvider>
|
</CourseContextProvider>
|
||||||
|
|||||||
@@ -2,12 +2,11 @@ import axios from "axios";
|
|||||||
import { localCourseKeys } from "./localCourseKeys";
|
import { localCourseKeys } from "./localCourseKeys";
|
||||||
import { LocalAssignment } from "@/models/local/assignmnet/localAssignment";
|
import { LocalAssignment } from "@/models/local/assignmnet/localAssignment";
|
||||||
import { useSuspenseQuery, useSuspenseQueries } from "@tanstack/react-query";
|
import { useSuspenseQuery, useSuspenseQueries } from "@tanstack/react-query";
|
||||||
|
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
|
||||||
|
|
||||||
export const useAssignmentNamesQuery = (
|
export const useAssignmentNamesQuery = (moduleName: string) => {
|
||||||
courseName: string,
|
const { courseName } = useCourseContext();
|
||||||
moduleName: string
|
return useSuspenseQuery({
|
||||||
) =>
|
|
||||||
useSuspenseQuery({
|
|
||||||
queryKey: localCourseKeys.assignmentNames(courseName, moduleName),
|
queryKey: localCourseKeys.assignmentNames(courseName, moduleName),
|
||||||
queryFn: async (): Promise<string[]> => {
|
queryFn: async (): Promise<string[]> => {
|
||||||
const url =
|
const url =
|
||||||
@@ -20,13 +19,13 @@ export const useAssignmentNamesQuery = (
|
|||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const getAssignmentQueryConfig = (
|
const getAssignmentQueryConfig = (
|
||||||
courseName: string,
|
courseName: string,
|
||||||
moduleName: string,
|
moduleName: string,
|
||||||
assignmentName: string
|
assignmentName: string
|
||||||
) => {
|
) => {
|
||||||
if (assignmentName === "Final Project Milestone ") console.log(moduleName);
|
|
||||||
return {
|
return {
|
||||||
queryKey: localCourseKeys.assignment(
|
queryKey: localCourseKeys.assignment(
|
||||||
courseName,
|
courseName,
|
||||||
@@ -47,20 +46,22 @@ const getAssignmentQueryConfig = (
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
export const useAssignmentQuery = (
|
export const useAssignmentQuery = (
|
||||||
courseName: string,
|
|
||||||
moduleName: string,
|
moduleName: string,
|
||||||
assignmentName: string
|
assignmentName: string
|
||||||
) =>
|
) => {
|
||||||
useSuspenseQuery(
|
const { courseName } = useCourseContext();
|
||||||
|
|
||||||
|
return useSuspenseQuery(
|
||||||
getAssignmentQueryConfig(courseName, moduleName, assignmentName)
|
getAssignmentQueryConfig(courseName, moduleName, assignmentName)
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const useAssignmentsQueries = (
|
export const useAssignmentsQueries = (
|
||||||
courseName: string,
|
|
||||||
moduleName: string,
|
moduleName: string,
|
||||||
assignmentNames: string[]
|
assignmentNames: string[]
|
||||||
) =>
|
) => {
|
||||||
useSuspenseQueries({
|
const { courseName } = useCourseContext();
|
||||||
|
return useSuspenseQueries({
|
||||||
queries: assignmentNames.map((name) =>
|
queries: assignmentNames.map((name) =>
|
||||||
getAssignmentQueryConfig(courseName, moduleName, name)
|
getAssignmentQueryConfig(courseName, moduleName, name)
|
||||||
),
|
),
|
||||||
@@ -69,3 +70,4 @@ export const useAssignmentsQueries = (
|
|||||||
pending: results.some((r) => r.isPending),
|
pending: results.some((r) => r.isPending),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
import { usePageNamesQuery, usePagesQueries } from "./pageHooks";
|
import { usePageNamesQuery, usePagesQueries } from "./pageHooks";
|
||||||
import { useQuizNamesQuery, useQuizzesQueries } from "./quizHooks";
|
import { useQuizNamesQuery, useQuizzesQueries } from "./quizHooks";
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
|
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
|
||||||
|
|
||||||
export const useLocalCourseNamesQuery = () =>
|
export const useLocalCourseNamesQuery = () =>
|
||||||
useSuspenseQuery({
|
useSuspenseQuery({
|
||||||
@@ -20,8 +21,9 @@ export const useLocalCourseNamesQuery = () =>
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const useLocalCourseSettingsQuery = (courseName: string) =>
|
export const useLocalCourseSettingsQuery = () => {
|
||||||
useSuspenseQuery({
|
const { courseName } = useCourseContext();
|
||||||
|
return useSuspenseQuery({
|
||||||
queryKey: localCourseKeys.settings(courseName),
|
queryKey: localCourseKeys.settings(courseName),
|
||||||
queryFn: async (): Promise<LocalCourseSettings> => {
|
queryFn: async (): Promise<LocalCourseSettings> => {
|
||||||
const url = `/api/courses/${courseName}/settings`;
|
const url = `/api/courses/${courseName}/settings`;
|
||||||
@@ -29,9 +31,11 @@ export const useLocalCourseSettingsQuery = (courseName: string) =>
|
|||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const useModuleNamesQuery = (courseName: string) =>
|
export const useModuleNamesQuery = () => {
|
||||||
useSuspenseQuery({
|
const { courseName } = useCourseContext();
|
||||||
|
return useSuspenseQuery({
|
||||||
queryKey: localCourseKeys.moduleNames(courseName),
|
queryKey: localCourseKeys.moduleNames(courseName),
|
||||||
queryFn: async (): Promise<string[]> => {
|
queryFn: async (): Promise<string[]> => {
|
||||||
const url = `/api/courses/${courseName}/modules`;
|
const url = `/api/courses/${courseName}/modules`;
|
||||||
@@ -39,26 +43,24 @@ export const useModuleNamesQuery = (courseName: string) =>
|
|||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const useModuleDataQuery = (courseName: string, moduleName: string) => {
|
export const useModuleDataQuery = (moduleName: string) => {
|
||||||
const { data: assignmentNames } = useAssignmentNamesQuery(
|
const { data: assignmentNames } = useAssignmentNamesQuery(
|
||||||
courseName,
|
|
||||||
moduleName
|
moduleName
|
||||||
);
|
);
|
||||||
const { data: quizNames } = useQuizNamesQuery(courseName, moduleName);
|
const { data: quizNames } = useQuizNamesQuery(moduleName);
|
||||||
const { data: pageNames } = usePageNamesQuery(courseName, moduleName);
|
const { data: pageNames } = usePageNamesQuery(moduleName);
|
||||||
|
|
||||||
const { data: assignments } = useAssignmentsQueries(
|
const { data: assignments } = useAssignmentsQueries(
|
||||||
courseName,
|
|
||||||
moduleName,
|
moduleName,
|
||||||
assignmentNames
|
assignmentNames
|
||||||
);
|
);
|
||||||
const { data: quizzes } = useQuizzesQueries(
|
const { data: quizzes } = useQuizzesQueries(
|
||||||
courseName,
|
|
||||||
moduleName,
|
moduleName,
|
||||||
quizNames
|
quizNames
|
||||||
);
|
);
|
||||||
const { data: pages } = usePagesQueries(courseName, moduleName, pageNames);
|
const { data: pages } = usePagesQueries(moduleName, pageNames);
|
||||||
|
|
||||||
return useMemo(
|
return useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ import { LocalCoursePage } from "@/models/local/page/localCoursePage";
|
|||||||
import { useSuspenseQueries, useSuspenseQuery } from "@tanstack/react-query";
|
import { useSuspenseQueries, useSuspenseQuery } from "@tanstack/react-query";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { localCourseKeys } from "./localCourseKeys";
|
import { localCourseKeys } from "./localCourseKeys";
|
||||||
|
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
|
||||||
|
|
||||||
export const usePageNamesQuery = (courseName: string, moduleName: string) =>
|
export const usePageNamesQuery = (moduleName: string) => {
|
||||||
useSuspenseQuery({
|
const { courseName } = useCourseContext();
|
||||||
|
return useSuspenseQuery({
|
||||||
queryKey: localCourseKeys.pageNames(courseName, moduleName),
|
queryKey: localCourseKeys.pageNames(courseName, moduleName),
|
||||||
queryFn: async (): Promise<string[]> => {
|
queryFn: async (): Promise<string[]> => {
|
||||||
const url =
|
const url =
|
||||||
@@ -17,17 +19,14 @@ export const usePageNamesQuery = (courseName: string, moduleName: string) =>
|
|||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
export const usePageQuery = (
|
};
|
||||||
courseName: string,
|
export const usePageQuery = (moduleName: string, pageName: string) => {
|
||||||
moduleName: string,
|
const { courseName } = useCourseContext();
|
||||||
pageName: string
|
return useSuspenseQuery(getPageQueryConfig(courseName, moduleName, pageName));
|
||||||
) => useSuspenseQuery(getPageQueryConfig(courseName, moduleName, pageName));
|
};
|
||||||
|
|
||||||
export const usePagesQueries = (
|
export const usePagesQueries = (moduleName: string, pageNames: string[]) => {
|
||||||
courseName: string,
|
const { courseName } = useCourseContext();
|
||||||
moduleName: string,
|
|
||||||
pageNames: string[]
|
|
||||||
) => {
|
|
||||||
return useSuspenseQueries({
|
return useSuspenseQueries({
|
||||||
queries: pageNames.map((name) =>
|
queries: pageNames.map((name) =>
|
||||||
getPageQueryConfig(courseName, moduleName, name)
|
getPageQueryConfig(courseName, moduleName, name)
|
||||||
|
|||||||
@@ -7,9 +7,11 @@ import {
|
|||||||
} from "@tanstack/react-query";
|
} from "@tanstack/react-query";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { localCourseKeys } from "./localCourseKeys";
|
import { localCourseKeys } from "./localCourseKeys";
|
||||||
|
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
|
||||||
|
|
||||||
export const useQuizNamesQuery = (courseName: string, moduleName: string) =>
|
export const useQuizNamesQuery = (moduleName: string) => {
|
||||||
useSuspenseQuery({
|
const { courseName } = useCourseContext();
|
||||||
|
return useSuspenseQuery({
|
||||||
queryKey: localCourseKeys.quizNames(courseName, moduleName),
|
queryKey: localCourseKeys.quizNames(courseName, moduleName),
|
||||||
queryFn: async (): Promise<string[]> => {
|
queryFn: async (): Promise<string[]> => {
|
||||||
const url =
|
const url =
|
||||||
@@ -22,19 +24,16 @@ export const useQuizNamesQuery = (courseName: string, moduleName: string) =>
|
|||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const useQuizQuery = (
|
export const useQuizQuery = (moduleName: string, quizName: string) => {
|
||||||
courseName: string,
|
const { courseName } = useCourseContext();
|
||||||
moduleName: string,
|
return useSuspenseQuery(getQuizQueryConfig(courseName, moduleName, quizName));
|
||||||
quizName: string
|
};
|
||||||
) => useSuspenseQuery(getQuizQueryConfig(courseName, moduleName, quizName));
|
|
||||||
|
|
||||||
export const useQuizzesQueries = (
|
export const useQuizzesQueries = (moduleName: string, quizNames: string[]) => {
|
||||||
courseName: string,
|
const { courseName } = useCourseContext();
|
||||||
moduleName: string,
|
return useSuspenseQueries({
|
||||||
quizNames: string[]
|
|
||||||
) =>
|
|
||||||
useSuspenseQueries({
|
|
||||||
queries: quizNames.map((name) =>
|
queries: quizNames.map((name) =>
|
||||||
getQuizQueryConfig(courseName, moduleName, name)
|
getQuizQueryConfig(courseName, moduleName, name)
|
||||||
),
|
),
|
||||||
@@ -43,6 +42,7 @@ export const useQuizzesQueries = (
|
|||||||
pending: results.some((r) => r.isPending),
|
pending: results.some((r) => r.isPending),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
function getQuizQueryConfig(
|
function getQuizQueryConfig(
|
||||||
courseName: string,
|
courseName: string,
|
||||||
@@ -65,7 +65,9 @@ function getQuizQueryConfig(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useUpdateQuizMutation = (courseName: string) => {
|
export const useUpdateQuizMutation = () => {
|
||||||
|
|
||||||
|
const { courseName } = useCourseContext();
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: async ({
|
mutationFn: async ({
|
||||||
|
|||||||
@@ -1,293 +1,293 @@
|
|||||||
import path from "path";
|
// import path from "path";
|
||||||
import { describe, it, expect, beforeEach } from "vitest";
|
// import { describe, it, expect, beforeEach } from "vitest";
|
||||||
import fs from "fs";
|
// import fs from "fs";
|
||||||
import { DayOfWeek, LocalCourse } from "@/models/local/localCourse";
|
// import { DayOfWeek, LocalCourse } from "@/models/local/localCourse";
|
||||||
import { AssignmentSubmissionType } from "@/models/local/assignmnet/assignmentSubmissionType";
|
// import { AssignmentSubmissionType } from "@/models/local/assignmnet/assignmentSubmissionType";
|
||||||
import { QuestionType } from "@/models/local/quiz/localQuizQuestion";
|
// import { QuestionType } from "@/models/local/quiz/localQuizQuestion";
|
||||||
import { fileStorageService } from "../fileStorage/fileStorageService";
|
// import { fileStorageService } from "../fileStorage/fileStorageService";
|
||||||
|
|
||||||
describe("FileStorageTests", () => {
|
// describe("FileStorageTests", () => {
|
||||||
beforeEach(() => {
|
// beforeEach(() => {
|
||||||
const storageDirectory = process.env.STORAGE_DIRECTORY ?? "/tmp/canvasManagerTests";
|
// const storageDirectory = process.env.STORAGE_DIRECTORY ?? "/tmp/canvasManagerTests";
|
||||||
if (fs.existsSync(storageDirectory)) {
|
// if (fs.existsSync(storageDirectory)) {
|
||||||
fs.rmdirSync(storageDirectory, { recursive: true });
|
// fs.rmdirSync(storageDirectory, { recursive: true });
|
||||||
}
|
// }
|
||||||
fs.mkdirSync(storageDirectory, { recursive: true });
|
// fs.mkdirSync(storageDirectory, { recursive: true });
|
||||||
});
|
// });
|
||||||
|
|
||||||
it("empty course can be saved and loaded", async () => {
|
// it("empty course can be saved and loaded", async () => {
|
||||||
const testCourse: LocalCourse = {
|
// const testCourse: LocalCourse = {
|
||||||
settings: {
|
// settings: {
|
||||||
name: "test empty course",
|
// name: "test empty course",
|
||||||
assignmentGroups: [],
|
// assignmentGroups: [],
|
||||||
daysOfWeek: [],
|
// daysOfWeek: [],
|
||||||
startDate: "07/09/2024 23:59:00",
|
// startDate: "07/09/2024 23:59:00",
|
||||||
endDate: "07/09/2024 23:59:00",
|
// endDate: "07/09/2024 23:59:00",
|
||||||
defaultDueTime: { hour: 1, minute: 59 },
|
// defaultDueTime: { hour: 1, minute: 59 },
|
||||||
},
|
// },
|
||||||
modules: [],
|
// modules: [],
|
||||||
};
|
// };
|
||||||
|
|
||||||
await fileStorageService.saveCourseAsync(testCourse);
|
// await fileStorageService.saveCourseAsync(testCourse);
|
||||||
|
|
||||||
const loadedCourses = await fileStorageService.loadSavedCourses();
|
// const loadedCourses = await fileStorageService.loadSavedCourses();
|
||||||
const loadedCourse = loadedCourses.find(
|
// const loadedCourse = loadedCourses.find(
|
||||||
(c) => c.settings.name === testCourse.settings.name
|
// (c) => c.settings.name === testCourse.settings.name
|
||||||
);
|
// );
|
||||||
|
|
||||||
expect(loadedCourse).toEqual(testCourse);
|
// expect(loadedCourse).toEqual(testCourse);
|
||||||
});
|
// });
|
||||||
|
|
||||||
it("course settings can be saved and loaded", async () => {
|
// it("course settings can be saved and loaded", async () => {
|
||||||
const testCourse: LocalCourse = {
|
// const testCourse: LocalCourse = {
|
||||||
settings: {
|
// settings: {
|
||||||
assignmentGroups: [],
|
// assignmentGroups: [],
|
||||||
name: "Test Course with settings",
|
// name: "Test Course with settings",
|
||||||
daysOfWeek: [DayOfWeek.Monday, DayOfWeek.Wednesday],
|
// daysOfWeek: [DayOfWeek.Monday, DayOfWeek.Wednesday],
|
||||||
startDate: "07/09/2024 23:59:00",
|
// startDate: "07/09/2024 23:59:00",
|
||||||
endDate: "07/09/2024 23:59:00",
|
// endDate: "07/09/2024 23:59:00",
|
||||||
defaultDueTime: { hour: 1, minute: 59 },
|
// defaultDueTime: { hour: 1, minute: 59 },
|
||||||
},
|
// },
|
||||||
modules: [],
|
// modules: [],
|
||||||
};
|
// };
|
||||||
|
|
||||||
await fileStorageService.saveCourseAsync(testCourse);
|
// await fileStorageService.saveCourseAsync(testCourse);
|
||||||
|
|
||||||
const loadedCourses = await fileStorageService.loadSavedCourses();
|
// const loadedCourses = await fileStorageService.loadSavedCourses();
|
||||||
const loadedCourse = loadedCourses.find(
|
// const loadedCourse = loadedCourses.find(
|
||||||
(c) => c.settings.name === testCourse.settings.name
|
// (c) => c.settings.name === testCourse.settings.name
|
||||||
);
|
// );
|
||||||
|
|
||||||
expect(loadedCourse?.settings).toEqual(testCourse.settings);
|
// expect(loadedCourse?.settings).toEqual(testCourse.settings);
|
||||||
});
|
// });
|
||||||
|
|
||||||
it("empty course modules can be saved and loaded", async () => {
|
// it("empty course modules can be saved and loaded", async () => {
|
||||||
const testCourse: LocalCourse = {
|
// const testCourse: LocalCourse = {
|
||||||
settings: {
|
// settings: {
|
||||||
name: "Test Course with modules",
|
// name: "Test Course with modules",
|
||||||
assignmentGroups: [],
|
// assignmentGroups: [],
|
||||||
daysOfWeek: [],
|
// daysOfWeek: [],
|
||||||
startDate: "07/09/2024 23:59:00",
|
// startDate: "07/09/2024 23:59:00",
|
||||||
endDate: "07/09/2024 23:59:00",
|
// endDate: "07/09/2024 23:59:00",
|
||||||
defaultDueTime: { hour: 1, minute: 59 },
|
// defaultDueTime: { hour: 1, minute: 59 },
|
||||||
},
|
// },
|
||||||
modules: [
|
// modules: [
|
||||||
{
|
// {
|
||||||
name: "test module 1",
|
// name: "test module 1",
|
||||||
assignments: [],
|
// assignments: [],
|
||||||
quizzes: [],
|
// quizzes: [],
|
||||||
pages: [],
|
// pages: [],
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
};
|
// };
|
||||||
|
|
||||||
await fileStorageService.saveCourseAsync(testCourse);
|
// await fileStorageService.saveCourseAsync(testCourse);
|
||||||
|
|
||||||
const loadedCourses = await fileStorageService.loadSavedCourses();
|
// const loadedCourses = await fileStorageService.loadSavedCourses();
|
||||||
const loadedCourse = loadedCourses.find(
|
// const loadedCourse = loadedCourses.find(
|
||||||
(c) => c.settings.name === testCourse.settings.name
|
// (c) => c.settings.name === testCourse.settings.name
|
||||||
);
|
// );
|
||||||
|
|
||||||
expect(loadedCourse?.modules).toEqual(testCourse.modules);
|
// expect(loadedCourse?.modules).toEqual(testCourse.modules);
|
||||||
});
|
// });
|
||||||
|
|
||||||
it("course modules with assignments can be saved and loaded", async () => {
|
// it("course modules with assignments can be saved and loaded", async () => {
|
||||||
const testCourse: LocalCourse = {
|
// const testCourse: LocalCourse = {
|
||||||
settings: {
|
// settings: {
|
||||||
name: "Test Course with modules and assignments",
|
// name: "Test Course with modules and assignments",
|
||||||
assignmentGroups: [],
|
// assignmentGroups: [],
|
||||||
daysOfWeek: [],
|
// daysOfWeek: [],
|
||||||
startDate: "07/09/2024 23:59:00",
|
// startDate: "07/09/2024 23:59:00",
|
||||||
endDate: "07/09/2024 23:59:00",
|
// endDate: "07/09/2024 23:59:00",
|
||||||
defaultDueTime: { hour: 1, minute: 59 },
|
// defaultDueTime: { hour: 1, minute: 59 },
|
||||||
},
|
// },
|
||||||
modules: [
|
// modules: [
|
||||||
{
|
// {
|
||||||
name: "test module 1 with assignments",
|
// name: "test module 1 with assignments",
|
||||||
assignments: [
|
// assignments: [
|
||||||
{
|
// {
|
||||||
name: "test assignment",
|
// name: "test assignment",
|
||||||
description: "here is the description",
|
// description: "here is the description",
|
||||||
dueAt: "07/09/2024 23:59:00",
|
// dueAt: "07/09/2024 23:59:00",
|
||||||
lockAt: "07/09/2024 23:59:00",
|
// lockAt: "07/09/2024 23:59:00",
|
||||||
submissionTypes: [AssignmentSubmissionType.ONLINE_UPLOAD],
|
// submissionTypes: [AssignmentSubmissionType.ONLINE_UPLOAD],
|
||||||
localAssignmentGroupName: "Final Project",
|
// localAssignmentGroupName: "Final Project",
|
||||||
rubric: [
|
// rubric: [
|
||||||
{ points: 4, label: "do task 1" },
|
// { points: 4, label: "do task 1" },
|
||||||
{ points: 2, label: "do task 2" },
|
// { points: 2, label: "do task 2" },
|
||||||
],
|
// ],
|
||||||
allowedFileUploadExtensions: [],
|
// allowedFileUploadExtensions: [],
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
quizzes: [],
|
// quizzes: [],
|
||||||
pages: [],
|
// pages: [],
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
};
|
// };
|
||||||
|
|
||||||
await fileStorageService.saveCourseAsync(testCourse);
|
// await fileStorageService.saveCourseAsync(testCourse);
|
||||||
|
|
||||||
const loadedCourses = await fileStorageService.loadSavedCourses();
|
// const loadedCourses = await fileStorageService.loadSavedCourses();
|
||||||
const loadedCourse = loadedCourses.find(
|
// const loadedCourse = loadedCourses.find(
|
||||||
(c) => c.settings.name === testCourse.settings.name
|
// (c) => c.settings.name === testCourse.settings.name
|
||||||
);
|
// );
|
||||||
|
|
||||||
expect(loadedCourse?.modules[0].assignments).toEqual(
|
// expect(loadedCourse?.modules[0].assignments).toEqual(
|
||||||
testCourse.modules[0].assignments
|
// testCourse.modules[0].assignments
|
||||||
);
|
// );
|
||||||
});
|
// });
|
||||||
|
|
||||||
it("course modules with quizzes can be saved and loaded", async () => {
|
// it("course modules with quizzes can be saved and loaded", async () => {
|
||||||
const testCourse: LocalCourse = {
|
// const testCourse: LocalCourse = {
|
||||||
settings: {
|
// settings: {
|
||||||
name: "Test Course with modules and quiz",
|
// name: "Test Course with modules and quiz",
|
||||||
assignmentGroups: [],
|
// assignmentGroups: [],
|
||||||
daysOfWeek: [],
|
// daysOfWeek: [],
|
||||||
startDate: "07/09/2024 23:59:00",
|
// startDate: "07/09/2024 23:59:00",
|
||||||
endDate: "07/09/2024 23:59:00",
|
// endDate: "07/09/2024 23:59:00",
|
||||||
defaultDueTime: { hour: 1, minute: 59 },
|
// defaultDueTime: { hour: 1, minute: 59 },
|
||||||
},
|
// },
|
||||||
modules: [
|
// modules: [
|
||||||
{
|
// {
|
||||||
name: "test module 1 with quiz",
|
// name: "test module 1 with quiz",
|
||||||
assignments: [],
|
// assignments: [],
|
||||||
quizzes: [
|
// quizzes: [
|
||||||
{
|
// {
|
||||||
name: "Test Quiz",
|
// name: "Test Quiz",
|
||||||
description: "quiz description",
|
// description: "quiz description",
|
||||||
lockAt: "07/09/2024 12:05:00",
|
// lockAt: "07/09/2024 12:05:00",
|
||||||
dueAt: "07/09/2024 12:05:00",
|
// dueAt: "07/09/2024 12:05:00",
|
||||||
shuffleAnswers: true,
|
// shuffleAnswers: true,
|
||||||
oneQuestionAtATime: true,
|
// oneQuestionAtATime: true,
|
||||||
localAssignmentGroupName: "Assignments",
|
// localAssignmentGroupName: "Assignments",
|
||||||
questions: [
|
// questions: [
|
||||||
{
|
// {
|
||||||
text: "test essay",
|
// text: "test essay",
|
||||||
questionType: QuestionType.ESSAY,
|
// questionType: QuestionType.ESSAY,
|
||||||
points: 1,
|
// points: 1,
|
||||||
answers: [],
|
// answers: [],
|
||||||
matchDistractors: [],
|
// matchDistractors: [],
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
showCorrectAnswers: false,
|
// showCorrectAnswers: false,
|
||||||
allowedAttempts: 0,
|
// allowedAttempts: 0,
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
pages: [],
|
// pages: [],
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
};
|
// };
|
||||||
|
|
||||||
await fileStorageService.saveCourseAsync(testCourse);
|
// await fileStorageService.saveCourseAsync(testCourse);
|
||||||
|
|
||||||
const loadedCourses = await fileStorageService.loadSavedCourses();
|
// const loadedCourses = await fileStorageService.loadSavedCourses();
|
||||||
const loadedCourse = loadedCourses.find(
|
// const loadedCourse = loadedCourses.find(
|
||||||
(c) => c.settings.name === testCourse.settings.name
|
// (c) => c.settings.name === testCourse.settings.name
|
||||||
);
|
// );
|
||||||
|
|
||||||
expect(loadedCourse?.modules[0].quizzes).toEqual(
|
// expect(loadedCourse?.modules[0].quizzes).toEqual(
|
||||||
testCourse.modules[0].quizzes
|
// testCourse.modules[0].quizzes
|
||||||
);
|
// );
|
||||||
});
|
// });
|
||||||
|
|
||||||
it("markdown storage fully populated does not lose data", async () => {
|
// it("markdown storage fully populated does not lose data", async () => {
|
||||||
const testCourse: LocalCourse = {
|
// const testCourse: LocalCourse = {
|
||||||
settings: {
|
// settings: {
|
||||||
name: "Test Course with lots of data",
|
// name: "Test Course with lots of data",
|
||||||
assignmentGroups: [],
|
// assignmentGroups: [],
|
||||||
daysOfWeek: [DayOfWeek.Monday, DayOfWeek.Wednesday],
|
// daysOfWeek: [DayOfWeek.Monday, DayOfWeek.Wednesday],
|
||||||
startDate: "07/09/2024 23:59:00",
|
// startDate: "07/09/2024 23:59:00",
|
||||||
endDate: "07/09/2024 23:59:00",
|
// endDate: "07/09/2024 23:59:00",
|
||||||
defaultDueTime: { hour: 1, minute: 59 },
|
// defaultDueTime: { hour: 1, minute: 59 },
|
||||||
},
|
// },
|
||||||
modules: [
|
// modules: [
|
||||||
{
|
// {
|
||||||
name: "new test module",
|
// name: "new test module",
|
||||||
assignments: [
|
// assignments: [
|
||||||
{
|
// {
|
||||||
name: "test assignment",
|
// name: "test assignment",
|
||||||
description: "here is the description",
|
// description: "here is the description",
|
||||||
dueAt: "07/09/2024 23:59:00",
|
// dueAt: "07/09/2024 23:59:00",
|
||||||
lockAt: "07/09/2024 23:59:00",
|
// lockAt: "07/09/2024 23:59:00",
|
||||||
submissionTypes: [AssignmentSubmissionType.ONLINE_UPLOAD],
|
// submissionTypes: [AssignmentSubmissionType.ONLINE_UPLOAD],
|
||||||
localAssignmentGroupName: "Final Project",
|
// localAssignmentGroupName: "Final Project",
|
||||||
rubric: [
|
// rubric: [
|
||||||
{ points: 4, label: "do task 1" },
|
// { points: 4, label: "do task 1" },
|
||||||
{ points: 2, label: "do task 2" },
|
// { points: 2, label: "do task 2" },
|
||||||
],
|
// ],
|
||||||
allowedFileUploadExtensions: [],
|
// allowedFileUploadExtensions: [],
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
quizzes: [
|
// quizzes: [
|
||||||
{
|
// {
|
||||||
name: "Test Quiz",
|
// name: "Test Quiz",
|
||||||
description: "quiz description",
|
// description: "quiz description",
|
||||||
lockAt: "07/09/2024 23:59:00",
|
// lockAt: "07/09/2024 23:59:00",
|
||||||
dueAt: "07/09/2024 23:59:00",
|
// dueAt: "07/09/2024 23:59:00",
|
||||||
shuffleAnswers: true,
|
// shuffleAnswers: true,
|
||||||
oneQuestionAtATime: false,
|
// oneQuestionAtATime: false,
|
||||||
localAssignmentGroupName: "someId",
|
// localAssignmentGroupName: "someId",
|
||||||
allowedAttempts: -1,
|
// allowedAttempts: -1,
|
||||||
questions: [
|
// questions: [
|
||||||
{
|
// {
|
||||||
text: "test short answer",
|
// text: "test short answer",
|
||||||
questionType: QuestionType.SHORT_ANSWER,
|
// questionType: QuestionType.SHORT_ANSWER,
|
||||||
points: 1,
|
// points: 1,
|
||||||
answers: [],
|
// answers: [],
|
||||||
matchDistractors: [],
|
// matchDistractors: [],
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
showCorrectAnswers: false,
|
// showCorrectAnswers: false,
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
pages: [],
|
// pages: [],
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
};
|
// };
|
||||||
|
|
||||||
await fileStorageService.saveCourseAsync(testCourse);
|
// await fileStorageService.saveCourseAsync(testCourse);
|
||||||
|
|
||||||
const loadedCourses = await fileStorageService.loadSavedCourses();
|
// const loadedCourses = await fileStorageService.loadSavedCourses();
|
||||||
const loadedCourse = loadedCourses.find(
|
// const loadedCourse = loadedCourses.find(
|
||||||
(c) => c.settings.name === testCourse.settings.name
|
// (c) => c.settings.name === testCourse.settings.name
|
||||||
);
|
// );
|
||||||
|
|
||||||
expect(loadedCourse).toEqual(testCourse);
|
// expect(loadedCourse).toEqual(testCourse);
|
||||||
});
|
// });
|
||||||
|
|
||||||
it("markdown storage can persist pages", async () => {
|
// it("markdown storage can persist pages", async () => {
|
||||||
const testCourse: LocalCourse = {
|
// const testCourse: LocalCourse = {
|
||||||
settings: {
|
// settings: {
|
||||||
name: "Test Course with page",
|
// name: "Test Course with page",
|
||||||
assignmentGroups: [],
|
// assignmentGroups: [],
|
||||||
daysOfWeek: [DayOfWeek.Monday, DayOfWeek.Wednesday],
|
// daysOfWeek: [DayOfWeek.Monday, DayOfWeek.Wednesday],
|
||||||
startDate: "07/09/2024 23:59:00",
|
// startDate: "07/09/2024 23:59:00",
|
||||||
endDate: "07/09/2024 23:59:00",
|
// endDate: "07/09/2024 23:59:00",
|
||||||
defaultDueTime: { hour: 1, minute: 59 },
|
// defaultDueTime: { hour: 1, minute: 59 },
|
||||||
},
|
// },
|
||||||
modules: [
|
// modules: [
|
||||||
{
|
// {
|
||||||
name: "page test module",
|
// name: "page test module",
|
||||||
assignments: [],
|
// assignments: [],
|
||||||
quizzes: [],
|
// quizzes: [],
|
||||||
pages: [
|
// pages: [
|
||||||
{
|
// {
|
||||||
name: "test page persistence",
|
// name: "test page persistence",
|
||||||
dueAt: "07/09/2024 23:59:00",
|
// dueAt: "07/09/2024 23:59:00",
|
||||||
text: "this is some\n## markdown\n",
|
// text: "this is some\n## markdown\n",
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
};
|
// };
|
||||||
|
|
||||||
await fileStorageService.saveCourseAsync(testCourse);
|
// await fileStorageService.saveCourseAsync(testCourse);
|
||||||
|
|
||||||
const loadedCourses = await fileStorageService.loadSavedCourses();
|
// const loadedCourses = await fileStorageService.loadSavedCourses();
|
||||||
const loadedCourse = loadedCourses.find(
|
// const loadedCourse = loadedCourses.find(
|
||||||
(c) => c.settings.name === testCourse.settings.name
|
// (c) => c.settings.name === testCourse.settings.name
|
||||||
);
|
// );
|
||||||
|
|
||||||
expect(loadedCourse).toEqual(testCourse);
|
// expect(loadedCourse).toEqual(testCourse);
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
|
|||||||
Reference in New Issue
Block a user