User:DannyS712/userfeedback.js

From mediawiki.org

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
/**
 * userfeedback.js
 *
 * Collect user votes on the helpfulness/quality of a documenation page by
 * posting an EventLogging log event to the "UserFeedback" channel.
 *
 * @source https://wikitech.wikimedia.org/wiki/MediaWiki:Gadget-userfeedback.js
 * @license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3-or-Later
 * @licstart  The following is the entire license notice for the JavaScript code in this gadget.
 *
 * Copyright (C) 2019 Srishti Sethi <https://meta.wikimedia.org/wiki/User:SSethi_(WMF)> and contributors
 *
 * The JavaScript/Gadget code in this page is free software: you can
 * redistribute it and/or modify it under the terms of the GNU
 * General Public License (GNU GPL) as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version.  The code is distributed WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.
 *
 * As additional permission under GNU GPL version 3 section 7, you
 * may distribute non-source (e.g., minimized or compacted) forms of
 * that code without the copy of the GNU GPL normally required by
 * section 4, provided you include this license notice and a URL
 * through which recipients can access the Corresponding Source.
 *
 * @licend  The above is the entire license notice for the JavaScript/Gadget code in this gadget.
 */
(function () {
  'use strict';

	var supportedNamespaces = [ 'API' ],
		validVotes = [ 'yes', 'no' ],
		articleId = mw.config.get( 'wgArticleId' ),
		namespace = mw.config.get( 'wgCanonicalNamespace' ),
		action = mw.config.get( 'wgAction' ),
		pageName = mw.config.get( 'wgPageName' ),
		voteCookieName = 'vote_' + articleId,
		isRedirect = mw.config.get( 'wgIsRedirect' );

	/**
	 * Check for a prior vote by the current user for the current page.
	 *
	 * @return {string|null} Prior recorded vote or null if no vote found
	 */
	function getPreviousVote() {
		return mw.cookie.get( voteCookieName );
	}

	/**
	 * Record a vote by posting an EventLogging event and then displaying a
	 * confirmation message to the user.
	 *
	 * @param {string} vote
	 */
	function collectVote( vote ) {
		if (
			getPreviousVote() !== null ||       // User already voted
			validVotes.indexOf( vote ) === -1   // Invalid vote submitted
		) {
			return;
		}
		mw.eventLog.logEvent( 'UserFeedback', {
			"page_id": articleId,
			"page_name": pageName,
			"vote": vote
		} );
		rememberVote( vote );
		showConfirmationMsg( vote );
	}

	/**
	 * Remember the vote for the current page.
	 *
	 * @param {string} vote
	 */
	function rememberVote( vote ) {
		var expInSecs = 600; // 10 minutes
		mw.cookie.set( voteCookieName, vote, { 'expires': expInSecs } );
	}

	/**
	 * Display a confirmation message to the user about their vote.
	 *
	 * @param {string} vote
	 */
	function showConfirmationMsg( vote ) {
		var $feedback = $( '#mw-gadget-userfeedback' );
		$feedback.empty();

		if ( vote === 'yes' ) {
			$feedback.append(
				$( '<span>' ).text( mw.msg('userfeedback-confirmYes') )
			);
		} else if ( vote === 'no' ) {
			var title = mw.Title.newFromText( pageName ),
				talkPage = title.getTalkPage(),
				talkPageUrl = talkPage.getUrl();

			$feedback.append(
				$( '<span>').html(
					mw.msg(
						'userfeedback-confirmNo',
						'<a href="' + mw.html.escape( talkPageUrl ) + '" target="blank">' + mw.msg( 'userfeedback-confirmNoTalk' ) + '</a>'
					)
				)
			);
		}
	}

	/**
	 * Show the form for voting or a confirmation message if the user has
	 * recently voted on the quality of the curent page.
	 */
	function showGadgetUI() {
		var displayAfter = '#catlinks',
			$displayAfter = $( displayAfter ),
			prevVote = getPreviousVote();

		if ( $displayAfter.length === 0 ) {
			$displayAfter = $( '#mw-content-text' );
		}
		$displayAfter.after( '<div id="mw-gadget-userfeedback"></div>' );

		if ( validVotes.indexOf( prevVote ) !== -1 ) {
			showConfirmationMsg( prevVote );
		} else {
			var $feedback = $( '#mw-gadget-userfeedback' ),
				voteYes = new OO.ui.ButtonWidget( {
					label: '👍',
					title: mw.msg('userfeedback-voteYes'),
					framed: false,
					classes: [ 'thumbs', 'thumbs-up' ]
				} ),
				voteNo = new OO.ui.ButtonWidget( {
					label: '👎',
					title: mw.msg('userfeedback-voteNo'),
					framed: false,
					classes: [ 'thumbs', 'thumbs-down' ]
				} ),
				buttonGroup = new OO.ui.ButtonGroupWidget( {
					items: [ voteYes, voteNo ]
				} );
			voteYes.on( 'click', function() { collectVote( 'yes' ); } );
			voteNo.on( 'click', function() { collectVote( 'no' ); } );
			$feedback.append(
				$( '<span class="survey-question">' ).text( mw.msg('userfeedback-question' ) )
			);
			$feedback.append( buttonGroup.$element );
		}
	}

	function setMessages() {
		const msg = {
			en: {
				'userfeedback-question': 'Was this documentation helpful?',
				'userfeedback-voteYes': 'Yes, it was helpful',
				'userfeedback-voteNo': 'No, it was not helpful',
				'userfeedback-confirmYes': 'Thank you for the feedback. We are glad that you found the documentation useful!',
				'userfeedback-confirmNo': 'Thank you for the feedback. It would be helpful if you could leave some suggestions for improving the article on its $1.',
				'userfeedback-confirmNoTalk': 'talk page',
			},
			de: {
				'userfeedback-question': 'War diese Dokumentation hilfreich?',
				'userfeedback-voteYes': 'Ja',
				'userfeedback-voteNo': 'Nein',
				'userfeedback-confirmYes': 'Danke fĂźr die RĂźckmeldung!',
				'userfeedback-confirmNo': 'Danke fĂźr die RĂźckmeldung! Bitte schlage auf der $1 vor wie man diesen Artikel verbessern kĂśnnte.',
				'userfeedback-confirmNoTalk': 'Diskussionsseite',
			}
		};
		const userLang = mw.config.get( 'wgUserLanguage' );
		mw.messages.set( msg.en );
		mw.messages.set( msg[ userLang ] || {} );
	}

	$( document ).ready( function () {
		if (
			articleId === 0 ||                              // Page must not be a redlink
			action !== 'view' ||                            // Only show when reading article
			supportedNamespaces.indexOf( namespace ) === -1 || // Page must be in supported namespace
			$('#softredirect').length > 0                   || // Page must not be a soft redirect
			isRedirect                                         // Page must not be a hard redirect
		) {
			return;
		}

		setMessages();

		// Remove when syncing with gadget
		mw.loader.load('//www.mediawiki.org/w/index.php?title=MediaWiki:Gadget-userfeedback.css&action=raw&ctype=text/css', 'text/css');

		// Only download these dependencies when we're on API pages
		// where we want the form to be shown.
		//
		// The form is only shown if the current page is not a redlink,
		// being viewed by the user (rather than edited),
		// and the page is in a supported namespace.
		mw.loader.using( ['mediawiki.Title', 'ext.eventLogging', 'oojs-ui-core'] ).then( showGadgetUI );
	} );
}());