From fdcee29a0d591f43417e8c26c3280a0585be235f Mon Sep 17 00:00:00 2001 From: swve Date: Sun, 19 Feb 2023 19:28:38 +0100 Subject: [PATCH] feat: add pdf extension to editor --- front/components/Editor/Editor.tsx | 6 + .../Editor/Extensions/PDF/PDFBlock.ts | 35 ++++++ .../Extensions/PDF/PDFBlockComponent.tsx | 88 ++++++++++++++ .../Editor/Toolbar/ToolbarButtons.tsx | 15 ++- front/services/files/documents.ts | 20 ++++ src/routers/files.py | 27 ++++- src/services/files/documents.py | 112 ++++++++++++++++++ 7 files changed, 297 insertions(+), 6 deletions(-) create mode 100644 front/components/Editor/Extensions/PDF/PDFBlock.ts create mode 100644 front/components/Editor/Extensions/PDF/PDFBlockComponent.tsx create mode 100644 front/services/files/documents.ts create mode 100644 src/services/files/documents.py diff --git a/front/components/Editor/Editor.tsx b/front/components/Editor/Editor.tsx index d90d5951..da0e0da5 100644 --- a/front/components/Editor/Editor.tsx +++ b/front/components/Editor/Editor.tsx @@ -20,6 +20,8 @@ import Youtube from "@tiptap/extension-youtube"; import VideoBlock from "./Extensions/Video/VideoBlock"; import { Save } from "lucide-react"; import MathEquationBlock from "./Extensions/MathEquation/MathEquationBlock"; +import PDFBlockComponent from "./Extensions/PDF/PDFBlockComponent"; +import PDFBlock from "./Extensions/PDF/PDFBlock"; interface Editor { content: string; @@ -59,6 +61,10 @@ function Editor(props: Editor) { editable: true, lecture: props.lecture, }), + PDFBlock.configure({ + editable: true, + lecture: props.lecture, + }), Youtube.configure({ controls: true, modestBranding: true, diff --git a/front/components/Editor/Extensions/PDF/PDFBlock.ts b/front/components/Editor/Extensions/PDF/PDFBlock.ts new file mode 100644 index 00000000..d329b79e --- /dev/null +++ b/front/components/Editor/Extensions/PDF/PDFBlock.ts @@ -0,0 +1,35 @@ +import { mergeAttributes, Node } from "@tiptap/core"; +import { ReactNodeViewRenderer } from "@tiptap/react"; + +import PDFBlockComponent from "./PDFBlockComponent"; + +export default Node.create({ + name: "blockPDF", + group: "block", + + atom: true, + + addAttributes() { + return { + fileObject: { + default: null, + }, + }; + }, + + parseHTML() { + return [ + { + tag: "block-pdf", + }, + ]; + }, + + renderHTML({ HTMLAttributes }) { + return ["block-pdf", mergeAttributes(HTMLAttributes), 0]; + }, + + addNodeView() { + return ReactNodeViewRenderer(PDFBlockComponent); + }, +}); diff --git a/front/components/Editor/Extensions/PDF/PDFBlockComponent.tsx b/front/components/Editor/Extensions/PDF/PDFBlockComponent.tsx new file mode 100644 index 00000000..57099699 --- /dev/null +++ b/front/components/Editor/Extensions/PDF/PDFBlockComponent.tsx @@ -0,0 +1,88 @@ +import { NodeViewWrapper } from "@tiptap/react"; +import React from "react"; +import styled from "styled-components"; +import { AlertCircle, AlertTriangle, FileText, Image, ImagePlus, Info } from "lucide-react"; +import { getPDFFile, uploadNewPDFFile } from "../../../../services/files/documents"; +import { getBackendUrl } from "../../../../services/config"; + +function PDFBlockComponent(props: any) { + const [pdf, setPDF] = React.useState(null); + const [isLoading, setIsLoading] = React.useState(false); + const [fileObject, setfileObject] = React.useState(props.node.attrs.fileObject); + + const handlePDFChange = (event: React.ChangeEvent) => { + setPDF(event.target.files[0]); + }; + + const handleSubmit = async (e: any) => { + e.preventDefault(); + setIsLoading(true); + let object = await uploadNewPDFFile(pdf, props.extension.options.lecture.lecture_id); + setIsLoading(false); + setfileObject(object); + props.updateAttributes({ + fileObject: object, + }); + }; + + return ( + + {!fileObject && ( + +
+ +
+
+ +
+ +
+ )} + {fileObject && ( + +