From 062bbd57a36b69111039ea87790e47a660df4c34 Mon Sep 17 00:00:00 2001 From: Jeet Desai <52026385+jeet1desai@users.noreply.github.com> Date: Mon, 22 Jan 2024 21:30:18 +0530 Subject: [PATCH] drag and drop on files tab (#3432) * #3345 drag and drop on files tab * #3432 resolved comments on drag and drop feature --- .../files/components/AttachmentList.tsx | 71 ++++++++---- .../files/components/Attachments.tsx | 101 +++++++----------- .../activities/files/components/DropZone.tsx | 96 +++++++++++++++++ .../files/hooks/useUploadAttachmentFile.tsx | 54 ++++++++++ 4 files changed, 239 insertions(+), 83 deletions(-) create mode 100644 packages/twenty-front/src/modules/activities/files/components/DropZone.tsx create mode 100644 packages/twenty-front/src/modules/activities/files/hooks/useUploadAttachmentFile.tsx diff --git a/packages/twenty-front/src/modules/activities/files/components/AttachmentList.tsx b/packages/twenty-front/src/modules/activities/files/components/AttachmentList.tsx index 3aa4a5dac..9e885f8b8 100644 --- a/packages/twenty-front/src/modules/activities/files/components/AttachmentList.tsx +++ b/packages/twenty-front/src/modules/activities/files/components/AttachmentList.tsx @@ -1,11 +1,15 @@ -import { ReactElement } from 'react'; +import { ReactElement, useState } from 'react'; import styled from '@emotion/styled'; +import { DropZone } from '@/activities/files/components/DropZone'; +import { useUploadAttachmentFile } from '@/activities/files/hooks/useUploadAttachmentFile'; import { Attachment } from '@/activities/files/types/Attachment'; +import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity'; import { AttachmentRow } from './AttachmentRow'; type AttachmentListProps = { + targetableObject: ActivityTargetableObject; title: string; attachments: Attachment[]; button?: ReactElement | false; @@ -17,7 +21,8 @@ const StyledContainer = styled.div` display: flex; flex-direction: column; justify-content: center; - padding: 8px 24px; + padding: ${({ theme }) => theme.spacing(2, 6, 6)}; + height: 100%; `; const StyledTitleBar = styled.h3` @@ -51,26 +56,50 @@ const StyledAttachmentContainer = styled.div` width: 100%; `; +const StyledDropZoneContainer = styled.div` + height: 100%; + width: 100%; +`; + export const AttachmentList = ({ + targetableObject, title, attachments, button, -}: AttachmentListProps) => ( - <> - {attachments && attachments.length > 0 && ( - - - - {title} {attachments.length} - - {button} - - - {attachments.map((attachment) => ( - - ))} - - - )} - -); +}: AttachmentListProps) => { + const { uploadAttachmentFile } = useUploadAttachmentFile(); + const [isDraggingFile, setIsDraggingFile] = useState(false); + + const onUploadFile = async (file: File) => { + await uploadAttachmentFile(file, targetableObject); + }; + + return ( + <> + {attachments && attachments.length > 0 && ( + + + + {title} {attachments.length} + + {button} + + setIsDraggingFile(true)}> + {isDraggingFile ? ( + + ) : ( + + {attachments.map((attachment) => ( + + ))} + + )} + + + )} + + ); +}; diff --git a/packages/twenty-front/src/modules/activities/files/components/Attachments.tsx b/packages/twenty-front/src/modules/activities/files/components/Attachments.tsx index 27225559c..7b80a3d6f 100644 --- a/packages/twenty-front/src/modules/activities/files/components/Attachments.tsx +++ b/packages/twenty-front/src/modules/activities/files/components/Attachments.tsx @@ -1,20 +1,14 @@ -import { ChangeEvent, useRef } from 'react'; +import { ChangeEvent, useRef, useState } from 'react'; import styled from '@emotion/styled'; import { isNonEmptyArray } from '@sniptt/guards'; -import { useRecoilValue } from 'recoil'; import { AttachmentList } from '@/activities/files/components/AttachmentList'; +import { DropZone } from '@/activities/files/components/DropZone'; import { useAttachments } from '@/activities/files/hooks/useAttachments'; -import { Attachment } from '@/activities/files/types/Attachment'; -import { getFileType } from '@/activities/files/utils/getFileType'; +import { useUploadAttachmentFile } from '@/activities/files/hooks/useUploadAttachmentFile'; import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity'; -import { getActivityTargetObjectFieldIdName } from '@/activities/utils/getTargetObjectFilterFieldName'; -import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; -import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; -import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord'; import { IconPlus } from '@/ui/display/icon'; import { Button } from '@/ui/input/button/components/Button'; -import { FileFolder, useUploadFileMutation } from '~/generated/graphql'; const StyledTaskGroupEmptyContainer = styled.div` align-items: center; @@ -24,10 +18,7 @@ const StyledTaskGroupEmptyContainer = styled.div` flex-direction: column; gap: ${({ theme }) => theme.spacing(2)}; justify-content: center; - padding-bottom: ${({ theme }) => theme.spacing(16)}; - padding-left: ${({ theme }) => theme.spacing(4)}; - padding-right: ${({ theme }) => theme.spacing(4)}; - padding-top: ${({ theme }) => theme.spacing(3)}; + height: 100%; `; const StyledEmptyTaskGroupTitle = styled.div` @@ -57,21 +48,21 @@ const StyledFileInput = styled.input` display: none; `; +const StyledDropZoneContainer = styled.div` + height: 100%; + padding: ${({ theme }) => theme.spacing(6)}; +`; + export const Attachments = ({ targetableObject, }: { targetableObject: ActivityTargetableObject; }) => { const inputFileRef = useRef(null); - const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const { attachments } = useAttachments(targetableObject); + const { uploadAttachmentFile } = useUploadAttachmentFile(); - const [uploadFile] = useUploadFileMutation(); - - const { createOneRecord: createOneAttachment } = - useCreateOneRecord({ - objectNameSingular: CoreObjectNameSingular.Attachment, - }); + const [isDraggingFile, setIsDraggingFile] = useState(false); const handleFileChange = (e: ChangeEvent) => { if (e.target.files) onUploadFile?.(e.target.files[0]); @@ -82,52 +73,37 @@ export const Attachments = ({ }; const onUploadFile = async (file: File) => { - const result = await uploadFile({ - variables: { - file, - fileFolder: FileFolder.Attachment, - }, - }); - - const attachmentUrl = result?.data?.uploadFile; - - if (!attachmentUrl) { - return; - } - - const targetableObjectFieldIdName = getActivityTargetObjectFieldIdName({ - nameSingular: targetableObject.targetObjectNameSingular, - }); - - const attachmentToCreate = { - authorId: currentWorkspaceMember?.id, - name: file.name, - fullPath: attachmentUrl, - type: getFileType(file.name), - [targetableObjectFieldIdName]: targetableObject.id, - }; - - await createOneAttachment(attachmentToCreate); + await uploadAttachmentFile(file, targetableObject); }; if (!isNonEmptyArray(attachments)) { return ( - - - - No files yet - Upload one: -