This commit is contained in:
Adam Teichert
2026-01-15 13:55:59 -07:00
29 changed files with 473 additions and 196 deletions

View File

@@ -17,6 +17,7 @@ import {
getDateFromStringOrThrow,
} from "@/features/local/utils/timeUtils";
import { useCreateAssignmentMutation } from "@/features/local/assignments/assignmentHooks";
import { validateFileName } from "@/services/fileNameValidation";
export default function NewItemForm({
moduleName: defaultModuleName,
@@ -41,20 +42,6 @@ export default function NewItemForm({
const [name, setName] = useState("");
const [nameError, setNameError] = useState("");
const validateFileName = (fileName: string): string => {
// Check for invalid file system characters
const invalidChars = [":", "/", "\\", "*", '"', "<", ">", "|"];
for (const char of fileName) {
if (invalidChars.includes(char)) {
return `Name contains invalid character: "${char}". Please avoid: ${invalidChars.join(
" "
)}`;
}
}
return "";
};
const handleNameChange = (newName: string) => {
setName(newName);
const error = validateFileName(newName);

View File

@@ -1,7 +1,6 @@
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
import { BreadCrumbs } from "@/components/BreadCrumbs";
import { UpdateAssignmentName } from "./UpdateAssignmentName";
import { getCourseUrl } from "@/services/urlUtils";
import Link from "next/link";
import { RightSingleChevron } from "@/components/icons/RightSingleChevron";
export default function EditAssignmentHeader({
moduleName,
@@ -10,22 +9,21 @@ export default function EditAssignmentHeader({
assignmentName: string;
moduleName: string;
}) {
const { courseName } = useCourseContext();
return (
<div className="py-1 flex flex-row justify-start gap-3">
<Link
className="btn"
href={getCourseUrl(courseName)}
shallow={true}
prefetch={true}
>
{courseName}
</Link>
<UpdateAssignmentName
assignmentName={assignmentName}
moduleName={moduleName}
/>
<div className="my-auto">{assignmentName}</div>
<div className="py-1 flex flex-row justify-between">
<div className="flex flex-row">
<BreadCrumbs />
<span className="text-slate-500 cursor-default select-none my-auto">
<RightSingleChevron />
</span>
<div className="my-auto px-3">{assignmentName}</div>
</div>
<div className="px-1">
<UpdateAssignmentName
assignmentName={assignmentName}
moduleName={moduleName}
/>
</div>
</div>
);
}

View File

@@ -40,8 +40,7 @@ export function UpdateAssignmentName({
if (name === assignmentName) closeModal();
setIsLoading(true); // page refresh resets flag
try{
try {
await updateAssignment.mutateAsync({
assignment: assignment,
moduleName,
@@ -50,17 +49,28 @@ export function UpdateAssignmentName({
previousAssignmentName: assignmentName,
courseName,
});
// update url (will trigger reload...)
router.replace(
getModuleItemUrl(courseName, moduleName, "assignment", name),
{}
);
}finally {
} finally {
setIsLoading(false);
}
}}
>
<div
className="
text-yellow-300
bg-yellow-950/30
border-2
rounded-lg
border-yellow-800
p-1 text-sm mb-2"
>
Warning: does not rename in Canvas
</div>
<TextInput
value={name}
setValue={setName}

View File

@@ -102,13 +102,13 @@ export default function EditPage({
<EditLayout
Header={<EditPageHeader pageName={pageName} moduleName={moduleName} />}
Body={
<div className="columns-2 min-h-0 flex-1">
<div className="flex-1 h-full">
<div className="flex min-h-0 flex-1 gap-4 overflow-hidden">
<div className="flex-1 h-full min-w-0 overflow-hidden">
<MonacoEditor key={monacoKey} value={text} onChange={textUpdate} />
</div>
<div className="h-full">
<div className="flex-1 h-full min-w-0 flex flex-col overflow-hidden">
<div className="text-red-300">{error && error}</div>
<div className="h-full overflow-y-auto">
<div className="flex-1 overflow-y-auto">
<br />
<PagePreview page={page} />
</div>

View File

@@ -1,7 +1,6 @@
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
import { getCourseUrl } from "@/services/urlUtils";
import Link from "next/link";
import { UpdatePageName } from "./UpdatePageName";
import { BreadCrumbs } from "@/components/BreadCrumbs";
import { RightSingleChevron } from "@/components/icons/RightSingleChevron";
export default function EditPageHeader({
moduleName,
@@ -10,19 +9,18 @@ export default function EditPageHeader({
pageName: string;
moduleName: string;
}) {
const { courseName } = useCourseContext();
return (
<div className="py-1 flex flex-row justify-start gap-3">
<Link
className="btn"
href={getCourseUrl(courseName)}
shallow={true}
prefetch={true}
>
{courseName}
</Link>
<UpdatePageName pageName={pageName} moduleName={moduleName} />
<div className="my-auto">{pageName}</div>
<div className="py-1 flex flex-row justify-between">
<div className="flex flex-row">
<BreadCrumbs />
<span className="text-slate-500 cursor-default select-none my-auto">
<RightSingleChevron />
</span>
<div className="my-auto px-3">{pageName}</div>
</div>
<div className="px-1">
<UpdatePageName pageName={pageName} moduleName={moduleName} />
</div>
</div>
);
}

View File

@@ -56,6 +56,17 @@ export function UpdatePageName({
);
}}
>
<div
className="
text-yellow-300
bg-yellow-950/30
border-2
rounded-lg
border-yellow-800
p-1 text-sm mb-2"
>
Warning: does not rename in Canvas
</div>
<TextInput value={name} setValue={setName} label={"Rename Page"} />
<button className="w-full my-3">Save New Name</button>
{isLoading && <Spinner />}

View File

@@ -1,7 +1,6 @@
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
import { getCourseUrl } from "@/services/urlUtils";
import Link from "next/link";
import { RightSingleChevron } from "@/components/icons/RightSingleChevron";
import { UpdateQuizName } from "./UpdateQuizName";
import { BreadCrumbs } from "@/components/BreadCrumbs";
export default function EditQuizHeader({
moduleName,
@@ -10,19 +9,18 @@ export default function EditQuizHeader({
quizName: string;
moduleName: string;
}) {
const { courseName } = useCourseContext();
return (
<div className="py-1 flex flex-row justify-start gap-3">
<Link
className="btn"
href={getCourseUrl(courseName)}
shallow={true}
prefetch={true}
>
{courseName}
</Link>
<UpdateQuizName quizName={quizName} moduleName={moduleName} />
<div>{quizName}</div>
<div className="py-1 flex flex-row justify-between">
<div className="flex flex-row">
<BreadCrumbs />
<span className="text-slate-500 cursor-default select-none my-auto">
<RightSingleChevron />
</span>
<div className="my-auto px-3">{quizName}</div>
</div>
<div className="px-1">
<UpdateQuizName quizName={quizName} moduleName={moduleName} />
</div>
</div>
);
}

View File

@@ -56,6 +56,17 @@ export function UpdateQuizName({
);
}}
>
<div
className="
text-yellow-300
bg-yellow-950/30
border-2
rounded-lg
border-yellow-800
p-1 text-sm mb-2"
>
Warning: does not rename in Canvas
</div>
<TextInput value={name} setValue={setName} label={"Rename Quiz"} />
<button className="w-full my-3">Save New Name</button>
{isLoading && <Spinner />}