User:BlankEclair/SpecialUploadPrefillFromComic.js: Difference between revisions
Content added Content deleted
BlankEclair (talk | contribs) (Update to production version) |
BlankEclair (talk | contribs) (Update to wiki prod version) |
||
Line 90: | Line 90: | ||
this.pageInput = new mw.widgets.TitleInputWidget({ |
this.pageInput = new mw.widgets.TitleInputWidget({ |
||
required: true, |
required: true, |
||
showMissing: false, |
|||
}); |
}); |
||
var pageField = new OO.ui.FieldLayout(this.pageInput, { |
var pageField = new OO.ui.FieldLayout(this.pageInput, { |
Revision as of 05:53, 9 June 2024
"use strict";
/* MISCELLANEOUS FUNCTIONS */
//const SUPC_MESSAGES = require("./SpecialUploadPrefillFromComic-i18n.json");
const SUPC_MESSAGES = {
"en": {
"close-button": "Close",
"continue-button": "Continue",
"prefill-description-from-comic-page-button": "Prefill description from comic page",
"prefill-dialog-title": "Prefill description",
"required-fields-unfilled": "Please fill in all required fields",
"cannot-find-link": "Failed to find direct link to the comic's source",
"cannot-find-synopsis": "Failed to automatically locate comic page synopsis",
"unexpected-error": "An unexpected error occured",
"overrides-description-warning": "Warning: Going through this prefill process will erase all text currently in the description field",
"page-input-header": "What comic page is this image from? (required)",
"description-select-header": "Image description:",
"description-auto": "Obtain from comic page automatically",
"description-manual": "Enter manually",
"description-input-placeholder": "e.g. Rain from Rain reading Rain",
"source-select-header": "Where was this image taken from? (required)",
"deviantart": "Deviantart",
"smackjeeves": "SmackJeeves",
"comicfury": "Comicfury",
"tapas": "Tapas",
"image-type-header": "What type of image is this? (sets license)",
"image-unspecified": "Unspecified (does not set license)",
"image-comic": "A comic page",
"image-crop": "Part of a comic page"
}
};
function getMessage(key) {
var languageCode = document.documentElement.lang;
if (languageCode === "qqx") {
return "(" + key + ")";
}
var messages = SUPC_MESSAGES[languageCode] || SUPC_MESSAGES.en;
return messages[key] || SUPC_MESSAGES.en[key] || "(" + key + ")";
}
function getDefaultDescription() {
return document.querySelector("#wpUploadDescription").textContent;
}
function getCurrentDescription() {
return document.querySelector("#wpUploadDescription").value;
}
function setCurrentDescription(text) {
document.querySelector("#wpUploadDescription").value = text;
}
function setLicense(key) {
document.querySelector("#wpLicense").value = key;
}
/* PREFILL DIALOG */
function PrefillDialog(config) {
PrefillDialog.super.call(this, config);
}
OO.inheritClass(PrefillDialog, OO.ui.ProcessDialog);
PrefillDialog.static.name = "prefillDialog";
PrefillDialog.static.title = getMessage("prefill-dialog-title");
PrefillDialog.static.actions = [
{
label: getMessage("close-button"),
flags: ["safe", "close"],
},
{
action: "continue",
label: getMessage("continue-button"),
flags: ["primary", "progressive"],
},
];
PrefillDialog.prototype.initialize = function() {
PrefillDialog.super.prototype.initialize.apply(this, arguments);
this.content = new OO.ui.PanelLayout({
padded: true,
expanded: false,
});
if (getCurrentDescription() !== getDefaultDescription()) {
var p = document.createElement("p");
p.innerText = getMessage("overrides-description-warning");
this.content.$element.append(p, document.createElement("hr"));
}
this.pageInput = new mw.widgets.TitleInputWidget({
required: true,
showMissing: false,
});
var pageField = new OO.ui.FieldLayout(this.pageInput, {
label: getMessage("page-input-header"),
align: "top",
});
this.content.$element.append(pageField.$element);
this.descriptionSourceSelect = new OO.ui.RadioSelectWidget({
items: [
new OO.ui.RadioOptionWidget({
data: "auto",
label: getMessage("description-auto"),
}),
new OO.ui.RadioOptionWidget({
data: "manual",
selected: true,
label: getMessage("description-manual"),
}),
],
});
var descriptionSourceField = new OO.ui.FieldLayout(this.descriptionSourceSelect, {
label: getMessage("description-select-header"),
align: "top",
});
descriptionSourceField.$element.addClass("description-source-field-layout");
this.content.$element.append(descriptionSourceField.$element);
this.manualDescriptionInput = new OO.ui.MultilineTextInputWidget({
placeholder: getMessage("description-input-placeholder"),
});
this.manualDescriptionInput.$element.addClass("manual-description-field-layout");
this.content.$element.append(this.manualDescriptionInput.$element);
this.sourceSelect = new OO.ui.RadioSelectWidget({
items: [
new OO.ui.RadioOptionWidget({
data: "deviantart",
label: getMessage("deviantart"),
}),
new OO.ui.RadioOptionWidget({
data: "smackjeeves",
label: getMessage("smackjeeves"),
}),
new OO.ui.RadioOptionWidget({
data: "comic-fury",
label: getMessage("comicfury"),
}),
new OO.ui.RadioOptionWidget({
data: "tapas",
label: getMessage("tapas"),
}),
],
});
var sourceField = new OO.ui.FieldLayout(this.sourceSelect, {
label: getMessage("source-select-header"),
align: "top",
});
this.content.$element.append(sourceField.$element);
this.typeSelect = new OO.ui.RadioSelectWidget({
items: [
new OO.ui.RadioOptionWidget({
selected: true,
label: getMessage("image-unspecified"),
}),
new OO.ui.RadioOptionWidget({
data: "Comic",
label: getMessage("image-comic"),
}),
new OO.ui.RadioOptionWidget({
data: "Copyright FairUse",
label: getMessage("image-crop"),
}),
],
});
var typeField = new OO.ui.FieldLayout(this.typeSelect, {
label: getMessage("image-type-header"),
align: "top",
});
this.content.$element.append(typeField.$element);
this.$body.append(this.content.$element);
};
PrefillDialog.prototype.requiredFieldsFilled = function() {
return this.pageInput.getValue() && this.sourceSelect.findSelectedItem();
};
PrefillDialog.prototype.getActionProcess = function(action) {
var dialog = this;
if (action === "continue") {
if (!this.requiredFieldsFilled()) {
mw.notify(getMessage("required-fields-unfilled"), {type: "error"});
return new OO.ui.Process(function() {});
}
var pageTitle = this.pageInput.getValue();
var automaticImageDescription = this.descriptionSourceSelect.findSelectedItem().getData() === "auto";
var imageDescription = this.manualDescriptionInput.getValue();
var sourceClass = this.sourceSelect.findSelectedItem().getData();
var licenseToSet = this.typeSelect.findSelectedItem();
licenseToSet = licenseToSet ? licenseToSet.getData() : null;
// Why isn't this using mw.Api? Because I keep breaking abstractions (seriously, is there no way I could get an AJAX response from JQuery without it parsing and potentially throwing an error?)
var search = new URLSearchParams({
action: "parse",
page: pageTitle,
prop: automaticImageDescription ? "text|wikitext" : "text",
format: "json",
formatversion: 2,
});
var url = mw.config.get("wgScriptPath") + "/api.php?" + search.toString();
return new OO.ui.Process(fetch(url).then(function(resp) {
return resp.json();
}).then(function(data) {
if (data.error) {
return mw.notify(data.error.info, {type: "error"});
}
var template = document.createElement("template");
template.innerHTML = data.parse.text;
var a = template.content.querySelector("a:has(." + sourceClass + ")");
if (!a) {
return mw.notify(getMessage("cannot-find-link"), {type: "error"});
}
var sourceLink = a.href;
var date = template.content.querySelector(".pi-item[data-source=published] .pi-data-value");
date = date ? date.innerText.trim() : "";
var spacedTitle = data.parse.title.replace(":", ": ");
if (automaticImageDescription) {
var match = /^\s*==\s*Synopsis\s*==\s*\n([\s\S]+?)\s+\n\s*==/m.exec(data.parse.wikitext);
if (!match) {
return mw.notify(getMessage("cannot-find-synopsis"), {type: "error"});
}
imageDescription = match[1];
}
var newDescription = getDefaultDescription();
newDescription = newDescription.replace(/(\|\s*description\s*=\s*)(?=\n)/, function(match) {
return match + imageDescription;
});
newDescription = newDescription.replace(/(\|\s*source\s*=\s*)(?=\n)/, function(match) {
return match + "[[" + spacedTitle + "]] ([" + sourceLink + " link])";
});
newDescription = newDescription.replace(/(\|\s*date\s*=\s*)(?=\n)/, function(match) {
return match + date;
});
setCurrentDescription(newDescription);
if (licenseToSet) {
setLicense(licenseToSet);
}
dialog.close();
}).catch(function(error) {
console.log(error);
mw.notify(error.message, {type: "error", title: getMessage("unexpected-error")});
}));
}
return PrefillDialog.super.prototype.getActionProcess.call(this, action);
};
PrefillDialog.prototype.getBodyHeight = function() {
return this.content.$element.outerHeight(true);
};
/* INIT CODE */
function prefillButtonActivated(windowManager) {
var prefillDialog = new PrefillDialog({
size: "medium",
});
windowManager.addWindows([prefillDialog]);
windowManager.openWindow(prefillDialog);
}
function injectPrefillButton(windowManager) {
var textarea = document.querySelector("#wpUploadDescription");
var button = document.createElement("button");
button.type = "button"; // Explicitly set the button's type as a button, otherwise it will inherit its submit status from the form it's injected into
button.innerText = getMessage("prefill-description-from-comic-page-button");
button.addEventListener("click", function(event) {
event.preventDefault();
prefillButtonActivated(windowManager);
});
textarea.parentElement.append(button);
}
if (document.body.classList.contains("mw-special-Upload") && !document.querySelector("#wpForReUpload")) {
var windowManager = new OO.ui.WindowManager();
$(document.body).append(windowManager.$element);
injectPrefillButton(windowManager);
}