You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

notification.js 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. const {AppSubUrl, csrf, NotificationSettings} = window.config;
  2. let notificationSequenceNumber = 0;
  3. export function initNotificationsTable() {
  4. $('#notification_table .button').on('click', async function () {
  5. const data = await updateNotification(
  6. $(this).data('url'),
  7. $(this).data('status'),
  8. $(this).data('page'),
  9. $(this).data('q'),
  10. $(this).data('notification-id'),
  11. );
  12. if ($(data).data('sequence-number') === notificationSequenceNumber) {
  13. $('#notification_div').replaceWith(data);
  14. initNotificationsTable();
  15. }
  16. await updateNotificationCount();
  17. return false;
  18. });
  19. }
  20. async function receiveUpdateCount(event) {
  21. try {
  22. const data = JSON.parse(event.data);
  23. const notificationCount = document.querySelector('.notification_count');
  24. if (data.Count > 0) {
  25. notificationCount.classList.remove('hidden');
  26. } else {
  27. notificationCount.classList.add('hidden');
  28. }
  29. notificationCount.textContent = `${data.Count}`;
  30. await updateNotificationTable();
  31. } catch (error) {
  32. console.error(error, event);
  33. }
  34. }
  35. export async function initNotificationCount() {
  36. const notificationCount = $('.notification_count');
  37. if (!notificationCount.length) {
  38. return;
  39. }
  40. if (NotificationSettings.EventSourceUpdateTime > 0 && !!window.EventSource && window.SharedWorker) {
  41. // Try to connect to the event source via the shared worker first
  42. const worker = new SharedWorker(`${__webpack_public_path__}js/eventsource.sharedworker.js`, 'notification-worker');
  43. worker.addEventListener('error', (event) => {
  44. console.error(event);
  45. });
  46. worker.port.addEventListener('messageerror', () => {
  47. console.error('Unable to deserialize message');
  48. });
  49. worker.port.postMessage({
  50. type: 'start',
  51. url: `${window.location.origin}${AppSubUrl}/user/events`,
  52. });
  53. worker.port.addEventListener('message', (event) => {
  54. if (!event.data || !event.data.type) {
  55. console.error(event);
  56. return;
  57. }
  58. if (event.data.type === 'notification-count') {
  59. receiveUpdateCount(event.data);
  60. } else if (event.data.type === 'error') {
  61. console.error(event.data);
  62. } else if (event.data.type === 'logout') {
  63. if (event.data.data !== 'here') {
  64. return;
  65. }
  66. worker.port.postMessage({
  67. type: 'close',
  68. });
  69. worker.port.close();
  70. window.location.href = AppSubUrl;
  71. } else if (event.data.type === 'close') {
  72. worker.port.postMessage({
  73. type: 'close',
  74. });
  75. worker.port.close();
  76. }
  77. });
  78. worker.port.addEventListener('error', (e) => {
  79. console.error(e);
  80. });
  81. worker.port.start();
  82. window.addEventListener('beforeunload', () => {
  83. worker.port.postMessage({
  84. type: 'close',
  85. });
  86. worker.port.close();
  87. });
  88. return;
  89. }
  90. if (NotificationSettings.MinTimeout <= 0) {
  91. return;
  92. }
  93. const fn = (timeout, lastCount) => {
  94. setTimeout(async () => {
  95. await updateNotificationCountWithCallback(fn, timeout, lastCount);
  96. }, timeout);
  97. };
  98. fn(NotificationSettings.MinTimeout, notificationCount.text());
  99. }
  100. async function updateNotificationCountWithCallback(callback, timeout, lastCount) {
  101. const currentCount = $('.notification_count').text();
  102. if (lastCount !== currentCount) {
  103. callback(NotificationSettings.MinTimeout, currentCount);
  104. return;
  105. }
  106. const newCount = await updateNotificationCount();
  107. let needsUpdate = false;
  108. if (lastCount !== newCount) {
  109. needsUpdate = true;
  110. timeout = NotificationSettings.MinTimeout;
  111. } else if (timeout < NotificationSettings.MaxTimeout) {
  112. timeout += NotificationSettings.TimeoutStep;
  113. }
  114. callback(timeout, newCount);
  115. if (needsUpdate) {
  116. await updateNotificationTable();
  117. }
  118. }
  119. async function updateNotificationTable() {
  120. const notificationDiv = $('#notification_div');
  121. if (notificationDiv.length > 0) {
  122. const data = await $.ajax({
  123. type: 'GET',
  124. url: `${AppSubUrl}/notifications?${notificationDiv.data('params')}`,
  125. data: {
  126. 'div-only': true,
  127. 'sequence-number': ++notificationSequenceNumber,
  128. }
  129. });
  130. if ($(data).data('sequence-number') === notificationSequenceNumber) {
  131. notificationDiv.replaceWith(data);
  132. initNotificationsTable();
  133. }
  134. }
  135. }
  136. async function updateNotificationCount() {
  137. const data = await $.ajax({
  138. type: 'GET',
  139. url: `${AppSubUrl}/api/v1/notifications/new`,
  140. headers: {
  141. 'X-Csrf-Token': csrf,
  142. },
  143. });
  144. const notificationCount = $('.notification_count');
  145. if (data.new === 0) {
  146. notificationCount.addClass('hidden');
  147. } else {
  148. notificationCount.removeClass('hidden');
  149. }
  150. notificationCount.text(`${data.new}`);
  151. return `${data.new}`;
  152. }
  153. async function updateNotification(url, status, page, q, notificationID) {
  154. if (status !== 'pinned') {
  155. $(`#notification_${notificationID}`).remove();
  156. }
  157. return $.ajax({
  158. type: 'POST',
  159. url,
  160. data: {
  161. _csrf: csrf,
  162. notification_id: notificationID,
  163. status,
  164. page,
  165. q,
  166. noredirect: true,
  167. 'sequence-number': ++notificationSequenceNumber,
  168. },
  169. });
  170. }