refactor: rename admin routes and views to mymusic namespace
- Move /admin/* routes to /mymusic/* for clearer user-focused section naming - Rename admin/ view templates to mymusic/ with updated paths and URLs - Add cover art preview in song edit form with current cover thumbnail styling - Update navigation active states to use new /mymusic* paths - Change now-playing creator link from window.open() to direct navigation
This commit is contained in:
parent
561f41f0ce
commit
20bd6422a6
|
|
@ -436,6 +436,8 @@ a.detail-creator-card:hover {
|
|||
.form-card::after { bottom: 6px; right: 6px; border-left: none; border-top: none; }
|
||||
|
||||
.stacked { display: flex; flex-direction: column; gap: 1rem; }
|
||||
.current-cover-wrap { margin: 0.25rem 0; }
|
||||
.current-cover-thumb { width: 80px; height: 80px; object-fit: cover; border-radius: var(--radius); border: 1px solid var(--border); }
|
||||
.stacked label {
|
||||
display: flex; flex-direction: column; gap: 0.35rem;
|
||||
font-size: 0.72rem; color: var(--muted);
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@
|
|||
// Make the whole creator block a link if we have a profile slug.
|
||||
if (creatorData.slug) {
|
||||
creatorInfo.style.cursor = 'pointer';
|
||||
creatorInfo.onclick = () => { window.open('/profiles/' + creatorData.slug, '_blank'); };
|
||||
creatorInfo.onclick = () => { window.location.href = '/profiles/' + creatorData.slug; };
|
||||
} else {
|
||||
creatorInfo.style.cursor = '';
|
||||
creatorInfo.onclick = null;
|
||||
|
|
|
|||
|
|
@ -77,8 +77,8 @@ app.use('/api', require('./routes/social')(csrfSynchronisedProtection));
|
|||
app.use('/', require('./routes/public'));
|
||||
app.use('/', require('./routes/auth')(csrfSynchronisedProtection));
|
||||
app.use('/account', require('./routes/account')(csrfSynchronisedProtection));
|
||||
app.use('/admin/users', require('./routes/users-admin')(csrfSynchronisedProtection));
|
||||
app.use('/admin', require('./routes/admin')(csrfSynchronisedProtection));
|
||||
app.use('/mymusic/users', require('./routes/users-admin')(csrfSynchronisedProtection));
|
||||
app.use('/mymusic', require('./routes/admin')(csrfSynchronisedProtection));
|
||||
|
||||
// 404.
|
||||
app.use((req, res) => {
|
||||
|
|
|
|||
|
|
@ -150,15 +150,15 @@ module.exports = function adminRoutes(csrfProtection) {
|
|||
router.use(requireUser);
|
||||
|
||||
// ---------- Songs ----------
|
||||
router.get('/', (req, res) => res.redirect('/admin/songs'));
|
||||
router.get('/', (req, res) => res.redirect('/mymusic/songs'));
|
||||
|
||||
router.get('/songs', (req, res) => {
|
||||
const songList = songs.listByUser(req.session.user.id);
|
||||
res.render('admin/songs', { title: 'My Music · Songs', songs: songList });
|
||||
res.render('mymusic/songs', { title: 'My Music · Songs', songs: songList });
|
||||
});
|
||||
|
||||
router.get('/songs/new', (req, res) => {
|
||||
res.render('admin/song_form', { title: 'New song', song: null, errors: {}, values: { visibility: 'logged_in' } });
|
||||
res.render('mymusic/song_form', { title: 'New song', song: null, errors: {}, values: { visibility: 'logged_in' } });
|
||||
});
|
||||
|
||||
router.post('/songs', songFields, csrfProtection, async (req, res, next) => {
|
||||
|
|
@ -170,7 +170,7 @@ module.exports = function adminRoutes(csrfProtection) {
|
|||
if (!req.files || !req.files.audio || !req.files.audio[0]) errors.audio = 'Audio file is required.';
|
||||
if (req.files?.audio?.[0]) unlinkQuiet(req.files.audio[0].path);
|
||||
if (req.files?.cover?.[0]) unlinkQuiet(req.files.cover[0].path);
|
||||
return res.status(400).render('admin/song_form', { title: 'New song', song: null, errors, values: req.body });
|
||||
return res.status(400).render('mymusic/song_form', { title: 'New song', song: null, errors, values: req.body });
|
||||
}
|
||||
const audioFile = req.files.audio[0];
|
||||
const coverFile = req.files.cover?.[0];
|
||||
|
|
@ -212,7 +212,7 @@ module.exports = function adminRoutes(csrfProtection) {
|
|||
uploadedBy: req.session.user.id,
|
||||
});
|
||||
req.flash('success', 'Song uploaded. Tags were read from the file — review and edit if needed.');
|
||||
res.redirect('/admin/songs');
|
||||
res.redirect('/mymusic/songs');
|
||||
} catch (err) { next(err); }
|
||||
});
|
||||
|
||||
|
|
@ -220,13 +220,13 @@ module.exports = function adminRoutes(csrfProtection) {
|
|||
const song = songs.findById(Number(req.params.id));
|
||||
if (!song) return next();
|
||||
if (!canManage(song, req.session.user)) return forbidden(next);
|
||||
res.render('admin/song_form', {
|
||||
res.render('mymusic/song_form', {
|
||||
title: 'Edit song', song, errors: {},
|
||||
values: { ...song },
|
||||
});
|
||||
});
|
||||
|
||||
router.post('/songs/:id', csrfProtection, (req, res, next) => {
|
||||
router.post('/songs/:id', songFields, csrfProtection, (req, res, next) => {
|
||||
try {
|
||||
const id = Number(req.params.id);
|
||||
const existing = songs.findById(id);
|
||||
|
|
@ -236,7 +236,8 @@ module.exports = function adminRoutes(csrfProtection) {
|
|||
if (!parsed.success) {
|
||||
const errors = {};
|
||||
for (const i of parsed.error.issues) errors[i.path[0]] = i.message;
|
||||
return res.status(400).render('admin/song_form', { title: 'Edit song', song: existing, errors, values: req.body });
|
||||
if (req.files?.cover?.[0]) unlinkQuiet(req.files.cover[0].path);
|
||||
return res.status(400).render('mymusic/song_form', { title: 'Edit song', song: existing, errors, values: req.body });
|
||||
}
|
||||
songs.update(id, {
|
||||
title: parsed.data.title,
|
||||
|
|
@ -246,8 +247,13 @@ module.exports = function adminRoutes(csrfProtection) {
|
|||
year: parsed.data.year ?? null,
|
||||
visibility: parsed.data.visibility,
|
||||
});
|
||||
const coverFile = req.files?.cover?.[0];
|
||||
if (coverFile) {
|
||||
if (existing.coverPath) unlinkQuiet(path.join(mediaDir, existing.coverPath));
|
||||
songs.setCover(id, relMedia(coverFile, 'covers'));
|
||||
}
|
||||
req.flash('success', 'Song updated.');
|
||||
res.redirect('/admin/songs');
|
||||
res.redirect('/mymusic/songs');
|
||||
} catch (err) { next(err); }
|
||||
});
|
||||
|
||||
|
|
@ -262,19 +268,19 @@ module.exports = function adminRoutes(csrfProtection) {
|
|||
if (existing.audioPath) unlinkQuiet(path.join(mediaDir, existing.audioPath));
|
||||
if (existing.coverPath) unlinkQuiet(path.join(mediaDir, existing.coverPath));
|
||||
req.flash('success', 'Song deleted.');
|
||||
res.redirect('/admin/songs');
|
||||
res.redirect('/mymusic/songs');
|
||||
} catch (err) { next(err); }
|
||||
});
|
||||
|
||||
// ---------- Playlists ----------
|
||||
router.get('/playlists', (req, res) => {
|
||||
const playlistList = playlists.listByUser(req.session.user.id);
|
||||
res.render('admin/playlists', { title: 'My Music · Playlists', playlists: playlistList });
|
||||
res.render('mymusic/playlists', { title: 'My Music · Playlists', playlists: playlistList });
|
||||
});
|
||||
|
||||
router.get('/playlists/new', (req, res) => {
|
||||
const allSongs = songs.listForManagement(req.session.user.id);
|
||||
res.render('admin/playlist_form', { title: 'New playlist', playlist: null, tracks: [], allSongs, errors: {}, values: { visibility: 'logged_in' } });
|
||||
res.render('mymusic/playlist_form', { title: 'New playlist', playlist: null, tracks: [], allSongs, errors: {}, values: { visibility: 'logged_in' } });
|
||||
});
|
||||
|
||||
router.post('/playlists', playlistFields, csrfProtection, (req, res, next) => {
|
||||
|
|
@ -286,7 +292,7 @@ module.exports = function adminRoutes(csrfProtection) {
|
|||
for (const i of parsed.error.issues) errors[i.path[0]] = i.message;
|
||||
if (req.files?.cover?.[0]) unlinkQuiet(req.files.cover[0].path);
|
||||
const allSongs = songs.listForManagement(user.id);
|
||||
return res.status(400).render('admin/playlist_form', { title: 'New playlist', playlist: null, tracks: [], allSongs, errors, values: req.body });
|
||||
return res.status(400).render('mymusic/playlist_form', { title: 'New playlist', playlist: null, tracks: [], allSongs, errors, values: req.body });
|
||||
}
|
||||
const coverFile = req.files?.cover?.[0];
|
||||
const created = playlists.create({
|
||||
|
|
@ -297,7 +303,7 @@ module.exports = function adminRoutes(csrfProtection) {
|
|||
createdBy: req.session.user.id,
|
||||
});
|
||||
req.flash('success', 'Playlist created.');
|
||||
res.redirect(`/admin/playlists/${created.id}/edit`);
|
||||
res.redirect(`/mymusic/playlists/${created.id}/edit`);
|
||||
} catch (err) { next(err); }
|
||||
});
|
||||
|
||||
|
|
@ -307,7 +313,7 @@ module.exports = function adminRoutes(csrfProtection) {
|
|||
if (!playlist) return next();
|
||||
if (!canManage(playlist, req.session.user)) return forbidden(next);
|
||||
const allSongs = songs.listForManagement(req.session.user.id);
|
||||
res.render('admin/playlist_form', {
|
||||
res.render('mymusic/playlist_form', {
|
||||
title: 'Edit playlist',
|
||||
playlist,
|
||||
tracks: playlists.getTracks(id),
|
||||
|
|
@ -330,7 +336,7 @@ module.exports = function adminRoutes(csrfProtection) {
|
|||
for (const i of parsed.error.issues) errors[i.path[0]] = i.message;
|
||||
if (req.files?.cover?.[0]) unlinkQuiet(req.files.cover[0].path);
|
||||
const allSongs = songs.listForManagement(user.id);
|
||||
return res.status(400).render('admin/playlist_form', {
|
||||
return res.status(400).render('mymusic/playlist_form', {
|
||||
title: 'Edit playlist', playlist: existing,
|
||||
tracks: playlists.getTracks(id), allSongs,
|
||||
errors, values: req.body,
|
||||
|
|
@ -347,7 +353,7 @@ module.exports = function adminRoutes(csrfProtection) {
|
|||
playlists.setCover(id, relMedia(coverFile, 'covers'));
|
||||
}
|
||||
req.flash('success', 'Playlist updated.');
|
||||
res.redirect(`/admin/playlists/${id}/edit`);
|
||||
res.redirect(`/mymusic/playlists/${id}/edit`);
|
||||
} catch (err) { next(err); }
|
||||
});
|
||||
|
||||
|
|
@ -364,7 +370,7 @@ module.exports = function adminRoutes(csrfProtection) {
|
|||
if (VISIBILITY_RANK[song.visibility] > VISIBILITY_RANK[playlist.visibility]) {
|
||||
playlists.setVisibility(id, song.visibility);
|
||||
}
|
||||
res.redirect(`/admin/playlists/${id}/edit`);
|
||||
res.redirect(`/mymusic/playlists/${id}/edit`);
|
||||
} catch (err) { next(err); }
|
||||
});
|
||||
|
||||
|
|
@ -376,7 +382,7 @@ module.exports = function adminRoutes(csrfProtection) {
|
|||
if (!playlist) return next();
|
||||
if (!canManage(playlist, req.session.user)) return forbidden(next);
|
||||
playlists.removeTrack(id, songId);
|
||||
res.redirect(`/admin/playlists/${id}/edit`);
|
||||
res.redirect(`/mymusic/playlists/${id}/edit`);
|
||||
} catch (err) { next(err); }
|
||||
});
|
||||
|
||||
|
|
@ -389,7 +395,7 @@ module.exports = function adminRoutes(csrfProtection) {
|
|||
const order = String(req.body.order || '')
|
||||
.split(',').map((x) => Number(x.trim())).filter(Number.isFinite);
|
||||
playlists.setOrder(id, order);
|
||||
res.redirect(`/admin/playlists/${id}/edit`);
|
||||
res.redirect(`/mymusic/playlists/${id}/edit`);
|
||||
} catch (err) { next(err); }
|
||||
});
|
||||
|
||||
|
|
@ -402,7 +408,7 @@ module.exports = function adminRoutes(csrfProtection) {
|
|||
playlists.remove(id);
|
||||
if (existing.coverPath) unlinkQuiet(path.join(mediaDir, existing.coverPath));
|
||||
req.flash('success', 'Playlist deleted.');
|
||||
res.redirect('/admin/playlists');
|
||||
res.redirect('/mymusic/playlists');
|
||||
} catch (err) { next(err); }
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ module.exports = function usersAdminRoutes(csrfProtection) {
|
|||
router.use(requireAdmin);
|
||||
|
||||
router.get('/', (req, res) => {
|
||||
res.render('admin/users', { title: 'Users', userList: users.listAllUsers() });
|
||||
res.render('mymusic/users', { title: 'Users', userList: users.listAllUsers() });
|
||||
});
|
||||
|
||||
router.post('/:id/disable', csrfProtection, (req, res, next) => {
|
||||
|
|
@ -23,11 +23,11 @@ module.exports = function usersAdminRoutes(csrfProtection) {
|
|||
const id = Number(req.params.id);
|
||||
if (id === req.session.user.id) {
|
||||
req.flash('error', 'You cannot disable your own account.');
|
||||
return res.redirect('/admin/users');
|
||||
return res.redirect('/mymusic/users');
|
||||
}
|
||||
users.setDisabled(id, true);
|
||||
req.flash('success', 'Account disabled.');
|
||||
res.redirect('/admin/users');
|
||||
res.redirect('/mymusic/users');
|
||||
} catch (err) { next(err); }
|
||||
});
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ module.exports = function usersAdminRoutes(csrfProtection) {
|
|||
try {
|
||||
users.setDisabled(Number(req.params.id), false);
|
||||
req.flash('success', 'Account enabled.');
|
||||
res.redirect('/admin/users');
|
||||
res.redirect('/mymusic/users');
|
||||
} catch (err) { next(err); }
|
||||
});
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ module.exports = function usersAdminRoutes(csrfProtection) {
|
|||
try {
|
||||
users.markVerifiedAdmin(Number(req.params.id));
|
||||
req.flash('success', 'Email marked as verified.');
|
||||
res.redirect('/admin/users');
|
||||
res.redirect('/mymusic/users');
|
||||
} catch (err) { next(err); }
|
||||
});
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ module.exports = function usersAdminRoutes(csrfProtection) {
|
|||
const id = Number(req.params.id);
|
||||
if (id === req.session.user.id) {
|
||||
req.flash('error', 'You cannot delete your own account.');
|
||||
return res.redirect('/admin/users');
|
||||
return res.redirect('/mymusic/users');
|
||||
}
|
||||
const { songs, playlists } = users.deleteUserWithContent(id);
|
||||
for (const s of songs) {
|
||||
|
|
@ -63,7 +63,7 @@ module.exports = function usersAdminRoutes(csrfProtection) {
|
|||
if (p.cover_path) unlinkQuiet(path.join(mediaDir, p.cover_path));
|
||||
}
|
||||
req.flash('success', 'User and all their content deleted.');
|
||||
res.redirect('/admin/users');
|
||||
res.redirect('/mymusic/users');
|
||||
} catch (err) { next(err); }
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<h1><%= playlist ? 'Edit playlist' : 'New playlist' %></h1>
|
||||
|
||||
<form method="post"
|
||||
action="<%= playlist ? '/admin/playlists/' + playlist.id : '/admin/playlists' %>"
|
||||
action="<%= playlist ? '/mymusic/playlists/' + playlist.id : '/mymusic/playlists' %>"
|
||||
enctype="multipart/form-data" class="stacked form-card">
|
||||
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
|
||||
<label>
|
||||
|
|
@ -35,7 +35,7 @@
|
|||
</fieldset>
|
||||
<div class="row">
|
||||
<button type="submit" class="btn-primary"><%= playlist ? 'Save' : 'Create' %></button>
|
||||
<a href="/admin/playlists" class="btn-link">Cancel</a>
|
||||
<a href="/mymusic/playlists" class="btn-link">Cancel</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
|
@ -56,7 +56,7 @@
|
|||
</svg>
|
||||
</span>
|
||||
<span class="track-label"><%= t.title %> — <span class="muted small"><%= t.artist %></span></span>
|
||||
<form method="post" action="/admin/playlists/<%= playlist.id %>/remove-track" class="inline-form">
|
||||
<form method="post" action="/mymusic/playlists/<%= playlist.id %>/remove-track" class="inline-form">
|
||||
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
|
||||
<input type="hidden" name="song_id" value="<%= t.id %>">
|
||||
<button type="submit" class="linklike danger">Remove</button>
|
||||
|
|
@ -64,13 +64,13 @@
|
|||
</li>
|
||||
<% }) %>
|
||||
</ol>
|
||||
<form id="reorder-form" method="post" action="/admin/playlists/<%= playlist.id %>/reorder" style="display:none">
|
||||
<form id="reorder-form" method="post" action="/mymusic/playlists/<%= playlist.id %>/reorder" style="display:none">
|
||||
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
|
||||
<input type="hidden" name="order" id="reorder-order">
|
||||
</form>
|
||||
<% } %>
|
||||
|
||||
<form method="post" action="/admin/playlists/<%= playlist.id %>/add-track" class="inline-row">
|
||||
<form method="post" action="/mymusic/playlists/<%= playlist.id %>/add-track" class="inline-row">
|
||||
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
|
||||
<select name="song_id" required>
|
||||
<option value="">— Add a song —</option>
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
<div class="row-between">
|
||||
<h1>My Music · Playlists</h1>
|
||||
<a href="/admin/playlists/new" class="btn-primary">New playlist</a>
|
||||
<a href="/mymusic/playlists/new" class="btn-primary">New playlist</a>
|
||||
</div>
|
||||
|
||||
<nav class="tabs">
|
||||
<a href="/admin/songs">Songs</a>
|
||||
<a href="/admin/playlists" class="active">Playlists</a>
|
||||
<a href="/mymusic/songs">Songs</a>
|
||||
<a href="/mymusic/playlists" class="active">Playlists</a>
|
||||
</nav>
|
||||
|
||||
<% if (playlists.length === 0) { %>
|
||||
|
|
@ -28,8 +28,8 @@
|
|||
</td>
|
||||
<td class="muted small"><%= p.createdAt %></td>
|
||||
<td class="actions">
|
||||
<a href="/admin/playlists/<%= p.id %>/edit">Edit</a>
|
||||
<form method="post" action="/admin/playlists/<%= p.id %>/delete" class="inline-form" onsubmit="return confirm('Delete this playlist?');">
|
||||
<a href="/mymusic/playlists/<%= p.id %>/edit">Edit</a>
|
||||
<form method="post" action="/mymusic/playlists/<%= p.id %>/delete" class="inline-form" onsubmit="return confirm('Delete this playlist?');">
|
||||
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
|
||||
<button type="submit" class="linklike danger">Delete</button>
|
||||
</form>
|
||||
|
|
@ -5,8 +5,8 @@
|
|||
<% } %>
|
||||
|
||||
<form method="post"
|
||||
action="<%= song ? '/admin/songs/' + song.id : '/admin/songs' %>"
|
||||
<% if (!song) { %>enctype="multipart/form-data"<% } %>
|
||||
action="<%= song ? '/mymusic/songs/' + song.id : '/mymusic/songs' %>"
|
||||
enctype="multipart/form-data"
|
||||
class="stacked form-card">
|
||||
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
|
||||
|
||||
|
|
@ -46,7 +46,15 @@
|
|||
<input type="file" name="cover" accept="image/*">
|
||||
</label>
|
||||
<% } else { %>
|
||||
<p class="muted small">Audio and cover can't be replaced from this form yet — delete and re-upload to change them.</p>
|
||||
<label>
|
||||
Replace cover art <span class="muted small">(optional — leave blank to keep current)</span>
|
||||
<% if (song.coverPath) { %>
|
||||
<div class="current-cover-wrap">
|
||||
<img src="/media/<%= song.coverPath %>" alt="Current cover" class="current-cover-thumb">
|
||||
</div>
|
||||
<% } %>
|
||||
<input type="file" name="cover" accept="image/*">
|
||||
</label>
|
||||
<% } %>
|
||||
|
||||
<fieldset class="visibility-field">
|
||||
|
|
@ -67,6 +75,6 @@
|
|||
|
||||
<div class="row">
|
||||
<button type="submit" class="btn-primary"><%= song ? 'Save' : 'Upload' %></button>
|
||||
<a href="/admin/songs" class="btn-link">Cancel</a>
|
||||
<a href="/mymusic/songs" class="btn-link">Cancel</a>
|
||||
</div>
|
||||
</form>
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
<div class="row-between">
|
||||
<h1>My Music · Songs</h1>
|
||||
<a href="/admin/songs/new" class="btn-primary">Upload song</a>
|
||||
<a href="/mymusic/songs/new" class="btn-primary">Upload song</a>
|
||||
</div>
|
||||
|
||||
<nav class="tabs">
|
||||
<a href="/admin/songs" class="active">Songs</a>
|
||||
<a href="/admin/playlists">Playlists</a>
|
||||
<a href="/mymusic/songs" class="active">Songs</a>
|
||||
<a href="/mymusic/playlists">Playlists</a>
|
||||
</nav>
|
||||
|
||||
<% if (songs.length === 0) { %>
|
||||
|
|
@ -29,8 +29,8 @@
|
|||
<% } %>
|
||||
</td>
|
||||
<td class="actions">
|
||||
<a href="/admin/songs/<%= s.id %>/edit">Edit</a>
|
||||
<form method="post" action="/admin/songs/<%= s.id %>/delete" class="inline-form" onsubmit="return confirm('Delete this song?');">
|
||||
<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>
|
||||
|
|
@ -20,24 +20,24 @@
|
|||
<td><%= u.disabled ? 'Disabled' : 'Active' %></td>
|
||||
<td class="actions">
|
||||
<% if (!u.emailVerified) { %>
|
||||
<form method="post" action="/admin/users/<%= u.id %>/verify" class="inline-form">
|
||||
<form method="post" action="/mymusic/users/<%= u.id %>/verify" class="inline-form">
|
||||
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
|
||||
<button type="submit" class="btn-small">Verify</button>
|
||||
</form>
|
||||
<% } %>
|
||||
<% if (u.id !== user.id) { %>
|
||||
<% if (u.disabled) { %>
|
||||
<form method="post" action="/admin/users/<%= u.id %>/enable" class="inline-form">
|
||||
<form method="post" action="/mymusic/users/<%= u.id %>/enable" class="inline-form">
|
||||
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
|
||||
<button type="submit" class="btn-small">Enable</button>
|
||||
</form>
|
||||
<% } else { %>
|
||||
<form method="post" action="/admin/users/<%= u.id %>/disable" class="inline-form">
|
||||
<form method="post" action="/mymusic/users/<%= u.id %>/disable" class="inline-form">
|
||||
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
|
||||
<button type="submit" class="btn-small">Disable</button>
|
||||
</form>
|
||||
<% } %>
|
||||
<form method="post" action="/admin/users/<%= u.id %>/delete" class="inline-form"
|
||||
<form method="post" action="/mymusic/users/<%= u.id %>/delete" class="inline-form"
|
||||
onsubmit="return confirm('Delete <%= u.displayName.replace(/'/g, "\\'") %> and ALL their content? This cannot be undone.')">
|
||||
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
|
||||
<button type="submit" class="btn-small danger">Delete</button>
|
||||
|
|
@ -6,9 +6,9 @@
|
|||
<a href="/playlists" class="<%= currentPath && currentPath.startsWith('/playlists') ? 'active' : '' %>">Playlists</a>
|
||||
<a href="/profiles" class="<%= currentPath && currentPath.startsWith('/profiles') ? 'active' : '' %>">Profiles</a>
|
||||
<% if (user) { %>
|
||||
<a href="/admin/songs" class="<%= currentPath && currentPath.startsWith('/admin') && !currentPath.startsWith('/admin/users') ? 'active' : '' %>">My Music</a>
|
||||
<a href="/mymusic/songs" class="<%= currentPath && currentPath.startsWith('/mymusic') && !currentPath.startsWith('/mymusic/users') ? 'active' : '' %>">My Music</a>
|
||||
<% if (user.role === 'admin') { %>
|
||||
<a href="/admin/users" class="<%= currentPath && currentPath.startsWith('/admin/users') ? 'active' : '' %>">Users</a>
|
||||
<a href="/mymusic/users" class="<%= currentPath && currentPath.startsWith('/mymusic/users') ? 'active' : '' %>">Users</a>
|
||||
<% } %>
|
||||
<a href="/account">Account</a>
|
||||
<form method="post" action="/logout" class="inline-form">
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@
|
|||
<section>
|
||||
<h2>Recently added <a href="/songs" class="muted small" style="font-weight:normal">(show all)</a></h2>
|
||||
<% if (recent.length === 0) { %>
|
||||
<p class="muted">No songs yet. <% if (user && user.role === 'admin') { %><a href="/admin/songs/new">Upload the first one →</a><% } %></p>
|
||||
<p class="muted">No songs yet. <% if (user && user.role === 'admin') { %><a href="/mymusic/songs/new">Upload the first one →</a><% } %></p>
|
||||
<% } else { %>
|
||||
<%- include('../partials/song_list', { songs: recent }) %>
|
||||
<% } %>
|
||||
|
|
|
|||
Loading…
Reference in New Issue