Jump to content

User:Prtksxna/jade-test.js: Difference between revisions

From Wikipedia, the free encyclopedia
Content deleted Content added
No edit summary
No edit summary
Line 84: Line 84:
$( 'td.diff-ntitle').append(
$( 'td.diff-ntitle').append(
$( '<div>' ).css( 'text-align', 'left').append(
$( '<div>' ).css( 'text-align', 'left').addClass('jade-container').append(
$ores,
$ores,
$newForm,
$newForm,

Revision as of 01:41, 21 September 2018

// 1. Find your common.js
//        https://en.wikipedia.org/wiki/Special:MyPage/common.js
// 2. Add the following code to it:
//        mw.loader.load('/w/index.php?title=User:Prtksxna/jade-test.js&action=raw&ctype=text/javascript');
// 3. Go to History page, for example:
//        https://en.wikipedia.org/w/index.php?title=Delhi_Airport_Metro_Express&action=history
// 4. Click on a revision that has (fake) judgements, for example:
//        https://en.wikipedia.org/w/index.php?f=Delhi_Airport_Metro_Express&diff=839712756&oldid=838620306&diffmode=source
// 5. ???
// 6. PROFIT!


mw.loader.using( ['oojs', 'oojs-ui-core', 'oojs-ui-widgets', 'moment', 'mediawiki.api.messages'], function () {
	
	// Config
	// Also see the following methods below
	// - getRandomJudgement
	// - hasJudgment
	// - getNoOfJudgements
	var config = {
		'showORES': false,
		'showDeleteButton': true,
		'singleJudgement': false,
		'notesPlaceholder': 'Notes about the judgment',
		// TODO: Show this help somewhere?
		'notesHelp': 'This is where to record thoughts about the entity and judgment.',
		// TODO: Include a link to the Jade_talk page.
		'lastSelectedDamaging': null,
		'lastSelectedGoodfaith': null,
		// Help text for judgment button option widget
		'notDamaging': 'Help text for not damaging',
		'damaging': 'Help text for damaging',
		'goodFaith': 'Help text for good faith',
		'badFaith': 'Help text for bad faith',
	};
	
	var flags = [];
	
	// Bootstrap
	new mw.Api().getMessages( [ 'damaging', 'february', 'march' ], { amlang: 'en' } ).then(
		function ( d ) {
			console.log( d );
		}
	);
	$( function () {
		var currentPage = whichPage();
		if ( !currentPage ) {
			return;
		} else if ( currentPage === 'history' ) {
			addJudgementsToHistory();
		} else	if ( currentPage === 'change' ) {
			addJudgementsToChanges();
		} else if ( currentPage === 'diff' ) {
			addJudgementsToDiff();
		}
	} );
	
	// Methods
	
	/*
	 * Add judgements to the diff page
	**/
	function addJudgementsToDiff () {
		var uriArray = $('#mw-diff-ntitle1').find('a').attr('href').split("=");
		var id = uriArray[ uriArray.length - 1 ];
		var nOfJ = getNoOfJudgements( id );
		var $ores, $newForm, $judgements = $( '<div>' ).addClass( 'jade-judgements');
		
		// Actual ORES score
		if ( config.showORES ) {
			$ores = $( '<div>' );
			populateORES( id, $ores );
		}
		
		// Show a new judgement form if applicable
		if ( config.singleJudgement === false || nOfJ === 0 ) {
			$newForm = getNewJudgementForm();
		}
		
		// Show 'existing' dummy judgements
		for( var i = 0; i < nOfJ; i++ ) {
			$judgements.append( getJudgementElement( getRandomJudgement( i ) ) );
		}
		
		$( 'td.diff-ntitle').append( 
			$( '<div>' ).css( 'text-align', 'left').addClass('jade-container').append(
				$ores, 
				$newForm, 
				'<h3>Judgements</h3>',
				$judgements 
			)
		);
	}
	
	function getJudgementElement ( j ) {
		var $user = $( '<a>' )
			.text( j.user )
			.css( 'font-weight', '800' )
			.attr( 'href', 'https://en.wikipedia.org/w/index.php?title=User:' + j.user );
			
		var ago = j.ago || moment( new Date(+(new Date()) - Math.floor(Math.random()*10000000000)) ).fromNow();
		
		var $reason = $( '<div>' )
			.text( j.reason )
			.css( {
				'border-top': '1px solid #c8ccd1',
				'margin-top': '5px',
				'padding': '10px',
				'overflow': 'hidden'
			} )
			.hide();
			
		var $deleteButton = '';
		if ( config.showDeleteButton ) {
			$deleteButton = new OO.ui.ButtonWidget( {
				icon: 'trash',
				framed: false,
			} ).$element.css( 'float', 'right' ).on( 'click', function () {
				OO.ui.confirm( 'Are you sure?' ).done( function ( confirmed ) {
    				if ( confirmed ) {
	        			$j.fadeOut();
    				}
				} );
			});
		}
		
		var $flaggedButton = new OO.ui.ToggleButtonWidget( {
			icon: 'flag',
			title: 'Preferred judgement'
		} );
		
		$flaggedButton.on( 'click', function (e,i) {
			flags.forEach( function( flag ) {
				flag.setValue( false );
				flag.setLabel('')
			} );
			$j.slideUp( 100, function () {
				var k = $j.detach();
				$( ".jade-judgements" ).prepend( k );
				k.slideDown();
				$flaggedButton.setValue( true );
				$flaggedButton.setLabel( 'Preferred');
			});
		});
		
		flags.push( $flaggedButton );
		
		var $expandButton = new OO.ui.ButtonWidget( {
			framed: false,
			icon: 'expand',
			title: 'Expand'
		} ).$element.on('click', function () {
			$reason.slideToggle();
		}).css( 'float', 'right');
		
		$expandButton = j.reason === null || j.reason === undefined || j.reason === '' ? '' : $expandButton;

		var $j = $( '<div>' ).css({
			'background': '#eaecf0',
			'border-radius': '2px',
			'padding': '3px 0',
			'margin-bottom': '20px',
		});
		
		$j.append( $expandButton, $deleteButton, $flaggedButton.$element.css( 'float', 'right') );
		var $vars = $( '<div>' ).css( 'margin', '10px');
		
		$j.append( $vars );
		
		if ( j.damaging === true ) {
			$vars.append(
				$( '<span>' )
					.css( {
						'color': '#fff',
						'background': '#d33',
						'border-radius': '2px',
						'padding': '3px 15px 6px',
						'margin-right': '5px',
						'text-transform': 'lowercase',
						'font-variant': 'small-caps',
						'letter-spacing': '0.3px'
					})
					.text( 'Damaging ')
			)
		} else if ( j.damaging === false ) {
			$vars.append(
				$( '<span>' )
					.css( {
						'color': '#fff',
						'background': '#36c',
						'border-radius': '2px',
						'padding': '3px 15px 6px',
						'margin-right': '5px',
						'text-transform': 'lowercase',
						'font-variant': 'small-caps',
						'letter-spacing': '0.3px'

					})
					.text( 'Not damaging')
			)
		}
		
		if ( j.goodfaith === true ) {
			$vars.append(
				$( '<span>' )
					.css( {
						'color': '#fff',
						'background': '#14866d',
						'border-radius': '2px',
						'padding': '3px 15px 6px',
						'margin-right': '5px',
						'text-transform': 'lowercase',
						'font-variant': 'small-caps',
						'letter-spacing': '0.3px'

					})
					.text( 'Good faith')
			)
		} else if ( j.goodfaith === false ) {
			$vars.append(
				$( '<span>' )
					.css( {
						'color': '#fff',
						'background': '#d33',
						'border-radius': '2px',
						'padding': '3px 15px 6px',
						'margin-right': '5px',
						'text-transform': 'lowercase',
						'font-variant': 'small-caps',
						'letter-spacing': '0.3px'

					})
					.text( 'Bad faith')
			)
		}

		
		$j.append( $( '<div>' )
			.css( 'color', '#54595d' )
			.css( 'padding', '0 10px' )
			.append( $user )
			.append ( ' • ' )
			.append( ago )
		).append( $reason);
		
		return $j;
	}
	
	// Returns a new judement form
	function getNewJudgementForm () {
		var d = new OO.ui.ButtonSelectWidget( {
			items: [
				new OO.ui.ButtonOptionWidget( {
					data: 'not damaging',
					label: 'Not damaging',
					title: config.notDamaging
				} ),
				new OO.ui.ButtonOptionWidget( {
					data: 'damaging',
					label: 'Damaging',
					title: config.damaging
				} ),
			]
		} );
		
		var f = new OO.ui.ButtonSelectWidget( {
			items: [
				new OO.ui.ButtonOptionWidget( {
					data: 'good faith',
					label: 'Good faith',
					title: config.goodFaith
				} ),
				new OO.ui.ButtonOptionWidget( {
					data: 'bad faith',
					label: 'Bad faith',
					title: config.badFaith
				} ),
			]
		} );
		
		var r = new OO.ui.MultilineTextInputWidget( {
			autosize: true,
			rows: 4,
			placeholder: config.notesPlaceholder
		} );
		
		var s = new OO.ui.ButtonWidget( {
			label: 'Add judgement',
			flags: ['progressive', 'primary' ]
		} );

		d.on('choose', function( item ) {
			if ( item === config.lastSelectedDamaging ) {
				// Deselect if the user is clicking on an already selected checkbox.
				d.selectItem( null );
				config.lastSelectedDamaging = null;
			} else {
				config.lastSelectedDamaging = item;
			}
		} );

		f.on('choose', function( item ) {
			if ( item === config.lastSelectedGoodfaith ) {
				// Deselect if the user is clicking on an already selected checkbox.
				f.selectItem( null );
				config.lastSelectedGoodfaith = null;
			} else {
				config.lastSelectedGoodfaith = item;
			}
		} );
		
		s.on('click', function () {
			var j = isValidJudgement( r, d, f );
			if ( !j ) {
				OO.ui.alert( 'Please enter a judgement' );
			} else {
				$thanks = $( '<div>' )
					.text( 'Thank you! Your judgement has been added.' )
					.css({
						'padding': '20px',
						'background': '#d5fdf4',
						'border': '1px solid #14866d',
						'color': '#14866d'
					});
				$( ".jade-judgements" ).prepend( getJudgementElement( j ).hide().fadeIn( 2000 ) );
				$( ".jade-new" )
					.empty()
					.append( $thanks );
			}
		} );
		
		r.$element.find( 'textarea' ).css( 'border-radius', '2px 2px 0 0');
		var $buttonHolder = $( '<div>' ).css( {
			'border': '1px solid #a2a9b1',
			'border-top': 'none',
			'border-radius': '0 0 2px 2px',
			'padding': '10px'
		}).append( d.$element, f.$element );
		
		var $submitHolder = $( '<div>' )
			.css( 'overflow', 'hidden')
			.append( $('<small>').css('display','block').text( config.notesHelp ) )
			.append( 
				$('<small>').css('display','block')
					.append( 'By saving changes, you agree to our ' )
					.append( $( '<a>').text( 'Terms of Use').attr( 'href', 'https://wikimediafoundation.org/wiki/Terms_of_Use/en' ) )
					.append( ' and agree to irrevocably release your text under the ')
					.append( $( '<a>').text( 'CC BY-SA 3.0 License').attr( 'href', 'https://creativecommons.org/licenses/by-sa/3.0' ) )
					.append( ' and ')
					.append( $( '<a>').text( 'GDFL').attr( 'href', 'https://en.wikipedia.org/wiki/Wikipedia:Text_of_the_GNU_Free_Documentation_License' ) )
			)
			.append( s.$element.css( 'float', 'right') );
		
		return $( '<div>' )
			.addClass( 'jade-new' )
			.append( 
				'<h3>New judgement</h3>', 
				r.$element, 
				$buttonHolder, 
				$submitHolder 
			);
	}
	
	function isValidJudgement( textInput, damagingInput, faithInput ) {
		var textInput = textInput.getValue();
		var faithInput = faithInput.findSelectedItem();
		var damagingInput = damagingInput.findSelectedItem();
		
		// At least one bit of data must be present.
		if (
			( textInput === '' || textInput === null ) &&
			faithInput === null &&
			damagingInput === null
		) {
			return false;
		}

		return {
			reason: textInput,
            // TODO: No ternary.
			goodfaith: ( faithInput === null ? null : faithInput.data === 'good faith' ),
			damaging: ( damagingInput === null ? null : damagingInput.data === 'damaging' ),
			user: $( "#pt-userpage a").text(),
			ago: moment( Date.now() ).fromNow()
		};
	}
	
	function populateORES ( id, $ores ) {
		var uri = 'https://ores.wikimedia.org/v3/scores/enwiki?models=damaging%7Cgoodfaith&revids=' + id;
		$.ajax( uri ).done(function( dat ) {
			var score = dat.enwiki.scores[id];
			var j = {
				'user': 'ORES' ,
				'damaging': score.damaging.score.prediction,
				'goodfaith': score.goodfaith.score.prediction
			};
			dPercent = Math.floor( score.damaging.score.probability[ score.damaging.score.prediction ] * 100 );
			fPercent = Math.floor( score.goodfaith.score.probability[ score.goodfaith.score.prediction ] * 100 );
			j.reason = "I am " + dPercent + "% sure about the damage, and " + fPercent + "% sure about the intention.";
			$ores.append( getJudgementElement( j ) );
		} );
	}
	
	/*
	 * Given a revId create a judgement token
	 *
	 * @param {Number} id
	 * @return {jQuery}
	**/
	function getJudgementToken ( id, href ) {
		
		if ( 
			// According to config, this rev won't have a judgement
			!hasJudgement( id ) || 
			// We couldn't find the diff page, so no judgement for this one
			href.indexOf( 'oldid' ) < 0
		) {
			return false;
		}
		
		var text = config.singleJudgement ? 'Judgement' : getNoOfJudgements( id ) + ' judgement(s)'; 
				
		return $( '<a>' )
			.addClass( 'judgement-token' )
			.attr( 'href', href )
			.css( {
				'background': '#72777d',
				'color': '#fff',
				'padding': '3px',
				'margin': '5px',
				'border-radius': '2px'
			} )
			.text( text )
	}
	
	/*
	 * Iterate over history items and add a judgement token
	**/
	function addJudgementsToHistory () {
		$( '#pagehistory li').each( function () {
			var $this = $( this );
			var href = $this.find( '.mw-history-histlinks a' ).last().attr( 'href' );
			var id = $this.attr( 'data-mw-revid');
			var $judgementToken = getJudgementToken( id, href );
			
			if ( $judgementToken ) {
				$this.find( '.history-user' ).append( $judgementToken );
			}
		} );
	}
	
	/*
	 * Iterate over changes items and add a judgement token
	**/
	function addJudgementsToChanges () {
		$( 'li.mw-changeslist-line').each( function () {
			var $this = $( this );
			var href = $this.find( 'a' ).first().attr( 'href' );
			var id = $this.attr( 'data-mw-revid');
			var $judgementToken = getJudgementToken( id, href );
			
			if ( $judgementToken ) {
				$this.find( '.mw-usertoollinks' ).append( $judgementToken );
			}
		} );
	}
	
	/*
	 * Dummy function that consistently tells how many judgements
	 * a rev should have based on its ID
	 *
	 * @param {Number} id
	 * @rutern {Number} Number of judgements
	**/
	function getNoOfJudgements ( id ) {
		if ( !hasJudgement( id ) ) {
			return 0;
		}
		
		if ( config.singleJudgement ) {
			return 1;
		}
		
		if ( id.slice( -1 ) === '0' ) {
			return 1;
		} else {
			return parseInt( id.slice( -1 ) );
		}
	}
	
	/* 
	 * Dummy function that tells whether a rev should have 
	 * judgements or not, just to keep things random
	 *
	 * @param {Number} id
	 * @return {Boolean} Whether this revision should have a judgement
	**/
	function hasJudgement ( id ) {
		return id % 2 === 0;
	}
	
	/* 
	 * Detect which page we are on
	 * Return false if we need not take any action
	 *
	 * @return {String|false}
	**/
	function whichPage () {
		if ( $( 'table.diff').length > 0 ) {
			return 'diff';
		}
		if ( $( '#pagehistory li ' ).length > 0 ) {
			return 'history';
		}
		if ( $( 'li.mw-changeslist-line' ).length > 0 ) {
			return 'change';
		}
		return false;
	}
	
	// Dummy function returns a random generated judgement
	function getRandomJudgement ( userId ) {
		var randomReasons = [
			"This is the deletion of a page on a local wiki. That can't be vandalism as it's something only a local admin can do. Maecenas ullamcorper quam a finibus consequat. Nunc et risus lorem. Sed pellentesque semper nibh, sed volutpat arcu pretium id. Cras auctor non libero id fermentum. Sed accumsan ornare elit eget pellentesque.",
			"Here I'm undoing bad edits. Maecenas ullamcorper quam a finibus consequat. Nunc et risus lorem. Sed pellentesque semper nibh, sed volutpat arcu pretium id. Cras auctor non libero id fermentum. Sed accumsan ornare elit eget pellentesque.",
			"This is just adding a sitelink, it doesn't look suspicious to me. Maecenas ullamcorper quam a finibus consequat. Nunc et risus lorem. Sed pellentesque semper nibh, sed volutpat arcu pretium id. Cras auctor non libero id fermentum. Sed accumsan ornare elit eget pellentesque.",
			"This is a bot fixing the way the value was entered. Maecenas ullamcorper quam a finibus consequat. Nunc et risus lorem. Sed pellentesque semper nibh, sed volutpat arcu pretium id. Cras auctor non libero id fermentum. Sed accumsan ornare elit eget pellentesque.",
			"Anonymous IPv6 user is adding a valid id for an external site. Nothing wrong with the addition. Maecenas ullamcorper quam a finibus consequat. Nunc et risus lorem. Sed pellentesque semper nibh, sed volutpat arcu pretium id. Cras auctor non libero id fermentum. Sed accumsan ornare elit eget pellentesque.",
			"This edit wasn't tagged, however can be considered vandalism. Maecenas ullamcorper quam a finibus consequat. Nunc et risus lorem. Sed pellentesque semper nibh, sed volutpat arcu pretium id. Cras auctor non libero id fermentum. Sed accumsan ornare elit eget pellentesque.",
			"It is a proper addition of a link. Maecenas ullamcorper quam a finibus consequat. Nunc et risus lorem. Sed pellentesque semper nibh, sed volutpat arcu pretium id. Cras auctor non libero id fermentum. Sed accumsan ornare elit eget pellentesque.",
			"Correction year of publication of a musical album by a registered user. Maecenas ullamcorper quam a finibus consequat. Nunc et risus lorem. Sed pellentesque semper nibh, sed volutpat arcu pretium id. Cras auctor non libero id fermentum. Sed accumsan ornare elit eget pellentesque.",
			"Typo noun correction from a registered user. Maecenas ullamcorper quam a finibus consequat. Nunc et risus lorem. Sed pellentesque semper nibh, sed volutpat arcu pretium id. Cras auctor non libero id fermentum. Sed accumsan ornare elit eget pellentesque.",
			"Modification of a word with a synonym by an anonymous user. Maecenas ullamcorper quam a finibus consequat. Nunc et risus lorem. Sed pellentesque semper nibh, sed volutpat arcu pretium id. Cras auctor non libero id fermentum. Sed accumsan ornare elit eget pellentesque.",
			"Rearrangement of comments by registered user. Maecenas ullamcorper quam a finibus consequat. Nunc et risus lorem. Sed pellentesque semper nibh, sed volutpat arcu pretium id. Cras auctor non libero id fermentum. Sed accumsan ornare elit eget pellentesque.",
			"","","","",""
		];
		var randomUsers = [ 'halfak', 'aaron', 'EpochFail', 'adam', 'awight', 'prtksxna', 'prateek', 'foo', 'bar' ];
		var goodfaith = ( Math.round( Math.random() ) === 0 ) ? true : false;
		var damaging = ( Math.round( Math.random() ) === 0 ) ? true : false;
		var reason = randomReasons[ Math.floor( Math.random() * ( randomReasons.length - 1 ) ) ];
		
		return {
			'goodfaith': goodfaith,
			'damaging': damaging,
			'reason': reason,
			'user': randomUsers[ userId ]
		};
	}
} );