frontend.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /**
  2. * Main Javascript file
  3. *
  4. * @author Giancarlo Voci
  5. * @date 27/06/2018
  6. * @time 17:42
  7. */
  8. import $ from '../../shared/jquery.js';
  9. import './common';
  10. import { AjaxReq } from './OMGUtils';
  11. const CUSTOM_NOTIFICATION_CODE = 0x4000;
  12. const FOCUS_INTERVAL_MS = 1000;
  13. const NOTIFICATION_REFRESH_INTERVAL_MS = 3000;
  14. const DELETE_ALL_NOTIFICATION_LINK = '#';
  15. /**
  16. * Adds a notification item to the notification menu.
  17. *
  18. * @param {{caption: string, code: number, count: number, link: string|null, timestamp: string}} notification Notification data.
  19. * @returns {JQuery} Notification menu item.
  20. * @sideEffects Registers a click handler.
  21. */
  22. function createNotificationItem(notification) {
  23. return $('<a>', { class: 'dropdown-item', href: '#' })
  24. .text(`[${notification.timestamp}] ${notification.caption}`)
  25. .append($('<span>', { class: 'ms-1 badge bg-danger', text: notification.count }))
  26. .on('click', event => {
  27. event.preventDefault();
  28. deleteNotification(notification.link, notification.code);
  29. });
  30. }
  31. /**
  32. * Renders the notifications visible to the user.
  33. *
  34. * @param {Array<object>} notifications Notifications returned by the API.
  35. * @returns {void}
  36. * @sideEffects Updates the notification menu.
  37. */
  38. function renderNotifications(notifications) {
  39. const visibleNotifications = notifications.filter(
  40. notification => notification.code <= CUSTOM_NOTIFICATION_CODE,
  41. );
  42. const notificationArea = $('#notification_area').empty();
  43. if (visibleNotifications.length === 0) {
  44. $('#notification_area_button').addClass('disabled');
  45. $('#sysmsgnum').empty();
  46. return;
  47. }
  48. visibleNotifications.forEach(notification => notificationArea.append(createNotificationItem(notification)));
  49. notificationArea.append(
  50. $('<a>', { id: 'notification_area_deleteall', class: 'dropdown-item text-center', href: '#', text: 'Cancella tutto' })
  51. .on('click', event => {
  52. event.preventDefault();
  53. deleteNotification(DELETE_ALL_NOTIFICATION_LINK, 0);
  54. }),
  55. );
  56. $('#notification_area_button').removeClass('disabled');
  57. $('#sysmsgnum').text(visibleNotifications.length);
  58. }
  59. /**
  60. * Retrieves and renders the current system notifications.
  61. *
  62. * @returns {void}
  63. * @sideEffects Performs a network request and updates the notification menu.
  64. */
  65. function refreshNotificationArea() {
  66. AjaxReq(`${BASEURL}/api.system.getserverstatus`, { method: 'GET' }).fetchPromise()
  67. .then(data => renderNotifications(data.notify))
  68. .catch(error => console.error('Unable to refresh system notifications.', error));
  69. }
  70. /**
  71. * Deletes one notification and optionally follows its link.
  72. *
  73. * @param {string|null} link Link associated with the notification.
  74. * @param {number} code Notification code.
  75. * @returns {void}
  76. * @sideEffects Performs a network request and may navigate the browser.
  77. */
  78. function deleteNotification(link, code) {
  79. fetch(`${BASEURL}/api.system.removenotification/${code}`, { method: 'POST' })
  80. .then(response => {
  81. if (!response.ok) {
  82. return Promise.reject(response);
  83. }
  84. if (link && link !== DELETE_ALL_NOTIFICATION_LINK) {
  85. window.location.href = `${BASEURL}${link}`;
  86. }
  87. })
  88. .catch(error => {
  89. console.error('Unable to delete the notification.', { code, error });
  90. alert('NotificationDelete error');
  91. });
  92. }
  93. /**
  94. * Enables confirmation prompts for elements that require explicit user approval.
  95. *
  96. * @returns {void}
  97. * @sideEffects Registers click handlers.
  98. */
  99. function setupConfirmationDialog() {
  100. $('.requestconfirm').on('click', function (event) {
  101. if (!confirm($(this).data('confirmtext'))) {
  102. event.preventDefault();
  103. }
  104. });
  105. }
  106. /**
  107. * Keeps elements marked with forcefocus focused.
  108. *
  109. * @returns {void}
  110. * @sideEffects Starts an interval timer.
  111. */
  112. function startFocusEnforcement() {
  113. setInterval(() => $('[forcefocus]').focus(), FOCUS_INTERVAL_MS);
  114. }
  115. /**
  116. * Initializes frontend interactions after the document is ready.
  117. *
  118. * @returns {void}
  119. * @sideEffects Registers UI handlers and starts polling timers.
  120. */
  121. function initializeFrontend() {
  122. setupConfirmationDialog();
  123. refreshNotificationArea();
  124. startFocusEnforcement();
  125. $('body').on('submit', 'form', function () {
  126. $('body').focus();
  127. $('form input,form select').prop('readonly', true);
  128. this.submit();
  129. return false;
  130. });
  131. setInterval(refreshNotificationArea, NOTIFICATION_REFRESH_INTERVAL_MS);
  132. window.NotificationDelete = deleteNotification;
  133. }
  134. document.addEventListener('DOMContentLoaded', initializeFrontend);