From d1debff4763b732402f141fa87bc8e410c080877 Mon Sep 17 00:00:00 2001 From: Marius Hoch Date: Wed, 3 Oct 2012 03:33:55 +0200 Subject: [PATCH] (bug 7851) Implement mediawiki.page.patrol.ajax Implement AJAX patrolling with the new mediawiki.page.patrol.ajax module, which makes use of the API via mediawiki.api. During the patrol process a spinner (created by jquery.spinner) shows up and after it a suitable message gets shown via mediawiki.notify. Depending on whether we had success or not the link then turns up again or the brackets completely disappear just like on a normal page view. On top of adding the module, I've changed the following: - Added the patrol token to the ResourceLoaderUserTokensModule. - Registered messages 'markedaspatrollednotify' and 'markedaspatrollederrornotify'. Change-Id: I472357566dda0ab572c20e2e4b87508b0f2f4c73 --- RELEASE-NOTES-1.21 | 1 + includes/Article.php | 4 ++ includes/diff/DifferenceEngine.php | 6 +- .../ResourceLoaderUserTokensModule.php | 3 +- languages/messages/MessagesEn.php | 2 + languages/messages/MessagesQqq.php | 2 + maintenance/language/messages.inc | 2 + resources/Resources.php | 17 +++++ .../mediawiki.page.patrol.ajax.js | 63 +++++++++++++++++++ 9 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 resources/mediawiki.page/mediawiki.page.patrol.ajax.js diff --git a/RELEASE-NOTES-1.21 b/RELEASE-NOTES-1.21 index 881f008436..31ce2e391b 100644 --- a/RELEASE-NOTES-1.21 +++ b/RELEASE-NOTES-1.21 @@ -35,6 +35,7 @@ production. tables that have a corresponding ORMTable class. * (bug 40876) Icon for PSD (Adobe Photoshop) file types. * (bug 40641) Implemented Special:Version/Credits with a list of contributors. +* (bug 7851) Implemented one-click AJAX patrolling. === Bug fixes in 1.21 === * (bug 40353) SpecialDoubleRedirect should support interwiki redirects. diff --git a/includes/Article.php b/includes/Article.php index 169dd03af3..1d2b0233b4 100644 --- a/includes/Article.php +++ b/includes/Article.php @@ -1044,6 +1044,8 @@ class Article extends Page { * If patrol is possible, output a patrol UI box. This is called from the * footer section of ordinary page views. If patrol is not possible or not * desired, does nothing. + * Side effect: When the patrol link is build, this method will call + * OutputPage::preventClickjacking() and load mediawiki.page.patrol.ajax. */ public function showPatrolFooter() { $request = $this->getContext()->getRequest(); @@ -1056,7 +1058,9 @@ class Article extends Page { } $token = $user->getEditToken( $rcid ); + $outputPage->preventClickjacking(); + $outputPage->addModules( 'mediawiki.page.patrol.ajax' ); $link = Linker::linkKnown( $this->getTitle(), diff --git a/includes/diff/DifferenceEngine.php b/includes/diff/DifferenceEngine.php index 0295f776d1..9afe69ea37 100644 --- a/includes/diff/DifferenceEngine.php +++ b/includes/diff/DifferenceEngine.php @@ -421,8 +421,8 @@ class DifferenceEngine extends ContextSource { /** * Get a link to mark the change as patrolled, or '' if there's either no * revision to patrol or the user is not allowed to to it. - * Side effect: this method will call OutputPage::preventClickjacking() - * when a link is builded. + * Side effect: When the patrol link is build, this method will call + * OutputPage::preventClickjacking() and load mediawiki.page.patrol.ajax. * * @return String */ @@ -463,6 +463,8 @@ class DifferenceEngine extends ContextSource { // Build the link if ( $rcid ) { $this->getOutput()->preventClickjacking(); + $this->getOutput()->addModules( 'mediawiki.page.patrol.ajax' ); + $token = $this->getUser()->getEditToken( $rcid ); $this->mMarkPatrolledLink = ' [' . Linker::linkKnown( $this->mNewPage, diff --git a/includes/resourceloader/ResourceLoaderUserTokensModule.php b/includes/resourceloader/ResourceLoaderUserTokensModule.php index 62d096a6b7..6d787c503a 100644 --- a/includes/resourceloader/ResourceLoaderUserTokensModule.php +++ b/includes/resourceloader/ResourceLoaderUserTokensModule.php @@ -43,7 +43,8 @@ class ResourceLoaderUserTokensModule extends ResourceLoaderModule { return array( 'editToken' => $wgUser->getEditToken(), - 'watchToken' => ApiQueryInfo::getWatchToken(null, null), + 'patrolToken' => ApiQueryRecentChanges::getPatrolToken( null, null ), + 'watchToken' => ApiQueryInfo::getWatchToken( null, null ), ); } diff --git a/languages/messages/MessagesEn.php b/languages/messages/MessagesEn.php index ec3187216a..5e33d62425 100644 --- a/languages/messages/MessagesEn.php +++ b/languages/messages/MessagesEn.php @@ -3810,6 +3810,8 @@ This is probably caused by a link to a blacklisted external site.', 'markedaspatrollederror' => 'Cannot mark as patrolled', 'markedaspatrollederrortext' => 'You need to specify a revision to mark as patrolled.', 'markedaspatrollederror-noautopatrol' => 'You are not allowed to mark your own changes as patrolled.', +'markedaspatrollednotify' => 'This change to $1 has been marked as patrolled.', +'markedaspatrollederrornotify' => 'Marking as patrolled failed.', # Patrol log 'patrol-log-page' => 'Patrol log', diff --git a/languages/messages/MessagesQqq.php b/languages/messages/MessagesQqq.php index 14e3886000..709f1dd8b4 100644 --- a/languages/messages/MessagesQqq.php +++ b/languages/messages/MessagesQqq.php @@ -3645,6 +3645,8 @@ Used as link text, linked to '{{int:Prefixindex}}' page ([[Special:PrefixIndex]] # Patrolling 'markedaspatrolledtext' => '{{Identical|Markedaspatrolled}}', +'markedaspatrollednotify' => 'Notification shown after a change has been marked as patrolled, $1 is the page title', +'markedaspatrollederrornotify' => 'Notification shown after marking a change as patrolled failed', # Patrol log 'patrol-log-page' => '{{doc-logpage}}', diff --git a/maintenance/language/messages.inc b/maintenance/language/messages.inc index eee979946e..d7a396f6d3 100644 --- a/maintenance/language/messages.inc +++ b/maintenance/language/messages.inc @@ -2738,6 +2738,8 @@ $wgMessageStructure = array( 'markedaspatrollederror', 'markedaspatrollederrortext', 'markedaspatrollederror-noautopatrol', + 'markedaspatrollednotify', + 'markedaspatrollederrornotify', ), 'patrol-log' => array( 'patrol-log-page', diff --git a/resources/Resources.php b/resources/Resources.php index afa9bb2c6e..80b9a76f68 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -810,6 +810,23 @@ return array( ), 'position' => 'top', ), + 'mediawiki.page.patrol.ajax' => array( + 'scripts' => 'resources/mediawiki.page/mediawiki.page.patrol.ajax.js', + 'dependencies' => array( + 'mediawiki.page.startup', + 'mediawiki.api', + 'mediawiki.util', + 'mediawiki.Title', + 'mediawiki.notify', + 'jquery.spinner', + 'user.tokens' + ), + 'messages' => array( + 'markedaspatrollednotify', + 'markedaspatrollederrornotify', + 'markedaspatrollederror-noautopatrol' + ), + ), 'mediawiki.page.watch.ajax' => array( 'scripts' => 'resources/mediawiki.page/mediawiki.page.watch.ajax.js', 'dependencies' => array( diff --git a/resources/mediawiki.page/mediawiki.page.patrol.ajax.js b/resources/mediawiki.page/mediawiki.page.patrol.ajax.js new file mode 100644 index 0000000000..d7a07d7157 --- /dev/null +++ b/resources/mediawiki.page/mediawiki.page.patrol.ajax.js @@ -0,0 +1,63 @@ +/** + * Animate patrol links to use asynchronous API requests to + * patrol pages, rather than navigating to a different URI. + * + * @since 1.21 + * @author Marius Hoch + */ +( function ( mw, $ ) { + if ( !mw.user.tokens.exists( 'patrolToken' ) ) { + // Current user has no patrol right, or an old cached version of user.tokens + // that didn't have patrolToken yet. + return; + } + $( document ).ready( function () { + var $patrolLinks = $( '.patrollink a' ); + $patrolLinks.on( 'click', function ( e ) { + var $spinner, href, rcid, apiRequest; + + // Hide the link and create a spinner to show it inside the brackets. + $spinner = $.createSpinner( { + size: 'small', + type: 'inline' + } ); + $( this ).hide().after( $spinner ); + + href = $( this ).attr( 'href' ); + rcid = mw.util.getParamValue( 'rcid', href ); + apiRequest = new mw.Api(); + + apiRequest.post( { + action: 'patrol', + token: mw.user.tokens.get( 'patrolToken' ), + rcid: rcid + } ) + .done( function ( data ) { + // Remove all patrollinks from the page (including any spinners inside). + $patrolLinks.closest( '.patrollink' ).remove(); + if ( data.patrol !== undefined ) { + // Success + var title = new mw.Title( data.patrol.title ); + mw.notify( mw.msg( 'markedaspatrollednotify', title.toText() ) ); + } else { + // This should never happen as errors should trigger fail + mw.notify( mw.msg( 'markedaspatrollederrornotify' ) ); + } + } ) + .fail( function ( error ) { + $spinner.remove(); + // Restore the patrol link. This allows the user to try again + // (or open it in a new window, bypassing this ajax module). + $patrolLinks.show(); + if ( error === 'noautopatrol' ) { + // Can't patrol own + mw.notify( mw.msg( 'markedaspatrollederror-noautopatrol' ) ); + } else { + mw.notify( mw.msg( 'markedaspatrollederrornotify' ) ); + } + } ); + + e.preventDefault(); + } ); + } ); +}( mediaWiki, jQuery ) ); -- 2.20.1