2015-12-21 21:47:09 +00:00
|
|
|
( function ( mw, $ ) {
|
2015-08-13 00:54:16 +00:00
|
|
|
/**
|
|
|
|
* Notification widget for echo popup.
|
|
|
|
*
|
|
|
|
* @class
|
|
|
|
* @extends OO.ui.Widget
|
|
|
|
*
|
|
|
|
* @constructor
|
|
|
|
* @param {mw.echo.dm.NotificationsModel} model Notifications view model
|
|
|
|
* @param {Object} [config] Configuration object
|
|
|
|
* @cfg {boolean} [markReadWhenSeen=false] State whether the notifications are all
|
|
|
|
* marked as read when they are seen.
|
2015-11-21 01:54:12 +00:00
|
|
|
* @cfg {jQuery} [$overlay] A jQuery element functioning as an overlay
|
|
|
|
* for popups.
|
2015-10-16 23:18:25 +00:00
|
|
|
* @cfg {boolean} [bundle=false] This notification is part of a bundled notification
|
|
|
|
* group. This affects the rendering of the items.
|
2015-08-13 00:54:16 +00:00
|
|
|
*/
|
|
|
|
mw.echo.ui.NotificationsWidget = function MwEchoUiNotificationsWidget( model, config ) {
|
|
|
|
config = config || {};
|
|
|
|
|
2015-10-16 23:18:25 +00:00
|
|
|
// Parent constructor
|
|
|
|
mw.echo.ui.NotificationsWidget.parent.call( this, config );
|
|
|
|
|
2015-08-13 00:54:16 +00:00
|
|
|
this.model = model;
|
|
|
|
|
|
|
|
this.markReadWhenSeen = !!config.markReadWhenSeen;
|
2015-10-16 23:18:25 +00:00
|
|
|
this.bundle = !!config.bundle;
|
|
|
|
this.$overlay = config.$overlay || this.$element;
|
2015-08-13 00:54:16 +00:00
|
|
|
|
|
|
|
// Dummy 'loading' option widget
|
2015-11-12 19:37:56 +00:00
|
|
|
this.loadingOptionWidget = new mw.echo.ui.PlaceholderItemWidget();
|
2015-08-13 00:54:16 +00:00
|
|
|
this.addItems( [ this.loadingOptionWidget ] );
|
|
|
|
|
|
|
|
// Events
|
|
|
|
this.model.connect( this, {
|
|
|
|
add: 'onModelNotificationAdd',
|
|
|
|
remove: 'onModelNotificationRemove',
|
2015-10-16 23:18:25 +00:00
|
|
|
clear: 'onModelNotificationClear',
|
|
|
|
done: 'onModelNotificationDone'
|
2015-08-13 00:54:16 +00:00
|
|
|
} );
|
|
|
|
|
|
|
|
this.$element
|
2015-10-16 23:18:25 +00:00
|
|
|
.addClass( 'mw-echo-ui-notificationsWidget' )
|
|
|
|
.toggleClass( 'mw-echo-ui-notificationsWidget-bundle', this.bundle );
|
2015-08-13 00:54:16 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Initialization */
|
|
|
|
|
|
|
|
OO.inheritClass( mw.echo.ui.NotificationsWidget, OO.ui.SelectWidget );
|
|
|
|
|
|
|
|
/* Methods */
|
|
|
|
|
2015-10-16 23:18:25 +00:00
|
|
|
/**
|
|
|
|
* Handle done event from the model
|
|
|
|
*
|
|
|
|
* @param {boolean} isSuccess The operation was successful
|
|
|
|
* @param {Object} result Result object from the API
|
2015-12-21 21:47:09 +00:00
|
|
|
* @param {string} result.errCode The API error code
|
|
|
|
* @param {string} result.errInfo The API error info string
|
2015-10-16 23:18:25 +00:00
|
|
|
*/
|
|
|
|
mw.echo.ui.NotificationsWidget.prototype.onModelNotificationDone = function ( isSuccess, result ) {
|
2015-12-21 21:47:09 +00:00
|
|
|
var loginPageTitle = mw.Title.newFromText( 'Special:UserLogin' );
|
2015-10-16 23:18:25 +00:00
|
|
|
if ( this.model.isEmpty() ) {
|
2015-12-21 21:47:09 +00:00
|
|
|
if ( isSuccess ) {
|
|
|
|
this.resetLoadingOption( mw.msg( 'echo-notification-placeholder' ) );
|
|
|
|
} else {
|
|
|
|
// If failure, check if the failure is due to login
|
2016-02-18 22:36:58 +00:00
|
|
|
// so we can display a more comprehensive error
|
2015-12-21 21:47:09 +00:00
|
|
|
// message in that case
|
|
|
|
if ( result.errCode === 'notlogin-required' ) {
|
|
|
|
// Login error
|
|
|
|
this.resetLoadingOption(
|
|
|
|
// This message has a link inside it, so it must be
|
|
|
|
// given to the OO.ui.LabelWidget as a jQuery object, otherwise
|
|
|
|
// the LabelWidget parses it as a raw string.
|
|
|
|
$( '<span>' ).text( mw.message( 'echo-notification-popup-loginrequired' ) ),
|
|
|
|
// Set the option link to the login page
|
|
|
|
loginPageTitle.getUrl()
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
// General error
|
|
|
|
this.resetLoadingOption( mw.msg( 'echo-api-failure', result.errInfo ) );
|
|
|
|
}
|
|
|
|
}
|
2015-10-16 23:18:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( isSuccess ) {
|
|
|
|
// Log impressions
|
2016-03-02 07:29:40 +00:00
|
|
|
mw.echo.logger.logNotificationImpressions(
|
|
|
|
undefined, // type: we don't know
|
|
|
|
result.ids,
|
|
|
|
mw.echo.Logger.static.context.popup,
|
|
|
|
this.getModel().getSource()
|
|
|
|
);
|
2015-10-16 23:18:25 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-08-13 00:54:16 +00:00
|
|
|
/**
|
|
|
|
* Respond to model add event
|
|
|
|
*
|
2015-10-28 20:47:54 +00:00
|
|
|
* @param {mw.echo.dm.NotificationItem} Added notification item
|
|
|
|
* @param {number} index Index to add the item
|
2015-08-13 00:54:16 +00:00
|
|
|
*/
|
2015-10-28 20:47:54 +00:00
|
|
|
mw.echo.ui.NotificationsWidget.prototype.onModelNotificationAdd = function ( notificationItem, index ) {
|
2015-10-16 23:18:25 +00:00
|
|
|
var widget;
|
|
|
|
|
|
|
|
if ( notificationItem instanceof mw.echo.dm.NotificationGroupItem ) {
|
|
|
|
widget = new mw.echo.ui.NotificationGroupItemWidget(
|
|
|
|
notificationItem,
|
|
|
|
{
|
|
|
|
bundle: this.bundle,
|
|
|
|
$overlay: this.$overlay
|
|
|
|
}
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
widget = new mw.echo.ui.NotificationItemWidget(
|
2015-10-28 20:47:54 +00:00
|
|
|
notificationItem,
|
2015-08-13 00:54:16 +00:00
|
|
|
{
|
2015-11-21 01:54:12 +00:00
|
|
|
$overlay: this.$overlay,
|
2015-10-16 23:18:25 +00:00
|
|
|
bundle: this.bundle,
|
2015-08-13 00:54:16 +00:00
|
|
|
markReadWhenSeen: this.markReadWhenSeen
|
|
|
|
}
|
|
|
|
);
|
2015-10-16 23:18:25 +00:00
|
|
|
}
|
2015-08-13 00:54:16 +00:00
|
|
|
|
|
|
|
// Fire hook for gadgets to update the option list
|
2015-10-28 20:47:54 +00:00
|
|
|
mw.hook( 'ext.echo.overlay.beforeShowingOverlay' ).fire( widget.$element );
|
2015-08-13 00:54:16 +00:00
|
|
|
|
|
|
|
// Remove dummy option
|
|
|
|
this.removeItems( [ this.loadingOptionWidget ] );
|
|
|
|
|
2015-10-28 20:47:54 +00:00
|
|
|
this.addItems( [ widget ], index );
|
2015-08-13 00:54:16 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Respond to model add event
|
|
|
|
*
|
|
|
|
* @param {mw.echo.dm.NotificationItem[]} Removed notification items
|
|
|
|
*/
|
|
|
|
mw.echo.ui.NotificationsWidget.prototype.onModelNotificationClear = function () {
|
|
|
|
var i, len,
|
|
|
|
items = this.getItems();
|
|
|
|
|
|
|
|
// Destroy all the widgets and their events
|
|
|
|
for ( i = 0, len = items.length; i < len; i++ ) {
|
2015-10-01 13:48:52 +00:00
|
|
|
if ( typeof items[ i ].destroy === 'function' ) {
|
2015-08-13 00:54:16 +00:00
|
|
|
// Destroy if destroyable
|
2015-10-01 13:48:52 +00:00
|
|
|
items[ i ].destroy();
|
2015-08-13 00:54:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.clearItems();
|
|
|
|
|
|
|
|
// Add dummy option
|
2015-09-16 20:42:17 +00:00
|
|
|
this.resetLoadingOption();
|
2015-08-13 00:54:16 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Respond to model add event
|
|
|
|
*
|
2015-10-28 20:47:54 +00:00
|
|
|
* @param {mw.echo.dm.NotificationItem} notificationItem Removed notification items
|
2015-08-13 00:54:16 +00:00
|
|
|
*/
|
2015-10-28 20:47:54 +00:00
|
|
|
mw.echo.ui.NotificationsWidget.prototype.onModelNotificationRemove = function ( notificationItem ) {
|
|
|
|
var widget, items;
|
|
|
|
|
|
|
|
widget = this.getItemFromData( notificationItem.getId() );
|
|
|
|
if ( widget && typeof widget.destroy === 'function' ) {
|
|
|
|
// Destroy all widgets that can be destroyed
|
|
|
|
widget.destroy();
|
2015-08-13 00:54:16 +00:00
|
|
|
}
|
2015-10-28 20:47:54 +00:00
|
|
|
this.removeItems( [ widget ] );
|
2015-08-13 00:54:16 +00:00
|
|
|
|
|
|
|
items = this.getItems();
|
|
|
|
if ( !items.length ) {
|
2015-09-16 20:42:17 +00:00
|
|
|
this.resetLoadingOption();
|
2015-08-13 00:54:16 +00:00
|
|
|
}
|
|
|
|
};
|
2015-09-16 20:42:17 +00:00
|
|
|
|
2015-09-23 00:15:28 +00:00
|
|
|
/**
|
|
|
|
* Go over the items and remove all items with 'initiallyUnseen' class on them.
|
|
|
|
* That class is given to the widgets so that the animation works. When we refresh
|
|
|
|
* the notifications, they should no longer be animated, allowing any new notifications
|
|
|
|
* that were fetched to be set as unseen.
|
|
|
|
*/
|
|
|
|
mw.echo.ui.NotificationsWidget.prototype.resetNotificationItems = function () {
|
|
|
|
var i, len,
|
|
|
|
items = this.getItems();
|
|
|
|
|
|
|
|
for ( i = 0, len = items.length; i < len; i++ ) {
|
2015-10-01 13:48:52 +00:00
|
|
|
if ( items[ i ] && typeof items[ i ].reset === 'function' ) {
|
|
|
|
items[ i ].reset();
|
2015-09-29 22:58:34 +00:00
|
|
|
}
|
2015-09-23 00:15:28 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-09-16 20:42:17 +00:00
|
|
|
/**
|
|
|
|
* Reset the loading 'dummy' option widget
|
|
|
|
*
|
|
|
|
* @param {string} [label] Label for the option widget
|
2015-12-21 21:47:09 +00:00
|
|
|
* @param {string} [link] Link for the option widget
|
2015-09-16 20:42:17 +00:00
|
|
|
*/
|
2015-12-21 21:47:09 +00:00
|
|
|
mw.echo.ui.NotificationsWidget.prototype.resetLoadingOption = function ( label, link ) {
|
2015-09-16 20:42:17 +00:00
|
|
|
this.loadingOptionWidget.setLabel( label || '' );
|
2015-12-21 21:47:09 +00:00
|
|
|
this.loadingOptionWidget.setLink( link || '' );
|
2015-09-16 20:42:17 +00:00
|
|
|
this.addItems( [ this.loadingOptionWidget ] );
|
|
|
|
};
|
2015-10-16 23:18:25 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the model associated with this widget
|
|
|
|
*
|
|
|
|
* @return {mw.echo.dm.NotificationsModel} Notifications model
|
|
|
|
*/
|
|
|
|
mw.echo.ui.NotificationsWidget.prototype.getModel = function () {
|
|
|
|
return this.model;
|
|
|
|
};
|
|
|
|
|
2015-12-21 21:47:09 +00:00
|
|
|
} )( mediaWiki, jQuery );
|