mediawiki-extensions-Echo/modules/model/mw.echo.dm.ModelManager.js
Moriel Schottlender cf99479468 Display a message if there are no notifications in Special:Notifications
The zero results can either be because there are no notifications
at all for this user in the local wiki, or because there are no
results for the specific filter. Both messages are used for either
case.

Also, clean up the display of push/pop pending for the inbox widget
and hide the label in case the message count is 0 or 1 notifications
as it is unhelpful and irrelevant in these cases.

Bug: T136586
Bug: T136574
Bug: T129363
Change-Id: I1465f772bb9f5247df645d6612f951e5fd7d38cf
2016-05-31 23:13:48 +00:00

347 lines
8.7 KiB
JavaScript

( function ( mw ) {
/**
* A container that manages all models that are involved in creating
* the notification list. There are currently two types of models:
* * mw.echo.dm.SortedList - This currently includes the local model
* or any model that has individual messages.
* * mw.echo.dm.CrossWikiNotificationItem - This is a model for the
* cross wiki notification, which acts as an item but itself contains
* a list.
*
* All notification models that are managed by the manager must implement the
* following methods:
* * isGroup - This should be true for xwiki model and local bundles
* * hasUnseen - This should iterate in the model's items and check whether
* there are any unseen notifications within them.
* * getCount - Get a total count of available notifications currently in the model
*
* @class
* @mixins OO.EventEmitter
*
* @constructor
* @param {mw.echo.dm.UnreadNotificationCounter} counter Unread counter
* @param {Object} [config] Configuration object
* @cfg {string|string[]} [type="message"] The type of the notifications in
* the models that this manager handles.
*/
mw.echo.dm.ModelManager = function MwEchoDmModelManager( counter, config ) {
config = config || {};
// Mixin constructor
OO.EventEmitter.call( this );
this.counter = counter;
// Keep types in an array
this.types = config.type || 'message';
this.types = Array.isArray( this.types ) ?
config.type : [ this.types ];
this.notificationModels = {};
this.paginationModel = new mw.echo.dm.PaginationModel();
this.filtersModel = new mw.echo.dm.FiltersModel();
// Properties
this.seenTime = mw.config.get( 'wgEchoSeenTime' ) || {};
};
OO.initClass( mw.echo.dm.ModelManager );
OO.mixinClass( mw.echo.dm.ModelManager, OO.EventEmitter );
/* Events */
/**
* @event update
* @param {Object[]} Current available notifications
*
* The model has been rebuilt or has been updated
*/
/**
* @event remove
* @param {string} Removed model
*
* A model has been removed
*/
/**
* @event seen
*
* All local notifications are seen
*/
/**
* @event allTalkRead
*
* There are no more local talk page notifications
*/
/* Methods */
/**
* Get the notifications
*
* @return {Object} Object of notification models and their symbolic names
*/
mw.echo.dm.ModelManager.prototype.getAllNotificationModels = function () {
return this.notificationModels;
};
/**
* Set the models in the manager.
*
* @param {Object} modelDefinitions An object defining the models
* The format for the definition object is:
* {
* 'modelId': {mw.echo.dm.SortedList},
* ...
* }
*/
mw.echo.dm.ModelManager.prototype.setNotificationModels = function ( modelDefinitions ) {
var modelId,
localModel;
this.resetNotificationModels();
for ( modelId in modelDefinitions ) {
this.notificationModels[ modelId ] = modelDefinitions[ modelId ];
}
localModel = this.getNotificationModel( 'local' );
if ( localModel ) {
localModel.aggregate( { update: 'itemUpdate' } );
localModel.connect( this, { itemUpdate: 'checkLocalUnreadTalk' } );
}
this.emit( 'update', this.getAllNotificationModels() );
};
/**
* Go over all the notification models and return the total number of
* available notifications.
*
* @return {number} A count of all notifications
*/
mw.echo.dm.ModelManager.prototype.getAllNotificationCount = function () {
var model,
count = 0,
models = this.getAllNotificationModels();
for ( model in models ) {
count += models[ model ].getCount();
}
return count;
};
/**
* Get a notification model.
*
* @param {string} modelName Unique model name
* @return {mw.echo.dm.SortedList} Notifications model
*/
mw.echo.dm.ModelManager.prototype.getNotificationModel = function ( modelName ) {
return this.notificationModels[ modelName ];
};
/**
* Get the pagination model
*
* @return {mw.echo.dm.PaginationModel} Pagination model
*/
mw.echo.dm.ModelManager.prototype.getPaginationModel = function () {
return this.paginationModel;
};
/**
* Get the filters model
*
* @return {mw.echo.dm.FiltersModel} Filters model
*/
mw.echo.dm.ModelManager.prototype.getFiltersModel = function () {
return this.filtersModel;
};
/**
* Remove a model from the manager
*
* @param {string} modelName Symbolic name of the model
* @fires remove
*/
mw.echo.dm.ModelManager.prototype.removeNotificationModel = function ( modelName ) {
delete this.notificationModels[ modelName ];
this.emit( 'remove', modelName );
};
/**
* Reset all models
*
* @private
*/
mw.echo.dm.ModelManager.prototype.resetNotificationModels = function () {
var model;
for ( model in this.notificationModels ) {
if ( this.notificationModels.hasOwnProperty( model ) ) {
this.notificationModels[ model ].disconnect( this );
delete this.notificationModels[ model ];
}
}
};
/**
* Get the unread notification counter
*
* @return {mw.echo.dm.UnreadNotificationCounter} Unread notification counter
*/
mw.echo.dm.ModelManager.prototype.getUnreadCounter = function () {
return this.counter;
};
/**
* Check if the local model has any unread notifications.
*
* @return {boolean} Local model has unread notifications.
*/
mw.echo.dm.ModelManager.prototype.hasLocalUnread = function () {
var localModel = this.getNotificationModel( 'local' ),
isUnread = function ( item ) {
return !item.isRead();
};
return localModel ?
localModel.getItems().some( isUnread ) :
false;
};
/**
* Check whether there are talk notifications, and emit an event
* in case there aren't any left.
*
* @fires allTalkRead
*/
mw.echo.dm.ModelManager.prototype.checkLocalUnreadTalk = function () {
if ( !this.hasLocalUnreadTalk() ) {
this.emit( 'allTalkRead' );
}
};
/**
* Check if the local model has any unread talk page notifications.
*
* @return {boolean} Local model has unread talk page notifications.
*/
mw.echo.dm.ModelManager.prototype.hasLocalUnreadTalk = function () {
var localModel = this.getNotificationModel( 'local' ),
isUnreadUserTalk = function ( item ) {
return !item.isRead() && item.getCategory() === 'edit-user-talk';
};
return localModel ?
localModel.getItems().some( isUnreadUserTalk ) :
false;
};
/**
* Check if a model has any unseen notifications.
*
* @param {string} modelId Model ID
* @return {boolean} The given model has unseen notifications.
*/
mw.echo.dm.ModelManager.prototype.hasUnseenInModel = function ( modelId ) {
var model = this.getNotificationModel( modelId || 'local' );
return model && model.hasUnseen();
};
/**
* Check if there are unseen notifications in any of the models
*
* @return {boolean} Local model has unseen notifications.
*/
mw.echo.dm.ModelManager.prototype.hasUnseenInAnyModel = function () {
var model,
models = this.getAllNotificationModels();
for ( model in models ) {
if ( models[ model ].hasUnseen() ) {
return true;
}
}
return false;
};
/**
* Update the local version of seenTime object.
*
* @private
* @param {string|string[]} type Type of notifications; could be a single type
* or an array of types.
* @param {string} time Seen time
*/
mw.echo.dm.ModelManager.prototype.updateSeenTimeObject = function ( type, time ) {
var i,
types = Array.isArray( type ) ? type : [ type ];
for ( i = 0; i < types.length; i++ ) {
if ( this.seenTime.hasOwnProperty( types[ i ] ) ) {
this.seenTime[ types[ i ] ] = time;
}
}
};
/**
* Set items in the local model as seen
*
* @private
*/
mw.echo.dm.ModelManager.prototype.setLocalModelItemsSeen = function () {
var model = this.getNotificationModel( 'local' );
model.getItems().forEach( function ( item ) {
item.toggleSeen( true );
} );
this.emit( 'seen' );
};
/**
* Get the system seen time
*
* @param {string|string[]} [type] Notification types
* @return {string} Mediawiki seen timestamp in Mediawiki timestamp format
*/
mw.echo.dm.ModelManager.prototype.getSeenTime = function ( type ) {
var types = type || this.getTypes();
types = Array.isArray( types ) ? types : [ types ];
// If the type that is set is an array [ 'alert', 'message' ]
// then the seen time will be the same to both, and we can
// return the value of the arbitrary first one.
return this.seenTime[ types[ 0 ] ];
};
/**
* Get the array of model types
*
* @return {string[]} Model types
*/
mw.echo.dm.ModelManager.prototype.getTypes = function () {
return this.types;
};
/**
* Get the model types string; 'message', 'alert', or 'all'
*
* @return {string} Model types
*/
mw.echo.dm.ModelManager.prototype.getTypeString = function () {
return (
this.types.length === 1 ?
this.types[ 0 ] :
'all'
);
};
} )( mediaWiki, jQuery );