From eeb8f36cb1a420f1ee04cc034c181c1ebf3297b6 Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Wed, 10 Apr 2024 12:33:39 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(app-impress)=20print=20to=20pdf?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Feature to print the pad to pdf. It display a button in the pad toolbar, when clicked it will convert the pad to markdown, send the markdown with a template to the backend to convert it to pdf and then download the pdf. --- .../pads/pad-tools/components/PadToolBox.tsx | 18 ++++ .../pad-tools/components/PrintToPDFButton.tsx | 85 +++++++++++++++++++ .../pads/pad-tools/components/index.ts | 1 + .../src/features/pads/pad-tools/index.tsx | 1 + .../src/features/pads/pad-tools/utils.ts | 11 +++ .../pads/pad/components/PadEditor.tsx | 14 ++- 6 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 src/frontend/apps/impress/src/features/pads/pad-tools/components/PadToolBox.tsx create mode 100644 src/frontend/apps/impress/src/features/pads/pad-tools/components/PrintToPDFButton.tsx create mode 100644 src/frontend/apps/impress/src/features/pads/pad-tools/components/index.ts create mode 100644 src/frontend/apps/impress/src/features/pads/pad-tools/index.tsx create mode 100644 src/frontend/apps/impress/src/features/pads/pad-tools/utils.ts diff --git a/src/frontend/apps/impress/src/features/pads/pad-tools/components/PadToolBox.tsx b/src/frontend/apps/impress/src/features/pads/pad-tools/components/PadToolBox.tsx new file mode 100644 index 000000000..7ade8c667 --- /dev/null +++ b/src/frontend/apps/impress/src/features/pads/pad-tools/components/PadToolBox.tsx @@ -0,0 +1,18 @@ +import React from 'react'; + +import { Box } from '@/components'; +import { Pad } from '@/features/pads/pad'; + +import PrintToPDFButton from './PrintToPDFButton'; + +interface PadToolBoxProps { + pad: Pad; +} + +export const PadToolBox = ({ pad }: PadToolBoxProps) => { + return ( + + + + ); +}; diff --git a/src/frontend/apps/impress/src/features/pads/pad-tools/components/PrintToPDFButton.tsx b/src/frontend/apps/impress/src/features/pads/pad-tools/components/PrintToPDFButton.tsx new file mode 100644 index 000000000..7bd30e918 --- /dev/null +++ b/src/frontend/apps/impress/src/features/pads/pad-tools/components/PrintToPDFButton.tsx @@ -0,0 +1,85 @@ +import { + Button, + VariantType, + useToastProvider, +} from '@openfun/cunningham-react'; +import React, { useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; + +import { Pad, usePadStore } from '@/features/pads/pad'; + +import { useCreatePdfFromMarkdown } from '../api/useCreatePdfFromMarkdown'; +import { downloadFile } from '../utils'; + +interface PrintToPDFButtonProps { + pad: Pad; +} + +const PrintToPDFButton = ({ pad }: PrintToPDFButtonProps) => { + const { t } = useTranslation(); + const [isFetching, setIsFetching] = useState(false); + const { toast } = useToastProvider(); + const { padsStore } = usePadStore(); + const { + mutate: createPdfFromMarkdown, + data: pdf, + isSuccess, + isPending, + error, + } = useCreatePdfFromMarkdown(); + + useEffect(() => { + setIsFetching(isPending); + }, [isPending]); + + useEffect(() => { + if (!error) { + return; + } + + toast(error.message, VariantType.ERROR); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [error, t]); + + useEffect(() => { + if (!pdf || !isSuccess) { + return; + } + + downloadFile(pdf, 'impress-document.pdf'); + setIsFetching(false); + + toast(t('Your pdf was downloaded succesfully'), VariantType.SUCCESS); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [pdf, isSuccess, t]); + + async function onSubmit() { + const editor = padsStore[pad.id].editor; + + if (!editor) { + toast(t('No editor found'), VariantType.ERROR); + return; + } + + const markdown = await editor.blocksToMarkdownLossy(editor.document); + + createPdfFromMarkdown({ + templateId: '472d0633-20b8-4cb1-998a-1134ade092ba', + markdown, + }); + } + + return ( + + ); +}; + +export default PrintToPDFButton; diff --git a/src/frontend/apps/impress/src/features/pads/pad-tools/components/index.ts b/src/frontend/apps/impress/src/features/pads/pad-tools/components/index.ts new file mode 100644 index 000000000..7704379e9 --- /dev/null +++ b/src/frontend/apps/impress/src/features/pads/pad-tools/components/index.ts @@ -0,0 +1 @@ +export * from './PadToolBox'; diff --git a/src/frontend/apps/impress/src/features/pads/pad-tools/index.tsx b/src/frontend/apps/impress/src/features/pads/pad-tools/index.tsx new file mode 100644 index 000000000..ef6330a0f --- /dev/null +++ b/src/frontend/apps/impress/src/features/pads/pad-tools/index.tsx @@ -0,0 +1 @@ +export * from './components/'; diff --git a/src/frontend/apps/impress/src/features/pads/pad-tools/utils.ts b/src/frontend/apps/impress/src/features/pads/pad-tools/utils.ts new file mode 100644 index 000000000..27ee2ba67 --- /dev/null +++ b/src/frontend/apps/impress/src/features/pads/pad-tools/utils.ts @@ -0,0 +1,11 @@ +export function downloadFile(blob: Blob, filename: string) { + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.style.display = 'none'; + a.href = url; + a.download = filename; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + window.URL.revokeObjectURL(url); +} diff --git a/src/frontend/apps/impress/src/features/pads/pad/components/PadEditor.tsx b/src/frontend/apps/impress/src/features/pads/pad/components/PadEditor.tsx index 924472c26..455930031 100644 --- a/src/frontend/apps/impress/src/features/pads/pad/components/PadEditor.tsx +++ b/src/frontend/apps/impress/src/features/pads/pad/components/PadEditor.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { Card, Text } from '@/components'; +import { PadToolBox } from '../../pad-tools'; import { Pad } from '../types'; import { BlockNoteEditor } from './BlockNoteEditor'; @@ -12,9 +13,14 @@ interface PadEditorProps { export const PadEditor = ({ pad }: PadEditorProps) => { return ( - - {pad.name} - - + <> + + + + {pad.name} + + + + ); };