Skip to content

Commit 4cb15cc

Browse files
committed
address comments
1 parent e13bd2f commit 4cb15cc

7 files changed

Lines changed: 241 additions & 124 deletions

File tree

apps/sim/app/api/workspaces/[id]/files/move/route.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import { createLogger } from '@sim/logger'
2+
import { getPostgresErrorCode } from '@sim/utils/errors'
23
import { type NextRequest, NextResponse } from 'next/server'
34
import { moveWorkspaceFileItemsContract } from '@/lib/api/contracts/workspace-file-folders'
45
import { parseRequest } from '@/lib/api/server'
56
import { getSession } from '@/lib/auth'
67
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
78
import {
89
moveWorkspaceFileItems,
10+
WorkspaceFileFolderConflictError,
911
WorkspaceFileMoveConflictError,
1012
} from '@/lib/uploads/contexts/workspace'
1113
import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils'
@@ -42,9 +44,24 @@ export const POST = withRouteHandler(
4244
})
4345
} catch (error) {
4446
logger.error('Failed to move workspace file items:', error)
47+
if (
48+
error instanceof WorkspaceFileMoveConflictError ||
49+
error instanceof WorkspaceFileFolderConflictError
50+
) {
51+
return NextResponse.json({ success: false, error: error.message }, { status: 409 })
52+
}
53+
if (getPostgresErrorCode(error) === '23505') {
54+
return NextResponse.json(
55+
{
56+
success: false,
57+
error: 'A file or folder with this name already exists in the destination folder',
58+
},
59+
{ status: 409 }
60+
)
61+
}
4562
return NextResponse.json(
4663
{ success: false, error: error instanceof Error ? error.message : 'Failed to move items' },
47-
{ status: error instanceof WorkspaceFileMoveConflictError ? 409 : 400 }
64+
{ status: 400 }
4865
)
4966
}
5067
}

apps/sim/app/workspace/[workspaceId]/files/files.tsx

Lines changed: 73 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,73 @@ export function Files() {
568568
[descendantFolderIdsByFolderId]
569569
)
570570

571+
const uploadFiles = useCallback(
572+
async (filesToUpload: File[], targetFolderId = currentFolderId) => {
573+
if (!workspaceId || filesToUpload.length === 0 || !canEdit) return
574+
575+
const oversized: string[] = []
576+
const sizeFiltered = filesToUpload.filter((f) => {
577+
if (f.size > MAX_WORKSPACE_FILE_SIZE) {
578+
oversized.push(f.name)
579+
return false
580+
}
581+
return true
582+
})
583+
if (oversized.length > 0) {
584+
toast.error(
585+
oversized.length === 1
586+
? `${oversized[0]} exceeds the 5 GiB upload limit`
587+
: `${oversized.length} files exceed the 5 GiB upload limit`
588+
)
589+
}
590+
591+
const unsupported: string[] = []
592+
const allowedFiles = sizeFiltered.filter((f) => {
593+
const ext = getFileExtension(f.name)
594+
const ok = SUPPORTED_EXTENSIONS.includes(ext as (typeof SUPPORTED_EXTENSIONS)[number])
595+
if (!ok) unsupported.push(f.name)
596+
return ok
597+
})
598+
599+
if (unsupported.length > 0) {
600+
logger.warn('Unsupported file types skipped:', unsupported)
601+
}
602+
603+
if (allowedFiles.length === 0) return
604+
605+
try {
606+
setUploading(true)
607+
setUploadProgress({ completed: 0, total: allowedFiles.length, currentPercent: 0 })
608+
609+
for (let i = 0; i < allowedFiles.length; i++) {
610+
try {
611+
await uploadFile.mutateAsync({
612+
workspaceId,
613+
file: allowedFiles[i],
614+
folderId: targetFolderId,
615+
onProgress: ({ percent }) => {
616+
setUploadProgress((prev) => ({ ...prev, currentPercent: percent }))
617+
},
618+
})
619+
setUploadProgress({
620+
completed: i + 1,
621+
total: allowedFiles.length,
622+
currentPercent: 0,
623+
})
624+
} catch (err) {
625+
logger.error('Error uploading file:', err)
626+
}
627+
}
628+
} catch (err) {
629+
logger.error('Error uploading file:', err)
630+
} finally {
631+
setUploading(false)
632+
setUploadProgress({ completed: 0, total: 0, currentPercent: 0 })
633+
}
634+
},
635+
[workspaceId, canEdit, currentFolderId, uploadFile.mutateAsync]
636+
)
637+
571638
const rowDragDropConfig = useMemo<RowDragDropConfig>(
572639
() => ({
573640
activeDropTargetId,
@@ -688,70 +755,6 @@ export function Files() {
688755
]
689756
)
690757

691-
async function uploadFiles(filesToUpload: File[], targetFolderId = currentFolderId) {
692-
if (!workspaceId || filesToUpload.length === 0 || !canEdit) return
693-
694-
const oversized: string[] = []
695-
const sizeFiltered = filesToUpload.filter((f) => {
696-
if (f.size > MAX_WORKSPACE_FILE_SIZE) {
697-
oversized.push(f.name)
698-
return false
699-
}
700-
return true
701-
})
702-
if (oversized.length > 0) {
703-
toast.error(
704-
oversized.length === 1
705-
? `${oversized[0]} exceeds the 5 GiB upload limit`
706-
: `${oversized.length} files exceed the 5 GiB upload limit`
707-
)
708-
}
709-
710-
const unsupported: string[] = []
711-
const allowedFiles = sizeFiltered.filter((f) => {
712-
const ext = getFileExtension(f.name)
713-
const ok = SUPPORTED_EXTENSIONS.includes(ext as (typeof SUPPORTED_EXTENSIONS)[number])
714-
if (!ok) unsupported.push(f.name)
715-
return ok
716-
})
717-
718-
if (unsupported.length > 0) {
719-
logger.warn('Unsupported file types skipped:', unsupported)
720-
}
721-
722-
if (allowedFiles.length === 0) return
723-
724-
try {
725-
setUploading(true)
726-
setUploadProgress({ completed: 0, total: allowedFiles.length, currentPercent: 0 })
727-
728-
for (let i = 0; i < allowedFiles.length; i++) {
729-
try {
730-
await uploadFile.mutateAsync({
731-
workspaceId,
732-
file: allowedFiles[i],
733-
folderId: targetFolderId,
734-
onProgress: ({ percent }) => {
735-
setUploadProgress((prev) => ({ ...prev, currentPercent: percent }))
736-
},
737-
})
738-
setUploadProgress({
739-
completed: i + 1,
740-
total: allowedFiles.length,
741-
currentPercent: 0,
742-
})
743-
} catch (err) {
744-
logger.error('Error uploading file:', err)
745-
}
746-
}
747-
} catch (err) {
748-
logger.error('Error uploading file:', err)
749-
} finally {
750-
setUploading(false)
751-
setUploadProgress({ completed: 0, total: 0, currentPercent: 0 })
752-
}
753-
}
754-
755758
const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
756759
const list = e.target.files
757760
if (!list || list.length === 0) return
@@ -819,12 +822,16 @@ export function Files() {
819822
if (target.fileIds.includes(fileIdFromRouteRef.current ?? '')) {
820823
setIsDirty(false)
821824
setSaveStatus('idle')
822-
router.push(`/workspace/${workspaceId}/files`)
825+
router.push(
826+
currentFolderId
827+
? `/workspace/${workspaceId}/files?folderId=${currentFolderId}`
828+
: `/workspace/${workspaceId}/files`
829+
)
823830
}
824831
} catch (err) {
825832
logger.error('Failed to delete file:', err)
826833
}
827-
}, [workspaceId, router, bulkArchiveItems, deleteFile])
834+
}, [workspaceId, router, currentFolderId, bulkArchiveItems, deleteFile])
828835

829836
const isDirtyRef = useRef(isDirty)
830837
isDirtyRef.current = isDirty

0 commit comments

Comments
 (0)