MediaWiki:Gadget-CargoHelper.js
From Angelina Jordan Wiki
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.
mw.loader.using(['mediawiki.api', 'ext.cargo.main']).then(function () {
const api = new mw.Api();
const page = mw.config.get('wgPageName');
// Sanitize page name the same way the Lua module does (compatible)
function sanitizeForPerfID(title) {
title = title.replace(/&[#\w]+;/g, "_");
title = title.replace(/[^A-Za-z0-9_.-]/g, "_");
return title;
}
// Compute next available local ID
function nextLocalId(perfIDs, sanitizedPage) {
let max = 0;
perfIDs.forEach(id => {
if (!id.startsWith(sanitizedPage + "_")) return;
const local = id.slice(sanitizedPage.length + 1);
const m = local.match(/^(\d+)/);
if (m) {
const n = parseInt(m[1], 10);
if (n > max) max = n;
}
});
return String(max + 1);
}
// Query existing performances for this page
function queryPerformances() {
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(data => {
if (data && data.cargoquery) {
return data.cargoquery.map(e => e.title);
}
return [];
});
}
// Redirect to preload editor
function buildAndRedirect(perfBlock, videoBlock) {
const url = mw.util.getUrl(page, {
action: "edit",
section: "new",
preload: "Template:CargoAddVideoPreload",
"preloadparams[]": [perfBlock, videoBlock]
});
window.location.href = url;
}
// Main driver
function openMinimalPrompt() {
queryPerformances().then(rows => {
const sanitized = sanitizeForPerfID(page);
const perfIds = rows.map(r => r.perfID);
const suggestedLocal = nextLocalId(perfIds, sanitized);
const suggestedPerfID = sanitized + "_" + suggestedLocal;
const chooseExisting = confirm(
"Select OK to attach video to an existing Performance.\n" +
"Select Cancel to create a new Performance."
);
// ------------------------------------------------------------
// EXISTING PERFORMANCE PATH (no new performance creation)
// ------------------------------------------------------------
if (chooseExisting) {
if (rows.length === 0) {
alert("No existing performances found. A new performance must be created.");
return;
}
const list = rows.map((r, i) =>
(i + 1) + ". " + r.perfID + " — " + r.event + " (" + r.date + ")"
).join("\n");
const index = prompt(
"Choose performance by number:\n\n" + list
);
const i = parseInt(index, 10) - 1;
if (isNaN(i) || i < 0 || i >= rows.length)
return;
const perfID = rows[i].perfID;
// --- Video prompts ---
const videoUrl = prompt("Video URL (mandatory):");
if (!videoUrl) return;
const videoDuration = prompt("Duration (full/short/fragment) optional:", "");
const videoQuality = prompt("Quality (best/good/acceptable/poor) optional:", "");
const videoComment = prompt("Comment (optional):", "");
const videoRating = prompt("Rating (optional integer):", "");
// --- Video-only block ---
const videoBlock =
`{{#cargo_store: _table=Videos
|perfID=${perfID}
|url=${videoUrl}
|duration=${videoDuration || ""}
|quality=${videoQuality || ""}
|comment=${videoComment || ""}
|rating=${videoRating || ""}
}}`;
// Preload only the video block
buildAndRedirect("", videoBlock);
return;
}
// ------------------------------------------------------------
// NEW PERFORMANCE PATH
// ------------------------------------------------------------
const event = prompt("Performance event (mandatory):");
const date = prompt("Performance date (mandatory, YYYY…):");
const type = prompt("Performance type (recording/track/music-video/live/...):");
if (!event || !date || !type) return;
// --- Video prompts ---
const videoUrl = prompt("Video URL (mandatory):");
if (!videoUrl) return;
const videoDuration = prompt("Duration (full/short/fragment) optional:", "");
const videoQuality = prompt("Quality (best/good/acceptable/poor) optional:", "");
const videoComment = prompt("Comment (optional):", "");
const videoRating = prompt("Rating (optional integer):", "");
// --- Performance block ---
const perfBlock =
`{{#cargo_store: _table=Performances
|song=${page}
|event=${event}
|context=
|date=${date}
|type=${type}
|perfID=${suggestedPerfID}
|page=${page}
}}`;
// --- Video block ---
const videoBlock =
`{{#cargo_store: _table=Videos
|perfID=${suggestedPerfID}
|url=${videoUrl}
|duration=${videoDuration || ""}
|quality=${videoQuality || ""}
|comment=${videoComment || ""}
|rating=${videoRating || ""}
}}`;
buildAndRedirect(perfBlock, videoBlock);
});
}
// Add portlet link
function addButton() {
mw.util.addPortletLink(
"p-cactions",
"#",
"Add Video",
"cargo-add-video",
"Add Video / Performance"
).addEventListener("click", function (e) {
e.preventDefault();
openMinimalPrompt();
});
}
if (mw.config.get('wgNamespaceNumber') === 0) {
addButton();
}
});