Bri-Tunes/src/views/mymusic/songs.ejs

158 lines
5.6 KiB
Plaintext

<div class="row-between">
<h1>My Music · Songs</h1>
<a href="/mymusic/songs/new" class="btn-primary">Upload song</a>
</div>
<nav class="tabs">
<a href="/mymusic/songs" class="active">Songs</a>
<a href="/mymusic/playlists">Playlists</a>
</nav>
<% if (songs.length === 0) { %>
<p class="muted">No songs yet.</p>
<% } else { %>
<div id="bulk-toolbar" style="display:none">
<span><span id="bulk-count">0</span> selected</span>
<div class="bulk-dropdown">
<button type="button" id="bulk-add-btn" class="btn-secondary">Add to Playlist &#9660;</button>
<ul class="bulk-menu" id="bulk-menu">
<li><a id="bulk-new-playlist" href="#">+ New Playlist</a></li>
<li class="has-submenu">
<span>Existing Playlist</span>
<ul class="bulk-submenu">
<% playlists.forEach(function(pl) { %>
<li><a class="bulk-pl-item" data-playlist-id="<%= pl.id %>" href="#"><%= pl.title %></a></li>
<% }) %>
<% if (!playlists.length) { %>
<li class="bulk-submenu-empty">No playlists yet</li>
<% } %>
</ul>
</li>
</ul>
</div>
</div>
<table class="data-table">
<thead>
<tr>
<th class="col-check"><input type="checkbox" id="select-all" title="Select all"></th>
<th>Title</th><th>Artist</th><th>Album</th><th>Visibility</th><th></th>
</tr>
</thead>
<tbody>
<% songs.forEach((s) => { %>
<tr>
<td class="col-check"><input type="checkbox" class="song-select" value="<%= s.id %>"></td>
<td><a href="/songs/<%= s.slug %>"><%= s.title %></a></td>
<td><%= s.artist %></td>
<td><%= s.album || '' %></td>
<td>
<% if (s.visibility === 'logged_in') { %>
<span class="badge badge-logged-in">Members</span>
<% } else if (s.visibility === 'private') { %>
<span class="badge badge-private">Private</span>
<% } else { %>
<span class="badge badge-public">Public</span>
<% } %>
</td>
<td class="actions">
<a href="/mymusic/songs/<%= s.id %>/edit">Edit</a>
<form method="post" action="/mymusic/songs/<%= s.id %>/delete" class="inline-form" onsubmit="return confirm('Delete this song?');">
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
<button type="submit" class="linklike danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<script>
(function () {
var toolbar = document.getElementById('bulk-toolbar');
var countSpan = document.getElementById('bulk-count');
var addBtn = document.getElementById('bulk-add-btn');
var menu = document.getElementById('bulk-menu');
var newBtn = document.getElementById('bulk-new-playlist');
var selectAll = document.getElementById('select-all');
var csrfToken = (document.querySelector('meta[name="csrf-token"]') || {}).content || '';
function allBoxes() { return document.querySelectorAll('.song-select'); }
function checkedBoxes(){ return document.querySelectorAll('.song-select:checked'); }
function getIds() { return Array.from(checkedBoxes()).map(function(el){ return el.value; }); }
function updateToolbar() {
var checked = checkedBoxes().length;
var total = allBoxes().length;
toolbar.style.display = checked ? '' : 'none';
countSpan.textContent = checked;
selectAll.indeterminate = checked > 0 && checked < total;
selectAll.checked = checked > 0 && checked === total;
}
document.addEventListener('change', function(e) {
if (e.target.matches('#select-all')) {
var state = e.target.checked;
allBoxes().forEach(function(cb){ cb.checked = state; });
}
if (e.target.matches('.song-select') || e.target.matches('#select-all')) {
updateToolbar();
}
});
addBtn.addEventListener('click', function(e) {
e.stopPropagation();
menu.classList.toggle('open');
});
document.addEventListener('click', function() {
menu.classList.remove('open');
});
newBtn.addEventListener('click', function(e) {
e.preventDefault();
var ids = getIds();
if (!ids.length) return;
window.location.href = '/mymusic/playlists/new?songs=' + ids.join(',');
});
document.addEventListener('click', function(e) {
var item = e.target.closest('.bulk-pl-item');
if (!item) return;
e.preventDefault();
var playlistId = item.dataset.playlistId;
var songIds = getIds();
if (!songIds.length || !playlistId) return;
var body = new URLSearchParams({ playlistId: playlistId, _csrf: csrfToken });
songIds.forEach(function(id){ body.append('songIds[]', id); });
fetch('/mymusic/songs/bulk-add', { method: 'POST', body: body })
.then(function(r){ return r.json(); })
.then(function(data) {
if (data.ok) {
allBoxes().forEach(function(cb){ cb.checked = false; });
selectAll.checked = false;
updateToolbar();
showToast('Added ' + data.added + ' song' + (data.added === 1 ? '' : 's') + ' to playlist');
}
})
.catch(function(err){ console.error(err); });
menu.classList.remove('open');
});
function showToast(msg) {
var t = document.createElement('div');
t.className = 'bulk-toast';
t.textContent = msg;
document.body.appendChild(t);
setTimeout(function(){ t.classList.add('visible'); }, 10);
setTimeout(function(){
t.classList.remove('visible');
setTimeout(function(){ t.remove(); }, 300);
}, 2800);
}
})();
</script>
<% } %>