//jshint maxerr:256
//Based on [[User:Enterprisey/draft-sorter.js]] <nowiki>
( function ( $, mw ) { mw.loader.using( ["mediawiki.api", "jquery.chosen", "oojs-ui-core"], function () {
mw.loader.load( "mediawiki.ui.input", "text/css" );
if ( mw.config.get( "wgNamespaceNumber" ) !== 118 ) {
if ( mw.util.getParamValue('draftsorttrigger') ) {
// "Next draft" was clicked, but we ended up on a non-draft page
nextDraft();
return;
} else {
return;
}
}
var portletLink = mw.util.addPortletLink("p-cactions", "#", "Sort draft (sandbox)", "pt-draftsort", "Manage WikiProject tags");
$( portletLink ).click( function ( e ) {
e.preventDefault();
// If it's already there, don't duplicate
if ( $( "#draft-sorter-wrapper" ).length ) { return; }
// Define the form
var form = $( "<div>" )
.attr( "id", "draft-sorter-wrapper" )
.css( { "background-image": "url(https://upload.wikimedia.org/wikipedia/commons/e/e2/OOjs_UI_icon_tag-ltr-progressive.svg)",
"background-repeat": "no-repeat",
"background-position-y": "center",
"background-size": "50px",
"min-height": "50px",
"margin": "1em auto",
"border": "thin solid #BBB",
"padding": "0.5em 50px",
"display": "inline-block",
"border-radius": "0.25em"
} ).append( $( "<span>" )
.text( "Loading form..." )
.css( "color", "gray" )
);
// Add the form to the page
form.insertAfter( "#jump-to-nav" );
var select = $( "<select>" )
.attr( "id", "draft-sorter-form" )
.attr( "multiple", "multiple" );
var submitButton = new OO.ui.ButtonWidget ()
.setLabel( "Submit" )
.setFlags( [ 'primary', 'progressive' ] )
.on("click", function ( e ) { submit(); } );
var nextButton = new OO.ui.ButtonWidget ()
.setIcon( "next" )
.setLabel( "Skip" )
.on("click", function ( e ) { nextDraft(); } );
// Determine what templates are already on the talk page
var api = new mw.Api();
var existingProjects = [];
var wikiprojects = {};
api.get( {
action: "query",
titles: "Draft talk:" + mw.config.get( "wgTitle" ),
generator: "templates",
redirects: "1",
gtllimit: "max",
} ).done (function (data) {
if (data && data.query && data.query.pages) {
$.each(data.query.pages, function (i) {
var item = data.query.pages[i].title.match(/^Template:(WikiProject\s[^\/]*)$/i);
if (item && item[1] && item[1] != "WikiProject banner shell") {
existingProjects.push(item[1]);
}
} );
}
console.log( "Project templates found on talk page: ");
console.log( existingProjects );
getTemplates();
} ).fail (function() {
console.log("Retrieving project templates from talk page failed.");
getTemplates();
});
predicts = [];
function nextDraft() {
// Special:RandomInCategory isn't random, so this function is a
// better substitute.
draftList = [];
console.log ("Fetching drafts from API");
if (nextButton) {
nextButton.setLabel( "Loading..." ).setDisabled( true );
}
getDrafts();
function getDrafts(cont) { // Recursively call API
var api = new mw.Api();
var query = {
action: "query",
list: "categorymembers",
cmtitle: "Category:Pending_AfC_submissions",
cmprop: "title",
cmnamespace: "118",
cmtype: "page",
cmlimit: "max"
};
if (cont) {
query = Object.assign(query, cont);
}
api.get( query )
.done (function (data) {
if (data && data.query && data.query.categorymembers) { //API query returned pages
data.query.categorymembers.forEach(function(item) {
draftList.push( item.title );
} );
}
if (data && data.continue) { //More results are available
getDrafts(data.continue);
} else { // Redirect to random page
console.log("Done fetching drafts!");
window.___location.href = mw.config.get( "wgServer" )
+ "/wiki/"
+ draftList[Math.random() * draftList.length | 0]
+ "?draftsorttrigger=y";
}
} ).fail (function(error) { // Use Special:RandomInCategory
console.log("Error getting list of drafts: " + error);
window.___location.href = mw.config.get( "wgServer" )
+ "/wiki/Special:RandomInCategory/Pending_AfC_submissions?draftsorttrigger=y";
} );
return;
}
}
function showPredicts() {
$( "#draft-sorter-status" ).append( "<li>Suggested categories from <a href=\"https://www.mediawiki.org/wiki/ORES#Curation_support\">ORES</a>:<ul id=\"draft-sorter-suggest\"></ul></li>" );
predicts.forEach( function(item) {
var addLink = $( "<a>" )
.text("add")
.click( function() {
$( select ).val(
$( select ).val().concat( [ "WikiProject " + item ] )
).trigger("chosen:updated");
} );
var singularItem = item.replace(/s$/, '');
if( !existingProjects.includes( "WikiProject " + item )
&& wikiprojects[item]
) { //Prediction matches a WikiProject and doesn't already exist
$( "#draft-sorter-suggest" ).append( $( "<li>" )
.append( item + " (" )
.append( addLink )
.append( ")" )
);
} else if( singularItem != item
&& !existingProjects.includes( "WikiProject " + singularItem )
&& wikiprojects[singularItem]
) { //Singular form of prediction matches a WikiProject and doesn't exist
addLink.click( function() {
$( select ).val(
$( select ).val().concat( [ "WikiProject " + singularItem ] )
).trigger("chosen:updated");
} );
$( "#draft-sorter-suggest" ).append( $( "<li>" )
.append( singularItem + " (" )
.append( addLink )
.append( ")" )
);
} else { //Prediction doesn't match a WikiProject or already exists
$( "#draft-sorter-suggest" ).append(
$( "<li>" ).append( item )
);
}
} );
return;
}
function getPredicts() {
var dbName = mw.config.get( "wgDBname" );
var revID = mw.config.get( "wgCurRevisionId" );
$.getJSON( "//ores.wikimedia.org/v3/scores/" + dbName + "/" + revID + "/drafttopic" )
.done( function ( data ) {
if(data && data[dbName] && data[dbName].scores &&
data[dbName].scores[revID] &&
data[dbName].scores[revID].drafttopic &&
data[dbName].scores[revID].drafttopic.score &&
data[dbName].scores[revID].drafttopic.score.prediction) {
var prediction = data[dbName].scores[revID].drafttopic.score.prediction;
console.log("Got ORES response! Raw predictions:");
console.log(prediction);
prediction.forEach( function (item) {
var last = item.split(".")[item.split(".").length-1];
var penultimate = item.split(".")[item.split(".").length-2];
if ( last.substr(-1) == "*" ) {
// Filter out redundant starred predictions
if (prediction.find(element => (
element.split(".")[element.split(".").length-1] != last &&
element.split(".")[element.split(".").length-2] == penultimate
) ) ) {
console.log("Prediction \"" + last + "\" excluded.");
last = null;
} else {
last = penultimate;
}
}
if ( wikiprojects[last] ) {
// WikiProject found, no need to try splitting
predicts.push(last);
} else if ( last ) {
// Can't find wikiProject, try splitting
var splitLast = last.split(/( & | and )/);
for (i=0;i<=splitLast.length;i+=2) {
splitLast[i] = splitLast[i].charAt(0).toUpperCase()
+ splitLast[i].slice(1);
predicts.push( splitLast[i] );
}
}
} );
console.log("Filtered predictions:");
console.log(predicts);
showPredicts();
} else {
console.log("Error finding predictions in ORES response:");
console.log(data);
}
} ).fail( function ( error ) {
console.log("Error retrieving ORES data: " + error);
} );
return;
}
function getTemplates(cont) { // Recursively call API
var api = new mw.Api();
var query = {
action: "query",
generator: "search",
gsrsearch: "hastemplate:\"Template:WPBannerMeta\" prefix:\"Template:WikiProject_\"",
gsrnamespace: "10",
gsrlimit: "max"
};
if (cont) {
query = Object.assign(query, cont);
}
api.get( query )
.done (function (data) {
if (data && data.query && data.query.pages) { //API query returned pages
Object.entries(data.query.pages).forEach(function(item) {
var title = item[1].title.match(/^Template:WikiProject\s(.*)$/);
if (title && title[1] && title[1] !== "") { //Valid page name format
if (title[1].indexOf("/") == -1) { //No subpages
wikiprojects[title[1]] = item[1].title.replace("Template:", "");
}
} else {
console.log("No valid title found in the following item:");
console.log(item);
}
} );
}
if (data && data.continue) { //More results are available
getTemplates(data.continue);
} else {
console.log("Done fetching templates!");
constructForm();
}
} ).fail (function(error) {
console.log("Error getting list of templates: " + error);
constructForm();
} );
return;
}
// Construct the form
function constructForm() {
mw.loader.load( "oojs-ui.styles.icons-movement");
console.log( "WikiProjects: ");
console.log( wikiprojects );
console.log( "Arguments: ");
console.log( arguments );
Object.keys(wikiprojects).sort().forEach( function(name) {
select.append( $( "<option>" )
.attr( "value", wikiprojects[name] )
.text( name ) );
} );
form.hide();
form.empty();
form.append( $( "<span>" )
.text( "Tag WikiProjects: " )
.css( {
"font-size": "115%",
"font-weight": "bold"
} )
);
form.append( select );
form.append( "  " );
form.append( submitButton.$element );
form.append( new OO.ui.ButtonWidget ()
.setLabel( "Cancel" )
.setFlags( ["destructive"] )
.on("click", function( e ) {
$( "#draft-sorter-wrapper" ).remove();
} ).$element
);
form.append( nextButton.$element );
form.append ( $( "<ul>" )
.attr( "id", "draft-sorter-status" )
);
form.show();
$( select )
.val( existingProjects )
.chosen( {"placeholder_text_multiple": "Select some WikiProjects"} )
.on("change", function(evt, params) { //Make existing projects undeletable
$( "#draft-sorter-status" ).empty();
if ( predicts.length > 0 ) { showPredicts(); }
if ( params.deselected && existingProjects.includes(params.deselected) ) {
$( select ).val( $( select ).val().concat([params.deselected]) ).trigger("chosen:updated");
$( "#draft-sorter-status" ).prepend( $( "<li>" )
.text( "Draft Sorter cannot remove existing WikiProjects." )
.addClass( "error" )
);
}
} );
// Add completed form to the page
$( '#draft-sorter-wrapper' ).replaceWith(form);
getPredicts();
return;
}
// The submission function
function submit() {
submitButton.setLabel( "Submitting..." ).setDisabled( true );
var newTags = [];
$( "#draft-sorter-form" ).val().forEach( function (element) {
if ( !existingProjects.includes(element) ) {
newTags.push(element);
}
} );
console.log( newTags.length + " new tag(s): " + newTags );
var statusList = $( "#draft-sorter-status" )
.html( "<li>Saving " + newTags.length + " new tags.</li>" );
var showStatus = function ( status ) {
return $( "<li>" )
.text( status )
.appendTo( statusList );
};
var newText = "";
newTags.forEach( function ( element ) {
newText += "{{" + element + "|importance=|class=draft}}\n";
} );
function editTalk(text, prefix) {
var params = {
action: "edit",
title: "Draft talk:" + mw.config.get( "wgTitle" ),
summary: "Tagging drafts ([[User:Ahecht/Scripts/draft-sorter.js|draft-sorter.js]])",
};
params[prefix + "text"] = text;
api.postWithEditToken( params ).done( function ( data ) {
if ( data && data.edit && data.edit.result && data.edit.result === "Success" ) {
showStatus( "Edit saved successfully! (" )
.append( $( "<a>" )
.text( "reload" )
.attr( "href", "#" )
.click( function () { document.___location.reload( true ); } ) )
.append( ")" );
submitButton.setLabel( "Submitted" );
nextButton.setLabel( "Next draft" ).setFlags( [ 'progressive' ] );
} else {
showStatus( "Couldn't save due to error: " + JSON.stringify( data ) );
}
} ).fail( function ( error ) {
showStatus( "Couldn't save due to error: " + JSON.stringify( error ) );
} );
return;
}
api.get( {
action: "query",
titles: "Draft talk:" + mw.config.get( 'wgTitle' ),
prop: "templates",
tltemplates: "Template:WikiProject_banner_shell"
} ).done (function (data) {
var bannerShellUsed = Object.entries(data.query.pages)[0][1].templates;
if(typeof(bannerShellUsed) == "object" && bannerShellUsed.length > 0) {
api.get( {
action: "parse",
page: "Draft talk:" + mw.config.get( 'wgTitle' ),
prop: "wikitext",
section: "0"
} ).done (function (data) {
var talkText = data.parse.wikitext["*"];
if (typeof(talkText) == "string") {
var pattern = /(\{\{\s*(?:Wiki[ _]?Project[ _]?banners?[ _]?shell(?:\/redirect)?|(?:(?:WP)?[ _]?Banner|(?:Wiki)?Project|Scope)[ _]?shell|Multiple[ _]wikiprojects|WikiProject[ _]?Banners?|WPBS?)\s*\|\s*)/im;
if (talkText.search(pattern) >= 0) {
newText = talkText.replace( pattern, ("$1" + newText) );
editTalk(newText,"");
} else {
console.log("Banner shell on talk page, but not found in wikitext: " + talkText);
editTalk(newText,"prepend");
}
} else {
console.log("typeof(talkText) = " + typeof(talkText));
editTalk(newText,"prepend");
}
} ).fail (function (error) {
console.log( "Couldn't retrieve talk page text due to error: " + JSON.stringify( error ) );
editTalk(newText,"prepend");
} );
} else if(newTags.length > 2) {
console.log("typeof(bannerShellUsed) = " + typeof(bannerShellUsed) );
newText = "{{WikiProject banner shell|\n" + newText + "}}";
editTalk(newText,"prepend");
} else {
console.log("typeof(bannerShellUsed) = " + typeof(bannerShellUsed) + "; newTags.length = " + newTags.length);
editTalk(newText,"prepend");
}
} ).fail( function ( error ) {
console.log( "Couldn't retrieve templates on talk page due to error: " + JSON.stringify( error ) );
editTalk(newText,"prepend");
} );
return;
}
} );
if (mw.util.getParamValue('draftsorttrigger')) {
$( portletLink ).trigger("click");
}
} ) }( jQuery, mediaWiki ) );
//</nowiki>