disable useeffecto for now

This commit is contained in:
2024-11-19 17:07:26 -07:00
parent cf200dab7f
commit e47810a741
6 changed files with 119 additions and 16 deletions

View File

@@ -22,6 +22,7 @@ export function DayTitle({ day, dayAsDate }: { day: string; dayAsDate: Date }) {
<Link <Link
className="ms-1 me-1 truncate text-nowrap transition-all hover:font-bold hover:text-slate-300" className="ms-1 me-1 truncate text-nowrap transition-all hover:font-bold hover:text-slate-300"
href={getLectureUrl(courseName, day)} href={getLectureUrl(courseName, day)}
prefetch={false}
draggable={true} draggable={true}
onDragStart={(e) => { onDragStart={(e) => {
if (todaysLecture) { if (todaysLecture) {

View File

@@ -1,3 +1,5 @@
import ClientOnly from "@/components/ClientOnly";
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";
import { rubricItemIsExtraCredit } from "@/models/local/assignment/rubricItem"; import { rubricItemIsExtraCredit } from "@/models/local/assignment/rubricItem";

View File

@@ -3,6 +3,7 @@ import { MonacoEditor } from "@/components/editor/MonacoEditor";
import { import {
useAssignmentQuery, useAssignmentQuery,
useUpdateAssignmentMutation, useUpdateAssignmentMutation,
useUpdateImageSettingsForAssignment,
} from "@/hooks/localCourse/assignmentHooks"; } from "@/hooks/localCourse/assignmentHooks";
import { import {
LocalAssignment, LocalAssignment,
@@ -31,9 +32,12 @@ export default function EditAssignment({
const router = useRouter(); const router = useRouter();
const { courseName } = useCourseContext(); const { courseName } = useCourseContext();
const [settings] = useLocalCourseSettingsQuery(); const [settings] = useLocalCourseSettingsQuery();
const [assignment, { dataUpdatedAt: serverDataUpdatedAt, isFetching: assignmentIsFetching }] = const [
useAssignmentQuery(moduleName, assignmentName); assignment,
{ dataUpdatedAt: serverDataUpdatedAt, isFetching: assignmentIsFetching },
] = useAssignmentQuery(moduleName, assignmentName);
const updateAssignment = useUpdateAssignmentMutation(); const updateAssignment = useUpdateAssignmentMutation();
useUpdateImageSettingsForAssignment({ moduleName, assignmentName });
const { const {
clientIsAuthoritative, clientIsAuthoritative,
@@ -138,7 +142,11 @@ export default function EditAssignment({
<div className="text-red-300">{error && error}</div> <div className="text-red-300">{error && error}</div>
<div className="px-3 h-full"> <div className="px-3 h-full">
<ClientOnly>
<SuspenseAndErrorHandling showToast={false}>
<AssignmentPreview assignment={assignment} /> <AssignmentPreview assignment={assignment} />
</SuspenseAndErrorHandling>
</ClientOnly>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -5,16 +5,19 @@ import { ErrorBoundary } from "react-error-boundary";
import { Spinner } from "./Spinner"; import { Spinner } from "./Spinner";
import toast from "react-hot-toast"; import toast from "react-hot-toast";
export const SuspenseAndErrorHandling: FC<{ children: ReactNode }> = ({ export const SuspenseAndErrorHandling: FC<{
children, children: ReactNode;
}) => { showToast?: boolean;
}> = ({ children, showToast = true }) => {
return ( return (
<QueryErrorResetBoundary> <QueryErrorResetBoundary>
{({ reset }) => ( {({ reset }) => (
<ErrorBoundary <ErrorBoundary
onReset={reset} onReset={reset}
fallbackRender={(props) => { fallbackRender={(props) => {
if (showToast) {
toast.error(getErrorMessage(props.error)); toast.error(getErrorMessage(props.error));
}
return ( return (
<div className="text-center"> <div className="text-center">
<div className="p-3">{getErrorMessage(props.error)}</div> <div className="p-3">{getErrorMessage(props.error)}</div>

View File

@@ -1,6 +1,15 @@
"use client"; "use client";
import { trpc } from "@/services/serverFunctions/trpcClient"; import { trpc } from "@/services/serverFunctions/trpcClient";
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext"; import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
import {
useLocalCourseSettingsQuery,
useUpdateLocalCourseSettingsMutation,
} from "./localCoursesHooks";
import {
extractImageSources,
markdownToHtmlNoImages,
} from "@/services/htmlMarkdownUtils";
import { useActionState, useEffect, useState } from "react";
export const useAssignmentQuery = ( export const useAssignmentQuery = (
moduleName: string, moduleName: string,
@@ -14,6 +23,57 @@ export const useAssignmentQuery = (
}); });
}; };
export const useUpdateImageSettingsForAssignment = ({
moduleName,
assignmentName,
}: {
moduleName: string;
assignmentName: string;
}) => {
const [settings] = useLocalCourseSettingsQuery();
const [assignment] = useAssignmentQuery(moduleName, assignmentName);
const updateSettings = useUpdateLocalCourseSettingsMutation();
const [isUpdatingSettings, setIsUpdatingSettings] = useState(false);
// useEffect(() => {
// if (isUpdatingSettings) {
// console.log("not updating image assets, still loading");
// return;
// }
// setIsUpdatingSettings(true);
// const assignmentMarkdown = markdownToHtmlNoImages(assignment.description);
// const imageSources = extractImageSources(assignmentMarkdown);
// const imagesToUpdate = imageSources.filter((source) =>
// settings.assets.every((a) => a.sourceUrl !== source)
// );
// console.log("images to update", imagesToUpdate);
// Promise.all(
// imagesToUpdate.map(async (source) => {
// // todo: get canvas url
// const canvasUrl = "";
// return { sourceUrl: source, canvasUrl };
// })
// ).then(async (newAssets) => {
// await updateSettings.mutateAsync({
// settings: {
// ...settings,
// assets: [...settings.assets, ...newAssets],
// },
// });
// setIsUpdatingSettings(false);
// });
// }, [
// assignment.description,
// isUpdatingSettings,
// settings,
// settings.assets,
// updateSettings,
// ]);
};
export const useAssignmentNamesQuery = (moduleName: string) => { export const useAssignmentNamesQuery = (moduleName: string) => {
const { courseName } = useCourseContext(); const { courseName } = useCourseContext();
return trpc.assignment.getAllAssignments.useSuspenseQuery( return trpc.assignment.getAllAssignments.useSuspenseQuery(

View File

@@ -3,18 +3,40 @@ import { marked } from "marked";
import * as DOMPurify from "isomorphic-dompurify"; import * as DOMPurify from "isomorphic-dompurify";
import { LocalCourseSettings } from "@/models/local/localCourseSettings"; import { LocalCourseSettings } from "@/models/local/localCourseSettings";
function extractImageSources(html: string) { export function extractImageSources(htmlString: string) {
const parser = new DOMParser(); const srcUrls = [];
const doc = parser.parseFromString(html, "text/html"); const regex = /<img[^>]+src=["']?([^"'>]+)["']?/g;
const imgElements = doc.querySelectorAll("img"); let match;
const srcUrls = Array.from(imgElements).map((img) => img.src);
return srcUrls; while ((match = regex.exec(htmlString)) !== null) {
srcUrls.push(match[1]);
} }
function handleImages(html: string, settings: LocalCourseSettings) { return srcUrls;
const imageSources = extractImageSources(html);
console.log(imageSources);
} }
export function convertImagesToCanvasImages(
html: string,
settings: LocalCourseSettings
) {
const imageSources = extractImageSources(html);
let mutableHtml = html;
// console.log(imageSources);
const imageLookup = settings.assets.reduce((acc, asset) => {
return { ...acc, [asset.sourceUrl]: asset.canvasUrl };
}, {} as { [key: string]: string });
for (const imageSrc of imageSources) {
const destinationUrl = imageLookup[imageSrc];
if (typeof destinationUrl === "undefined") {
throw `cannot convert to html, no canvas url for ${imageSrc} in settings`;
}
mutableHtml = mutableHtml.replaceAll(imageSrc, destinationUrl);
}
// console.log(imageSources, imageLookup, mutableHtml);
return mutableHtml;
}
export function markdownToHTMLSafe( export function markdownToHTMLSafe(
markdownString: string, markdownString: string,
settings: LocalCourseSettings settings: LocalCourseSettings
@@ -22,6 +44,13 @@ export function markdownToHTMLSafe(
const clean = DOMPurify.sanitize( const clean = DOMPurify.sanitize(
marked.parse(markdownString, { async: false, pedantic: false, gfm: true }) marked.parse(markdownString, { async: false, pedantic: false, gfm: true })
); );
handleImages(clean, settings); return convertImagesToCanvasImages(clean, settings);
// return clean;
}
export function markdownToHtmlNoImages(markdownString: string) {
const clean = DOMPurify.sanitize(
marked.parse(markdownString, { async: false, pedantic: false, gfm: true })
);
return clean; return clean;
} }