mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-25 23:28:33 -06:00
added catches around markdown to html, might throw exception if image error
This commit is contained in:
@@ -38,11 +38,9 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}
|
- TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "cloudflared", "--version"]
|
test: [ "CMD", "cloudflared", "--version" ]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 3
|
retries: 3
|
||||||
start_period: 10s
|
start_period: 10s
|
||||||
|
|
||||||
|
|
||||||
# https://ngrok.com/docs/using-ngrok-with/docker/
|
# https://ngrok.com/docs/using-ngrok-with/docker/
|
||||||
|
|||||||
2
run.sh
2
run.sh
@@ -9,9 +9,9 @@ docker run -it --rm \
|
|||||||
-p 3000:3000 \
|
-p 3000:3000 \
|
||||||
-w /app \
|
-w /app \
|
||||||
-v .:/app \
|
-v .:/app \
|
||||||
-v ~/projects/faculty/1810/2024-fall-alex/modules:/app/storage/intro_to_web \
|
|
||||||
-v ~/projects/faculty/4850_AdvancedFE/2024-fall-alex/modules:/app/storage/advanced_frontend \
|
-v ~/projects/faculty/4850_AdvancedFE/2024-fall-alex/modules:/app/storage/advanced_frontend \
|
||||||
-v ~/projects/faculty/1810/2025-spring-alex/online:/app/storage/intro_to_web_online \
|
-v ~/projects/faculty/1810/2025-spring-alex/online:/app/storage/intro_to_web_online \
|
||||||
|
-v ~/projects/faculty/1810/2025-spring-alex/in-person:/app/storage/intro_to_web \
|
||||||
-v ~/projects/faculty/1400/2025_spring_alex/modules:/app/storage/1400 \
|
-v ~/projects/faculty/1400/2025_spring_alex/modules:/app/storage/1400 \
|
||||||
-v ~/projects/faculty/1405/2025_spring_alex:/app/storage/1405 \
|
-v ~/projects/faculty/1405/2025_spring_alex:/app/storage/1405 \
|
||||||
-v ~/projects/faculty/3840_Telemetry/2025_spring_alex/modules:/app/storage/telemetry \
|
-v ~/projects/faculty/3840_Telemetry/2025_spring_alex/modules:/app/storage/telemetry \
|
||||||
|
|||||||
@@ -104,15 +104,22 @@ export const getStatus = ({
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
const htmlIsSame = htmlIsCloseEnough(
|
try {
|
||||||
markdownToHTMLSafe(assignment.description, settings),
|
const htmlIsSame = htmlIsCloseEnough(
|
||||||
canvasAssignment.description
|
markdownToHTMLSafe(assignment.description, settings),
|
||||||
);
|
canvasAssignment.description
|
||||||
if (!htmlIsSame)
|
);
|
||||||
|
if (!htmlIsSame)
|
||||||
|
return {
|
||||||
|
status: "incomplete",
|
||||||
|
message: "Canvas description is different",
|
||||||
|
};
|
||||||
|
} catch (exception) {
|
||||||
return {
|
return {
|
||||||
status: "incomplete",
|
status: "incomplete",
|
||||||
message: "Canvas description is different",
|
message: "Error parsing markdown " + exception,
|
||||||
};
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { status: "published", message: "" };
|
return { status: "published", message: "" };
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import MarkdownDisplay from "@/components/MarkdownDisplay";
|
||||||
|
import { SuspenseAndErrorHandling } from "@/components/SuspenseAndErrorHandling";
|
||||||
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
||||||
import { Lecture } from "@/models/local/lecture";
|
import { Lecture } from "@/models/local/lecture";
|
||||||
import { markdownToHTMLSafe } from "@/services/htmlMarkdownUtils";
|
import { markdownToHTMLSafe } from "@/services/htmlMarkdownUtils";
|
||||||
@@ -8,15 +10,12 @@ export default function LecturePreview({ lecture }: { lecture: Lecture }) {
|
|||||||
<>
|
<>
|
||||||
<section className="border-b-slate-700 border-b-4">
|
<section className="border-b-slate-700 border-b-4">
|
||||||
<div className="text-center font-extrabold">{lecture.name}</div>
|
<div className="text-center font-extrabold">{lecture.name}</div>
|
||||||
<div className="text-center font-bold text-slate-400">{lecture.date}</div>
|
<div className="text-center font-bold text-slate-400">
|
||||||
|
{lecture.date}
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<div
|
<MarkdownDisplay markdown={lecture.content} />
|
||||||
className="markdownPreview "
|
|
||||||
dangerouslySetInnerHTML={{
|
|
||||||
__html: markdownToHTMLSafe(lecture.content, settings),
|
|
||||||
}}
|
|
||||||
></div>
|
|
||||||
</section>
|
</section>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import ClientOnly from "@/components/ClientOnly";
|
import ClientOnly from "@/components/ClientOnly";
|
||||||
|
import MarkdownDisplay from "@/components/MarkdownDisplay";
|
||||||
import { SuspenseAndErrorHandling } from "@/components/SuspenseAndErrorHandling";
|
import { SuspenseAndErrorHandling } from "@/components/SuspenseAndErrorHandling";
|
||||||
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
||||||
import { LocalAssignment } from "@/models/local/assignment/localAssignment";
|
import { LocalAssignment } from "@/models/local/assignment/localAssignment";
|
||||||
@@ -18,7 +19,6 @@ export default function AssignmentPreview({
|
|||||||
(sum, cur) => (rubricItemIsExtraCredit(cur) ? sum + cur.points : sum),
|
(sum, cur) => (rubricItemIsExtraCredit(cur) ? sum + cur.points : sum),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
const htmlPreview = markdownToHTMLSafe(assignment.description, settings);
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full overflow-y-auto">
|
<div className="h-full overflow-y-auto">
|
||||||
<section>
|
<section>
|
||||||
@@ -59,12 +59,13 @@ export default function AssignmentPreview({
|
|||||||
<hr />
|
<hr />
|
||||||
<br />
|
<br />
|
||||||
<section>
|
<section>
|
||||||
<div
|
<MarkdownDisplay markdown={assignment.description} />
|
||||||
|
{/* <div
|
||||||
className="markdownPreview"
|
className="markdownPreview"
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: htmlPreview,
|
__html: htmlPreview,
|
||||||
}}
|
}}
|
||||||
></div>
|
></div> */}
|
||||||
</section>
|
</section>
|
||||||
<hr />
|
<hr />
|
||||||
<section>
|
<section>
|
||||||
|
|||||||
@@ -1,16 +1,11 @@
|
|||||||
|
import MarkdownDisplay from "@/components/MarkdownDisplay";
|
||||||
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
||||||
import { LocalCoursePage } from "@/models/local/page/localCoursePage";
|
import { LocalCoursePage } from "@/models/local/page/localCoursePage";
|
||||||
import { markdownToHTMLSafe } from "@/services/htmlMarkdownUtils";
|
import { markdownToHTMLSafe } from "@/services/htmlMarkdownUtils";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export default function PagePreview({ page }: { page: LocalCoursePage }) {
|
export default function PagePreview({ page }: { page: LocalCoursePage }) {
|
||||||
const [settings] = useLocalCourseSettingsQuery();
|
|
||||||
return (
|
return (
|
||||||
<div
|
<MarkdownDisplay markdown={page.text} />
|
||||||
className="markdownPreview"
|
|
||||||
dangerouslySetInnerHTML={{
|
|
||||||
__html: markdownToHTMLSafe(page.text, settings),
|
|
||||||
}}
|
|
||||||
></div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import CheckIcon from "@/components/icons/CheckIcon";
|
import CheckIcon from "@/components/icons/CheckIcon";
|
||||||
|
import MarkdownDisplay from "@/components/MarkdownDisplay";
|
||||||
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
||||||
import { useQuizQuery } from "@/hooks/localCourse/quizHooks";
|
import { useQuizQuery } from "@/hooks/localCourse/quizHooks";
|
||||||
import {
|
import {
|
||||||
@@ -53,12 +54,7 @@ export default function QuizPreview({
|
|||||||
<div className="text-end">Assignment Group Name</div>
|
<div className="text-end">Assignment Group Name</div>
|
||||||
<div>{quiz.localAssignmentGroupName}</div>
|
<div>{quiz.localAssignmentGroupName}</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<MarkdownDisplay markdown={quiz.description} className="p-3" />
|
||||||
className="p-3 markdownPreview"
|
|
||||||
dangerouslySetInnerHTML={{
|
|
||||||
__html: markdownToHTMLSafe(quiz.description, settings),
|
|
||||||
}}
|
|
||||||
></div>
|
|
||||||
<div className="p-3 rounded-md bg-slate-950 m-5 flex flex-col gap-3">
|
<div className="p-3 rounded-md bg-slate-950 m-5 flex flex-col gap-3">
|
||||||
{quiz.questions.map((question, i) => (
|
{quiz.questions.map((question, i) => (
|
||||||
<QuizQuestionPreview key={i} question={question} />
|
<QuizQuestionPreview key={i} question={question} />
|
||||||
@@ -88,13 +84,7 @@ function QuizQuestionPreview({ question }: { question: LocalQuizQuestion }) {
|
|||||||
{question.points} {question.points === 1 ? " Point" : " Points"}
|
{question.points} {question.points === 1 ? " Point" : " Points"}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<MarkdownDisplay markdown={question.text} className="ms-4 mb-2" />
|
||||||
<div
|
|
||||||
className="ms-4 mb-2 markdownPreview"
|
|
||||||
dangerouslySetInnerHTML={{
|
|
||||||
__html: markdownToHTMLSafe(question.text, settings),
|
|
||||||
}}
|
|
||||||
></div>
|
|
||||||
{question.questionType === QuestionType.MATCHING && (
|
{question.questionType === QuestionType.MATCHING && (
|
||||||
<div>
|
<div>
|
||||||
{question.answers.map((answer) => (
|
{question.answers.map((answer) => (
|
||||||
@@ -134,12 +124,7 @@ function QuizQuestionPreview({ question }: { question: LocalQuizQuestion }) {
|
|||||||
<div></div>
|
<div></div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<MarkdownDisplay markdown={answer.text} className="markdownQuizAnswerPreview" />
|
||||||
className="markdownQuizAnswerPreview"
|
|
||||||
dangerouslySetInnerHTML={{
|
|
||||||
__html: markdownToHTMLSafe(answer.text, settings),
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
42
src/components/MarkdownDisplay.tsx
Normal file
42
src/components/MarkdownDisplay.tsx
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
|
||||||
|
import { SuspenseAndErrorHandling } from "./SuspenseAndErrorHandling";
|
||||||
|
import { markdownToHTMLSafe } from "@/services/htmlMarkdownUtils";
|
||||||
|
import { LocalCourseSettings } from "@/models/local/localCourseSettings";
|
||||||
|
|
||||||
|
export default function MarkdownDisplay({
|
||||||
|
markdown,
|
||||||
|
className = "",
|
||||||
|
}: {
|
||||||
|
markdown: string;
|
||||||
|
className?: string;
|
||||||
|
}) {
|
||||||
|
const [settings] = useLocalCourseSettingsQuery();
|
||||||
|
return (
|
||||||
|
<SuspenseAndErrorHandling>
|
||||||
|
<DangerousInnerMarkdown
|
||||||
|
markdown={markdown}
|
||||||
|
settings={settings}
|
||||||
|
className={className}
|
||||||
|
/>
|
||||||
|
</SuspenseAndErrorHandling>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function DangerousInnerMarkdown({
|
||||||
|
markdown,
|
||||||
|
settings,
|
||||||
|
className,
|
||||||
|
}: {
|
||||||
|
markdown: string;
|
||||||
|
settings: LocalCourseSettings;
|
||||||
|
className: string;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={"markdownPreview " + className}
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: markdownToHTMLSafe(markdown, settings),
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -46,10 +46,12 @@ export function convertImagesToCanvasImages(
|
|||||||
|
|
||||||
export function markdownToHTMLSafe(
|
export function markdownToHTMLSafe(
|
||||||
markdownString: string,
|
markdownString: string,
|
||||||
settings: LocalCourseSettings
|
settings: LocalCourseSettings,
|
||||||
|
convertImages: boolean = true
|
||||||
) {
|
) {
|
||||||
const html = markdownToHtmlNoImages(markdownString);
|
const html = markdownToHtmlNoImages(markdownString);
|
||||||
return convertImagesToCanvasImages(html, settings);
|
if (convertImages) return convertImagesToCanvasImages(html, settings);
|
||||||
|
else return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function markdownToHtmlNoImages(markdownString: string) {
|
export function markdownToHtmlNoImages(markdownString: string) {
|
||||||
|
|||||||
Reference in New Issue
Block a user