Changeset 749605a in Klonkt for src/assets/js/mod/playlist-editor.js
- Timestamp:
- 08/16/2026 03:06:18 PM (3 weeks ago)
- Branches:
- main
- Children:
- a5caa73
- Parents:
- a5515b4 (diff), 9026de5 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - File:
-
- 1 edited
-
src/assets/js/mod/playlist-editor.js (modified) (21 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/assets/js/mod/playlist-editor.js
ra5515b4 r749605a 6 6 7 7 import { pageData } from './lib.js'; 8 9 /** 10 * De teksten van deze modal, uit het gegevensblok van partials/playlist-editor.ejs. 11 * 12 * EIGEN BLOK en niet pageData(): die pakt met querySelector er EEN, en deze 13 * modal hangt onder pagina's die er zelf al een hebben. Een tweede blok zou 14 * daar genegeerd worden. 15 * 16 * De terugval is bewust de sleutelnaam en niet de Nederlandse tekst: ontbreekt 17 * er iets, dan zie je DAT er iets ontbreekt in plaats van een pagina die er 18 * half vertaald uitziet en waarvan niemand merkt welke helft. 19 */ 20 let _T = null; 21 function T(sleutel) { 22 if (_T === null) { 23 try { 24 const el = document.querySelector('script[type="application/json"][data-playlist-editor-i18n]'); 25 _T = el ? (JSON.parse(el.textContent) || {}) : {}; 26 } catch (e) { _T = {}; } 27 } 28 return _T[sleutel] != null ? _T[sleutel] : sleutel; 29 } 8 30 9 31 (function() { … … 54 76 if (Array.isArray(j.tracks)) tracks = j.tracks; 55 77 } catch (e) { 56 alert( 'Tracks ophalen mislukt');78 alert(T('e_tracks')); 57 79 return; 58 80 } 59 81 if (!tracks.length) { 60 alert( 'Geen audio-tracks beschikbaar. Upload eerst tracks via Admin → Audio.');82 alert(T('e_geen_tracks')); 61 83 return; 62 84 } 63 85 64 86 // Existing playlist data when editing 65 let initial = { title: '', artist: '', year: '', cover: '', kind: 'album', track_ids: [] };87 let initial = { title: '', artist: '', year: '', cover: '', kind: 'album', release_date: '', mb_release_id: '', track_ids: [] }; 66 88 if (isEdit && opts.id) { 67 89 try { … … 75 97 backdrop.className = 'pl-modal-backdrop'; 76 98 backdrop.innerHTML = ` 77 <div class="pl-modal" role="dialog" aria-label=" Playlist editor">99 <div class="pl-modal" role="dialog" aria-label="${T('dialoog')}"> 78 100 <div class="pl-modal-header"> 79 <h3>${isEdit ? '✎ Playlist bewerken' : '+ Nieuwe playlist'}</h3>80 <button type="button" class="pl-modal-close" aria-label=" Sluiten">×</button>101 <h3>${isEdit ? '✎ ' + T('t_edit') : '+ ' + T('t_new')}</h3> 102 <button type="button" class="pl-modal-close" aria-label="${T('sluiten')}">×</button> 81 103 </div> 82 104 <div class="pl-modal-body"> … … 85 107 <div class="pl-meta-grid"> 86 108 <label class="pl-field pl-field-full"> 87 <span> Titel *</span>109 <span>${T('titel')}</span> 88 110 <input type="text" id="pli-title" maxlength="200" autofocus value="${esc(initial.title)}"> 89 111 </label> 90 112 <label class="pl-field"> 91 <span> Artiest</span>113 <span>${T('artiest')}</span> 92 114 <input type="text" id="pli-artist" maxlength="200" value="${esc(initial.artist)}"> 93 115 </label> 94 116 <label class="pl-field"> 95 <span> Jaar</span>117 <span>${T('jaar')}</span> 96 118 <input type="number" id="pli-year" min="1900" max="2099" value="${initial.year || ''}"> 97 119 </label> 98 120 <label class="pl-field"> 99 <span> Type</span>121 <span>${T('type')}</span> 100 122 <select id="pli-kind"> 101 <option value="album" ${initial.kind === 'album' ? 'selected' : ''}>💿 Album (genummerd)</option>102 <option value="playlist" ${initial.kind === 'playlist' ? 'selected' : ''}>📃 Playlist (track-covers)</option>123 <option value="album" ${initial.kind === 'album' ? 'selected' : ''}>💿 ${T('k_album')}</option> 124 <option value="playlist" ${initial.kind === 'playlist' ? 'selected' : ''}>📃 ${T('k_playlist')}</option> 103 125 </select> 104 126 </label> 127 <label class="pl-field pl-uitgave"> 128 <span>${T('uitgave')}</span> 129 <input type="date" id="pli-release-date" value="${esc(initial.release_date || '')}"> 130 </label> 131 <label class="pl-field pl-uitgave"> 132 <span>${T('mb_release')}</span> 133 <input type="text" id="pli-mb-release" maxlength="36" spellcheck="false" 134 placeholder="00000000-0000-0000-0000-000000000000" 135 value="${esc(initial.mb_release_id || '')}"> 136 </label> 105 137 <div class="pl-field pl-field-full"> 106 <span> Cover</span>138 <span>${T('cover')}</span> 107 139 <div class="pl-cover-row"> 108 140 <span class="pl-cover-thumb" id="pli-cover-thumb"> … … 111 143 : `<span class="pl-cover-empty">🎨</span>`} 112 144 </span> 113 <input type="text" id="pli-cover" placeholder=" https://… of upload" value="${esc(initial.cover)}" style="flex:1">145 <input type="text" id="pli-cover" placeholder="${T('cover_url')}" value="${esc(initial.cover)}" style="flex:1"> 114 146 </div> 115 147 <div class="pl-cover-upload-row"> 116 148 <input type="file" id="pli-cover-file" accept="image/jpeg,image/png,image/webp,image/gif" hidden> 117 <button type="button" class="pl-btn-small" id="pli-cover-pick">📷 Foto kiezen…</button>149 <button type="button" class="pl-btn-small" id="pli-cover-pick">📷 ${T('cover_kies')}</button> 118 150 <span class="pl-cover-status" id="pli-cover-status"></span> 119 151 </div> … … 121 153 </div> 122 154 <div class="pl-section-title"> 123 Tracks in playlist<span class="pl-track-count" id="pli-count">0</span>124 <small> (sleep ⠿ om te ordenen)</small>155 ${T('tracks_in')} <span class="pl-track-count" id="pli-count">0</span> 156 <small>${T('sleep_hint')}</small> 125 157 </div> 126 158 <div id="pli-selected" class="pl-selected-list"></div> 127 159 </div> 128 160 <div class="pl-editor-right"> 129 <div class="pl-section-title"> Beschikbare tracks</div>130 <input type="search" id="pli-search" placeholder=" Zoek..." class="pl-search-input">161 <div class="pl-section-title">${T('beschikbaar')}</div> 162 <input type="search" id="pli-search" placeholder="${T('zoek')}" class="pl-search-input"> 131 163 <div id="pli-available" class="pl-available-list"></div> 132 164 </div> … … 134 166 </div> 135 167 <div class="pl-modal-footer"> 136 <button type="button" class="btn" id="pli-cancel"> Annuleren</button>168 <button type="button" class="btn" id="pli-cancel">${T('annuleren')}</button> 137 169 <button type="button" class="btn btn-primary" id="pli-save" disabled> 138 ${isEdit ? 'Opslaan' : 'Aanmaken'}170 ${isEdit ? T('opslaan') : T('aanmaken')} 139 171 </button> 140 172 </div> … … 157 189 const yearEl = $('#pli-year'); 158 190 const kindEl = $('#pli-kind'); 191 const releaseEl = $('#pli-release-date'); 192 const mbReleaseEl = $('#pli-mb-release'); 159 193 const coverEl = $('#pli-cover'); 194 195 // Uitgavedatum en release-id horen bij een ALBUM, niet bij een 196 // afspeellijst -- dat is wat de keuze album/playlist betekent. Ze 197 // verdwijnen dus als je omschakelt, en de server maakt ze dan ook leeg; 198 // dit scherm is de uitleg, niet de bewaking. 199 const toonUitgave = () => { 200 const album = kindEl.value !== 'playlist'; 201 for (const el of backdrop.querySelectorAll('.pl-uitgave')) el.hidden = !album; 202 }; 203 kindEl.addEventListener('change', toonUitgave); 204 toonUitgave(); 160 205 const coverThumb = $('#pli-cover-thumb'); 161 206 const saveBtn = $('#pli-save'); … … 176 221 // requireAuth) dat een /media/-URL teruggeeft — dat heeft GEEN playlist-id 177 222 // nodig, dus uploaden kan ook al vóór het aanmaken. De URL belandt in het 178 // cover-veld en wordt bij 'Aanmaken'/'Opslaan'met de playlist meegestuurd.223 // cover-veld en wordt bij het opslaan met de playlist meegestuurd. 179 224 const coverFileInput = $('#pli-cover-file'); 180 225 const coverPickBtn = $('#pli-cover-pick'); … … 187 232 if (!file) return; 188 233 if (!/^image\//.test(file.type)) { 189 coverStatus.textContent = 'Alleen afbeeldingen';234 coverStatus.textContent = T('e_alleen_afb'); 190 235 coverStatus.className = 'pl-cover-status is-error'; 191 236 return; 192 237 } 193 coverStatus.textContent = 'Uploaden…';238 coverStatus.textContent = T('bezig'); 194 239 coverStatus.className = 'pl-cover-status'; 195 240 const fd = new FormData(); … … 200 245 ); 201 246 const j = await r.json(); 202 if (!r.ok || !j.url) throw new Error(j.error || 'Upload mislukt');247 if (!r.ok || !j.url) throw new Error(j.error || T('e_upload')); 203 248 const url = j.url || ''; 204 249 coverEl.value = url; … … 209 254 coverStatus.className = 'pl-cover-status is-ok'; 210 255 } catch (err) { 211 coverStatus.textContent = 'Mislukt: '+ err.message;256 coverStatus.textContent = T('e_mislukt') + err.message; 212 257 coverStatus.className = 'pl-cover-status is-error'; 213 258 } … … 222 267 countEl.textContent = selected.length; 223 268 if (selected.length === 0) { 224 selectedEl.innerHTML = '<div class="pl-empty"> Klik tracks rechts om toe te voegen.</div>';269 selectedEl.innerHTML = '<div class="pl-empty">' + T('leeg_sel') + '</div>'; 225 270 updateSaveBtn(); 226 271 return; … … 233 278 : `<span class="pl-row-cover pl-row-cover-empty">♪</span>`; 234 279 return `<div class="pl-row" data-id="${esc(id)}" data-pos="${i}"> 235 <span class="pl-row-handle" aria-label=" Verslepen">⠿</span>280 <span class="pl-row-handle" aria-label="${T('versleep')}">⠿</span> 236 281 <span class="pl-row-num">${i + 1}</span> 237 282 ${cover} … … 240 285 ${t.artist ? `<span class="pl-row-artist">${esc(t.artist)}</span>` : ''} 241 286 </span> 242 <button type="button" class="pl-row-x" data-id="${esc(id)}" aria-label=" Verwijderen">×</button>287 <button type="button" class="pl-row-x" data-id="${esc(id)}" aria-label="${T('verwijder')}">×</button> 243 288 </div>`; 244 289 }).join(''); … … 263 308 }); 264 309 if (matches.length === 0) { 265 availEl.innerHTML = '<div class="pl-empty"> Geen resultaten.</div>';310 availEl.innerHTML = '<div class="pl-empty">' + T('geen_res') + '</div>'; 266 311 return; 267 312 } … … 274 319 ? `<span class="pl-row-cover"><img src="${esc(t.cover)}" alt=""></span>` 275 320 : `<span class="pl-row-cover pl-row-cover-empty">♪</span>`; 276 return `<div class="${cls.join(' ')}" data-id="${esc(t.id)}" ${t.playable ? '' : 'title="Track heeft geen audio-bestand"'}>321 return `<div class="${cls.join(' ')}" data-id="${esc(t.id)}" ${t.playable ? '' : `title="${T('geen_audio')}"`}> 277 322 ${cover} 278 323 <span class="pl-row-info"> … … 368 413 const orig = saveBtn.textContent; 369 414 saveBtn.disabled = true; 370 saveBtn.textContent = 'Opslaan...';415 saveBtn.textContent = T('bezig_opslaan'); 371 416 372 417 const payload = { … … 376 421 cover: coverEl.value.trim(), 377 422 kind: kindEl.value === 'playlist' ? 'playlist' : 'album', 423 release_date: releaseEl.value.trim(), 424 mb_release_id: mbReleaseEl.value.trim(), 378 425 tracks: selected.slice(), 379 426 }; … … 385 432 const j = await api('POST', url, payload); 386 433 if (!j.ok) { 387 alert( 'Opslaan mislukt: '+ (j.error || 'onbekend'));434 alert(T('e_opslaan') + (j.error || 'onbekend')); 388 435 saveBtn.disabled = false; 389 436 saveBtn.textContent = orig; … … 396 443 } 397 444 } catch (err) { 398 alert( 'Opslaan mislukt: '+ err.message);445 alert(T('e_opslaan') + err.message); 399 446 saveBtn.disabled = false; 400 447 saveBtn.textContent = orig;
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)