feat(admin): add bulk song selection with playlist assignment
- Introduces bulk checkboxes on the songs list page to select multiple songs - Adds a toolbar with dropdown to add selected songs to existing playlists or create a new playlist - Implements `/songs/bulk-add` POST endpoint for efficient batch addition of tracks to playlists - Auto-upgrades playlist visibility when adding more-restrictive songs - Supports preselecting songs via query parameter when creating a new playlist (`?songs=1,2,3`) - Includes custom-styled checkboxes, toast notifications, and keyboard-friendly UI interactions
This commit is contained in:
parent
983b00f375
commit
31edb59583
|
|
@ -9,11 +9,24 @@
|
||||||
catch { return false; }
|
catch { return false; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Re-execute script tags injected via innerHTML (browser skips them otherwise).
|
||||||
|
function runScripts(container) {
|
||||||
|
container.querySelectorAll('script').forEach((old) => {
|
||||||
|
const s = document.createElement('script');
|
||||||
|
[...old.attributes].forEach((a) => s.setAttribute(a.name, a.value));
|
||||||
|
s.textContent = old.textContent;
|
||||||
|
old.replaceWith(s);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Swap #page-shell content, update title, and optionally push history.
|
// Swap #page-shell content, update title, and optionally push history.
|
||||||
function applyPage(doc, finalUrl, pushState) {
|
function applyPage(doc, finalUrl, pushState) {
|
||||||
const newShell = doc.getElementById('page-shell');
|
const newShell = doc.getElementById('page-shell');
|
||||||
const curShell = document.getElementById('page-shell');
|
const curShell = document.getElementById('page-shell');
|
||||||
if (newShell && curShell) curShell.innerHTML = newShell.innerHTML;
|
if (newShell && curShell) {
|
||||||
|
curShell.innerHTML = newShell.innerHTML;
|
||||||
|
runScripts(curShell);
|
||||||
|
}
|
||||||
document.title = doc.title;
|
document.title = doc.title;
|
||||||
if (pushState) history.pushState({ btiNav: true }, doc.title, finalUrl);
|
if (pushState) history.pushState({ btiNav: true }, doc.title, finalUrl);
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@
|
||||||
const form = document.getElementById('reorder-form');
|
const form = document.getElementById('reorder-form');
|
||||||
document.getElementById('reorder-order').value =
|
document.getElementById('reorder-order').value =
|
||||||
[...list.querySelectorAll('li')].map(li => li.dataset.songId).join(',');
|
[...list.querySelectorAll('li')].map(li => li.dataset.songId).join(',');
|
||||||
fetch(form.action, { method: 'POST', body: new FormData(form) })
|
fetch(form.action, { method: 'POST', body: new URLSearchParams(new FormData(form)) })
|
||||||
.catch(err => console.error('[reorder] failed:', err));
|
.catch(err => console.error('[reorder] failed:', err));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue