mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-25 23:28:33 -06:00
pages for editing
This commit is contained in:
@@ -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>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import React, { ReactNode, Suspense } from "react";
|
||||||
|
|
||||||
|
export default function layout({ children }: { children: ReactNode }) {
|
||||||
|
return <Suspense>{children}</Suspense>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { Spinner } from "@/components/Spinner";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export default function Loading() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Spinner />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import React, { ReactNode, Suspense } from "react";
|
||||||
|
|
||||||
|
export default function layout({ children }: { children: ReactNode }) {
|
||||||
|
return <Suspense>{children}</Suspense>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { Spinner } from "@/components/Spinner";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export default function Loading() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Spinner />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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} />;
|
||||||
|
}
|
||||||
@@ -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} />
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import React, { ReactNode, Suspense } from "react";
|
||||||
|
|
||||||
|
export default function layout({ children }: { children: ReactNode }) {
|
||||||
|
return <Suspense>{children}</Suspense>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { Spinner } from "@/components/Spinner";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export default function Loading() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Spinner />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user