diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-editor.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-editor.spec.ts index 7aabc689c..4af5cd8dc 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-editor.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-editor.spec.ts @@ -356,20 +356,20 @@ test.describe('Doc Editor', () => { const fileChooser = await fileChooserPromise; await fileChooser.setFiles(path.join(__dirname, 'assets/test.html')); - await expect(editor.getByText('Analyzing file...')).toBeVisible(); + await expect(editor.getByText('Analyzing the file')).toBeVisible(); // To be sure the retry happens even after a page reload await goToGridDoc(page, { title: randomDoc, }); - await expect(editor.getByText('Analyzing file...')).toBeVisible(); + await expect(editor.getByText('Analyzing the file')).toBeVisible(); // The retry takes a few seconds await expect(editor.getByText('test.html')).toBeVisible({ timeout: 7000, }); - await expect(editor.getByText('Analyzing file...')).toBeHidden(); + await expect(editor.getByText('Analyzing the file')).toBeHidden(); }); test('it checks if callout custom block', async ({ page, browserName }) => { 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 879473f3d..8425caec7 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 @@ -33,7 +33,7 @@ import { useTranslation } from 'react-i18next'; import { WebsocketProvider } from 'y-websocket'; import * as Y from 'yjs'; -import { Box, TextErrors } from '@/components'; +import { Box } from '@/components'; import { useConfig } from '@/core'; import { useCunninghamTheme } from '@/cunningham'; import { @@ -133,7 +133,7 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => { ? DEFAULT_LOCALE : i18n.resolvedLanguage; - const { uploadFile, errorAttachment } = useUploadFile(doc.id); + const { uploadFile } = useUploadFile(doc.id); const conf = useConfig().data; const { isFeatureFlagActivated } = useAnalytics(); const aiBlockNoteAllowed = !!( @@ -346,15 +346,6 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => { currentUserAvatarUrl={currentUserAvatarUrl} /> - {errorAttachment && ( - - - - )} { isError: isErrorAttachment, error: errorAttachment, } = useCreateDocAttachment(); + const editor = useEditorStore((state) => state.editor); + const uploadBlockIdRef = useRef(undefined); const maxFileSize = config?.DOCUMENT_IMAGE_MAX_SIZE ?? DEFAULT_MAX_FILE_SIZE; const uploadFile = useCallback( - async (file: File) => { + async (file: File, blockId?: string) => { + uploadBlockIdRef.current = blockId; + // The server rejects an oversized file, but the proxy in front of it usually cuts the // request first and answers a bare 413 the editor cannot make sense of. Telling the // user before sending anything saves them the wait and the cryptic message. @@ -85,6 +90,38 @@ export const useUploadFile = (docId: string) => { [createDocAttachment, docId, maxFileSize, t, toast], ); + /** + * Handle the upload error by replacing the block with an + * uploadLoader block displaying a warning message. + */ + useEffect(() => { + const blockId = uploadBlockIdRef.current; + if (!errorAttachment || !blockId || !editor) { + return; + } + + try { + editor.replaceBlocks( + [blockId], + [ + { + type: 'uploadLoader', + props: { + information: t( + 'A problem occurred while uploading the file, please try again.', + ), + type: 'warning', + }, + }, + ], + ); + } catch { + /* The block may be gone already (removed or updated by a collaborator) */ + } + + uploadBlockIdRef.current = undefined; + }, [editor, errorAttachment, t]); + return { uploadFile, isErrorAttachment, @@ -132,7 +169,7 @@ export const useUploadStatus = (editor: DocsBlockNoteEditor) => { { type: 'uploadLoader', props: { - information: t('Analyzing file...'), + information: t('Analyzing the file'), type: 'loading', blockUploadName, blockUploadType,