fix(upload): resolve folder selection issue and improve 'To Be Scanned' playlist creation - add debug logging, visual selection indicator, simplify playlist creation logic, support batch uploads with markForScan
This commit is contained in:
parent
7557eddeb4
commit
675c1f8d8f
@ -102,33 +102,21 @@ router.post('/upload', upload.single('file'), async (req, res) => {
|
||||
if (markForScan) {
|
||||
try {
|
||||
const { Playlist } = await import('../models/Playlist.js');
|
||||
// Ensure root exists or create simple structure
|
||||
let root = await Playlist.findOne({ name: 'ROOT' });
|
||||
if (!root) {
|
||||
root = new Playlist({ name: 'ROOT', type: 'folder', children: [] });
|
||||
await root.save();
|
||||
}
|
||||
// Find or create the "To Be Scanned" playlist at root level
|
||||
const findNode = (node: any, name: string): any => {
|
||||
if (!node) return null;
|
||||
if (node.type === 'playlist' && node.name === name) return node;
|
||||
if (Array.isArray(node.children)) {
|
||||
for (const child of node.children) {
|
||||
const found = findNode(child, name);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
let toScan = findNode(root, 'To Be Scanned');
|
||||
if (!toScan) {
|
||||
toScan = { id: 'to-be-scanned', name: 'To Be Scanned', type: 'playlist', tracks: [] } as any;
|
||||
root.children = [...(root.children || []), toScan];
|
||||
}
|
||||
// Add by songId? We don't have a Song yet; add by MusicFile ObjectId to track later
|
||||
// Instead, we will create a stub Song entry if none exists so XML export can include it
|
||||
const { Song } = await import('../models/Song.js');
|
||||
|
||||
// Find or create the "To Be Scanned" playlist
|
||||
let toScanPlaylist = await Playlist.findOne({ name: 'To Be Scanned' });
|
||||
if (!toScanPlaylist) {
|
||||
toScanPlaylist = new Playlist({
|
||||
name: 'To Be Scanned',
|
||||
type: 'playlist',
|
||||
tracks: [],
|
||||
order: 0
|
||||
});
|
||||
await toScanPlaylist.save();
|
||||
console.log('✅ Created "To Be Scanned" playlist');
|
||||
}
|
||||
|
||||
// Create stub song with temporary id if needed
|
||||
const tempId = `stub-${musicFile._id.toString()}`;
|
||||
let existingStub = await Song.findOne({ id: tempId });
|
||||
@ -140,14 +128,25 @@ router.post('/upload', upload.single('file'), async (req, res) => {
|
||||
album: musicFile.album || '',
|
||||
totalTime: musicFile.duration ? String(Math.round(musicFile.duration / 1000)) : '',
|
||||
location: '',
|
||||
s3File: {
|
||||
musicFileId: musicFile._id,
|
||||
s3Key: musicFile.s3Key,
|
||||
s3Url: musicFile.s3Url,
|
||||
hasS3File: true
|
||||
}
|
||||
});
|
||||
await stub.save();
|
||||
console.log('✅ Created stub song:', tempId);
|
||||
}
|
||||
|
||||
// Add stub song to playlist if not already there
|
||||
if (!toScanPlaylist.tracks.includes(tempId)) {
|
||||
toScanPlaylist.tracks.push(tempId);
|
||||
await toScanPlaylist.save();
|
||||
console.log('✅ Added song to "To Be Scanned" playlist');
|
||||
}
|
||||
// Push stub id into playlist
|
||||
toScan.tracks = Array.from(new Set([...(toScan.tracks || []), tempId]));
|
||||
await root.save();
|
||||
} catch (e) {
|
||||
console.warn('Failed to mark uploaded file for scanning:', e);
|
||||
console.error('❌ Failed to mark uploaded file for scanning:', e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,6 +169,7 @@ router.post('/batch-upload', upload.array('files', 10), async (req, res) => {
|
||||
return res.status(400).json({ error: 'No files uploaded' });
|
||||
}
|
||||
|
||||
const { markForScan = false } = req.body;
|
||||
const results = [];
|
||||
|
||||
for (const file of req.files as Express.Multer.File[]) {
|
||||
@ -195,6 +195,58 @@ router.post('/batch-upload', upload.array('files', 10), async (req, res) => {
|
||||
await musicFile.save();
|
||||
results.push({ success: true, musicFile });
|
||||
|
||||
// Optionally add to "To Be Scanned" playlist
|
||||
if (markForScan) {
|
||||
try {
|
||||
const { Playlist } = await import('../models/Playlist.js');
|
||||
const { Song } = await import('../models/Song.js');
|
||||
|
||||
// Find or create the "To Be Scanned" playlist
|
||||
let toScanPlaylist = await Playlist.findOne({ name: 'To Be Scanned' });
|
||||
if (!toScanPlaylist) {
|
||||
toScanPlaylist = new Playlist({
|
||||
name: 'To Be Scanned',
|
||||
type: 'playlist',
|
||||
tracks: [],
|
||||
order: 0
|
||||
});
|
||||
await toScanPlaylist.save();
|
||||
console.log('✅ Created "To Be Scanned" playlist (batch)');
|
||||
}
|
||||
|
||||
// Create stub song with temporary id if needed
|
||||
const tempId = `stub-${musicFile._id.toString()}`;
|
||||
let existingStub = await Song.findOne({ id: tempId });
|
||||
if (!existingStub) {
|
||||
const stub = new Song({
|
||||
id: tempId,
|
||||
title: musicFile.title || musicFile.originalName,
|
||||
artist: musicFile.artist || '',
|
||||
album: musicFile.album || '',
|
||||
totalTime: musicFile.duration ? String(Math.round(musicFile.duration / 1000)) : '',
|
||||
location: '',
|
||||
s3File: {
|
||||
musicFileId: musicFile._id,
|
||||
s3Key: musicFile.s3Key,
|
||||
s3Url: musicFile.s3Url,
|
||||
hasS3File: true
|
||||
}
|
||||
});
|
||||
await stub.save();
|
||||
console.log('✅ Created stub song (batch):', tempId);
|
||||
}
|
||||
|
||||
// Add stub song to playlist if not already there
|
||||
if (!toScanPlaylist.tracks.includes(tempId)) {
|
||||
toScanPlaylist.tracks.push(tempId);
|
||||
await toScanPlaylist.save();
|
||||
console.log('✅ Added song to "To Be Scanned" playlist (batch)');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('❌ Failed to mark uploaded file for scanning (batch):', e);
|
||||
}
|
||||
}
|
||||
|
||||
// Invalidate folder cache since we added a new file
|
||||
invalidateFolderCache();
|
||||
} catch (error) {
|
||||
|
||||
@ -155,6 +155,11 @@ export const MusicUpload: React.FC<MusicUploadProps> = ({ onUploadComplete }) =>
|
||||
<VStack spacing={4} align="stretch" w="full">
|
||||
<Box>
|
||||
<Text color="gray.300" fontSize="sm" mb={3}>Target S3 folder</Text>
|
||||
{targetFolder && (
|
||||
<Text color="blue.400" fontSize="sm" mb={2}>
|
||||
Selected: {targetFolder === '' ? '(root)' : targetFolder}
|
||||
</Text>
|
||||
)}
|
||||
{isLoadingFolders ? (
|
||||
<Box
|
||||
p={6}
|
||||
@ -171,7 +176,10 @@ export const MusicUpload: React.FC<MusicUploadProps> = ({ onUploadComplete }) =>
|
||||
<FolderBrowser
|
||||
folders={folders}
|
||||
selectedFolder={targetFolder}
|
||||
onFolderSelect={setTargetFolder}
|
||||
onFolderSelect={(folder) => {
|
||||
console.log('Folder selected:', folder);
|
||||
setTargetFolder(folder);
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Input
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user