notificationView.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /*
  2. * Licensed Materials - Property of IBM
  3. *
  4. * IBM Cognos Products: SHARE
  5. *
  6. * (C) Copyright IBM Corp. 2015, 2018
  7. *
  8. * US Government Users Restricted Rights - Use, duplication or disclosure
  9. * restricted by GSA ADP Schedule Contract with IBM Corp.
  10. */
  11. define([
  12. 'underscore',
  13. 'jquery',
  14. "q",
  15. "bi/sharecommon/utils/simpledoT",
  16. 'text!bi/notifications/templates/notification.html',
  17. 'text!bi/notifications/templates/emptyMessageList.html',
  18. 'text!bi/notifications/templates/loadingMessagesPopUp.html',
  19. "bi/sharecommon/utils/translator",
  20. "bi/glass/app/ContentView",
  21. "bi/notifications/views/messageListView",
  22. 'bi/commons/utils/Utils',
  23. "bi/notifications/app/n10nController",
  24. "../../admin/ba-graphics/dist/illustrations-js/notifications_128",
  25. ], function(_, $, Q, dot, Template, emptyMsgTemplate, loadingTemplate, t, View, MessageListView, Utils, n10nController, notifications_128) {
  26. var __notificationView_firstRender = true;
  27. var __currentMessageList = null;
  28. var notificationView = View.extend({
  29. /**
  30. * Constructor. Expect
  31. * { context: context, maxFetch: maximum_number_of_items_to_retrieve }
  32. */
  33. init: function(options) {
  34. notificationView.inherited('init', this, arguments);
  35. $.extend(this, options);
  36. this.offset = 0;
  37. this.prependLoading = false;
  38. this.currentTopUnreadId = '';
  39. this.currentTopReadId = '';
  40. this.isShowingEmptyMessageList = false;
  41. this.loadingAnimation = Utils.getLoadingAnimation(1);
  42. this.$loadingMessagePopUp = $(dot.template(loadingTemplate)());
  43. },
  44. /**
  45. * Automatically called when render is done. Sets the focus
  46. * to the first message in the notifications list.
  47. */
  48. setFocus: function() {
  49. this.$el.find('.n10n_message_container .n10n_message:first .n10n_message_inner').focus();
  50. },
  51. _setEvents: function() {
  52. this.offset = 0;
  53. var $messageList = this.$el.find('.n10n_message_container');
  54. var lastScrollTopPosition = 0;
  55. var isLoading = false;
  56. $messageList.on('keypress', function(event) {
  57. var key = event.keyCode || event.charCode || event.which || 0;
  58. // This little bit is to prevent space from scrolling the notification list
  59. if (key == 32) {
  60. event.preventDefault();
  61. }
  62. });
  63. $messageList.scroll(function() {
  64. var currentScrollTopPostion = $messageList.scrollTop();
  65. if (currentScrollTopPostion > lastScrollTopPosition) {
  66. if (!isLoading && (currentScrollTopPostion >= $messageList[0].scrollHeight - $messageList.innerHeight())) {
  67. isLoading = true;
  68. this._checkForMoreMessages($messageList).then(function() {
  69. isLoading = false;
  70. });
  71. }
  72. }
  73. lastScrollTopPosition = currentScrollTopPostion;
  74. }.bind(this));
  75. },
  76. _checkForMoreMessages: function($messageList) {
  77. $messageList.find('.n10n_message:last').after(this.$loadingMessagePopUp.append(this.loadingAnimation));
  78. return this.glassContext.getSvc('.Notification').then(function(notificationSvc) {
  79. return notificationSvc.getNotifications(n10nController.MAX_DISPLAY, this.offset);
  80. }.bind(this)).then(function(data) {
  81. __currentMessageList.appendNewMessages(data);
  82. this.$loadingMessagePopUp.remove();
  83. this.offset += data.length;
  84. return true;
  85. }.bind(this))
  86. .catch(function() {
  87. /* swallow */
  88. });
  89. },
  90. _loadNewMessages: function(newData) {
  91. var $messageList = this.$el.find('.n10n_message_container');
  92. var newMessagesOffset = 0;
  93. var topMessageLocation = n10nController.MAX_DISPLAY;
  94. var loadingAnimation = Utils.getLoadingAnimation(1);
  95. var $loadingMessagePopUp = $(dot.template(loadingTemplate)());
  96. var newMessages = [];
  97. function checkMessages(offset, notificationView, newData) {
  98. for (var i = 0; i < newData.length; i++) {
  99. if (newData[i].id === notificationView.currentTopUnreadId) {
  100. topMessageLocation = i;
  101. break;
  102. } else if (newData[i].id === notificationView.currentTopReadId) {
  103. topMessageLocation = i;
  104. break;
  105. }
  106. }
  107. newMessages = newMessages.concat(newData.slice(0, topMessageLocation));
  108. if (newMessages.length === 0) {
  109. notificationView.prependLoading = false;
  110. $('.n10n_loading_messages_popup:first').remove();
  111. return;
  112. } else {
  113. if (newMessages.length < newMessagesOffset + n10nController.MAX_DISPLAY) {
  114. // Current top message is found, prepend to messageListView
  115. $('.n10n_loading_messages_popup:first').remove();
  116. notificationView.currentTopUnreadId = newMessages[0].id;
  117. notificationView.prependLoading = false;
  118. __currentMessageList.prependNewMessages(newMessages);
  119. } else {
  120. // Current Top message not found yet, meaning there is more new messages than MAX_DISPLAY
  121. newMessagesOffset += n10nController.MAX_DISPLAY;
  122. notificationView.glassContext.getSvc('.Notification').then(function(notificationSvc) {
  123. return notificationSvc.getNotifications(n10nController.MAX_DISPLAY, newMessagesOffset);
  124. }).then(function(data) {
  125. checkMessages(newMessagesOffset, notificationView, data);
  126. });
  127. }
  128. }
  129. } // end checkMessages
  130. if (!this.prependLoading) {
  131. $messageList.scrollTop(0);
  132. this.prependLoading = true;
  133. $('.n10n_message:first').before($loadingMessagePopUp.append(loadingAnimation));
  134. checkMessages(newMessagesOffset, this, newData);
  135. }
  136. },
  137. render: function() {
  138. var html = dot.template(Template);
  139. var labels = {
  140. n10n_label: t.translate("n10n_label")
  141. };
  142. this.$el.addClass("share_message_panel");
  143. this.$el.html(html(labels));
  144. this._setEvents();
  145. return this.glassContext.getSvc('.Notification').then(function(notificationSvc) {
  146. return notificationSvc.getNotifications(n10nController.MAX_DISPLAY, this.offset).then(function(data) {
  147. if (!this.isShowingEmptyMessageList && data.length === 0) {
  148. var sHtml = dot.template(emptyMsgTemplate)({'text': t.translate("empty_notification_list")});
  149. this.$el.find('.n10n_message_container').append(sHtml);
  150. this.isShowingEmptyMessageList = true;
  151. var $icon = this.$el.find('.empty_notifications_illustration_128');
  152. Utils.setIcon($icon, notifications_128.default.id);
  153. }
  154. if (this.isShowingEmptyMessageList && data.length > 0) {
  155. this.$el.find('.emptyTableContent').remove();
  156. this.isShowingEmptyMessageList = false;
  157. }
  158. this.offset += data.length;
  159. __currentMessageList = new MessageListView({
  160. $el: this.$el.find('.n10n_message_container'),
  161. glassContext: this.glassContext,
  162. data: data,
  163. slideout: this.slideout,
  164. loadMessagesCallback: this._checkForMoreMessages.bind(this)
  165. });
  166. __currentMessageList.render();
  167. this._getNewTopMsgIds();
  168. if (__notificationView_firstRender) {
  169. notificationSvc.on("notifications:deleted", this._getNewTopMsgIds.bind(this));
  170. notificationSvc.on("notifications:read", this._getNewTopMsgIds.bind(this));
  171. notificationSvc .on('notifications:new', function(newData) {
  172. var newMessages = newData;
  173. // checks
  174. var noUnreadMessages = (!this.currentTopUnreadId);
  175. var mixedMessages = !noUnreadMessages;
  176. var checkNoUnreadMessages = (noUnreadMessages && newData.length);
  177. var checkMixed = (mixedMessages && (newData[0].id !== this.currentTopUnreadId) && (newData[0].id !== this.currentTopReadId));
  178. var checkNewMessages = (checkNoUnreadMessages || checkMixed);
  179. if (checkNewMessages && $('#share_message_list').length && !this.prependLoading) {
  180. this.glassContext.appController.showToast(t.translate('toast_new_notifications'), {
  181. 'type': 'info',
  182. 'onclick': function(event) {
  183. event.preventDefault();
  184. this._loadNewMessages(newMessages);
  185. }.bind(this),
  186. 'timeOut': 0,
  187. 'extendedTimeOut': 0
  188. });
  189. }
  190. }.bind(this));
  191. __notificationView_firstRender = false;
  192. }
  193. return this;
  194. }.bind(this));
  195. }.bind(this));
  196. // show messages
  197. },
  198. _getNewTopMsgIds: function(data) {
  199. this.currentTopUnreadId = this.$el.find('.n10n_message:has(.unread)').first().attr('id') || '';
  200. this.currentTopReadId = this.$el.find('.n10n_message:has(.read)').first().attr('id') || '';
  201. },
  202. // Method for unit tests; DO NOT TEST
  203. __setNotificationViewFirstRender: function(value) {
  204. __notificationView_firstRender = value;
  205. }
  206. });
  207. return notificationView;
  208. });