pages for editing

This commit is contained in:
2024-09-03 16:45:37 -06:00
parent 3103ab00ae
commit d75ccf3a8c
17 changed files with 303 additions and 12 deletions

View File

@@ -33,6 +33,7 @@ export default function DayItemsInModule({
} }
function Pages({ moduleName, day }: { moduleName: string; day: string }) { function Pages({ moduleName, day }: { moduleName: string; day: string }) {
const { courseName } = useCourseContext();
const { data: pageNames } = usePageNamesQuery(moduleName); const { data: pageNames } = usePageNamesQuery(moduleName);
const { data: pages } = usePagesQueries(moduleName, pageNames); const { data: pages } = usePagesQueries(moduleName, pageNames);
const todaysPages = useMemo( const todaysPages = useMemo(
@@ -72,7 +73,18 @@ function Pages({ moduleName, day }: { moduleName: string; day: string }) {
); );
}} }}
> >
{p.name} <Link
href={
"/course/" +
encodeURIComponent(courseName) +
"/modules/" +
encodeURIComponent(moduleName) +
"/page/" +
encodeURIComponent(p.name)
}
>
{p.name}
</Link>
</li> </li>
))} ))}
</> </>
@@ -82,8 +94,8 @@ function Pages({ moduleName, day }: { moduleName: string; day: string }) {
function Quizzes({ moduleName, day }: { moduleName: string; day: string }) { function Quizzes({ moduleName, day }: { moduleName: string; day: string }) {
const { data: quizNames } = useQuizNamesQuery(moduleName); const { data: quizNames } = useQuizNamesQuery(moduleName);
const { data: quizzes } = useQuizzesQueries(moduleName, quizNames); const { data: quizzes } = useQuizzesQueries(moduleName, quizNames);
const { courseName } = useCourseContext(); const { courseName } = useCourseContext();
const todaysQuizzes = useMemo( const todaysQuizzes = useMemo(
() => () =>
quizzes.filter((q) => { quizzes.filter((q) => {
@@ -142,6 +154,7 @@ function Quizzes({ moduleName, day }: { moduleName: string; day: string }) {
function Assignments({ moduleName, day }: { moduleName: string; day: string }) { function Assignments({ moduleName, day }: { moduleName: string; day: string }) {
const { data: assignmentNames } = useAssignmentNamesQuery(moduleName); const { data: assignmentNames } = useAssignmentNamesQuery(moduleName);
const { courseName } = useCourseContext();
const { data: assignments } = useAssignmentsQueries( const { data: assignments } = useAssignmentsQueries(
moduleName, moduleName,
assignmentNames assignmentNames
@@ -183,7 +196,18 @@ function Assignments({ moduleName, day }: { moduleName: string; day: string }) {
); );
}} }}
> >
{a.name} <Link
href={
"/course/" +
encodeURIComponent(courseName) +
"/modules/" +
encodeURIComponent(moduleName) +
"/assignment/" +
encodeURIComponent(a.name)
}
>
{a.name}
</Link>
</li> </li>
))} ))}
</> </>

View File

@@ -0,0 +1,58 @@
import { LocalAssignment } from "@/models/local/assignment/localAssignment";
import { markdownToHTMLSafe } from "@/services/htmlMarkdownUtils";
import React from "react";
export default function AssignmentPreview({
assignment,
}: {
assignment: LocalAssignment;
}) {
return (
<div>
<section>
<div className="flex">
<div className="flex-1 text-end pe-3">Due Date</div>
<div className="flex-1">{assignment.dueAt}</div>
</div>
<div className="flex">
<div className="flex-1 text-end pe-3">Lock Date</div>
<div className="flex-1">{assignment.lockAt}</div>
</div>
<div className="flex">
<div className="flex-1 text-end pe-3">Assignment Group Name</div>
<div className="flex-1">{assignment.localAssignmentGroupName}</div>
</div>
<div className="flex">
<div className="flex-1 text-end pe-3">Submission Types</div>
<div className="flex-1">
<ul className="">
{assignment.submissionTypes.map((t) => (
<li key={t}>{t}</li>
))}
</ul>
</div>
</div>
<div className="flex">
<div className="flex-1 text-end pe-3">File Upload Types</div>
<div className="flex-1">
<ul className="">
{assignment.allowedFileUploadExtensions.map((t) => (
<li key={t}>{t}</li>
))}
</ul>
</div>
</div>
</section>
<br />
<hr />
<br />
<section>
<div
dangerouslySetInnerHTML={{
__html: markdownToHTMLSafe(assignment.description),
}}
></div>
</section>
</div>
);
}

View File

@@ -0,0 +1,39 @@
"use client";
import { MonacoEditor } from "@/components/editor/MonacoEditor";
import { useAssignmentQuery } from "@/hooks/localCourse/assignmentHooks";
import { localAssignmentMarkdown } from "@/models/local/assignment/localAssignment";
import { useState } from "react";
import AssignmentPreview from "./AssignmentPreview";
export default function EditAssignment({
moduleName,
assignmentName,
}: {
assignmentName: string;
moduleName: string;
}) {
const { data: assignment } = useAssignmentQuery(moduleName, assignmentName);
const [assignmentText, setAssignmentText] = useState(
localAssignmentMarkdown.toMarkdown(assignment)
);
const [error, setError] = useState("");
return (
<div className="h-full flex flex-col">
<div className="columns-2 min-h-0 flex-1">
<div className="flex-1 h-full">
<MonacoEditor value={assignmentText} onChange={setAssignmentText} />
</div>
<div className="h-full">
<div className="text-red-300">{error && error}</div>
<AssignmentPreview assignment={assignment} />
</div>
</div>
<div className="p-5">
<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Add to canvas....
</button>
</div>
</div>
);
}

View File

@@ -0,0 +1,5 @@
import React, { ReactNode, Suspense } from "react";
export default function layout({ children }: { children: ReactNode }) {
return <Suspense>{children}</Suspense>;
}

View File

@@ -0,0 +1,10 @@
import { Spinner } from "@/components/Spinner";
import React from "react";
export default function Loading() {
return (
<div>
<Spinner />
</div>
);
}

View File

@@ -0,0 +1,17 @@
import React from "react";
import EditAssignment from "./EditAssignment";
export default function Page({
params: { moduleName, assignmentName },
}: {
params: { assignmentName: string; moduleName: string };
}) {
const decodedAssignmentName = decodeURIComponent(assignmentName);
const decodedModuleName = decodeURIComponent(moduleName);
return (
<EditAssignment
assignmentName={decodedAssignmentName}
moduleName={decodedModuleName}
/>
);
}

View File

@@ -0,0 +1,40 @@
"use client";
import { MonacoEditor } from "@/components/editor/MonacoEditor";
import { usePageQuery } from "@/hooks/localCourse/pageHooks";
import { localPageMarkdownUtils } from "@/models/local/page/localCoursePage";
import { useState } from "react";
import PagePreview from "./PagePreview";
export default function EditPage({
moduleName,
pageName,
}: {
pageName: string;
moduleName: string;
}) {
const { data: page } = usePageQuery(moduleName, pageName);
const [pageText, setPageText] = useState(
localPageMarkdownUtils.toMarkdown(page)
);
const [error, setError] = useState("");
return (
<div className="h-full flex flex-col">
<div className="columns-2 min-h-0 flex-1">
<div className="flex-1 h-full">
<MonacoEditor value={pageText} onChange={setPageText} />
</div>
<div className="h-full">
<div className="text-red-300">{error && error}</div>
<PagePreview page={page} />
</div>
</div>
<div className="p-5">
<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Add to canvas....
</button>
</div>
</div>
);
}

View File

@@ -0,0 +1,13 @@
import { LocalCoursePage } from "@/models/local/page/localCoursePage";
import { markdownToHTMLSafe } from "@/services/htmlMarkdownUtils";
import React from "react";
export default function PagePreview({ page }: { page: LocalCoursePage }) {
return (
<div
dangerouslySetInnerHTML={{
__html: markdownToHTMLSafe(page.text),
}}
></div>
);
}

View File

@@ -0,0 +1,5 @@
import React, { ReactNode, Suspense } from "react";
export default function layout({ children }: { children: ReactNode }) {
return <Suspense>{children}</Suspense>;
}

View File

@@ -0,0 +1,10 @@
import { Spinner } from "@/components/Spinner";
import React from "react";
export default function Loading() {
return (
<div>
<Spinner />
</div>
);
}

View File

@@ -0,0 +1,12 @@
import React from "react";
import EditPage from "./EditPage";
export default async function Page({
params: { moduleName, pageName },
}: {
params: { pageName: string; moduleName: string };
}) {
const decodedPageName = decodeURIComponent(pageName);
const decodedModuleName = decodeURIComponent(moduleName);
return <EditPage pageName={decodedPageName} moduleName={decodedModuleName} />;
}

View File

@@ -47,9 +47,10 @@ export default function EditQuiz({
return ( return (
<div className="h-full flex flex-col"> <div className="h-full flex flex-col">
{quiz.name}
<div className="columns-2 min-h-0 flex-1"> <div className="columns-2 min-h-0 flex-1">
<MonacoEditor value={quizText} onChange={setQuizText} /> <div className="flex-1 h-full">
<MonacoEditor value={quizText} onChange={setQuizText} />
</div>
<div className="h-full"> <div className="h-full">
<div className="text-red-300">{error && error}</div> <div className="text-red-300">{error && error}</div>
<QuizPreview quiz={quiz} /> <QuizPreview quiz={quiz} />

View File

@@ -61,7 +61,6 @@ export default function QuizPreview({ quiz }: { quiz: LocalQuiz }) {
} }
function QuizQuestionPreview({ question }: { question: LocalQuizQuestion }) { function QuizQuestionPreview({ question }: { question: LocalQuizQuestion }) {
console.log(question);
return ( return (
<div className="rounded"> <div className="rounded">
<div>Points: {question.points}</div> <div>Points: {question.points}</div>

View File

@@ -0,0 +1,5 @@
import React, { ReactNode, Suspense } from "react";
export default function layout({ children }: { children: ReactNode }) {
return <Suspense>{children}</Suspense>;
}

View File

@@ -0,0 +1,10 @@
import { Spinner } from "@/components/Spinner";
import React from "react";
export default function Loading() {
return (
<div>
<Spinner />
</div>
);
}

View File

@@ -2,8 +2,6 @@
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
@layer utilities { @layer utilities {
.text-balance { .text-balance {
text-wrap: balance; text-wrap: balance;
@@ -11,6 +9,48 @@
} }
/* monaco editor */ /* monaco editor */
.monaco-editor-background, .monaco-editor .margin { .monaco-editor-background,
background-color: black !important; .monaco-editor .margin {
} background-color: black !important;
}
h1 {
@apply text-4xl font-bold;
}
h2 {
@apply text-3xl font-semibold;
}
h3 {
@apply text-2xl font-semibold;
}
h4 {
@apply text-xl font-medium;
}
h5 {
@apply text-lg font-medium;
}
h6 {
@apply text-base font-medium;
}
strong {
@apply font-semibold;
}
ul {
list-style-type: disc;
padding-left: 1.5rem; /* list-inside equivalent */
}
ol {
list-style-type: decimal;
padding-left: 1.5rem; /* list-inside equivalent */
}
hr {
@apply border-t border-gray-200 my-4;
}

View File

@@ -1,6 +1,7 @@
import type { Metadata } from "next"; import type { Metadata } from "next";
import "./globals.css"; import "./globals.css";
import Providers from "./providers"; import Providers from "./providers";
import { Suspense } from "react";
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Canvas Manager 2.0", title: "Canvas Manager 2.0",
@@ -14,7 +15,9 @@ export default function RootLayout({
return ( return (
<html lang="en"> <html lang="en">
<body className="bg-slate-900 h-screen p-1 text-slate-300"> <body className="bg-slate-900 h-screen p-1 text-slate-300">
<Providers>{children}</Providers> <Suspense>
<Providers>{children}</Providers>
</Suspense>
</body> </body>
</html> </html>
); );