mediawiki-skins-MinervaNeue/resources/skins.minerva.notifications.badge/NotificationBadge.js

179 lines
5.3 KiB
JavaScript
Raw Normal View History

( function ( M ) {
var View = M.require( 'mobile.startup/View' ),
util = M.require( 'mobile.startup/util' ),
Icon = M.require( 'mobile.startup/Icon' ),
notificationIcon = new Icon( {
name: 'notifications',
glyphPrefix: 'minerva'
} ),
icons = M.require( 'mobile.startup/icons' );
/**
* A notification button for communicating with an NotificationOverlay
* @class NotificationButton
* @extends View
* @param {Object} options Configuration options
*/
function NotificationBadge( options ) {
var $el,
count = options.notificationCountRaw || 0,
el = options.el;
if ( el ) {
$el = $( el );
options.hasUnseenNotifications = $el.find( '.notification-unseen' ).length;
options.hasNotifications = options.hasUnseenNotifications;
options.title = $el.find( 'a' ).attr( 'title' );
options.url = $el.find( 'a' ).attr( 'href' );
count = Number( $el.find( 'span' ).data( 'notification-count' ) );
options.onError = function () {
// FIXME: Blocked on T189173. Ideally we'd use the router here.
window.location.href = this.getNotificationURL();
}.bind( this );
}
View.call( this,
util.extend( options, {
isBorderBox: false
} )
);
this.url = options.url;
this._bindOverlayManager();
this.setCount( count );
}
OO.mfExtend( NotificationBadge, View, {
/**
* @cfg {object} defaults Default options hash.
* @cfg {string} defaults.notificationIconClass e.g. mw-ui-icon for icon
* @cfg {string} defaults.loadingIconHtml for spinner
* @cfg {boolean} defaults.hasUnseenNotifications whether the user has unseen notifications
* @cfg {number} defaults.notificationCountRaw number of unread notifications
* @memberof NotificationBadge
* @instance
*/
defaults: {
notificationIconClass: notificationIcon.getClassName(),
loadingIconHtml: icons.spinner().toHtmlString(),
hasNotifications: false,
hasUnseenNotifications: false,
notificationCountRaw: 0
},
/**
* Loads a ResourceLoader module script. Shows ajax loader whilst loading.
* @method
* @private
* @memberof NotificationBadge
* @instance
* @param {string} moduleName Name of a module to fetch
* @return {JQuery.Promise}
*/
_loadModuleScript: function ( moduleName ) {
var self = this;
this.$el.html( this.options.loadingIconHtml );
return mw.loader.using( moduleName ).then( function () {
// trigger a re-render once one to remove loading icon
self.render();
} );
},
/**
* Load the notification overlay.
* @method
* @private
* @memberof NotificationBadge
* @instance
* @uses NotificationsOverlay
* @return {JQuery.Deferred} with an instance of NotificationsOverlay
*/
_loadNotificationOverlay: function () {
var self = this;
return this._loadModuleScript( 'mobile.notifications.overlay' ).then( function () {
var NotificationsOverlay =
M.require( 'mobile.notifications.overlay/NotificationsOverlay' ); // resource-modules-disable-line
return new NotificationsOverlay( {
badge: self
} );
} );
},
/**
* Sets up routes in overlay manager and click behaviour for NotificationBadge
* This is not unit tested as it's behaviour is covered by browser tests.
* @memberof NotificationBadge
* @instance
* @private
*/
_bindOverlayManager: function () {
var self = this,
mainMenu = this.options.mainMenu;
this.$el.on( 'click', $.proxy( this.onClickBadge, this ) );
this.options.overlayManager.add( /^\/notifications$/, function () {
return self._loadNotificationOverlay().then( function ( overlay ) {
mainMenu.openNavigationDrawer( 'secondary' );
overlay.on( 'hide', function () {
mainMenu.closeNavigationDrawers();
$( '#mw-mf-page-center' ).off( '.secondary' );
} );
$( '#mw-mf-page-center' ).one( 'click.secondary', function () {
self.options.router.back();
} );
return overlay;
} );
} );
},
template: mw.template.get( 'skins.minerva.notifications.badge', 'badge.hogan' ),
/**
* Click handler for clicking on the badge
* @memberof NotificationBadge
* @instance
* @return {boolean}
*/
onClickBadge: function () {
this.options.router.navigate( '#/notifications' );
// Important that we also prevent propagation to avoid interference with events that may
// be binded on #mw-mf-page-center that close overlay
return false;
},
/**
* Return the URL for the full non-overlay notification view
* @memberof NotificationBadge
* @instance
* @return {string} url
*/
getNotificationURL: function () {
return this.options.url;
},
/**
* Update the notification count
* @memberof NotificationBadge
* @instance
* @param {number} count
*/
setCount: function ( count ) {
if ( count > 100 ) {
count = 100;
}
this.options.notificationCountRaw = count;
this.options.notificationCountString = mw.message( 'echo-badge-count',
mw.language.convertNumber( count )
).text();
this.options.isNotificationCountZero = count === 0;
this.render();
},
/**
* Marks all notifications as seen
*
* @memberof NotificationBadge
* @instance
*/
markAsSeen: function () {
this.options.hasUnseenNotifications = false;
this.render();
}
} );
M.define( 'skins.minerva.notifications/NotificationBadge', NotificationBadge );
}( mw.mobileFrontend ) );