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.
// Script to respond to edit filter false positive reports
// Based on [[User:DannyS712/EFFPRH/sandbox.js]]
// <nowiki>
$(() => {
    const EFFPRH = {
        config: {
            debug: false
        },
        responseOptions: [
            { data: 'none', label: 'None' },
            { data: 'nofilterstriggered', label: 'No filters triggered' },
            { data: 'done', label: 'Done (no change to filter)' },
            { data: 'defm', label: 'Done (may need a change to filter)' },
            { data: 'notdone', label: 'Not Done (filter working properly)' },
            { data: 'ndefm', label: 'Not Done (may need a change to filter)' },
            { data: 'redlink', label: 'Not Done (notable people)' },
            { data: 'alreadydone', label: 'Already Done' },
            { data: 'denied', label: 'Decline (edits are vandalism)' },
            { data: 'checking', label: 'Checking' },
            { data: 'blocked', label: 'User blocked' },
            { data: 'talk', label: 'Request on article talk page' },
            { data: 'fixed', label: 'Fixed filter' },
            { data: 'question', label: 'Question' },
            { data: 'note', label: 'Note' },
            { data: 'private', label: 'Private filter' },
            { data: 'pin', label: 'Pin' },
            { data: 'moot', label: 'Moot (filter working properly)' },
            { data: 'mootefm', label: 'Moot (may need a change to filter)' }
        ],
        responseSummaryMap: {
            none: '',
            nofilterstriggered: 'No filters triggered',
            done: 'Done; no change to filter',
            defm: 'Done; may need a change to filter',
            notdone: 'Not done; filter working properly',
            ndefm: 'Not done; may need a change to filter',
            redlink: 'Not done; notable people lists and similar are only meant for [[WP:WTAF|people who already have articles about them]]',
            alreadydone: 'Already done',
            denied: 'Decline; edits are vandalism',
            checking: 'Checking',
            blocked: 'User is blocked',
            talk: 'Please request on article talk page',
            fixed: 'Fixed filter',
            question: 'Question',
            note: 'Note',
            private: 'Private filter',
            pin: 'Pin',
            moot: 'Moot; filter working properly',
            mootefm: 'Moot; may need a change to filter'
        },
        init() {
            const allowedPages = [
                'Wikipedia:Edit filter/False positives/Reports',
                'User:DannyS712/EFFPRH/sandbox'
            ];
            const currentPage = mw.config.get('wgPageName').replace(/_/g, ' ');
            if (!allowedPages.includes(currentPage)) return;
            mw.loader.using(['oojs-ui', 'mediawiki.util', 'mediawiki.api'], this.run.bind(this));
        },
        run() {
            this.addStyle();
            $('div.mw-heading h2').each((_, heading) => {
                const editLinks = $(heading).parent().find('.mw-editsection');
                const sectionNum = this.getSectionNumber(editLinks);
                if (sectionNum !== -1) {
                    const nextSection = $(heading).parent().next('section');
                    if (nextSection.length > 0) {
                        nextSection.prepend($('<div>').attr('id', `script-EFFPRH-${sectionNum}`));
                    } else {
                        $(heading).parent().after($('<div>').attr('id', `script-EFFPRH-${sectionNum}`));
                    }
                    this.addHandlerLink(editLinks, $(heading).text(), sectionNum);
                }
            });
        },
        addStyle() {
            mw.util.addCSS(`
                .script-EFFPRH-handler { background-color: #f5f5f5; border: 1px solid #ccc; margin: 10px 0; padding: 10px; border-radius: 5px; }
                .script-EFFPRH-handler td { vertical-align: middle; padding: 5px; }
                .script-EFFPRH-handler ul { margin: 10px 0 10px 2em; padding: 0; list-style-position: inside; }
                .script-EFFPRH-preview { background-color: white; }
                .oo-ui-dropdownWidget .oo-ui-dropdownWidget-handle { min-width: 220px; }
            `);
        },
        getSectionNumber(editLinks) {
            const editSectionUrl = editLinks.find('a:first').attr('href');
            const sectionMatch = editSectionUrl && editSectionUrl.match(/&section=(\d+)(?:$|&)/);
            return sectionMatch ? parseInt(sectionMatch[1]) : -1;
        },
        addHandlerLink(editLinks, reporterName, sectionNum) {
            const handlerLink = $('<a>').attr('id', `script-EFFPRH-launch-${sectionNum}`).text('Review report');
            handlerLink.click((e) => {
                e.stopPropagation();
                if (!handlerLink.hasClass('script-EFFPRH-disabled')) {
                    handlerLink.addClass('script-EFFPRH-disabled');
                    this.showHandler(reporterName, sectionNum);
                }
            });
            editLinks.children().last().before(' | ', handlerLink);
        },
        showHandler(reporterName, sectionNum) {
            $(`#script-EFFPRH-${sectionNum}`).empty();
            let selectedResponse = 'none';
            let commentValue = '';
            let showPreview = false;
            let haveSubmitted = false;
            let editMade = false;
            let editError = false;
            const $container = $('<div>').addClass('script-EFFPRH-handler');
            $container.append($('<p>').text(`Responding to report by ${reporterName}.`));
            let $debugP, updateDebug;
            if (EFFPRH.config.debug) {
                $debugP = $('<p>');
                $container.append($debugP);
                updateDebug = function() {
                    $debugP.text(
                        `Section ${sectionNum}, selected response: ${selectedResponse}, comment: ${commentValue}.`
                    );
                };
                updateDebug();
            }
            const $table = $('<table>');
            const dropdown = new OO.ui.DropdownWidget({
                label: 'Response to report',
                menu: {
                    items: EFFPRH.responseOptions.map(opt =>
                        new OO.ui.MenuOptionWidget({ data: opt.data, label: opt.label })
                    )
                }
            });
            dropdown.getMenu().selectItemByData('none');
            const $dropdownRow = $('<tr>')
                .append($('<td>').append($('<label>').text('Action:')))
                .append($('<td>').append(dropdown.$element));
            $table.append($dropdownRow);
            const textInput = new OO.ui.TextInputWidget({
                placeholder: 'Optional comment'
            });
            const $commentRow = $('<tr>')
                .append($('<td>').append($('<label>').text('Comment:')))
                .append($('<td>').append(textInput.$element));
            $table.append($commentRow);
            $container.append($table);
            const $statusUl = $('<ul>').css('margin', 0).hide();
            const $liSubmitting = $('<li>').text('Submitting...');
            const $liSuccess = $('<li>').html(`Success! <a href="#"><strong>Reload the page</strong></a></li>`);
            const $liError = $('<li>').text('Uh-oh, something went wrong. Please check the console for details.');
            $statusUl.append($liSubmitting).append($liSuccess.hide()).append($liError.hide());
            $container.append($statusUl);
            const submitBtn = new OO.ui.ButtonWidget({
                label: 'Submit',
                flags: ['progressive'],
                disabled: true
            });
            const cancelBtn = new OO.ui.ButtonWidget({
                label: 'Cancel',
                flags: ['destructive']
            });
            const previewToggleBtn = new OO.ui.ToggleButtonWidget({
                label: 'Show preview',
                disabled: true
            });
            const $btnRow = $('<div>').css('margin', '10px 0')
                .append(submitBtn.$element)
                .append(cancelBtn.$element)
                .append(previewToggleBtn.$element);
            $container.append($btnRow);
            const $previewArea = $('<div>').addClass('script-EFFPRH-preview').hide();
            $container.append($previewArea);
            $(`#script-EFFPRH-${sectionNum}`).append($container);
            function getResponseWikiText() {
                return `: {{EFFP|${selectedResponse}}} ${commentValue} – ~~~~`;
            }
            function updatePreview() {
                $previewArea.empty();
                if (showPreview && selectedResponse !== 'none') {
                    $previewArea.append('<hr>');
                    $previewArea.append($('<div>').text('Loading preview...'));
                    new mw.Api().get({
                        action: 'parse',
                        formatversion: 2,
                        title: mw.config.get('wgPageName'),
                        text: getResponseWikiText(),
                        prop: 'text|wikitext',
                        pst: true,
                        disablelimitreport: true,
                        disableeditsection: true,
                        sectionpreview: true
                    }).then(function (res) {
                        if (res && res.parse && res.parse.text) {
                            $previewArea.empty().append('<hr>').append(
                                $('<div>').html(res.parse.text)
                            );
                        } else {
                            $previewArea.empty().append('<hr>').append(
                                $('<div>').text('Error loading preview.')
                            );
                        }
                    });
                }
                $previewArea.toggle(showPreview && selectedResponse !== 'none');
            }
            function updateCanSubmit() {
                const canSubmit = !haveSubmitted && selectedResponse !== 'none';
                submitBtn.setDisabled(!canSubmit);
                previewToggleBtn.setDisabled(!canSubmit);
            }
            dropdown.getMenu().on('choose', function (item) {
                selectedResponse = item.getData();
                updateCanSubmit();
                previewToggleBtn.setLabel(showPreview ? 'Hide preview' : 'Show preview');
                updatePreview();
                if (EFFPRH.config.debug) updateDebug();
            });
            textInput.on('change', function (val) {
                commentValue = val;
                updatePreview();
                if (EFFPRH.config.debug) updateDebug();
            });
            previewToggleBtn.on('change', function (on) {
                showPreview = on;
                previewToggleBtn.setLabel(showPreview ? 'Hide preview' : 'Show preview');
                updatePreview();
            });
            submitBtn.on('click', function () {
                haveSubmitted = true;
                updateCanSubmit();
                $statusUl.show();
                $liSubmitting.show();
                $liSuccess.hide();
                $liError.hide();
                EFFPRH.respondToReport(
                    reporterName,
                    sectionNum,
                    getResponseWikiText(),
                    selectedResponse
                ).then(
                    function () {
                        editMade = true;
                        $liSubmitting.hide();
                        $liSuccess.show();
                        $liSuccess.find('a').on('click', function (e) {
                            e.preventDefault();
                            ___location.assign(`${mw.util.getUrl(mw.config.get('wgPageName'))}#${reporterName}`);
                            ___location.reload();
                        });
                    },
                    function () {
                        editError = true;
                        $liSubmitting.hide();
                        $liError.show();
                    }
                );
            });
            cancelBtn.on('click', function () {
                $(`#script-EFFPRH-${sectionNum}`).empty();
                $(`#script-EFFPRH-launch-${sectionNum}`).removeClass('script-EFFPRH-disabled');
            });
            updateCanSubmit();
        },
        respondToReport(reporterName, sectionNum, responseWikiText, selectedResponse) {
            return new Promise((resolve, reject) => {
                const wikitextToAdd = `\n${responseWikiText}`;
                let respText = EFFPRH.responseSummaryMap[selectedResponse] || selectedResponse;
                if (!respText) {
                    respText = 'Response to false positive report';
                }
                const editParams = {
                    action: 'edit',
                    title: mw.config.get('wgPageName'),
                    section: sectionNum,
                    summary: `/* ${reporterName} */ ${respText} ([[User:DreamRimmer/EFFPRH|EFFPRH.js]])`,
                    appendtext: wikitextToAdd,
                    token: mw.user.tokens.get('csrfToken')
                };
                new mw.Api().postWithEditToken(editParams).then(resolve, reject);
            });
        }
    };
    EFFPRH.init();
});
// </nowiki>