mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-26 07:38:33 -06:00
passing settings into markdown rendering
This commit is contained in:
@@ -3,6 +3,7 @@ import { CanvasAssignment } from "@/models/canvas/assignments/canvasAssignment";
|
||||
import { CanvasPage } from "@/models/canvas/pages/canvasPageModel";
|
||||
import { CanvasQuiz } from "@/models/canvas/quizzes/canvasQuizModel";
|
||||
import { LocalAssignment } from "@/models/local/assignment/localAssignment";
|
||||
import { LocalCourseSettings } from "@/models/local/localCourseSettings";
|
||||
import { LocalCoursePage } from "@/models/local/page/localCoursePage";
|
||||
import { LocalQuiz } from "@/models/local/quiz/localQuiz";
|
||||
import {
|
||||
@@ -17,10 +18,12 @@ export const getStatus = ({
|
||||
item,
|
||||
canvasItem,
|
||||
type,
|
||||
settings,
|
||||
}: {
|
||||
item: LocalQuiz | LocalAssignment | LocalCoursePage;
|
||||
canvasItem?: CanvasQuiz | CanvasAssignment | CanvasPage;
|
||||
type: "assignment" | "page" | "quiz";
|
||||
settings: LocalCourseSettings;
|
||||
}): {
|
||||
status: "localOnly" | "incomplete" | "published";
|
||||
message: ReactNode;
|
||||
@@ -102,7 +105,7 @@ export const getStatus = ({
|
||||
};
|
||||
|
||||
const htmlIsSame = htmlIsCloseEnough(
|
||||
markdownToHTMLSafe(assignment.description),
|
||||
markdownToHTMLSafe(assignment.description, settings),
|
||||
canvasAssignment.description
|
||||
);
|
||||
if (!htmlIsSame)
|
||||
|
||||
@@ -12,8 +12,10 @@ import {
|
||||
import { ReactNode } from "react";
|
||||
import { useCalendarItemsContext } from "../../context/calendarItemsContext";
|
||||
import { getStatus } from "./getStatus";
|
||||
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
||||
|
||||
export function useTodaysItems(day: string) {
|
||||
const [settings] = useLocalCourseSettingsQuery();
|
||||
const dayAsDate = getDateFromStringOrThrow(
|
||||
day,
|
||||
"calculating same month in day items"
|
||||
@@ -43,6 +45,7 @@ export function useTodaysItems(day: string) {
|
||||
item: assignment,
|
||||
canvasItem: canvasAssignment,
|
||||
type: "assignment",
|
||||
settings,
|
||||
}),
|
||||
};
|
||||
})
|
||||
@@ -65,6 +68,7 @@ export function useTodaysItems(day: string) {
|
||||
item: quiz,
|
||||
canvasItem: canvasQuiz,
|
||||
type: "quiz",
|
||||
settings,
|
||||
}),
|
||||
};
|
||||
})
|
||||
@@ -87,6 +91,7 @@ export function useTodaysItems(day: string) {
|
||||
item: page,
|
||||
canvasItem: canvasPage,
|
||||
type: "page",
|
||||
settings,
|
||||
}),
|
||||
};
|
||||
})
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
||||
import { Lecture } from "@/models/local/lecture";
|
||||
import { markdownToHTMLSafe } from "@/services/htmlMarkdownUtils";
|
||||
|
||||
export default function LecturePreview({ lecture }: { lecture: Lecture }) {
|
||||
const [settings] = useLocalCourseSettingsQuery();
|
||||
return (
|
||||
<>
|
||||
<section className="border-b-slate-700 border-b-4">
|
||||
@@ -12,7 +14,7 @@ export default function LecturePreview({ lecture }: { lecture: Lecture }) {
|
||||
<div
|
||||
className="markdownPreview text-xl"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: markdownToHTMLSafe(lecture.content),
|
||||
__html: markdownToHTMLSafe(lecture.content, settings),
|
||||
}}
|
||||
></div>
|
||||
</section>
|
||||
|
||||
@@ -16,7 +16,6 @@ export default function LecturePreviewPage({
|
||||
const lecture = weeks
|
||||
.flatMap(({ lectures }) => lectures.map((lecture) => lecture))
|
||||
.find((l) => l.date === lectureDay);
|
||||
console.log(lecture);
|
||||
|
||||
if (!lecture) {
|
||||
return <div>lecture not found for day</div>;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
||||
import { LocalAssignment } from "@/models/local/assignment/localAssignment";
|
||||
import { rubricItemIsExtraCredit } from "@/models/local/assignment/rubricItem";
|
||||
import { markdownToHTMLSafe } from "@/services/htmlMarkdownUtils";
|
||||
@@ -8,6 +9,7 @@ export default function AssignmentPreview({
|
||||
}: {
|
||||
assignment: LocalAssignment;
|
||||
}) {
|
||||
const [settings] = useLocalCourseSettingsQuery();
|
||||
const totalPoints = assignment.rubric.reduce(
|
||||
(sum, cur) => (rubricItemIsExtraCredit(cur) ? sum : sum + cur.points),
|
||||
0
|
||||
@@ -59,7 +61,7 @@ export default function AssignmentPreview({
|
||||
<div
|
||||
className="markdownPreview"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: markdownToHTMLSafe(assignment.description),
|
||||
__html: markdownToHTMLSafe(assignment.description, settings),
|
||||
}}
|
||||
></div>
|
||||
</section>
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
||||
import { LocalCoursePage } from "@/models/local/page/localCoursePage";
|
||||
import { markdownToHTMLSafe } from "@/services/htmlMarkdownUtils";
|
||||
import React from "react";
|
||||
|
||||
export default function PagePreview({ page }: { page: LocalCoursePage }) {
|
||||
const [settings] = useLocalCourseSettingsQuery();
|
||||
return (
|
||||
<div
|
||||
className="markdownPreview"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: markdownToHTMLSafe(page.text),
|
||||
__html: markdownToHTMLSafe(page.text, settings),
|
||||
}}
|
||||
></div>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import CheckIcon from "@/components/icons/CheckIcon";
|
||||
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
||||
import { useQuizQuery } from "@/hooks/localCourse/quizHooks";
|
||||
import {
|
||||
LocalQuizQuestion,
|
||||
@@ -14,6 +15,7 @@ export default function QuizPreview({
|
||||
moduleName: string;
|
||||
}) {
|
||||
const [quiz] = useQuizQuery(moduleName, quizName);
|
||||
const [settings] = useLocalCourseSettingsQuery();
|
||||
return (
|
||||
<div style={{ overflow: "scroll", height: "100%" }}>
|
||||
<div className="columns-2">
|
||||
@@ -53,7 +55,7 @@ export default function QuizPreview({
|
||||
<div
|
||||
className="p-3 markdownPreview"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: markdownToHTMLSafe(quiz.description),
|
||||
__html: markdownToHTMLSafe(quiz.description, settings),
|
||||
}}
|
||||
></div>
|
||||
<div className="p-3 rounded-md bg-slate-950 m-5 flex flex-col gap-3">
|
||||
@@ -75,6 +77,7 @@ export default function QuizPreview({
|
||||
}
|
||||
|
||||
function QuizQuestionPreview({ question }: { question: LocalQuizQuestion }) {
|
||||
const [settings] = useLocalCourseSettingsQuery();
|
||||
return (
|
||||
<div className="rounded bg-slate-900 px-2">
|
||||
<div className="flex flex-row justify-between text-slate-400">
|
||||
@@ -86,7 +89,7 @@ function QuizQuestionPreview({ question }: { question: LocalQuizQuestion }) {
|
||||
|
||||
<div
|
||||
className="ms-4 mb-2 markdownPreview"
|
||||
dangerouslySetInnerHTML={{ __html: markdownToHTMLSafe(question.text) }}
|
||||
dangerouslySetInnerHTML={{ __html: markdownToHTMLSafe(question.text, settings) }}
|
||||
></div>
|
||||
{question.questionType === QuestionType.MATCHING && (
|
||||
<div>
|
||||
@@ -128,7 +131,7 @@ function QuizQuestionPreview({ question }: { question: LocalQuizQuestion }) {
|
||||
<div
|
||||
className="markdownQuizAnswerPreview"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: markdownToHTMLSafe(answer.text),
|
||||
__html: markdownToHTMLSafe(answer.text, settings),
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -104,6 +104,7 @@ export default function NewCourseForm() {
|
||||
return { ...groupWithoutCanvas, canvasId: undefined };
|
||||
}
|
||||
),
|
||||
assets: [],
|
||||
}
|
||||
: {
|
||||
name: selectedDirectory,
|
||||
@@ -120,6 +121,7 @@ export default function NewCourseForm() {
|
||||
defaultFileUploadTypes: ["pdf", "png", "jpg", "jpeg"],
|
||||
defaultLockHoursOffset: 0,
|
||||
holidays: [],
|
||||
assets: [],
|
||||
};
|
||||
await createCourse.mutateAsync({
|
||||
settings: newSettings,
|
||||
|
||||
@@ -22,6 +22,7 @@ export const useCanvasAssignmentsQuery = () => {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
export const useAddAssignmentToCanvasMutation = () => {
|
||||
const [settings] = useLocalCourseSettingsQuery();
|
||||
const { data: canvasModules } = useCanvasModulesQuery();
|
||||
@@ -44,9 +45,11 @@ export const useAddAssignmentToCanvasMutation = () => {
|
||||
const assignmentGroup = settings.assignmentGroups.find(
|
||||
(g) => g.name === assignment.localAssignmentGroupName
|
||||
);
|
||||
|
||||
const canvasAssignmentId = await canvasAssignmentService.create(
|
||||
settings.canvasId,
|
||||
assignment,
|
||||
settings,
|
||||
assignmentGroup?.canvasId
|
||||
);
|
||||
const canvasModule = canvasModules.find((c) => c.name === moduleName);
|
||||
@@ -89,6 +92,7 @@ export const useUpdateAssignmentInCanvasMutation = () => {
|
||||
settings.canvasId,
|
||||
canvasAssignmentId,
|
||||
assignment,
|
||||
settings,
|
||||
assignmentGroup?.canvasId
|
||||
);
|
||||
},
|
||||
|
||||
@@ -44,7 +44,7 @@ export const useCreateCanvasPageMutation = () => {
|
||||
}
|
||||
const canvasPage = await canvasPageService.create(
|
||||
settings.canvasId,
|
||||
page
|
||||
page,settings
|
||||
);
|
||||
|
||||
const canvasModule = canvasModules.find((c) => c.name === moduleName);
|
||||
@@ -78,7 +78,7 @@ export const useUpdateCanvasPageMutation = () => {
|
||||
}: {
|
||||
page: LocalCoursePage;
|
||||
canvasPageId: number;
|
||||
}) => canvasPageService.update(settings.canvasId, canvasPageId, page),
|
||||
}) => canvasPageService.update(settings.canvasId, canvasPageId, page, settings),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: canvasPageKeys.pagesInCourse(settings.canvasId),
|
||||
|
||||
@@ -50,6 +50,7 @@ export const useAddQuizToCanvasMutation = () => {
|
||||
const canvasQuizId = await canvasQuizService.create(
|
||||
settings.canvasId,
|
||||
quiz,
|
||||
settings,
|
||||
assignmentGroup?.canvasId
|
||||
);
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
LocalAssignmentGroup,
|
||||
zodLocalAssignmentGroup,
|
||||
} from "./assignment/localAssignmentGroup";
|
||||
import { LocalModule } from "./localModules";
|
||||
import { parse, stringify } from "yaml";
|
||||
|
||||
// export interface LocalCourse {
|
||||
@@ -59,6 +58,10 @@ export interface LocalCourseSettings {
|
||||
name: string;
|
||||
days: string[];
|
||||
}[];
|
||||
assets: {
|
||||
sourceUrl: string;
|
||||
canvasUrl: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
export const zodLocalCourseSettings = z.object({
|
||||
@@ -78,6 +81,12 @@ export const zodLocalCourseSettings = z.object({
|
||||
days: z.string().array(),
|
||||
})
|
||||
.array(),
|
||||
assets: z
|
||||
.object({
|
||||
sourceUrl: z.string(),
|
||||
canvasUrl: z.string(),
|
||||
})
|
||||
.array(),
|
||||
});
|
||||
|
||||
export function getDayOfWeek(date: Date): DayOfWeek {
|
||||
|
||||
@@ -7,6 +7,7 @@ import { CanvasRubricCreationResponse } from "@/models/canvas/assignments/canvas
|
||||
import { assignmentPoints } from "@/models/local/assignment/utils/assignmentPointsUtils";
|
||||
import { getDateFromString } from "@/models/local/utils/timeUtils";
|
||||
import { getRubricCriterion } from "./canvasRubricUtils";
|
||||
import { LocalCourseSettings } from "@/models/local/localCourseSettings";
|
||||
|
||||
export const canvasAssignmentService = {
|
||||
async getAll(courseId: number): Promise<CanvasAssignment[]> {
|
||||
@@ -23,6 +24,7 @@ export const canvasAssignmentService = {
|
||||
async create(
|
||||
canvasCourseId: number,
|
||||
localAssignment: LocalAssignment,
|
||||
settings: LocalCourseSettings,
|
||||
canvasAssignmentGroupId?: number
|
||||
) {
|
||||
console.log(`Creating assignment: ${localAssignment.name}`);
|
||||
@@ -36,7 +38,7 @@ export const canvasAssignmentService = {
|
||||
allowed_extensions: localAssignment.allowedFileUploadExtensions.map(
|
||||
(e) => e.toString()
|
||||
),
|
||||
description: markdownToHTMLSafe(localAssignment.description),
|
||||
description: markdownToHTMLSafe(localAssignment.description, settings),
|
||||
due_at: getDateFromString(localAssignment.dueAt)?.toISOString(),
|
||||
lock_at:
|
||||
localAssignment.lockAt &&
|
||||
@@ -58,6 +60,7 @@ export const canvasAssignmentService = {
|
||||
courseId: number,
|
||||
canvasAssignmentId: number,
|
||||
localAssignment: LocalAssignment,
|
||||
settings: LocalCourseSettings,
|
||||
canvasAssignmentGroupId?: number
|
||||
) {
|
||||
console.log(`Updating assignment: ${localAssignment.name}`);
|
||||
@@ -71,7 +74,7 @@ export const canvasAssignmentService = {
|
||||
allowed_extensions: localAssignment.allowedFileUploadExtensions.map(
|
||||
(e) => e.toString()
|
||||
),
|
||||
description: markdownToHTMLSafe(localAssignment.description),
|
||||
description: markdownToHTMLSafe(localAssignment.description, settings),
|
||||
due_at: getDateFromString(localAssignment.dueAt)?.toISOString(),
|
||||
lock_at:
|
||||
localAssignment.lockAt &&
|
||||
|
||||
@@ -4,6 +4,7 @@ import { canvasApi, paginatedRequest } from "./canvasServiceUtils";
|
||||
import { markdownToHTMLSafe } from "../htmlMarkdownUtils";
|
||||
import { axiosClient } from "../axiosUtils";
|
||||
import { rateLimitAwareDelete } from "./canvasWebRequestor";
|
||||
import { LocalCourseSettings } from "@/models/local/localCourseSettings";
|
||||
|
||||
export const canvasPageService = {
|
||||
async getAll(courseId: number): Promise<CanvasPage[]> {
|
||||
@@ -17,14 +18,15 @@ export const canvasPageService = {
|
||||
|
||||
async create(
|
||||
canvasCourseId: number,
|
||||
page: LocalCoursePage
|
||||
page: LocalCoursePage,
|
||||
settings: LocalCourseSettings
|
||||
): Promise<CanvasPage> {
|
||||
console.log(`Creating course page: ${page.name}`);
|
||||
const url = `${canvasApi}/courses/${canvasCourseId}/pages`;
|
||||
const body = {
|
||||
wiki_page: {
|
||||
title: page.name,
|
||||
body: markdownToHTMLSafe(page.text),
|
||||
body: markdownToHTMLSafe(page.text, settings),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -38,14 +40,15 @@ export const canvasPageService = {
|
||||
async update(
|
||||
courseId: number,
|
||||
canvasPageId: number,
|
||||
page: LocalCoursePage
|
||||
page: LocalCoursePage,
|
||||
settings: LocalCourseSettings
|
||||
): Promise<void> {
|
||||
console.log(`Updating course page: ${page.name}`);
|
||||
const url = `${canvasApi}/courses/${courseId}/pages/${canvasPageId}`;
|
||||
const body = {
|
||||
wiki_page: {
|
||||
title: page.name,
|
||||
body: markdownToHTMLSafe(page.text),
|
||||
body: markdownToHTMLSafe(page.text, settings),
|
||||
},
|
||||
};
|
||||
await axiosClient.put(url, body);
|
||||
|
||||
@@ -10,8 +10,12 @@ import {
|
||||
QuestionType,
|
||||
} from "@/models/local/quiz/localQuizQuestion";
|
||||
import { CanvasQuizQuestion } from "@/models/canvas/quizzes/canvasQuizQuestionModel";
|
||||
import { LocalCourseSettings } from "@/models/local/localCourseSettings";
|
||||
|
||||
const getAnswers = (question: LocalQuizQuestion) => {
|
||||
const getAnswers = (
|
||||
question: LocalQuizQuestion,
|
||||
settings: LocalCourseSettings
|
||||
) => {
|
||||
if (question.questionType === QuestionType.MATCHING)
|
||||
return question.answers.map((a) => ({
|
||||
answer_match_left: a.text,
|
||||
@@ -19,7 +23,7 @@ const getAnswers = (question: LocalQuizQuestion) => {
|
||||
}));
|
||||
|
||||
return question.answers.map((answer) => ({
|
||||
answer_html: markdownToHTMLSafe(answer.text),
|
||||
answer_html: markdownToHTMLSafe(answer.text, settings),
|
||||
answer_weight: answer.correct ? 100 : 0,
|
||||
}));
|
||||
};
|
||||
@@ -28,18 +32,19 @@ const createQuestionOnly = async (
|
||||
canvasCourseId: number,
|
||||
canvasQuizId: number,
|
||||
question: LocalQuizQuestion,
|
||||
position: number
|
||||
position: number,
|
||||
settings: LocalCourseSettings
|
||||
) => {
|
||||
console.log("Creating individual question"); //, question);
|
||||
|
||||
const url = `${canvasApi}/courses/${canvasCourseId}/quizzes/${canvasQuizId}/questions`;
|
||||
const body = {
|
||||
question: {
|
||||
question_text: markdownToHTMLSafe(question.text),
|
||||
question_text: markdownToHTMLSafe(question.text, settings),
|
||||
question_type: `${question.questionType}_question`,
|
||||
points_possible: question.points,
|
||||
position,
|
||||
answers: getAnswers(question),
|
||||
answers: getAnswers(question, settings),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -93,13 +98,20 @@ const hackFixRedundantAssignments = async (canvasCourseId: number) => {
|
||||
const createQuizQuestions = async (
|
||||
canvasCourseId: number,
|
||||
canvasQuizId: number,
|
||||
localQuiz: LocalQuiz
|
||||
localQuiz: LocalQuiz,
|
||||
settings: LocalCourseSettings
|
||||
) => {
|
||||
console.log("Creating quiz questions"); //, localQuiz);
|
||||
|
||||
const tasks = localQuiz.questions.map(
|
||||
async (question, index) =>
|
||||
await createQuestionOnly(canvasCourseId, canvasQuizId, question, index)
|
||||
await createQuestionOnly(
|
||||
canvasCourseId,
|
||||
canvasQuizId,
|
||||
question,
|
||||
index,
|
||||
settings
|
||||
)
|
||||
);
|
||||
const questionAndPositions = await Promise.all(tasks);
|
||||
await hackFixQuestionOrdering(
|
||||
@@ -126,15 +138,17 @@ export const canvasQuizService = {
|
||||
async create(
|
||||
canvasCourseId: number,
|
||||
localQuiz: LocalQuiz,
|
||||
settings: LocalCourseSettings,
|
||||
canvasAssignmentGroupId?: number
|
||||
) {
|
||||
console.log("Creating quiz", localQuiz);
|
||||
|
||||
const url = `${canvasApi}/courses/${canvasCourseId}/quizzes`;
|
||||
|
||||
const body = {
|
||||
quiz: {
|
||||
title: localQuiz.name,
|
||||
description: markdownToHTMLSafe(localQuiz.description),
|
||||
description: markdownToHTMLSafe(localQuiz.description, settings),
|
||||
shuffle_answers: localQuiz.shuffleAnswers,
|
||||
access_code: localQuiz.password,
|
||||
show_correct_answers: localQuiz.showCorrectAnswers,
|
||||
@@ -158,7 +172,7 @@ export const canvasQuizService = {
|
||||
};
|
||||
|
||||
const { data: canvasQuiz } = await axiosClient.post<CanvasQuiz>(url, body);
|
||||
await createQuizQuestions(canvasCourseId, canvasQuiz.id, localQuiz);
|
||||
await createQuizQuestions(canvasCourseId, canvasQuiz.id, localQuiz, settings);
|
||||
return canvasQuiz.id;
|
||||
},
|
||||
async delete(canvasCourseId: number, canvasQuizId: number) {
|
||||
|
||||
@@ -50,6 +50,9 @@ const populateDefaultValues = (settingsFromFile: LocalCourseSettings) => {
|
||||
holidays: Array.isArray(settingsFromFile.holidays)
|
||||
? settingsFromFile.holidays
|
||||
: [],
|
||||
assets: Array.isArray(settingsFromFile.assets)
|
||||
? settingsFromFile.assets
|
||||
: [],
|
||||
};
|
||||
return settings;
|
||||
};
|
||||
|
||||
@@ -1,18 +1,27 @@
|
||||
"use client";
|
||||
import { marked } from "marked";
|
||||
// import markedKatex from "marked-katex-extension";
|
||||
import * as DOMPurify from "isomorphic-dompurify";
|
||||
import { LocalCourseSettings } from "@/models/local/localCourseSettings";
|
||||
|
||||
export function markdownToHTMLSafe(markdownString: string) {
|
||||
// const options = {
|
||||
// throwOnError: false,
|
||||
// nonStandard: true
|
||||
// };
|
||||
|
||||
// marked.use(markedKatex(options));
|
||||
function extractImageSources(html: string) {
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(html, "text/html");
|
||||
const imgElements = doc.querySelectorAll("img");
|
||||
const srcUrls = Array.from(imgElements).map((img) => img.src);
|
||||
return srcUrls;
|
||||
}
|
||||
|
||||
function handleImages(html: string, settings: LocalCourseSettings) {
|
||||
const imageSources = extractImageSources(html);
|
||||
console.log(imageSources);
|
||||
}
|
||||
export function markdownToHTMLSafe(
|
||||
markdownString: string,
|
||||
settings: LocalCourseSettings
|
||||
) {
|
||||
const clean = DOMPurify.sanitize(
|
||||
marked.parse(markdownString, { async: false, pedantic: false, gfm: true })
|
||||
);
|
||||
handleImages(clean, settings);
|
||||
return clean;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ describe("FileStorageTests", () => {
|
||||
defaultAssignmentSubmissionTypes: [],
|
||||
defaultFileUploadTypes: [],
|
||||
holidays: [],
|
||||
assets: []
|
||||
};
|
||||
|
||||
await fileStorageService.settings.updateCourseSettings(name, settings);
|
||||
|
||||
Reference in New Issue
Block a user