fixed page key

This commit is contained in:
2024-09-02 11:21:07 -06:00
parent 1b03061fdd
commit 130035cc48
15 changed files with 446 additions and 336 deletions

View File

@@ -4,6 +4,9 @@ export async function GET(
_request: Request,
{ params: { courseName } }: { params: { courseName: string } }
) {
const settings = await fileStorageService.getCourseSettings(courseName)
if (courseName.includes(".js.map")) {
return Response.json({});
}
const settings = await fileStorageService.getCourseSettings(courseName);
return Response.json(settings);
}

View File

@@ -27,7 +27,7 @@ export const CalendarMonth = ({ month }: { month: CalendarMonthModel }) => {
aria-expanded={!isCollapsed}
aria-controls={monthName}
> */}
{monthName}
{monthName}
{/* </button> */}
</h3>
@@ -41,13 +41,25 @@ export const CalendarMonth = ({ month }: { month: CalendarMonthModel }) => {
</div>
{month.daysByWeek.map((week, weekIndex) => (
<div className="grid grid-cols-7 m-3" key={weekIndex}>
{week.map((day, dayIndex) => (
<Day key={dayIndex} day={day} month={month.month} />
))}
</div>
<CalendarWeek key={weekIndex} week={week} monthNumber={month.month} />
))}
</div>
</>
);
};
function CalendarWeek({
week,
monthNumber,
}: {
week: Date[];
monthNumber: number;
}) {
return (
<div className="grid grid-cols-7 m-3">
{week.map((day, dayIndex) => (
<Day key={dayIndex} day={day} month={monthNumber} />
))}
</div>
);
}

View File

@@ -4,20 +4,24 @@ import { useCourseContext } from "../context/courseContext";
import { getMonthsBetweenDates } from "./calendarMonthUtils";
import { CalendarMonth } from "./CalendarMonth";
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
import { useMemo } from "react";
export default function CourseCalendar() {
const { courseName } = useCourseContext();
const { data: settings } = useLocalCourseSettingsQuery(courseName);
const startDateTime = getDateFromStringOrThrow(
settings.startDate,
"course start date"
const startDateTime = useMemo(
() => getDateFromStringOrThrow(settings.startDate, "course start date"),
[settings.startDate]
);
const endDateTime = getDateFromStringOrThrow(
settings.endDate,
"course end date"
const endDateTime = useMemo(
() => getDateFromStringOrThrow(settings.endDate, "course end date"),
[settings.endDate]
);
const months = useMemo(
() => getMonthsBetweenDates(startDateTime, endDateTime),
[endDateTime, startDateTime]
);
const months = getMonthsBetweenDates(startDateTime, endDateTime);
return (
<div

View File

@@ -1,8 +1,12 @@
import React from "react";
"use client";
import React, { useCallback, useMemo } from "react";
import { useCourseContext } from "../context/courseContext";
import { useModuleDataQuery } from "@/hooks/localCourse/localCoursesHooks";
import { getDateFromStringOrThrow } from "@/models/local/timeUtils";
import Link from "next/link";
import { LocalAssignment } from "@/models/local/assignmnet/localAssignment";
import { LocalQuiz } from "@/models/local/quiz/localQuiz";
import { LocalCoursePage } from "@/models/local/page/localCoursePage";
export default function DayItemsInModule({
day,
@@ -17,54 +21,105 @@ export default function DayItemsInModule({
moduleName
);
const todaysAssignments = assignments.filter((a) => {
const dueDate = getDateFromStringOrThrow(
a.dueAt,
"due at for assignment in day"
);
return (
dueDate.getFullYear() === day.getFullYear() &&
dueDate.getMonth() === day.getMonth() &&
dueDate.getDate() === day.getDate()
);
});
const todaysQuizzes = quizzes.filter((q) => {
const dueDate = getDateFromStringOrThrow(q.dueAt, "due at for quiz in day");
return (
dueDate.getFullYear() === day.getFullYear() &&
dueDate.getMonth() === day.getMonth() &&
dueDate.getDate() === day.getDate()
);
});
const todaysPages = pages.filter((p) => {
const dueDate = getDateFromStringOrThrow(p.dueAt, "due at for page in day");
return (
dueDate.getFullYear() === day.getFullYear() &&
dueDate.getMonth() === day.getMonth() &&
dueDate.getDate() === day.getDate()
);
});
const todaysAssignments = useMemo(
() =>
assignments.filter((a) => {
const dueDate = getDateFromStringOrThrow(
a.dueAt,
"due at for assignment in day"
);
return (
dueDate.getFullYear() === day.getFullYear() &&
dueDate.getMonth() === day.getMonth() &&
dueDate.getDate() === day.getDate()
);
}),
[assignments, day]
);
const todaysQuizzes = useMemo(
() =>
quizzes.filter((q) => {
const dueDate = getDateFromStringOrThrow(
q.dueAt,
"due at for quiz in day"
);
return (
dueDate.getFullYear() === day.getFullYear() &&
dueDate.getMonth() === day.getMonth() &&
dueDate.getDate() === day.getDate()
);
}),
[day, quizzes]
);
const todaysPages = useMemo(
() =>
pages.filter((p) => {
const dueDate = getDateFromStringOrThrow(
p.dueAt,
"due at for page in day"
);
return (
dueDate.getFullYear() === day.getFullYear() &&
dueDate.getMonth() === day.getMonth() &&
dueDate.getDate() === day.getDate()
);
}),
[day, pages]
);
const startAssignmentDrag = useCallback(
(a: LocalAssignment) => () =>
startItemDrag({
type: "assignment",
item: a,
sourceModuleName: moduleName,
}),
[moduleName, startItemDrag]
);
const startQuizDrag = useCallback(
(q: LocalQuiz) => () =>
startItemDrag({
type: "quiz",
item: q,
sourceModuleName: moduleName,
}),
[moduleName, startItemDrag]
);
const starPageDrag = useCallback(
(p: LocalCoursePage) => () =>
startItemDrag({
type: "page",
item: p,
sourceModuleName: moduleName,
}),
[moduleName, startItemDrag]
);
return (
<>
<ul className="list-disc ms-4">
{todaysAssignments.map((a) => (
<li key={a.name}>{a.name}</li>
<li
key={a.name}
role="button"
draggable="true"
onDragStart={startAssignmentDrag(a)}
onDragEnd={endItemDrag}
>
{a.name}
</li>
))}
{todaysQuizzes.map((q) => (
<li
key={q.name}
role="button"
draggable="true"
onDragStart={() =>
startItemDrag({
type: "quiz",
item: q,
sourceModuleName: moduleName,
})
}
onDragStart={startQuizDrag(q)}
onDragEnd={endItemDrag}
>
<Link href={`/course/${courseName}/modules/${moduleName}/quiz/${q.name}`}>{q.name}</Link>
<Link
href={`/course/${courseName}/modules/${moduleName}/quiz/${q.name}`}
>
{q.name}
</Link>
</li>
))}
{todaysPages.map((p) => (
@@ -72,13 +127,7 @@ export default function DayItemsInModule({
key={p.name}
role="button"
draggable="true"
onDragStart={() =>
startItemDrag({
type: "page",
item: p,
sourceModuleName: moduleName,
})
}
onDragStart={starPageDrag(p)}
>
{p.name}
</li>

View File

@@ -49,19 +49,26 @@ export default function CourseContextProvider({
}
setItemBeingDragged(undefined);
},
[itemBeingDragged, settings.defaultDueTime.hour, settings.defaultDueTime.minute, updateQuizMutation]
[
itemBeingDragged,
settings.defaultDueTime.hour,
settings.defaultDueTime.minute,
updateQuizMutation,
]
);
const startItemDrag = useCallback((d: DraggableItem) => {
setItemBeingDragged(d);
}, []);
const endItemDrag = useCallback(() => {
setItemBeingDragged(undefined);
}, []);
return (
<CourseContext.Provider
value={{
courseName: localCourseName,
startItemDrag: (d) => {
setItemBeingDragged(d);
},
endItemDrag: () => {
setItemBeingDragged(undefined);
},
startItemDrag: startItemDrag,
endItemDrag: endItemDrag,
itemDrop,
}}
>

View File

@@ -1,4 +1,8 @@
import { dehydrate, HydrationBoundary, QueryClient } from "@tanstack/react-query";
import {
dehydrate,
HydrationBoundary,
QueryClient,
} from "@tanstack/react-query";
import { hydrateCourse } from "@/hooks/hookHydration";
import { getQueryClient } from "@/app/providersQueryClientUtils";
@@ -9,6 +13,10 @@ export default async function CourseLayout({
children: React.ReactNode;
params: { courseName: string };
}) {
if (courseName.includes(".js.map")) {
console.log("cannot load course that is .js.map " + courseName);
return <div></div>;
}
const queryClient = getQueryClient();
await hydrateCourse(queryClient, courseName);

View File

@@ -1,11 +0,0 @@
import { hydrateCourses } from "@/hooks/hookHydration";
import { createQueryClientForServer } from "@/services/utils/queryClientServer";
import { dehydrate } from "@tanstack/react-query";
export async function getDehydratedState() {
const queryClient = createQueryClientForServer();
await hydrateCourses(queryClient);
const dehydratedState = dehydrate(queryClient);
return dehydratedState;
}

View File

@@ -6,7 +6,7 @@ export function makeQueryClient() {
queries: {
// With SSR, we usually want to set some default staleTime
// above 0 to avoid refetching immediately on the client
staleTime: 1000,
staleTime: 60_000,
},
},
});

View File

@@ -1,7 +1,7 @@
import { QueryClient } from "@tanstack/react-query";
import { localCourseKeys } from "./localCourse/localCourseKeys";
import { fileStorageService } from "@/services/fileStorage/fileStorageService";
// https://tanstack.com/query/latest/docs/framework/react/guides/ssr
export const hydrateCourses = async (queryClient: QueryClient) => {
await queryClient.prefetchQuery({
queryKey: localCourseKeys.allCourses,
@@ -13,6 +13,7 @@ export const hydrateCourse = async (
queryClient: QueryClient,
courseName: string
) => {
const settings = await fileStorageService.getCourseSettings(courseName);
const moduleNames = await fileStorageService.getModuleNames(courseName);
const modulesData = await Promise.all(

View File

@@ -15,7 +15,7 @@ export const useAssignmentNamesQuery = (
encodeURIComponent(courseName) +
"/modules/" +
encodeURIComponent(moduleName) +
"/assignments"
"/assignments";
const response = await axios.get(url);
return response.data;
},
@@ -41,8 +41,6 @@ const getAssignmentQueryConfig = (
encodeURIComponent(moduleName) +
"/assignments/" +
encodeURIComponent(assignmentName);
console.log(url);
const response = await axios.get(url);
return response.data;
},

View File

@@ -8,6 +8,7 @@ import {
} from "./assignmentHooks";
import { usePageNamesQuery, usePagesQueries } from "./pageHooks";
import { useQuizNamesQuery, useQuizzesQueries } from "./quizHooks";
import { useMemo } from "react";
export const useLocalCourseNamesQuery = () =>
useSuspenseQuery({
@@ -59,11 +60,14 @@ export const useModuleDataQuery = (courseName: string, moduleName: string) => {
);
const { data: pages } = usePagesQueries(courseName, moduleName, pageNames);
return {
assignments,
quizzes,
pages,
};
return useMemo(
() => ({
assignments,
quizzes,
pages,
}),
[assignments, pages, quizzes]
);
};
// export const useUpdateCourseMutation = (courseName: string) => {

View File

@@ -27,8 +27,8 @@ export const usePagesQueries = (
courseName: string,
moduleName: string,
pageNames: string[]
) =>
useSuspenseQueries({
) => {
return useSuspenseQueries({
queries: pageNames.map((name) =>
getPageQueryConfig(courseName, moduleName, name)
),
@@ -37,6 +37,7 @@ export const usePagesQueries = (
pending: results.some((r) => r.isPending),
}),
});
};
function getPageQueryConfig(
courseName: string,
@@ -44,7 +45,7 @@ function getPageQueryConfig(
pageName: string
) {
return {
queryKey: localCourseKeys.quiz(courseName, moduleName, pageName),
queryKey: localCourseKeys.page(courseName, moduleName, pageName),
queryFn: async (): Promise<LocalCoursePage> => {
const url =
"/api/courses/" +
@@ -53,8 +54,15 @@ function getPageQueryConfig(
encodeURIComponent(moduleName) +
"/pages/" +
encodeURIComponent(pageName);
const response = await axios.get(url);
return response.data;
try {
console.log("making a request to get a page");
const response = await axios.get(url);
return response.data;
} catch (e) {
console.log("error getting page", e, url);
debugger;
throw e;
}
},
};
}