From 009f5d6ed41752e9f459a5d1486c1a575aacd7b5 Mon Sep 17 00:00:00 2001 From: Nathan Vasse Date: Fri, 14 Feb 2025 15:28:33 +0100 Subject: [PATCH 1/2] =?UTF-8?q?=E2=99=BB=EF=B8=8F(front)=20improve=20table?= =?UTF-8?q?=20pdf=20rendering?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous way of rendering table was causing issues when tables could not fit on one page. I then came accross this discussion https://github.com/diegomura/react-pdf/issues/2343. The author created a lib to improve the rendering of table, it's better, but still not perfect maybe. --- CHANGELOG.md | 30 ++------ src/frontend/apps/impress/package.json | 1 + .../doc-header/components/ModalExport.tsx | 6 ++ .../doc-header/components/blocks/Table.tsx | 76 +++++++++++++++++++ .../src/types/@ag-media/react-pdf-table.d.ts | 9 +++ src/frontend/yarn.lock | 5 ++ 6 files changed, 105 insertions(+), 22 deletions(-) create mode 100644 src/frontend/apps/impress/src/features/docs/doc-header/components/blocks/Table.tsx create mode 100644 src/frontend/apps/impress/src/types/@ag-media/react-pdf-table.d.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index e933ca54..4ddf0ce2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - ## [Unreleased] ## Changed @@ -15,6 +14,9 @@ and this project adheres to - πŸ“(doc) minor README.md formatting and wording enhancements - ♻️Stop setting a default title on doc creation #634 +## Fixed + +- ♻️(frontend) improve table pdf rendering ## [2.2.0] - 2025-02-10 @@ -35,7 +37,6 @@ and this project adheres to - πŸ›(frontend) fix cursor breakline #609 - πŸ›(frontend) fix style pdf export #609 - ## [2.1.0] - 2025-01-29 ## Added @@ -51,7 +52,7 @@ and this project adheres to ## Changed - πŸ’„(frontend) add abilities on doc row #581 -- πŸ’„(frontend) improve DocsGridItem responsive padding #582 +- πŸ’„(frontend) improve DocsGridItem responsive padding #582 - πŸ”§(backend) Bump maximum page size to 200 #516 - πŸ“(doc) Improve Read me #558 @@ -63,7 +64,6 @@ and this project adheres to - πŸ”₯(backend) remove "content" field from list serializer # 516 - ## [2.0.1] - 2025-01-17 ## Fixed @@ -118,12 +118,11 @@ and this project adheres to - ⚑️(e2e) reduce flakiness on e2e tests #511 - ## Fixed + - πŸ›(frontend) update doc editor height #481 - πŸ’„(frontend) add doc search #485 - ## [1.9.0] - 2024-12-11 ## Added @@ -145,21 +144,18 @@ and this project adheres to - πŸ›(frontend) Fix hidden menu on Firefox #468 - πŸ›(backend) fix sanitize problem IA #490 - ## [1.8.2] - 2024-11-28 ## Changed - ♻️(SW) change strategy html caching #460 - ## [1.8.1] - 2024-11-27 ## Fixed - πŸ›(frontend) link not clickable and flickering firefox #457 - ## [1.8.0] - 2024-11-25 ## Added @@ -188,7 +184,6 @@ and this project adheres to - πŸ›(frontend) users have view access when revoked #387 - πŸ›(frontend) fix placeholder editable when double clicks #454 - ## [1.7.0] - 2024-10-24 ## Added @@ -216,7 +211,6 @@ and this project adheres to - πŸ”₯(helm) remove infra related codes #366 - ## [1.6.0] - 2024-10-17 ## Added @@ -239,7 +233,6 @@ and this project adheres to - πŸ›(backend) fix nginx docker container #340 - πŸ›(frontend) fix copy paste firefox #353 - ## [1.5.1] - 2024-10-10 ## Fixed @@ -274,7 +267,6 @@ and this project adheres to - πŸ”§(backend) fix configuration to avoid different ssl warning #297 - πŸ›(frontend) fix editor break line not working #302 - ## [1.4.0] - 2024-09-17 ## Added @@ -295,7 +287,6 @@ and this project adheres to - πŸ›(backend) Fix forcing ID when creating a document via API endpoint #234 - πŸ› Rebuild frontend dev container from makefile #248 - ## [1.3.0] - 2024-09-05 ## Added @@ -320,7 +311,6 @@ and this project adheres to - πŸ”₯(frontend) remove saving modal #213 - ## [1.2.1] - 2024-08-23 ## Changed @@ -328,7 +318,6 @@ and this project adheres to - ♻️ Change ordering docs datagrid #195 - πŸ”₯(helm) use scaleway email #194 - ## [1.2.0] - 2024-08-22 ## Added @@ -352,14 +341,14 @@ and this project adheres to - ⚑️(CI) only e2e chrome mandatory #177 ## Removed -- πŸ”₯(helm) remove htaccess #181 +- πŸ”₯(helm) remove htaccess #181 ## [1.1.0] - 2024-07-15 ## Added -- 🀑(demo) generate dummy documents on dev users #120 +- 🀑(demo) generate dummy documents on dev users #120 - ✨(frontend) create side modal component #134 - ✨(frontend) Doc grid actions (update / delete) #136 - ✨(frontend) Doc editor header information #137 @@ -370,12 +359,11 @@ and this project adheres to - ♻️(frontend) create a doc from a modal #132 - ♻️(frontend) manage members from the share modal #140 - ## [1.0.0] - 2024-07-02 ## Added -- πŸ›‚(frontend) Manage the document's right (#75) +- πŸ›‚(frontend) Manage the document's right (#75) - ✨(frontend) Update document (#68) - ✨(frontend) Remove document (#68) - 🐳(docker) dockerize dev frontend (#63) @@ -409,7 +397,6 @@ and this project adheres to - πŸ’š(CI) Remove trigger workflow on push tags on CI (#68) - πŸ”₯(frontend) Remove coming soon page (#121) - ## [0.1.0] - 2024-05-24 ## Added @@ -417,7 +404,6 @@ and this project adheres to - ✨(frontend) Coming Soon page (#67) - πŸš€ Impress, project to manage your documents easily and collaboratively. - [unreleased]: https://github.com/numerique-gouv/impress/compare/v2.2.0...main [v2.2.0]: https://github.com/numerique-gouv/impress/releases/v2.2.0 [v2.1.0]: https://github.com/numerique-gouv/impress/releases/v2.1.0 diff --git a/src/frontend/apps/impress/package.json b/src/frontend/apps/impress/package.json index a6a0d29e..290c80a8 100644 --- a/src/frontend/apps/impress/package.json +++ b/src/frontend/apps/impress/package.json @@ -15,6 +15,7 @@ "test:watch": "jest --watch" }, "dependencies": { + "@ag-media/react-pdf-table": "2.0.1", "@blocknote/core": "0.23.2", "@blocknote/mantine": "0.23.2", "@blocknote/react": "0.23.2", diff --git a/src/frontend/apps/impress/src/features/docs/doc-header/components/ModalExport.tsx b/src/frontend/apps/impress/src/features/docs/doc-header/components/ModalExport.tsx index 5faf70a8..8e99b2db 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-header/components/ModalExport.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-header/components/ModalExport.tsx @@ -27,6 +27,8 @@ import { Doc } from '@/features/docs/doc-management'; import { TemplatesOrdering, useTemplates } from '../api/useTemplates'; import { downloadFile, exportResolveFileUrl } from '../utils'; +import { Table } from './blocks/Table'; + enum DocDownloadFormat { PDF = 'pdf', DOCX = 'docx', @@ -114,6 +116,7 @@ export const ModalExport = ({ onClose, doc }: ModalExportProps) => { : 1.17; return ( { ); }, + table: (block, transformer) => { + return ; + }, }, }, { diff --git a/src/frontend/apps/impress/src/features/docs/doc-header/components/blocks/Table.tsx b/src/frontend/apps/impress/src/features/docs/doc-header/components/blocks/Table.tsx new file mode 100644 index 00000000..156c3eb6 --- /dev/null +++ b/src/frontend/apps/impress/src/features/docs/doc-header/components/blocks/Table.tsx @@ -0,0 +1,76 @@ +import { TD, TH, TR, Table as TablePDF } from '@ag-media/react-pdf-table'; +import { + DefaultBlockSchema, + Exporter, + InlineContentSchema, + StyleSchema, + TableContent, +} from '@blocknote/core'; +import { View } from '@react-pdf/renderer'; +import { ReactNode } from 'react'; + +export const Table = (props: { + data: TableContent; + transformer: Exporter< + DefaultBlockSchema, + InlineContentSchema, + StyleSchema, + unknown, + unknown, + unknown, + unknown + >; +}) => { + return ( + + {props.data.rows.map((row, index) => { + if (index === 0) { + return ( + + ); + })} + + ); + } + return ( + + {row.cells.map((cell, index) => { + // Make empty cells are rendered. + if (cell.length === 0) { + cell.push({ + styles: {}, + text: ' ', + type: 'text', + }); + } + return ( + + ); + })} + + ); + })} + + ); +}; diff --git a/src/frontend/apps/impress/src/types/@ag-media/react-pdf-table.d.ts b/src/frontend/apps/impress/src/types/@ag-media/react-pdf-table.d.ts new file mode 100644 index 00000000..84c10bc1 --- /dev/null +++ b/src/frontend/apps/impress/src/types/@ag-media/react-pdf-table.d.ts @@ -0,0 +1,9 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +// This file is used to declare the types for the @ag-media/react-pdf-table package +// This library does not export its types in the "exports" field in the package.json. +declare module '@ag-media/react-pdf-table' { + export const TD: React.FC; + export const TH: React.FC; + export const TR: React.FC; + export const Table: React.FC; +} diff --git a/src/frontend/yarn.lock b/src/frontend/yarn.lock index cbbd2ee7..38330b15 100644 --- a/src/frontend/yarn.lock +++ b/src/frontend/yarn.lock @@ -7,6 +7,11 @@ resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.4.1.tgz#2447a230bfe072c1659e6815129c03cf170710e3" integrity sha512-12WGKBQzjUAI4ayyF4IAtfw2QR/IDoqk6jTddXDhtYTJF9ASmoE1zst7cVtP0aL/F1jUJL5r+JxKXKEgHNbEUQ== +"@ag-media/react-pdf-table@2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@ag-media/react-pdf-table/-/react-pdf-table-2.0.1.tgz#609e51992faed54bcf379a376442997c6bac53cc" + integrity sha512-UMNdGYAfuI6L1wLRziYmwcp/8I2JgbwX+PY7bHXGb2+P6MwgFJH8W71qZO1bxfxrmVUTP8YblQwl1PkXG2m6Rg== + "@ampproject/remapping@^2.2.0": version "2.3.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" From ad47fc2d60e0fe97f9246705459c7639e0e6551c Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Wed, 19 Feb 2025 12:50:51 +0100 Subject: [PATCH 2/2] =?UTF-8?q?=E2=9C=85(e2e)=20global=20setup=20authentic?= =?UTF-8?q?ation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Because of the parallelism of the tests, the authentication setup was flaky. Sometimes the tests would run before the authentication was complete. We change to a global setup instead of the project dependency setup, it should be more reliable. We improved the waiting states of the authentication setup. --- .../e2e/__tests__/app-impress/auth.setup.ts | 63 ++++++++++++------- src/frontend/apps/e2e/playwright.config.ts | 6 +- 2 files changed, 42 insertions(+), 27 deletions(-) diff --git a/src/frontend/apps/e2e/__tests__/app-impress/auth.setup.ts b/src/frontend/apps/e2e/__tests__/app-impress/auth.setup.ts index 31d22b71..57168af9 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/auth.setup.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/auth.setup.ts @@ -1,27 +1,46 @@ -import { test as setup } from '@playwright/test'; +import { FullConfig, FullProject, chromium, expect } from '@playwright/test'; import { keyCloakSignIn } from './common'; -setup('authenticate-chromium', async ({ page }) => { - await page.goto('/'); - await keyCloakSignIn(page, 'chromium'); - await page - .context() - .storageState({ path: `playwright/.auth/user-chromium.json` }); -}); +const saveStorageState = async ( + browserConfig: FullProject, +) => { + const browserName = browserConfig?.name || 'chromium'; -setup('authenticate-webkit', async ({ page }) => { - await page.goto('/'); - await keyCloakSignIn(page, 'webkit'); - await page - .context() - .storageState({ path: `playwright/.auth/user-webkit.json` }); -}); + const { storageState, ...useConfig } = browserConfig?.use; + const browser = await chromium.launch(); + const context = await browser.newContext(useConfig); + const page = await context.newPage(); -setup('authenticate-firefox', async ({ page }) => { - await page.goto('/'); - await keyCloakSignIn(page, 'firefox'); - await page - .context() - .storageState({ path: `playwright/.auth/user-firefox.json` }); -}); + await page.goto('/', { waitUntil: 'networkidle' }); + await page.content(); + await expect(page.getByText('Docs').first()).toBeVisible(); + + await keyCloakSignIn(page, browserName); + + await expect( + page.locator('header').first().getByRole('button', { + name: 'Logout', + }), + ).toBeVisible(); + + await page.context().storageState({ + path: storageState as string, + }); + + await browser.close(); +}; + +async function globalSetup(config: FullConfig) { + /* eslint-disable @typescript-eslint/no-non-null-assertion */ + const chromeConfig = config.projects.find((p) => p.name === 'chromium')!; + const firefoxConfig = config.projects.find((p) => p.name === 'firefox')!; + const webkitConfig = config.projects.find((p) => p.name === 'webkit')!; + /* eslint-enable @typescript-eslint/no-non-null-assertion */ + + await saveStorageState(chromeConfig); + await saveStorageState(webkitConfig); + await saveStorageState(firefoxConfig); +} + +export default globalSetup; diff --git a/src/frontend/apps/e2e/playwright.config.ts b/src/frontend/apps/e2e/playwright.config.ts index f6007eb0..cdb6aadc 100644 --- a/src/frontend/apps/e2e/playwright.config.ts +++ b/src/frontend/apps/e2e/playwright.config.ts @@ -38,10 +38,9 @@ export default defineConfig({ timeout: 120 * 1000, reuseExistingServer: true, }, - + globalSetup: require.resolve('./__tests__/app-impress/auth.setup'), /* Configure projects for major browsers */ projects: [ - { name: 'setup', testMatch: /.*\.setup\.ts/ }, { name: 'chromium', use: { @@ -53,7 +52,6 @@ export default defineConfig({ permissions: ['clipboard-read', 'clipboard-write'], }, }, - dependencies: ['setup'], }, { name: 'webkit', @@ -63,7 +61,6 @@ export default defineConfig({ timezoneId: 'Europe/Paris', storageState: 'playwright/.auth/user-webkit.json', }, - dependencies: ['setup'], }, { name: 'firefox', @@ -79,7 +76,6 @@ export default defineConfig({ }, }, }, - dependencies: ['setup'], }, ], });
+ {row.cells.map((cell, index) => { + // Make empty cells are rendered. + if (cell.length === 0) { + cell.push({ + styles: {}, + text: ' ', + type: 'text', + }); + } + return ( + + {props.transformer.transformInlineContent(cell)} +
+ + { + props.transformer.transformInlineContent( + cell, + ) as ReactNode + } + +