/*
This script make easy the review process on [[Commons:Quality_images_candidates]]
It prevent edit conflicts and you can vote with a simple click (selecting the vote type in the combobox below of each image)
Please, feel free of contact to me to improve this tool. Thanks
*/
mw.loader.using("mediawiki.api.edit").done(function() {
"use strict";
mw.util.addCSS(
" #voting_bar { " +
" position: fixed; " +
" bottom: 0; " +
" width: 100%; " +
" height: 40px; " +
" padding: 15px; " +
" border: 1px solid #a2a9b1; " +
" background-color: #E6E6FA; " +
" } "+
" #loading_ { " +
" display: inline-block !important; " +
" padding-left: 10px; " +
" color: green; " +
" font-weight: bold; " +
" } " +
" #confirm_ { " +
" display: inline-block !important; " +
" padding-left: 10px; " +
" color: red; " +
" } "
);
const CONFIRM_BAR = "<div id='voting_bar'><span id='confirm_review' style='margin:auto !important' class='submit ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary ui-button-large' role='button'><span class='ui-button-icon-primary ui-icon-green ui-icon ui-icon-check'> </span><span class='ui-button-text'>Confirm reviews</span></span><div id='loading_'></div><div id='confirm_'></div><p style='padding-left: 50px;padding-right:50px;float:right;'><input type='checkbox' id='hidereviews' value='first_checkbox'> <label for='hidereviews'> Hide reviewed nominations</label></p></div>";
const QIC_PAGE_DESTINY = "Commons:Quality_images_candidates/candidate_list";
const NOMINATION_CONTAINER = "div.qi-nomination";
const REVIEW_MESSAGE = "Dear wikiuser, please enter your review comment";
const USERNAME = mw.config.get("wgUserName");
let TITLE = mw.config.get("wgPageName");
if (TITLE == "Commons:Quality_images_candidates") TITLE = QIC_PAGE_DESTINY;
let api = new mw.Api();
let opt = {
"Nomination": {
color: "#0000FF",
message: ""
},
"Promotion": {
color: "lime",
message: "Good quality."
},
"Decline": {
color: "red",
message: "Insufficient quality."
},
"Comment": {
color: "#0000FF",
message: ""
},
"Discuss": {
color: "#EEEE00",
message: "I disagree."
}
};
const comboValues = {
"Promotion": "Promotion",
"Decline": "Decline",
"Nomination": "Comment",
"Discuss": "Discuss",
"": "..."
};
let votes = [];
let reviewCount = 0;
function _loading(show) {
if (show) {
$('#confirm_').text('');
$('#loading_').text('Sending reviews..');
}
else {
$('#loading_').text('');
}
}
function _confirmMessage () {
if (reviewCount > 0) {
$('#confirm_').text(reviewCount + ' pending review confirmations');
}
}
function getSection(section) {
_loading(true);
return api.get({
action: "query",
prop: "revisions",
rvprop: ["content", "timestamp"],
titles: [TITLE],
section: section, // Future support of section edition
formatversion: "2",
curtimestamp: true
})
.then(function(data) {
var page, revision;
page = data.query.pages[0];
revision = page.revisions[0];
return revision.content;
});
}
function editSection(section, content) {
$.ajax({
url: mw.util.wikiScript("api"),
data: {
format: "json",
action: "edit",
title: TITLE,
summary: "adding vote using [[User:The Photographer/QICvote.js]]",
text: content,
//section: section, // Future support of section edition
token: mw.user.tokens.get("editToken")
},
dataType: 'json',
type: 'POST',
success: function(data) {
if (data && data.edit && data.edit.result == "Success") {
_loading(false);
votes = [];
reviewCount = 0;
$('#confirm_').text('');
} else if (data && data.error) {
throw new Error('Error: API returned error code "' + data.error.code + '": ' + data.error.info);
} else {
throw new Error('Error: Unknown result from API.');
}
},
error: function(xhr) {
alert('Error: Request failed.');
}
});
}
function getSectionId(element) {
var url = $(element).parent().parent().parent().find("h2 span a").last().attr("href");
var results = new RegExp('[\?&]section=([^&#]*)').exec(url);
return results[1] || 0;
}
function createCombo() {
var $cmb = $("<select style='width:100%; margin:0px !important;' class='submit ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary ui-button-blue ui-button-large' />");
$.each(comboValues, function(key, value) {
$cmb
.append($("<option>", {
value: key
})
.text(value));
});
$cmb.val("");
return $cmb;
}
function _getImageName(aElement) {
let imageName = null;
const imageNode = $(aElement).parent().find("a.image").last().attr("href").split(":");
if (imageNode.length > 0) {
if (imageNode[1].indexOf(".") !== -1) {
imageName = imageNode[1];
}
}
return imageName;
}
function _remplaceLast(str, word, newWord) {
var n = str.lastIndexOf(word);
str = str.slice(0, n) + str.slice(n).replace(word, newWord);
return str;
}
function escapeRegExp(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
function _getSignature() {
return ' [[User:' + USERNAME + '|' + USERNAME + ']] ' + new Date().toUTCString();
}
function _addVote(content, image, type, comment) {
const reg = escapeRegExp(image) + "(.*)\\n";
let nomination = content.match(new RegExp(reg, "g"))[0];
let newNomination = nomination.replace(/\{\{\/(Nomination|Promotion|Decline|Discuss)\|/g, '{{/' + type + '|');
const eol = (newNomination.indexOf("|}}") !== -1) ? "<br />" : "|";
newNomination = _remplaceLast(newNomination, "}}", eol + comment + _getSignature() + "}}");
return content.replace(nomination, newNomination);
}
function scapeFilenames(filesname) {
function removeSpaces(match) {
return match.replace(/\ /g, '_');
}
return filesname.replace(/File:(.*?)\|\{\{+/g, removeSpaces);
}
function _addVotes() {
$.each(votes, function(section, votesSection) {
if ((typeof votesSection !== 'undefined') && (votesSection.length > 0)) {
getSection(section - 1).then(function(content) {
content = scapeFilenames(content);
$.each(votesSection, function(i, vote) {
content = _addVote(content, vote.image, vote.type, vote.comment);
});
editSection(section, content);
});
}
});
}
function _getNominationContainer(e) {
return $(e).parent().find(NOMINATION_CONTAINER);
}
function _nullVote(cmb) {
let nullVote = false;
if ($(cmb).val() === "") {
_getNominationContainer(cmb).find("ul li i").text("Review needed");
_getNominationContainer(cmb).css("border-color", "#0000FF");
$(cmb).val("");
nullVote = true;
}
return nullVote;
}
function _getSelection(cmb) {
return opt[$(cmb).val()];
}
function _removePreviusVote(cmb) {
_getNominationContainer(cmb).find("ul li > .coment").remove();
}
function _setBoderColorVote(cmb, colorBorder) {
_getNominationContainer(cmb).css("border-color", colorBorder);
}
function _setVoteTitle(cmb) {
_getNominationContainer(cmb).find("ul li i").append("b").text($(cmb).val());
}
function _getCommentElement(comment) {
return $('<div />', {
text: comment,
"class": "coment"
});
}
function _getSignatureElement() {
return $('<a />', {
href: String("/wiki/User:" + USERNAME),
text: USERNAME,
"class": "coment"
});
}
function _getDateElement() {
return $('<p />', {
"class": "coment",
text: String(new Date().toUTCString())
});
}
function _hideReviewds(e) {
$(".gallerybox").each(function() {
if($(this).find(NOMINATION_CONTAINER).find("ul").first().find("li").last().find("i").text() !== "Review needed" && $(e).is(':checked'))
{
$(this).hide();
}
else
{
$(this).show();
}
});
$( ".gallery.mw-gallery-traditional" ).each(function( index ) {
if($(this).children(':visible').length === 0) {
$(this).hide();
$(this).prev().hide();
} else {
$(this).show();
$(this).prev().show();
}
});
}
function _onChangeVote(cmb, section) {
if (_nullVote(cmb)) return;
let selection;
let imageName;
let comment = "";
selection = _getSelection(cmb);
_setVoteTitle(cmb);
_setBoderColorVote(cmb, selection.color);
_removePreviusVote(cmb);
comment = prompt(REVIEW_MESSAGE, selection.message);
let $comment = _getCommentElement(comment);
let $signature = _getSignatureElement();
let $date = _getDateElement();
$(cmb).parent().find(NOMINATION_CONTAINER).
find("ul li").last().append($comment).
append($signature).
append($date);
imageName = _getImageName(cmb);
if (typeof votes[section] === "undefined") {
votes[section] = [];
}
votes[section].push({
image: decodeURIComponent(imageName),
comment: comment,
type: $(cmb).val()
});
reviewCount++;
}
if (TITLE == QIC_PAGE_DESTINY) {
let section;
let $cmb;
$("body").append(CONFIRM_BAR);
$('#confirm_review').on('click', function() {
_addVotes();
});
$(".gallerybox").each(function() {
$cmb = createCombo();
$(this).append($cmb);
section = getSectionId(this);
$cmb.on("change", function() {
_onChangeVote(this, section);
_confirmMessage ();
});
});
$( "#hidereviews" ).change(function() {
_hideReviewds(this);
});
}
});