notifications.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. import $ from 'jquery';
  2. import { config } from 'grav-config';
  3. import request from '../utils/request';
  4. const canFetchNotifications = () => config.notifications;
  5. class Notifications {
  6. showNotificationInFeed(notification, index) {
  7. let notifications = $('#notifications').removeClass('hidden');
  8. let loader = notifications.find('.widget-loader').hide();
  9. let content = notifications.find('.widget-content > ul').show();
  10. loader.find('div').remove();
  11. loader.find('.fa-warning').removeClass('fa-warning').addClass('fa-refresh fa-spin');
  12. if (!notification.type) {
  13. notification.type = 'note';
  14. }
  15. switch (notification.type) {
  16. case 'note':
  17. notification.intro_text = 'Note';
  18. break;
  19. case 'info':
  20. notification.intro_text = 'Info';
  21. break;
  22. case 'warning':
  23. notification.intro_text = 'Warning';
  24. break;
  25. }
  26. let hidden = '';
  27. if (index > 9) {
  28. hidden = ' hidden ';
  29. }
  30. if (notification.link) {
  31. content.append(`
  32. <li class="single-notification ${hidden}">
  33. <span class="badge alert ${notification.type}">${notification.intro_text}</span>
  34. <a target="_blank" href="${notification.link}" title="${notification.message}">${notification.message}</a>
  35. </li>
  36. `);
  37. } else {
  38. let clean_text = $('<p>' + notification.message + '</p>').text();
  39. content.append(`
  40. <li class="single-notification ${hidden}">
  41. <span class="badge alert ${notification.type}">${notification.intro_text}</span>
  42. <span title="${clean_text}">${notification.message}</span>
  43. </li>
  44. `);
  45. }
  46. }
  47. addShowAllInFeed() {
  48. $('#notifications ul').append(`
  49. <li class="show-all" data-notification-action="show-all-notifications">Show all</li>
  50. `);
  51. }
  52. showNotificationInTop(notification) {
  53. let element;
  54. if (notification.link) {
  55. element = $(`<div class="single-notification ${notification.type} alert">
  56. <a target="_blank" href="${notification.link}">${notification.message}</a>
  57. ${notification.closeButton}
  58. </div>`);
  59. } else {
  60. element = $(`<div class="single-notification ${notification.type} alert">
  61. ${notification.message}
  62. ${notification.closeButton}
  63. </div>`);
  64. }
  65. element.hide();
  66. $('.top-notifications-container').removeClass('hidden').addClass('default-box-shadow').append(element);
  67. element.slideDown(150);
  68. }
  69. showNotificationInDashboard(notification) {
  70. let element;
  71. if (notification.link) {
  72. element = $(`<div class="single-notification alert ${notification.type}">
  73. <a target="_blank" href="${notification.link}">${notification.message}</a>
  74. ${notification.closeButton}
  75. </div>`);
  76. } else {
  77. element = $(`<div class="single-notification alert ${notification.type}">
  78. ${notification.message}
  79. ${notification.closeButton}
  80. </div>`);
  81. }
  82. element.hide();
  83. $('.dashboard-notifications-container').removeClass('hidden').append(element);
  84. element.slideDown(150);
  85. }
  86. showNotificationInPlugins(notification) {
  87. let element;
  88. if (notification.link) {
  89. element = $(`<div class="single-notification alert ${notification.type}">
  90. <a target="_blank" href="${notification.link}">${notification.message}</a>
  91. ${notification.closeButton}
  92. </div>`);
  93. } else {
  94. element = $(`<div class="single-notification alert ${notification.type}">
  95. ${notification.message} ${notification.closeButton}
  96. </div>`);
  97. }
  98. element.hide();
  99. $('.plugins-notifications-container').removeClass('hidden').append(element);
  100. element.slideDown(150);
  101. }
  102. showNotificationInThemes(notification) {
  103. let element;
  104. if (notification.link) {
  105. element = $(`<div class="single-notification alert ${notification.type}">
  106. <a target="_blank" href="${notification.link}">${notification.message}</a>
  107. ${notification.closeButton}
  108. </div>`);
  109. } else {
  110. element = $(`<div class="single-notification alert ${notification.type}">
  111. ${notification.message}
  112. ${notification.closeButton}
  113. </div>`);
  114. }
  115. element.hide();
  116. $('.themes-notifications-container').removeClass('hidden').append(element);
  117. element.slideDown(150);
  118. }
  119. processLocation(location, notification, index = 0) {
  120. switch (location) {
  121. case 'feed':
  122. this.showNotificationInFeed(notification, index);
  123. break;
  124. case 'top':
  125. if (!notification.read) {
  126. this.showNotificationInTop(notification);
  127. }
  128. break;
  129. case 'dashboard':
  130. if (!notification.read) {
  131. this.showNotificationInDashboard(notification);
  132. }
  133. break;
  134. case 'plugins':
  135. if (!notification.read) {
  136. this.showNotificationInPlugins(notification);
  137. }
  138. break;
  139. case 'themes':
  140. if (!notification.read) {
  141. this.showNotificationInThemes(notification);
  142. }
  143. break;
  144. }
  145. }
  146. // Grav.default.Notifications.fetch()
  147. fetch({ locations = [], refresh = false } = {}) {
  148. if (!canFetchNotifications()) {
  149. return false;
  150. }
  151. let that = this;
  152. let feed = $('#notifications');
  153. let loader = feed.find('.widget-loader');
  154. let content = feed.find('.widget-content > ul');
  155. loader.find('div').remove();
  156. loader.find('.fa-warning').removeClass('fa-warning').addClass('fa-refresh fa-spin');
  157. loader.show();
  158. content.hide();
  159. let processNotifications = function processNotifications(response) {
  160. let notifications = response.notifications;
  161. $('#notifications').find('.widget-content > ul').empty();
  162. if (notifications) {
  163. let index = 0;
  164. notifications.forEach(function(notification, i) {
  165. notification.closeButton = `<a href="#" data-notification-action="hide-notification" data-notification-id="${notification.id}" class="close hide-notification"><i class="fa fa-close"></i></a>`;
  166. if (notification.options && notification.options.indexOf('sticky') !== -1) {
  167. notification.closeButton = '';
  168. }
  169. if (Array.isArray(notification.location)) {
  170. notification.location.forEach(function(location) {
  171. if (locations.length && locations.indexOf(location) === -1) {
  172. return;
  173. }
  174. if (location === 'feed') {
  175. that.processLocation(location, notification, index);
  176. index++;
  177. } else {
  178. that.processLocation(location, notification);
  179. }
  180. });
  181. } else {
  182. if (locations.length && locations.indexOf(notification.location) === -1) {
  183. return;
  184. }
  185. that.processLocation(notification.location, notification);
  186. }
  187. });
  188. if (index > 10) {
  189. that.addShowAllInFeed();
  190. }
  191. }
  192. };
  193. request(`${config.base_url_relative}/notifications.json/task${config.param_sep}getNotifications`, {
  194. method: 'post'
  195. }, (response) => {
  196. if (response.need_update === true || refresh) {
  197. $.get((config.local_notifications ? 'http://localhost' : 'https://getgrav.org') + '/notifications.json?' + Date.now()).then(function(response) {
  198. request(`${config.base_url_relative}/notifications.json/task${config.param_sep}processNotifications`, {
  199. method: 'post',
  200. body: { 'notifications': JSON.stringify(response) }
  201. }, (response) => {
  202. if (response.show_immediately === true) {
  203. processNotifications(response);
  204. }
  205. });
  206. }).fail(function() {
  207. let widget = $('#notifications .widget-content');
  208. widget
  209. .find('.widget-loader')
  210. .find('div').remove();
  211. widget
  212. .find('.widget-loader')
  213. .append('<div>Failed to retrieve notifications</div>')
  214. .find('.fa-spin')
  215. .removeClass('fa-spin fa-refresh').addClass('fa-warning');
  216. });
  217. }
  218. processNotifications(response);
  219. });
  220. }
  221. }
  222. let notifications = new Notifications();
  223. export default notifications;
  224. if (canFetchNotifications()) {
  225. notifications.fetch();
  226. $(document).on('click', '[data-notification-action="hide-notification"]', (event) => {
  227. let notification_id = $(event.target).parents('.hide-notification').data('notification-id');
  228. let url = `${config.base_url_relative}/notifications.json/task${config.param_sep}hideNotification/notification_id${config.param_sep}${notification_id}`;
  229. request(url, { method: 'post' }, () => {});
  230. $(event.target).parents('.single-notification').hide();
  231. });
  232. $(document).on('click', '[data-notification-action="show-all-notifications"]', (event) => {
  233. $('#notifications .show-all').hide();
  234. $('#notifications .hidden').removeClass('hidden');
  235. });
  236. $(document).on('click', '[data-refresh="notifications"]', (event) => {
  237. event.preventDefault();
  238. notifications.fetch({ locations: ['feed'], refresh: true });
  239. });
  240. }