diff --git a/frontend/src/api/lablingApi.ts b/frontend/src/api/lablingApi.ts index 0c922c9..efd91a9 100644 --- a/frontend/src/api/lablingApi.ts +++ b/frontend/src/api/lablingApi.ts @@ -11,5 +11,5 @@ export async function saveImageLabels( } export async function runAutoLabel(projectId: number, modelId = 1) { - return api.post(`/projects/${projectId}/auto`, { modelId }).then(({ data }) => data); + return api.post(`/projects/${projectId}/auto`, { modelId }, { timeout: 0 }).then(({ data }) => data); } diff --git a/frontend/src/components/ImageCanvas/LabelRect.tsx b/frontend/src/components/ImageCanvas/LabelRect.tsx index a6cf656..f0b3402 100644 --- a/frontend/src/components/ImageCanvas/LabelRect.tsx +++ b/frontend/src/components/ImageCanvas/LabelRect.tsx @@ -1,4 +1,5 @@ import { Label } from '@/types'; +import rectSort from '@/utils/rectSort'; import Konva from 'konva'; import { useEffect, useRef } from 'react'; import { Line, Transformer } from 'react-konva'; @@ -39,8 +40,9 @@ export default function LabelRect({ [info.coordinates[0][0] * scale.x + rect.x, info.coordinates[0][1] * scale.y + rect.y], [info.coordinates[1][0] * scale.x + rect.x, info.coordinates[1][1] * scale.y + rect.y], ]; + const sortedPoints = rectSort(points as [[number, number], [number, number]]); - setLabel(points); + setLabel(sortedPoints); rectRef.current?.setPosition({ x: 0, y: 0 }); rectRef.current?.scale({ x: 1, y: 1 }); }; diff --git a/frontend/src/components/ImageCanvas/index.tsx b/frontend/src/components/ImageCanvas/index.tsx index 9c4783a..568a8f1 100644 --- a/frontend/src/components/ImageCanvas/index.tsx +++ b/frontend/src/components/ImageCanvas/index.tsx @@ -19,6 +19,7 @@ import { useQueryClient } from '@tanstack/react-query'; import useSaveImageLabelsQuery from '@/queries/projects/useSaveImageLabelsQuery'; import { useToast } from '@/hooks/use-toast'; import CommentLabel from './CommentLabel'; +import rectSort from '@/utils/rectSort'; export default function ImageCanvas() { const { project, folderId, categories } = useProjectStore(); @@ -188,11 +189,11 @@ export default function ImageCanvas() { const endDrawRect = () => { if (drawState !== 'rect' || rectPoints.length === 0) return; + setRectPoints([]); if (rectPoints[0][0] === rectPoints[1][0] && rectPoints[0][1] === rectPoints[1][1]) { - setRectPoints([]); return; } - setRectPoints([]); + const sortedPoints = rectSort(rectPoints as [[number, number], [number, number]]); const color = Math.floor(Math.random() * 0xffffff) .toString(16) @@ -203,7 +204,7 @@ export default function ImageCanvas() { categoryId: categories[0]!.id, type: 'rectangle', color: `#${color}`, - coordinates: rectPoints, + coordinates: sortedPoints, }); setDrawState('pointer'); setSelectedLabelId(id); diff --git a/frontend/src/components/ImageUploadPresignedModal/index.tsx b/frontend/src/components/ImageUploadPresignedModal/index.tsx index bf134e3..11a641d 100644 --- a/frontend/src/components/ImageUploadPresignedModal/index.tsx +++ b/frontend/src/components/ImageUploadPresignedModal/index.tsx @@ -6,7 +6,7 @@ import ImageUploadPresingedForm from '@/components/ImageUploadPresignedModal/Ima export default function ImageUploadPresignedModal({ projectId, folderId }: { projectId: number; folderId: number }) { const [isOpen, setIsOpen] = React.useState(false); const [fileCount, setFileCount] = React.useState(0); - + const handleOpen = () => setIsOpen(true); const handleClose = () => setIsOpen(false); const handleFileCount = (fileCount: number) => { @@ -27,7 +27,7 @@ export default function ImageUploadPresignedModal({ projectId, folderId }: { pro - 0 ? `파일 업로드 (${fileCount}) PreSigned` : '파일 업로드 PreSigned'} /> + 0 ? `파일 업로드 PreSigned (${fileCount})` : '파일 업로드 PreSigned'} />
카테고리
- - 직접 입력 - 파일로 입력 + + + 직접 입력 + + + 파일로 입력 +
@@ -192,7 +202,7 @@ export default function ProjectCreateForm({ onSubmit }: { onSubmit: (data: Proje
handleDrop(event, field.onChange)} onClick={() => fileInputRef.current?.click()} > -

- 파일을 업로드하려면 여기를 클릭하거나 파일을 드래그하여 여기에 놓으세요. -

+ {isDragging ? ( +

드래그한 파일을 여기에 놓으세요

+ ) : ( +

+ 파일을 업로드하려면 여기를 클릭하거나 +
+ 파일을 드래그하여 여기에 놓으세요. +

+ )} diff --git a/frontend/src/components/WorkspaceDropdownMenu/index.tsx b/frontend/src/components/WorkspaceDropdownMenu/index.tsx index d2c271d..999d22f 100644 --- a/frontend/src/components/WorkspaceDropdownMenu/index.tsx +++ b/frontend/src/components/WorkspaceDropdownMenu/index.tsx @@ -12,7 +12,7 @@ import ImageUploadFileForm from '../ImageUploadFileModal/ImageUploadFileForm'; import ImageUploadFolderFileForm from '../ImageUploadFolderFileModal/ImageUploadFolderFileForm'; import ImageUploadFolderForm from '../ImageUploadFolderModal/ImageUploadFolderForm'; import ImageUploadZipForm from '../ImageUploadZipModal/ImageUploadZipForm'; -import ImageUploadPresignedForm from '../ImageUploadPresignedModal/ImageUploadPresignedForm.tsx' +import ImageUploadPresignedForm from '../ImageUploadPresignedModal/ImageUploadPresignedForm.tsx'; export default function WorkspaceDropdownMenu({ projectId, @@ -25,9 +25,10 @@ export default function WorkspaceDropdownMenu({ }) { const [isOpenUploadFile, setIsOpenUploadFile] = 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 [isOpenUploadPresigned, setIsOpenUploadPresigned] = React.useState(false); const [isOpenUploadZip, setIsOpenUploadZip] = React.useState(false); const handleOpenUploadFile = () => setIsOpenUploadFile(true); @@ -36,6 +37,20 @@ export default function WorkspaceDropdownMenu({ setIsOpenUploadFile(false); }; + const handleFileCount = (fileCount: number) => { + setFileCount(fileCount); + }; + + const handleOpenUploadPresigned = () => setIsOpenUploadPresigned(true); + + const handleCloseUploadPresigned = () => { + setIsOpenUploadPresigned(false); + }; + + const handlePresignedCount = (fileCount: number) => { + setPresignedCount(fileCount); + }; + const handleOpenUploadFolderFile = () => setIsOpenUploadFolderFile(true); const handleCloseUploadFolderFile = () => { @@ -48,22 +63,12 @@ export default function WorkspaceDropdownMenu({ setIsOpenUploadFolder(false); }; - const handleOpenUploadPresigned = () => setIsOpenUploadPresigned(true); - - const handleCloseUploadPresigned = () => { - setIsOpenUploadPresigned(false); - }; - const handleOpenUploadZip = () => setIsOpenUploadZip(true); const handleCloseUploadZip = () => { setIsOpenUploadZip(false); }; - const handleFileCount = (fileCount: number) => { - setFileCount(fileCount); - }; - return ( <> @@ -83,9 +88,9 @@ export default function WorkspaceDropdownMenu({ 파일 업로드 + 파일 업로드 (PresignedUrl 이용) 폴더 업로드 (파일 업로드 API 이용) 폴더 업로드 (백엔드 구현 필요) - 폴더 업로드 (PresignedUrl 이용) 폴더 압축파일 업로드 @@ -107,6 +112,25 @@ export default function WorkspaceDropdownMenu({ + + + + 0 ? `파일 업로드 PreSigned (${presignedCount})` : '파일 업로드 PreSigned'} + /> + + + + - - - - - - - - { + it('should sort coordinates when first point is top-left and second point is bottom-right', () => { + const result = rectSort([ + [1, 2], + [3, 4], + ]); + expect(result).toEqual([ + [1, 2], + [3, 4], + ]); + }); + + it('should sort coordinates when first point is bottom-right and second point is top-left', () => { + const result = rectSort([ + [3, 4], + [1, 2], + ]); + expect(result).toEqual([ + [1, 2], + [3, 4], + ]); + }); + + it('should sort coordinates when first point is bottom-left and second point is top-right', () => { + const result = rectSort([ + [1, 4], + [3, 2], + ]); + expect(result).toEqual([ + [1, 2], + [3, 4], + ]); + }); + + it('should sort coordinates when first point is top-right and second point is bottom-left', () => { + const result = rectSort([ + [3, 2], + [1, 4], + ]); + expect(result).toEqual([ + [1, 2], + [3, 4], + ]); + }); +}); diff --git a/frontend/src/utils/rectSort.ts b/frontend/src/utils/rectSort.ts new file mode 100644 index 0000000..ba43c99 --- /dev/null +++ b/frontend/src/utils/rectSort.ts @@ -0,0 +1,9 @@ +export default function rectSort([[x1, y1], [x2, y2]]: [[number, number], [number, number]]): [ + [number, number], + [number, number], +] { + return [ + [Math.min(x1, x2), Math.min(y1, y2)], + [Math.max(x1, x2), Math.max(y1, y2)], + ]; +}