mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-25 15:18:32 -06:00
trpc stuff
This commit is contained in:
@@ -1,16 +1,11 @@
|
||||
"use client";
|
||||
import { useLocalCoursesSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
||||
import { trpc } from "@/services/trpc/utils";
|
||||
import { getCourseUrl } from "@/services/urlUtils";
|
||||
import Link from "next/link";
|
||||
import { useEffect } from "react";
|
||||
|
||||
export default function CourseList() {
|
||||
const { data: allSettings } = useLocalCoursesSettingsQuery();
|
||||
|
||||
const {data} = trpc.sayHello.useQuery()
|
||||
|
||||
console.log(data);
|
||||
return (
|
||||
<div>
|
||||
{allSettings.map((settings) => (
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
getDateOnlyMarkdownString,
|
||||
} from "@/models/local/timeUtils";
|
||||
import { useAllCourseDataQuery } from "@/hooks/localCourse/localCourseModuleHooks";
|
||||
import { trpc } from "@/services/trpc/utils";
|
||||
|
||||
export default function CalendarItemsContextProvider({
|
||||
children,
|
||||
@@ -17,6 +18,9 @@ export default function CalendarItemsContextProvider({
|
||||
const { assignmentsAndModules, quizzesAndModules, pagesAndModules } =
|
||||
useAllCourseDataQuery();
|
||||
|
||||
|
||||
|
||||
|
||||
const assignmentsByModuleByDate = assignmentsAndModules.reduce(
|
||||
(previous, { assignment, moduleName }) => {
|
||||
const dueDay = getDateOnlyMarkdownString(
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
"use client";
|
||||
import { useAssignmentsQueries } from "@/hooks/localCourse/assignmentHooks";
|
||||
import { usePagesQueries } from "@/hooks/localCourse/pageHooks";
|
||||
import { IModuleItem } from "@/models/local/IModuleItem";
|
||||
import {
|
||||
@@ -13,13 +12,17 @@ import NewItemForm from "./NewItemForm";
|
||||
import { ModuleCanvasStatus } from "./ModuleCanvasStatus";
|
||||
import ClientOnly from "@/components/ClientOnly";
|
||||
import ExpandIcon from "../../../../components/icons/ExpandIcon";
|
||||
import { DraggableItem, useDraggingContext } from "../context/drag/draggingContext";
|
||||
import {
|
||||
DraggableItem,
|
||||
useDraggingContext,
|
||||
} from "../context/drag/draggingContext";
|
||||
import Link from "next/link";
|
||||
import { getModuleItemUrl } from "@/services/urlUtils";
|
||||
import { useCourseContext } from "../context/courseContext";
|
||||
import { Expandable } from "../../../../components/Expandable";
|
||||
import { useDragStyleContext } from "../context/drag/dragStyleContext";
|
||||
import { useItemsQueries } from "@/hooks/localCourse/courseItemHooks";
|
||||
import { useAssignmentsQuery } from "@/hooks/localCourse/assignmentHooks";
|
||||
|
||||
export default function ExpandableModule({
|
||||
moduleName,
|
||||
@@ -28,7 +31,7 @@ export default function ExpandableModule({
|
||||
}) {
|
||||
const { itemDropOnModule } = useDraggingContext();
|
||||
|
||||
const { data: assignments } = useAssignmentsQueries(moduleName);
|
||||
const [assignments] = useAssignmentsQuery(moduleName);
|
||||
const { data: quizzes } = useItemsQueries(moduleName, "Quiz");
|
||||
const { data: pages } = usePagesQueries(moduleName);
|
||||
const modal = useModal();
|
||||
|
||||
@@ -14,7 +14,9 @@ import {
|
||||
getDateFromString,
|
||||
getDateFromStringOrThrow,
|
||||
} from "@/models/local/timeUtils";
|
||||
import { trpc } from "@/services/trpc/utils";
|
||||
import React, { useState } from "react";
|
||||
import { useCourseContext } from "../context/courseContext";
|
||||
|
||||
export default function NewItemForm({
|
||||
moduleName: defaultModuleName,
|
||||
@@ -26,10 +28,15 @@ export default function NewItemForm({
|
||||
onCreate?: () => void;
|
||||
}) {
|
||||
const { data: settings } = useLocalCourseSettingsQuery();
|
||||
const { courseName } = useCourseContext();
|
||||
const { data: modules } = useModuleNamesQuery();
|
||||
const [type, setType] = useState<"Assignment" | "Quiz" | "Page">(
|
||||
"Assignment"
|
||||
);
|
||||
const assignmentCreationMutation = useCreateAssignmentMutation({
|
||||
courseName,
|
||||
moduleName: defaultModuleName ?? "",
|
||||
});
|
||||
|
||||
const [moduleName, setModuleName] = useState<string | undefined>(
|
||||
defaultModuleName
|
||||
@@ -50,12 +57,13 @@ export default function NewItemForm({
|
||||
const [assignmentGroup, setAssignmentGroup] =
|
||||
useState<LocalAssignmentGroup>();
|
||||
|
||||
const createAssignment = useCreateAssignmentMutation();
|
||||
const createPage = useCreatePageMutation();
|
||||
const createQuiz = useCreateItemMutation("Quiz");
|
||||
|
||||
const isPending =
|
||||
createAssignment.isPending || createPage.isPending || createQuiz.isPending;
|
||||
assignmentCreationMutation.isPending ||
|
||||
createPage.isPending ||
|
||||
createQuiz.isPending;
|
||||
|
||||
return (
|
||||
<form
|
||||
@@ -84,8 +92,22 @@ export default function NewItemForm({
|
||||
return;
|
||||
}
|
||||
if (type === "Assignment") {
|
||||
createAssignment.mutate({
|
||||
item: {
|
||||
// createAssignment.mutate({
|
||||
// item: {
|
||||
// name,
|
||||
// description: "",
|
||||
// localAssignmentGroupName: assignmentGroup?.name ?? "",
|
||||
// dueAt,
|
||||
// lockAt,
|
||||
// submissionTypes: settings.defaultAssignmentSubmissionTypes,
|
||||
// allowedFileUploadExtensions: settings.defaultFileUploadTypes,
|
||||
// rubric: [],
|
||||
// },
|
||||
// moduleName: moduleName,
|
||||
// itemName: name,
|
||||
// });
|
||||
assignmentCreationMutation.mutate({
|
||||
assignment: {
|
||||
name,
|
||||
description: "",
|
||||
localAssignmentGroupName: assignmentGroup?.name ?? "",
|
||||
@@ -96,7 +118,8 @@ export default function NewItemForm({
|
||||
rubric: [],
|
||||
},
|
||||
moduleName: moduleName,
|
||||
itemName: name,
|
||||
assignmentName: name,
|
||||
courseName,
|
||||
});
|
||||
} else if (type === "Quiz") {
|
||||
createQuiz.mutate({
|
||||
|
||||
@@ -27,7 +27,7 @@ export default function EditAssignment({
|
||||
const router = useRouter();
|
||||
const { courseName } = useCourseContext();
|
||||
const { data: settings } = useLocalCourseSettingsQuery();
|
||||
const { data: assignment } = useAssignmentQuery(moduleName, assignmentName);
|
||||
const [assignment] = useAssignmentQuery(moduleName, assignmentName);
|
||||
const updateAssignment = useUpdateAssignmentMutation();
|
||||
|
||||
const [assignmentText, setAssignmentText] = useState(
|
||||
|
||||
@@ -12,6 +12,10 @@ import { canvasPageService } from "@/services/canvas/canvasPageService";
|
||||
import { canvasQuizKeys } from "./canvas/canvasQuizHooks";
|
||||
import { canvasPageKeys } from "./canvas/canvasPageHooks";
|
||||
import { getLecturesQueryConfig } from "./localCourse/lectureHooks";
|
||||
import { createServerSideHelpers } from "@trpc/react-query/server";
|
||||
import { appRouter } from "@/services/trpc/router/app";
|
||||
import superjson from "superjson";
|
||||
import { createContext } from "@/services/trpc/context";
|
||||
|
||||
// https://tanstack.com/query/latest/docs/framework/react/guides/ssr
|
||||
export const hydrateCourses = async (queryClient: QueryClient) => {
|
||||
@@ -32,10 +36,27 @@ export const hydrateCourse = async (
|
||||
queryClient: QueryClient,
|
||||
courseSettings: LocalCourseSettings
|
||||
) => {
|
||||
const trpcHelpers = createServerSideHelpers({
|
||||
router: appRouter,
|
||||
ctx: createContext(),
|
||||
transformer: superjson,
|
||||
});
|
||||
|
||||
const courseName = courseSettings.name;
|
||||
const moduleNames = await fileStorageService.modules.getModuleNames(
|
||||
courseName
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
moduleNames.map(
|
||||
async (moduleName) =>
|
||||
await trpcHelpers.assignment.getAllAssignments.fetch({
|
||||
courseName,
|
||||
moduleName,
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
const modulesData = await Promise.all(
|
||||
moduleNames.map((moduleName) => loadAllModuleData(courseName, moduleName))
|
||||
);
|
||||
@@ -77,36 +98,36 @@ export const hydrateCanvasCourse = async (
|
||||
};
|
||||
|
||||
const loadAllModuleData = async (courseName: string, moduleName: string) => {
|
||||
const [assignmentNames, pages, quizzes] = await Promise.all([
|
||||
await fileStorageService.assignments.getAssignmentNames(
|
||||
courseName,
|
||||
moduleName
|
||||
),
|
||||
const [pages, quizzes] = await Promise.all([
|
||||
// await fileStorageService.assignments.getAssignmentNames(
|
||||
// courseName,
|
||||
// moduleName
|
||||
// ),
|
||||
await fileStorageService.pages.getPages(courseName, moduleName),
|
||||
await fileStorageService.quizzes.getQuizzes(courseName, moduleName),
|
||||
]);
|
||||
|
||||
const [assignments] = await Promise.all([
|
||||
await Promise.all(
|
||||
assignmentNames.map(async (assignmentName) => {
|
||||
try {
|
||||
return await fileStorageService.assignments.getAssignment(
|
||||
courseName,
|
||||
moduleName,
|
||||
assignmentName
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(`Error fetching assignment: ${assignmentName}`, error);
|
||||
return null; // or any other placeholder value
|
||||
}
|
||||
})
|
||||
),
|
||||
]);
|
||||
// const [assignments] = await Promise.all([
|
||||
// await Promise.all(
|
||||
// assignmentNames.map(async (assignmentName) => {
|
||||
// try {
|
||||
// return await fileStorageService.assignments.getAssignment(
|
||||
// courseName,
|
||||
// moduleName,
|
||||
// assignmentName
|
||||
// );
|
||||
// } catch (error) {
|
||||
// console.error(`Error fetching assignment: ${assignmentName}`, error);
|
||||
// return null; // or any other placeholder value
|
||||
// }
|
||||
// })
|
||||
// ),
|
||||
// ]);
|
||||
|
||||
const assignmentsLoaded = assignments.filter((a) => a !== null);
|
||||
// const assignmentsLoaded = assignments.filter((a) => a !== null);
|
||||
return {
|
||||
moduleName,
|
||||
assignments: assignmentsLoaded,
|
||||
// assignments: assignmentsLoaded,
|
||||
quizzes,
|
||||
pages,
|
||||
};
|
||||
|
||||
@@ -1,38 +1,65 @@
|
||||
"use client";
|
||||
import { trpc } from "@/services/trpc/utils";
|
||||
import {
|
||||
getAllItemsQueryConfig,
|
||||
getItemQueryConfig,
|
||||
useCreateItemMutation,
|
||||
useDeleteItemMutation,
|
||||
useItemQuery,
|
||||
useItemsQueries,
|
||||
useUpdateItemMutation,
|
||||
} from "./courseItemHooks";
|
||||
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
|
||||
|
||||
export const getAllAssignmentsQueryConfig = (
|
||||
courseName: string,
|
||||
moduleName: string
|
||||
) => getAllItemsQueryConfig(courseName, moduleName, "Assignment");
|
||||
// export const getAllAssignmentsQueryConfig = (
|
||||
// courseName: string,
|
||||
// moduleName: string
|
||||
// ) => getAllItemsQueryConfig(courseName, moduleName, "Assignment");
|
||||
|
||||
export const getAssignmentQueryConfig = (
|
||||
courseName: string,
|
||||
moduleName: string,
|
||||
assignmentName: string
|
||||
) => getItemQueryConfig(courseName, moduleName, assignmentName, "Assignment");
|
||||
// export const getAssignmentQueryConfig = (
|
||||
// courseName: string,
|
||||
// moduleName: string,
|
||||
// assignmentName: string
|
||||
// ) => getItemQueryConfig(courseName, moduleName, assignmentName, "Assignment");
|
||||
|
||||
export const useAssignmentQuery = (
|
||||
moduleName: string,
|
||||
assignmentName: string
|
||||
) => useItemQuery(moduleName, assignmentName, "Assignment");
|
||||
) => {
|
||||
const { courseName } = useCourseContext();
|
||||
return trpc.assignment.getAssignment.useSuspenseQuery({
|
||||
moduleName,
|
||||
courseName,
|
||||
assignmentName,
|
||||
});
|
||||
};
|
||||
|
||||
export const useAssignmentsQueries = (moduleName: string) =>
|
||||
useItemsQueries(moduleName, "Assignment");
|
||||
export const useAssignmentsQuery = (moduleName: string) => {
|
||||
const { courseName } = useCourseContext();
|
||||
return trpc.assignment.getAllAssignments.useSuspenseQuery({
|
||||
moduleName,
|
||||
courseName,
|
||||
});
|
||||
};
|
||||
// useItemsQueries(moduleName, "Assignment");
|
||||
|
||||
export const useUpdateAssignmentMutation = () =>
|
||||
useUpdateItemMutation("Assignment");
|
||||
|
||||
export const useCreateAssignmentMutation = () =>
|
||||
useCreateItemMutation("Assignment");
|
||||
export const useCreateAssignmentMutation = ({
|
||||
courseName,
|
||||
moduleName,
|
||||
}: {
|
||||
courseName: string;
|
||||
moduleName: string;
|
||||
}) => {
|
||||
const utils = trpc.useUtils();
|
||||
return trpc.assignment.createAssignment.useMutation({
|
||||
onSuccess: () => {
|
||||
utils.assignment.getAllAssignments.invalidate({ courseName, moduleName });
|
||||
},
|
||||
});
|
||||
};
|
||||
// useCreateItemMutation("Assignment");
|
||||
|
||||
export const useDeleteAssignmentMutation = () =>
|
||||
useDeleteItemMutation("Assignment");
|
||||
|
||||
@@ -6,12 +6,12 @@ import {
|
||||
useSuspenseQuery,
|
||||
} from "@tanstack/react-query";
|
||||
import { localCourseKeys } from "./localCourseKeys";
|
||||
import { getAllAssignmentsQueryConfig } from "./assignmentHooks";
|
||||
import { getAllItemsQueryConfig } from "./courseItemHooks";
|
||||
import {
|
||||
createModuleOnServer,
|
||||
getModuleNamesFromServer,
|
||||
} from "./localCourseModuleServerActions";
|
||||
import { trpc } from "@/services/trpc/utils";
|
||||
|
||||
export const useModuleNamesQuery = () => {
|
||||
const { courseName } = useCourseContext();
|
||||
@@ -42,21 +42,31 @@ export const useAllCourseDataQuery = () => {
|
||||
const { courseName } = useCourseContext();
|
||||
const { data: moduleNames } = useModuleNamesQuery();
|
||||
|
||||
const { data: assignmentsAndModules } = useSuspenseQueries({
|
||||
queries: moduleNames.map((moduleName) =>
|
||||
getAllAssignmentsQueryConfig(courseName, moduleName)
|
||||
),
|
||||
combine: (results) => ({
|
||||
data: results.flatMap((r, i) =>
|
||||
r.data.map((assignment) => ({
|
||||
moduleName: moduleNames[i],
|
||||
assignment,
|
||||
}))
|
||||
),
|
||||
pending: results.some((r) => r.isPending),
|
||||
}),
|
||||
const [assignments] = trpc.useSuspenseQueries((t) =>
|
||||
moduleNames.map((moduleName) =>
|
||||
t.assignment.getAllAssignments({ courseName, moduleName })
|
||||
)
|
||||
);
|
||||
|
||||
const assignmentsAndModules = moduleNames.flatMap((moduleName, index) => {
|
||||
return assignments[index].map((assignment) => ({ moduleName, assignment }));
|
||||
});
|
||||
|
||||
// const { data: assignmentsAndModules } = useSuspenseQueries({
|
||||
// queries: moduleNames.map((moduleName) =>
|
||||
// getAllAssignmentsQueryConfig(courseName, moduleName)
|
||||
// ),
|
||||
// combine: (results) => ({
|
||||
// data: results.flatMap((r, i) =>
|
||||
// r.data.map((assignment) => ({
|
||||
// moduleName: moduleNames[i],
|
||||
// assignment,
|
||||
// }))
|
||||
// ),
|
||||
// pending: results.some((r) => r.isPending),
|
||||
// }),
|
||||
// });
|
||||
|
||||
const { data: quizzesAndModules } = useSuspenseQueries({
|
||||
queries: moduleNames.map((moduleName) =>
|
||||
getAllItemsQueryConfig(courseName, moduleName, "Quiz")
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { z } from "zod";
|
||||
export enum AssignmentSubmissionType {
|
||||
ONLINE_TEXT_ENTRY = "online_text_entry",
|
||||
ONLINE_UPLOAD = "online_upload",
|
||||
@@ -6,6 +7,14 @@ export enum AssignmentSubmissionType {
|
||||
ONLINE_URL = "online_url",
|
||||
NONE = "none",
|
||||
}
|
||||
export const zodAssignmentSubmissionType = z.enum([
|
||||
AssignmentSubmissionType.ONLINE_TEXT_ENTRY,
|
||||
AssignmentSubmissionType.ONLINE_UPLOAD,
|
||||
AssignmentSubmissionType.ONLINE_QUIZ,
|
||||
AssignmentSubmissionType.DISCUSSION_TOPIC,
|
||||
AssignmentSubmissionType.ONLINE_URL,
|
||||
AssignmentSubmissionType.NONE,
|
||||
]);
|
||||
|
||||
export const AssignmentSubmissionTypeList: AssignmentSubmissionType[] = [
|
||||
AssignmentSubmissionType.ONLINE_TEXT_ENTRY,
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import { IModuleItem } from "../IModuleItem";
|
||||
import { AssignmentSubmissionType } from "./assignmentSubmissionType";
|
||||
import { RubricItem } from "./rubricItem";
|
||||
import {
|
||||
AssignmentSubmissionType,
|
||||
zodAssignmentSubmissionType,
|
||||
} from "./assignmentSubmissionType";
|
||||
import { RubricItem, zodRubricItem } from "./rubricItem";
|
||||
import { assignmentMarkdownParser } from "./utils/assignmentMarkdownParser";
|
||||
import { assignmentMarkdownSerializer } from "./utils/assignmentMarkdownSerializer";
|
||||
import { z } from "zod";
|
||||
|
||||
export interface LocalAssignment extends IModuleItem {
|
||||
name: string;
|
||||
@@ -15,6 +19,16 @@ export interface LocalAssignment extends IModuleItem {
|
||||
rubric: RubricItem[];
|
||||
}
|
||||
|
||||
export const zodLocalAssignment = z.object({
|
||||
name: z.string(),
|
||||
description: z.string(),
|
||||
lockAt: z.string().optional(),
|
||||
dueAt: z.string(),
|
||||
localAssignmentGroupName: z.string(),
|
||||
submissionTypes: zodAssignmentSubmissionType.array(),
|
||||
allowedFileUploadExtensions: z.string().array(),
|
||||
rubric: zodRubricItem.array(),
|
||||
});
|
||||
|
||||
export const localAssignmentMarkdown = {
|
||||
parseMarkdown: assignmentMarkdownParser.parseMarkdown,
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export interface RubricItem {
|
||||
label: string;
|
||||
points: number;
|
||||
}
|
||||
|
||||
export const zodRubricItem = z.object({
|
||||
label: z.string(),
|
||||
points: z.number(),
|
||||
});
|
||||
|
||||
export const rubricItemIsExtraCredit = (item: RubricItem) => {
|
||||
const extraCredit = '(extra credit)';
|
||||
const extraCredit = "(extra credit)";
|
||||
return item.label.toLowerCase().includes(extraCredit.toLowerCase());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { createContext } from "../context";
|
||||
import publicProcedure from "../procedures/public";
|
||||
import { createCallerFactory, mergeRouters, router } from "../trpc";
|
||||
import { assignmentRouter } from "./assignmentRouter";
|
||||
|
||||
export const helloRouter = router({
|
||||
sayHello: publicProcedure.query(() => {
|
||||
@@ -10,8 +11,10 @@ export const helloRouter = router({
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
export const appRouter = mergeRouters(helloRouter);
|
||||
export const appRouter = router({
|
||||
hello: helloRouter,
|
||||
assignment: assignmentRouter,
|
||||
});
|
||||
|
||||
export const createCaller = createCallerFactory(appRouter);
|
||||
|
||||
|
||||
@@ -2,8 +2,9 @@ import publicProcedure from "../procedures/public";
|
||||
import { z } from "zod";
|
||||
import { router } from "../trpc";
|
||||
import { fileStorageService } from "@/services/fileStorage/fileStorageService";
|
||||
import { zodLocalAssignment } from "@/models/local/assignment/localAssignment";
|
||||
|
||||
export const courseItemRouter = router({
|
||||
export const assignmentRouter = router({
|
||||
getAssignment: publicProcedure
|
||||
.input(
|
||||
z.object({
|
||||
@@ -32,4 +33,28 @@ export const courseItemRouter = router({
|
||||
moduleName
|
||||
);
|
||||
}),
|
||||
createAssignment: publicProcedure
|
||||
.input(
|
||||
z.object({
|
||||
courseName: z.string(),
|
||||
moduleName: z.string(),
|
||||
assignmentName: z.string(),
|
||||
assignment: zodLocalAssignment,
|
||||
})
|
||||
)
|
||||
.mutation(
|
||||
async ({
|
||||
input: { courseName, moduleName, assignmentName, assignment },
|
||||
ctx,
|
||||
}) => {
|
||||
await fileStorageService.assignments.updateOrCreateAssignment({
|
||||
courseName,
|
||||
moduleName,
|
||||
assignmentName,
|
||||
assignment,
|
||||
});
|
||||
|
||||
ctx;
|
||||
}
|
||||
),
|
||||
});
|
||||
Reference in New Issue
Block a user