notifications.js 11 KB

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