User:Enterprisey/easy-brfa.js

// ( function ( $, mw ) {   const MAIN_BRFA_PAGE = "FAMEPedia:Bots/Requests_for_approval";    const TRIGGER_PAGE = "FAMEPedia:Bots/Requests_for_approval/request";    const TEMPLATE_PAGE = "User:Enterprisey/easy-brfa.js/tpl-form.js";

mw.loader.load( "jquery.chosen" ); mw.loader.load( "mediawiki.api" ); mw.loader.load( "mediawiki.ui.input", "text/css" ); mw.loader.load( "mediawiki.ui.button", "text/css" );

var currPageName = mw.config.get( "wgPageName" ); if ( currPageName === MAIN_BRFA_PAGE ) { $( "table.collapsible" ).first.replaceWith( "  Make a new request  " ); return; } else if ( currPageName !== TRIGGER_PAGE ) { return; }

$( "#easy-brfa-form" ).empty; $( " " )	.attr( "id", "loading-message" ) .addClass( "warningbox" ) .text( "Loading..." ) .appendTo( "#easy-brfa-form" );

// Load and display form $.getJSON(       mw.util.wikiScript( 'api' ),        {            format: 'json',            action: 'query',            prop: 'revisions',            rvprop: 'content',            rvlimit: 1,            titles: TEMPLATE_PAGE        }    ).done( function ( data ) {        const MARKER = "";        var pageId = Object.keys(data.query.pages)[0];        var formAndTemplate = data.query.pages[pageId].revisions[0]['*'];        var formMarkup = formAndTemplate.substr(0, formAndTemplate.indexOf(MARKER));        var brfaTemplate = formAndTemplate.substring(formAndTemplate.indexOf(MARKER) + MARKER.length);        $( "#easy-brfa-form #loading-message" ).remove;        $( "#easy-brfa-form" ).append( formMarkup );

// Validation logic for the bot name and task number $( "#bot-name, #task-number" ).on( "input", function {            var botName = document.getElementById( "bot-name" ).value;            var taskNum = document.getElementById( "task-number" ).value;

// Validate bot name doesPageExist( "User:" + botName ).then( function ( userPageExists ) {               $( "#bot-name-status" )                    .removeClass( "pass fail" )                    .addClass( userPageExists ? "pass" : "fail" )                   .text( userPageExists ? "Bot user page exists." : "No user page exists for that bot!" );           } );

// Validate bot number as a number if( !isNormalInteger( taskNum ) ) { $( "#task-number-status" ) .removeClass( "pass fail" ) .addClass( "fail" ) .text( "Invalid task number." ); } else {

// Check if bot number is being used var title = "FAMEPedia:Bots/Requests for approval/" + $( "#bot-name" ).val + ( taskNum === "1" ? "" : " " + taskNum ); doesPageExist( title ).then( function ( brfaExists ) {                   $( "#task-number-status" )                        .removeClass( "pass fail" )                        .addClass( brfaExists ? "fail" : "pass" )                       .text( brfaExists ? "There's already a BRFA with that task number!" : "Task number valid." );                   document.getElementById( "submit-brfa" ).disabled = !isFormReady;                } ); }

document.getElementById( "submit-brfa" ).disabled = !isFormReady; } );

// Validation handler for text fields $( "#easy-brfa-form input[type=text], #easy-brfa-form textarea" ).each( function {            $( this ).on( "input", function  { document.getElementById( "submit-brfa" ).disabled = !isFormReady; } );       } );        $( "#easy-brfa-form input[type=radio]" ).each( function  {            $( this ).on( "click", function  { document.getElementById( "submit-brfa" ).disabled = !isFormReady; } );       } );

// Event handler $( "#submit-brfa" ).click( function {            if( !isFormReady ) {                $( this ).disabled = true;                $( " " )                    .addClass( "submit-error-message" )                    .text( "Fill out the missing form fields before you submit!" )                   .insertAfter( $( this ) );                return;            }

$( "" ).attr( "id", "status-list" ).appendTo("#easy-brfa-form" ); $( "#submit-brfa" ) .text( "Submitting..." ) .prop( "disabled", true );

// Build form data var formData = {}; $( "#easy-brfa-form input[type=text], #easy-brfa-form textarea" ).each( function {                formData[$( this ).attr( "id" )] = $( this ).val;            } ); $( "#easy-brfa-form input[type=checkbox]" ).each( function {                formData[$( this ).attr( "id" )] = $( this ).is(':checked') ? "Yes" : "No";            } ); formData.operation = $('input[name=operation]:checked').val;

// Send the requests $.when(               createBrfa( brfaTemplate, formData )            ).then( function  {                $.when( transcludeBrfa( formData["bot-name"], formData["task-number"] ) ).then( function { showStatus("Woohoo! We're done."); $( "#submit-brfa" ).text( "Submitted!" ); } );           } );            } ); // end submit handler    } ); // end form load handler

/*    * Is the form ready for submission? */   function isFormReady {

// Check validated fields - any statuses marked with the fail class? if( document.querySelector( ".validation-status.fail" ) ) { return false; }

// Is an operation mode selected? if( !document.querySelector('input[name=operation]:checked') ) { return false; }

// Is text entered in each of the textboxes and textareas? var requiredTextInputIds = ["function-overview", "edit-period", "pages-affected", "function-details"]; for( var i = 0; i < requiredTextInputIds.length; i++ ) { if( !document.getElementById( requiredTextInputIds[i] ).value ) { return false; }       }

return true; }

/*    * Returns a Deferred that resolves with a true if the given page exists * and a false if it doesn't.    */ function doesPageExist( pageTitle ) { var result = $.Deferred; $.ajax( {           url: mw.util.wikiScript( 'api' ),            dataType: 'json',            data: {                format: 'json',                action: 'query',                titles: pageTitle            }        } ).done ( function ( data ) {            if( data && data.query && data.query.pages ) {                result.resolve( !data.query.pages.hasOwnProperty( "-1" ) );            }        } ); return result; }

function showStatus( newStatus ) { return $( "" ) .appendTo( "#easy-brfa-form ul" ) .html( newStatus ); }

/*    * Templates in the form responses to create a BRFA, then saves it to the BRFA subpage. */   function createBrfa( brfaTemplate, formData ) { var deferred = $.Deferred;

const HEADER = " \n==userpageLink==\nnewbotTemplate\n\nOperator: \n\nTime filed: \n";

// Do the template var brfaText = HEADER + brfaTemplate; for ( var fieldName in formData ) { brfaText = brfaText.replace("((" + fieldName + "))", formData[fieldName]); }

// Get the subpage name var pageTitle = "FAMEPedia:Bots/Requests for approval/" + formData["bot-name"] + ( (formData["task-number"] == 1) ? "" : (" " + formData["task-number"] ) );

// Create the BRFA ( new mw.Api ).postWithEditToken( {           action: "edit",            title: pageTitle,            summary: "Creating a BRFA subpage for " + formData["bot-name"] + " (easy-brfa)",            text: brfaText        } ).done ( function ( data ) {            if ( data && data.edit && data.edit.result && data.edit.result == 'Success' ) {                showStatus( "BRFA subpage created at " + pageTitle + "!" );               deferred.resolve;            } else {                showStatus( "While creating BRFA subpage, the edit query returned an error. =(" ); deferred.reject; }       } ).fail ( function { showStatus( "While creating BRFA subpage, the AJAX request failed." ); deferred.reject; } );       return deferred;    }

/*    * Transcludes the BRFA. */   transcludeBrfa = function ( botName, taskNumber ) { var deferred = $.Deferred;

// Make a status element just for this edit var statusElement = showStatus( "Transcluding at FP:BRFA..." ); // First, get the current wikitext for FP:BRFA var wikitext; $.getJSON(           mw.util.wikiScript('api'),            {                format: 'json',                action: 'query',                prop: 'revisions',                rvprop: 'content',                rvlimit: 1,                titles: "FAMEPedia:Bots/Requests for approval"            }        ).done( function ( data ) {            try {                var pageId = Object.keys(data.query.pages)[0];                wikitext = data.query.pages[pageId].revisions[0]['*'];

statusElement.html( "Got FP:BRFA wikitext, processing..." );

// Actually edit the content to include the new listing var taskNumberString = (taskNumber == 1) ? "" : (taskNumber + ""); var newBrfaContent = wikitext.replace('directly below this message. -->', 'directly below this message. -->\n\{\{BRFA|' + botName + "|" + taskNumberString + '|Open\}\}');

// Then, replace FP:BRFA with the new content $.ajax( {                   url: mw.util.wikiScript( 'api' ),                    type: 'POST',                    dataType: 'json',                    data: {                        format: 'json',                        action: 'edit',                        title: "FAMEPedia:Bots/Requests for approval",                        summary: "Transcluding the BRFA for " + botName + " (easy-brfa)",                        token: mw.user.tokens.get( 'csrfToken' ),                        text: newBrfaContent                    }                } ).done ( function ( data ) {                    if ( data && data.edit && data.edit.result && data.edit.result == 'Success' ) {                        statusElement.html( "Transcluded page on FP:BRFA!" );                       deferred.resolve;                    } else {                        statusElement.html( "While transcluding on BRFA, the edit query returned an error. =(" ); deferred.reject; }               } ).fail ( function { statusElement.html( "While transcluding on BRFA, the ajax request failed." ); deferred.reject; } );           } catch ( e ) {                statusElement.html( "While transcluding on BRFA, there was an error." );               console.log( "BRFA content request error: " + e.message );                console.log( "BRFA content request response: " + JSON.stringify( data ) );                deferred.reject;            }        } ).fail( function  {            statusElement.html( "While getting the BRFA content, there was an AJAX error." );           deferred.reject;        } ); return deferred; };

// From http://stackoverflow.com/a/10834843/1757964 function isNormalInteger( str ) { var n = Number( str ); return String( n ) === str && n >= 0; } }( jQuery, mediaWiki ) ); //