mirror of
https://github.com/nfonteyne/octane-website.git
synced 2026-09-03 23:24:48 +02:00
update: user can add musics, concerts and all
This commit is contained in:
parent
0683108c8e
commit
692b19a846
7 changed files with 92 additions and 42 deletions
|
|
@ -62,13 +62,12 @@ function songCardTemplate(song) {
|
|||
<button class="secondary icon-btn toggle-tutorials" data-id="${song.id}">
|
||||
${isOpen ? 'Masquer les tutos' : `Tutos (${song.tutorial_count})`}
|
||||
</button>
|
||||
${me && me.isAdmin ? `<button class="secondary icon-btn edit-song" data-id="${song.id}">Modifier</button>` : ''}
|
||||
<button class="secondary icon-btn edit-song" data-id="${song.id}">Modifier</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tutorials-panel panel" style="${isOpen ? '' : 'display:none'}">
|
||||
<div class="tag-list" data-tutorials-for="${song.id}"><p class="empty">Chargement…</p></div>
|
||||
${me && me.isAdmin ? `
|
||||
<div class="tutorial-grid" data-tutorials-for="${song.id}"><p class="empty">Chargement…</p></div>
|
||||
<form class="inline-form add-tutorial-form" data-song-id="${song.id}">
|
||||
<label>Instrument
|
||||
<select name="instrumentId" required>${instrumentOptions()}</select>
|
||||
|
|
@ -76,7 +75,7 @@ function songCardTemplate(song) {
|
|||
<label>Lien <input name="url" type="url" required placeholder="https://..."></label>
|
||||
<label>Libellé <input name="label" placeholder="ex: tuto solo"></label>
|
||||
<button type="submit">Ajouter le tuto</button>
|
||||
</form>` : ''}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
|
@ -101,6 +100,35 @@ function editSongCardTemplate(song) {
|
|||
`;
|
||||
}
|
||||
|
||||
function tutorialCardTemplate(t) {
|
||||
const thumb = youtubeThumbnailUrl(t.url);
|
||||
if (thumb) {
|
||||
return `
|
||||
<div class="tutorial-card" data-tutorial-id="${t.id}">
|
||||
<div class="song-thumb tutorial-thumb">
|
||||
<img src="${thumb}" alt="${escapeHtml(t.label || t.instrument_name)}" loading="lazy">
|
||||
<a class="play-overlay" href="${escapeHtml(t.url)}" target="_blank" rel="noopener" title="Regarder sur YouTube">►</a>
|
||||
</div>
|
||||
<div class="tutorial-meta">
|
||||
<span class="tag">${escapeHtml(t.instrument_name)}</span>
|
||||
<div class="tutorial-label">${escapeHtml(t.label || 'Tuto')}</div>
|
||||
</div>
|
||||
<button class="secondary icon-btn remove-tutorial" data-song-id="${t.song_id}" data-id="${t.id}">Retirer</button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
return `
|
||||
<div class="tutorial-card" data-tutorial-id="${t.id}">
|
||||
<div class="song-thumb tutorial-thumb placeholder">🔗</div>
|
||||
<div class="tutorial-meta">
|
||||
<span class="tag">${escapeHtml(t.instrument_name)}</span>
|
||||
<div class="tutorial-label"><a href="${escapeHtml(t.url)}" target="_blank" rel="noopener">${escapeHtml(t.label || t.url)}</a></div>
|
||||
</div>
|
||||
<button class="secondary icon-btn remove-tutorial" data-song-id="${t.song_id}" data-id="${t.id}">Retirer</button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function renderSongs() {
|
||||
const container = document.getElementById('songs-list');
|
||||
renderList(container, songs, songCardTemplate, 'Aucun morceau au répertoire pour le moment.');
|
||||
|
|
@ -152,11 +180,10 @@ async function loadTutorials(songId) {
|
|||
container.innerHTML = '<p class="empty">Aucun lien pour le moment.</p>';
|
||||
return;
|
||||
}
|
||||
container.innerHTML = detail.tutorials
|
||||
.map(
|
||||
(t) => `<span class="tag">${escapeHtml(t.instrument_name)}: <a href="${escapeHtml(t.url)}" target="_blank" rel="noopener">${escapeHtml(t.label || t.url)}</a></span>`
|
||||
)
|
||||
.join('');
|
||||
container.innerHTML = detail.tutorials.map(tutorialCardTemplate).join('');
|
||||
container.querySelectorAll('.remove-tutorial').forEach((btn) => {
|
||||
btn.addEventListener('click', () => onRemoveTutorial(parseInt(btn.dataset.songId, 10), parseInt(btn.dataset.id, 10)));
|
||||
});
|
||||
} catch (err) {
|
||||
showError(err.message);
|
||||
}
|
||||
|
|
@ -181,6 +208,18 @@ async function onAddTutorial(e) {
|
|||
}
|
||||
}
|
||||
|
||||
async function onRemoveTutorial(songId, tutorialId) {
|
||||
try {
|
||||
await api.del(`/api/songs/${songId}/tutorials/${tutorialId}`);
|
||||
const song = songs.find((s) => s.id === songId);
|
||||
if (song) song.tutorial_count -= 1;
|
||||
await loadTutorials(songId);
|
||||
renderSongs();
|
||||
} catch (err) {
|
||||
showError(err.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function onAddSong(e) {
|
||||
e.preventDefault();
|
||||
const form = e.target;
|
||||
|
|
@ -233,9 +272,6 @@ function showError(message) {
|
|||
(async function init() {
|
||||
me = await initNav('repertoire');
|
||||
await loadInstruments();
|
||||
if (me.isAdmin) {
|
||||
document.getElementById('admin-add-song').style.display = 'block';
|
||||
document.getElementById('add-song-form').addEventListener('submit', onAddSong);
|
||||
}
|
||||
document.getElementById('add-song-form').addEventListener('submit', onAddSong);
|
||||
await loadSongs();
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -30,17 +30,15 @@ function readOnlyView() {
|
|||
? `<ol class="setlist">${encore.map((s) => `<li><span class="row-title">${escapeHtml(s.title)}</span> <span class="row-artist">— ${escapeHtml(s.artist)}</span>${s.note ? `<span class="note">${escapeHtml(s.note)}</span>` : ''}</li>`).join('')}</ol>`
|
||||
: '<p class="empty">Aucun morceau de rappel prévu.</p>'}
|
||||
</div>
|
||||
${me.isAdmin ? '<button id="edit-btn" class="secondary" style="margin-top:1rem">Modifier la setlist</button>' : ''}
|
||||
<button id="edit-btn" class="secondary" style="margin-top:1rem">Modifier la setlist</button>
|
||||
`;
|
||||
}
|
||||
|
||||
function renderReadOnly() {
|
||||
const container = document.getElementById('content');
|
||||
if (!setlist) {
|
||||
container.innerHTML = me.isAdmin
|
||||
? `<p class="empty">Aucun concert à venir.</p>${metaFormTemplate()}`
|
||||
: '<p class="empty">Aucun concert à venir pour le moment.</p>';
|
||||
if (me.isAdmin) attachMetaFormHandler();
|
||||
container.innerHTML = `<p class="empty">Aucun concert à venir.</p>${metaFormTemplate()}`;
|
||||
attachMetaFormHandler();
|
||||
return;
|
||||
}
|
||||
container.innerHTML = readOnlyView();
|
||||
|
|
@ -249,9 +247,7 @@ function showError(message) {
|
|||
|
||||
(async function init() {
|
||||
me = await initNav('setlist');
|
||||
if (me.isAdmin) {
|
||||
allSongs = await api.get('/api/songs');
|
||||
}
|
||||
allSongs = await api.get('/api/songs');
|
||||
setlist = await api.get('/api/setlists/next');
|
||||
renderReadOnly();
|
||||
})();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue