mirror of
https://github.com/twentyhq/twenty.git
synced 2024-11-25 20:00:34 +03:00
Reusing the useUploadAttachment Hook In the implementation of the feature to ensure the attachment table is updated whenever new images are added to a RICH_TEXT field #7617 , it is likely that the useUploadAttachment hook is reused. The useUploadAttachment hook is responsible for handling the upload of attachments, including images, and returning the uploaded file URL. By reusing this hook, you can leverage its existing functionality to handle image uploads within the RICH_TEXT field. In this case, the modified image handling logic would utilize the useUploadAttachment hook to upload new images added to the RICH_TEXT content. The hook would then return the uploaded file URL, which would be used to update the attachment table with the details of the newly added images. By reusing the useUploadAttachment hook, you can avoid duplicating code and ensure consistency in the way attachments are handled throughout the application. Fixes #6565 --------- Co-authored-by: Charles Bochet <charles@twenty.com> Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
parent
9e051d7900
commit
ca91dc2dc6
@ -1,7 +1,7 @@
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import { useCreateBlockNote } from '@blocknote/react';
|
||||
import { isArray, isNonEmptyString } from '@sniptt/guards';
|
||||
import { ClipboardEvent, useCallback, useMemo } from 'react';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { useRecoilCallback, useRecoilState } from 'recoil';
|
||||
import { Key } from 'ts-key-enum';
|
||||
import { useDebouncedCallback } from 'use-debounce';
|
||||
@ -20,20 +20,16 @@ import { RightDrawerHotkeyScope } from '@/ui/layout/right-drawer/types/RightDraw
|
||||
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
import { isNonTextWritingKey } from '@/ui/utilities/hotkey/utils/isNonTextWritingKey';
|
||||
import { FileFolder, useUploadFileMutation } from '~/generated/graphql';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
|
||||
import { getFileType } from '../files/utils/getFileType';
|
||||
|
||||
import { BLOCK_SCHEMA } from '@/activities/blocks/constants/Schema';
|
||||
import { useUploadAttachmentFile } from '@/activities/files/hooks/useUploadAttachmentFile';
|
||||
import { Note } from '@/activities/types/Note';
|
||||
import { Task } from '@/activities/types/Task';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import '@blocknote/core/fonts/inter.css';
|
||||
import '@blocknote/mantine/style.css';
|
||||
import '@blocknote/react/style.css';
|
||||
import { getFileAbsoluteURI } from '~/utils/file/getFileAbsoluteURI';
|
||||
|
||||
type RichTextEditorProps = {
|
||||
activityId: string;
|
||||
@ -121,22 +117,13 @@ export const RichTextEditor = ({
|
||||
canCreateActivityState,
|
||||
);
|
||||
|
||||
const [uploadFile] = useUploadFileMutation();
|
||||
const { uploadAttachmentFile } = useUploadAttachmentFile();
|
||||
|
||||
const handleUploadAttachment = async (file: File): Promise<string> => {
|
||||
if (isUndefinedOrNull(file)) {
|
||||
return '';
|
||||
}
|
||||
const result = await uploadFile({
|
||||
variables: {
|
||||
file,
|
||||
fileFolder: FileFolder.Attachment,
|
||||
},
|
||||
const handleUploadAttachment = async (file: File) => {
|
||||
return await uploadAttachmentFile(file, {
|
||||
id: activityId,
|
||||
targetObjectNameSingular: activityObjectNameSingular,
|
||||
});
|
||||
if (!result?.data?.uploadFile) {
|
||||
throw new Error("Couldn't upload Image");
|
||||
}
|
||||
return getFileAbsoluteURI(result.data.uploadFile);
|
||||
};
|
||||
|
||||
const prepareBody = (newStringifiedBody: string) => {
|
||||
@ -152,8 +139,6 @@ export const RichTextEditor = ({
|
||||
const imageProps = block.props;
|
||||
const imageUrl = new URL(imageProps.url);
|
||||
|
||||
imageUrl.searchParams.delete('token');
|
||||
|
||||
return {
|
||||
...block,
|
||||
props: {
|
||||
@ -284,65 +269,19 @@ export const RichTextEditor = ({
|
||||
}
|
||||
}, [activity, activityBody]);
|
||||
|
||||
const handleEditorBuiltInUploadFile = async (file: File) => {
|
||||
const { attachementAbsoluteURL } = await handleUploadAttachment(file);
|
||||
|
||||
return attachementAbsoluteURL;
|
||||
};
|
||||
|
||||
const editor = useCreateBlockNote({
|
||||
initialContent: initialBody,
|
||||
domAttributes: { editor: { class: 'editor' } },
|
||||
schema: BLOCK_SCHEMA,
|
||||
uploadFile: handleUploadAttachment,
|
||||
uploadFile: handleEditorBuiltInUploadFile,
|
||||
});
|
||||
|
||||
const handleImagePaste = async (event: ClipboardEvent) => {
|
||||
const clipboardItems = event.clipboardData?.items;
|
||||
|
||||
if (isDefined(clipboardItems)) {
|
||||
for (let i = 0; i < clipboardItems.length; i++) {
|
||||
if (clipboardItems[i].kind === 'file') {
|
||||
const isImage = clipboardItems[i].type.match('^image/');
|
||||
const pastedFile = clipboardItems[i].getAsFile();
|
||||
if (!pastedFile) {
|
||||
return;
|
||||
}
|
||||
|
||||
const attachmentUrl = await handleUploadAttachment(pastedFile);
|
||||
|
||||
if (!attachmentUrl) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDefined(isImage)) {
|
||||
editor?.insertBlocks(
|
||||
[
|
||||
{
|
||||
type: 'image',
|
||||
props: {
|
||||
url: attachmentUrl,
|
||||
},
|
||||
},
|
||||
],
|
||||
editor?.getTextCursorPosition().block,
|
||||
'after',
|
||||
);
|
||||
} else {
|
||||
editor?.insertBlocks(
|
||||
[
|
||||
{
|
||||
type: 'file',
|
||||
props: {
|
||||
url: attachmentUrl,
|
||||
fileType: getFileType(pastedFile.name),
|
||||
name: pastedFile.name,
|
||||
},
|
||||
},
|
||||
],
|
||||
editor?.getTextCursorPosition().block,
|
||||
'after',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
useScopedHotkeys(
|
||||
Key.Escape,
|
||||
() => {
|
||||
@ -427,7 +366,6 @@ export const RichTextEditor = ({
|
||||
<BlockEditor
|
||||
onFocus={handleBlockEditorFocus}
|
||||
onBlur={handlerBlockEditorBlur}
|
||||
onPaste={handleImagePaste}
|
||||
onChange={handleEditorChange}
|
||||
editor={editor}
|
||||
/>
|
||||
|
@ -7,7 +7,9 @@ import { getActivityTargetObjectFieldIdName } from '@/activities/utils/getActivi
|
||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { FileFolder, useUploadFileMutation } from '~/generated/graphql';
|
||||
import { getFileAbsoluteURI } from '~/utils/file/getFileAbsoluteURI';
|
||||
|
||||
// Note: This is probably not the right way to do this.
|
||||
export const computePathWithoutToken = (attachmentPath: string): string => {
|
||||
@ -36,8 +38,8 @@ export const useUploadAttachmentFile = () => {
|
||||
|
||||
const attachmentPath = result?.data?.uploadFile;
|
||||
|
||||
if (!attachmentPath) {
|
||||
return;
|
||||
if (!isNonEmptyString(attachmentPath)) {
|
||||
throw new Error("Couldn't upload the attachment.");
|
||||
}
|
||||
|
||||
const targetableObjectFieldIdName = getActivityTargetObjectFieldIdName({
|
||||
@ -55,6 +57,10 @@ export const useUploadAttachmentFile = () => {
|
||||
} as Partial<Attachment>;
|
||||
|
||||
await createOneAttachment(attachmentToCreate);
|
||||
|
||||
const attachementAbsoluteURL = getFileAbsoluteURI(attachmentPath);
|
||||
|
||||
return { attachementAbsoluteURL };
|
||||
};
|
||||
|
||||
return { uploadAttachmentFile };
|
||||
|
Loading…
Reference in New Issue
Block a user