From 7922c702cd19be6069ec1b088ff85380911ba3d5 Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Mon, 15 Apr 2024 22:34:19 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80(app-impress)=20add=20template=20bu?= =?UTF-8?q?ilder=20editor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We add the template builder editor to the template feature. It will be used to create and edit templates. --- .../apps/e2e/__tests__/app-impress/common.ts | 29 ++++++ .../e2e/__tests__/app-impress/menu.spec.ts | 1 + .../app-impress/template-editor.spec.ts | 29 ++++++ src/frontend/apps/impress/package.json | 3 + .../template/components/TemplateEditor.tsx | 35 ++++++++ src/frontend/yarn.lock | 90 +++++++++++++++++++ 6 files changed, 187 insertions(+) create mode 100644 src/frontend/apps/e2e/__tests__/app-impress/template-editor.spec.ts create mode 100644 src/frontend/apps/impress/src/features/templates/template/components/TemplateEditor.tsx diff --git a/src/frontend/apps/e2e/__tests__/app-impress/common.ts b/src/frontend/apps/e2e/__tests__/app-impress/common.ts index 542638cc..0aea93c5 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/common.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/common.ts @@ -45,6 +45,35 @@ export const createPad = async ( return randomPads; }; +export const createTemplate = async ( + page: Page, + templateName: string, + browserName: string, + length: number, +) => { + const menu = page.locator('menu').first(); + await menu.getByLabel(`Template button`).click(); + + const panel = page.getByLabel('Templates panel').first(); + const buttonCreate = page.getByRole('button', { + name: 'Create the template', + }); + + const randomTemplates = randomName(templateName, browserName, length); + + for (let i = 0; i < randomTemplates.length; i++) { + await panel.getByRole('button', { name: 'Add a template' }).click(); + await page.getByText('Template name').fill(randomTemplates[i]); + await expect(buttonCreate).toBeEnabled(); + await buttonCreate.click(); + await expect( + panel.locator('li').getByText(randomTemplates[i]), + ).toBeVisible(); + } + + return randomTemplates; +}; + export const addNewMember = async ( page: Page, index: number, diff --git a/src/frontend/apps/e2e/__tests__/app-impress/menu.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/menu.spec.ts index 4bd73852..1eafa55a 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/menu.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/menu.spec.ts @@ -10,6 +10,7 @@ test.beforeEach(async ({ page, browserName }) => { test.describe('Menu', () => { const menuItems = [ { name: 'Search', isDefault: true }, + { name: 'Template', isDefault: false }, { name: 'Favorite', isDefault: false }, { name: 'Recent', isDefault: false }, { name: 'Contacts', isDefault: false }, diff --git a/src/frontend/apps/e2e/__tests__/app-impress/template-editor.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/template-editor.spec.ts new file mode 100644 index 00000000..e8ea725a --- /dev/null +++ b/src/frontend/apps/e2e/__tests__/app-impress/template-editor.spec.ts @@ -0,0 +1,29 @@ +import { expect, test } from '@playwright/test'; + +import { createTemplate, keyCloakSignIn } from './common'; + +test.beforeEach(async ({ page, browserName }) => { + await page.goto('/'); + await keyCloakSignIn(page, browserName); +}); + +test.describe('Template Editor', () => { + test('checks the template editor interact correctly', async ({ + page, + browserName, + }) => { + const randomTemplate = await createTemplate( + page, + 'template-editor', + browserName, + 1, + ); + + await expect(page.locator('h2').getByText(randomTemplate[0])).toBeVisible(); + + await page.getByTitle('Open Blocks').click(); + await expect( + page.locator('.gjs-editor .gjs-block[title="Text"]'), + ).toBeVisible(); + }); +}); diff --git a/src/frontend/apps/impress/package.json b/src/frontend/apps/impress/package.json index a8d9eb9d..70951af3 100644 --- a/src/frontend/apps/impress/package.json +++ b/src/frontend/apps/impress/package.json @@ -19,6 +19,7 @@ "@blocknote/react": "0.12.4", "@openfun/cunningham-react": "2.7.0", "@tanstack/react-query": "5.28.14", + "grapesjs-blocks-basic": "1.0.2", "i18next": "23.10.1", "lodash": "4.17.21", "luxon": "3.4.4", @@ -34,6 +35,7 @@ "zustand": "4.5.2" }, "devDependencies": { + "@grapesjs/react": "1.0.0", "@svgr/webpack": "8.1.0", "@tanstack/react-query-devtools": "5.28.14", "@testing-library/jest-dom": "6.4.2", @@ -48,6 +50,7 @@ "dotenv": "16.4.5", "eslint-config-impress": "*", "fetch-mock": "9.11.0", + "grapesjs": "0.21.10", "jest": "29.7.0", "jest-environment-jsdom": "29.7.0", "node-fetch": "2.7.0", diff --git a/src/frontend/apps/impress/src/features/templates/template/components/TemplateEditor.tsx b/src/frontend/apps/impress/src/features/templates/template/components/TemplateEditor.tsx new file mode 100644 index 00000000..22277202 --- /dev/null +++ b/src/frontend/apps/impress/src/features/templates/template/components/TemplateEditor.tsx @@ -0,0 +1,35 @@ +import GjsEditor from '@grapesjs/react'; +import grapesjs, { Editor, ProjectData } from 'grapesjs'; +import 'grapesjs/dist/css/grapes.min.css'; +import pluginBlocksBasic from 'grapesjs-blocks-basic'; + +import { Card, Text } from '@/components'; + +import { useUpdateTemplateCodeEditor } from '../api/useUpdateTemplateCodeEditor'; +import { Template } from '../types'; + +interface TemplateEditorProps { + template: Template; +} + +export const TemplateEditor = ({ template }: TemplateEditorProps) => { + const onEditor = (editor: Editor) => {}; + + return ( + <> + + {template.title} + + + pluginBlocksBasic(editor, {})]} + onEditor={onEditor} + /> + + + ); +}; diff --git a/src/frontend/yarn.lock b/src/frontend/yarn.lock index 292c72e1..ecd89d01 100644 --- a/src/frontend/yarn.lock +++ b/src/frontend/yarn.lock @@ -1485,6 +1485,11 @@ dependencies: tslib "^2.4.0" +"@grapesjs/react@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@grapesjs/react/-/react-1.0.0.tgz#bfa938128db7b69ca1c23439b66decf4eaa0ca9a" + integrity sha512-HHttzxwgvhbxQqqsiiQzb+OJtKFl8yWI9Yp3IgPgiKXqwY19lEJWSkCukvfqxugbYRxi0M1uERLAt209AmY5vQ== + "@humanwhocodes/config-array@^0.11.14": version "0.11.14" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" @@ -3428,6 +3433,14 @@ dependencies: "@babel/types" "^7.20.7" +"@types/backbone@^1.4.15": + version "1.4.19" + resolved "https://registry.yarnpkg.com/@types/backbone/-/backbone-1.4.19.tgz#f6e8406fed40ca3fe224f6e59115142b62be76d6" + integrity sha512-byyn236JymGByOajKA7mi1k+/jKn162TIvArOB4SHgOGbVlFj8CSfJH4jekP0qo0vJwW5khrrsiiO1Jsos6ZvA== + dependencies: + "@types/jquery" "*" + "@types/underscore" "*" + "@types/debug@^4.0.0": version "4.1.12" resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917" @@ -3488,6 +3501,13 @@ expect "^29.0.0" pretty-format "^29.0.0" +"@types/jquery@*": + version "3.5.29" + resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.5.29.tgz#3c06a1f519cd5fc3a7a108971436c00685b5dcea" + integrity sha512-oXQQC9X9MOPRrMhPHHOsXqeQDnWeCDT3PelUIg/Oy8FAbzSZtFHRjc7IpbfFVmpLtJ+UOoywpRsuO5Jxjybyeg== + dependencies: + "@types/sizzle" "*" + "@types/jsdom@^20.0.0": version "20.0.1" resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-20.0.1.tgz#07c14bc19bd2f918c1929541cdaacae894744808" @@ -3588,6 +3608,11 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== +"@types/sizzle@*": + version "2.3.8" + resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.8.tgz#518609aefb797da19bf222feb199e8f653ff7627" + integrity sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg== + "@types/stack-utils@^2.0.0": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" @@ -3608,6 +3633,11 @@ resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304" integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA== +"@types/underscore@*": + version "1.11.15" + resolved "https://registry.yarnpkg.com/@types/underscore/-/underscore-1.11.15.tgz#29c776daecf6f1935da9adda17509686bf979947" + integrity sha512-HP38xE+GuWGlbSRq9WrZkousaQ7dragtZCruBVMi0oX1migFZavZ3OROKHSkNp/9ouq82zrWtZpg18jFnVN96g== + "@types/unist@*", "@types/unist@^3.0.0": version "3.0.2" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.2.tgz#6dd61e43ef60b34086287f83683a5c1b2dc53d20" @@ -4202,6 +4232,28 @@ babel-preset-jest@^29.6.3: babel-plugin-jest-hoist "^29.6.3" babel-preset-current-node-syntax "^1.0.0" +backbone-undo@^0.2.5: + version "0.2.6" + resolved "https://registry.yarnpkg.com/backbone-undo/-/backbone-undo-0.2.6.tgz#00c4d78ab2425c18a76f2a96a1eee181560a5d8d" + integrity sha512-AsfpNiljLXlk7TcffDUu3EAUq7CxWbyTNwARWrql5XTzN4vh6WzEEBZYaKK4kTTz+iW1tSzqUooaGRIwO83kWA== + dependencies: + backbone ">=1.0.0" + underscore ">=1.4.4" + +backbone@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/backbone/-/backbone-1.4.1.tgz#099a78184bc07b034048a8332229c2ccca1e3e62" + integrity sha512-ADy1ztN074YkWbHi8ojJVFe3vAanO/lrzMGZWUClIP7oDD/Pjy2vrASraUP+2EVCfIiTtCW4FChVow01XneivA== + dependencies: + underscore ">=1.8.3" + +backbone@>=1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/backbone/-/backbone-1.6.0.tgz#5cdfa25257819b223109a77a74dde26d38995930" + integrity sha512-13PUjmsgw/49EowNcQvfG4gmczz1ximTMhUktj0Jfrjth0MVaTxehpU+qYYX4MxnuIuhmvBLC6/ayxuAGnOhbA== + dependencies: + underscore ">=1.8.3" + bail@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/bail/-/bail-2.0.2.tgz#d26f5cd8fe5d6f832a31517b9f7c356040ba6d5d" @@ -4539,6 +4591,16 @@ co@^4.6.0: resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== +codemirror-formatting@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/codemirror-formatting/-/codemirror-formatting-1.0.0.tgz#879cc1fdd9018343c1d5511769ce5360d705ebf2" + integrity sha512-br9yM6eJI3pJHekEnoyHaBEb1B7XxxDjju+vRyBe8QGLp5saTIXXkZ+eFCTqXSAtI8QEZDFVEX2/SOjH2sVWRQ== + +codemirror@^5.63.0: + version "5.65.16" + resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.65.16.tgz#efc0661be6bf4988a6a1c2fe6893294638cdb334" + integrity sha512-br21LjYmSlVL0vFCPWPfhzUCT34FM/pAdK7rRIZwa0rrtrIdotvP4Oh4GUHsu2E3IrQMCfRkL/fN3ytMNxVQvg== + collect-v8-coverage@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" @@ -6094,6 +6156,24 @@ graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.6, graceful-fs@^4.2.0, resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== +grapesjs-blocks-basic@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/grapesjs-blocks-basic/-/grapesjs-blocks-basic-1.0.2.tgz#d7e4cc44a2ad1f41d6622ca337668e3fd5945191" + integrity sha512-SsPKf/CvQkZ+kABOsN01auAPHXh/2J20g0AWYF7fHR3Gw3TZLtdIxT1mk90Qzi76u/7sUYi3CTI+i3ZaTtXHRA== + +grapesjs@0.21.10: + version "0.21.10" + resolved "https://registry.yarnpkg.com/grapesjs/-/grapesjs-0.21.10.tgz#f64c7eeac17412555b523249f80ae0ce3297a9c0" + integrity sha512-wvOBa8kjBLDeH006p4/krSzGNze2H7Rsncv37LxvDzC6QCQucEjQ7Lb+Fd50jDSWNnxavRRJLJPnXyPTGZYGuQ== + dependencies: + "@types/backbone" "^1.4.15" + backbone "1.4.1" + backbone-undo "^0.2.5" + codemirror "^5.63.0" + codemirror-formatting "^1.0.0" + promise-polyfill "^8.1.3" + underscore "^1.13.1" + graphemer@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" @@ -8730,6 +8810,11 @@ promise-map-series@^0.3.0: resolved "https://registry.yarnpkg.com/promise-map-series/-/promise-map-series-0.3.0.tgz#41873ca3652bb7a042b387d538552da9b576f8a1" integrity sha512-3npG2NGhTc8BWBolLLf8l/92OxMGaRLbqvIh9wjCHhDXNvk4zsxaTaCpiCunW09qWPrN2zeNSNwRLVBrQQtutA== +promise-polyfill@^8.1.3: + version "8.3.0" + resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-8.3.0.tgz#9284810268138d103807b11f4e23d5e945a4db63" + integrity sha512-H5oELycFml5yto/atYqmjyigJoAo3+OXwolYiH7OfQuYlAqhxNvTfiNMbV9hsC6Yp83yE5r2KTVmtrG6R9i6Pg== + prompts@^2.0.1: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" @@ -10424,6 +10509,11 @@ underscore.string@~3.3.4: sprintf-js "^1.1.1" util-deprecate "^1.0.2" +underscore@>=1.4.4, underscore@>=1.8.3, underscore@^1.13.1: + version "1.13.6" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.6.tgz#04786a1f589dc6c09f761fc5f45b89e935136441" + integrity sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A== + undici-types@~5.26.4: version "5.26.5" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"