Changeset 6401681 in Klonkt


Ignore:
Timestamp:
08/13/2026 01:08:32 PM (4 weeks ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
f59a46c
Parents:
5300652
git-author:
Robin <roboburr@…> (08/13/2026 12:16:47 PM)
git-committer:
Robin <roboburr@…> (08/13/2026 01:08:32 PM)
Message:

Het paneel hoort bij wie je bent, niet bij je bestanden (Robins correctie)

Verhuisd van Beheer -> Audio naar het profielscherm van de site-eigenaar, en
daar staat het NAAST de aliassen -- want dat is dezelfde vraag. Een alias zegt
wie je elders in de fediverse bent, een MBID zegt wie je in het muziekregister
bent. Bij de audiobestanden ging het over beheer van spullen; hier gaat het over
identiteit, en daar hoort het thuis.

DE VERHUIZING VERANDERDE DE VORM, en dat is de moeite waard om te weten. Het
profielscherm IS een formulier, en een formulier in een formulier bestaat niet
in HTML. Dus geen eigen opslaan-knop meer: de keuze zet een verborgen veld en
gaat mee met de Opslaan van de pagina, precies zoals de profielfoto. Dat leest
ook beter -- een halve wijziging die je nog kunt herzien voor je opslaat.

Ontkoppelen is nu het veld leegmaken, geen aparte route. Minder oppervlak.

Het zoek-endpoint ging mee naar /admin/sites/:slug/api/musicbrainz. Een endpoint
onder /admin/audio laten staan voor een scherm in /admin/sites is precies zo'n
naad die later niemand meer kan plaatsen. De teksten heten nu asite.mb_* in
plaats van aaud.mb_*, in alle drie de talen, met een placeholder erbij.

Wat NIET veranderde: de zoekopdracht draait server-side (hun regel geldt per
applicatie), wij kiezen niet voor de artiest, en alleen een echte MBID komt de
kolom in.

Co-Authored-By: Claude Opus 5 <noreply@…>

Location:
src
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • src/assets/js/mod/admin-audio.js

    r5300652 r6401681  
    452452  });
    453453})();
    454 
    455   // MusicBrainz-paneel (shaer-mbz). Binnen run(), niet op moduleniveau:
    456   // deze modules krijgen bij elke paginawissel opnieuw init(), en een blok dat
    457   // maar een keer per sessie draait is precies wat shaer-5s1 opleverde.
    458   wireMusicBrainz();
    459454}
    460 
    461 // ── MusicBrainz: ben jij dit? (shaer-mbz, stap 2) ─────────────────
    462 //
    463 // De kandidaten komen van de server, want MusicBrainz eist een verzoek per
    464 // seconde per APPLICATIE en een User-Agent met contact -- allebei niet vanuit
    465 // een browser af te dwingen.
    466 //
    467 // WIJ KIEZEN NIET. Ook niet als er precies een treffer is: een verkeerd
    468 // geraden MBID zet jouw naam onder andermans werk. De knop staat er, de klik
    469 // is van de artiest.
    470 function wireMusicBrainz() {
    471   const knop = document.getElementById('mb-zoek-btn');
    472   const veld = document.getElementById('mb-q');
    473   const uit = document.getElementById('mb-uit');
    474   if (!knop || !veld || !uit || knop.__wired) return;
    475   knop.__wired = true;
    476 
    477   const el = (tag, cls, tekst) => {
    478     const e = document.createElement(tag);
    479     if (cls) e.className = cls;
    480     if (tekst != null) e.textContent = tekst;   // textContent: nooit HTML uit een vreemd register
    481     return e;
    482   };
    483 
    484   async function zoek() {
    485     const q = (veld.value || '').trim();
    486     if (!q) return;
    487     uit.hidden = false;
    488     uit.replaceChildren(el('p', 'ax-hint', T.aaud_mb_busy || 'Zoeken…'));
    489     knop.disabled = true;
    490     try {
    491       const r = await fetch(`api/musicbrainz?q=${encodeURIComponent(q)}`, { credentials: 'same-origin' });
    492       const j = await r.json();
    493       toon((j && j.kandidaten) || []);
    494     } catch {
    495       uit.replaceChildren(el('p', 'ax-hint', T.aaud_mb_fail || 'MusicBrainz is even niet bereikbaar.'));
    496     } finally {
    497       knop.disabled = false;
    498     }
    499   }
    500 
    501   function toon(kandidaten) {
    502     if (!kandidaten.length) {
    503       uit.replaceChildren(el('p', 'ax-hint', T.aaud_mb_none || 'Niets gevonden.'));
    504       return;
    505     }
    506     const lijst = el('ul', 'mb-lijst');
    507     for (const k of kandidaten) {
    508       const li = el('li', 'mb-kandidaat');
    509       li.appendChild(el('strong', null, k.naam));
    510       // De toelichting is het hele punt: er zijn drie bands die Nirvana heten,
    511       // en zonder dit veld kiest iemand de verkeerde.
    512       const bij = [k.toelichting, k.soort, k.land, k.jaren].filter(Boolean).join(' · ');
    513       if (bij) li.appendChild(el('small', 'mb-bij', bij));
    514       const open = el('a', 'mb-open', T.aaud_mb_open || 'Bekijk op MusicBrainz');
    515       open.href = k.url; open.target = '_blank'; open.rel = 'noopener';
    516       li.appendChild(open);
    517       li.appendChild(kiesForm(k));
    518       lijst.appendChild(li);
    519     }
    520     uit.replaceChildren(lijst);
    521   }
    522 
    523   function kiesForm(k) {
    524     const f = document.createElement('form');
    525     f.method = 'POST';
    526     f.action = 'musicbrainz/link';
    527     for (const [naam, waarde] of [['_csrf', csrf()], ['mbid', k.mbid], ['naam', k.naam]]) {
    528       const i = document.createElement('input');
    529       i.type = 'hidden'; i.name = naam; i.value = waarde || '';
    530       f.appendChild(i);
    531     }
    532     const b = el('button', 'ax-btn', T.aaud_mb_pick || 'Dit ben ik');
    533     b.type = 'submit';
    534     f.appendChild(b);
    535     return f;
    536   }
    537 
    538   // Het token staat al in elk formulier op deze pagina; er is er geen apart voor.
    539   const csrf = () => (document.querySelector('input[name="_csrf"]') || {}).value || '';
    540 
    541   knop.addEventListener('click', zoek);
    542   veld.addEventListener('keydown', (e) => { if (e.key === 'Enter') { e.preventDefault(); zoek(); } });
    543 }
  • src/assets/js/mod/admin-site-edit.js

    r5300652 r6401681  
    134134  }
    135135})();
     136
     137  // MusicBrainz-paneel (shaer-mbz). Binnen run(), niet op moduleniveau: deze
     138  // modules krijgen bij elke paginawissel opnieuw init(), en een blok dat maar
     139  // een keer per sessie draait is precies wat shaer-5s1 opleverde.
     140  wireMusicBrainz();
    136141}
     142
     143// ── MusicBrainz: ben jij dit? (shaer-mbz) ─────────────────────────
     144//
     145// De kandidaten komen van de server, want MusicBrainz eist een verzoek per
     146// seconde per APPLICATIE en een User-Agent met contact -- allebei niet vanuit
     147// een browser af te dwingen.
     148//
     149// WIJ KIEZEN NIET. Ook niet als er precies een treffer is: een verkeerd geraden
     150// MBID zet jouw naam onder andermans werk. De knop staat er, de klik is van de
     151// artiest. En de keuze gaat mee met de Opslaan-knop van de pagina -- een eigen
     152// formulier kan hier niet, want deze pagina IS er een.
     153function wireMusicBrainz() {
     154  const knop = document.getElementById('mb-zoek-btn');
     155  const veld = document.getElementById('mb-q');
     156  const uit = document.getElementById('mb-uit');
     157  const idVeld = document.getElementById('mb-id');
     158  const naamVeld = document.getElementById('mb-naam');
     159  const huidig = document.getElementById('mb-huidig');
     160  if (!knop || !veld || !uit || !idVeld || knop.__wired) return;
     161  knop.__wired = true;
     162
     163  const el = (tag, cls, tekst) => {
     164    const e = document.createElement(tag);
     165    if (cls) e.className = cls;
     166    // textContent en nooit innerHTML: dit is tekst uit een vreemd register.
     167    if (tekst != null) e.textContent = tekst;
     168    return e;
     169  };
     170
     171  function zet(mbid, naam) {
     172    idVeld.value = mbid || '';
     173    naamVeld.value = naam || '';
     174    if (huidig) {
     175      huidig.hidden = !mbid;
     176      const n = document.getElementById('mb-huidig-naam');
     177      const a = document.getElementById('mb-huidig-link');
     178      if (n) n.textContent = naam || mbid || '';
     179      if (a) a.href = mbid ? `https://musicbrainz.org/artist/${mbid}` : '#';
     180    }
     181    uit.hidden = true;
     182    uit.replaceChildren();
     183  }
     184
     185  const wis = document.getElementById('mb-wis');
     186  if (wis) wis.addEventListener('click', () => zet('', ''));
     187
     188  async function zoek() {
     189    const q = (veld.value || '').trim();
     190    if (!q) return;
     191    uit.hidden = false;
     192    uit.replaceChildren(el('p', 'form-hint', T.asite_mb_busy || 'Zoeken…'));
     193    knop.disabled = true;
     194    try {
     195      const r = await fetch(`api/musicbrainz?q=${encodeURIComponent(q)}`, { credentials: 'same-origin' });
     196      const j = await r.json();
     197      toon((j && j.kandidaten) || []);
     198    } catch {
     199      uit.replaceChildren(el('p', 'form-hint', T.asite_mb_fail || 'MusicBrainz is even niet bereikbaar.'));
     200    } finally {
     201      knop.disabled = false;
     202    }
     203  }
     204
     205  function toon(kandidaten) {
     206    if (!kandidaten.length) {
     207      uit.replaceChildren(el('p', 'form-hint', T.asite_mb_none || 'Niets gevonden.'));
     208      return;
     209    }
     210    const lijst = el('ul', 'mb-lijst');
     211    for (const k of kandidaten) {
     212      const li = el('li', 'mb-kandidaat');
     213      li.appendChild(el('strong', null, k.naam));
     214      // De toelichting is het hele punt: er zijn drie bands die Nirvana heten,
     215      // en zonder dit veld kiest iemand de verkeerde.
     216      const bij = [k.toelichting, k.soort, k.land, k.jaren].filter(Boolean).join(' · ');
     217      if (bij) li.appendChild(el('small', 'mb-bij', bij));
     218      const open = el('a', 'mb-open', T.asite_mb_open || 'Bekijk op MusicBrainz');
     219      open.href = k.url; open.target = '_blank'; open.rel = 'noopener';
     220      li.appendChild(open);
     221      const b = el('button', 'btn', T.asite_mb_pick || 'Dit ben ik');
     222      b.type = 'button';
     223      b.addEventListener('click', () => zet(k.mbid, k.naam));
     224      li.appendChild(b);
     225      lijst.appendChild(li);
     226    }
     227    uit.replaceChildren(lijst);
     228  }
     229
     230  knop.addEventListener('click', zoek);
     231  veld.addEventListener('keydown', (e) => { if (e.key === 'Enter') { e.preventDefault(); zoek(); } });
     232}
  • src/routes/admin-audio.js

    r5300652 r6401681  
    2323import { audioUrl } from '../services/AudioStreamService.js';
    2424import { mediaDir } from '../config/paths.js';
    25 import MusicBrainz from '../services/MusicBrainzService.js';
    2625
    2726const __dirname = path.dirname(fileURLToPath(import.meta.url));
     
    384383
    385384/** GET /admin/audio/api/albums — distinct list of album names (for datalist) */
    386 /**
    387  * "Ben jij dit?" -- kandidaten uit MusicBrainz (shaer-mbz, stap 1).
    388  *
    389  * De zoekopdracht draait HIER en niet in de browser: MusicBrainz staat een
    390  * verzoek per seconde toe per APPLICATIE, en dat is alleen af te dwingen als
    391  * alles langs een plek gaat. Bovendien eisen ze een User-Agent met contact, en
    392  * die kan een browser niet zetten.
    393  *
    394  * De keuze blijft van de artiest. Wij tonen kandidaten met hun toelichting; we
    395  * kiezen er niet zelf een, ook niet als er maar een treffer is -- een verkeerd
    396  * geraden MBID koppelt iemand aan het werk van een ander.
    397  */
    398 router.get('/api/musicbrainz', requireGod, async (req, res) => {
    399   const site = res.locals.site;
    400   if (!site) return res.status(404).json({ error: 'no_site' });
    401   // Standaard de artiestennaam die al in de site staat: negen van de tien keer
    402   // is dat precies waar iemand op zou zoeken.
    403   const q = String(req.query.q || site.author || site.title || '').trim();
    404   if (!q) return res.json({ ok: true, q: '', kandidaten: [] });
    405   const kandidaten = await MusicBrainz.zoekArtiesten(q);
    406   res.json({
    407     ok: true,
    408     q,
    409     gekoppeld: site.mb_artist_id
    410       ? { mbid: site.mb_artist_id, naam: site.mb_artist_name || '', url: MusicBrainz.artiestUrl(site.mb_artist_id) }
    411       : null,
    412     kandidaten,
    413   });
    414 });
    415 
    416 /**
    417  * De keuze vastleggen. Alleen een echte MBID komt de kolom in: de naam die we
    418  * ernaast bewaren is voor het scherm, de MBID is het enige dat naar buiten gaat.
    419  */
    420 router.post('/musicbrainz/link', requireGod, (req, res) => {
    421   const site = res.locals.site;
    422   if (!site) return res.status(404).end();
    423   const mbid = String(req.body.mbid || '').trim().toLowerCase();
    424   const naam = String(req.body.naam || '').trim().slice(0, 200);
    425   const terug = (res.locals.siteUrlBase || '') + '/admin/audio';
    426   if (!MusicBrainz.isMbid(mbid)) return res.redirect(`${terug}?error=` + encodeURIComponent('Geen geldige MusicBrainz-id.'));
    427   db.prepare('UPDATE sites SET mb_artist_id = ?, mb_artist_name = ? WHERE id = ?').run(mbid, naam || null, site.id);
    428   res.redirect(`${terug}?success=` + encodeURIComponent('Gekoppeld aan MusicBrainz.'));
    429 });
    430 
    431 /** Terugdraaien. Een verkeerde koppeling zet jouw naam onder andermans werk. */
    432 router.post('/musicbrainz/unlink', requireGod, (req, res) => {
    433   const site = res.locals.site;
    434   if (!site) return res.status(404).end();
    435   db.prepare('UPDATE sites SET mb_artist_id = NULL, mb_artist_name = NULL WHERE id = ?').run(site.id);
    436   res.redirect((res.locals.siteUrlBase || '') + '/admin/audio?success=' + encodeURIComponent('Ontkoppeld.'));
    437 });
    438 
    439385router.get('/api/albums', requireGod, (req, res) => {
    440386  const site = res.locals.site;
  • src/routes/admin-sites.js

    r5300652 r6401681  
    2727import { mediaDir } from '../config/paths.js';
    2828import AP from '../services/ActivityPubService.js';
     29import MusicBrainz from '../services/MusicBrainzService.js';
    2930
    3031
     
    322323
    323324// ==================== SAVE ====================
     325/**
     326 * "Ben jij dit?" -- kandidaten uit MusicBrainz (shaer-mbz).
     327 *
     328 * De zoekopdracht draait HIER en niet in de browser: MusicBrainz staat een
     329 * verzoek per seconde toe per APPLICATIE, en dat is alleen af te dwingen als
     330 * alles langs een plek gaat. Bovendien eisen ze een User-Agent met contact, en
     331 * die kan een browser niet zetten.
     332 *
     333 * Wij kiezen NIET. Ook niet als er precies een treffer is: een verkeerd geraden
     334 * MBID zet jouw naam onder andermans werk.
     335 */
     336router.get('/:slug/api/musicbrainz', requireSiteManagerBySlug, async (req, res) => {
     337  const site = db.prepare('SELECT title, mb_artist_id, mb_artist_name FROM sites WHERE slug = ?').get(req.params.slug);
     338  if (!site) return res.status(404).json({ error: 'no_site' });
     339  const q = String(req.query.q || site.title || '').trim();
     340  if (!q) return res.json({ ok: true, q: '', kandidaten: [] });
     341  res.json({ ok: true, q, kandidaten: await MusicBrainz.zoekArtiesten(q) });
     342});
     343
    324344router.post('/:slug/save', requireSiteManagerBySlug, async (req, res) => {
    325345  const site = db.prepare('SELECT id, ap_aliases FROM sites WHERE slug = ?').get(req.params.slug);
     
    346366  // accent: only accept colors from the curated ACCENTS list. Falls back to
    347367  // the orange default if the submitted value isn't recognised.
     368  // De MusicBrainz-koppeling (shaer-mbz). Alleen een echte MBID komt de kolom
     369  // in: zonder deze zeef sluipt er een hele URL of een handle in het veld dat
     370  // straks naar buiten gaat. Leeg is een geldige keuze -- dat is ontkoppelen.
     371  const mbRuw = String(f.mb_artist_id || '').trim().toLowerCase();
     372  const mbArtistId = MusicBrainz.isMbid(mbRuw) ? mbRuw : null;
     373
    348374  const accent = ThemeService.validateAccent(f.accent) || '#e8b04b';
    349375
     
    355381      profile_links = ?,
    356382      ap_aliases = ?,
     383      mb_artist_id = ?, mb_artist_name = ?,
    357384      is_public = ?, robots_index = ?, require_login_to_comment = ?,
    358385      enable_audio_player = ?,
     
    374401    profileLinksJson,
    375402    apAliasesJson,
     403    mbArtistId,
     404    mbArtistId ? (String(f.mb_artist_name || '').trim().slice(0, 200) || null) : null,
    376405    f.is_public ? 1 : 0,
    377406    f.robots_index ? 1 : 0,
  • src/services/i18n.js

    r5300652 r6401681  
    360360    'aaud.fedi_off': 'Niet op de fediverse gedeeld (alleen webspeler, bestand verborgen) — klik om te delen',
    361361    'aaud.embed_player': 'Embedbare speler',
    362     'aaud.mb_title': 'Ben jij dit in MusicBrainz?',
    363     'aaud.mb_hint': 'MusicBrainz is het open register waar muziekdiensten je aan herkennen. Zoek jezelf op en kies je eigen pagina — dan weten anderen dat jouw muziek van jou is.',
    364     'aaud.mb_search': 'Zoeken',
    365     'aaud.mb_none': 'Niets gevonden. Sta je er nog niet in? Dan kun je jezelf aanmelden op musicbrainz.org — dat kan alleen daar, niet vanuit Klonkt.',
    366     'aaud.mb_pick': 'Dit ben ik',
    367     'aaud.mb_linked': 'Gekoppeld aan',
    368     'aaud.mb_unlink': 'Ontkoppelen',
    369     'aaud.mb_open': 'Bekijk op MusicBrainz',
    370     'aaud.mb_busy': 'Zoeken…',
    371     'aaud.mb_fail': 'MusicBrainz is even niet bereikbaar.',
     362    'asite.mb_title': 'Ben jij dit in MusicBrainz?',
     363    'asite.mb_hint': 'MusicBrainz is het open register waar muziekdiensten je aan herkennen. Zoek jezelf op en kies je eigen pagina — dan weten anderen dat jouw muziek van jou is.',
     364    'asite.mb_search': 'Zoeken',
     365    'asite.mb_placeholder': 'Je artiestennaam',
     366    'asite.mb_none': 'Niets gevonden. Sta je er nog niet in? Dan kun je jezelf aanmelden op musicbrainz.org — dat kan alleen daar, niet vanuit Klonkt.',
     367    'asite.mb_pick': 'Dit ben ik',
     368    'asite.mb_linked': 'Gekoppeld aan',
     369    'asite.mb_unlink': 'Ontkoppelen',
     370    'asite.mb_open': 'Bekijk op MusicBrainz',
     371    'asite.mb_busy': 'Zoeken…',
     372    'asite.mb_fail': 'MusicBrainz is even niet bereikbaar.',
    372373    'aaud.embed_hint': 'Plak deze code op je eigen website/blog om je muziek met deze speler in te sluiten:',
    373374    'aaud.preview_player': 'Speler-voorbeeld openen',
     
    13171318    'aaud.fedi_off': 'Not shared on the fediverse (web player only, file hidden) — click to share',
    13181319    'aaud.embed_player': 'Embeddable player',
    1319     'aaud.mb_title': 'Is this you on MusicBrainz?',
    1320     'aaud.mb_hint': 'MusicBrainz is the open register music services recognise you by. Look yourself up and pick your own page — then others know your music is yours.',
    1321     'aaud.mb_search': 'Search',
    1322     'aaud.mb_none': 'Nothing found. Not in there yet? You can add yourself on musicbrainz.org — that can only be done there, not from Klonkt.',
    1323     'aaud.mb_pick': 'This is me',
    1324     'aaud.mb_linked': 'Linked to',
    1325     'aaud.mb_unlink': 'Unlink',
    1326     'aaud.mb_open': 'View on MusicBrainz',
    1327     'aaud.mb_busy': 'Searching…',
    1328     'aaud.mb_fail': 'MusicBrainz is unreachable right now.',
     1320    'asite.mb_title': 'Is this you on MusicBrainz?',
     1321    'asite.mb_hint': 'MusicBrainz is the open register music services recognise you by. Look yourself up and pick your own page — then others know your music is yours.',
     1322    'asite.mb_search': 'Search',
     1323    'asite.mb_placeholder': 'Your artist name',
     1324    'asite.mb_none': 'Nothing found. Not in there yet? You can add yourself on musicbrainz.org — that can only be done there, not from Klonkt.',
     1325    'asite.mb_pick': 'This is me',
     1326    'asite.mb_linked': 'Linked to',
     1327    'asite.mb_unlink': 'Unlink',
     1328    'asite.mb_open': 'View on MusicBrainz',
     1329    'asite.mb_busy': 'Searching…',
     1330    'asite.mb_fail': 'MusicBrainz is unreachable right now.',
    13291331    'aaud.embed_hint': 'Paste this code on your own website/blog to embed your music with this player:',
    13301332    'aaud.preview_player': 'Open player preview',
     
    22732275    'aaud.fedi_off': 'Nicht im Fediverse geteilt (nur Web-Player, Datei verborgen) — zum Teilen klicken',
    22742276    'aaud.embed_player': 'Einbettbarer Player',
    2275     'aaud.mb_title': 'Bist das du bei MusicBrainz?',
    2276     'aaud.mb_hint': 'MusicBrainz ist das offene Register, an dem Musikdienste dich erkennen. Suche dich und wähle deine eigene Seite — dann wissen andere, dass deine Musik von dir ist.',
    2277     'aaud.mb_search': 'Suchen',
    2278     'aaud.mb_none': 'Nichts gefunden. Noch nicht dabei? Du kannst dich auf musicbrainz.org eintragen — das geht nur dort, nicht aus Klonkt heraus.',
    2279     'aaud.mb_pick': 'Das bin ich',
    2280     'aaud.mb_linked': 'Verknüpft mit',
    2281     'aaud.mb_unlink': 'Trennen',
    2282     'aaud.mb_open': 'Bei MusicBrainz ansehen',
    2283     'aaud.mb_busy': 'Suche läuft…',
    2284     'aaud.mb_fail': 'MusicBrainz ist gerade nicht erreichbar.',
     2277    'asite.mb_title': 'Bist das du bei MusicBrainz?',
     2278    'asite.mb_hint': 'MusicBrainz ist das offene Register, an dem Musikdienste dich erkennen. Suche dich und wähle deine eigene Seite — dann wissen andere, dass deine Musik von dir ist.',
     2279    'asite.mb_search': 'Suchen',
     2280    'asite.mb_placeholder': 'Dein Künstlername',
     2281    'asite.mb_none': 'Nichts gefunden. Noch nicht dabei? Du kannst dich auf musicbrainz.org eintragen — das geht nur dort, nicht aus Klonkt heraus.',
     2282    'asite.mb_pick': 'Das bin ich',
     2283    'asite.mb_linked': 'Verknüpft mit',
     2284    'asite.mb_unlink': 'Trennen',
     2285    'asite.mb_open': 'Bei MusicBrainz ansehen',
     2286    'asite.mb_busy': 'Suche läuft…',
     2287    'asite.mb_fail': 'MusicBrainz ist gerade nicht erreichbar.',
    22852288    'aaud.embed_hint': 'Füge diesen Code auf deiner eigenen Website/deinem Blog ein, um deine Musik mit diesem Player einzubetten:',
    22862289    'aaud.preview_player': 'Player-Vorschau öffnen',
  • src/views/pages/admin-audio.ejs

    r5300652 r6401681  
    1212  <% if (success) { %><div class="ax-flash ax-flash-ok"><%= success %></div><% } %>
    1313  <% if (error) { %><div class="ax-flash ax-flash-err"><%= error %></div><% } %>
    14 
    15   <%# ── MUSICBRAINZ ─────────────────────────────────────────────
    16       Wie ben jij, buiten Klonkt? Een MBID is geen vocabulaire maar een
    17       register: eraan koppelen is als je ISBN noemen. Andere muziekdiensten
    18       -- Funkwhale voorop -- herkennen je eraan zonder dat wij hun model
    19       hoeven over te nemen (shaer-mbz). %>
    20   <section class="ax-card" id="mb-card">
    21     <div class="ax-card-title"><%= t('aaud.mb_title') %></div>
    22     <p class="ax-hint"><%= t('aaud.mb_hint') %></p>
    23 
    24     <% if (site.mb_artist_id) { %>
    25       <p class="mb-linked">
    26         <%= t('aaud.mb_linked') %>
    27         <strong><%= site.mb_artist_name || site.mb_artist_id %></strong>
    28         <a href="https://musicbrainz.org/artist/<%= site.mb_artist_id %>"
    29            target="_blank" rel="noopener"><%= t('aaud.mb_open') %></a>
    30       </p>
    31       <%# Ontkoppelen moet kunnen: een verkeerde koppeling zet jouw naam onder
    32           andermans werk, en dat hoort met een klik terug te draaien zijn. %>
    33       <form method="POST" action="<%= (typeof siteUrlBase !== 'undefined' ? siteUrlBase : '') %>/admin/audio/musicbrainz/unlink">
    34         <input type="hidden" name="_csrf" value="<%= csrfToken %>">
    35         <button type="submit" class="ax-btn ax-btn-quiet"><%= t('aaud.mb_unlink') %></button>
    36       </form>
    37     <% } %>
    38 
    39     <div class="mb-zoek">
    40       <input type="text" id="mb-q" value="<%= site.author || site.title || '' %>"
    41              placeholder="<%= t('aaud.artist') %>" autocomplete="off">
    42       <button type="button" class="ax-btn" id="mb-zoek-btn"><%= t('aaud.mb_search') %></button>
    43     </div>
    44     <div id="mb-uit" class="mb-uit" hidden></div>
    45   </section>
    4614
    4715  <%# ── UPLOAD ──────────────────────────────────────────────── %>
  • src/views/pages/admin-site-edit.ejs

    r5300652 r6401681  
    190190    </fieldset>
    191191
     192    <%# ── MUSICBRAINZ ─────────────────────────────────────────────
     193        Naast de aliassen, want het is dezelfde vraag: wie ben jij elders?
     194        Een MBID is geen vocabulaire maar een register -- eraan koppelen is als
     195        je ISBN noemen, en muziekdiensten herkennen je eraan zonder dat wij hun
     196        model hoeven over te nemen (shaer-mbz).
     197
     198        GEEN EIGEN FORMULIER: deze pagina IS er een, en een formulier in een
     199        formulier bestaat niet in HTML. De keuze zet een verborgen veld en gaat
     200        mee met de Opslaan-knop van de pagina, net als de profielfoto. %>
     201    <fieldset id="mb-veld">
     202      <legend><%= t('asite.mb_title') %></legend>
     203      <p class="form-hint"><%= t('asite.mb_hint') %></p>
     204
     205      <input type="hidden" name="mb_artist_id" id="mb-id" value="<%= site.mb_artist_id || '' %>">
     206      <input type="hidden" name="mb_artist_name" id="mb-naam" value="<%= site.mb_artist_name || '' %>">
     207
     208      <p class="mb-huidig" id="mb-huidig" <%= site.mb_artist_id ? '' : 'hidden' %>>
     209        <%= t('asite.mb_linked') %>
     210        <strong id="mb-huidig-naam"><%= site.mb_artist_name || site.mb_artist_id || '' %></strong>
     211        <a id="mb-huidig-link" target="_blank" rel="noopener"
     212           href="https://musicbrainz.org/artist/<%= site.mb_artist_id || '' %>"><%= t('asite.mb_open') %></a>
     213        <button type="button" class="btn" id="mb-wis"><%= t('asite.mb_unlink') %></button>
     214      </p>
     215
     216      <div class="mb-zoek">
     217        <input type="text" id="mb-q" value="<%= site.title || '' %>" autocomplete="off"
     218               placeholder="<%= t('asite.mb_placeholder') %>">
     219        <button type="button" class="btn" id="mb-zoek-btn"><%= t('asite.mb_search') %></button>
     220      </div>
     221      <div id="mb-uit" class="mb-uit" hidden></div>
     222    </fieldset>
     223
    192224    <fieldset>
    193225      <legend><%= t('asite.feed_view') %></legend>
Note: See TracChangeset for help on using the changeset viewer.