mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-25 15:18:32 -06:00
(wip) fix earlier breaking change (feedback in quizzes) by allowing custom feedback delims so that - doesn't need to conflict with markdown list item
This commit is contained in:
@@ -9,11 +9,15 @@ import {
|
|||||||
CourseItemType,
|
CourseItemType,
|
||||||
typeToFolder,
|
typeToFolder,
|
||||||
} from "@/features/local/course/courseItemTypes";
|
} from "@/features/local/course/courseItemTypes";
|
||||||
import { getCoursePathByName } from "../globalSettings/globalSettingsFileStorageService";
|
import {
|
||||||
|
getCoursePathByName,
|
||||||
|
getGlobalSettings,
|
||||||
|
} from "../globalSettings/globalSettingsFileStorageService";
|
||||||
import {
|
import {
|
||||||
localPageMarkdownUtils,
|
localPageMarkdownUtils,
|
||||||
} from "@/features/local/pages/localCoursePageModels";
|
} from "@/features/local/pages/localCoursePageModels";
|
||||||
import { quizMarkdownUtils } from "../quizzes/models/utils/quizMarkdownUtils";
|
import { quizMarkdownUtils } from "../quizzes/models/utils/quizMarkdownUtils";
|
||||||
|
import { getFeedbackDelimitersFromSettings } from "../globalSettings/globalSettingsUtils";
|
||||||
|
|
||||||
|
|
||||||
const getItemFileNames = async ({
|
const getItemFileNames = async ({
|
||||||
@@ -60,9 +64,12 @@ const getItem = async <T extends CourseItemType>({
|
|||||||
name
|
name
|
||||||
) as CourseItemReturnType<T>;
|
) as CourseItemReturnType<T>;
|
||||||
} else if (type === "Quiz") {
|
} else if (type === "Quiz") {
|
||||||
|
const globalSettings = await getGlobalSettings();
|
||||||
|
const delimiters = getFeedbackDelimitersFromSettings(globalSettings);
|
||||||
return quizMarkdownUtils.parseMarkdown(
|
return quizMarkdownUtils.parseMarkdown(
|
||||||
rawFile,
|
rawFile,
|
||||||
name
|
name,
|
||||||
|
delimiters
|
||||||
) as CourseItemReturnType<T>;
|
) as CourseItemReturnType<T>;
|
||||||
} else if (type === "Page") {
|
} else if (type === "Page") {
|
||||||
return localPageMarkdownUtils.parseMarkdown(
|
return localPageMarkdownUtils.parseMarkdown(
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ export const zodGlobalSettingsCourse = z.object({
|
|||||||
|
|
||||||
export const zodGlobalSettings = z.object({
|
export const zodGlobalSettings = z.object({
|
||||||
courses: z.array(zodGlobalSettingsCourse),
|
courses: z.array(zodGlobalSettingsCourse),
|
||||||
|
options: z.record(z.any()).optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import { describe, it, expect } from "vitest";
|
||||||
|
import { getFeedbackDelimitersFromSettings, overriddenDefaults } from "./globalSettingsUtils";
|
||||||
|
import { defaultFeedbackDelimiters } from "../quizzes/models/utils/quizFeedbackMarkdownUtils";
|
||||||
|
import { GlobalSettings } from "./globalSettingsModels";
|
||||||
|
|
||||||
|
describe("overriddenDefaults", () => {
|
||||||
|
it("uses defaults when overrides are missing", () => {
|
||||||
|
const defaults = { a: 1, b: 2 };
|
||||||
|
const overrides = {};
|
||||||
|
expect(overriddenDefaults(defaults, overrides)).toEqual({ a: 1, b: 2 });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("uses overrides when present", () => {
|
||||||
|
const defaults = { a: 1, b: 2 };
|
||||||
|
const overrides = { a: 3 };
|
||||||
|
expect(overriddenDefaults(defaults, overrides)).toEqual({ a: 3, b: 2 });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("ignores extra keys in overrides", () => {
|
||||||
|
const defaults = { a: 1 };
|
||||||
|
const overrides = { a: 2, c: 3 };
|
||||||
|
expect(overriddenDefaults(defaults, overrides)).toEqual({ a: 2 });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getFeedbackDelimitersFromSettings", () => {
|
||||||
|
it("returns default delimiters if options are missing", () => {
|
||||||
|
const settings: GlobalSettings = {
|
||||||
|
courses: [],
|
||||||
|
};
|
||||||
|
expect(getFeedbackDelimitersFromSettings(settings)).toEqual(
|
||||||
|
defaultFeedbackDelimiters
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns custom delimiters if options are present", () => {
|
||||||
|
const settings: GlobalSettings = {
|
||||||
|
courses: [],
|
||||||
|
options: {
|
||||||
|
feedbackDelims: {
|
||||||
|
neutral: ":|",
|
||||||
|
correct: ":)",
|
||||||
|
incorrect: ":(",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const expected = {
|
||||||
|
correct: ":)",
|
||||||
|
incorrect: ":(",
|
||||||
|
neutral: ":|",
|
||||||
|
};
|
||||||
|
expect(getFeedbackDelimitersFromSettings(settings)).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns mixed delimiters if some options are missing", () => {
|
||||||
|
const settings: GlobalSettings = {
|
||||||
|
courses: [],
|
||||||
|
options: {
|
||||||
|
feedbackDelims: {
|
||||||
|
correct: ":)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const expected = {
|
||||||
|
...defaultFeedbackDelimiters,
|
||||||
|
correct: ":)",
|
||||||
|
};
|
||||||
|
expect(getFeedbackDelimitersFromSettings(settings)).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,5 +1,10 @@
|
|||||||
import { GlobalSettings, zodGlobalSettings } from "./globalSettingsModels";
|
import { GlobalSettings, zodGlobalSettings } from "./globalSettingsModels";
|
||||||
import { parse, stringify } from "yaml";
|
import { parse, stringify } from "yaml";
|
||||||
|
import {
|
||||||
|
FeedbackDelimiters,
|
||||||
|
defaultFeedbackDelimiters,
|
||||||
|
} from "../quizzes/models/utils/quizFeedbackMarkdownUtils";
|
||||||
|
import { string } from "zod";
|
||||||
|
|
||||||
export const globalSettingsToYaml = (settings: GlobalSettings) => {
|
export const globalSettingsToYaml = (settings: GlobalSettings) => {
|
||||||
return stringify(settings);
|
return stringify(settings);
|
||||||
@@ -14,3 +19,22 @@ export const parseGlobalSettingsYaml = (yaml: string): GlobalSettings => {
|
|||||||
throw new Error(`Error parsing global settings, got ${yaml}, ${e}`);
|
throw new Error(`Error parsing global settings, got ${yaml}, ${e}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function overriddenDefaults<T extends object>(
|
||||||
|
defaults: T,
|
||||||
|
overrides: Record<string, any>,
|
||||||
|
): T {
|
||||||
|
return Object.fromEntries(
|
||||||
|
Object.entries(defaults).map(([k, v]) => [k, overrides[k] ?? v])
|
||||||
|
) as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getFeedbackDelimitersFromSettings = (
|
||||||
|
settings: GlobalSettings
|
||||||
|
): FeedbackDelimiters => {
|
||||||
|
return overriddenDefaults(
|
||||||
|
defaultFeedbackDelimiters,
|
||||||
|
settings.options?.feedbackDelims ?? {}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
import { describe, it, expect } from "vitest";
|
||||||
|
import { quizQuestionMarkdownUtils } from "../../quizzes/models/utils/quizQuestionMarkdownUtils";
|
||||||
|
import { FeedbackDelimiters } from "../../quizzes/models/utils/quizFeedbackMarkdownUtils";
|
||||||
|
import { QuestionType } from "../../quizzes/models/localQuizQuestion";
|
||||||
|
|
||||||
|
describe("Custom Feedback Delimiters", () => {
|
||||||
|
const customDelimiters: FeedbackDelimiters = {
|
||||||
|
correct: ":)",
|
||||||
|
incorrect: ":(",
|
||||||
|
neutral: ":|",
|
||||||
|
};
|
||||||
|
|
||||||
|
it("can parse question with custom feedback delimiters", () => {
|
||||||
|
const input = `Points: 1
|
||||||
|
Question text
|
||||||
|
:) Correct feedback
|
||||||
|
:( Incorrect feedback
|
||||||
|
:| Neutral feedback
|
||||||
|
*a) Answer 1
|
||||||
|
b) Answer 2`;
|
||||||
|
|
||||||
|
const question = quizQuestionMarkdownUtils.parseMarkdown(input, 0, customDelimiters);
|
||||||
|
|
||||||
|
expect(question.correctComments).toBe("Correct feedback");
|
||||||
|
expect(question.incorrectComments).toBe("Incorrect feedback");
|
||||||
|
expect(question.neutralComments).toBe("Neutral feedback");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("can serialize question with custom feedback delimiters", () => {
|
||||||
|
const question = {
|
||||||
|
points: 1,
|
||||||
|
text: "Question text",
|
||||||
|
questionType: "multiple_choice_question" as QuestionType,
|
||||||
|
answers: [
|
||||||
|
{ text: "Answer 1", correct: true, weight: 100 },
|
||||||
|
{ text: "Answer 2", correct: false, weight: 0 },
|
||||||
|
],
|
||||||
|
correctComments: "Correct feedback",
|
||||||
|
incorrectComments: "Incorrect feedback",
|
||||||
|
neutralComments: "Neutral feedback",
|
||||||
|
matchDistractors: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const markdown = quizQuestionMarkdownUtils.toMarkdown(question, customDelimiters);
|
||||||
|
|
||||||
|
expect(markdown).toContain(":) Correct feedback");
|
||||||
|
expect(markdown).toContain(":( Incorrect feedback");
|
||||||
|
expect(markdown).toContain(":| Neutral feedback");
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,7 +1,22 @@
|
|||||||
|
export interface FeedbackDelimiters {
|
||||||
|
correct: string;
|
||||||
|
incorrect: string;
|
||||||
|
neutral: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const defaultFeedbackDelimiters: FeedbackDelimiters = {
|
||||||
|
correct: "+",
|
||||||
|
incorrect: "-",
|
||||||
|
neutral: "...",
|
||||||
|
};
|
||||||
|
|
||||||
type feedbackTypeOptions = "correct" | "incorrect" | "neutral" | "none";
|
type feedbackTypeOptions = "correct" | "incorrect" | "neutral" | "none";
|
||||||
|
|
||||||
export const quizFeedbackMarkdownUtils = {
|
export const quizFeedbackMarkdownUtils = {
|
||||||
extractFeedback(lines: string[]): {
|
extractFeedback(
|
||||||
|
lines: string[],
|
||||||
|
delimiters: FeedbackDelimiters = defaultFeedbackDelimiters
|
||||||
|
): {
|
||||||
correctComments?: string;
|
correctComments?: string;
|
||||||
incorrectComments?: string;
|
incorrectComments?: string;
|
||||||
neutralComments?: string;
|
neutralComments?: string;
|
||||||
@@ -15,20 +30,18 @@ export const quizFeedbackMarkdownUtils = {
|
|||||||
|
|
||||||
const otherLines: string[] = [];
|
const otherLines: string[] = [];
|
||||||
|
|
||||||
const feedbackIndicators = {
|
const feedbackIndicators = delimiters;
|
||||||
correct: "+",
|
|
||||||
incorrect: "-",
|
|
||||||
neutral: "...",
|
|
||||||
};
|
|
||||||
|
|
||||||
let currentFeedbackType: feedbackTypeOptions = "none";
|
let currentFeedbackType: feedbackTypeOptions = "none";
|
||||||
|
|
||||||
for (const line of lines.map((l) => l)) {
|
for (const line of lines.map((l) => l)) {
|
||||||
const lineFeedbackType: feedbackTypeOptions = line.startsWith("+")
|
const lineFeedbackType: feedbackTypeOptions = line.startsWith(
|
||||||
|
feedbackIndicators.correct
|
||||||
|
)
|
||||||
? "correct"
|
? "correct"
|
||||||
: line.startsWith("-")
|
: line.startsWith(feedbackIndicators.incorrect)
|
||||||
? "incorrect"
|
? "incorrect"
|
||||||
: line.startsWith("...")
|
: line.startsWith(feedbackIndicators.neutral)
|
||||||
? "neutral"
|
? "neutral"
|
||||||
: "none";
|
: "none";
|
||||||
|
|
||||||
@@ -37,15 +50,12 @@ export const quizFeedbackMarkdownUtils = {
|
|||||||
.replace(feedbackIndicators[currentFeedbackType], "")
|
.replace(feedbackIndicators[currentFeedbackType], "")
|
||||||
.trim();
|
.trim();
|
||||||
comments[currentFeedbackType].push(lineWithoutIndicator);
|
comments[currentFeedbackType].push(lineWithoutIndicator);
|
||||||
|
|
||||||
} else if (lineFeedbackType !== "none") {
|
} else if (lineFeedbackType !== "none") {
|
||||||
|
|
||||||
const lineWithoutIndicator = line
|
const lineWithoutIndicator = line
|
||||||
.replace(feedbackIndicators[lineFeedbackType], "")
|
.replace(feedbackIndicators[lineFeedbackType], "")
|
||||||
.trim();
|
.trim();
|
||||||
currentFeedbackType = lineFeedbackType;
|
currentFeedbackType = lineFeedbackType;
|
||||||
comments[lineFeedbackType].push(lineWithoutIndicator);
|
comments[lineFeedbackType].push(lineWithoutIndicator);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
otherLines.push(line);
|
otherLines.push(line);
|
||||||
}
|
}
|
||||||
@@ -66,17 +76,18 @@ export const quizFeedbackMarkdownUtils = {
|
|||||||
formatFeedback(
|
formatFeedback(
|
||||||
correctComments?: string,
|
correctComments?: string,
|
||||||
incorrectComments?: string,
|
incorrectComments?: string,
|
||||||
neutralComments?: string
|
neutralComments?: string,
|
||||||
|
delimiters: FeedbackDelimiters = defaultFeedbackDelimiters
|
||||||
): string {
|
): string {
|
||||||
let feedbackText = "";
|
let feedbackText = "";
|
||||||
if (correctComments) {
|
if (correctComments) {
|
||||||
feedbackText += `+ ${correctComments}\n`;
|
feedbackText += `${delimiters.correct} ${correctComments}\n`;
|
||||||
}
|
}
|
||||||
if (incorrectComments) {
|
if (incorrectComments) {
|
||||||
feedbackText += `- ${incorrectComments}\n`;
|
feedbackText += `${delimiters.incorrect} ${incorrectComments}\n`;
|
||||||
}
|
}
|
||||||
if (neutralComments) {
|
if (neutralComments) {
|
||||||
feedbackText += `... ${neutralComments}\n`;
|
feedbackText += `${delimiters.neutral} ${neutralComments}\n`;
|
||||||
}
|
}
|
||||||
return feedbackText;
|
return feedbackText;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
} from "@/features/local/utils/timeUtils";
|
} from "@/features/local/utils/timeUtils";
|
||||||
import { LocalQuiz } from "../localQuiz";
|
import { LocalQuiz } from "../localQuiz";
|
||||||
import { quizQuestionMarkdownUtils } from "./quizQuestionMarkdownUtils";
|
import { quizQuestionMarkdownUtils } from "./quizQuestionMarkdownUtils";
|
||||||
|
import { FeedbackDelimiters } from "./quizFeedbackMarkdownUtils";
|
||||||
|
|
||||||
const extractLabelValue = (input: string, label: string): string => {
|
const extractLabelValue = (input: string, label: string): string => {
|
||||||
const pattern = new RegExp(`${label}: (.*?)\n`);
|
const pattern = new RegExp(`${label}: (.*?)\n`);
|
||||||
@@ -103,7 +104,7 @@ const getQuizWithOnlySettings = (settings: string, name: string): LocalQuiz => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const quizMarkdownUtils = {
|
export const quizMarkdownUtils = {
|
||||||
toMarkdown(quiz: LocalQuiz): string {
|
toMarkdown(quiz: LocalQuiz, delimiters?: FeedbackDelimiters): string {
|
||||||
if (!quiz) {
|
if (!quiz) {
|
||||||
throw Error(`quiz was undefined, cannot parse markdown`);
|
throw Error(`quiz was undefined, cannot parse markdown`);
|
||||||
}
|
}
|
||||||
@@ -115,7 +116,7 @@ export const quizMarkdownUtils = {
|
|||||||
throw Error(`quiz ${quiz.name} is probably not a quiz`);
|
throw Error(`quiz ${quiz.name} is probably not a quiz`);
|
||||||
}
|
}
|
||||||
const questionMarkdownArray = quiz.questions.map((q) =>
|
const questionMarkdownArray = quiz.questions.map((q) =>
|
||||||
quizQuestionMarkdownUtils.toMarkdown(q)
|
quizQuestionMarkdownUtils.toMarkdown(q, delimiters)
|
||||||
);
|
);
|
||||||
const questionDelimiter = "\n\n---\n\n";
|
const questionDelimiter = "\n\n---\n\n";
|
||||||
const questionMarkdown = questionMarkdownArray.join(questionDelimiter);
|
const questionMarkdown = questionMarkdownArray.join(questionDelimiter);
|
||||||
@@ -133,7 +134,11 @@ Description: ${quiz.description}
|
|||||||
${questionMarkdown}`;
|
${questionMarkdown}`;
|
||||||
},
|
},
|
||||||
|
|
||||||
parseMarkdown(input: string, name: string): LocalQuiz {
|
parseMarkdown(
|
||||||
|
input: string,
|
||||||
|
name: string,
|
||||||
|
delimiters?: FeedbackDelimiters
|
||||||
|
): LocalQuiz {
|
||||||
const splitInput = input.split("---\n");
|
const splitInput = input.split("---\n");
|
||||||
const settings = splitInput[0];
|
const settings = splitInput[0];
|
||||||
const quizWithoutQuestions = getQuizWithOnlySettings(settings, name);
|
const quizWithoutQuestions = getQuizWithOnlySettings(settings, name);
|
||||||
@@ -141,7 +146,7 @@ ${questionMarkdown}`;
|
|||||||
const rawQuestions = splitInput.slice(1);
|
const rawQuestions = splitInput.slice(1);
|
||||||
const questions = rawQuestions
|
const questions = rawQuestions
|
||||||
.filter((str) => str.trim().length > 0)
|
.filter((str) => str.trim().length > 0)
|
||||||
.map((q, i) => quizQuestionMarkdownUtils.parseMarkdown(q, i));
|
.map((q, i) => quizQuestionMarkdownUtils.parseMarkdown(q, i, delimiters));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...quizWithoutQuestions,
|
...quizWithoutQuestions,
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import { LocalQuizQuestion, QuestionType } from "../localQuizQuestion";
|
import { LocalQuizQuestion, QuestionType } from "../localQuizQuestion";
|
||||||
import { quizFeedbackMarkdownUtils } from "./quizFeedbackMarkdownUtils";
|
import {
|
||||||
|
quizFeedbackMarkdownUtils,
|
||||||
|
FeedbackDelimiters,
|
||||||
|
} from "./quizFeedbackMarkdownUtils";
|
||||||
import { quizQuestionAnswerMarkdownUtils } from "./quizQuestionAnswerMarkdownUtils";
|
import { quizQuestionAnswerMarkdownUtils } from "./quizQuestionAnswerMarkdownUtils";
|
||||||
|
|
||||||
const splitLinesAndPoints = (input: string[]) => {
|
const splitLinesAndPoints = (input: string[]) => {
|
||||||
@@ -58,7 +61,10 @@ const removeQuestionTypeFromDescriptionLines = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const quizQuestionMarkdownUtils = {
|
export const quizQuestionMarkdownUtils = {
|
||||||
toMarkdown(question: LocalQuizQuestion): string {
|
toMarkdown(
|
||||||
|
question: LocalQuizQuestion,
|
||||||
|
delimiters?: FeedbackDelimiters
|
||||||
|
): string {
|
||||||
const answerArray = question.answers.map((a, i) =>
|
const answerArray = question.answers.map((a, i) =>
|
||||||
quizQuestionAnswerMarkdownUtils.getAnswerMarkdown(question, a, i)
|
quizQuestionAnswerMarkdownUtils.getAnswerMarkdown(question, a, i)
|
||||||
);
|
);
|
||||||
@@ -72,7 +78,8 @@ export const quizQuestionMarkdownUtils = {
|
|||||||
const feedbackText = quizFeedbackMarkdownUtils.formatFeedback(
|
const feedbackText = quizFeedbackMarkdownUtils.formatFeedback(
|
||||||
question.correctComments,
|
question.correctComments,
|
||||||
question.incorrectComments,
|
question.incorrectComments,
|
||||||
question.neutralComments
|
question.neutralComments,
|
||||||
|
delimiters
|
||||||
);
|
);
|
||||||
|
|
||||||
const answersText = answerArray.join("\n");
|
const answersText = answerArray.join("\n");
|
||||||
@@ -87,7 +94,11 @@ export const quizQuestionMarkdownUtils = {
|
|||||||
return `Points: ${question.points}\n${question.text}\n${feedbackText}${answersText}${distractorText}${questionTypeIndicator}`;
|
return `Points: ${question.points}\n${question.text}\n${feedbackText}${answersText}${distractorText}${questionTypeIndicator}`;
|
||||||
},
|
},
|
||||||
|
|
||||||
parseMarkdown(input: string, questionIndex: number): LocalQuizQuestion {
|
parseMarkdown(
|
||||||
|
input: string,
|
||||||
|
questionIndex: number,
|
||||||
|
delimiters?: FeedbackDelimiters
|
||||||
|
): LocalQuizQuestion {
|
||||||
const { points, lines } = splitLinesAndPoints(input.trim().split("\n"));
|
const { points, lines } = splitLinesAndPoints(input.trim().split("\n"));
|
||||||
|
|
||||||
const linesWithoutAnswers = getLinesBeforeAnswerLines(lines);
|
const linesWithoutAnswers = getLinesBeforeAnswerLines(lines);
|
||||||
@@ -107,7 +118,10 @@ export const quizQuestionMarkdownUtils = {
|
|||||||
incorrectComments,
|
incorrectComments,
|
||||||
neutralComments,
|
neutralComments,
|
||||||
otherLines: descriptionLines,
|
otherLines: descriptionLines,
|
||||||
} = quizFeedbackMarkdownUtils.extractFeedback(linesWithoutAnswersAndTypes);
|
} = quizFeedbackMarkdownUtils.extractFeedback(
|
||||||
|
linesWithoutAnswersAndTypes,
|
||||||
|
delimiters
|
||||||
|
);
|
||||||
|
|
||||||
const { answers, distractors } = quizQuestionAnswerMarkdownUtils.getAnswers(
|
const { answers, distractors } = quizQuestionAnswerMarkdownUtils.getAnswers(
|
||||||
lines,
|
lines,
|
||||||
|
|||||||
@@ -5,11 +5,15 @@ import {
|
|||||||
LocalQuiz,
|
LocalQuiz,
|
||||||
zodLocalQuiz,
|
zodLocalQuiz,
|
||||||
} from "@/features/local/quizzes/models/localQuiz";
|
} from "@/features/local/quizzes/models/localQuiz";
|
||||||
import { getCoursePathByName } from "../globalSettings/globalSettingsFileStorageService";
|
import {
|
||||||
|
getCoursePathByName,
|
||||||
|
getGlobalSettings,
|
||||||
|
} from "../globalSettings/globalSettingsFileStorageService";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { promises as fs } from "fs";
|
import { promises as fs } from "fs";
|
||||||
import { quizMarkdownUtils } from "./models/utils/quizMarkdownUtils";
|
import { quizMarkdownUtils } from "./models/utils/quizMarkdownUtils";
|
||||||
import { courseItemFileStorageService } from "../course/courseItemFileStorageService";
|
import { courseItemFileStorageService } from "../course/courseItemFileStorageService";
|
||||||
|
import { getFeedbackDelimitersFromSettings } from "../globalSettings/globalSettingsUtils";
|
||||||
|
|
||||||
export const quizRouter = router({
|
export const quizRouter = router({
|
||||||
getQuiz: publicProcedure
|
getQuiz: publicProcedure
|
||||||
@@ -159,7 +163,9 @@ export async function updateQuizFile({
|
|||||||
quizName + ".md"
|
quizName + ".md"
|
||||||
);
|
);
|
||||||
|
|
||||||
const quizMarkdown = quizMarkdownUtils.toMarkdown(quiz);
|
const globalSettings = await getGlobalSettings();
|
||||||
|
const delimiters = getFeedbackDelimitersFromSettings(globalSettings);
|
||||||
|
const quizMarkdown = quizMarkdownUtils.toMarkdown(quiz, delimiters);
|
||||||
console.log(`Saving quiz ${filePath}`);
|
console.log(`Saving quiz ${filePath}`);
|
||||||
await fs.writeFile(filePath, quizMarkdown);
|
await fs.writeFile(filePath, quizMarkdown);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user