MediaWiki:Gadget-CargoHelper.js

From Angelina Jordan Wiki
Revision as of 13:11, 14 November 2025 by Most2dot0 (talk | contribs) (various updates: use Performance/Video templates, provide context, UI changes)

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/* Full CargoHelper gadget with context, templates, improved UI */

mw.loader.using(["mediawiki.util", "mediawiki.api"], function () {
    if (mw.config.get('wgNamespaceNumber') !== 0) return;

    function sanitizePageName(name) {
        return name.replace(/&[#%w]+;/g, "_").replace(/[^\w_\-.]/g, "_");
    }

    function apiCargoQuery(page) {
        const apiUrl = new URL(mw.util.wikiScript('api'), location.origin);
        apiUrl.searchParams.set('action', 'cargoquery');
        apiUrl.searchParams.set('format', 'json');
        apiUrl.searchParams.set('tables', 'Performances');
        apiUrl.searchParams.set('fields', 'perfID,event,date,type,context');
        apiUrl.searchParams.set('where', 'song="' + page + '"');
        return $.getJSON(apiUrl.toString()).then(d => (d && d.cargoquery) ? d.cargoquery.map(q => q.title) : []);
    }

    function choose(list, label) {
        const msg = list.map((r, i) => (i + 1) + '. ' + label(r)).join('\n');
        const x = prompt(msg);
        if (!x) return null;
        const i = parseInt(x, 10) - 1;
        return (i >= 0 && i < list.length) ? list[i] : null;
    }

    function buildPerfTemplate(data) {
        return `{{Performance\n|song=${data.song}\n|event=${data.event}\n|context=${data.context}\n|date=${data.date}\n|type=${data.type}\n|pos=${data.pos}\n|with=${data.partners}\n|comment=${data.comment}\n|id=${data.id}\n}}`;
    }

    function buildVideoTemplate(data) {
        return `{{Video\n|pid=${data.pid}\n|url=${data.url}\n|duration=${data.duration}\n|quality=${data.quality}\n|comment=${data.comment}\n}}`;
    }

    function nextLocalID(perfs, base) {
        const prefix = sanitizePageName(base) + '_';
        let maxID = 0;
        perfs.forEach(p => {
            if (p.perfID && p.perfID.startsWith(prefix)) {
                const local = p.perfID.slice(prefix.length);
                const n = parseInt(local, 10);
                if (!isNaN(n) && n > maxID) maxID = n;
            }
        });
        return String(maxID + 1);
    }

    function insertContent(text) {
        const page = mw.config.get('wgPageName');
        const url = mw.util.getUrl(page, { action: 'edit', preload: text });
        location.href = url;
    }

    function run() {
        const page = mw.config.get('wgPageName');
        apiCargoQuery(page).then(perfs => {
            const mode = prompt('1: Add video to existing performance\n2: Create new performance and video');
            if (!mode) return;

            const cleanedPage = sanitizePageName(page);

            if (mode === '1') {
                if (!perfs.length) { alert('No performances found.'); return; }

                const perf = choose(perfs, r => r.perfID + ' — ' + r.event + ' (' + r.date + ')');
                if (!perf) return;

                const pid = perf.perfID.replace(/^.*_/, '');

                const url = prompt('Video URL:'); if (!url) return;
                const duration = prompt('Duration (full/short/fragment):') || '';
                const quality = prompt('Quality (best/good/acceptable/poor):') || '';
                const comment = prompt('Comment:') || '';

                const block = buildVideoTemplate({ pid, url, duration, quality, comment });
                insertContent(block);
                return;
            }

            if (mode === '2') {
                const event = prompt('Event:'); if (!event) return;
                const date = prompt('Date (YYYY…):'); if (!date) return;
                let context = prompt('Context (# separated):'); if (!context) return;
                const type = prompt('Type (recording/track/music-video/live/rehearsal/soundcheck/sing-along/lip-sync):') || '';
                const pos = prompt('Position:') || '';
                const partners = prompt('Partners (# separated):') || '';
                const commentP = prompt('Performance comment:') || '';

                const id = nextLocalID(perfs, page);

                const url = prompt('Video URL:'); if (!url) return;
                const duration = prompt('Duration (full/short/fragment):') || '';
                const quality = prompt('Quality (best/good/acceptable/poor):') || '';
                const commentV = prompt('Video comment:') || '';

                const perfBlock = buildPerfTemplate({ song: page, event, context, date, type, pos, partners, comment: commentP, id });
                const videoBlock = buildVideoTemplate({ pid: id, url, duration, quality, comment: commentV });

                insertContent(perfBlock + "\n\n" + videoBlock);
            }
        });
    }

    mw.util.addPortletLink('p-cactions', '#', 'Add video', 'cargo-add-video').onclick = function (e) {
        e.preventDefault();
        run();
    };
});