From 532303e7779818f82ef26aa1a5ac94bff2658968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=ED=98=84=EC=A1=B0?= Date: Mon, 7 Oct 2024 16:19:34 +0900 Subject: [PATCH] =?UTF-8?q?Refactor:=20=ED=8C=8C=EC=9D=BC=20=EC=97=85?= =?UTF-8?q?=EB=A1=9C=EB=93=9C=20presinged=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/ImagePreSignedForm/index.tsx | 75 +++++-- .../WorkspaceDropdownMenu/index.tsx | 189 ++++-------------- 2 files changed, 98 insertions(+), 166 deletions(-) diff --git a/frontend/src/components/ImagePreSignedForm/index.tsx b/frontend/src/components/ImagePreSignedForm/index.tsx index 9cd6ae9..4e756e1 100644 --- a/frontend/src/components/ImagePreSignedForm/index.tsx +++ b/frontend/src/components/ImagePreSignedForm/index.tsx @@ -5,6 +5,7 @@ import useAuthStore from '@/stores/useAuthStore'; import { CircleCheckBig, CircleDashed, CircleX, X } from 'lucide-react'; import { FixedSizeList } from 'react-window'; import useUploadFiles from '@/hooks/useUploadFiles'; +import useUploadImagePresignedQuery from '@/queries/images/useUploadImagePresignedQuery'; import { unzipFilesWithPath, extractFilesRecursivelyWithPath } from '@/utils/fileUtils'; interface ImagePreSignedFormProps { @@ -34,9 +35,11 @@ export default function ImagePreSignedForm({ const [isUploaded, setIsUploaded] = useState(false); const [isFailed, setIsFailed] = useState(false); const [progress, setProgress] = useState(0); + const [uploadStatus, setUploadStatus] = useState<(boolean | null)[]>([]); + // Ensure to destructure the uploadFiles function properly from the hook const { uploadFiles } = useUploadFiles(); - + const uploadImageFile = useUploadImagePresignedQuery(); const handleClose = () => { onClose(); setFiles([]); @@ -45,6 +48,7 @@ export default function ImagePreSignedForm({ setIsUploaded(false); setIsFailed(false); setProgress(0); + setUploadStatus([]); }; const handleRefetch = () => { @@ -65,6 +69,7 @@ export default function ImagePreSignedForm({ } setFiles((prevFiles) => [...prevFiles, ...processedFiles]); + setUploadStatus((prevStatus) => [...prevStatus, ...processedFiles.map(() => null)]); } event.target.value = ''; @@ -103,6 +108,7 @@ export default function ImagePreSignedForm({ } setFiles((prevFiles) => [...prevFiles, ...processedFiles]); + setUploadStatus((prevStatus) => [...prevStatus, ...processedFiles.map(() => null)]); } else { const droppedFiles = event.dataTransfer.files; if (droppedFiles) { @@ -111,12 +117,14 @@ export default function ImagePreSignedForm({ processedFiles.push({ path: file.name, file }); } setFiles((prevFiles) => [...prevFiles, ...processedFiles]); + setUploadStatus((prevStatus) => [...prevStatus, ...processedFiles.map(() => null)]); } } }; const handleRemoveFile = (index: number) => { setFiles(files.filter((_, i) => i !== index)); + setUploadStatus((prevStatus) => prevStatus.filter((_, i) => i !== index)); }; const handleUpload = async () => { @@ -138,19 +146,52 @@ export default function ImagePreSignedForm({ } } - try { - await uploadFiles({ - files: finalFiles, - projectId, - folderId, - memberId, - onProgress: (progressValue) => setProgress(progressValue), - }); - setIsUploaded(true); - handleRefetch(); - } catch (error) { - setIsFailed(true); - console.error('업로드 실패:', error); + if (uploadType === 'file') { + uploadImageFile.mutate( + { + memberId, + projectId, + folderId, + files: finalFiles.map(({ file }) => file), // Extract only the file + progressCallback: (index: number) => { + setUploadStatus((prevStatus) => { + const newStatus = [...prevStatus]; + newStatus[index] = true; // Mark as uploaded + return newStatus; + }); + }, + }, + { + onSuccess: () => { + handleRefetch(); + setIsUploaded(true); + }, + onError: () => { + setIsFailed(true); + setUploadStatus((prevStatus) => prevStatus.map((status) => (status === null ? false : status))); + }, + } + ); + } else { + try { + await uploadFiles({ + files: finalFiles, // Pass the files with path and file + projectId, + folderId, + memberId, + onProgress: (progressValue: number) => { + setProgress(progressValue); + }, + }); + + setUploadStatus(finalFiles.map(() => true)); + setIsUploaded(true); + handleRefetch(); + } catch (error) { + setIsFailed(true); + setUploadStatus(finalFiles.map(() => false)); + console.error('업로드 실패:', error); + } } } }; @@ -176,7 +217,7 @@ export default function ImagePreSignedForm({ type="file" webkitdirectory={uploadType === 'folder' ? '' : undefined} multiple={uploadType !== 'zip'} - accept={uploadType === 'zip' ? '.zip' : undefined} + accept={uploadType === 'zip' ? '.zip' : uploadType === 'file' ? '.jpg,.jpeg,.png' : undefined} className="absolute inset-0 h-full w-full cursor-pointer opacity-0" onChange={handleChange} /> @@ -212,13 +253,13 @@ export default function ImagePreSignedForm({ {files[index].path} {isUploading ? (
- {isUploaded ? ( + {uploadStatus[index] === true ? ( - ) : isFailed ? ( + ) : uploadStatus[index] === false ? ( void; }) { - const [isOpenUploadFile, setIsOpenUploadFile] = React.useState(false); + const [isOpenUpload, setIsOpenUpload] = React.useState(false); const [fileCount, setFileCount] = React.useState(0); - const [isOpenUploadPresigned, setIsOpenUploadPresigned] = React.useState(false); - const [presignedCount, setPresignedCount] = React.useState(0); - const [isOpenUploadFolderFile, setIsOpenUploadFolderFile] = React.useState(false); - const [isOpenUploadFolder, setIsOpenUploadFolder] = React.useState(false); - const [isOpenUploadZip, setIsOpenUploadZip] = React.useState(false); - const [isOpenTestUpload, setIsOpenTestUpload] = React.useState(false); + const [uploadType, setUploadType] = React.useState<'file' | 'folder' | 'zip'>('file'); - const uploadImageZipMutation = useUploadImageZipQuery(); - const uploadImageFolderFileMutation = useUploadImageFolderFileQuery(); - const uploadImageFileMutation = useUploadImageFileQuery(); - const uploadImageFolderMutation = useUploadImageFolderQuery(); - - const handleCloseUploadFile = () => setIsOpenUploadFile(false); - const handleCloseUploadFolderFile = () => setIsOpenUploadFolderFile(false); - const handleCloseUploadFolder = () => setIsOpenUploadFolder(false); - const handleCloseUploadZip = () => setIsOpenUploadZip(false); - const handleCloseTestUpload = () => setIsOpenTestUpload(false); + const handleCloseUpload = () => setIsOpenUpload(false); const handleFileCount = (fileCount: number) => { setFileCount(fileCount); @@ -56,148 +36,59 @@ export default function WorkspaceDropdownMenu({ - console.log('프로젝트 이름 수정')}>프로젝트 이름 수정 + { + setUploadType('file'); + setIsOpenUpload(true); + }} + > + 파일 업로드 + - setIsOpenUploadFile(true)}>파일 업로드 - setIsOpenUploadPresigned(true)}> - 파일 업로드 (PresignedUrl 이용) + { + setUploadType('folder'); + setIsOpenUpload(true); + }} + > + 폴더 업로드 - setIsOpenUploadFolderFile(true)}> - 폴더 업로드 (파일 업로드 API 이용) + + { + setUploadType('zip'); + setIsOpenUpload(true); + }} + > + 압축 파일 업로드 - setIsOpenUploadFolder(true)}> - 폴더 업로드 (백엔드 구현 필요) - - setIsOpenUploadZip(true)}>폴더 압축파일 업로드 - setIsOpenTestUpload(true)}> - 테스트 업로드 (PresignedUrl 이용) - {' '} - {/* 새로운 메뉴 항목 추가 */} - {/* 기존 Dialogs */} - - - 0 ? `파일 업로드 (${fileCount})` : '파일 업로드'} /> - setFileCount(fileCount)} - projectId={projectId} - folderId={folderId} - uploadImageZipMutation={uploadImageZipMutation} - uploadImageFolderFileMutation={uploadImageFolderFileMutation} - uploadImageFileMutation={uploadImageFileMutation} - uploadImageFolderMutation={uploadImageFolderMutation} - /> - - - - 0 ? `파일 업로드 PreSigned (${presignedCount})` : '파일 업로드 PreSigned'} + title={ + fileCount > 0 + ? `파일 업로드 (${fileCount})` + : uploadType === 'file' + ? '파일 업로드' + : uploadType === 'folder' + ? '폴더 업로드' + : '압축 파일 업로드' + } /> - setIsOpenUploadPresigned(false)} - onRefetch={onRefetch} - onFileCount={(fileCount: number) => setPresignedCount(fileCount)} - projectId={projectId} - folderId={folderId} - /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - {/* 테스트 업로드 Dialog */} - - - - setFileCount(fileCount)} + onFileCount={handleFileCount} projectId={projectId} folderId={folderId} - uploadType="folder" // zip flie 가능 + uploadType={uploadType} />