From 6eff21f51eb232ea4c6f6c352ac2f0131d92c986 Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Thu, 29 Aug 2024 16:36:06 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(frontend)=20add=20upload=20to=20the?= =?UTF-8?q?=20doc=20editor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can now upload images to the doc editor. The image is uploaded to the server and the URL is inserted into the editor. --- CHANGELOG.md | 6 ++- .../assets/logo-suite-numerique.png | Bin 0 -> 13584 bytes .../__tests__/app-impress/doc-editor.spec.ts | 29 ++++++++++++++ .../__tests__/app-impress/doc-export.spec.ts | 5 +++ src/frontend/apps/impress/.env | 5 ++- src/frontend/apps/impress/src/core/conf.ts | 15 ++++--- .../apps/impress/src/custom-next.d.ts | 1 + .../doc-editor/components/BlockNoteEditor.tsx | 37 ++++++++++++++++-- 8 files changed, 84 insertions(+), 14 deletions(-) create mode 100644 src/frontend/apps/e2e/__tests__/app-impress/assets/logo-suite-numerique.png diff --git a/CHANGELOG.md b/CHANGELOG.md index 76fa1e3a..b559d621 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,13 @@ 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] + # Added - ✨Add image attachments with access control - -## [Unreleased] +- ✨(frontend) Upload image to a document ## [1.2.1] - 2024-08-23 diff --git a/src/frontend/apps/e2e/__tests__/app-impress/assets/logo-suite-numerique.png b/src/frontend/apps/e2e/__tests__/app-impress/assets/logo-suite-numerique.png new file mode 100644 index 0000000000000000000000000000000000000000..243c96629ee72f48f0083f4ba6bcea2653c1a9c3 GIT binary patch literal 13584 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 { page.getByText('Read only, you cannot edit this document.'), ).toBeVisible(); }); + + test('it adds an image to the doc editor', async ({ page }) => { + await goToGridDoc(page); + + const fileChooserPromise = page.waitForEvent('filechooser'); + + await page.locator('.bn-block-outer').last().fill('Hello World'); + + await page.keyboard.press('Enter'); + await page.locator('.bn-block-outer').last().fill('/'); + await page.getByText('Resizable image with caption').click(); + await page.getByText('Upload image').click(); + + const fileChooser = await fileChooserPromise; + await fileChooser.setFiles( + path.join(__dirname, 'assets/logo-suite-numerique.png'), + ); + + const image = page.getByRole('img', { name: 'logo-suite-numerique.png' }); + + await expect(image).toBeVisible(); + + // Check src of image + expect(await image.getAttribute('src')).toMatch( + /http:\/\/localhost:8083\/media\/.*\/attachments\/.*.png/, + ); + }); }); diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-export.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-export.spec.ts index 065f8488..9c9933a0 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-export.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-export.spec.ts @@ -175,6 +175,11 @@ test.describe('Doc Export', () => { name: 'Image', }) .click(); + await page + .getByRole('tab', { + name: 'Embed', + }) + .click(); await page .getByPlaceholder('Enter URL') .fill('https://example.com/image.jpg'); diff --git a/src/frontend/apps/impress/.env b/src/frontend/apps/impress/.env index 5c413314..9e631e42 100644 --- a/src/frontend/apps/impress/.env +++ b/src/frontend/apps/impress/.env @@ -1,3 +1,4 @@ -NEXT_PUBLIC_THEME=dsfr -NEXT_PUBLIC_SIGNALING_URL= NEXT_PUBLIC_API_ORIGIN= +NEXT_PUBLIC_MEDIA_URL= +NEXT_PUBLIC_SIGNALING_URL= +NEXT_PUBLIC_THEME=dsfr \ No newline at end of file diff --git a/src/frontend/apps/impress/src/core/conf.ts b/src/frontend/apps/impress/src/core/conf.ts index dc778311..ba79a144 100644 --- a/src/frontend/apps/impress/src/core/conf.ts +++ b/src/frontend/apps/impress/src/core/conf.ts @@ -1,10 +1,13 @@ -export const baseApiUrl = (apiVersion: string = '1.0') => { - const origin = - process.env.NEXT_PUBLIC_API_ORIGIN || - (typeof window !== 'undefined' ? window.location.origin : ''); +export const mediaUrl = () => + process.env.NEXT_PUBLIC_MEDIA_URL || + (typeof window !== 'undefined' ? window.location.origin : ''); - return `${origin}/api/v${apiVersion}/`; -}; +export const backendUrl = () => + process.env.NEXT_PUBLIC_API_ORIGIN || + (typeof window !== 'undefined' ? window.location.origin : ''); + +export const baseApiUrl = (apiVersion: string = '1.0') => + `${backendUrl()}/api/v${apiVersion}/`; export const signalingUrl = (docId: string) => { const base = diff --git a/src/frontend/apps/impress/src/custom-next.d.ts b/src/frontend/apps/impress/src/custom-next.d.ts index b8bbf9bf..064d02bc 100644 --- a/src/frontend/apps/impress/src/custom-next.d.ts +++ b/src/frontend/apps/impress/src/custom-next.d.ts @@ -20,6 +20,7 @@ declare module '*.svg?url' { namespace NodeJS { interface ProcessEnv { NEXT_PUBLIC_API_ORIGIN?: string; + NEXT_PUBLIC_MEDIA_URL?: string; NEXT_PUBLIC_SIGNALING_URL?: string; NEXT_PUBLIC_SW_DEACTIVATED?: string; NEXT_PUBLIC_THEME?: string; diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx index b1447397..89c7ccda 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx @@ -2,14 +2,16 @@ import { BlockNoteEditor as BlockNoteEditorCore } from '@blocknote/core'; import '@blocknote/core/fonts/inter.css'; import { BlockNoteView } from '@blocknote/mantine'; import '@blocknote/mantine/style.css'; -import React, { useEffect, useMemo } from 'react'; +import React, { useCallback, useEffect, useMemo } from 'react'; import { WebrtcProvider } from 'y-webrtc'; -import { Box } from '@/components'; +import { Box, TextErrors } from '@/components'; +import { mediaUrl } from '@/core'; import { useAuthStore } from '@/core/auth'; import { Doc } from '@/features/docs/doc-management'; import { Version } from '@/features/docs/doc-versioning/'; +import { useCreateDocAttachment } from '../api/useCreateDocUpload'; import useSaveDoc from '../hook/useSaveDoc'; import { useDocStore } from '../stores'; import { randomColor } from '../utils'; @@ -56,8 +58,28 @@ export const BlockNoteContent = ({ const { setStore, docsStore } = useDocStore(); const canSave = doc.abilities.partial_update && !isVersion; useSaveDoc(doc.id, provider.doc, canSave); - const storedEditor = docsStore?.[storeId]?.editor; + const { + mutateAsync: createDocAttachment, + isError: isErrorAttachment, + error: errorAttachment, + } = useCreateDocAttachment(); + + const uploadFile = useCallback( + async (file: File) => { + const body = new FormData(); + body.append('file', file); + + const ret = await createDocAttachment({ + docId: doc.id, + body, + }); + + return `${mediaUrl()}${ret.file}`; + }, + [createDocAttachment, doc.id], + ); + const editor = useMemo(() => { if (storedEditor) { return storedEditor; @@ -72,8 +94,9 @@ export const BlockNoteContent = ({ color: randomColor(), }, }, + uploadFile, }); - }, [provider, storedEditor, userData?.email]); + }, [provider, storedEditor, uploadFile, userData?.email]); useEffect(() => { setStore(storeId, { editor }); @@ -90,6 +113,12 @@ export const BlockNoteContent = ({ } `} > + {isErrorAttachment && ( + + + + )} +