User:Ahecht/Scripts/draft-sorter.js
Appearance
< User:Ahecht | Scripts
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
![]() | This user script seems to have a documentation page at User:Ahecht/Scripts/draft-sorter. |
//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(/media/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>