Mooeypoo has uploaded a new change for review. https://gerrit.wikimedia.org/r/291851
Change subject: Display a message if there are no notifications in Special:Page ...................................................................... Display a message if there are no notifications in Special:Page 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 Change-Id: I1465f772bb9f5247df645d6612f951e5fd7d38cf --- M Resources.php M i18n/en.json M i18n/qqq.json M modules/api/mw.echo.api.EchoApi.js M modules/controller/mw.echo.Controller.js M modules/model/mw.echo.dm.ModelManager.js M modules/model/mw.echo.dm.NotificationsList.js M modules/model/mw.echo.dm.PaginationModel.js M modules/styles/mw.echo.ui.NotificationsInboxWidget.less M modules/ui/mw.echo.ui.NotificationsInboxWidget.js M modules/ui/mw.echo.ui.PaginationWidget.js 11 files changed, 164 insertions(+), 15 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Echo refs/changes/51/291851/1 diff --git a/Resources.php b/Resources.php index 9cdbfce..8b1b63f 100644 --- a/Resources.php +++ b/Resources.php @@ -296,6 +296,7 @@ 'notification-inbox-filter-read', 'notification-inbox-filter-unread', 'notification-inbox-filter-all', + 'echo-notification-placeholder-filters', 'echo-more-info', 'echo-feedback', 'echo-specialpage-section-markread', diff --git a/i18n/en.json b/i18n/en.json index d193e0d..abff167 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -108,6 +108,7 @@ "echo-api-failure": "Failed to fetch notifications.", "echo-api-failure-cross-wiki": "Access to the remote domain was denied.", "echo-notification-placeholder": "There are no notifications.", + "echo-notification-placeholder-filters": "There are no notifications matching this criteria.", "echo-notification-loginrequired": "You must login to see your notifications.", "echo-notification-popup-loginrequired": "Please log in to view your notifications.", "echo-notification-markasread": "Mark as read", diff --git a/i18n/qqq.json b/i18n/qqq.json index f03c35e..900a9ca 100644 --- a/i18n/qqq.json +++ b/i18n/qqq.json @@ -99,6 +99,7 @@ "echo-api-failure": "Label for the text that notes an error in retrieving notifications for the Echo popup.", "echo-api-failure-cross-wiki": "Label for the api failure text for a failure to fetch cross-wiki notifications, but the remote server is not granted access.", "echo-notification-placeholder": "Label for the text that appears if there are no notifications in the Echo popup.", + "echo-notification-placeholder-filters": "Label for the text that appears if there are no notifications in the Special:Notifications page with filters selected.", "echo-notification-loginrequired": "Message that displays when an anonymous user attempts to view notifications and gets redirect to the login page.", "echo-notification-popup-loginrequired": "Message that displays when an anonymous user attempts to view notifications in their popup after a session expired.", "echo-notification-markasread": "Label for the button to mark the notification as read.", diff --git a/modules/api/mw.echo.api.EchoApi.js b/modules/api/mw.echo.api.EchoApi.js index c0de083..f4aee2f 100644 --- a/modules/api/mw.echo.api.EchoApi.js +++ b/modules/api/mw.echo.api.EchoApi.js @@ -189,4 +189,7 @@ return this.network.getApiHandler( source ).getFetchNotificationPromise( type ); }; + mw.echo.api.EchoApi.prototype.getLimit = function () { + return this.limit; + }; } )( mediaWiki ); diff --git a/modules/controller/mw.echo.Controller.js b/modules/controller/mw.echo.Controller.js index 7fad2b5..bfd2081 100644 --- a/modules/controller/mw.echo.Controller.js +++ b/modules/controller/mw.echo.Controller.js @@ -76,6 +76,7 @@ filters = this.manager.getFiltersModel(), continueValue = pagination.getPageContinue( page || pagination.getCurrPageIndex() ); + pagination.setItemsPerPage( this.api.getLimit() ); return this.api.fetchNotifications( this.manager.getTypeString(), 'local', @@ -84,7 +85,7 @@ filters.getReadState() ) .then( function ( data ) { - var i, notifData, newNotifData, date, itemModel, symbolicName, + var i, notifData, newNotifData, date, itemModel, symbolicName, count, dateItemIds = {}, dateItems = {}, models = {}; @@ -137,7 +138,13 @@ controller.manager.setNotificationModels( models ); // Update the pagination - controller.manager.getPaginationModel().setNextPageContinue( data.continue ); + count = controller.manager.getAllNotificationCount(); + if ( count < pagination.getItemsPerPage() ) { + pagination.setLastPageItemCount( + controller.manager.getAllNotificationCount() + ); + } + pagination.setNextPageContinue( data.continue ); return dateItemIds; } ); diff --git a/modules/model/mw.echo.dm.ModelManager.js b/modules/model/mw.echo.dm.ModelManager.js index 766200c..9fcae1c 100644 --- a/modules/model/mw.echo.dm.ModelManager.js +++ b/modules/model/mw.echo.dm.ModelManager.js @@ -8,11 +8,12 @@ * cross wiki notification, which acts as an item but itself contains * a list. * - * All models that are managed by the manager must implement the following - * methods: + * 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 @@ -116,6 +117,23 @@ }; /** + * 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 diff --git a/modules/model/mw.echo.dm.NotificationsList.js b/modules/model/mw.echo.dm.NotificationsList.js index 97f2732..b2b46fe 100644 --- a/modules/model/mw.echo.dm.NotificationsList.js +++ b/modules/model/mw.echo.dm.NotificationsList.js @@ -193,6 +193,15 @@ }; /** + * A general method to get the number of notifications in this list + * + * @return {number} Item count + */ + mw.echo.dm.NotificationsList.prototype.getCount = function () { + return this.getItemCount(); + }; + + /** * Check if there are unseen items in this list * * @return {boolean} There are unseen items in the list diff --git a/modules/model/mw.echo.dm.PaginationModel.js b/modules/model/mw.echo.dm.PaginationModel.js index b13d58a..4d516ff 100644 --- a/modules/model/mw.echo.dm.PaginationModel.js +++ b/modules/model/mw.echo.dm.PaginationModel.js @@ -8,6 +8,9 @@ * @constructor * @param {Object} config Configuration object * @cfg {string} [pageNext] The continue value of the next page + * @cfg {number} [lastPageItemCount] The number of items that are in the + * last page. + * @cfg {number} [itemsPerPage] The number of items per page */ mw.echo.dm.PaginationModel = function MwEchoDmPaginationModel( config ) { config = config || {}; @@ -16,6 +19,8 @@ OO.EventEmitter.call( this ); this.pagesContinue = []; + this.lastPageItemCount = this.lastPageItemCount || 0; + this.itemsPerPage = this.itemsPerPage || 25; // Set initial page this.currPageIndex = 0; @@ -161,4 +166,40 @@ mw.echo.dm.PaginationModel.prototype.hasNextPage = function () { return !!this.pagesContinue[ this.currPageIndex + 1 ]; }; + + /** + * Set the number of items in the last page + * + * @param {number} count Number of items + */ + mw.echo.dm.PaginationModel.prototype.setLastPageItemCount = function ( count ) { + this.lastPageItemCount = count; + }; + + /** + * Get the number of items in the last page + * + * @return {number} Number of items + */ + mw.echo.dm.PaginationModel.prototype.getLastPageItemCount = function () { + return this.lastPageItemCount; + }; + + /** + * Set the number of items per page + * + * @param {number} count Number of items per page + */ + mw.echo.dm.PaginationModel.prototype.setItemsPerPage = function ( count ) { + this.itemsPerPage = count; + }; + + /** + * Get the number of items per page + * + * @return {number} Number of items per page + */ + mw.echo.dm.PaginationModel.prototype.getItemsPerPage = function () { + return this.itemsPerPage; + }; } )( mediaWiki ); diff --git a/modules/styles/mw.echo.ui.NotificationsInboxWidget.less b/modules/styles/mw.echo.ui.NotificationsInboxWidget.less index fedbea7..df5bdf6 100644 --- a/modules/styles/mw.echo.ui.NotificationsInboxWidget.less +++ b/modules/styles/mw.echo.ui.NotificationsInboxWidget.less @@ -1,6 +1,9 @@ .mw-echo-ui-notificationsInboxWidget { - &.oo-ui-pendingElement-pending .mw-echo-ui-datedSubGroupListWidget { - opacity: 0.5; + &.oo-ui-pendingElement-pending { + .mw-echo-ui-notificationsInboxWidget-notice, + .mw-echo-ui-datedSubGroupListWidget { + opacity: 0.5; + } } &-toolbar { diff --git a/modules/ui/mw.echo.ui.NotificationsInboxWidget.js b/modules/ui/mw.echo.ui.NotificationsInboxWidget.js index 5e5d24d..bd6a4d8 100644 --- a/modules/ui/mw.echo.ui.NotificationsInboxWidget.js +++ b/modules/ui/mw.echo.ui.NotificationsInboxWidget.js @@ -27,6 +27,11 @@ 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, @@ -84,6 +89,7 @@ .append( this.topPaginationWidget.$element ) ) ), + this.noticeMessageWidget.$element, this.datedListWidget.$element, $( '<div>' ) .addClass( 'mw-echo-ui-notificationsInboxWidget-toolbar-bottom' ) @@ -152,12 +158,67 @@ } this.pushPending(); - this.topPaginationWidget.setDisabled( true ); - this.bottomPaginationWidget.setDisabled( true ); return fetchPromise - .then( this.topPaginationWidget.setDisabled.bind( this.topPaginationWidget, false ) ) - .then( this.bottomPaginationWidget.setDisabled.bind( this.bottomPaginationWidget, false ) ) // Pop pending .always( this.popPending.bind( this ) ); }; + + /** + * Extend the pushPending method to disable UI elements + */ + mw.echo.ui.NotificationsInboxWidget.prototype.pushPending = function () { + this.noticeMessageWidget.toggle( false ); + this.readStateSelectWidget.setDisabled( true ); + 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.readStateSelectWidget.setDisabled( false ); + 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 hte list + * in case the list is empty. + * + * @param {string} [label] Label for the option widget + * @param {string} [link] Link for the option widget + */ + mw.echo.ui.NotificationsInboxWidget.prototype.resetMessageLabel = function () { + var label, + count = this.manager.getAllNotificationCount(); + + 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( true ); + } + + 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 ); diff --git a/modules/ui/mw.echo.ui.PaginationWidget.js b/modules/ui/mw.echo.ui.PaginationWidget.js index e32951d..7906b78 100644 --- a/modules/ui/mw.echo.ui.PaginationWidget.js +++ b/modules/ui/mw.echo.ui.PaginationWidget.js @@ -143,12 +143,16 @@ * per page, and the amount of notifications on the current page. */ mw.echo.ui.PaginationWidget.prototype.updateLabel = function () { - var firstNotifNum = ( this.model.getCurrPageIndex() * this.itemsPerPage ), - lastNotifNum = firstNotifNum + this.itemsPerPage, - label = ( firstNotifNum + 1 ) + ' - ' + lastNotifNum; + var label = '', + itemsInPage = this.model.hasNextPage() ? + this.itemsPerPage : this.model.getLastPageItemCount(), + firstNotifNum = ( this.model.getCurrPageIndex() * this.itemsPerPage ), + lastNotifNum = firstNotifNum + itemsInPage; - // Display the range + if ( itemsInPage > 1 ) { + label = ( firstNotifNum + 1 ) + ' - ' + lastNotifNum; + } + this.labelWidget.setLabel( label ); }; - } )( jQuery, mediaWiki ); -- To view, visit https://gerrit.wikimedia.org/r/291851 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I1465f772bb9f5247df645d6612f951e5fd7d38cf Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Echo Gerrit-Branch: master Gerrit-Owner: Mooeypoo <mor...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits