mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-26 07:38:33 -06:00
more configs for default types
This commit is contained in:
@@ -30,24 +30,32 @@ function createCalendarMonth(year: number, month: number): CalendarMonthModel {
|
||||
let currentDay = 1;
|
||||
const firstDayOfMonth = new Date(year, month - 1, 1).getDay();
|
||||
|
||||
const daysByWeek = Array.from({ length: weeksNumber }).map((_, weekIndex) =>
|
||||
Array.from({ length: 7 }).map((_, dayIndex) => {
|
||||
if (weekIndex === 0 && dayIndex < firstDayOfMonth) {
|
||||
return dateToMarkdownString(
|
||||
new Date(year, month - 1, dayIndex - firstDayOfMonth + 1, 12, 0, 0)
|
||||
);
|
||||
} else if (currentDay <= daysInMonth) {
|
||||
return dateToMarkdownString(
|
||||
new Date(year, month - 1, currentDay++, 12, 0, 0)
|
||||
);
|
||||
} else {
|
||||
currentDay++;
|
||||
return dateToMarkdownString(
|
||||
new Date(year, month, currentDay - daysInMonth - 1, 12, 0, 0)
|
||||
);
|
||||
}
|
||||
})
|
||||
);
|
||||
const daysByWeek = Array.from({ length: weeksNumber })
|
||||
.map((_, weekIndex) =>
|
||||
Array.from({ length: 7 }).map((_, dayIndex) => {
|
||||
if (weekIndex === 0 && dayIndex < firstDayOfMonth) {
|
||||
return dateToMarkdownString(
|
||||
new Date(year, month - 1, dayIndex - firstDayOfMonth + 1, 12, 0, 0)
|
||||
);
|
||||
} else if (currentDay <= daysInMonth) {
|
||||
return dateToMarkdownString(
|
||||
new Date(year, month - 1, currentDay++, 12, 0, 0)
|
||||
);
|
||||
} else {
|
||||
currentDay++;
|
||||
return dateToMarkdownString(
|
||||
new Date(year, month, currentDay - daysInMonth - 1, 12, 0, 0)
|
||||
);
|
||||
}
|
||||
})
|
||||
)
|
||||
.filter((week) => {
|
||||
const lastDate = getDateFromStringOrThrow(
|
||||
week.at(-1)!,
|
||||
"filtering out last week of month"
|
||||
);
|
||||
return lastDate.getMonth() <= month - 1;
|
||||
});
|
||||
|
||||
const weeks = daysByWeek.map((week) =>
|
||||
week.map((day) =>
|
||||
|
||||
@@ -33,7 +33,6 @@ export default function EditAssignment({
|
||||
const [assignmentText, setAssignmentText] = useState(
|
||||
localAssignmentMarkdown.toMarkdown(assignment)
|
||||
);
|
||||
console.log("assignment text render");
|
||||
|
||||
const [error, setError] = useState("");
|
||||
const [showHelp, setShowHelp] = useState(false);
|
||||
|
||||
@@ -22,6 +22,12 @@ export default function QuizPreview({
|
||||
<div className="text-end">Name</div>
|
||||
<div>{quiz.name}</div>
|
||||
</div>
|
||||
<div className="columns-2">
|
||||
<div className="text-end">Points</div>
|
||||
<div>
|
||||
{quiz.questions.reduce((sum, question) => sum + question.points, 0)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="columns-2">
|
||||
<div className="text-end">Due Date</div>
|
||||
<div>{quiz.dueAt}</div>
|
||||
@@ -46,9 +52,12 @@ export default function QuizPreview({
|
||||
<div className="text-end">Assignment Group Name</div>
|
||||
<div>{quiz.localAssignmentGroupName}</div>
|
||||
</div>
|
||||
<div className="p-3" style={{ whiteSpace: "pre-wrap" }}>
|
||||
{quiz.description}
|
||||
</div>
|
||||
<div
|
||||
className="p-3 markdownPreview"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: markdownToHTMLSafe(quiz.description),
|
||||
}}
|
||||
></div>
|
||||
<div className="p-3 rounded-md bg-slate-950 m-5 flex flex-col gap-3">
|
||||
{quiz.questions.map((question, i) => (
|
||||
<QuizQuestionPreview key={i} question={question} />
|
||||
|
||||
@@ -70,7 +70,7 @@ export default function AssignmentGroupManagement() {
|
||||
<button
|
||||
className="btn-danger"
|
||||
onClick={() => {
|
||||
setAssignmentGroups((oldGroups) => oldGroups.slice(1));
|
||||
setAssignmentGroups((oldGroups) => oldGroups.slice(0, -1));
|
||||
}}
|
||||
>
|
||||
Remove Assignment Group
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
"use client";
|
||||
import TextInput from "@/components/form/TextInput";
|
||||
import {
|
||||
useLocalCourseSettingsQuery,
|
||||
useUpdateLocalCourseSettingsMutation,
|
||||
} from "@/hooks/localCourse/localCoursesHooks";
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
export default function DefaultFileUploadTypes() {
|
||||
const { data: settings } = useLocalCourseSettingsQuery();
|
||||
const [defaultFileUploadTypes, setDefaultFileUploadTypes] = useState<
|
||||
string[]
|
||||
>(settings.defaultFileUploadTypes);
|
||||
const updateSettings = useUpdateLocalCourseSettingsMutation();
|
||||
|
||||
useEffect(() => {
|
||||
const id = setTimeout(() => {
|
||||
if (
|
||||
JSON.stringify(settings.defaultFileUploadTypes) !==
|
||||
JSON.stringify(defaultFileUploadTypes)
|
||||
) {
|
||||
updateSettings.mutate({
|
||||
...settings,
|
||||
defaultFileUploadTypes: defaultFileUploadTypes,
|
||||
});
|
||||
}
|
||||
}, 500);
|
||||
return () => clearTimeout(id);
|
||||
}, [defaultFileUploadTypes, settings, updateSettings]);
|
||||
|
||||
return (
|
||||
<div className="border w-fit p-3 m-3 rounded-md">
|
||||
<div className="text-center">Default File Upload Types</div>
|
||||
|
||||
{defaultFileUploadTypes.map((type, index) => (
|
||||
<div key={index} className="flex flex-row gap-3">
|
||||
<TextInput
|
||||
value={type}
|
||||
setValue={(newValue) =>
|
||||
setDefaultFileUploadTypes((oldTypes) =>
|
||||
oldTypes.map((t, i) => (i === index ? newValue : t))
|
||||
)
|
||||
}
|
||||
label={"Default Type " + index}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
<div className="flex gap-3 mt-3">
|
||||
<button
|
||||
className="btn-danger"
|
||||
onClick={() => {
|
||||
setDefaultFileUploadTypes((old) => old.slice(0, -1));
|
||||
}}
|
||||
>
|
||||
Remove Default File Upload Type
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setDefaultFileUploadTypes((old) => [...old, ""])}
|
||||
>
|
||||
Add Default File Upload Type
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
"use client";
|
||||
import SelectInput from "@/components/form/SelectInput";
|
||||
import {
|
||||
useLocalCourseSettingsQuery,
|
||||
useUpdateLocalCourseSettingsMutation,
|
||||
} from "@/hooks/localCourse/localCoursesHooks";
|
||||
import {
|
||||
AssignmentSubmissionType,
|
||||
AssignmentSubmissionTypeList,
|
||||
} from "@/models/local/assignment/assignmentSubmissionType";
|
||||
import React, { useEffect, useState } from "react";
|
||||
|
||||
export default function SubmissionDefaults() {
|
||||
const { data: settings } = useLocalCourseSettingsQuery();
|
||||
const [defaultSubmissionTypes, setDefaultSubmissionTypes] = useState<
|
||||
AssignmentSubmissionType[]
|
||||
>(settings.defaultAssignmentSubmissionTypes);
|
||||
const updateSettings = useUpdateLocalCourseSettingsMutation();
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
JSON.stringify(settings.defaultAssignmentSubmissionTypes) !==
|
||||
JSON.stringify(defaultSubmissionTypes)
|
||||
) {
|
||||
updateSettings.mutate({
|
||||
...settings,
|
||||
defaultAssignmentSubmissionTypes: defaultSubmissionTypes,
|
||||
});
|
||||
}
|
||||
}, [defaultSubmissionTypes, settings, updateSettings]);
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<div className="border w-fit p-3 m-3 rounded-md">
|
||||
<div className="text-center">Default Assignment Submission Type</div>
|
||||
|
||||
{defaultSubmissionTypes.map((type, index) => (
|
||||
<div key={index} className="flex flex-row gap-3">
|
||||
<SelectInput
|
||||
value={type}
|
||||
setValue={(newType) => {
|
||||
if (newType)
|
||||
setDefaultSubmissionTypes((oldTypes) =>
|
||||
oldTypes.map((t, i) => (i === index ? newType : t))
|
||||
);
|
||||
}}
|
||||
label={""}
|
||||
options={AssignmentSubmissionTypeList}
|
||||
getOptionName={(t) => t}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
<div className="flex gap-3 mt-3">
|
||||
<button
|
||||
className="btn-danger"
|
||||
onClick={() => {
|
||||
setDefaultSubmissionTypes((old) => old.slice(0, -1));
|
||||
}}
|
||||
>
|
||||
Remove Default Type
|
||||
</button>
|
||||
<button
|
||||
onClick={() =>
|
||||
setDefaultSubmissionTypes((old) => [
|
||||
...old,
|
||||
AssignmentSubmissionType.NONE,
|
||||
])
|
||||
}
|
||||
>
|
||||
Add Default Type
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -5,6 +5,8 @@ import SettingsHeader from "./SettingsHeader";
|
||||
import DefaultDueTime from "./DefaultDueTime";
|
||||
import DaysOfWeekSettings from "./DaysOfWeekSettings";
|
||||
import AssignmentGroupManagement from "./AssignmentGroupManagement";
|
||||
import SubmissionDefaults from "./SubmissionDefaults";
|
||||
import DefaultFileUploadTypes from "./DefaultFileUploadTypes";
|
||||
|
||||
export default function page() {
|
||||
return (
|
||||
@@ -13,6 +15,8 @@ export default function page() {
|
||||
<SettingsHeader />
|
||||
<DaysOfWeekSettings />
|
||||
<StartAndEndDate />
|
||||
<SubmissionDefaults />
|
||||
<DefaultFileUploadTypes />
|
||||
<DefaultDueTime />
|
||||
<AssignmentGroupManagement />
|
||||
</div>
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
import { useEmptyDirectoriesQuery } from "@/hooks/localCourse/storageDirectoryHooks";
|
||||
import { CanvasCourseModel } from "@/models/canvas/courses/canvasCourseModel";
|
||||
import { CanvasEnrollmentTermModel } from "@/models/canvas/enrollmentTerms/canvasEnrollmentTermModel";
|
||||
import { AssignmentSubmissionType } from "@/models/local/assignment/assignmentSubmissionType";
|
||||
import { DayOfWeek } from "@/models/local/localCourse";
|
||||
import { getCourseUrl } from "@/services/urlUtils";
|
||||
import { useRouter } from "next/navigation";
|
||||
@@ -89,6 +90,10 @@ export default function NewCourseForm() {
|
||||
startDate: selectedTerm.start_at ?? "",
|
||||
endDate: selectedTerm.end_at ?? "",
|
||||
defaultDueTime: { hour: 23, minute: 59 },
|
||||
defaultAssignmentSubmissionTypes: [
|
||||
AssignmentSubmissionType.ONLINE_TEXT_ENTRY,
|
||||
AssignmentSubmissionType.ONLINE_UPLOAD,
|
||||
],
|
||||
},
|
||||
})
|
||||
.then(() => {
|
||||
|
||||
@@ -17,8 +17,8 @@ export function DayOfWeekInput({
|
||||
key={day}
|
||||
className={
|
||||
hasDay
|
||||
? "bg-blue-300 text-blue-950 border-blue-500 border"
|
||||
: "bg-slate-900 border-blue-900 border "
|
||||
? ""
|
||||
: "unstyled btn-outline "
|
||||
}
|
||||
onClick={() => updateSettings(day)}
|
||||
>
|
||||
|
||||
@@ -6,3 +6,12 @@ export enum AssignmentSubmissionType {
|
||||
ONLINE_URL = "online_url",
|
||||
NONE = "none",
|
||||
}
|
||||
|
||||
export const AssignmentSubmissionTypeList: AssignmentSubmissionType[] = [
|
||||
AssignmentSubmissionType.ONLINE_TEXT_ENTRY,
|
||||
AssignmentSubmissionType.ONLINE_UPLOAD,
|
||||
AssignmentSubmissionType.ONLINE_QUIZ,
|
||||
AssignmentSubmissionType.DISCUSSION_TOPIC,
|
||||
AssignmentSubmissionType.ONLINE_URL,
|
||||
AssignmentSubmissionType.NONE,
|
||||
] as const;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { AssignmentSubmissionType } from "./assignment/assignmentSubmissionType";
|
||||
import { LocalAssignmentGroup } from "./assignment/localAssignmentGroup";
|
||||
import { LocalModule } from "./localModules";
|
||||
import { parse, stringify } from "yaml";
|
||||
@@ -20,6 +21,8 @@ export interface LocalCourseSettings {
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
defaultDueTime: SimpleTimeOnly;
|
||||
defaultAssignmentSubmissionTypes: AssignmentSubmissionType[];
|
||||
defaultFileUploadTypes: string[];
|
||||
}
|
||||
|
||||
export enum DayOfWeek {
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
directoryOrFileExists,
|
||||
getCourseNames,
|
||||
} from "./utils/fileSystemUtils";
|
||||
import { AssignmentSubmissionType } from "@/models/local/assignment/assignmentSubmissionType";
|
||||
|
||||
const getCourseSettings = async (
|
||||
courseName: string
|
||||
@@ -22,7 +23,24 @@ const getCourseSettings = async (
|
||||
}
|
||||
|
||||
const settingsString = await fs.readFile(settingsPath, "utf-8");
|
||||
const settings = localCourseYamlUtils.parseSettingYaml(settingsString);
|
||||
|
||||
const settingsFromFile =
|
||||
localCourseYamlUtils.parseSettingYaml(settingsString);
|
||||
|
||||
const defaultSubmissionType = [
|
||||
AssignmentSubmissionType.ONLINE_TEXT_ENTRY,
|
||||
AssignmentSubmissionType.ONLINE_UPLOAD,
|
||||
];
|
||||
const defaultFileUploadTypes = ["pdf", "jpg", "jpeg", "pdf"];
|
||||
|
||||
const settings: LocalCourseSettings = {
|
||||
...settingsFromFile,
|
||||
defaultAssignmentSubmissionTypes:
|
||||
settingsFromFile.defaultAssignmentSubmissionTypes ||
|
||||
defaultSubmissionType,
|
||||
defaultFileUploadTypes:
|
||||
settingsFromFile.defaultFileUploadTypes || defaultFileUploadTypes,
|
||||
};
|
||||
|
||||
const folderName = path.basename(courseDirectory);
|
||||
return { ...settings, name: folderName };
|
||||
@@ -54,4 +72,3 @@ export const settingsFileStorageService = {
|
||||
await fs.writeFile(settingsPath, settingsMarkdown);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user