MediaWiki:Reports.js

/** * Flexible form script for VSTF Wiki reports * * @author Lil' Miss Rarity - original author * @author Joeytje50       - i18n fixes and dropdown * @author Jr Mime         - pop-up layout, variables * @author VegaDark        - vstf adaption * @author Cqm             - Major cleanup/rewrite * @author TK-999          - wds buttons * @author Noreplyz        - i18n fixes, template, design * * TODO check if this script is needed before loading i18n * @license: CC-BY-NC-SA */ require(['jquery', 'mw'], function ($, mw) {   var c = mw.config.get([ 'wgNamespaceNumber', 'wgPageName', 'wgServer', 'wgUserName', 'wgUserLanguage' ]),       options = {            profile: {},            vandalism: {},            spam: {},             phalanx: {},            wiki: {}        },        reportDropdown;    /**     * Set up options for use in forms, buttons     */    function setOptions {        if(typeof window.dev === 'undefined' || typeof window.dev.i18n === 'undefined') {            importScriptPage('MediaWiki:I18n-js/code.js', 'dev');        }        mw.hook('dev.i18n').add(function(i18no) { i18no.loadMessages('u:vstf:MediaWiki:Custom-Reports/i18n.json').done(function(i18n) {               options = {                    /*                     //BEGIN EXAMPLE                    example: {                        page: 'Page name the form is for',                        buttonText: 'Text for button to open form',                        form: 'HTML form for reporting users. Each input/textarea should have an id. any optional inputs should be marked with the `optional` class. If any attributes need URI encoding, the relevant inputs should have the `data-encode` attribute set to `true`.',                        // this is where the input ids in the form are matched to numbers                        // for use in the summary/submitted text                        formParams: {                            '$1': 'foo',                            '$2': 'bar'                        }, submitText: 'Text to submit to the page. Any form parameters can be inserted via the key names in `formParams`', summary: 'Text used for the edit summary. Any form parameters can be inserted via the key names in `formParams`', sectionTitle: 'Text used as the section title. Any form parameters can be inserted via the key names in `formParams`' },                   // END EXAMPLE */                   profile: { page: 'Report:User_profile_headers', buttonText: i18n.msg("buttonProfile").escape, form: '' + ' ' +                                   ' ' +                                        ' ' + i18n.msg("formSocial").escape + ' ' + ' ' + i18n.msg("formWikiName").escape + ' ' + '' + ' ' +                                        '  ' + i18n.msg("formWikiURL").escape + ' ' + '' + ' ' +                                       '  ' + i18n.msg("formUsername").escape + ' ' + i18n.msg("formOfBadUser").escape + ' (' + i18n.msg("formMultipleUsers").escape + ') ' + ' ' + ' ' +                                       '  ' + i18n.msg("formReason").escape + ' ' + ' ' + ' ' +                                       ' ' +                                            '  ' + i18n.msg("formSockpuppet").escape + ' ' + ' ' + i18n.msg("formUsername").escape + ' ' + i18n.msg("formOfSock").escape + ' ' + ' ' +                                           ' ' +                                        ' ' +                                     ' ' +                                ' ' +                            ' ',                        formParams: { '$1': 'wikiurl', '$2': 'wikiname', '$3': 'user', '$4': 'comment', '$5': 'user', // for different styling '$7': 'socks', '$8': 'sockusers' },                       submitText: '', summary: 'New profile report ($2, $5)', sectionTitle: '$2' },                   vandalism: { page: 'Report:Vandalism', buttonText: i18n.msg("buttonVandalism").escape, form: '' + ' ' +                                   ' ' +                                        '  ' + i18n.msg("formWikiName").escape + ' ' + '' + ' ' +                                        '  ' + i18n.msg("formWikiURL").escape + ' ' + '' + ' ' +                                       '  ' + i18n.msg("formUsername").escape + ' ' + i18n.msg("formOfBadUser").escape + ' (' + i18n.msg("formMultipleUsers").escape + ') ' + ' ' + ' ' +                                       '  ' + i18n.msg("formReason").escape + ' ' + ' ' + ' ' +                                       ' ' +                                            '  ' + i18n.msg("formCrossWiki").escape + ' ' + ' ' +                                        ' ' +                                            '  ' + i18n.msg("formSockpuppet").escape + ' ' + ' ' + i18n.msg("formUsername").escape + ' ' + i18n.msg("formOfSock").escape + ' ' + ' ' +                                           ' ' +                                        ' ' +                                     ' ' +                                ' ' +                            ' ',                        formParams: { '$1': 'wikiurl', '$2': 'wikiname', '$3': 'user', '$4': 'comment', '$5': 'user', // for different styling '$6': 'crosswiki', '$7': 'socks', '$8': 'sockusers' },                       submitText: '', summary: 'New vandalism report ($1, $5)', sectionTitle: '$5 at $2' },                   spam: { page: 'Report:Spam', buttonText: i18n.msg("buttonSpam").escape, form: '' + ' ' +                                   ' ' +                                        '  ' + i18n.msg("formWikiName").escape + ' ' + '<input id="wikiname" class="rf-wikiname optional" type="text" placeholder="' + i18n.msg("formphWikiName").escape + '"/>' + ' ' +                                        '  ' + i18n.msg("formWikiURL").escape + ' ' + '<input id="wikiurl" class="rf-wikiurl" type="text" placeholder="vstf.wikia.com"/>' + ' ' +                                       '  ' + i18n.msg("formUsername").escape + ' ' + i18n.msg("formOfBadUser").escape + ' (' + i18n.msg("formMultipleUsers").escape + ') ' + '<textarea name="" id="user" class="rf-wikiuser" type="text" placeholder="Rappy 4187\nDucksoup"> ' + ' ' +                                       '  ' + i18n.msg("formReason").escape + ' ' + '<textarea name="" id="comment" placeholder="' + i18n.msg("formphReason").escape + '" class="optional"> ' + ' ' +                                       ' ' +                                            ' <input type="checkbox" id="crosswiki" class="option-input optional"/> ' + i18n.msg("formCrossWiki").escape + ' ' + ' ' +                                    ' ' +                                ' ' +                            ' ',                        formParams: { '$1': 'wikiurl', '$2': 'wikiname', '$3': 'user', '$4': 'comment', '$5': 'user', // for different styling '$6': 'crosswiki', },                       submitText: '', summary: 'New spam report ($1, $5)', sectionTitle: '$5 at $2' },                   phalanx: { page: 'Report:Spam_filter_problems', buttonText: i18n.msg("buttonFalsePositive").escape, form: '<form class="WikiaForm ReportForm" method="" name="" id="phalanx">' + ' ' +                                   ' ' +                                        '  ' + i18n.msg("formWikiName").escape + ' ' + '<input id="wikiname" class="rf-wikiname optional" type="text" placeholder="' + i18n.msg("formphWikiName").escape + '"/>' + ' ' +                                        '  ' + i18n.msg("formWikiPage").escape + ' ' + '<input id="wikiurl" class="rf-wikiurl" type="text" placeholder="vstf.wikia.com"/>' + ' /wiki/ ' + '<input id="wikipage" class="rf-wikiurl" type="text" placeholder="Report:Spam_filter_problems"/>' + ' ' +                                       '  ' + i18n.msg("formBlockID").escape + ' ' + '<input id="blockid" class="rf-wikiurl" type="text" placeholder="12345" data-encode="true"/>' + ' ' +                                       '  ' + i18n.msg("formPhalanxReason").escape + ' ' + '<textarea name="" id="comment" placeholder="' + i18n.msg("formphReason").escape + '" class="optional"> ' + ' ' +                                   ' ' +                                ' ' +                            ' ',                        formParams: { '$1': 'wikiurl', '$2': 'wikiname', '$5': 'wikipage', '$3': 'blockid', '$4': 'comment' },                       submitText: '', summary: 'New filter report ($2, #$3)', sectionTitle: 'Block #$3 on $2' },                   wiki: { page: 'Report:Wiki', buttonText: i18n.msg("buttonWiki").escape, form: '<form class="WikiaForm ReportForm" method="" name="" id="wiki">' + ' ' +                                   ' ' +                                        '  ' + i18n.msg("formWikiName").escape + ' ' + '<input id="wikiname" class="rf-wikiname optional" type="text" placeholder="' + i18n.msg("formphWikiName").escape + '"/>' + ' ' +                                        '  ' + i18n.msg("formWikiURL").escape + ' ' + '<input id="wikiurl" class="rf-wikiurl" type="text" placeholder="vstf.wikia.com"/>' + ' ' +                                       '  ' + i18n.msg("formReason").escape + ' ' + '<input name="" id="comment" placeholder="' + i18n.msg("formphReason").escape + '" class="optional"> ' + ' ' +                                       '  N.B.; Guidelines: ' + 'Please add to this list if you believe a wiki violates Fandom\'s <a href="https://www.fandom.com/terms-of-use">Terms of Use</a>. ' +                                       '<ol><li>1. Do not use this page to report <a href="https://www.fandom.com/community-creation-policy">duplicate wikis</a>.</li>' + '<li>2. Do not add wikis just because you feel that they are "unproductive." This list is for <a href="https://www.fandom.com/terms-of-use">Terms of Use</a> violations only -- advertisement spam, harassment wikis, or obscene and illegal content.</li>' + '<li>3. Do not add wikis where you feel the administrators are being unfair. Please <a href="/Special:Contact/general">contact Staff</a> about bad admins.</li>' + '<li>4. New entries may be added to the <a href="#New reports (To be VSTF checked)">non-VSTF checked section</a> only. Check to ensure you are not duplicating an entry already there.</li></ol>' + ' ' +                                   ' ' +                                ' ' +                            ' ',                        formParams: { '$1': 'wikiname', '$2': 'wikiurl', '$3': 'comment' },                       submitText: '', summary: 'New bad wiki report ($1, comment: $3)', sectionTitle: '' },               };                reportDropdown = ' ' + '<div class="wds-dropdown__toggle wds-button">' + ' ' + i18n.msg("buttonReport").escape + ' ' + '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" class="wds-icon wds-icon-tiny wds-dropdown__toggle-chevron"><path d="M1 3h10L6 9z"> ' + ' ' +                '<div class="wds-dropdown__content">' + '<ul class="wds-list wds-is-linked" id="rf-dropdown-list">' + '</ul>' + ' ' +                ' '            }).done(init);        }); }   /**     * Report form submission handler *    * @param opts {object} */   function submitForm(opts) { var $form = $('#requestWindow form'), $inputs = $form.find('input, textarea'), $button = $('#submit'), params = {}, x,           y,            $input, text; if (($button).attr('disabled') === 'disabled') { return; }       $button.attr('disabled', true); var keyedValueCount = 0, sockCount = 0; for (x in opts.formParams) { if (opts.formParams.hasOwnProperty(x)) { $input = $inputs.filter('#' + opts.formParams[x]); if (!$input.length) { console.log('An error has been found in the form config. Please check the formParams and input ids'); $button.attr('disabled', false); return; }               text = $input.val; if ($input.is(':checkbox')) { text = $input.prop("checked"); }               if (!text && !$input.hasClass('optional')) { console.log($input); alert('One or more required fields are missing. Please check your submission and try again.'); $button.attr('disabled', false); return; }               /* Specific customisations for each form output */ if ($input.attr('data-encode') === 'true') { text = encodeURIComponent(text); }               // default wikiname if($input.attr('id') == "wikiurl") { re = /\/\/(.*)\.(wikia|fandom)\./; domain = re.exec(text); if(domain != null) { params[x] = domain[1]; continue; }               } else if($input.attr('id') === "wikiname") { if (!text) { text = $inputs.filter('#wikiurl').val; }                   re = /\/\/(.*)\.(wikia|fandom)\./; domain = re.exec(text); if(domain != null) { params[x] = domain[1].charAt(0).toUpperCase + domain[1].slice(1) + " Wiki"; continue; }               }                // handle multiple users if($input.attr('id') == "user" && text.indexOf('\n') !== -1) { if (x === '$5') { text = (text.match(/(?:\r\n|\r|\n)/g) || []).length + 1 + ' users'; } else { text = text.replace(/\n$/g, ''); // fix blank last user text = text.replace(/(?:\r\n|\r|\n)/g,'\n|'); }               }                // handle checkboxes if ($input.attr('id') == "crosswiki") { if (text) { text = "\\crosswiki=yes\n" keyedValueCount++; } else { text = "" }               }                if ($input.attr('id') == "socks") { if (text) { sockCount = 1; keyedValueCount++; }                   text = "" }               // handle socks if ($input.attr('id') == "sockusers") { if (text === "" && sockCount) { console.log($input); alert('One or more required fields are missing. Please check your submission and try again.'); $button.attr('disabled', false); return; } else if (sockCount) { text = "\\socks=" + text + '\n'; } else { text = ""; }               }                // patch | in reason if ($input.attr('id') == "comment") { text = text.replace(/\|/g, '\\\\'); }               params[x] = text; }       }        for (x in params) { if (params.hasOwnProperty(x)) { // convert to regex so the same parameter can be used multiple times in each string y = new RegExp(x.replace(/\$/, '\\$'), 'g'); opts.submitText = opts.submitText.replace(y, params[x]); opts.summary = opts.summary.replace(y, params[x]); opts.sectionTitle = opts.sectionTitle.replace(y, params[x]); }       }        // Fix when template thinks = is a key if (opts.submitText.match(/=/g) != null && opts.submitText.match(/=/g).length > keyedValueCount) { var templateParam = 0; opts.submitText = opts.submitText.replace(/\|/g, function (match, i, original) {               templateParam++;                return '|' + templateParam + '=';            }); }       if (keyedValueCount) { opts.submitText = opts.submitText.replace(/\\crosswiki/g, '|crosswiki'); opts.submitText = opts.submitText.replace(/\\socks/g, '|socks'); }       console.log(opts.submitText, opts.summary); if(opts.page === "Report:Wiki") { (new mw.Api) .post({                   action: 'edit',                    title: opts.page,                    appendtext: '\n' + opts.submitText,                    summary: opts.summary,                    token: mw.user.tokens.get('editToken')            }) .done(function (res) {               if (c.wgPageName == "VSTF_Wiki") {                    location.replace('https://vstf.wikia.com/wiki/' + opts.page + '?action=purge');                } else {                    location.reload(location + '?action=purge');                }            }); } else { (new mw.Api) .post({                   action: 'edit',                    title: opts.page,                    section: 'new',                    sectiontitle: opts.sectionTitle,                    text: opts.submitText,                    summary: opts.summary,                    token: mw.user.tokens.get('editToken')            }) .done(function (res) {               if (c.wgPageName == "VSTF_Wiki") {                    location.replace('https://vstf.wikia.com/wiki/' + opts.page + '?action=purge');                } else {                    location.reload(location + '?action=purge');                }            }); }   }    /**     * Loads the report form */   function loadForm { var $this = $(this), type = $this.attr('id').split('-')[2], opts = options[type]; $.showCustomModal(           opts.buttonText,            opts.form,            {                id: 'requestWindow',                width: 650,                buttons: [{                    id: 'cancel',                    message: 'Cancel',                    handler: function  {                        $('#requestWindow').closeModal;                    }                }, {                    id: 'submit',                    defaultButton: true,                    message: 'Save',                    handler: function  {                        submitForm(opts);                    }                }],                callback: function {                    // Fire hook for scripts that use the form                    mw.hook('vstf.reportsform').fire;                }            }        ); }   /**     * Loads the report form button *     * @param type {string} */   function loadButton(type) { var opts = options[type]; var $newButton = $(' ', {           'class': 'wds-button',            click: loadForm,            id: 'vstf-report-' + type,            text: opts.buttonText        }); $('.rb-' + type) .empty .append($newButton); // Fire hook for scripts that use the button mw.hook('vstf.reports').fire($newButton); }   /**     * loads dropdown of all report possibilities */   function loadDropdown { $('.rf-dropdown') .empty .append(reportDropdown); var x;       for (x in options) { var opts = options[x]; if (options.hasOwnProperty(x)) { $('#rf-dropdown-list').append(                   $('<li>')                        .attr('id', 'vstf-report-' + x)                        .attr('class', 'wds-global-navigation__dropdown-link')                        .on('click',loadForm)                        .text(opts.buttonText)                ); }       }    }    /**     * start up method */   function init { for (var x in options) { if ($('.rb-' + x).length > 0) { loadButton(x); }       }        if ($('.rf-dropdown').length > 0) { loadDropdown(x); }       importStylesheetURI('https://vstf.wikia.com/index.php?title=MediaWiki:Reports.css&action=raw&ctype=text/css'); }   $(setOptions); });