diff --git a/src/frontend/apps/e2e/__tests__/app-impress/pad-editor.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/pad-editor.spec.ts index 8c460c9a..035bb9dd 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/pad-editor.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/pad-editor.spec.ts @@ -1,6 +1,4 @@ import { expect, test } from '@playwright/test'; -import cs from 'convert-stream'; -import pdf from 'pdf-parse'; import { createPad, keyCloakSignIn } from './common'; @@ -77,33 +75,6 @@ test.describe('Pad Editor', () => { ).toHaveAttribute('href', 'http://test-markdown.html'); }); - test('it converts the pad to pdf with a template integrated', async ({ - page, - browserName, - }) => { - const downloadPromise = page.waitForEvent('download', (download) => { - return download.suggestedFilename().includes('impress-document.pdf'); - }); - - const randomPad = await createPad(page, 'pad-editor', browserName, 1); - await expect(page.locator('h2').getByText(randomPad[0])).toBeVisible(); - - await page.locator('.ProseMirror.bn-editor').click(); - await page.locator('.ProseMirror.bn-editor').fill('Hello World'); - - await page.getByText('Generate PDF').first().click(); - - const download = await downloadPromise; - expect(download.suggestedFilename()).toBe('impress-document.pdf'); - - const pdfBuffer = await cs.toBuffer(await download.createReadStream()); - const pdfText = (await pdf(pdfBuffer)).text; - - expect(pdfText).toContain('Monsieur le Premier Ministre'); // This is the template text - expect(pdfText).toContain('La directrice'); // This is the template text - expect(pdfText).toContain('Hello World'); // This is the pad text - }); - test('it renders correctly when we switch from one pad to another', async ({ page, browserName, diff --git a/src/frontend/apps/e2e/__tests__/app-impress/pad-tools.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/pad-tools.spec.ts new file mode 100644 index 00000000..be17b20c --- /dev/null +++ b/src/frontend/apps/e2e/__tests__/app-impress/pad-tools.spec.ts @@ -0,0 +1,50 @@ +import { expect, test } from '@playwright/test'; +import cs from 'convert-stream'; +import pdf from 'pdf-parse'; + +import { createPad, keyCloakSignIn } from './common'; + +test.beforeEach(async ({ page, browserName }) => { + await page.goto('/'); + await keyCloakSignIn(page, browserName); +}); + +test.describe('Pad Tools', () => { + test('it converts the pad to pdf with a template integrated', async ({ + page, + browserName, + }) => { + const downloadPromise = page.waitForEvent('download', (download) => { + return download.suggestedFilename().includes('impress-document.pdf'); + }); + + const [randomPad] = await createPad(page, 'pad-editor', browserName, 1); + await expect(page.locator('h2').getByText(randomPad)).toBeVisible(); + + await page.locator('.ProseMirror.bn-editor').click(); + await page.locator('.ProseMirror.bn-editor').fill('Hello World'); + + await page.getByLabel('Open the document options').click(); + await page + .getByRole('button', { + name: 'Generate PDF', + }) + .click(); + + await page + .getByRole('button', { + name: 'Download', + }) + .click(); + + const download = await downloadPromise; + expect(download.suggestedFilename()).toBe('impress-document.pdf'); + + const pdfBuffer = await cs.toBuffer(await download.createReadStream()); + const pdfText = (await pdf(pdfBuffer)).text; + + expect(pdfText).toContain('Monsieur le Premier Ministre'); // This is the template text + expect(pdfText).toContain('La directrice'); // This is the template text + expect(pdfText).toContain('Hello World'); // This is the pad text + }); +}); diff --git a/src/frontend/apps/impress/src/components/IconOptions.tsx b/src/frontend/apps/impress/src/components/IconOptions.tsx index a6b26569..293f1b8c 100644 --- a/src/frontend/apps/impress/src/components/IconOptions.tsx +++ b/src/frontend/apps/impress/src/components/IconOptions.tsx @@ -10,7 +10,6 @@ export const IconOptions = ({ isOpen, ...props }: IconOptionsProps) => { void; + templateOptions: { + label: string; + value: string; + }[]; + pad: Pad; +} + +export const ModalPDF = ({ onClose, templateOptions, pad }: ModalPDFProps) => { + const { toast } = useToastProvider(); + const { padsStore } = usePadStore(); + const { + mutate: createPdf, + data: pdf, + isSuccess, + + isPending, + error, + } = useCreatePdf(); + const [templateIdSelected, setTemplateIdSelected] = useState( + templateOptions?.[0].value, + ); + + useEffect(() => { + if (!error) { + return; + } + + toast(error.message, VariantType.ERROR); + + onClose(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [error, t]); + + useEffect(() => { + if (!pdf || !isSuccess) { + return; + } + + downloadFile(pdf, 'impress-document.pdf'); + + toast(t('Your pdf was downloaded succesfully'), VariantType.SUCCESS); + + onClose(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [pdf, isSuccess, t]); + + async function onSubmit() { + if (!templateIdSelected) { + return; + } + + const editor = padsStore[pad.id].editor; + + if (!editor) { + toast(t('No editor found'), VariantType.ERROR); + return; + } + + const body = await editor.blocksToHTMLLossy(editor.document); + + createPdf({ + templateId: templateIdSelected, + body, + body_type: 'html', + }); + } + + return ( + onClose()} + > + {t('Cancel')} + + } + onClose={() => onClose()} + rightActions={ + + } + size={ModalSize.MEDIUM} + title={ + + + picture_as_pdf + + + {t('Generate PDF')} + + + } + > + + + {t( + 'Generate a PDF from your document, it will be inserted in the selected template.', + )} + + + - setTemplateIdSelected(options.target.value as string) + + } - /> - {templateIdSelected && ( - + onOpenChange={(isOpen) => setIsDropOpen(isOpen)} + isOpen={isDropOpen} + > + + + + + {isModalPDFOpen && ( + setIsModalPDFOpen(false)} + templateOptions={templateOptions} + pad={pad} + /> )} ); 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 23c79c7a..8d74d105 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 @@ -16,16 +16,21 @@ export const PadEditor = ({ pad }: PadEditorProps) => { <> - + {pad.title} - +