mediawiki-extensions-Echo/modules/ui/mw.echo.ui.NotificationsInboxWidget.js
Moriel Schottlender 545d4e67ae Add a mark-all-read button and a settings menu to Special:Notifications
Add a global-wiki 'mark all as read' to the Special:Notifications page.
The 'mark all as read' will makr all notifications in the given
wiki. The context of the wiki changes when filters are chosen,
and so the message of the button changes as well.

Bug: T115528
Change-Id: Ibd9dcdf7072d6cbc1a268c18e558e6d0df28f929
2016-07-20 17:25:38 -07:00

305 lines
9.2 KiB
JavaScript

( function ( $, mw ) {
/**
* An inbox-type widget that encompases a dated notifications list with pagination
*
* @class
* @extends OO.ui.Widget
* @mixins OO.ui.mixin.PendingElement
*
* @constructor
* @param {mw.echo.Controller} controller Echo controller
* @param {mw.echo.dm.ModelManager} manager Model manager
* @param {Object} [config] Configuration object
* @cfg {number} [limit=25] Limit the number of notifications per page
* @cfg {jQuery} [$overlay] An overlay for the popup menus
*/
mw.echo.ui.NotificationsInboxWidget = function MwEchoUiNotificationsInboxWidget( controller, manager, config ) {
var $main, $sidebar;
config = config || {};
// Parent
mw.echo.ui.NotificationsInboxWidget.parent.call( this, config );
// Mixin constructors
OO.ui.mixin.PendingElement.call( this, config );
this.controller = controller;
this.manager = manager;
this.$overlay = config.$overlay || this.$element;
this.limit = config.limit || 25;
// A notice or error message widget
this.noticeMessageWidget = new OO.ui.LabelWidget( {
classes: [ 'mw-echo-ui-notificationsInboxWidget-notice' ]
} );
// Notifications list
this.datedListWidget = new mw.echo.ui.DatedNotificationsWidget(
this.controller,
this.manager,
{
$overlay: this.$overlay
}
);
this.setPendingElement( this.datedListWidget.$element );
// Pagination
this.topPaginationWidget = new mw.echo.ui.PaginationWidget(
this.manager.getPaginationModel(),
{
itemsPerPage: this.limit
}
);
this.bottomPaginationWidget = new mw.echo.ui.PaginationWidget(
this.manager.getPaginationModel(),
{
itemsPerPage: this.limit
}
);
// Settings menu
this.settingsMenu = new mw.echo.ui.SpecialHelpMenuWidget(
this.manager,
{
framed: true,
helpLink: config.helpLink,
prefLink: config.prefLink
}
);
// Filter by read state
this.readStateSelectWidget = new mw.echo.ui.ReadStateButtonSelectWidget();
// Sidebar filters
this.xwikiUnreadWidget = new mw.echo.ui.CrossWikiUnreadFilterWidget(
this.controller,
this.manager.getFiltersModel()
);
// Events
this.readStateSelectWidget.connect( this, { filter: 'onReadStateFilter' } );
this.xwikiUnreadWidget.connect( this, { filter: 'onSourcePageFilter' } );
this.manager.connect( this, {
modelItemUpdate: 'updatePaginationLabels',
localCountChange: 'updatePaginationLabels'
} );
this.manager.getFiltersModel().connect( this, { update: 'updateReadStateSelectWidget' } );
this.manager.getPaginationModel().connect( this, { update: 'updatePaginationLabels' } );
this.topPaginationWidget.connect( this, { change: 'populateNotifications' } );
this.bottomPaginationWidget.connect( this, { change: 'populateNotifications' } );
this.settingsMenu.connect( this, { markAllRead: 'onSettingsMarkAllRead' } );
this.topPaginationWidget.setDisabled( true );
this.bottomPaginationWidget.setDisabled( true );
// Initialization
$sidebar = $( '<div>' )
.addClass( 'mw-echo-ui-notificationsInboxWidget-sidebar' )
.append( this.xwikiUnreadWidget.$element );
$main = $( '<div>' )
.addClass( 'mw-echo-ui-notificationsInboxWidget-main' )
.append(
$( '<div>' )
.addClass( 'mw-echo-ui-notificationsInboxWidget-main-toolbar-top' )
.append(
$( '<div>' )
.addClass( 'mw-echo-ui-notificationsInboxWidget-row' )
.append(
$( '<div>' )
.addClass( 'mw-echo-ui-notificationsInboxWidget-main-toolbar-readState' )
.addClass( 'mw-echo-ui-notificationsInboxWidget-cell' )
.append( this.readStateSelectWidget.$element ),
$( '<div>' )
.addClass( 'mw-echo-ui-notificationsInboxWidget-cell-placeholder' ),
$( '<div>' )
.addClass( 'mw-echo-ui-notificationsInboxWidget-main-toolbar-pagination' )
.addClass( 'mw-echo-ui-notificationsInboxWidget-cell' )
.append( this.topPaginationWidget.$element ),
$( '<div>' )
.addClass( 'mw-echo-ui-notificationsInboxWidget-main-toolbar-settings' )
.addClass( 'mw-echo-ui-notificationsInboxWidget-cell' )
.append( this.settingsMenu.$element )
)
),
this.noticeMessageWidget.$element,
this.datedListWidget.$element,
$( '<div>' )
.addClass( 'mw-echo-ui-notificationsInboxWidget-main-toolbar-bottom' )
.append(
$( '<div>' )
.addClass( 'mw-echo-ui-notificationsInboxWidget-row' )
.append(
$( '<div>' )
.addClass( 'mw-echo-ui-notificationsInboxWidget-cell' )
.append(
this.bottomPaginationWidget.$element
)
)
)
);
this.$element
.addClass( 'mw-echo-ui-notificationsInboxWidget' )
.append(
$( '<div>' )
.addClass( 'mw-echo-ui-notificationsInboxWidget-row' )
.append(
$sidebar
.addClass( 'mw-echo-ui-notificationsInboxWidget-cell' ),
$main
.addClass( 'mw-echo-ui-notificationsInboxWidget-cell' )
)
);
this.updateReadStateSelectWidget();
this.xwikiUnreadWidget.populateSources();
this.populateNotifications();
};
/* Initialization */
OO.inheritClass( mw.echo.ui.NotificationsInboxWidget, OO.ui.Widget );
OO.mixinClass( mw.echo.ui.NotificationsInboxWidget, OO.ui.mixin.PendingElement );
/* Methods */
/**
* Respond to filters update
*/
mw.echo.ui.NotificationsInboxWidget.prototype.updateReadStateSelectWidget = function () {
this.readStateSelectWidget
.getItemFromData( this.manager.getFiltersModel().getReadState() )
.setSelected( true );
};
/**
* Update pagination messages
*/
mw.echo.ui.NotificationsInboxWidget.prototype.updatePaginationLabels = function () {
this.resetMessageLabel();
// Update the pagination label
this.topPaginationWidget.updateLabel();
this.bottomPaginationWidget.updateLabel();
};
/**
* Respond to mark all read for selected wiki
*/
mw.echo.ui.NotificationsInboxWidget.prototype.onSettingsMarkAllRead = function () {
this.pushPending();
this.controller.markAllRead()
.always( this.popPending.bind( this ) );
};
/**
* Respond to unread page filter
*
* @param {string} source Source symbolic name
* @param {string} page Page name
*/
mw.echo.ui.NotificationsInboxWidget.prototype.onSourcePageFilter = function ( source, page ) {
this.controller.setFilter( 'sourcePage', source, page );
this.populateNotifications();
};
/**
* Respond to read state filter event
*
* @param {string} readState Read state 'all', 'read' or 'unread'
*/
mw.echo.ui.NotificationsInboxWidget.prototype.onReadStateFilter = function ( readState ) {
this.controller.setFilter( 'readState', readState );
this.populateNotifications();
};
/**
* Populate the notifications list
*
* @param {string} [direction] Direction to fetch from. 'prev' for previous page
* or 'next' for the next page. If not given, the first page of results will be fetched.
* @return {jQuery.Promise} A promise that is resolved when the results
* have been fetched.
*/
mw.echo.ui.NotificationsInboxWidget.prototype.populateNotifications = function ( direction ) {
var fetchPromise,
widget = this;
if ( direction === 'prev' ) {
fetchPromise = this.controller.fetchPrevPageByDate();
} else if ( direction === 'next' ) {
fetchPromise = this.controller.fetchNextPageByDate();
} else {
fetchPromise = this.controller.fetchFirstPageByDate();
}
this.pushPending();
return fetchPromise
.then(
// Success
function () {
widget.popPending();
// Update seen time
widget.controller.updateSeenTimeForCurrentSource();
},
// Failure
this.popPending.bind( this )
);
};
/**
* Extend the pushPending method to disable UI elements
*/
mw.echo.ui.NotificationsInboxWidget.prototype.pushPending = function () {
this.noticeMessageWidget.toggle( false );
this.topPaginationWidget.setDisabled( true );
this.bottomPaginationWidget.setDisabled( true );
// Mixin method
OO.ui.mixin.PendingElement.prototype.pushPending.call( this );
};
/**
* Extend the popPending method to enable UI elements
*/
mw.echo.ui.NotificationsInboxWidget.prototype.popPending = function () {
this.resetMessageLabel();
this.topPaginationWidget.setDisabled( false );
this.bottomPaginationWidget.setDisabled( false );
// Mixin method
OO.ui.mixin.PendingElement.prototype.popPending.call( this );
};
/**
* Reset the the text of the error message that displays in place of the list
* in case the list is empty.
*/
mw.echo.ui.NotificationsInboxWidget.prototype.resetMessageLabel = function () {
var label,
count = this.manager.getPaginationModel().getCurrentPageItemCount();
if ( count === 0 ) {
label = this.manager.getFiltersModel().getReadState() === 'all' ?
mw.msg( 'echo-notification-placeholder' ) :
mw.msg( 'echo-notification-placeholder-filters' );
this.noticeMessageWidget.setLabel( label );
}
this.displayMessage( count === 0 );
};
/**
* Display the error/notice message instead of the notifications list or vise versa.
*
* @private
* @param {boolean} displayMessage Display error message
*/
mw.echo.ui.NotificationsInboxWidget.prototype.displayMessage = function ( displayMessage ) {
this.noticeMessageWidget.toggle( displayMessage );
this.datedListWidget.toggle( !displayMessage );
};
} )( jQuery, mediaWiki );