🥅(frontend) change ui when catch unexpected upload error

We updated the UI to provide a clearer indication
when an unexpected upload error occurs.
Before the error was displayed on the top
of the editor, making it less noticeable to the user,
now we display the error directly within the
upload block, making it more visible to the user
and more user-friendly.
This commit is contained in:
Anthony LC
2026-10-06 16:20:51 +02:00
parent f93ea20ae0
commit 039ab2a296
3 changed files with 45 additions and 17 deletions
@@ -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 }) => {
@@ -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}
/>
<DocsFindReplaceStyle />
{errorAttachment && (
<Box $margin={{ bottom: 'big', top: 'none', horizontal: 'large' }}>
<TextErrors
causes={errorAttachment.cause}
canClose
$textAlign="left"
/>
</Box>
)}
<BlockNoteView
className="--docs--main-editor"
editor={editor}
@@ -1,7 +1,7 @@
import { Block } from '@blocknote/core';
import { VariantType } from '@gouvfr-lasuite/ui-components';
import { captureException } from '@sentry/nextjs';
import { useCallback, useEffect } from 'react';
import { useCallback, useEffect, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { backendUrl } from '@/api';
@@ -12,6 +12,7 @@ import { isSafeUrl } from '@/utils/url';
import { useCreateDocAttachment } from '../api';
import { ANALYZE_URL } from '../conf';
import { useEditorStore } from '../stores';
import { DocsBlockNoteEditor } from '../types';
const DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024; // Default to 10MB
@@ -49,11 +50,15 @@ export const useUploadFile = (docId: string) => {
isError: isErrorAttachment,
error: errorAttachment,
} = useCreateDocAttachment();
const editor = useEditorStore((state) => state.editor);
const uploadBlockIdRef = useRef<string | undefined>(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,