assignment renaming is whole process now

This commit is contained in:
2024-12-17 14:35:20 -07:00
parent c557bbcc28
commit 9a8c5bff91
7 changed files with 134 additions and 34 deletions

View File

@@ -18,7 +18,7 @@ import Link from "next/link";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useState } from "react"; import { useState } from "react";
export function AssignmentButtons({ export function AssignmentFooterButtons({
moduleName, moduleName,
assignmentName, assignmentName,
toggleHelp, toggleHelp,
@@ -54,8 +54,6 @@ export function AssignmentButtons({
deleteFromCanvas.isPending || deleteFromCanvas.isPending ||
updateAssignment.isPending; updateAssignment.isPending;
console.log("assignment pending", updateAssignment.isPending);
return ( return (
<div className="p-5 flex flex-row justify-between gap-3"> <div className="p-5 flex flex-row justify-between gap-3">
<div> <div>

View File

@@ -11,7 +11,6 @@ import {
} from "@/models/local/assignment/localAssignment"; } from "@/models/local/assignment/localAssignment";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import AssignmentPreview from "./AssignmentPreview"; import AssignmentPreview from "./AssignmentPreview";
import { getModuleItemUrl } from "@/services/urlUtils";
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext"; import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks"; import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
import ClientOnly from "@/components/ClientOnly"; import ClientOnly from "@/components/ClientOnly";
@@ -19,9 +18,9 @@ import { SuspenseAndErrorHandling } from "@/components/SuspenseAndErrorHandling"
import { AssignmentSubmissionType } from "@/models/local/assignment/assignmentSubmissionType"; import { AssignmentSubmissionType } from "@/models/local/assignment/assignmentSubmissionType";
import { LocalCourseSettings } from "@/models/local/localCourseSettings"; import { LocalCourseSettings } from "@/models/local/localCourseSettings";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { AssignmentButtons } from "./AssignmentButtons"; import { AssignmentFooterButtons } from "./AssignmentFooterButtons";
import { useAuthoritativeUpdates } from "@/app/course/[courseName]/utils/useAuthoritativeUpdates"; import { useAuthoritativeUpdates } from "@/app/course/[courseName]/utils/useAuthoritativeUpdates";
import { extractLabelValue } from "@/models/local/assignment/utils/markdownUtils"; import EditAssignmentHeader from "./EditAssignmentHeader";
export default function EditAssignment({ export default function EditAssignment({
moduleName, moduleName,
@@ -65,39 +64,38 @@ export default function EditAssignment({
return; return;
} }
const name = extractLabelValue(text, "Name"); // make separate way to update name?
const updatedAssignment: LocalAssignment = const updatedAssignment: LocalAssignment =
localAssignmentMarkdown.parseMarkdown(text, name); localAssignmentMarkdown.parseMarkdown(text, assignmentName);
if ( if (
localAssignmentMarkdown.toMarkdown(assignment) !== localAssignmentMarkdown.toMarkdown(assignment) !==
localAssignmentMarkdown.toMarkdown(updatedAssignment) localAssignmentMarkdown.toMarkdown(updatedAssignment)
) { ) {
if (clientIsAuthoritative) { if (clientIsAuthoritative) {
console.log("updating assignment, client is authoritative"); console.log("updating assignment, client is authoritative");
updateAssignment updateAssignment.mutateAsync({
.mutateAsync({ assignment: updatedAssignment,
assignment: updatedAssignment, moduleName,
moduleName, assignmentName,
assignmentName: updatedAssignment.name, previousModuleName: moduleName,
previousModuleName: moduleName, previousAssignmentName: assignmentName,
previousAssignmentName: assignmentName, courseName,
courseName, });
}) // .then(async () => {
.then(async () => { // // await new Promise(resolve => setTimeout(resolve, 1000));
// await new Promise(resolve => setTimeout(resolve, 1000));
if (updatedAssignment.name !== assignmentName) // if (updatedAssignment.name !== assignmentName)
router.replace( // router.replace(
getModuleItemUrl( // getModuleItemUrl(
courseName, // courseName,
moduleName, // moduleName,
"assignment", // "assignment",
updatedAssignment.name // updatedAssignment.name
), { // ), {
} // }
); // );
}); // });
} else { } else {
console.log( console.log(
"client not authoritative, updating client with server assignment", "client not authoritative, updating client with server assignment",
@@ -135,6 +133,10 @@ export default function EditAssignment({
return ( return (
<div className="h-full flex flex-col align-middle px-1"> <div className="h-full flex flex-col align-middle px-1">
<EditAssignmentHeader
moduleName={moduleName}
assignmentName={assignmentName}
/>
<div className={"min-h-0 flex flex-row w-full flex-grow"}> <div className={"min-h-0 flex flex-row w-full flex-grow"}>
{showHelp && ( {showHelp && (
<pre className=" max-w-96"> <pre className=" max-w-96">
@@ -158,7 +160,7 @@ export default function EditAssignment({
</div> </div>
<ClientOnly> <ClientOnly>
<SuspenseAndErrorHandling> <SuspenseAndErrorHandling>
<AssignmentButtons <AssignmentFooterButtons
moduleName={moduleName} moduleName={moduleName}
assignmentName={assignmentName} assignmentName={assignmentName}
toggleHelp={() => setShowHelp((h) => !h)} toggleHelp={() => setShowHelp((h) => !h)}

View File

@@ -0,0 +1,26 @@
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
import { UpdateAssignmentName } from "./UpdateAssignmentName";
import { getCourseUrl } from "@/services/urlUtils";
import Link from "next/link";
export default function EditAssignmentHeader({
moduleName,
assignmentName,
}: {
assignmentName: string;
moduleName: string;
}) {
const { courseName } = useCourseContext();
return (
<div className="py-1 flex flex-row justify-start gap-3">
<Link className="btn btn-thin" href={getCourseUrl(courseName)} shallow={true}>
{courseName}
</Link>
<UpdateAssignmentName
assignmentName={assignmentName}
moduleName={moduleName}
/>
<div>{assignmentName}</div>
</div>
);
}

View File

@@ -0,0 +1,71 @@
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
import TextInput from "@/components/form/TextInput";
import Modal, { useModal } from "@/components/Modal";
import { Spinner } from "@/components/Spinner";
import {
useAssignmentQuery,
useUpdateAssignmentMutation,
} from "@/hooks/localCourse/assignmentHooks";
import { getModuleItemUrl } from "@/services/urlUtils";
import { useRouter } from "next/navigation";
import { useState } from "react";
export function UpdateAssignmentName({
moduleName,
assignmentName,
}: {
assignmentName: string;
moduleName: string;
}) {
const modal = useModal();
const { courseName } = useCourseContext();
const router = useRouter();
const [assignment] = useAssignmentQuery(moduleName, assignmentName);
const updateAssignment = useUpdateAssignmentMutation();
const [name, setName] = useState(assignment.name);
const [isLoading, setIsLoading] = useState(false);
return (
<div>
<Modal
modalControl={modal}
buttonText="Rename Assignment"
buttonClass="py-0"
modalWidth="w-1/5"
>
{({ closeModal }) => (
<form
onSubmit={async (e) => {
e.preventDefault();
if (name === assignmentName) closeModal();
setIsLoading(true); // page refresh resets flag
await updateAssignment.mutateAsync({
assignment: assignment,
moduleName,
assignmentName: name,
previousModuleName: moduleName,
previousAssignmentName: assignmentName,
courseName,
});
// update url (will trigger reload...)
router.replace(
getModuleItemUrl(courseName, moduleName, "assignment", name),
{}
);
}}
>
<TextInput
value={name}
setValue={setName}
label={"Rename Assignment"}
/>
<button className="w-full my-3">Save New Name</button>
{isLoading && <Spinner />}
</form>
)}
</Modal>
</div>
);
}

View File

@@ -87,6 +87,10 @@ button,
@apply font-bold py-1 px-3 rounded transition-all duration-200; @apply font-bold py-1 px-3 rounded transition-all duration-200;
} }
.btn-thin {
@apply py-0;
}
button:not(.unstyled):not(.btn-danger), button:not(.unstyled):not(.btn-danger),
.btn:not(.unstyled):not(.btn-danger) { .btn:not(.unstyled):not(.btn-danger) {
@apply bg-blue-900 hover:bg-blue-700 text-blue-50; @apply bg-blue-900 hover:bg-blue-700 text-blue-50;

View File

@@ -130,7 +130,7 @@ export const assignmentMarkdownParser = {
const rubric = parseRubricMarkdown(rubricString); const rubric = parseRubricMarkdown(rubricString);
const assignment: LocalAssignment = { const assignment: LocalAssignment = {
name: name.trim(), name,
localAssignmentGroupName: assignmentGroupName.trim(), localAssignmentGroupName: assignmentGroupName.trim(),
submissionTypes: submissionTypes, submissionTypes: submissionTypes,
allowedFileUploadExtensions: fileUploadExtensions, allowedFileUploadExtensions: fileUploadExtensions,

View File

@@ -26,7 +26,6 @@ const settingsToMarkdown = (assignment: LocalAssignment) => {
.join("\n"); .join("\n");
const settingsMarkdown = [ const settingsMarkdown = [
`Name: ${assignment.name}`,
`LockAt: ${printableLockAt}`, `LockAt: ${printableLockAt}`,
`DueAt: ${printableDueDate}`, `DueAt: ${printableDueDate}`,
`AssignmentGroupName: ${assignment.localAssignmentGroupName}`, `AssignmentGroupName: ${assignment.localAssignmentGroupName}`,