User:DannyS712/EFFPRH/sandbox.js

This is an old revision of this page, as edited by DannyS712 (talk | contribs) at 07:54, 20 May 2022 (disable inputs on submitting, cannot submit without response, clean up debug logging). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
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>
// Script to respond to edit filter false positive reports
// @author DannyS712
$(() => {
const EFFPRH = {};
window.EFFPRH = EFFPRH;

EFFPRH.init = function () {
	mw.loader.using(
		[ 'vue', 'wvui', 'mediawiki.util', 'mediawiki.api' ],
		EFFPRH.run
	);
};

EFFPRH.run = function () {
	console.log( 'EFFPRH - running' );
	EFFPRH.addStyle();
	// Add links to each section to open a dialog
	$('span.mw-headline').each( function () {
		const $editSectionLinks = $( this ).parent().find( '.mw-editsection' );
		if ( $editSectionLinks.length === 0 ) {
			// Missing links span, nothing to do
			return;
		}
		const sectionNum = EFFPRH.getHeadingSectionNum( $editSectionLinks );
		if ( sectionNum === -1 ) {
			// Missing link, no idea what section this is
			return;
		}
		// Add a hidden div after the headline that will be where the Vue
		// display goes
		$( this ).parent().after(
			$( '<div>' ).attr( 'id', 'script-EFFPRH-' + sectionNum )
		);
		const reporterName = $( this ).text();
		EFFPRH.addHandlerLink( $editSectionLinks, reporterName, sectionNum );
	} );
};

/**
 * Add styles for our interface.
 */
EFFPRH.addStyle = function () {
	mw.util.addCSS(`
		.script-EFFPRH-handler {
			background-color: #d6d6d6;
			border: 1px solid black;
			margin: 10px 0 10px 0;
		}
		/* Don't take up entire width for input, and make dropdown the same */
		.wvui-dropdown,
		.wvui-input {
			width: 50%;
		}
		/* Override normal rules for indenting lists */
		.wvui-dropdown ul {
			margin-left: 0px;
		}
		/* Separate the dropdown and input */
		.wvui-dropdown {
			margin-bottom: 10px;
		}
	`);
};

/**
 * Get the section number for a response, given the jQuery element for the
 * <span> with the edit section link. Returns -1 on failure.
 */
EFFPRH.getHeadingSectionNum = function ( $editSectionLinks ) {
	const editSectionUrl = $editSectionLinks.find( 'a:first' ).attr( 'href' );
	if ( editSectionUrl === undefined ) {
		return -1;
	}
	const sectionMatch = editSectionUrl.match( /&section=(\d+)(?:$|&)/ );
	if ( sectionMatch === null ) {
		return -1;
	}
	return parseInt( sectionMatch[1] );
};

/**
 * Add a link next to the edit section link that will launch the report handler.
 */
EFFPRH.addHandlerLink = function ( $editSectionLinks, reporterName, sectionNum ) {
	const $handlerLink = $( '<a>' )
		.attr( 'id', 'script-EFFPRH-launch-' + sectionNum )
		.text( 'Review report' );
	$handlerLink.click(
		function () {
			// Only allow running once per link (until the Vue handler is removed)
			if ( $( this ).hasClass( 'script-EFFPRH-disabled' ) ) {
				return;
			}
			$( this ).addClass( 'script-EFFPRH-disabled' );
			EFFPRH.showHandler( reporterName, sectionNum );
		}
	);
	// Add before the closing ] of the links
	$editSectionLinks.children().last().before(
		' | ',
		$handlerLink
	);
};

// Handler options, see {{EFFP}}
EFFPRH.responseOptions = [
	{ id: 'none', label: 'Nothing' },
	{ id: 'checking', label: 'Checking with edit filter managers' },
	{ id: 'notdone-change', label: 'Not done, but a filter change may be needed' },
	{ id: 'done-change', label: 'Done, and a filter change may be needed' },
	{ id: 'notdone', label: 'Not done' }
];

/**
 * Actually show the handler for a given reporter name and section number.
 */
EFFPRH.showHandler = function ( reporterName, sectionNum ) {
	const targetDivId = 'script-EFFPRH-' + sectionNum;
	// Need a reference so that it can be unmounted
	let vueAppInstance;
	// We shouldn't use the mw.loader access directly, but I'm not
	// pasing around the `require` function everywhere
	const wvui = mw.loader.require( 'wvui' );
	const handlerApp = {
		components: {
			WvuiButton: wvui.WvuiButton,
			WvuiDropdown: wvui.WvuiDropdown,
			WvuiInput: wvui.WvuiInput
		},
		data: function () {
			return {
				reporterName: reporterName,
				sectionNum: sectionNum,
				responseOptions: EFFPRH.responseOptions,
				selectedResponse: 'none',
				commentValue: '',

				// Overall state
				haveSubmitted: false
			};
		},
		computed: {
			canSubmit: function () {
				return !this.haveSubmitted && this.selectedResponse !== 'none';
			}
		},
		methods: {
			onCommentChange: function ( newComment ) {
				this.commentValue = newComment;
			},
			submitHandler: function () {
				this.haveSubmitted = true;
				console.log( 'Should submit!' );
			},
			cancelHandler: function () {
				if ( vueAppInstance === undefined ) {
					console.log( 'Cannot unmount, no vueAppInstance' );
				} else {
					vueAppInstance.unmount();
					// Restore link
					$( '#script-EFFPRH-launch-' + sectionNum ).removeClass(
						'script-EFFPRH-disabled'
					);
				}
			}
		},
		template: `
<div class="script-EFFPRH-handler">
<p>Section {{ sectionNum }} for report by {{ reporterName }}. Selected response: {{ selectedResponse }}. Comment: {{ commentValue }}.</p>
<wvui-dropdown v-model="selectedResponse" :items="responseOptions" defaultLabel="Response to report" :disabled="!haveSubmitted" />
<wvui-input :value="commentValue" v-on:input="onCommentChange" placeholder="Comment" :disabled="!haveSubmitted" />
<br />
<wvui-button type="primary" action="progressive" :disabled="!canSubmit" v-on:click="submitHandler">Submit</wvui-button>
<wvui-button type="primary" action="destructive" :disabled="!haveSubmitted" v-on:click="cancelHandler">Cancel</wvui-button>
</div>`
	};
	vueAppInstance = Vue.createMwApp( handlerApp );
	vueAppInstance.mount( '#' + targetDivId );
};

});

$( document ).ready( () => {
	if (
		mw.config.get( 'wgPageName' ) === 'Wikipedia:Edit_filter/False_positives/Reports'
		|| mw.config.get( 'wgPageName' ) === 'User:DannyS712/EFFPRH/sandbox'
	) {
		window.EFFPRH.init();
	}
});

// </nowiki>