User:Enterprisey/falsePositiveHelper.js

Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
//<nowiki>
( function ( $, mw ) {
    mw.loader.load( "mediawiki.ui.input", "text/css" );
    mw.loader.load( "mediawiki.api" );
    var ADVERTISEMENT = " ([[User:Samtar/falsePositiveHelper|falsePositiveHelper]])";

    if ( mw.config.get( 'wgPageName' ) === "Wikipedia:Edit_filter/False_positives" ) {
        $( `<style>
        .orcp-rating {
            box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
            padding: 5px;
            padding-left: 19px;
            display: inline-block;
        }

        .orcp-rating input {
            padding: 4px 4px 4px 8px;
            height: 35px;
        }

        .orcp-rating input.invalid {
        	box-shadow: 0px 0px 0px 2px #D11D13 inset;
        	border-color: #D11D13;
        }

        .orcp-rating th {
            text-align: left;
        }
        </style>` ).appendTo( "head" );
        $( "h2:not(:contains('Instructions')) .mw-editsection" ).each( function ( index, element ) {
            var username = $( this ).parent().text().replace( /\[[\s\S]+\]/, "" );
            // We shouldn't be able to respond using this script twice
            var testLink = function ( link ) { return link.href.indexOf( mw.config.get( "wgUserName" ) ) >= 0; };
            var linksInComments = $( this ).parent().nextUntil( "h2" ).filter( "ul" ).children().children( "a" ).toArray();
            if( linksInComments.some( testLink ) ) return;
            $( this ).children( ".mw-editsection-bracket" ).last()
                .before( " | " )
                .before( makeActionLink( username ) );
        } );
    }

    function specificElementId ( username ) {
        var prefix = "orcp-" + username.replace( /[^a-z0-9]/g, "_" ) + "-";
        return {
            "rating": prefix + "rating-field",
            "comment": prefix + "comment-field",
            "button": prefix + "rate-button",
            "placeholder": prefix + "placeholder",
            "cancel": prefix + "cancel-button"
        };
    }

    function specificElement ( username ) {
        var ids = specificElementId( username );

        // Object "mapping" taken from http://stackoverflow.com/a/14810722
        return Object.keys( ids ).reduce( function ( previous, current ) {
            previous[ current ] = $( "#" + ids[ current ] );
            return previous;
        }, {} );
    }

    function makeActionLink ( username ) {
        return $( "<a>" ).css( "cursor", "pointer" ).text( "respond" ).attr( "href", "#" ).click( function ( e ) {
            buildPanel( $( this ), username );
            $( this ).replaceWith( "<span id='" + specificElementId( username ).placeholder + "'>respond</a>" );
            return false;
        } );
    }

    /*
     * target is the "add request" link that was clicked to trigger this.
     */
    function buildPanel ( target, username ) {
        var ids = specificElementId( username ),
            createSeparator = function () { return $( "<span class='separator'>|</span>" ); };
        target.parent().parent().after( `
        <div class="orcp-rating">
          <table>
            <tr>
              <th><label for="${ ids.rating }">Response</label></th>
              <th><label for="${ ids.comment }">Comment</label></th>
              <th>&nbsp;</th>
            </tr>
            <tr>
              <td>
              	 <select id="${ ids.rating }" class="mw-ui-input mw-ui-input-inline">
              	 	<option value="{{EF false positive}}">False positive</option>
			<option value="{{EF not false positive}}">Not false positive</option>
		</select>
              </td>
              <td>
                <input type="text" id="${ ids.comment }" class="mw-ui-input mw-ui-input-inline" />
              </td>
              <td>
                <button id="${ ids.button }" class="mw-ui-button mw-ui-constructive">Respond</button>
                <button id="${ ids.cancel }" class="mw-ui-button mw-ui-destructive mw-ui-quiet">Cancel</button>
              </td>
            </tr>
          </table>
        </div>`);
        specificElement( username ).button.click( function () { saveRating( username, $( this ).parent() ); } );
        specificElement( username ).cancel.click( function () {

            // This statement walks back up the DOM to the .orcp-rating div
            $( this ).parent().parent().parent().parent().parent().remove();
            specificElement( username ).placeholder.replaceWith( makeActionLink( username ) );
        } );
    }

    // The argument "that" represents the entire panel div
    function saveRating ( username, that ) {
    	
        $( specificElement( username ).button ).prop( "disabled", true );
        $( specificElement( username ).rating ).prop( "disabled", true );
        $( specificElement( username ).comment ).prop( "disabled", true );
        var statusElement = $( "<span style='margin-left:10px' class='status'>Saving response...</span>" ).appendTo( that ),
            setStatus = function ( status, callback ) { statusElement.fadeOut( function () { statusElement.html( status ).fadeIn( callback ); } ) };
        setStatus( "Getting wikitext..." );
        var wikitext;
        $.getJSON(
            mw.util.wikiScript('api'),
            {
                format: 'json',
                action: 'query',
                prop: 'revisions',
                rvprop: 'content',
                rvlimit: 1,
                titles: "Wikipedia:Edit filter/False positives/Reports"
            }
        ).done( function ( data ) {
            try {
                var pageId = Object.keys(data.query.pages)[0];
                wikitext = data.query.pages[pageId].revisions[0]['*'];
                setStatus( "Got this page's wikitext, processing..." );

                // Get the last line of the report
                var headerMatch = ( new RegExp( "(==\\s*" + username + "\\s*==)" ) ).exec( wikitext );
                var sectionTextPlus = wikitext.slice( headerMatch.index + headerMatch[1].length );
                var sectionText = sectionTextPlus.substring( 0, sectionTextPlus.indexOf( "==" ) ).trim();

                // Make the new wikitext
                var rating = specificElement( username ).rating.val();
                var newLine = ":" + rating + " " + specificElement( username ).comment.val() + " ~~~~";
                var newWikitext = wikitext.replace( sectionText, sectionText + "\n" + newLine );

                setStatus( "Wikitext processed. Saving..." );
                ( new mw.Api() ).postWithEditToken( {
                    action: "edit",
                    title: "Wikipedia:Edit filter/False positives/Reports",
                    summary: rating + " " + ADVERTISEMENT,
                    text: newWikitext
                } ).done ( function ( data ) {
                    if ( data && data.edit && data.edit.result && data.edit.result == 'Success' ) {
                        setStatus( "Rating saved! (<a href='javascript:void(0)' class='reload'>Reload</a>)" );
                        $( ":animated" ).promise().done( function() {
                            that.children( "span.status" ).children( "a" ).click( function () { document.location.reload( true ); } );
                        } );
                        specificElement( username ).cancel.text( "Done" );
                    } else {
                        setStatus( "While saving, the edit query returned an error. =(" );
                    }
                } ).fail ( function() {
                    setStatus( "While saving, the AJAX request failed." );
                } );
            } catch ( e ) {
                setStatus( "While getting the wikitext, there was an error." );
                console.log( "Content request error: " + e.message );
                console.log( "Content request response: " + JSON.stringify( data ) );
            }
        } ).fail( function () {
            setStatus( "While getting the wikitext, there was an AJAX error." );
        } );
    }
}( jQuery, mediaWiki ) );
//</nowiki>