diff --git a/nextjs/src/app/course/[courseName]/calendar/CourseCalendar.tsx b/nextjs/src/app/course/[courseName]/calendar/CourseCalendar.tsx index 26bd53f..66e6c79 100644 --- a/nextjs/src/app/course/[courseName]/calendar/CourseCalendar.tsx +++ b/nextjs/src/app/course/[courseName]/calendar/CourseCalendar.tsx @@ -28,7 +28,7 @@ export default function CourseCalendar() { h-full overflow-y-scroll border-4 - border-slate-600 + border-gray-900 rounded-xl bg-slate-950 " diff --git a/nextjs/src/app/course/[courseName]/modules/[moduleName]/quiz/[quizName]/EditQuiz.tsx b/nextjs/src/app/course/[courseName]/modules/[moduleName]/quiz/[quizName]/EditQuiz.tsx index 65fbb00..1eec857 100644 --- a/nextjs/src/app/course/[courseName]/modules/[moduleName]/quiz/[quizName]/EditQuiz.tsx +++ b/nextjs/src/app/course/[courseName]/modules/[moduleName]/quiz/[quizName]/EditQuiz.tsx @@ -7,6 +7,14 @@ import { import { quizMarkdownUtils } from "@/models/local/quiz/utils/quizMarkdownUtils"; import { useEffect, useState } from "react"; import QuizPreview from "./QuizPreview"; +import { + useAddQuizToCanvasMutation, + useCanvasQuizzesQuery, + useDeleteQuizFromCanvasMutation, +} from "@/hooks/canvas/canvasQuizHooks"; +import { Spinner } from "@/components/Spinner"; +import { baseCanvasUrl, canvasApi } from "@/services/canvas/canvasServiceUtils"; +import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks"; export default function EditQuiz({ moduleName, @@ -59,11 +67,54 @@ export default function EditQuiz({ -
- -
+ + + ); +} + +function QuizButtons({ + moduleName, + quizName, +}: { + quizName: string; + moduleName: string; +}) { + const { data: canvasQuizzes } = useCanvasQuizzesQuery(); + const { data: quiz } = useQuizQuery(moduleName, quizName); + const { data: settings } = useLocalCourseSettingsQuery(); + const addToCanvas = useAddQuizToCanvasMutation(); + const deleteFromCanvas = useDeleteQuizFromCanvasMutation(); + + const quizInCanvas = canvasQuizzes.find((c) => c.title === quizName); + + return ( +
+ {!quizInCanvas && ( + + )} + {quizInCanvas && ( + + View in Canvas + + )} + {quizInCanvas && ( + + )} + {(addToCanvas.isPending || deleteFromCanvas.isPending) && }
); } diff --git a/nextjs/src/hooks/canvas/canvasQuizHooks.ts b/nextjs/src/hooks/canvas/canvasQuizHooks.ts index 61abdf1..be71d95 100644 --- a/nextjs/src/hooks/canvas/canvasQuizHooks.ts +++ b/nextjs/src/hooks/canvas/canvasQuizHooks.ts @@ -1,8 +1,62 @@ - +import { + useMutation, + useQueryClient, + useSuspenseQuery, +} from "@tanstack/react-query"; +import { useLocalCourseSettingsQuery } from "../localCourse/localCoursesHooks"; +import { canvasQuizService } from "@/services/canvas/canvasQuizService"; +import { LocalQuiz } from "@/models/local/quiz/localQuiz"; export const canvasQuizKeys = { - quizzes: (canvasCourseId: number )=> ["canvas", canvasCourseId, "quizzes"], -} + quizzes: (canvasCourseId: number) => ["canvas", canvasCourseId, "quizzes"], +}; +export const useCanvasQuizzesQuery = () => { + const { data: settings } = useLocalCourseSettingsQuery(); -export const useCanvasQuizQuery \ No newline at end of file + return useSuspenseQuery({ + queryKey: canvasQuizKeys.quizzes(settings.canvasId), + queryFn: async () => canvasQuizService.getAll(settings.canvasId), + }); +}; + +export const useAddQuizToCanvasMutation = () => { + const { data: settings } = useLocalCourseSettingsQuery(); + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: async (quiz: LocalQuiz) => { + const assignmentGroup = settings.assignmentGroups.find( + (g) => g.name === quiz.localAssignmentGroupName + ); + console.log("starting"); + await canvasQuizService.create( + settings.canvasId, + quiz, + assignmentGroup?.canvasId + ); + console.log("ending"); + }, + onSuccess: () => { + console.log("invalidating"); + queryClient.invalidateQueries({ + queryKey: canvasQuizKeys.quizzes(settings.canvasId), + }); + }, + }); +}; + +export const useDeleteQuizFromCanvasMutation = () => { + const { data: settings } = useLocalCourseSettingsQuery(); + const queryClient = useQueryClient(); + return useMutation({ + mutationFn: async (canvasQuizId: number) => { + await canvasQuizService.delete(settings.canvasId, canvasQuizId); + }, + onSuccess: () => { + queryClient.invalidateQueries({ + queryKey: canvasQuizKeys.quizzes(settings.canvasId), + }); + }, + }); +}; diff --git a/nextjs/src/models/canvas/quizzes/canvasQuizAnswerModel.ts b/nextjs/src/models/canvas/quizzes/canvasQuizAnswerModel.ts new file mode 100644 index 0000000..2f66a9d --- /dev/null +++ b/nextjs/src/models/canvas/quizzes/canvasQuizAnswerModel.ts @@ -0,0 +1,19 @@ +export interface CanvasQuizAnswer { + id: number; + text: string; + html?: string; + weight: number; + // comments?: string; + // text_after_answers?: string; + // answer_match_left?: string; + // answer_match_right?: string; + // matching_answer_incorrect_matches?: string; + // numerical_answer_type?: string; + // exact?: number; + // margin?: number; + // approximate?: number; + // precision?: number; + // start?: number; + // end?: number; + // blank_id?: number; +} diff --git a/nextjs/src/models/canvas/quizzes/canvasQuizQuestionModel.ts b/nextjs/src/models/canvas/quizzes/canvasQuizQuestionModel.ts new file mode 100644 index 0000000..eab3572 --- /dev/null +++ b/nextjs/src/models/canvas/quizzes/canvasQuizQuestionModel.ts @@ -0,0 +1,14 @@ +import { CanvasQuizAnswer } from "./canvasQuizAnswerModel"; + +export interface CanvasQuizQuestion { + id: number; + quiz_id: number; + position?: number; + question_name: string; + question_type: string; + question_text: string; + correct_comments: string; + incorrect_comments: string; + neutral_comments: string; + answers?: CanvasQuizAnswer[]; +} \ No newline at end of file diff --git a/nextjs/src/services/canvas/canvasAssignmentGroupService.ts b/nextjs/src/services/canvas/canvasAssignmentGroupService.ts index 7fc285a..2237bc7 100644 --- a/nextjs/src/services/canvas/canvasAssignmentGroupService.ts +++ b/nextjs/src/services/canvas/canvasAssignmentGroupService.ts @@ -1,14 +1,13 @@ -import { baseCanvasUrl, canvasServiceUtils } from "./canvasServiceUtils"; +import { canvasApi, canvasServiceUtils } from "./canvasServiceUtils"; import { axiosClient } from "../axiosUtils"; import { CanvasAssignmentGroup } from "@/models/canvas/assignments/canvasAssignmentGroup"; import { LocalAssignmentGroup } from "@/models/local/assignment/localAssignmentGroup"; import { rateLimitAwareDelete } from "./canvasWebRequestor"; - export const canvasAssignmentGroupService = { async getAll(courseId: number): Promise { console.log("Requesting assignment groups"); - const url = `${baseCanvasUrl}/courses/${courseId}/assignment_groups`; + const url = `${canvasApi}/courses/${courseId}/assignment_groups`; const assignmentGroups = await canvasServiceUtils.paginatedRequest< CanvasAssignmentGroup[] >({ @@ -22,7 +21,7 @@ export const canvasAssignmentGroupService = { localAssignmentGroup: LocalAssignmentGroup ): Promise { console.log(`Creating assignment group: ${localAssignmentGroup.name}`); - const url = `${baseCanvasUrl}/courses/${canvasCourseId}/assignment_groups`; + const url = `${canvasApi}/courses/${canvasCourseId}/assignment_groups`; const body = { name: localAssignmentGroup.name, group_weight: localAssignmentGroup.weight, @@ -45,7 +44,7 @@ export const canvasAssignmentGroupService = { if (!localAssignmentGroup.canvasId) { throw new Error("Cannot update assignment group if canvas ID is null"); } - const url = `${baseCanvasUrl}/courses/${canvasCourseId}/assignment_groups/${localAssignmentGroup.canvasId}`; + const url = `${canvasApi}/courses/${canvasCourseId}/assignment_groups/${localAssignmentGroup.canvasId}`; const body = { name: localAssignmentGroup.name, group_weight: localAssignmentGroup.weight, @@ -56,11 +55,11 @@ export const canvasAssignmentGroupService = { async delete( canvasCourseId: number, - canvasAssignmentGroupId: number - , assignmentGroupName: string + canvasAssignmentGroupId: number, + assignmentGroupName: string ): Promise { console.log(`Deleting assignment group: ${assignmentGroupName}`); - const url = `${baseCanvasUrl}/courses/${canvasCourseId}/assignment_groups/${canvasAssignmentGroupId}`; + const url = `${canvasApi}/courses/${canvasCourseId}/assignment_groups/${canvasAssignmentGroupId}`; await rateLimitAwareDelete(url); }, }; diff --git a/nextjs/src/services/canvas/canvasAssignmentService.ts b/nextjs/src/services/canvas/canvasAssignmentService.ts index 9503cf7..41a82ae 100644 --- a/nextjs/src/services/canvas/canvasAssignmentService.ts +++ b/nextjs/src/services/canvas/canvasAssignmentService.ts @@ -1,5 +1,5 @@ import { CanvasAssignment } from "@/models/canvas/assignments/canvasAssignment"; -import { baseCanvasUrl, canvasServiceUtils } from "./canvasServiceUtils"; +import { canvasApi, canvasServiceUtils } from "./canvasServiceUtils"; import { LocalAssignment } from "@/models/local/assignment/localAssignment"; import { axiosClient } from "../axiosUtils"; import { markdownToHTMLSafe } from "../htmlMarkdownUtils"; @@ -8,17 +8,15 @@ import { assignmentPoints } from "@/models/local/assignment/utils/assignmentPoin export const canvasAssignmentService = { async getAll(courseId: number): Promise { - const url = `courses/${courseId}/assignments`; - const assignments = await canvasServiceUtils.paginatedRequest< - CanvasAssignment[] - >({ url }); - return assignments.flatMap((assignments) => - assignments.map((a) => ({ - ...a, - due_at: a.due_at ? new Date(a.due_at).toLocaleString() : undefined, // timezones? - lock_at: a.lock_at ? new Date(a.lock_at).toLocaleString() : undefined, // timezones? - })) + const url = `${canvasApi}/courses/${courseId}/assignments`; + const { data: assignments } = await axiosClient.get( + url ); + return assignments.map((a) => ({ + ...a, + due_at: a.due_at ? new Date(a.due_at).toLocaleString() : undefined, // timezones? + lock_at: a.lock_at ? new Date(a.lock_at).toLocaleString() : undefined, // timezones? + })); }, async create( @@ -27,7 +25,7 @@ export const canvasAssignmentService = { canvasAssignmentGroupId?: number ): Promise { console.log(`Creating assignment: ${localAssignment.name}`); - const url = `${baseCanvasUrl}/courses/${canvasCourseId}/assignments`; + const url = `${canvasApi}/courses/${canvasCourseId}/assignments`; const body = { assignment: { name: localAssignment.name, @@ -66,7 +64,7 @@ export const canvasAssignmentService = { canvasAssignmentGroupId?: number ): Promise { console.log(`Updating assignment: ${localAssignment.name}`); - const url = `${baseCanvasUrl}/courses/${courseId}/assignments/${canvasAssignmentId}`; + const url = `${canvasApi}/courses/${courseId}/assignments/${canvasAssignmentId}`; const body = { assignment: { name: localAssignment.name, @@ -94,7 +92,7 @@ export const canvasAssignmentService = { assignmentName: string ): Promise { console.log(`Deleting assignment from Canvas: ${assignmentName}`); - const url = `${baseCanvasUrl}/courses/${courseId}/assignments/${assignmentCanvasId}`; + const url = `${canvasApi}/courses/${courseId}/assignments/${assignmentCanvasId}`; const response = await axiosClient.delete(url); if (!response.status.toString().startsWith("2")) { @@ -134,7 +132,7 @@ export const canvasAssignmentService = { }, }; - const rubricUrl = `${baseCanvasUrl}/courses/${courseId}/rubrics`; + const rubricUrl = `${canvasApi}/courses/${courseId}/rubrics`; const rubricResponse = await axiosClient.post( rubricUrl, rubricBody @@ -142,7 +140,7 @@ export const canvasAssignmentService = { if (!rubricResponse.data) throw new Error("Failed to create rubric"); - const assignmentPointAdjustmentUrl = `${baseCanvasUrl}/courses/${courseId}/assignments/${assignmentCanvasId}`; + const assignmentPointAdjustmentUrl = `${canvasApi}/courses/${courseId}/assignments/${assignmentCanvasId}`; const assignmentPointAdjustmentBody = { assignment: { points_possible: assignmentPoints(localAssignment) }, }; diff --git a/nextjs/src/services/canvas/canvasModuleService.ts b/nextjs/src/services/canvas/canvasModuleService.ts index cd40fd3..23d15b2 100644 --- a/nextjs/src/services/canvas/canvasModuleService.ts +++ b/nextjs/src/services/canvas/canvasModuleService.ts @@ -1,7 +1,7 @@ import { CanvasModuleItem } from "@/models/canvas/modules/canvasModuleItems"; import { CanvasPage } from "@/models/canvas/pages/canvasPageModel"; import { axiosClient } from "../axiosUtils"; -import { baseCanvasUrl } from "./canvasServiceUtils"; +import { canvasApi } from "./canvasServiceUtils"; import { CanvasModule } from "@/models/canvas/modules/canvasModule"; export const canvasModuleService = { @@ -11,7 +11,7 @@ export const canvasModuleService = { item: CanvasModuleItem ) { console.log(`Updating module item ${item.title}`); - const url = `${baseCanvasUrl}/courses/${canvasCourseId}/modules/${canvasModuleId}/items/${item.id}`; + const url = `${canvasApi}/courses/${canvasCourseId}/modules/${canvasModuleId}/items/${item.id}`; const body = { module_item: { title: item.title, position: item.position }, }; @@ -28,7 +28,7 @@ export const canvasModuleService = { contentId: number | string ): Promise { console.log(`Creating new module item ${title}`); - const url = `${baseCanvasUrl}/courses/${canvasCourseId}/modules/${canvasModuleId}/items`; + const url = `${canvasApi}/courses/${canvasCourseId}/modules/${canvasModuleId}/items`; const body = { module_item: { title, type, content_id: contentId } }; await axiosClient.post(url, body); }, @@ -40,7 +40,7 @@ export const canvasModuleService = { canvasPage: CanvasPage ): Promise { console.log(`Creating new module item ${title}`); - const url = `${baseCanvasUrl}/courses/${canvasCourseId}/modules/${canvasModuleId}/items`; + const url = `${canvasApi}/courses/${canvasCourseId}/modules/${canvasModuleId}/items`; const body = { module_item: { title, type: "Page", page_url: canvasPage.url }, }; @@ -48,13 +48,13 @@ export const canvasModuleService = { }, async getCourseModules(canvasCourseId: number) { - const url = `${baseCanvasUrl}/courses/${canvasCourseId}/modules`; + const url = `${canvasApi}/courses/${canvasCourseId}/modules`; const response = await axiosClient.get(url); return response.data; }, async createModule(canvasCourseId: number, moduleName: string) { - const url = `${baseCanvasUrl}/courses/${canvasCourseId}/modules`; + const url = `${canvasApi}/courses/${canvasCourseId}/modules`; const body = { module: { name: moduleName, diff --git a/nextjs/src/services/canvas/canvasPageService.ts b/nextjs/src/services/canvas/canvasPageService.ts index 6fdadc1..5561bd4 100644 --- a/nextjs/src/services/canvas/canvasPageService.ts +++ b/nextjs/src/services/canvas/canvasPageService.ts @@ -1,15 +1,14 @@ import { CanvasPage } from "@/models/canvas/pages/canvasPageModel"; import { LocalCoursePage } from "@/models/local/page/localCoursePage"; -import { baseCanvasUrl, canvasServiceUtils } from "./canvasServiceUtils"; +import { canvasApi, canvasServiceUtils } from "./canvasServiceUtils"; import { markdownToHTMLSafe } from "../htmlMarkdownUtils"; import { axiosClient } from "../axiosUtils"; import { rateLimitAwareDelete } from "./canvasWebRequestor"; - export const canvasPageService = { async getAll(courseId: number): Promise { console.log("requesting pages"); - const url = `${baseCanvasUrl}/courses/${courseId}/pages`; + const url = `${canvasApi}/courses/${courseId}/pages`; const pages = await canvasServiceUtils.paginatedRequest({ url, }); @@ -21,7 +20,7 @@ export const canvasPageService = { page: LocalCoursePage ): Promise { console.log(`Creating course page: ${page.name}`); - const url = `${baseCanvasUrl}/courses/${canvasCourseId}/pages`; + const url = `${canvasApi}/courses/${canvasCourseId}/pages`; const body = { wiki_page: { title: page.name, @@ -42,7 +41,7 @@ export const canvasPageService = { page: LocalCoursePage ): Promise { console.log(`Updating course page: ${page.name}`); - const url = `${baseCanvasUrl}/courses/${courseId}/pages/${canvasPageId}`; + const url = `${canvasApi}/courses/${courseId}/pages/${canvasPageId}`; const body = { wiki_page: { title: page.name, @@ -54,7 +53,7 @@ export const canvasPageService = { async delete(courseId: number, canvasPageId: number): Promise { console.log(`Deleting page from canvas ${canvasPageId}`); - const url = `${baseCanvasUrl}/courses/${courseId}/pages/${canvasPageId}`; + const url = `${canvasApi}/courses/${courseId}/pages/${canvasPageId}`; await rateLimitAwareDelete(url); }, }; diff --git a/nextjs/src/services/canvas/canvasQuizService.ts b/nextjs/src/services/canvas/canvasQuizService.ts index 0ca3ad6..a3b545c 100644 --- a/nextjs/src/services/canvas/canvasQuizService.ts +++ b/nextjs/src/services/canvas/canvasQuizService.ts @@ -1,27 +1,38 @@ import { CanvasQuiz } from "@/models/canvas/quizzes/canvasQuizModel"; import { axiosClient } from "../axiosUtils"; -import { baseCanvasUrl } from "./canvasServiceUtils"; +import { canvasApi } from "./canvasServiceUtils"; import { LocalQuiz } from "@/models/local/quiz/localQuiz"; import { markdownToHTMLSafe } from "../htmlMarkdownUtils"; import { getDateFromStringOrThrow } from "@/models/local/timeUtils"; import { canvasAssignmentService } from "./canvasAssignmentService"; -import { LocalQuizQuestion } from "@/models/local/quiz/localQuizQuestion"; +import { + LocalQuizQuestion, + QuestionType, +} from "@/models/local/quiz/localQuizQuestion"; +import { CanvasQuizQuestion } from "@/models/canvas/quizzes/canvasQuizQuestionModel"; const getAnswers = (question: LocalQuizQuestion) => { - return question.answers.map((answer: any) => ({ - answer_html: answer.htmlText, + if (question.questionType === QuestionType.MATCHING) + return question.answers.map((a) => ({ + answer_match_left: a.text, + answer_match_right: a.matchedText, + })); + + return question.answers.map((answer) => ({ + answer_html: markdownToHTMLSafe(answer.text), answer_weight: answer.correct ? 100 : 0, })); }; + const createQuestionOnly = async ( canvasCourseId: number, canvasQuizId: number, question: LocalQuizQuestion, position: number -): Promise<{ question: any; position: number }> => { - console.log("Creating individual question", question); +) => { + console.log("Creating individual question"); //, question); - const url = `${baseCanvasUrl}/courses/${canvasCourseId}/quizzes/${canvasQuizId}/questions`; + const url = `${canvasApi}/courses/${canvasCourseId}/quizzes/${canvasQuizId}/questions`; const body = { question: { question_text: markdownToHTMLSafe(question.text), @@ -32,7 +43,7 @@ const createQuestionOnly = async ( }, }; - const response = await axiosClient.post(url, body); + const response = await axiosClient.post(url, body); const newQuestion = response.data; if (!newQuestion) throw new Error("Created question is null"); @@ -52,7 +63,7 @@ const hackFixQuestionOrdering = async ( id: qp.question.id.toString(), })); - const url = `${baseCanvasUrl}/courses/${canvasCourseId}/quizzes/${canvasQuizId}/reorder`; + const url = `${canvasApi}/courses/${canvasCourseId}/quizzes/${canvasQuizId}/reorder`; await axiosClient.post(url, { order }); }; @@ -65,21 +76,43 @@ const hackFixRedundantAssignments = async (canvasCourseId: number) => { assignment.submission_types.includes("online_quiz") ); - const deletionTasks = assignmentsToDelete.map((assignment) => - canvasAssignmentService.delete( - canvasCourseId, - assignment.id, - assignment.name + await Promise.all( + assignmentsToDelete.map( + async (assignment) => + await canvasAssignmentService.delete( + canvasCourseId, + assignment.id, + assignment.name + ) ) ); - await Promise.all(deletionTasks); console.log(`Deleted ${assignmentsToDelete.length} redundant assignments`); }; +const createQuizQuestions = async ( + canvasCourseId: number, + canvasQuizId: number, + localQuiz: LocalQuiz +) => { + console.log("Creating quiz questions"); //, localQuiz); + + const tasks = localQuiz.questions.map( + async (question, index) => + await createQuestionOnly(canvasCourseId, canvasQuizId, question, index) + ); + const questionAndPositions = await Promise.all(tasks); + await hackFixQuestionOrdering( + canvasCourseId, + canvasQuizId, + questionAndPositions + ); + await hackFixRedundantAssignments(canvasCourseId); +}; + export const canvasQuizService = { async getAll(canvasCourseId: number): Promise { - const url = `${baseCanvasUrl}/courses/${canvasCourseId}/quizzes`; + const url = `${canvasApi}/courses/${canvasCourseId}/quizzes`; const response = await axiosClient.get(url); return response.data.map((quiz) => ({ ...quiz, @@ -97,7 +130,7 @@ export const canvasQuizService = { ): Promise { console.log("Creating quiz", localQuiz); - const url = `${baseCanvasUrl}/courses/${canvasCourseId}/quizzes`; + const url = `${canvasApi}/courses/${canvasCourseId}/quizzes`; const body = { quiz: { title: localQuiz.name, @@ -124,31 +157,14 @@ export const canvasQuizService = { }, }; - const response = await axiosClient.post(url, body); - const canvasQuiz: CanvasQuiz = response.data; - + const { data: canvasQuiz } = await axiosClient.post(url, body); if (!canvasQuiz) throw new Error("Created quiz is null"); - await this.createQuizQuestions(canvasCourseId, canvasQuiz.id, localQuiz); + await createQuizQuestions(canvasCourseId, canvasQuiz.id, localQuiz); return canvasQuiz.id; }, - - async createQuizQuestions( - canvasCourseId: number, - canvasQuizId: number, - localQuiz: LocalQuiz - ) { - console.log("Creating quiz questions", localQuiz); - - const tasks = localQuiz.questions.map((question, index) => - createQuestionOnly(canvasCourseId, canvasQuizId, question, index) - ); - const questionAndPositions = await Promise.all(tasks); - await hackFixQuestionOrdering( - canvasCourseId, - canvasQuizId, - questionAndPositions - ); - await hackFixRedundantAssignments(canvasCourseId); + async delete(canvasCourseId: number, canvasQuizId: number) { + const url = `${canvasApi}/courses/${canvasCourseId}/quizzes/${canvasQuizId}`; + await axiosClient.delete(url); }, }; diff --git a/nextjs/src/services/canvas/canvasService.ts b/nextjs/src/services/canvas/canvasService.ts index 484849e..8c09540 100644 --- a/nextjs/src/services/canvas/canvasService.ts +++ b/nextjs/src/services/canvas/canvasService.ts @@ -1,19 +1,16 @@ import { CanvasEnrollmentTermModel } from "@/models/canvas/enrollmentTerms/canvasEnrollmentTermModel"; -import { baseCanvasUrl, canvasServiceUtils } from "./canvasServiceUtils"; +import { canvasApi, canvasServiceUtils } from "./canvasServiceUtils"; import { CanvasCourseModel } from "@/models/canvas/courses/canvasCourseModel"; import { CanvasModuleItem } from "@/models/canvas/modules/canvasModuleItems"; import { CanvasPage } from "@/models/canvas/pages/canvasPageModel"; import { CanvasEnrollmentModel } from "@/models/canvas/enrollments/canvasEnrollmentModel"; import { axiosClient } from "../axiosUtils"; - const getAllTerms = async () => { - const url = `${baseCanvasUrl}/accounts/10/terms`; - const { data } = await axiosClient.get< - { - enrollment_terms: CanvasEnrollmentTermModel[]; - } - >(url); + const url = `${canvasApi}/accounts/10/terms`; + const { data } = await axiosClient.get<{ + enrollment_terms: CanvasEnrollmentTermModel[]; + }>(url); const terms = data.enrollment_terms; return terms; }; @@ -21,7 +18,7 @@ const getAllTerms = async () => { export const canvasService = { getAllTerms, async getCourses(termId: number) { - const url = `${baseCanvasUrl}/courses`; + const url = `${canvasApi}/courses`; const response = await axiosClient.get(url); const allCourses = response.data; const coursesInTerm = allCourses @@ -31,7 +28,7 @@ export const canvasService = { }, async getCourse(courseId: number): Promise { - const url = `${baseCanvasUrl}/courses/${courseId}`; + const url = `${canvasApi}/courses/${courseId}`; const { data } = await axiosClient.get(url); return data; }, @@ -56,10 +53,9 @@ export const canvasService = { return currentTerms; }, - async getEnrolledStudents(canvasCourseId: number) { console.log(`Getting students for course ${canvasCourseId}`); - const url = `${baseCanvasUrl}/courses/${canvasCourseId}/enrollments?enrollment_type=student`; + const url = `${canvasApi}/courses/${canvasCourseId}/enrollments?enrollment_type=student`; const { data } = await axiosClient.get(url); if (!data) diff --git a/nextjs/src/services/canvas/canvasServiceUtils.ts b/nextjs/src/services/canvas/canvasServiceUtils.ts index 360b971..48dab46 100644 --- a/nextjs/src/services/canvas/canvasServiceUtils.ts +++ b/nextjs/src/services/canvas/canvasServiceUtils.ts @@ -3,8 +3,8 @@ import { AxiosResponseHeaders, RawAxiosResponseHeaders } from "axios"; import { axiosClient } from "../axiosUtils"; - -export const baseCanvasUrl = "https://snow.instructure.com/api/v1"; +export const baseCanvasUrl = "https://snow.instructure.com"; +export const canvasApi = baseCanvasUrl + "/api/v1"; const getNextUrl = ( headers: AxiosResponseHeaders | RawAxiosResponseHeaders