mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-26 07:38:33 -06:00
limited latex support
This commit is contained in:
54
nextjs/package-lock.json
generated
54
nextjs/package-lock.json
generated
@@ -12,7 +12,9 @@
|
|||||||
"@tanstack/react-query": "^5.54.1",
|
"@tanstack/react-query": "^5.54.1",
|
||||||
"axios": "^1.7.5",
|
"axios": "^1.7.5",
|
||||||
"isomorphic-dompurify": "^2.15.0",
|
"isomorphic-dompurify": "^2.15.0",
|
||||||
"marked": "^14.1.0",
|
"katex": "^0.16.11",
|
||||||
|
"marked": "^14.1.2",
|
||||||
|
"marked-katex-extension": "^5.1.2",
|
||||||
"next": "^14.2.7",
|
"next": "^14.2.7",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
@@ -1751,6 +1753,12 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/katex": {
|
||||||
|
"version": "0.16.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz",
|
||||||
|
"integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "22.5.2",
|
"version": "22.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.2.tgz",
|
||||||
@@ -5196,6 +5204,31 @@
|
|||||||
"node": ">=4.0"
|
"node": ">=4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/katex": {
|
||||||
|
"version": "0.16.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.11.tgz",
|
||||||
|
"integrity": "sha512-RQrI8rlHY92OLf3rho/Ts8i/XvjgguEjOkO1BEXcU3N8BqPpSzBNwV/G0Ukr+P/l3ivvJUE/Fa/CwbS6HesGNQ==",
|
||||||
|
"funding": [
|
||||||
|
"https://opencollective.com/katex",
|
||||||
|
"https://github.com/sponsors/katex"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^8.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"katex": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/katex/node_modules/commander": {
|
||||||
|
"version": "8.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
|
||||||
|
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/keyv": {
|
"node_modules/keyv": {
|
||||||
"version": "4.5.4",
|
"version": "4.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
||||||
@@ -5337,9 +5370,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/marked": {
|
"node_modules/marked": {
|
||||||
"version": "14.1.0",
|
"version": "14.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/marked/-/marked-14.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/marked/-/marked-14.1.2.tgz",
|
||||||
"integrity": "sha512-P93GikH/Pde0hM5TAXEd8I4JAYi8IB03n8qzW8Bh1BIEFpEyBoYxi/XWZA53LSpTeLBiMQOoSMj0u5E/tiVYTA==",
|
"integrity": "sha512-f3r0yqpz31VXiDB/wj9GaOB0a2PRLQl6vJmXiFrniNwjkKdvakqJRULhjFKJpxOchlCRiG5fcacoUZY5Xa6PEQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
"marked": "bin/marked.js"
|
"marked": "bin/marked.js"
|
||||||
@@ -5348,6 +5381,19 @@
|
|||||||
"node": ">= 18"
|
"node": ">= 18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/marked-katex-extension": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/marked-katex-extension/-/marked-katex-extension-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-jRtacvDAPULKBWArDno0IGpzzpUw12yb8OaEsv3dTlvcIr21+mF9kD+Bxo2m/ErX/2ZIml6zFVMnpxCpqx3stw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/katex": "^0.16.7"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"katex": ">=0.16 <0.17",
|
||||||
|
"marked": ">=4 <15"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/merge-stream": {
|
"node_modules/merge-stream": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||||
|
|||||||
@@ -14,7 +14,9 @@
|
|||||||
"@tanstack/react-query": "^5.54.1",
|
"@tanstack/react-query": "^5.54.1",
|
||||||
"axios": "^1.7.5",
|
"axios": "^1.7.5",
|
||||||
"isomorphic-dompurify": "^2.15.0",
|
"isomorphic-dompurify": "^2.15.0",
|
||||||
"marked": "^14.1.0",
|
"katex": "^0.16.11",
|
||||||
|
"marked": "^14.1.2",
|
||||||
|
"marked-katex-extension": "^5.1.2",
|
||||||
"next": "^14.2.7",
|
"next": "^14.2.7",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
import { NextRequest, NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
import { axiosClient } from "@/services/axiosUtils";
|
import { axiosClient } from "@/services/axiosUtils";
|
||||||
import { withErrorHandling } from "@/services/withErrorHandling";
|
import { withErrorHandling } from "@/services/withErrorHandling";
|
||||||
import { AxiosResponseHeaders, RawAxiosResponseHeaders } from "axios";
|
import {
|
||||||
|
AxiosResponseHeaders,
|
||||||
|
isAxiosError,
|
||||||
|
RawAxiosResponseHeaders,
|
||||||
|
} from "axios";
|
||||||
|
|
||||||
const getUrl = (params: { rest: string[] }) => {
|
const getUrl = (params: { rest: string[] }) => {
|
||||||
const { rest } = params;
|
const { rest } = params;
|
||||||
@@ -27,7 +31,9 @@ const getNextUrl = (
|
|||||||
const nextLink = links.find((link) => link.includes('rel="next"'));
|
const nextLink = links.find((link) => link.includes('rel="next"'));
|
||||||
|
|
||||||
if (!nextLink) {
|
if (!nextLink) {
|
||||||
console.log("could not find next url in link header, reached end of pagination");
|
console.log(
|
||||||
|
"could not find next url in link header, reached end of pagination"
|
||||||
|
);
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,9 +64,8 @@ export async function GET(
|
|||||||
url.toString()
|
url.toString()
|
||||||
);
|
);
|
||||||
|
|
||||||
if(!Array.isArray(firstData))
|
if (!Array.isArray(firstData)) {
|
||||||
{
|
return NextResponse.json(firstData);
|
||||||
return NextResponse.json(firstData)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var returnData = firstData;
|
var returnData = firstData;
|
||||||
@@ -82,7 +87,6 @@ export async function GET(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return NextResponse.json(returnData);
|
return NextResponse.json(returnData);
|
||||||
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
return new NextResponse(
|
return new NextResponse(
|
||||||
JSON.stringify({ error: error.message || "Canvas GET request failed" }),
|
JSON.stringify({ error: error.message || "Canvas GET request failed" }),
|
||||||
@@ -97,18 +101,24 @@ export async function POST(
|
|||||||
{ params }: { params: { rest: string[] } }
|
{ params }: { params: { rest: string[] } }
|
||||||
) {
|
) {
|
||||||
return withErrorHandling(async () => {
|
return withErrorHandling(async () => {
|
||||||
|
const url = getUrl(params);
|
||||||
|
const body = await req.json();
|
||||||
|
let response;
|
||||||
try {
|
try {
|
||||||
const url = getUrl(params);
|
response = await axiosClient.post(url.toString(), body);
|
||||||
const body = await req.json();
|
|
||||||
const response = await axiosClient.post(url.toString(), body);
|
|
||||||
|
|
||||||
const headers = proxyResponseHeaders(response);
|
const headers = proxyResponseHeaders(response);
|
||||||
return new NextResponse(JSON.stringify(response.data), { headers });
|
return new NextResponse(JSON.stringify(response.data), { headers });
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
return new NextResponse(
|
if (isAxiosError(error)) {
|
||||||
JSON.stringify({
|
console.log(url.toString(), body);
|
||||||
|
console.log("response data", JSON.stringify( error.response?.data));
|
||||||
|
console.log("is axios error");
|
||||||
|
}
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
error: error.message || "Canvas POST request failed",
|
error: error.message || "Canvas POST request failed",
|
||||||
}),
|
},
|
||||||
{ status: error.response?.status || 500 }
|
{ status: error.response?.status || 500 }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ function DraggableListItem({
|
|||||||
href={getModuleItemUrl(courseName, moduleName, type, item.name)}
|
href={getModuleItemUrl(courseName, moduleName, type, item.name)}
|
||||||
shallow={true}
|
shallow={true}
|
||||||
className={
|
className={
|
||||||
" border rounded-sm px-1 mx-1 break-all " +
|
" border rounded-sm px-1 mx-1 break-all mb-1 " +
|
||||||
" border-slate-600 bg-slate-800 " +
|
" border-slate-600 bg-slate-800 " +
|
||||||
" block "
|
" block "
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,9 +15,11 @@ import {
|
|||||||
useAddAssignmentToCanvasMutation,
|
useAddAssignmentToCanvasMutation,
|
||||||
useCanvasAssignmentsQuery,
|
useCanvasAssignmentsQuery,
|
||||||
useDeleteAssignmentFromCanvasMutation,
|
useDeleteAssignmentFromCanvasMutation,
|
||||||
|
useUpdateAssignmentInCanvasMutation,
|
||||||
} from "@/hooks/canvas/canvasAssignmentHooks";
|
} from "@/hooks/canvas/canvasAssignmentHooks";
|
||||||
import { Spinner } from "@/components/Spinner";
|
import { Spinner } from "@/components/Spinner";
|
||||||
import { baseCanvasUrl } from "@/services/canvas/canvasServiceUtils";
|
import { baseCanvasUrl } from "@/services/canvas/canvasServiceUtils";
|
||||||
|
import ClientOnly from "@/components/ClientOnly";
|
||||||
|
|
||||||
export default function EditAssignment({
|
export default function EditAssignment({
|
||||||
moduleName,
|
moduleName,
|
||||||
@@ -79,10 +81,12 @@ export default function EditAssignment({
|
|||||||
<AssignmentPreview assignment={assignment} />
|
<AssignmentPreview assignment={assignment} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<AssignmentButtons
|
<ClientOnly>
|
||||||
moduleName={moduleName}
|
<AssignmentButtons
|
||||||
assignmentName={assignmentName}
|
moduleName={moduleName}
|
||||||
/>
|
assignmentName={assignmentName}
|
||||||
|
/>
|
||||||
|
</ClientOnly>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -100,13 +104,16 @@ function AssignmentButtons({
|
|||||||
const { data: assignment } = useAssignmentQuery(moduleName, assignmentName);
|
const { data: assignment } = useAssignmentQuery(moduleName, assignmentName);
|
||||||
const addToCanvas = useAddAssignmentToCanvasMutation();
|
const addToCanvas = useAddAssignmentToCanvasMutation();
|
||||||
const deleteFromCanvas = useDeleteAssignmentFromCanvasMutation();
|
const deleteFromCanvas = useDeleteAssignmentFromCanvasMutation();
|
||||||
|
const updateAssignment = useUpdateAssignmentInCanvasMutation();
|
||||||
|
|
||||||
const assignmentInCanvas = canvasAssignments.find(
|
const assignmentInCanvas = canvasAssignments.find(
|
||||||
(a) => a.name === assignmentName
|
(a) => a.name === assignmentName
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<div className="p-5 flex flex-row justify-end gap-3">
|
<div className="p-5 flex flex-row justify-end gap-3">
|
||||||
{(addToCanvas.isPending || deleteFromCanvas.isPending) && <Spinner />}
|
{(addToCanvas.isPending ||
|
||||||
|
deleteFromCanvas.isPending ||
|
||||||
|
updateAssignment.isPending) && <Spinner />}
|
||||||
{assignmentInCanvas && !assignmentInCanvas.published && (
|
{assignmentInCanvas && !assignmentInCanvas.published && (
|
||||||
<div className="text-rose-300 my-auto">Not Published</div>
|
<div className="text-rose-300 my-auto">Not Published</div>
|
||||||
)}
|
)}
|
||||||
@@ -115,7 +122,7 @@ function AssignmentButtons({
|
|||||||
disabled={addToCanvas.isPending}
|
disabled={addToCanvas.isPending}
|
||||||
onClick={() => addToCanvas.mutate(assignment)}
|
onClick={() => addToCanvas.mutate(assignment)}
|
||||||
>
|
>
|
||||||
Add to canvas....
|
Add to canvas
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{assignmentInCanvas && (
|
{assignmentInCanvas && (
|
||||||
@@ -127,6 +134,20 @@ function AssignmentButtons({
|
|||||||
View in Canvas
|
View in Canvas
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
|
{assignmentInCanvas && (
|
||||||
|
<button
|
||||||
|
className=""
|
||||||
|
disabled={deleteFromCanvas.isPending}
|
||||||
|
onClick={() =>
|
||||||
|
updateAssignment.mutate({
|
||||||
|
canvasAssignmentId: assignmentInCanvas.id,
|
||||||
|
assignment,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Update in Canvas
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
{assignmentInCanvas && (
|
{assignmentInCanvas && (
|
||||||
<button
|
<button
|
||||||
className="btn-danger"
|
className="btn-danger"
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import {
|
|||||||
useCanvasPagesQuery,
|
useCanvasPagesQuery,
|
||||||
useCreateCanvasPageMutation,
|
useCreateCanvasPageMutation,
|
||||||
} from "@/hooks/canvas/canvasPageHooks";
|
} from "@/hooks/canvas/canvasPageHooks";
|
||||||
import { Spinner } from "@/components/Spinner";
|
|
||||||
import EditPageButtons from "./EditPageButtons";
|
import EditPageButtons from "./EditPageButtons";
|
||||||
|
|
||||||
export default function EditPage({
|
export default function EditPage({
|
||||||
|
|||||||
@@ -18,7 +18,8 @@
|
|||||||
/* monaco editor */
|
/* monaco editor */
|
||||||
.monaco-editor-background,
|
.monaco-editor-background,
|
||||||
.monaco-editor .margin {
|
.monaco-editor .margin {
|
||||||
background-color: #18181b !important;
|
background-color: #020617 !important;
|
||||||
|
/* background-color: #18181b !important; */
|
||||||
}
|
}
|
||||||
.monaco-editor { position: absolute !important; }
|
.monaco-editor { position: absolute !important; }
|
||||||
|
|
||||||
@@ -59,6 +60,19 @@ ol {
|
|||||||
list-style-type: decimal;
|
list-style-type: decimal;
|
||||||
padding-left: 1.5rem;
|
padding-left: 1.5rem;
|
||||||
}
|
}
|
||||||
|
table {
|
||||||
|
@apply border-collapse border border-gray-700;
|
||||||
|
}
|
||||||
|
|
||||||
|
thead {
|
||||||
|
@apply text-lg ;
|
||||||
|
}
|
||||||
|
|
||||||
|
th, td {
|
||||||
|
@apply px-2 py-1 border border-gray-700;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
@apply border-t border-gray-500 my-4;
|
@apply border-t border-gray-500 my-4;
|
||||||
}
|
}
|
||||||
@@ -70,6 +84,7 @@ blockquote {
|
|||||||
code {
|
code {
|
||||||
@apply font-mono text-sm bg-gray-800 px-2 py-1 rounded-md leading-tight inline-block;
|
@apply font-mono text-sm bg-gray-800 px-2 py-1 rounded-md leading-tight inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
@apply mb-3;
|
@apply mb-3;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import { Suspense } from "react";
|
|||||||
import { getQueryClient } from "./providersQueryClientUtils";
|
import { getQueryClient } from "./providersQueryClientUtils";
|
||||||
import { hydrateCourses } from "@/hooks/hookHydration";
|
import { hydrateCourses } from "@/hooks/hookHydration";
|
||||||
import { dehydrate, HydrationBoundary } from "@tanstack/react-query";
|
import { dehydrate, HydrationBoundary } from "@tanstack/react-query";
|
||||||
import { ToastBar, Toaster } from "react-hot-toast";
|
|
||||||
import { MyToaster } from "./MyToaster";
|
import { MyToaster } from "./MyToaster";
|
||||||
|
import "katex/dist/katex.min.css";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Canvas Manager 2.0",
|
title: "Canvas Manager 2.0",
|
||||||
|
|||||||
@@ -46,13 +46,43 @@ export const useAddAssignmentToCanvasMutation = () => {
|
|||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: async (assignmnet: LocalAssignment) => {
|
mutationFn: async (assignment: LocalAssignment) => {
|
||||||
const assignmentGroup = settings.assignmentGroups.find(
|
const assignmentGroup = settings.assignmentGroups.find(
|
||||||
(g) => g.name === assignmnet.localAssignmentGroupName
|
(g) => g.name === assignment.localAssignmentGroupName
|
||||||
);
|
);
|
||||||
await canvasAssignmentService.create(
|
await canvasAssignmentService.create(
|
||||||
settings.canvasId,
|
settings.canvasId,
|
||||||
assignmnet,
|
assignment,
|
||||||
|
assignmentGroup?.canvasId
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onSuccess: () => {
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: canvasAssignmentKeys.assignments(settings.canvasId),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useUpdateAssignmentInCanvasMutation = () => {
|
||||||
|
const { data: settings } = useLocalCourseSettingsQuery();
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: async ({
|
||||||
|
assignment,
|
||||||
|
canvasAssignmentId,
|
||||||
|
}: {
|
||||||
|
assignment: LocalAssignment;
|
||||||
|
canvasAssignmentId: number;
|
||||||
|
}) => {
|
||||||
|
const assignmentGroup = settings.assignmentGroups.find(
|
||||||
|
(g) => g.name === assignment.localAssignmentGroupName
|
||||||
|
);
|
||||||
|
await canvasAssignmentService.update(
|
||||||
|
settings.canvasId,
|
||||||
|
canvasAssignmentId,
|
||||||
|
assignment,
|
||||||
assignmentGroup?.canvasId
|
assignmentGroup?.canvasId
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -31,20 +31,26 @@ axiosClient.interceptors.response.use(
|
|||||||
(response) => response,
|
(response) => response,
|
||||||
(error: AxiosError) => {
|
(error: AxiosError) => {
|
||||||
if (error.response) {
|
if (error.response) {
|
||||||
console.log("response error", error.response);
|
// console.log("response error", error.response);
|
||||||
const responseErrorText =
|
const responseErrorText =
|
||||||
typeof error.response.data === "object"
|
typeof error.response.data === "object"
|
||||||
? (error.response.data as any).error
|
? (error.response.data as any).error
|
||||||
: error.response.data;
|
: error.response.data;
|
||||||
toast.error(
|
if (!isServer) {
|
||||||
`Error: ${error.response.status} - ${responseErrorText}, ${decodeURI(
|
toast.error(
|
||||||
error.response.config.url ?? ""
|
`Error: ${error.response.status} - ${responseErrorText}, ${decodeURI(
|
||||||
)}`
|
error.response.config.url ?? ""
|
||||||
);
|
)}`
|
||||||
|
);
|
||||||
|
}
|
||||||
} else if (error.request) {
|
} else if (error.request) {
|
||||||
toast.error("Error: No response from server");
|
if (!isServer) {
|
||||||
|
toast.error("Error: No response from server");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
toast.error(`Error: ${error.message}`);
|
if (!isServer) {
|
||||||
|
toast.error(`Error: ${error.message}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ import { axiosClient } from "../axiosUtils";
|
|||||||
import { markdownToHTMLSafe } from "../htmlMarkdownUtils";
|
import { markdownToHTMLSafe } from "../htmlMarkdownUtils";
|
||||||
import { CanvasRubricCreationResponse } from "@/models/canvas/assignments/canvasRubricCreationResponse";
|
import { CanvasRubricCreationResponse } from "@/models/canvas/assignments/canvasRubricCreationResponse";
|
||||||
import { assignmentPoints } from "@/models/local/assignment/utils/assignmentPointsUtils";
|
import { assignmentPoints } from "@/models/local/assignment/utils/assignmentPointsUtils";
|
||||||
|
import {
|
||||||
|
getDateFromString,
|
||||||
|
getDateFromStringOrThrow,
|
||||||
|
} from "@/models/local/timeUtils";
|
||||||
|
|
||||||
const createRubric = async (
|
const createRubric = async (
|
||||||
courseId: number,
|
courseId: number,
|
||||||
@@ -77,18 +81,22 @@ 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 body = {
|
const body = {
|
||||||
name: localAssignment.name,
|
assignment: {
|
||||||
submission_types: localAssignment.submissionTypes.map((t) =>
|
name: localAssignment.name,
|
||||||
t.toString()
|
submission_types: localAssignment.submissionTypes.map((t) =>
|
||||||
),
|
t.toString()
|
||||||
allowed_extensions: localAssignment.allowedFileUploadExtensions.map((e) =>
|
),
|
||||||
e.toString()
|
allowed_extensions: localAssignment.allowedFileUploadExtensions.map(
|
||||||
),
|
(e) => e.toString()
|
||||||
description: markdownToHTMLSafe(localAssignment.description),
|
),
|
||||||
due_at: localAssignment.dueAt,
|
description: markdownToHTMLSafe(localAssignment.description),
|
||||||
lock_at: localAssignment.lockAt,
|
due_at: getDateFromString(localAssignment.dueAt)?.toISOString(),
|
||||||
points_possible: assignmentPoints(localAssignment),
|
lock_at:
|
||||||
assignment_group_id: canvasAssignmentGroupId,
|
localAssignment.lockAt &&
|
||||||
|
getDateFromString(localAssignment.lockAt)?.toISOString(),
|
||||||
|
points_possible: assignmentPoints(localAssignment),
|
||||||
|
assignment_group_id: canvasAssignmentGroupId,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await axiosClient.post<CanvasAssignment>(url, body);
|
const response = await axiosClient.post<CanvasAssignment>(url, body);
|
||||||
|
|||||||
@@ -1,8 +1,16 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { marked } from "marked";
|
import { marked } from "marked";
|
||||||
|
import markedKatex from "marked-katex-extension";
|
||||||
import * as DOMPurify from "isomorphic-dompurify";
|
import * as DOMPurify from "isomorphic-dompurify";
|
||||||
|
|
||||||
export function markdownToHTMLSafe(markdownString: string) {
|
export function markdownToHTMLSafe(markdownString: string) {
|
||||||
|
const options = {
|
||||||
|
throwOnError: false,
|
||||||
|
nonStandard: true
|
||||||
|
};
|
||||||
|
|
||||||
|
marked.use(markedKatex(options));
|
||||||
|
|
||||||
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 })
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user