utils.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. (function () {
  2. let escapeMap = undefined;
  3. let createEscaper = undefined;
  4. const Cls = (this.Utils = class Utils {
  5. static initClass() {
  6. // _.escape from underscore: https://github.com/jashkenas/underscore/blob/1e68f06610fa4ecb7f2c45d1eb2ad0173d6a2cc1/underscore.js#L1411-L1436
  7. escapeMap = {
  8. "&": "&",
  9. "<": "&lt;",
  10. ">": "&gt;",
  11. '"': "&quot;",
  12. "'": "&#x27;",
  13. "`": "&#x60;",
  14. };
  15. createEscaper = function (map) {
  16. const escaper = (match) => map[match];
  17. // Regexes for identifying a key that needs to be escaped.
  18. const source = "(?:" + Object.keys(map).join("|") + ")";
  19. const testRegexp = RegExp(source);
  20. const replaceRegexp = RegExp(source, "g");
  21. return function (string) {
  22. string = string === null ? "" : "" + string;
  23. if (testRegexp.test(string)) {
  24. return string.replace(replaceRegexp, escaper);
  25. } else {
  26. return string;
  27. }
  28. };
  29. };
  30. this.escape = createEscaper(escapeMap);
  31. }
  32. static navigatePath(path) {
  33. if (!path.match(/^\//)) {
  34. path = "/" + path;
  35. }
  36. return (window.location.href = path);
  37. }
  38. static currentPath() {
  39. return window.location.href.replace(/https?:\/\/.*?\//g, "");
  40. }
  41. static registerPage(klass, options) {
  42. if (options == null) {
  43. options = {};
  44. }
  45. if (options.forPathsMatching != null) {
  46. if (Utils.currentPath().match(options.forPathsMatching)) {
  47. return (window.currentPage = new klass());
  48. }
  49. } else {
  50. return new klass();
  51. }
  52. }
  53. static showDynamicModal(content, param) {
  54. if (content == null) {
  55. content = "";
  56. }
  57. if (param == null) {
  58. param = {};
  59. }
  60. const { title, body, onHide } = param;
  61. $("body").append(`\
  62. <div class="modal fade" tabindex="-1" id='dynamic-modal' role="dialog" aria-labelledby="dynamic-modal-label" aria-hidden="true">
  63. <div class="modal-dialog modal-lg">
  64. <div class="modal-content">
  65. <div class="modal-header">
  66. <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
  67. <h4 class="modal-title" id="dynamic-modal-label"></h4>
  68. </div>
  69. <div class="modal-body">${content}</div>
  70. </div>
  71. </div>
  72. </div>\
  73. `);
  74. const modal = document.querySelector("#dynamic-modal");
  75. $(modal)
  76. .find(".modal-title")
  77. .text(title || "")
  78. .end()
  79. .on("hidden.bs.modal", function () {
  80. $("#dynamic-modal").remove();
  81. return typeof onHide === "function" ? onHide() : undefined;
  82. });
  83. if (typeof body === "function") {
  84. body(modal.querySelector(".modal-body"));
  85. }
  86. return $(modal).modal("show");
  87. }
  88. static handleDryRunButton(button, data) {
  89. if (data == null) {
  90. data = button.form
  91. ? $(':input[name!="_method"]', button.form).serialize()
  92. : "";
  93. }
  94. $(button).prop("disabled", true);
  95. const cleanup = () => $(button).prop("disabled", false);
  96. const url = $(button).data("action-url");
  97. const with_event_mode = $(button).data("with-event-mode");
  98. if (with_event_mode === "no") {
  99. return this.invokeDryRun(url, data, cleanup);
  100. }
  101. return $.ajax(url, {
  102. method: "GET",
  103. data: {
  104. with_event_mode,
  105. source_ids: $.map($(".link-region select option:selected"), (el) =>
  106. $(el).val()
  107. ),
  108. },
  109. success: (modal_data) => {
  110. return Utils.showDynamicModal(modal_data, {
  111. body: (body) => {
  112. let previous;
  113. const form = $(body).find(".dry-run-form");
  114. const payload_editor = form.find(".payload-editor");
  115. if ((previous = $(button).data("payload"))) {
  116. payload_editor.text(previous);
  117. }
  118. const editor = window.setupJsonEditor(payload_editor)[0];
  119. $(body)
  120. .find(".dry-run-event-sample")
  121. .click((e) => {
  122. e.preventDefault();
  123. editor.json = $(e.currentTarget).data("payload");
  124. return editor.rebuild();
  125. });
  126. form.submit((e) => {
  127. let dry_run_data;
  128. e.preventDefault();
  129. let json = $(e.target).find(".payload-editor").val();
  130. if (json === "") {
  131. json = "{}";
  132. }
  133. try {
  134. const payload = JSON.parse(
  135. json.replace(/\\\\([n|r|t])/g, "\\$1")
  136. );
  137. if (payload.constructor !== Object) {
  138. throw true;
  139. }
  140. if (Object.keys(payload).length === 0) {
  141. json = "";
  142. } else {
  143. json = JSON.stringify(payload);
  144. }
  145. } catch (error) {
  146. alert("Invalid JSON object.");
  147. return;
  148. }
  149. if (json === "") {
  150. if (with_event_mode === "yes") {
  151. alert("Event is required for this agent to run.");
  152. return;
  153. }
  154. dry_run_data = data;
  155. $(button).data("payload", null);
  156. } else {
  157. dry_run_data = `event=${encodeURIComponent(json)}&${data}`;
  158. $(button).data("payload", json);
  159. }
  160. return $(body)
  161. .closest("[role=dialog]")
  162. .on("hidden.bs.modal", () => {
  163. return this.invokeDryRun(url, dry_run_data, cleanup);
  164. })
  165. .modal("hide");
  166. });
  167. return $(body)
  168. .closest("[role=dialog]")
  169. .on("shown.bs.modal", function () {
  170. return $(this).find(".btn-primary").focus();
  171. });
  172. },
  173. title: "Dry Run",
  174. onHide: cleanup,
  175. });
  176. },
  177. });
  178. }
  179. static invokeDryRun(url, data, callback) {
  180. $("body").css({ cursor: "progress" });
  181. return $.ajax({ type: "POST", url, dataType: "html", data })
  182. .always(() => {
  183. return $("body").css({ cursor: "auto" });
  184. })
  185. .done((modal_data) => {
  186. return Utils.showDynamicModal(modal_data, {
  187. title: "Dry Run Results",
  188. onHide: callback,
  189. });
  190. })
  191. .fail(function (xhr, status, error) {
  192. alert("Error: " + error);
  193. return callback();
  194. });
  195. }
  196. static select2TagClickHandler(e, elem) {
  197. if (e.which === 1) {
  198. return (window.location = $(elem).attr("href"));
  199. } else {
  200. return window.open($(elem).attr("href"));
  201. }
  202. }
  203. });
  204. Cls.initClass();
  205. return Cls;
  206. })();