fixup! 🥅(frontend) change ui when catch unexpected upload error

This commit is contained in:
Anthony LC
2026-10-06 16:20:51 +02:00
parent 039ab2a296
commit c37df722fd
3 changed files with 53 additions and 55 deletions
@@ -23,6 +23,10 @@ import {
import {
FloatingComposerController,
FloatingThreadController,
ReactAudioBlock,
ReactFileBlock,
ReactImageBlock,
ReactVideoBlock,
ThreadsSidebar,
useCreateBlockNote,
} from '@blocknote/react';
@@ -83,6 +87,10 @@ const baseBlockNoteSchema = withPageBreak(
BlockNoteSchema.create({
blockSpecs: {
...defaultBlockSpecs,
audio: ReactAudioBlock(),
file: ReactFileBlock(),
image: ReactImageBlock(),
video: ReactVideoBlock(),
callout: CalloutBlock(),
codeBlock: createSafeCodeBlockSpec(),
diagram: createReactDiagramBlockSpec(),
@@ -71,6 +71,26 @@ describe('useUploadFile', () => {
'error',
);
});
it('toasts the causes of the API and rethrows when the upload fails', async () => {
fetchMock.hardReset();
fetchMock.mockGlobal();
fetchMock.post(uploadUrl, {
status: 400,
body: { file: ['File type not allowed.'] },
});
const result = renderUseUploadFile();
await expect(
result.current.uploadFile(createFile(MAX_FILE_SIZE)),
).rejects.toThrow('Failed to upload on the doc');
expect(mockToast).toHaveBeenCalledWith(
'A problem occurred while uploading the file, cause: File type not allowed.',
'error',
);
});
});
describe('useUploadStatus', () => {
@@ -1,10 +1,10 @@
import { Block } from '@blocknote/core';
import { VariantType } from '@gouvfr-lasuite/ui-components';
import { captureException } from '@sentry/nextjs';
import { useCallback, useEffect, useRef } from 'react';
import { useCallback, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { backendUrl } from '@/api';
import { APIError, backendUrl } from '@/api';
import { useConfig } from '@/core';
import { useToast } from '@/hooks';
import { formatFileSize } from '@/utils';
@@ -12,7 +12,6 @@ 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
@@ -45,20 +44,12 @@ export const useUploadFile = (docId: string) => {
const { t } = useTranslation();
const { toast } = useToast();
const { data: config } = useConfig();
const {
mutateAsync: createDocAttachment,
isError: isErrorAttachment,
error: errorAttachment,
} = useCreateDocAttachment();
const editor = useEditorStore((state) => state.editor);
const uploadBlockIdRef = useRef<string | undefined>(undefined);
const { mutateAsync: createDocAttachment } = useCreateDocAttachment();
const maxFileSize = config?.DOCUMENT_IMAGE_MAX_SIZE ?? DEFAULT_MAX_FILE_SIZE;
const uploadFile = useCallback(
async (file: File, blockId?: string) => {
uploadBlockIdRef.current = blockId;
async (file: File) => {
// 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.
@@ -80,53 +71,32 @@ export const useUploadFile = (docId: string) => {
const body = new FormData();
body.append('file', file);
const ret = await createDocAttachment({
docId,
body,
});
try {
const ret = await createDocAttachment({
docId,
body,
});
return `${backendUrl()}${ret.file}`;
return `${backendUrl()}${ret.file}`;
} catch (error) {
const causes = error instanceof APIError ? error.cause : undefined;
toast(
causes?.length
? `${t('A problem occurred while uploading the file, cause:')} ${causes.join(' ')}`
: t(
'A problem occurred while uploading the file, please try again.',
),
VariantType.ERROR,
);
throw error;
}
},
[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,
errorAttachment,
};
return { uploadFile };
};
/**