mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-25 23:28:33 -06:00
can upload images
This commit is contained in:
@@ -21,6 +21,7 @@ import { useRouter } from "next/navigation";
|
|||||||
import { AssignmentFooterButtons } from "./AssignmentFooterButtons";
|
import { AssignmentFooterButtons } from "./AssignmentFooterButtons";
|
||||||
import { useAuthoritativeUpdates } from "@/app/course/[courseName]/utils/useAuthoritativeUpdates";
|
import { useAuthoritativeUpdates } from "@/app/course/[courseName]/utils/useAuthoritativeUpdates";
|
||||||
import EditAssignmentHeader from "./EditAssignmentHeader";
|
import EditAssignmentHeader from "./EditAssignmentHeader";
|
||||||
|
import { Spinner } from "@/components/Spinner";
|
||||||
|
|
||||||
export default function EditAssignment({
|
export default function EditAssignment({
|
||||||
moduleName,
|
moduleName,
|
||||||
@@ -37,7 +38,8 @@ export default function EditAssignment({
|
|||||||
{ dataUpdatedAt: serverDataUpdatedAt, isFetching: assignmentIsFetching },
|
{ dataUpdatedAt: serverDataUpdatedAt, isFetching: assignmentIsFetching },
|
||||||
] = useAssignmentQuery(moduleName, assignmentName);
|
] = useAssignmentQuery(moduleName, assignmentName);
|
||||||
const updateAssignment = useUpdateAssignmentMutation();
|
const updateAssignment = useUpdateAssignmentMutation();
|
||||||
useUpdateImageSettingsForAssignment({ moduleName, assignmentName });
|
const { isPending: imageUpdateIsPending } =
|
||||||
|
useUpdateImageSettingsForAssignment({ moduleName, assignmentName });
|
||||||
|
|
||||||
const {
|
const {
|
||||||
clientIsAuthoritative,
|
clientIsAuthoritative,
|
||||||
@@ -152,6 +154,12 @@ export default function EditAssignment({
|
|||||||
<div className="px-3 h-full">
|
<div className="px-3 h-full">
|
||||||
<ClientOnly>
|
<ClientOnly>
|
||||||
<SuspenseAndErrorHandling showToast={false}>
|
<SuspenseAndErrorHandling showToast={false}>
|
||||||
|
{imageUpdateIsPending && (
|
||||||
|
<div className="flex justify-center">
|
||||||
|
<Spinner /> images being uploaded to canvas
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<AssignmentPreview assignment={assignment} />
|
<AssignmentPreview assignment={assignment} />
|
||||||
</SuspenseAndErrorHandling>
|
</SuspenseAndErrorHandling>
|
||||||
</ClientOnly>
|
</ClientOnly>
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export const useUpdateImageSettingsForAssignment = ({
|
|||||||
const [settings] = useLocalCourseSettingsQuery();
|
const [settings] = useLocalCourseSettingsQuery();
|
||||||
const [assignment] = useAssignmentQuery(moduleName, assignmentName);
|
const [assignment] = useAssignmentQuery(moduleName, assignmentName);
|
||||||
const updateSettings = useUpdateLocalCourseSettingsMutation();
|
const updateSettings = useUpdateLocalCourseSettingsMutation();
|
||||||
const [isUpdatingSettings, setIsUpdatingSettings] = useState(false);
|
const [isPending, setIsPending] = useState(false);
|
||||||
const createCanvasUrlMutation =
|
const createCanvasUrlMutation =
|
||||||
trpc.canvasFile.getCanvasFileUrl.useMutation();
|
trpc.canvasFile.getCanvasFileUrl.useMutation();
|
||||||
|
|
||||||
@@ -45,18 +45,17 @@ export const useUpdateImageSettingsForAssignment = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isUpdatingSettings) {
|
if (isPending) {
|
||||||
console.log("not updating image assets, still loading");
|
console.log("not updating image assets, still loading");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setIsUpdatingSettings(true);
|
setIsPending(true);
|
||||||
const assignmentMarkdown = markdownToHtmlNoImages(assignment.description);
|
const assignmentMarkdown = markdownToHtmlNoImages(assignment.description);
|
||||||
|
|
||||||
const imageSources = extractImageSources(assignmentMarkdown);
|
const imageSources = extractImageSources(assignmentMarkdown);
|
||||||
const imagesToUpdate = imageSources.filter((source) =>
|
const imagesToUpdate = imageSources.filter((source) =>
|
||||||
settings.assets.every((a) => a.sourceUrl !== source)
|
settings.assets.every((a) => a.sourceUrl !== source)
|
||||||
);
|
);
|
||||||
console.log("images to update", imagesToUpdate);
|
|
||||||
|
|
||||||
if (imagesToUpdate.length) {
|
if (imagesToUpdate.length) {
|
||||||
Promise.all(
|
Promise.all(
|
||||||
@@ -78,17 +77,20 @@ export const useUpdateImageSettingsForAssignment = ({
|
|||||||
assets: [...settings.assets, ...newAssets],
|
assets: [...settings.assets, ...newAssets],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
setIsUpdatingSettings(false);
|
setIsPending(false);
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
setIsPending(false)
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
assignment.description,
|
assignment.description,
|
||||||
createCanvasUrlMutation,
|
createCanvasUrlMutation,
|
||||||
isUpdatingSettings,
|
isPending,
|
||||||
settings,
|
settings,
|
||||||
settings.assets,
|
settings.assets,
|
||||||
updateSettings,
|
updateSettings,
|
||||||
]);
|
]);
|
||||||
|
return { isPending };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useAssignmentNamesQuery = (moduleName: string) => {
|
export const useAssignmentNamesQuery = (moduleName: string) => {
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export const canvasAssignmentService = {
|
|||||||
) {
|
) {
|
||||||
console.log(`Creating assignment: ${localAssignment.name}`);
|
console.log(`Creating assignment: ${localAssignment.name}`);
|
||||||
const url = `${canvasApi}/courses/${canvasCourseId}/assignments`;
|
const url = `${canvasApi}/courses/${canvasCourseId}/assignments`;
|
||||||
|
const content = markdownToHTMLSafe(localAssignment.description, settings);
|
||||||
const body = {
|
const body = {
|
||||||
assignment: {
|
assignment: {
|
||||||
name: localAssignment.name,
|
name: localAssignment.name,
|
||||||
@@ -38,7 +39,7 @@ export const canvasAssignmentService = {
|
|||||||
allowed_extensions: localAssignment.allowedFileUploadExtensions.map(
|
allowed_extensions: localAssignment.allowedFileUploadExtensions.map(
|
||||||
(e) => e.toString()
|
(e) => e.toString()
|
||||||
),
|
),
|
||||||
description: markdownToHTMLSafe(localAssignment.description, settings),
|
description: content,
|
||||||
due_at: getDateFromString(localAssignment.dueAt)?.toISOString(),
|
due_at: getDateFromString(localAssignment.dueAt)?.toISOString(),
|
||||||
lock_at:
|
lock_at:
|
||||||
localAssignment.lockAt &&
|
localAssignment.lockAt &&
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { marked } from "marked";
|
import { marked } from "marked";
|
||||||
import DOMPurify from "isomorphic-dompurify";
|
import DOMPurify from "isomorphic-dompurify";
|
||||||
import { LocalCourseSettings } from "@/models/local/localCourseSettings";
|
import { LocalCourseSettings } from "@/models/local/localCourseSettings";
|
||||||
import markedKatex from "marked-katex-extension";
|
import markedKatex from "marked-katex-extension";
|
||||||
|
|
||||||
marked.use(markedKatex({
|
marked.use(
|
||||||
throwOnError: false,
|
markedKatex({
|
||||||
output: "mathml"
|
throwOnError: false,
|
||||||
}));
|
output: "mathml",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
export function extractImageSources(htmlString: string) {
|
export function extractImageSources(htmlString: string) {
|
||||||
const srcUrls = [];
|
const srcUrls = [];
|
||||||
@@ -46,7 +48,8 @@ export function markdownToHTMLSafe(
|
|||||||
markdownString: string,
|
markdownString: string,
|
||||||
settings: LocalCourseSettings
|
settings: LocalCourseSettings
|
||||||
) {
|
) {
|
||||||
return markdownToHtmlNoImages(markdownString);
|
const html = markdownToHtmlNoImages(markdownString);
|
||||||
|
return convertImagesToCanvasImages(html, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function markdownToHtmlNoImages(markdownString: string) {
|
export function markdownToHtmlNoImages(markdownString: string) {
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import {
|
|||||||
uploadToCanvasPart2,
|
uploadToCanvasPart2,
|
||||||
} from "@/services/canvas/files/canvasFileService";
|
} from "@/services/canvas/files/canvasFileService";
|
||||||
|
|
||||||
|
const fileStorageLocation = process.env.FILE_STORAGE_LOCATION ?? "/app/public";
|
||||||
|
|
||||||
export const canvasFileRouter = router({
|
export const canvasFileRouter = router({
|
||||||
getCanvasFileUrl: publicProcedure
|
getCanvasFileUrl: publicProcedure
|
||||||
.input(
|
.input(
|
||||||
@@ -16,15 +18,17 @@ export const canvasFileRouter = router({
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
.mutation(async ({ input: { sourceUrl, canvasCourseId } }) => {
|
.mutation(async ({ input: { sourceUrl, canvasCourseId } }) => {
|
||||||
const localTempFile = await downloadUrlToTempDirectory(sourceUrl);
|
const localFile = sourceUrl.startsWith("/")
|
||||||
console.log("local temp file", localTempFile);
|
? fileStorageLocation + sourceUrl
|
||||||
|
: await downloadUrlToTempDirectory(sourceUrl);
|
||||||
|
console.log("local temp file", localFile);
|
||||||
const { upload_url, upload_params } = await uploadToCanvasPart1(
|
const { upload_url, upload_params } = await uploadToCanvasPart1(
|
||||||
localTempFile,
|
localFile,
|
||||||
canvasCourseId
|
canvasCourseId
|
||||||
);
|
);
|
||||||
console.log("part 1 done", upload_url, upload_params);
|
console.log("part 1 done", upload_url, upload_params);
|
||||||
const canvasUrl = await uploadToCanvasPart2({
|
const canvasUrl = await uploadToCanvasPart2({
|
||||||
pathToUpload: localTempFile,
|
pathToUpload: localFile,
|
||||||
upload_url,
|
upload_url,
|
||||||
upload_params,
|
upload_params,
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user