mirror of
https://github.com/suitenumerique/docs.git
synced 2026-10-19 22:41:44 +02:00
🥅(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:
@@ -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 }) => {
|
||||
|
||||
+2
-11
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user