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.

common.js 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /* global jQuery */
  2. define(["jquery", "nprogress"],
  3. ($, NProgress) => {
  4. "use strict";
  5. const ui = {
  6. breakpoints: {
  7. xs: 0,
  8. sm: 576,
  9. md: 768,
  10. lg: 992,
  11. xl: 1200,
  12. xxl: 1400
  13. },
  14. chartLegend: [
  15. {label: "reject", color: "#FF0000"},
  16. {label: "soft reject", color: "#BF8040"},
  17. {label: "rewrite subject", color: "#FF6600"},
  18. {label: "add header", color: "#FFAD00"},
  19. {label: "greylist", color: "#436EEE"},
  20. {label: "no action", color: "#66CC00"}
  21. ],
  22. locale: (localStorage.getItem("selected_locale") === "custom") ? localStorage.getItem("custom_locale") : null,
  23. neighbours: [],
  24. page_size: {
  25. scan: 25,
  26. errors: 25,
  27. history: 25
  28. },
  29. symbols: {
  30. scan: [],
  31. history: []
  32. },
  33. tables: {}
  34. };
  35. NProgress.configure({
  36. minimum: 0.01,
  37. showSpinner: false,
  38. });
  39. function getPassword() {
  40. return sessionStorage.getItem("Password");
  41. }
  42. function alertMessage(alertClass, alertText) {
  43. const a = $("<div class=\"alert " + alertClass + " alert-dismissible fade in show\">" +
  44. "<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" title=\"Dismiss\"></button>" +
  45. "<strong>" + alertText + "</strong>");
  46. $(".notification-area").append(a);
  47. setTimeout(() => {
  48. $(a).fadeTo(500, 0).slideUp(500, function () {
  49. $(this).alert("close");
  50. });
  51. }, 5000);
  52. }
  53. function queryServer(neighbours_status, ind, req_url, o) {
  54. neighbours_status[ind].checked = false;
  55. neighbours_status[ind].data = {};
  56. neighbours_status[ind].status = false;
  57. const req_params = {
  58. jsonp: false,
  59. data: o.data,
  60. headers: $.extend({Password: getPassword()}, o.headers),
  61. url: neighbours_status[ind].url + req_url,
  62. xhr: function () {
  63. const xhr = $.ajaxSettings.xhr();
  64. // Download progress
  65. if (req_url !== "neighbours") {
  66. xhr.addEventListener("progress", (e) => {
  67. if (e.lengthComputable) {
  68. neighbours_status[ind].percentComplete = e.loaded / e.total;
  69. const percentComplete = neighbours_status
  70. .reduce((prev, curr) => (curr.percentComplete ? curr.percentComplete + prev : prev), 0);
  71. NProgress.set(percentComplete / neighbours_status.length);
  72. }
  73. }, false);
  74. }
  75. return xhr;
  76. },
  77. success: function (json) {
  78. neighbours_status[ind].checked = true;
  79. neighbours_status[ind].status = true;
  80. neighbours_status[ind].data = json;
  81. },
  82. error: function (jqXHR, textStatus, errorThrown) {
  83. neighbours_status[ind].checked = true;
  84. function errorMessage() {
  85. alertMessage("alert-error", neighbours_status[ind].name + " > " +
  86. (o.errorMessage ? o.errorMessage : "Request failed") +
  87. (errorThrown ? ": " + errorThrown : ""));
  88. }
  89. if (o.error) {
  90. o.error(neighbours_status[ind],
  91. jqXHR, textStatus, errorThrown);
  92. } else if (o.errorOnceId) {
  93. const alert_status = o.errorOnceId + neighbours_status[ind].name;
  94. if (!(alert_status in sessionStorage)) {
  95. sessionStorage.setItem(alert_status, true);
  96. errorMessage();
  97. }
  98. } else {
  99. errorMessage();
  100. }
  101. },
  102. complete: function (jqXHR) {
  103. if (neighbours_status.every((elt) => elt.checked)) {
  104. if (neighbours_status.some((elt) => elt.status)) {
  105. if (o.success) {
  106. o.success(neighbours_status, jqXHR);
  107. } else {
  108. alertMessage("alert-success", "Request completed");
  109. }
  110. } else {
  111. alertMessage("alert-error", "Request failed");
  112. }
  113. if (o.complete) o.complete();
  114. NProgress.done();
  115. }
  116. },
  117. statusCode: o.statusCode
  118. };
  119. if (o.method) {
  120. req_params.method = o.method;
  121. }
  122. if (o.params) {
  123. $.each(o.params, (k, v) => {
  124. req_params[k] = v;
  125. });
  126. }
  127. $.ajax(req_params);
  128. }
  129. // Public functions
  130. ui.alertMessage = alertMessage;
  131. ui.getPassword = getPassword;
  132. // Get selectors' current state
  133. ui.getSelector = function (id) {
  134. const e = document.getElementById(id);
  135. return e.options[e.selectedIndex].value;
  136. };
  137. ui.getServer = function () {
  138. const checked_server = ui.getSelector("selSrv");
  139. return (checked_server === "All SERVERS") ? "local" : checked_server;
  140. };
  141. /**
  142. * @param {string} url - A string containing the URL to which the request is sent
  143. * @param {Object} [options] - A set of key/value pairs that configure the Ajax request. All settings are optional.
  144. *
  145. * @param {Function} [options.complete] - A function to be called when the requests to all neighbours complete.
  146. * @param {Object|string|Array} [options.data] - Data to be sent to the server.
  147. * @param {Function} [options.error] - A function to be called if the request fails.
  148. * @param {string} [options.errorMessage] - Text to display in the alert message if the request fails.
  149. * @param {string} [options.errorOnceId] - A prefix of the alert ID to be added to the session storage. If the
  150. * parameter is set, the error for each server will be displayed only once per session.
  151. * @param {Object} [options.headers] - An object of additional header key/value pairs to send along with requests
  152. * using the XMLHttpRequest transport.
  153. * @param {string} [options.method] - The HTTP method to use for the request.
  154. * @param {Object} [options.params] - An object of additional jQuery.ajax() settings key/value pairs.
  155. * @param {string} [options.server] - A server to which send the request.
  156. * @param {Function} [options.success] - A function to be called if the request succeeds.
  157. *
  158. * @returns {undefined}
  159. */
  160. ui.query = function (url, options) {
  161. // Force options to be an object
  162. const o = options || {};
  163. Object.keys(o).forEach((option) => {
  164. if (["complete", "data", "error", "errorMessage", "errorOnceId", "headers", "method", "params", "server",
  165. "statusCode", "success"]
  166. .indexOf(option) < 0) {
  167. throw new Error("Unknown option: " + option);
  168. }
  169. });
  170. let neighbours_status = [{
  171. name: "local",
  172. host: "local",
  173. url: "",
  174. }];
  175. o.server = o.server || ui.getSelector("selSrv");
  176. if (o.server === "All SERVERS") {
  177. queryServer(neighbours_status, 0, "neighbours", {
  178. success: function (json) {
  179. const [{data}] = json;
  180. if (jQuery.isEmptyObject(data)) {
  181. ui.neighbours = {
  182. local: {
  183. host: window.location.host,
  184. url: window.location.origin + window.location.pathname
  185. }
  186. };
  187. } else {
  188. ui.neighbours = data;
  189. }
  190. neighbours_status = [];
  191. $.each(ui.neighbours, (ind) => {
  192. neighbours_status.push({
  193. name: ind,
  194. host: ui.neighbours[ind].host,
  195. url: ui.neighbours[ind].url,
  196. });
  197. });
  198. $.each(neighbours_status, (ind) => {
  199. queryServer(neighbours_status, ind, url, o);
  200. });
  201. },
  202. errorMessage: "Cannot receive neighbours data"
  203. });
  204. } else {
  205. if (o.server !== "local") {
  206. neighbours_status = [{
  207. name: o.server,
  208. host: ui.neighbours[o.server].host,
  209. url: ui.neighbours[o.server].url,
  210. }];
  211. }
  212. queryServer(neighbours_status, 0, url, o);
  213. }
  214. };
  215. ui.escapeHTML = function (string) {
  216. const htmlEscaper = /[&<>"'/`=]/g;
  217. const htmlEscapes = {
  218. "&": "&amp;",
  219. "<": "&lt;",
  220. ">": "&gt;",
  221. "\"": "&quot;",
  222. "'": "&#39;",
  223. "/": "&#x2F;",
  224. "`": "&#x60;",
  225. "=": "&#x3D;"
  226. };
  227. return String(string).replace(htmlEscaper, (match) => htmlEscapes[match]);
  228. };
  229. ui.appendButtonsToFtFilterDropdown = (ftFilter) => {
  230. function button(text, classes, check) {
  231. return $("<button/>", {
  232. type: "button",
  233. class: "btn btn-xs " + classes,
  234. text: text,
  235. click: () => {
  236. const checkboxes = ftFilter.$dropdown.find(".checkbox input");
  237. return (check) ? checkboxes.attr("checked", "checked") : checkboxes.removeAttr("checked");
  238. }
  239. });
  240. }
  241. $("<div/>", {class: "d-flex justify-content-between footable-dropdown-btn-group"}).append(
  242. button("Check all", "btn-secondary", true),
  243. button("Uncheck all", "btn-outline-secondary ms-1")
  244. ).appendTo(ftFilter.$dropdown);
  245. };
  246. return ui;
  247. });