"rcfilters-liveupdates-button": "Live updates",
"rcfilters-liveupdates-button-title-on": "Turn off live updates",
"rcfilters-liveupdates-button-title-off": "Display new changes as they happen",
+ "rcfilters-watchlist-markSeen-button": "Mark all changes as seen",
"rcnotefrom": "Below {{PLURAL:$5|is the change|are the changes}} since <strong>$3, $4</strong> (up to <strong>$1</strong> shown).",
"rclistfromreset": "Reset date selection",
"rclistfrom": "Show new changes starting from $2, $3",
"rcfilters-liveupdates-button": "Label for the button to enable or disable live updates on [[Special:RecentChanges]]",
"rcfilters-liveupdates-button-title-on": "Title for the button to enable or disable live updates on [[Special:RecentChanges]] when the feature is ON.",
"rcfilters-liveupdates-button-title-off": "Title for the button to enable or disable live updates on [[Special:RecentChanges]] when the feature is OFF.",
+ "rcfilters-watchlist-markSeen-button": "Label for the button to mark all changes as seen on [[Special:Watchlist]] when using the structured filters interface.",
"rcnotefrom": "This message is displayed at [[Special:RecentChanges]] when viewing recentchanges from some specific time.\n\nThe corresponding message is {{msg-mw|Rclistfrom}}.\n\nParameters:\n* $1 - the maximum number of changes that are displayed\n* $2 - (Optional) a date and time\n* $3 - a date\n* $4 - a time\n* $5 - Number of changes are displayed, for use with PLURAL",
"rclistfromreset": "Used on [[Special:RecentChanges]] to reset a selection of a certain date range.",
"rclistfrom": "Used on [[Special:RecentChanges]]. Parameters:\n* $1 - (Currently not use) date and time. The date and the time adds to the rclistfrom description.\n* $2 - time. The time adds to the rclistfrom link description (with split of date and time).\n* $3 - date. The date adds to the rclistfrom link description (with split of date and time).\n\nThe corresponding message is {{msg-mw|Rcnotefrom}}.",
'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterItemHighlightButton.js',
'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.HighlightColorPickerWidget.js',
'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.LiveUpdateButtonWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MarkSeenButtonWidget.js',
'resources/src/mediawiki.rcfilters/mw.rcfilters.HighlightColors.js',
'resources/src/mediawiki.rcfilters/mw.rcfilters.init.js',
],
'rcfilters-liveupdates-button',
'rcfilters-liveupdates-button-title-on',
'rcfilters-liveupdates-button-title-off',
+ 'rcfilters-watchlist-markSeen-button',
'rcfilters-other-review-tools',
'blanknamespace',
'namespaces',
this.newChangesExist = false;
this.nextFrom = null;
this.liveUpdate = false;
+ this.unseenWatchedChanges = false;
};
/* Initialization */
if ( mw.rcfilters.featureFlags.liveUpdate ) {
this.extractNextFrom( $fieldset );
}
+ this.checkForUnseenWatchedChanges( changesListContent );
this.emit( 'update', changesListContent, $fieldset, isInitialDOM, separateOldAndNew ? from : null );
};
return this.liveUpdate;
};
+ /**
+ * Check if some of the given changes watched and unseen
+ *
+ * @param {jQuery|string} changeslistContent
+ */
+ mw.rcfilters.dm.ChangesListViewModel.prototype.checkForUnseenWatchedChanges = function ( changeslistContent ) {
+ this.unseenWatchedChanges = changeslistContent !== 'NO_RESULTS' &&
+ changeslistContent.find( '.mw-changeslist-line-watched' ).length > 0;
+ };
+
+ /**
+ * @return {boolean} Whether some of the current changes are watched and unseen
+ */
+ mw.rcfilters.dm.ChangesListViewModel.prototype.hasUnseenWatchedChanges = function () {
+ return this.unseenWatchedChanges;
+ };
}( mediaWiki ) );
* Update the list of changes and notify the model
*
* @param {Object} [params] Extra parameters to add to the API call
- * @param {string} [updateMode='filterChange'] One of 'filterChange', 'liveUpdate', 'showNewChanges'
+ * @param {string} [updateMode='filterChange'] One of 'filterChange', 'liveUpdate', 'showNewChanges', 'markSeen'
* @return {jQuery.Promise} Promise that is resolved when the update is complete
*/
mw.rcfilters.Controller.prototype.updateChangesList = function ( params, updateMode ) {
this.prevLoggedItems = filters;
}
};
+
+ /**
+ * Mark all changes as seen on Watchlist
+ */
+ mw.rcfilters.Controller.prototype.markAllChangesAsSeen = function () {
+ var api = new mw.Api();
+ api.postWithToken( 'csrf', {
+ formatversion: 2,
+ action: 'setnotificationtimestamp',
+ entirewatchlist: true
+ } ).then( function () {
+ this.updateChangesList( null, 'markSeen' );
+ }.bind( this ) );
+ };
}( mediaWiki, jQuery ) );
$overlay = $( '<div>' )
.addClass( 'mw-rcfilters-ui-overlay' ),
filtersWidget = new mw.rcfilters.ui.FilterWrapperWidget(
- controller, filtersModel, savedQueriesModel, changesListModel, { $overlay: $overlay } );
+ controller, filtersModel, savedQueriesModel, changesListModel, { $overlay: $overlay } ),
+ markSeenButton,
+ currentPage = mw.config.get( 'wgCanonicalNamespace' ) +
+ ':' +
+ mw.config.get( 'wgCanonicalSpecialPageName' );
// TODO: The changesListWrapperWidget should be able to initialize
// after the model is ready.
controller.replaceUrl();
- toplinksTitle = new OO.ui.ButtonWidget( {
- framed: false,
- indicator: topLinksCookieValue === 'collapsed' ? 'down' : 'up',
- flags: [ 'progressive' ],
- label: $( '<span>' ).append( mw.message( 'rcfilters-other-review-tools' ).parse() ).contents()
- } );
- $( '.mw-recentchanges-toplinks-title' ).replaceWith( toplinksTitle.$element );
- // Move the top links to a designated area so it's near the
- // 'saved filters' button and make it collapsible
- $( '.mw-recentchanges-toplinks' )
- .addClass( 'mw-rcfilters-ui-ready' )
- .makeCollapsible( {
- collapsed: topLinksCookieValue === 'collapsed',
- $customTogglers: toplinksTitle.$element
- } )
- .on( 'beforeExpand.mw-collapsible', function () {
- mw.cookie.set( topLinksCookieName, 'expanded' );
- toplinksTitle.setIndicator( 'up' );
- } )
- .on( 'beforeCollapse.mw-collapsible', function () {
- mw.cookie.set( topLinksCookieName, 'collapsed' );
- toplinksTitle.setIndicator( 'down' );
- } )
- .appendTo( '.mw-rcfilters-ui-filterWrapperWidget-top-placeholder' );
+ if ( currentPage === 'Special:Recentchanges' ) {
+ toplinksTitle = new OO.ui.ButtonWidget( {
+ framed: false,
+ indicator: topLinksCookieValue === 'collapsed' ? 'down' : 'up',
+ flags: [ 'progressive' ],
+ label: $( '<span>' ).append( mw.message( 'rcfilters-other-review-tools' ).parse() ).contents()
+ } );
+ $( '.mw-recentchanges-toplinks-title' ).replaceWith( toplinksTitle.$element );
+ // Move the top links to a designated area so it's near the
+ // 'saved filters' button and make it collapsible
+ $( '.mw-recentchanges-toplinks' )
+ .addClass( 'mw-rcfilters-ui-ready' )
+ .makeCollapsible( {
+ collapsed: topLinksCookieValue === 'collapsed',
+ $customTogglers: toplinksTitle.$element
+ } )
+ .on( 'beforeExpand.mw-collapsible', function () {
+ mw.cookie.set( topLinksCookieName, 'expanded' );
+ toplinksTitle.setIndicator( 'up' );
+ } )
+ .on( 'beforeCollapse.mw-collapsible', function () {
+ mw.cookie.set( topLinksCookieName, 'collapsed' );
+ toplinksTitle.setIndicator( 'down' );
+ } )
+ .appendTo( '.mw-rcfilters-ui-filterWrapperWidget-top-placeholder' );
+ } // end Special:RC
+
+ if ( currentPage === 'Special:Watchlist' ) {
+ markSeenButton = new mw.rcfilters.ui.MarkSeenButtonWidget( controller, changesListModel );
+ $( 'form#mw-watchlist-resetbutton' ).detach();
+ filtersWidget.prependToTopRow( markSeenButton );
+ } // end Special:WL
}
};
mw.rcfilters.ui.FilterWrapperWidget = function MwRcfiltersUiFilterWrapperWidget(
controller, model, savedQueriesModel, changesListModel, config
) {
- var $top, $topRow, $bottom;
+ var $top, $bottom;
config = config || {};
// Parent
);
// Initialize
- $topRow = $( '<div>' )
+ this.$topRow = $( '<div>' )
.addClass( 'mw-rcfilters-ui-row' )
.append(
$( '<div>' )
$top = $( '<div>' )
.addClass( 'mw-rcfilters-ui-filterWrapperWidget-top' )
.addClass( 'mw-rcfilters-ui-table' )
- .append( $topRow );
+ .append( this.$topRow );
$bottom = $( '<div>' )
.addClass( 'mw-rcfilters-ui-filterWrapperWidget-bottom' )
{ $overlay: this.$overlay }
);
- $topRow.append(
+ this.$topRow.append(
$( '<div>' )
.addClass( 'mw-rcfilters-ui-cell' )
.addClass( 'mw-rcfilters-ui-filterWrapperWidget-top-savedLinks' )
OO.inheritClass( mw.rcfilters.ui.FilterWrapperWidget, OO.ui.Widget );
OO.mixinClass( mw.rcfilters.ui.FilterWrapperWidget, OO.ui.mixin.PendingElement );
+
+ /* Methods */
+
+ /**
+ * Add a widget at the beginning of the top row
+ *
+ * @param {OO.ui.Widget} widget Any widget
+ */
+ mw.rcfilters.ui.FilterWrapperWidget.prototype.prependToTopRow = function ( widget ) {
+ this.$topRow.prepend(
+ widget.$element
+ .addClass( 'mw-rcfilters-ui-cell' )
+ );
+ };
+
}( mediaWiki ) );
--- /dev/null
+( function ( mw ) {
+ /**
+ * Button for marking all changes as seen on the Watchlist
+ *
+ * @extends OO.ui.ButtonWidget
+ *
+ * @constructor
+ * @param {mw.rcfilters.Controller} controller
+ * @param {mw.rcfilters.dm.ChangesListViewModel} model Changes list view model
+ * @param {Object} [config] Configuration object
+ */
+ mw.rcfilters.ui.MarkSeenButtonWidget = function MwRcfiltersUiMarkSeenButtonWidget( controller, model, config ) {
+ config = config || {};
+
+ // Parent
+ mw.rcfilters.ui.MarkSeenButtonWidget.parent.call( this, $.extend( {
+ label: mw.message( 'rcfilters-watchlist-markSeen-button' ).text(),
+ icon: 'doubleCheck'
+ }, config ) );
+
+ this.controller = controller;
+ this.model = model;
+
+ // Events
+ this.connect( this, { click: 'onClick' } );
+ this.model.connect( this, { update: 'onModelUpdate' } );
+
+ this.$element.addClass( 'mw-rcfilters-ui-markSeenButtonWidget' );
+
+ this.onModelUpdate();
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.rcfilters.ui.MarkSeenButtonWidget, OO.ui.ButtonWidget );
+
+ /* Methods */
+
+ /**
+ * Respond to the button being clicked
+ */
+ mw.rcfilters.ui.MarkSeenButtonWidget.prototype.onClick = function () {
+ this.controller.markAllChangesAsSeen();
+ // assume there's no more unseen changes until the next model update
+ this.setDisabled( true );
+ };
+
+ /**
+ * Respond to the model being updated with new changes
+ */
+ mw.rcfilters.ui.MarkSeenButtonWidget.prototype.onModelUpdate = function () {
+ this.setDisabled( !this.model.hasUnseenWatchedChanges() );
+ };
+
+}( mediaWiki ) );