mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-25 23:28:33 -06:00
moving to a global config
This commit is contained in:
4
build.sh
4
build.sh
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
MAJOR_VERSION="2"
|
||||
MINOR_VERSION="8"
|
||||
MAJOR_VERSION="3"
|
||||
MINOR_VERSION="0"
|
||||
VERSION="$MAJOR_VERSION.$MINOR_VERSION"
|
||||
|
||||
TAG_FLAG=false
|
||||
|
||||
@@ -15,6 +15,7 @@ services:
|
||||
- NEXT_PUBLIC_ENABLE_FILE_SYNC=true
|
||||
- REDIS_URL=redis://redis:6379
|
||||
volumes:
|
||||
- ./globalSettings.yml:/app/globalSettings.yml
|
||||
- .:/app
|
||||
- ~/projects/faculty/1810/2025-spring-alex/in-person:/app/storage/intro_to_web_old
|
||||
- ~/projects/faculty/1810/2025-fall-alex/modules:/app/storage/intro_to_web
|
||||
|
||||
3
globalSettings.yml
Normal file
3
globalSettings.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
courses:
|
||||
- path: "./intro_to_web_old"
|
||||
name: "Intro to Web (Old)"
|
||||
@@ -3,8 +3,6 @@ import { trpcAppRouter } from "@/services/serverFunctions/router/app";
|
||||
import { fetchRequestHandler } from "@trpc/server/adapters/fetch";
|
||||
|
||||
const handler = async (request: Request) => {
|
||||
|
||||
// await new Promise(r => setTimeout(r, 1000)); // delay for testing
|
||||
return fetchRequestHandler({
|
||||
endpoint: "/api/trpc",
|
||||
req: request,
|
||||
|
||||
14
src/models/local/globalSettings.ts
Normal file
14
src/models/local/globalSettings.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import z from "zod";
|
||||
|
||||
export const zodGlobalSettingsCourse = z.object({
|
||||
path: z.string(),
|
||||
name: z.string(),
|
||||
});
|
||||
|
||||
export const zodGlobalSettings = z.object({
|
||||
courses: z.array(zodGlobalSettingsCourse),
|
||||
});
|
||||
|
||||
|
||||
export type GlobalSettings = z.infer<typeof zodGlobalSettings>;
|
||||
export type GlobalSettingsCourse = z.infer<typeof zodGlobalSettingsCourse>;
|
||||
17
src/models/local/globalSettingsUtils.ts
Normal file
17
src/models/local/globalSettingsUtils.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { GlobalSettings, zodGlobalSettings } from "./globalSettings";
|
||||
import { parse, stringify } from "yaml";
|
||||
|
||||
export const globalSettingsToYaml = (settings: GlobalSettings) => {
|
||||
return stringify(settings);
|
||||
};
|
||||
|
||||
export const parseGlobalSettingsYaml = (yaml: string): GlobalSettings => {
|
||||
const parsed = parse(yaml);
|
||||
try {
|
||||
return zodGlobalSettings.parse(parsed);
|
||||
} catch (e) {
|
||||
console.error("Error parsing global settings YAML:", e);
|
||||
throw new Error(`Error parsing global settings, got ${yaml}, ${e}`);
|
||||
}
|
||||
};
|
||||
|
||||
26
src/models/local/tests/globalSettingsMarkdown.test.ts
Normal file
26
src/models/local/tests/globalSettingsMarkdown.test.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { GlobalSettings } from "../globalSettings";
|
||||
import {
|
||||
globalSettingsToYaml,
|
||||
parseGlobalSettingsYaml,
|
||||
} from "../globalSettingsUtils";
|
||||
|
||||
describe("GlobalSettingsMarkdownTests", () => {
|
||||
it("can parse global settings", () => {
|
||||
const globalSettings: GlobalSettings = {
|
||||
courses: [
|
||||
{
|
||||
path: "./distributed/2025-alex/modules",
|
||||
name: "distributed",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const globalSettingsMarkdown = globalSettingsToYaml(globalSettings);
|
||||
const parsedGlobalSettings = parseGlobalSettingsYaml(
|
||||
globalSettingsMarkdown
|
||||
);
|
||||
|
||||
expect(parsedGlobalSettings).toEqual(globalSettings);
|
||||
});
|
||||
});
|
||||
@@ -4,12 +4,14 @@ import {
|
||||
} from "@/models/local/assignment/localAssignment";
|
||||
import { assignmentMarkdownSerializer } from "@/models/local/assignment/utils/assignmentMarkdownSerializer";
|
||||
import path from "path";
|
||||
import { basePath, directoryOrFileExists } from "./utils/fileSystemUtils";
|
||||
import { directoryOrFileExists } from "./utils/fileSystemUtils";
|
||||
import { promises as fs } from "fs";
|
||||
import { courseItemFileStorageService } from "./courseItemFileStorageService";
|
||||
import { getCoursePathByName } from "./globalSettingsFileStorageService";
|
||||
|
||||
const getAssignmentNames = async (courseName: string, moduleName: string) => {
|
||||
const filePath = path.join(basePath, courseName, moduleName, "assignments");
|
||||
const courseDirectory = await getCoursePathByName(courseName);
|
||||
const filePath = path.join(courseDirectory, moduleName, "assignments");
|
||||
if (!(await directoryOrFileExists(filePath))) {
|
||||
console.log(
|
||||
`Error loading course by name, assignments folder does not exist in ${filePath}`
|
||||
@@ -26,9 +28,9 @@ const getAssignment = async (
|
||||
moduleName: string,
|
||||
assignmentName: string
|
||||
) => {
|
||||
const courseDirectory = await getCoursePathByName(courseName);
|
||||
const filePath = path.join(
|
||||
basePath,
|
||||
courseName,
|
||||
courseDirectory,
|
||||
moduleName,
|
||||
"assignments",
|
||||
assignmentName + ".md"
|
||||
@@ -58,12 +60,12 @@ export const assignmentsFileStorageService = {
|
||||
assignmentName: string;
|
||||
assignment: LocalAssignment;
|
||||
}) {
|
||||
const folder = path.join(basePath, courseName, moduleName, "assignments");
|
||||
const courseDirectory = await getCoursePathByName(courseName);
|
||||
const folder = path.join(courseDirectory, moduleName, "assignments");
|
||||
await fs.mkdir(folder, { recursive: true });
|
||||
|
||||
const filePath = path.join(
|
||||
basePath,
|
||||
courseName,
|
||||
courseDirectory,
|
||||
moduleName,
|
||||
"assignments",
|
||||
assignmentName + ".md"
|
||||
@@ -75,7 +77,7 @@ export const assignmentsFileStorageService = {
|
||||
|
||||
await fs.writeFile(filePath, assignmentMarkdown);
|
||||
},
|
||||
|
||||
|
||||
async delete({
|
||||
courseName,
|
||||
moduleName,
|
||||
@@ -85,9 +87,9 @@ export const assignmentsFileStorageService = {
|
||||
moduleName: string;
|
||||
assignmentName: string;
|
||||
}) {
|
||||
const courseDirectory = await getCoursePathByName(courseName);
|
||||
const filePath = path.join(
|
||||
basePath,
|
||||
courseName,
|
||||
courseDirectory,
|
||||
moduleName,
|
||||
"assignments",
|
||||
assignmentName + ".md"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import path from "path";
|
||||
import { basePath, directoryOrFileExists } from "./utils/fileSystemUtils";
|
||||
import { directoryOrFileExists } from "./utils/fileSystemUtils";
|
||||
import fs from "fs/promises";
|
||||
import {
|
||||
LocalAssignment,
|
||||
@@ -20,14 +20,16 @@ import {
|
||||
CourseItemType,
|
||||
typeToFolder,
|
||||
} from "@/models/local/courseItemTypes";
|
||||
import { getCoursePathByName } from "./globalSettingsFileStorageService";
|
||||
|
||||
const getItemFileNames = async (
|
||||
courseName: string,
|
||||
moduleName: string,
|
||||
type: CourseItemType
|
||||
) => {
|
||||
const courseDirectory = await getCoursePathByName(courseName);
|
||||
const folder = typeToFolder[type];
|
||||
const filePath = path.join(basePath, courseName, moduleName, folder);
|
||||
const filePath = path.join(courseDirectory, moduleName, folder);
|
||||
if (!(await directoryOrFileExists(filePath))) {
|
||||
console.log(
|
||||
`Error loading ${type}, ${folder} folder does not exist in ${filePath}`
|
||||
@@ -45,14 +47,9 @@ const getItem = async <T extends CourseItemType>(
|
||||
name: string,
|
||||
type: T
|
||||
): Promise<CourseItemReturnType<T>> => {
|
||||
const courseDirectory = await getCoursePathByName(courseName);
|
||||
const folder = typeToFolder[type];
|
||||
const filePath = path.join(
|
||||
basePath,
|
||||
courseName,
|
||||
moduleName,
|
||||
folder,
|
||||
name + ".md"
|
||||
);
|
||||
const filePath = path.join(courseDirectory, moduleName, folder, name + ".md");
|
||||
const rawFile = (await fs.readFile(filePath, "utf-8")).replace(/\r\n/g, "\n");
|
||||
if (type === "Assignment") {
|
||||
return localAssignmentMarkdown.parseMarkdown(
|
||||
@@ -61,11 +58,13 @@ const getItem = async <T extends CourseItemType>(
|
||||
) as CourseItemReturnType<T>;
|
||||
} else if (type === "Quiz") {
|
||||
return localQuizMarkdownUtils.parseMarkdown(
|
||||
rawFile, name
|
||||
rawFile,
|
||||
name
|
||||
) as CourseItemReturnType<T>;
|
||||
} else if (type === "Page") {
|
||||
return localPageMarkdownUtils.parseMarkdown(
|
||||
rawFile, name
|
||||
rawFile,
|
||||
name
|
||||
) as CourseItemReturnType<T>;
|
||||
}
|
||||
|
||||
@@ -107,13 +106,13 @@ export const courseItemFileStorageService = {
|
||||
item: LocalAssignment | LocalQuiz | LocalCoursePage;
|
||||
type: CourseItemType;
|
||||
}) {
|
||||
const courseDirectory = await getCoursePathByName(courseName);
|
||||
const typeFolder = typeToFolder[type];
|
||||
const folder = path.join(basePath, courseName, moduleName, typeFolder);
|
||||
const folder = path.join(courseDirectory, moduleName, typeFolder);
|
||||
await fs.mkdir(folder, { recursive: true });
|
||||
|
||||
const filePath = path.join(
|
||||
basePath,
|
||||
courseName,
|
||||
courseDirectory,
|
||||
moduleName,
|
||||
typeFolder,
|
||||
name + ".md"
|
||||
|
||||
@@ -6,6 +6,7 @@ import { quizFileStorageService } from "./quizFileStorageService";
|
||||
import { pageFileStorageService } from "./pageFileStorageService";
|
||||
import { moduleFileStorageService } from "./moduleFileStorageService";
|
||||
import { settingsFileStorageService } from "./settingsFileStorageService";
|
||||
import { getCoursePathByName } from "./globalSettingsFileStorageService";
|
||||
|
||||
export const fileStorageService = {
|
||||
settings: settingsFileStorageService,
|
||||
@@ -42,7 +43,7 @@ export const fileStorageService = {
|
||||
},
|
||||
|
||||
async createCourseFolderForTesting(courseName: string) {
|
||||
const courseDirectory = path.join(basePath, courseName);
|
||||
const courseDirectory = await getCoursePathByName(courseName);
|
||||
|
||||
await fs.mkdir(courseDirectory, { recursive: true });
|
||||
},
|
||||
|
||||
36
src/services/fileStorage/globalSettingsFileStorageService.ts
Normal file
36
src/services/fileStorage/globalSettingsFileStorageService.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { GlobalSettings } from "@/models/local/globalSettings";
|
||||
import { parseGlobalSettingsYaml } from "@/models/local/globalSettingsUtils";
|
||||
import { promises as fs } from "fs";
|
||||
import path from "path";
|
||||
import { basePath } from "./utils/fileSystemUtils";
|
||||
|
||||
const SETTINGS_FILE_PATH =
|
||||
process.env.SETTINGS_FILE_PATH || "./globalSettings.yml";
|
||||
|
||||
export const getGlobalSettings = async (): Promise<GlobalSettings> => {
|
||||
try {
|
||||
await fs.access(SETTINGS_FILE_PATH);
|
||||
} catch (err) {
|
||||
throw new Error(
|
||||
`Global Settings file does not exist at path: ${SETTINGS_FILE_PATH}`
|
||||
);
|
||||
}
|
||||
|
||||
const globalSettingsString = process.env.GLOBAL_SETTINGS
|
||||
? process.env.GLOBAL_SETTINGS
|
||||
: await fs.readFile(SETTINGS_FILE_PATH, "utf-8");
|
||||
const globalSettings = parseGlobalSettingsYaml(globalSettingsString);
|
||||
|
||||
return globalSettings;
|
||||
};
|
||||
|
||||
export const getCoursePathByName = async (courseName: string) => {
|
||||
const globalSettings = await getGlobalSettings();
|
||||
const course = globalSettings.courses.find((c) => c.name === courseName);
|
||||
if (!course) {
|
||||
throw new Error(
|
||||
`Course with name ${courseName} not found in global settings`
|
||||
);
|
||||
}
|
||||
return path.join(basePath, course.path);
|
||||
};
|
||||
@@ -1,6 +1,5 @@
|
||||
|
||||
import path from "path";
|
||||
import { basePath } from "./utils/fileSystemUtils";
|
||||
import fs from "fs/promises";
|
||||
import {
|
||||
getLectureWeekName,
|
||||
@@ -14,9 +13,11 @@ import {
|
||||
LocalCourseSettings,
|
||||
} from "@/models/local/localCourseSettings";
|
||||
import { getDateFromStringOrThrow } from "@/models/local/utils/timeUtils";
|
||||
import { getCoursePathByName } from "./globalSettingsFileStorageService";
|
||||
|
||||
export async function getLectures(courseName: string) {
|
||||
const courseLectureRoot = path.join(basePath, courseName, lectureFolderName);
|
||||
const courseDirectory = await getCoursePathByName(courseName);
|
||||
const courseLectureRoot = path.join(courseDirectory, lectureFolderName);
|
||||
if (!(await directoryExists(courseLectureRoot))) {
|
||||
return [];
|
||||
}
|
||||
@@ -53,7 +54,8 @@ export async function updateLecture(
|
||||
courseSettings: LocalCourseSettings,
|
||||
lecture: Lecture
|
||||
) {
|
||||
const courseLectureRoot = path.join(basePath, courseName, lectureFolderName);
|
||||
const courseDirectory = await getCoursePathByName(courseName);
|
||||
const courseLectureRoot = path.join(courseDirectory, lectureFolderName);
|
||||
const lectureDate = getDateFromStringOrThrow(
|
||||
lecture.date,
|
||||
"lecture start date in update lecture"
|
||||
@@ -92,7 +94,8 @@ export async function deleteLecture(
|
||||
dayAsString
|
||||
);
|
||||
|
||||
const courseLectureRoot = path.join(basePath, courseName, lectureFolderName);
|
||||
const courseDirectory = await getCoursePathByName(courseName);
|
||||
const courseLectureRoot = path.join(courseDirectory, lectureFolderName);
|
||||
const weekPath = path.join(courseLectureRoot, weekFolderName);
|
||||
const lecturePath = path.join(
|
||||
weekPath,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { promises as fs } from "fs";
|
||||
import path from "path";
|
||||
import { basePath } from "./utils/fileSystemUtils";
|
||||
import { lectureFolderName } from "./utils/lectureUtils";
|
||||
import { getCoursePathByName } from "./globalSettingsFileStorageService";
|
||||
|
||||
export const moduleFileStorageService = {
|
||||
async getModuleNames(courseName: string) {
|
||||
const courseDirectory = path.join(basePath, courseName);
|
||||
const courseDirectory = await getCoursePathByName(courseName);
|
||||
const moduleDirectories = await fs.readdir(courseDirectory, {
|
||||
withFileTypes: true,
|
||||
});
|
||||
@@ -21,7 +21,7 @@ export const moduleFileStorageService = {
|
||||
return modulesWithoutLectures.sort((a, b) => a.localeCompare(b));
|
||||
},
|
||||
async createModule(courseName: string, moduleName: string) {
|
||||
const courseDirectory = path.join(basePath, courseName);
|
||||
const courseDirectory = await getCoursePathByName(courseName);
|
||||
|
||||
await fs.mkdir(courseDirectory + "/" + moduleName, { recursive: true });
|
||||
},
|
||||
|
||||
@@ -4,8 +4,8 @@ import {
|
||||
} from "@/models/local/page/localCoursePage";
|
||||
import { promises as fs } from "fs";
|
||||
import path from "path";
|
||||
import { basePath } from "./utils/fileSystemUtils";
|
||||
import { courseItemFileStorageService } from "./courseItemFileStorageService";
|
||||
import { getCoursePathByName } from "./globalSettingsFileStorageService";
|
||||
|
||||
export const pageFileStorageService = {
|
||||
getPage: async (courseName: string, moduleName: string, name: string) =>
|
||||
@@ -29,12 +29,12 @@ export const pageFileStorageService = {
|
||||
pageName: string;
|
||||
page: LocalCoursePage;
|
||||
}) {
|
||||
const folder = path.join(basePath, courseName, moduleName, "pages");
|
||||
const courseDirectory = await getCoursePathByName(courseName);
|
||||
const folder = path.join(courseDirectory, moduleName, "pages");
|
||||
await fs.mkdir(folder, { recursive: true });
|
||||
|
||||
const filePath = path.join(
|
||||
basePath,
|
||||
courseName,
|
||||
courseDirectory,
|
||||
moduleName,
|
||||
"pages",
|
||||
pageName + ".md"
|
||||
@@ -53,9 +53,9 @@ export const pageFileStorageService = {
|
||||
moduleName: string;
|
||||
pageName: string;
|
||||
}) {
|
||||
const courseDirectory = await getCoursePathByName(courseName);
|
||||
const filePath = path.join(
|
||||
basePath,
|
||||
courseName,
|
||||
courseDirectory,
|
||||
moduleName,
|
||||
"pages",
|
||||
pageName + ".md"
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { LocalQuiz } from "@/models/local/quiz/localQuiz";
|
||||
import { quizMarkdownUtils } from "@/models/local/quiz/utils/quizMarkdownUtils";
|
||||
import path from "path";
|
||||
import { basePath } from "./utils/fileSystemUtils";
|
||||
import { promises as fs } from "fs";
|
||||
import { courseItemFileStorageService } from "./courseItemFileStorageService";
|
||||
import { getCoursePathByName } from "./globalSettingsFileStorageService";
|
||||
|
||||
export const quizFileStorageService = {
|
||||
getQuiz: async (courseName: string, moduleName: string, quizName: string) =>
|
||||
@@ -27,11 +27,11 @@ export const quizFileStorageService = {
|
||||
quizName: string;
|
||||
quiz: LocalQuiz;
|
||||
}) {
|
||||
const folder = path.join(basePath, courseName, moduleName, "quizzes");
|
||||
const courseDirectory = await getCoursePathByName(courseName);
|
||||
const folder = path.join(courseDirectory, moduleName, "quizzes");
|
||||
await fs.mkdir(folder, { recursive: true });
|
||||
const filePath = path.join(
|
||||
basePath,
|
||||
courseName,
|
||||
courseDirectory,
|
||||
moduleName,
|
||||
"quizzes",
|
||||
quizName + ".md"
|
||||
@@ -50,9 +50,9 @@ export const quizFileStorageService = {
|
||||
moduleName: string;
|
||||
quizName: string;
|
||||
}) {
|
||||
const courseDirectory = await getCoursePathByName(courseName);
|
||||
const filePath = path.join(
|
||||
basePath,
|
||||
courseName,
|
||||
courseDirectory,
|
||||
moduleName,
|
||||
"quizzes",
|
||||
quizName + ".md"
|
||||
|
||||
@@ -4,20 +4,21 @@ import {
|
||||
} from "@/models/local/localCourseSettings";
|
||||
import { promises as fs } from "fs";
|
||||
import path from "path";
|
||||
import {
|
||||
basePath,
|
||||
directoryOrFileExists,
|
||||
getCourseNames,
|
||||
} from "./utils/fileSystemUtils";
|
||||
import { basePath, directoryOrFileExists } from "./utils/fileSystemUtils";
|
||||
import { AssignmentSubmissionType } from "@/models/local/assignment/assignmentSubmissionType";
|
||||
import {
|
||||
getCoursePathByName,
|
||||
getGlobalSettings,
|
||||
} from "./globalSettingsFileStorageService";
|
||||
import { GlobalSettingsCourse } from "@/models/local/globalSettings";
|
||||
|
||||
const getCourseSettings = async (
|
||||
courseName: string
|
||||
course: GlobalSettingsCourse
|
||||
): Promise<LocalCourseSettings> => {
|
||||
const courseDirectory = path.join(basePath, courseName);
|
||||
const courseDirectory = await getCoursePathByName(course.name);
|
||||
const settingsPath = path.join(courseDirectory, "settings.yml");
|
||||
if (!(await directoryOrFileExists(settingsPath))) {
|
||||
const errorMessage = `could not find settings for ${courseName}, settings file ${settingsPath}`;
|
||||
const errorMessage = `could not find settings for ${course.name}, settings file ${settingsPath}`;
|
||||
console.log(errorMessage);
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
@@ -29,8 +30,7 @@ const getCourseSettings = async (
|
||||
|
||||
const settings: LocalCourseSettings = populateDefaultValues(settingsFromFile);
|
||||
|
||||
const folderName = path.basename(courseDirectory);
|
||||
return { ...settings, name: folderName };
|
||||
return { ...settings, name: course.name };
|
||||
};
|
||||
|
||||
const populateDefaultValues = (settingsFromFile: LocalCourseSettings) => {
|
||||
@@ -60,7 +60,10 @@ const populateDefaultValues = (settingsFromFile: LocalCourseSettings) => {
|
||||
export const settingsFileStorageService = {
|
||||
getCourseSettings,
|
||||
async getAllCoursesSettings() {
|
||||
const courses = await getCourseNames();
|
||||
const globalSettings = await getGlobalSettings();
|
||||
|
||||
// const courses = await getCourseNames();
|
||||
const courses = globalSettings.courses;
|
||||
|
||||
const courseSettings = await Promise.all(
|
||||
courses.map(async (c) => await getCourseSettings(c))
|
||||
@@ -72,7 +75,7 @@ export const settingsFileStorageService = {
|
||||
courseName: string,
|
||||
settings: LocalCourseSettings
|
||||
) {
|
||||
const courseDirectory = path.join(basePath, courseName);
|
||||
const courseDirectory = await getCoursePathByName(courseName);
|
||||
const settingsPath = path.join(courseDirectory, "settings.yml");
|
||||
|
||||
const { name: _, ...settingsWithoutName } = settings;
|
||||
|
||||
@@ -1,17 +1,10 @@
|
||||
import { promises as fs } from "fs";
|
||||
import path from "path";
|
||||
import { getGlobalSettings } from "../globalSettingsFileStorageService";
|
||||
|
||||
export const hasFileSystemEntries = async (
|
||||
export const directoryOrFileExists = async (
|
||||
directoryPath: string
|
||||
): Promise<boolean> => {
|
||||
try {
|
||||
const entries = await fs.readdir(directoryPath);
|
||||
return entries.length > 0;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
export const directoryOrFileExists = async (directoryPath: string): Promise<boolean> => {
|
||||
try {
|
||||
await fs.access(directoryPath);
|
||||
return true;
|
||||
@@ -22,31 +15,9 @@ export const directoryOrFileExists = async (directoryPath: string): Promise<bool
|
||||
|
||||
export async function getCourseNames() {
|
||||
console.log("loading course ids");
|
||||
const courseDirectories = await fs.readdir(basePath, {
|
||||
withFileTypes: true,
|
||||
});
|
||||
const coursePromises = await Promise.all(
|
||||
courseDirectories
|
||||
.filter((dirent) => dirent.isDirectory())
|
||||
.map(async (dirent) => {
|
||||
const coursePath = path.join(basePath, dirent.name);
|
||||
const settingsPath = path.join(coursePath, "settings.yml");
|
||||
const hasSettings = await directoryOrFileExists(settingsPath);
|
||||
return {
|
||||
dirent,
|
||||
hasSettings,
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
const courseNamesFromDirectories = coursePromises
|
||||
.filter(({ hasSettings }) => hasSettings)
|
||||
.map(({ dirent }) => dirent.name);
|
||||
|
||||
return courseNamesFromDirectories;
|
||||
const globalSettings = await getGlobalSettings();
|
||||
return globalSettings.courses.map((course) => course.name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
export const basePath = process.env.STORAGE_DIRECTORY ?? "./storage";
|
||||
console.log("base path", basePath);
|
||||
console.log("base path", basePath);
|
||||
|
||||
@@ -10,6 +10,9 @@ describe("FileStorageTests", () => {
|
||||
beforeEach(async () => {
|
||||
const storageDirectory =
|
||||
process.env.STORAGE_DIRECTORY ?? "/tmp/canvasManagerTests";
|
||||
process.env.GLOBAL_SETTINGS = `courses:
|
||||
- path: test empty course
|
||||
name: test empty course`;
|
||||
try {
|
||||
await fs.access(storageDirectory);
|
||||
await fs.rm(storageDirectory, { recursive: true });
|
||||
@@ -31,14 +34,15 @@ describe("FileStorageTests", () => {
|
||||
defaultAssignmentSubmissionTypes: [],
|
||||
defaultFileUploadTypes: [],
|
||||
holidays: [],
|
||||
assets: []
|
||||
assets: [],
|
||||
};
|
||||
|
||||
await fileStorageService.settings.updateCourseSettings(name, settings);
|
||||
|
||||
const loadedSettings = await fileStorageService.settings.getCourseSettings(
|
||||
name
|
||||
);
|
||||
const loadedSettings = await fileStorageService.settings.getCourseSettings({
|
||||
name,
|
||||
path: name,
|
||||
});
|
||||
|
||||
expect(loadedSettings).toEqual(settings);
|
||||
});
|
||||
|
||||
@@ -7,6 +7,9 @@ describe("FileStorageTests", () => {
|
||||
beforeEach(async () => {
|
||||
const storageDirectory =
|
||||
process.env.STORAGE_DIRECTORY ?? "/tmp/canvasManagerTests";
|
||||
process.env.GLOBAL_SETTINGS = `courses:
|
||||
- path: testCourse
|
||||
name: testCourse`;
|
||||
try {
|
||||
await fs.access(storageDirectory);
|
||||
await fs.rm(storageDirectory, { recursive: true });
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import toast, { CheckmarkIcon } from "react-hot-toast";
|
||||
import { ReactNode } from "react";
|
||||
import { getHTTPStatusCodeFromError } from "@trpc/server/http";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
|
||||
// const addErrorAsToast = async (error: unknown) => {
|
||||
// console.error("error from toast", error);
|
||||
@@ -41,6 +43,12 @@ import { ReactNode } from "react";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function getErrorMessage(error: any) {
|
||||
if (error instanceof TRPCError) {
|
||||
const httpCode = getHTTPStatusCodeFromError(error);
|
||||
console.log("trpc error", httpCode, error); // 400
|
||||
return `TRPC Error: ${error.message} (HTTP ${httpCode})`;
|
||||
}
|
||||
|
||||
if (error?.response?.status === 422) {
|
||||
console.log(error.response.data.detail);
|
||||
const serializationMessages = error.response.data.detail.map(
|
||||
@@ -59,7 +67,9 @@ export function getErrorMessage(error: any) {
|
||||
return error.response?.data.detail;
|
||||
} else return JSON.stringify(error.response?.data.detail);
|
||||
}
|
||||
console.log(error);
|
||||
console.log("error message: ", error);
|
||||
if(error.message )
|
||||
return error.message;
|
||||
return "Error With Request";
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user