no errors when viewing a different course

This commit is contained in:
2025-04-09 12:26:02 -06:00
parent 0fef2a6b87
commit b35ba0f939
8 changed files with 80 additions and 46 deletions

1
run.sh
View File

@@ -16,6 +16,7 @@ docker run -it --rm \
-v ~/projects/faculty/1405/2025_spring_alex:/app/storage/1405 \ -v ~/projects/faculty/1405/2025_spring_alex:/app/storage/1405 \
-v ~/projects/faculty/3840_Telemetry/2025_spring_alex/modules:/app/storage/telemetry \ -v ~/projects/faculty/3840_Telemetry/2025_spring_alex/modules:/app/storage/telemetry \
-v ~/projects/faculty/4620_Distributed/2025Spring/modules:/app/storage/distributed \ -v ~/projects/faculty/4620_Distributed/2025Spring/modules:/app/storage/distributed \
-v ~/projects/faculty/1430/2025-spring-jonathan/Modules:/app/storage/jonathan-ux \
-v ~/projects/public:/app/public/images/public \ -v ~/projects/public:/app/public/images/public \
-v ~/projects/facultyFiles:/app/public/images/facultyFiles \ -v ~/projects/facultyFiles:/app/public/images/facultyFiles \
node \ node \

View File

@@ -1,4 +1,7 @@
import { getAxiosErrorMessage } from "@/services/axiosUtils";
import { isServer, QueryCache, QueryClient } from "@tanstack/react-query"; import { isServer, QueryCache, QueryClient } from "@tanstack/react-query";
import { AxiosError } from "axios";
import toast from "react-hot-toast";
export function makeQueryClient() { export function makeQueryClient() {
return new QueryClient({ return new QueryClient({
@@ -13,6 +16,15 @@ export function makeQueryClient() {
retry: 0, retry: 0,
refetchOnMount: false, refetchOnMount: false,
}, },
mutations: {
onError: (error) => {
const message = getAxiosErrorMessage(error as AxiosError);
console.error("Mutation error:", message);
if (!isServer) {
toast.error(message);
}
},
},
}, },
queryCache: new QueryCache({ queryCache: new QueryCache({
onError: (e) => console.log("error in query client", e), onError: (e) => console.log("error in query client", e),

View File

@@ -38,8 +38,8 @@ export const useAddAssignmentToCanvasMutation = () => {
moduleName: string; moduleName: string;
}) => { }) => {
if (!canvasModules) { if (!canvasModules) {
console.log("cannot add assignment until modules loaded"); // console.log("cannot add assignment until modules loaded");
return; throw new Error("cannot add assignment until modules loaded");
} }
const assignmentGroup = settings.assignmentGroups.find( const assignmentGroup = settings.assignmentGroups.find(

View File

@@ -17,8 +17,7 @@ if (!isServer) {
} else { } else {
const token = process.env.CANVAS_TOKEN; const token = process.env.CANVAS_TOKEN;
if (!token) { if (!token) {
console.error("CANVAS_TOKEN not in environment") console.error("CANVAS_TOKEN not in environment");
// throw new Error("CANVAS_TOKEN not in environment");
} else { } else {
axiosClient.interceptors.request.use((config) => { axiosClient.interceptors.request.use((config) => {
if (config.url && config.url.startsWith(canvasBaseUrl)) { if (config.url && config.url.startsWith(canvasBaseUrl)) {
@@ -32,28 +31,37 @@ if (!isServer) {
axiosClient.interceptors.response.use( axiosClient.interceptors.response.use(
(response) => response, (response) => response,
(error: AxiosError) => { (error: AxiosError) => {
const errorMessage = getAxiosErrorMessage(error);
if (errorMessage) toast.error(errorMessage);
return Promise.reject(error);
}
);
export function getAxiosErrorMessage(error: AxiosError) {
if (error.response) { if (error.response) {
// console.log("response error", error.response); console.log("response error", error.response);
const responseErrorText = const responseErrorText =
typeof error.response.data === "object" typeof error.response.data === "object"
? (error.response.data as any).error ? (error.response.data as any).error
: error.response.data; : error.response.data;
if (!isServer) {
toast.error( if (
`Error: ${error.response.status} - ${responseErrorText}, ${decodeURI( !isServer &&
error.response.config.url ?? "" error.config?.method?.toUpperCase() !== "GET" &&
)}` error.response.status !== 403
); ) {
return `Error: ${
error.response.status
} - ${responseErrorText}, ${decodeURI(error.response.config.url ?? "")}`;
} }
} else if (error.request) { } else if (error.request) {
if (!isServer) { if (!isServer) {
toast.error("Error: No response from server"); return "Error: No response from server";
} }
} else { } else {
if (!isServer) { if (!isServer) {
toast.error(`Error: ${error.message}`); return `Error: ${error.message}`;
} }
} }
return Promise.reject(error); return "";
} }
);

View File

@@ -50,7 +50,7 @@ export const canvasModuleService = {
async getCourseModules(canvasCourseId: number) { async getCourseModules(canvasCourseId: number) {
const url = `${canvasApi}/courses/${canvasCourseId}/modules`; const url = `${canvasApi}/courses/${canvasCourseId}/modules`;
const response = await paginatedRequest<CanvasModule[]>({ url }); const response = await paginatedRequest<CanvasModule[]>({ url });
return response return response;
}, },
async createModule(canvasCourseId: number, moduleName: string) { async createModule(canvasCourseId: number, moduleName: string) {

View File

@@ -9,11 +9,21 @@ import { LocalCourseSettings } from "@/models/local/localCourseSettings";
export const canvasPageService = { export const canvasPageService = {
async getAll(courseId: number): Promise<CanvasPage[]> { async getAll(courseId: number): Promise<CanvasPage[]> {
console.log("requesting pages"); console.log("requesting pages");
try {
const url = `${canvasApi}/courses/${courseId}/pages`; const url = `${canvasApi}/courses/${courseId}/pages`;
const pages = await paginatedRequest<CanvasPage[]>({ const pages = await paginatedRequest<CanvasPage[]>({
url, url,
}); });
return pages.flatMap((pageList) => pageList); return pages.flatMap((pageList) => pageList);
} catch (error: any) {
if (error?.response?.status === 403) {
console.log(
"Canvas API error: 403 Forbidden for pages. Returning empty array."
);
return [];
}
throw error;
}
}, },
async create( async create(

View File

@@ -13,7 +13,6 @@ import { CanvasQuizQuestion } from "@/models/canvas/quizzes/canvasQuizQuestionMo
import { LocalCourseSettings } from "@/models/local/localCourseSettings"; import { LocalCourseSettings } from "@/models/local/localCourseSettings";
import { escapeMatchingText } from "../utils/questionHtmlUtils"; import { escapeMatchingText } from "../utils/questionHtmlUtils";
export const getAnswers = ( export const getAnswers = (
question: LocalQuizQuestion, question: LocalQuizQuestion,
settings: LocalCourseSettings settings: LocalCourseSettings
@@ -138,23 +137,27 @@ const createQuizQuestions = async (
export const canvasQuizService = { export const canvasQuizService = {
async getAll(canvasCourseId: number): Promise<CanvasQuiz[]> { async getAll(canvasCourseId: number): Promise<CanvasQuiz[]> {
try {
const url = `${canvasApi}/courses/${canvasCourseId}/quizzes`; const url = `${canvasApi}/courses/${canvasCourseId}/quizzes`;
const quizzes = await paginatedRequest<CanvasQuiz[]>({ url }); const quizzes = await paginatedRequest<CanvasQuiz[]>({ url });
return quizzes.map((quiz) => ({ return quizzes.map((quiz) => ({
...quiz, ...quiz,
due_at: quiz.due_at ? new Date(quiz.due_at).toLocaleString() : undefined, due_at: quiz.due_at
? new Date(quiz.due_at).toLocaleString()
: undefined,
lock_at: quiz.lock_at lock_at: quiz.lock_at
? new Date(quiz.lock_at).toLocaleString() ? new Date(quiz.lock_at).toLocaleString()
: undefined, : undefined,
})); }));
// const response = await axiosClient.get<CanvasQuiz[]>(url); } catch (error: any) {
// return response.data.map((quiz) => ({ if (error?.response?.status === 403) {
// ...quiz, console.log(
// due_at: quiz.due_at ? new Date(quiz.due_at).toLocaleString() : undefined, "Canvas API error: 403 Forbidden for quizzes. Returning empty array."
// lock_at: quiz.lock_at );
// ? new Date(quiz.lock_at).toLocaleString() return [];
// : undefined, }
// })); throw error;
}
}, },
async create( async create(