From e4ee7230d1427bd50e7e0edac5effd1fdd4c7733 Mon Sep 17 00:00:00 2001 From: Geert Rademakes Date: Wed, 13 Aug 2025 17:04:20 +0200 Subject: [PATCH] feat(upload): include root folder option in S3 folder dropdown and support empty targetFolder (root) on backend --- packages/backend/src/routes/music.ts | 3 ++- packages/backend/src/services/s3Service.ts | 7 +++++-- packages/frontend/src/components/MusicUpload.tsx | 8 ++++---- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/backend/src/routes/music.ts b/packages/backend/src/routes/music.ts index cea66ef..b4feb82 100644 --- a/packages/backend/src/routes/music.ts +++ b/packages/backend/src/routes/music.ts @@ -226,7 +226,8 @@ router.get('/files', async (req, res) => { router.get('/folders', async (req, res) => { try { const folders = await s3Service.listAllFolders(''); - res.json({ folders }); + // Include root option as empty string + res.json({ folders: [''] as string[] .concat(folders) }); } catch (error) { console.error('Error fetching S3 folders:', error); res.status(500).json({ error: 'Failed to fetch S3 folders' }); diff --git a/packages/backend/src/services/s3Service.ts b/packages/backend/src/services/s3Service.ts index 0e980b5..7ed7da8 100644 --- a/packages/backend/src/services/s3Service.ts +++ b/packages/backend/src/services/s3Service.ts @@ -83,8 +83,11 @@ export class S3Service { targetFolder?: string ): Promise { const fileExtension = originalName.split('.').pop(); - const safeFolder = (targetFolder || 'music').replace(/^\/+|\/+$/g, ''); - const key = `${safeFolder}/${uuidv4()}.${fileExtension}`; + const cleaned = typeof targetFolder === 'string' ? targetFolder.replace(/^\/+|\/+$/g, '') : ''; + const safeFolder = cleaned; + const key = safeFolder + ? `${safeFolder}/${uuidv4()}.${fileExtension}` + : `${uuidv4()}.${fileExtension}`; const command = new PutObjectCommand({ Bucket: this.bucketName, diff --git a/packages/frontend/src/components/MusicUpload.tsx b/packages/frontend/src/components/MusicUpload.tsx index c9f91b1..ddefd50 100644 --- a/packages/frontend/src/components/MusicUpload.tsx +++ b/packages/frontend/src/components/MusicUpload.tsx @@ -131,9 +131,9 @@ export const MusicUpload: React.FC = ({ onUploadComplete }) => const data = await res.json(); const items = Array.isArray(data.folders) ? data.folders : []; setFolders(items); - if (items.length > 0) { - // default to first folder if uploads not present - const defaultChoice = items.find((f: string) => f.toLowerCase().includes('upload')) || items[0]; + if (items.length > 0 && targetFolder === 'uploads') { + // default target: root (empty) if available, else first item + const defaultChoice = items.find((f: string) => f === '') || items[0]; setTargetFolder(defaultChoice.replace(/^\/+/, '')); } } catch (e) { @@ -154,7 +154,7 @@ export const MusicUpload: React.FC = ({ onUploadComplete }) => {folders.length > 0 ? ( ) : (