renaming pages also a thing

This commit is contained in:
2024-12-17 14:49:34 -07:00
parent b020673282
commit 0f1d999e16
7 changed files with 127 additions and 42 deletions

View File

@@ -10,10 +10,10 @@ import PagePreview from "./PagePreview";
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks"; import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
import EditPageButtons from "./EditPageButtons"; import EditPageButtons from "./EditPageButtons";
import ClientOnly from "@/components/ClientOnly"; import ClientOnly from "@/components/ClientOnly";
import { getModuleItemUrl } from "@/services/urlUtils";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext"; import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
import { useAuthoritativeUpdates } from "@/app/course/[courseName]/utils/useAuthoritativeUpdates"; import { useAuthoritativeUpdates } from "@/app/course/[courseName]/utils/useAuthoritativeUpdates";
import EditPageHeader from "./EditPageHeader";
export default function EditPage({ export default function EditPage({
moduleName, moduleName,
@@ -48,33 +48,35 @@ export default function EditPage({
} }
try { try {
const updatedPage = localPageMarkdownUtils.parseMarkdown(text); const updatedPage = localPageMarkdownUtils.parseMarkdown(
text,
pageName
);
if ( if (
localPageMarkdownUtils.toMarkdown(page) !== localPageMarkdownUtils.toMarkdown(page) !==
localPageMarkdownUtils.toMarkdown(updatedPage) localPageMarkdownUtils.toMarkdown(updatedPage)
) { ) {
if (clientIsAuthoritative) { if (clientIsAuthoritative) {
console.log("updating page"); console.log("updating page");
updatePage updatePage.mutateAsync({
.mutateAsync({
page: updatedPage, page: updatedPage,
moduleName, moduleName,
pageName: updatedPage.name, pageName,
previousModuleName: moduleName, previousModuleName: moduleName,
previousPageName: pageName, previousPageName: pageName,
courseName, courseName,
})
.then(() => {
if (updatedPage.name !== pageName)
router.replace(
getModuleItemUrl(
courseName,
moduleName,
"page",
updatedPage.name
)
);
}); });
// .then(() => {
// if (updatedPage.name !== pageName)
// router.replace(
// getModuleItemUrl(
// courseName,
// moduleName,
// "page",
// updatedPage.name
// )
// );
// });
} else { } else {
console.log( console.log(
"client not authoritative, updating client with server page" "client not authoritative, updating client with server page"
@@ -106,6 +108,7 @@ export default function EditPage({
return ( return (
<div className="h-full flex flex-col"> <div className="h-full flex flex-col">
<EditPageHeader pageName={pageName} moduleName={moduleName} />
<div className="columns-2 min-h-0 flex-1"> <div className="columns-2 min-h-0 flex-1">
<div className="flex-1 h-full"> <div className="flex-1 h-full">
<MonacoEditor key={monacoKey} value={text} onChange={textUpdate} /> <MonacoEditor key={monacoKey} value={text} onChange={textUpdate} />

View File

@@ -0,0 +1,27 @@
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
import { getCourseUrl } from "@/services/urlUtils";
import Link from "next/link";
import { UpdatePageName } from "./UpdatePageName";
export default function EditPageHeader({
moduleName,
pageName,
}: {
pageName: 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>
<UpdatePageName pageName={pageName} moduleName={moduleName} />
<div>{pageName}</div>
</div>
);
}

View File

@@ -0,0 +1,68 @@
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 { usePageQuery, useUpdatePageMutation } from "@/hooks/localCourse/pageHooks";
import { getModuleItemUrl } from "@/services/urlUtils";
import { useRouter } from "next/navigation";
import { useState } from "react";
export function UpdatePageName({
moduleName,
pageName,
}: {
pageName: string;
moduleName: string;
}) {
const modal = useModal();
const { courseName } = useCourseContext();
const router = useRouter();
const [page] = usePageQuery(moduleName, pageName);
const updatePage = useUpdatePageMutation();
const [name, setName] = useState(page.name);
const [isLoading, setIsLoading] = useState(false);
return (
<div>
<Modal
modalControl={modal}
buttonText="Rename Page"
buttonClass="py-0"
modalWidth="w-1/5"
>
{({ closeModal }) => (
<form
onSubmit={async (e) => {
e.preventDefault();
if (name === pageName) closeModal();
setIsLoading(true); // page refresh resets flag
await updatePage.mutateAsync({
page: page,
moduleName,
pageName: name,
previousModuleName: moduleName,
previousPageName: pageName,
courseName,
});
// update url (will trigger reload...)
router.replace(
getModuleItemUrl(courseName, moduleName, "page", name),
{}
);
}}
>
<TextInput
value={name}
setValue={setName}
label={"Rename Page"}
/>
<button className="w-full my-3">Save New Name</button>
{isLoading && <Spinner />}
</form>
)}
</Modal>
</div>
);
}

View File

@@ -21,13 +21,12 @@ export const localPageMarkdownUtils = {
page.dueAt, page.dueAt,
"page DueDateForOrdering" "page DueDateForOrdering"
); );
const settingsMarkdown = `Name: ${page.name}\nDueDateForOrdering: ${printableDueDate}\n---\n`; const settingsMarkdown = `DueDateForOrdering: ${printableDueDate}\n---\n`;
return settingsMarkdown + page.text; return settingsMarkdown + page.text;
}, },
parseMarkdown: (pageMarkdown: string) => { parseMarkdown: (pageMarkdown: string, name: string) => {
const rawSettings = pageMarkdown.split("---")[0]; const rawSettings = pageMarkdown.split("---")[0];
const name = extractLabelValue(rawSettings, "Name");
const rawDate = extractLabelValue(rawSettings, "DueDateForOrdering"); const rawDate = extractLabelValue(rawSettings, "DueDateForOrdering");
const dueAt = verifyDateOrThrow(rawDate, "page DueDateForOrdering"); const dueAt = verifyDateOrThrow(rawDate, "page DueDateForOrdering");

View File

@@ -3,15 +3,16 @@ import { LocalCoursePage, localPageMarkdownUtils } from "../page/localCoursePage
describe("PageMarkdownTests", () => { describe("PageMarkdownTests", () => {
it("can parse page", () => { it("can parse page", () => {
const name = "test title"
const page: LocalCoursePage = { const page: LocalCoursePage = {
name: "test title", name,
text: "test text content", text: "test text content",
dueAt: "07/09/2024 23:59:00", dueAt: "07/09/2024 23:59:00",
}; };
const pageMarkdownString = localPageMarkdownUtils.toMarkdown(page); const pageMarkdownString = localPageMarkdownUtils.toMarkdown(page);
const parsedPage = localPageMarkdownUtils.parseMarkdown(pageMarkdownString); const parsedPage = localPageMarkdownUtils.parseMarkdown(pageMarkdownString, name);
expect(parsedPage).toEqual(page); expect(parsedPage).toEqual(page);
}); });

View File

@@ -65,7 +65,7 @@ const getItem = async <T extends CourseItemType>(
) as CourseItemReturnType<T>; ) as CourseItemReturnType<T>;
} else if (type === "Page") { } else if (type === "Page") {
return localPageMarkdownUtils.parseMarkdown( return localPageMarkdownUtils.parseMarkdown(
rawFile rawFile, name
) as CourseItemReturnType<T>; ) as CourseItemReturnType<T>;
} }

View File

@@ -37,25 +37,12 @@ export const pageFileStorageService = {
courseName, courseName,
moduleName, moduleName,
"pages", "pages",
page.name + ".md" pageName + ".md"
); );
const pageMarkdown = localPageMarkdownUtils.toMarkdown(page); const pageMarkdown = localPageMarkdownUtils.toMarkdown(page);
console.log(`Saving page ${filePath}`); console.log(`Saving page ${filePath}`);
await fs.writeFile(filePath, pageMarkdown); await fs.writeFile(filePath, pageMarkdown);
const pageNameIsChanged = pageName !== page.name;
if (pageNameIsChanged) {
console.log("removing old page after name change " + pageName);
const oldFilePath = path.join(
basePath,
courseName,
moduleName,
"pages",
pageName + ".md"
);
await fs.unlink(oldFilePath);
}
}, },
async delete({ async delete({
courseName, courseName,