mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Echo
synced 2024-11-12 09:26:05 +00:00
f8a8d392d6
Support bundles being expandable to show their sub-notifications. Bug: T114356 Change-Id: I1507cae360f45cc87f2d60e966b4d047abfa202d
211 lines
5.6 KiB
JavaScript
211 lines
5.6 KiB
JavaScript
( function ( mw ) {
|
|
/**
|
|
* Notifications list widget.
|
|
* All of its items must be of the mw.echo.ui.NotificationItem type.
|
|
*
|
|
* @class
|
|
* @extends mw.echo.ui.SortedListWidget
|
|
*
|
|
* @constructor
|
|
* @param {mw.echo.Controller} controller Echo notifications controller
|
|
* @param {mw.echo.dm.ModelManager} manager Model manager
|
|
* @param {Object} [config] Configuration object
|
|
* marked as read when they are seen.
|
|
* @cfg {jQuery} [$overlay] A jQuery element functioning as an overlay
|
|
* for popups.
|
|
*/
|
|
mw.echo.ui.NotificationsListWidget = function MwEchoUiNotificationsListWidget( controller, manager, config ) {
|
|
config = config || {};
|
|
// Parent constructor
|
|
mw.echo.ui.NotificationsListWidget.parent.call( this, config );
|
|
|
|
// Initialize models
|
|
this.controller = controller;
|
|
this.manager = manager;
|
|
this.models = {};
|
|
|
|
// Properties
|
|
this.$overlay = config.$overlay || this.$element;
|
|
this.timestamp = config.timestamp || 0;
|
|
|
|
// Dummy 'loading' option widget
|
|
this.loadingOptionWidget = new mw.echo.ui.PlaceholderItemWidget();
|
|
|
|
// Define the sorting order
|
|
this.setSortingCallback( function ( a, b ) {
|
|
var diff;
|
|
|
|
if ( !a.isRead() && b.isRead() ) {
|
|
return -1; // Unread items are always above read items
|
|
} else if ( a.isRead() && !b.isRead() ) {
|
|
return 1;
|
|
} else if ( !a.isForeign() && b.isForeign() ) {
|
|
return -1;
|
|
} else if ( a.isForeign() && !b.isForeign() ) {
|
|
return 1;
|
|
} else {
|
|
// Reverse sorting
|
|
diff = Number( b.getTimestamp() ) - Number( a.getTimestamp() );
|
|
if ( diff !== 0 ) {
|
|
return diff;
|
|
}
|
|
|
|
// Fallback on IDs
|
|
return b.getId() - a.getId();
|
|
}
|
|
} );
|
|
|
|
this.resetLoadingOption();
|
|
|
|
this.manager.connect( this, {
|
|
update: 'resetDataFromModel',
|
|
remove: 'onModelManagerRemove'
|
|
} );
|
|
|
|
this.$element
|
|
.addClass( 'mw-echo-ui-notificationsListWidget' );
|
|
};
|
|
|
|
/* Initialization */
|
|
|
|
OO.inheritClass( mw.echo.ui.NotificationsListWidget, mw.echo.ui.SortedListWidget );
|
|
|
|
/* Methods */
|
|
|
|
mw.echo.ui.NotificationsListWidget.prototype.onModelManagerRemove = function ( modelName ) {
|
|
var i,
|
|
items = this.getItems();
|
|
|
|
// For the moment, this is only relevant for xwiki bundles.
|
|
// Local single items will not get their entire model removed, but
|
|
// local bundles may - when that happens, the condition below should
|
|
// also deal with local bundles and removing them specifically
|
|
if ( modelName === 'xwiki' ) {
|
|
for ( i = 0; i < items.length; i++ ) {
|
|
if ( items[ i ] instanceof mw.echo.ui.CrossWikiNotificationItemWidget ) {
|
|
this.removeItems( [ items[ i ] ] );
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Respond to model manager update event.
|
|
* This event means we are repopulating the entire list and the
|
|
* associated models within it.
|
|
*
|
|
* @param {Object} models Object of new models to populate the
|
|
* list.
|
|
*/
|
|
mw.echo.ui.NotificationsListWidget.prototype.resetDataFromModel = function ( models ) {
|
|
var i, modelId, model, subItems, subItem,
|
|
itemWidgets = [];
|
|
|
|
// Detach all attached models
|
|
for ( modelId in this.models ) {
|
|
this.detachModel( modelId );
|
|
}
|
|
|
|
// Attach and process new models
|
|
for ( modelId in models ) {
|
|
model = models[ modelId ];
|
|
this.attachModel( modelId, model );
|
|
|
|
// Build widgets based on the data in the model
|
|
if ( model.isGroup() ) {
|
|
if ( model.isForeign() ) {
|
|
// One Widget to Rule Them All
|
|
itemWidgets.push( new mw.echo.ui.CrossWikiNotificationItemWidget(
|
|
this.controller,
|
|
model,
|
|
{
|
|
$overlay: this.$overlay
|
|
}
|
|
) );
|
|
} else {
|
|
// local bundle
|
|
itemWidgets.push( new mw.echo.ui.BundleNotificationItemWidget(
|
|
this.controller,
|
|
model,
|
|
{
|
|
$overlay: this.$overlay,
|
|
bundle: false
|
|
}
|
|
) );
|
|
}
|
|
} else {
|
|
subItems = model.getItems();
|
|
// Separate widgets per item
|
|
for ( i = 0; i < subItems.length; i++ ) {
|
|
subItem = subItems[ i ];
|
|
itemWidgets.push( new mw.echo.ui.SingleNotificationItemWidget(
|
|
this.controller,
|
|
subItem,
|
|
{
|
|
$overlay: this.$overlay,
|
|
bundle: false
|
|
}
|
|
) );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Reset the current items and re-add the new item widgets
|
|
this.clearItems();
|
|
this.addItems( itemWidgets );
|
|
|
|
this.resetLoadingOption(
|
|
itemWidgets.length === 0 ?
|
|
mw.msg( 'echo-notification-placeholder' ) :
|
|
''
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Attach a model to the widget
|
|
*
|
|
* @param {string} modelId Symbolic name for the model
|
|
* @param {mw.echo.dm.SortedList} model Notifications list model
|
|
*/
|
|
mw.echo.ui.NotificationsListWidget.prototype.attachModel = function ( modelId, model ) {
|
|
this.models[ modelId ] = model;
|
|
};
|
|
|
|
/**
|
|
* Detach a model from the widget
|
|
*
|
|
* @param {string} modelId Notifications list model
|
|
*/
|
|
mw.echo.ui.NotificationsListWidget.prototype.detachModel = function ( modelId ) {
|
|
this.models[ modelId ].disconnect( this );
|
|
delete this.models[ modelId ];
|
|
};
|
|
|
|
/**
|
|
* Reset the loading 'dummy' option widget
|
|
*
|
|
* @param {string} [label] Label for the option widget
|
|
* @param {string} [link] Link for the option widget
|
|
*/
|
|
mw.echo.ui.NotificationsListWidget.prototype.resetLoadingOption = function ( label, link ) {
|
|
this.loadingOptionWidget.setLabel( label || '' );
|
|
this.loadingOptionWidget.setLink( link || '' );
|
|
if ( this.isEmpty() ) {
|
|
this.addItems( [ this.loadingOptionWidget ] );
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Reset the 'initiallyUnseen' state of all items
|
|
*/
|
|
mw.echo.ui.NotificationsListWidget.prototype.resetInitiallyUnseenItems = function () {
|
|
var i,
|
|
itemWidgets = this.getItems();
|
|
|
|
for ( i = 0; i < itemWidgets.length; i++ ) {
|
|
itemWidgets[ i ].resetInitiallyUnseen();
|
|
}
|
|
};
|
|
} )( mediaWiki );
|