diff options
-rw-r--r-- | .eslintrc.json | 2 | ||||
-rw-r--r-- | interface/js/app/config.js | 189 | ||||
-rw-r--r-- | interface/js/app/graph.js | 36 | ||||
-rw-r--r-- | interface/js/app/history.js | 97 | ||||
-rw-r--r-- | interface/js/app/rspamd.js | 367 | ||||
-rw-r--r-- | interface/js/app/selectors.js | 121 | ||||
-rw-r--r-- | interface/js/app/stats.js | 12 | ||||
-rw-r--r-- | interface/js/app/symbols.js | 39 | ||||
-rw-r--r-- | interface/js/app/upload.js | 149 | ||||
-rw-r--r-- | interface/js/main.js | 16 |
10 files changed, 513 insertions, 515 deletions
diff --git a/.eslintrc.json b/.eslintrc.json index a2d754d5d..c224b5d00 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -28,7 +28,7 @@ "line-comment-position": "off", "logical-assignment-operators": ["error", "never"], "max-params": ["warn", 6], - "max-statements": ["warn", 50], + "max-statements": ["warn", 55], "max-statements-per-line": ["error", { "max": 2 }], "multiline-comment-style": "off", "multiline-ternary": ["error", "always-multiline"], diff --git a/interface/js/app/config.js b/interface/js/app/config.js index 71a59a34b..dd47578ae 100644 --- a/interface/js/app/config.js +++ b/interface/js/app/config.js @@ -22,12 +22,14 @@ THE SOFTWARE. */ -define(["jquery", "codejar", "linenumbers", "prism"], - function ($, CodeJar, withLineNumbers, Prism) { +/* global require */ + +define(["jquery", "app/rspamd"], + function ($, rspamd) { "use strict"; var ui = {}; - ui.getActions = function getActions(rspamd, checked_server) { + ui.getActions = function getActions(checked_server) { rspamd.query("actions", { success: function (data) { $("#actionsFormField").empty(); @@ -63,7 +65,7 @@ define(["jquery", "codejar", "linenumbers", "prism"], }); }; - ui.saveActions = function (rspamd, server) { + ui.saveActions = function (server) { function descending(arr) { var desc = true; var filtered = arr.filter(function (el) { @@ -113,7 +115,7 @@ define(["jquery", "codejar", "linenumbers", "prism"], } }; - ui.getMaps = function (rspamd, checked_server) { + ui.getMaps = function (checked_server) { var $listmaps = $("#listMaps"); $listmaps.closest(".card").hide(); rspamd.query("maps", { @@ -142,107 +144,108 @@ define(["jquery", "codejar", "linenumbers", "prism"], }); }; - ui.setup = function (rspamd) { - var jar = {}; - const editor = { - advanced: { - codejar: true, - elt: "div", - class: "editor language-clike", - readonly_attr: {contenteditable: false}, + + var jar = {}; + const editor = { + advanced: { + codejar: true, + elt: "div", + class: "editor language-clike", + readonly_attr: {contenteditable: false}, + }, + basic: { + elt: "textarea", + class: "form-control map-textarea", + readonly_attr: {readonly: true}, + } + }; + let mode = "advanced"; + + // Modal form for maps + $(document).on("click", "[data-bs-toggle=\"modal\"]", function () { + var checked_server = rspamd.getSelector("selSrv"); + var item = $(this).data("item"); + rspamd.query("getmap", { + headers: { + Map: item.map }, - basic: { - elt: "textarea", - class: "form-control map-textarea", - readonly_attr: {readonly: true}, - } - }; - let mode = "advanced"; - - // Modal form for maps - $(document).on("click", "[data-bs-toggle=\"modal\"]", function () { - var checked_server = rspamd.getSelector("selSrv"); - var item = $(this).data("item"); - rspamd.query("getmap", { - headers: { - Map: item.map - }, - success: function (data) { - // Highlighting a large amount of text is unresponsive - mode = (new Blob([data[0].data]).size > 5120) ? "basic" : $("input[name=editorMode]:checked").val(); + success: function (data) { + // Highlighting a large amount of text is unresponsive + mode = (new Blob([data[0].data]).size > 5120) ? "basic" : $("input[name=editorMode]:checked").val(); - $("<" + editor[mode].elt + ' id="editor" class="' + editor[mode].class + '" data-id="' + item.map + '">' + - "</" + editor[mode].elt + ">").appendTo("#modalBody"); + $("<" + editor[mode].elt + ' id="editor" class="' + editor[mode].class + '" data-id="' + item.map + '">' + + "</" + editor[mode].elt + ">").appendTo("#modalBody"); - if (editor[mode].codejar) { + if (editor[mode].codejar) { + require(["codejar", "linenumbers", "prism"], function (CodeJar, withLineNumbers, Prism) { jar = new CodeJar( document.querySelector("#editor"), withLineNumbers((el) => Prism.highlightElement(el)) ); jar.updateCode(data[0].data); - } else { - document.querySelector("#editor").innerHTML = rspamd.escapeHTML(data[0].data); - } - - var icon = "fa-edit"; - if (item.editable === false || rspamd.read_only) { - $("#editor").attr(editor[mode].readonly_attr); - icon = "fa-eye"; - $("#modalSaveGroup").hide(); - } else { - $("#modalSaveGroup").show(); - } - $("#modalDialog .modal-header").find("[data-fa-i2svg]").addClass(icon); - $("#modalTitle").html(item.uri); + }); + } else { + document.querySelector("#editor").innerHTML = rspamd.escapeHTML(data[0].data); + } - $("#modalDialog").modal("show"); - }, - errorMessage: "Cannot receive maps data", - server: (checked_server === "All SERVERS") ? "local" : checked_server - }); - return false; - }); - $("#modalDialog").on("hidden.bs.modal", function () { - if (editor[mode].codejar) { - jar.destroy(); - $(".codejar-wrap").remove(); - } else { - $("#editor").remove(); - } - }); + var icon = "fa-edit"; + if (item.editable === false || rspamd.read_only) { + $("#editor").attr(editor[mode].readonly_attr); + icon = "fa-eye"; + $("#modalSaveGroup").hide(); + } else { + $("#modalSaveGroup").show(); + } + $("#modalDialog .modal-header").find("[data-fa-i2svg]").addClass(icon); + $("#modalTitle").html(item.uri); - $("#saveActionsBtn").on("click", function () { - ui.saveActions(rspamd); - }); - $("#saveActionsClusterBtn").on("click", function () { - ui.saveActions(rspamd, "All SERVERS"); + $("#modalDialog").modal("show"); + }, + errorMessage: "Cannot receive maps data", + server: (checked_server === "All SERVERS") ? "local" : checked_server }); - - function saveMap(server) { - rspamd.query("savemap", { - success: function () { - rspamd.alertMessage("alert-success", "Map data successfully saved"); - $("#modalDialog").modal("hide"); - }, - errorMessage: "Save map error", - method: "POST", - headers: { - Map: $("#editor").data("id"), - }, - params: { - data: editor[mode].codejar ? jar.toString() : $("#editor").val(), - dataType: "text", - }, - server: server - }); + return false; + }); + $("#modalDialog").on("hidden.bs.modal", function () { + if (editor[mode].codejar) { + jar.destroy(); + $(".codejar-wrap").remove(); + } else { + $("#editor").remove(); } - $("#modalSave").on("click", function () { - saveMap(); - }); - $("#modalSaveAll").on("click", function () { - saveMap("All SERVERS"); + }); + + $("#saveActionsBtn").on("click", function () { + ui.saveActions(); + }); + $("#saveActionsClusterBtn").on("click", function () { + ui.saveActions("All SERVERS"); + }); + + function saveMap(server) { + rspamd.query("savemap", { + success: function () { + rspamd.alertMessage("alert-success", "Map data successfully saved"); + $("#modalDialog").modal("hide"); + }, + errorMessage: "Save map error", + method: "POST", + headers: { + Map: $("#editor").data("id"), + }, + params: { + data: editor[mode].codejar ? jar.toString() : $("#editor").val(), + dataType: "text", + }, + server: server }); - }; + } + $("#modalSave").on("click", function () { + saveMap(); + }); + $("#modalSaveAll").on("click", function () { + saveMap("All SERVERS"); + }); return ui; }); diff --git a/interface/js/app/graph.js b/interface/js/app/graph.js index 16fb338a2..3dca7da9c 100644 --- a/interface/js/app/graph.js +++ b/interface/js/app/graph.js @@ -23,10 +23,10 @@ THE SOFTWARE. */ -/* global d3, FooTable */ +/* global FooTable */ -define(["jquery", "d3evolution", "d3pie", "footable"], - function ($, D3Evolution, D3Pie) { +define(["jquery", "app/rspamd", "d3evolution", "d3pie", "d3", "footable"], + function ($, rspamd, D3Evolution, D3Pie, d3) { "use strict"; var rrd_pie_config = { @@ -59,7 +59,7 @@ define(["jquery", "d3evolution", "d3pie", "footable"], var ui = {}; var prevUnit = "msg/s"; - ui.draw = function (rspamd, graphs, tables, neighbours, checked_server, type) { + ui.draw = function (graphs, neighbours, checked_server, type) { var graph_options = { title: "Rspamd throughput", width: 1060, @@ -126,7 +126,7 @@ define(["jquery", "d3evolution", "d3pie", "footable"], } function initSummaryTable(rows, unit) { - tables.rrd_summary = FooTable.init("#rrd-table", { + rspamd.tables.rrd_summary = FooTable.init("#rrd-table", { sorting: { enabled: true }, @@ -152,8 +152,8 @@ define(["jquery", "d3evolution", "d3pie", "footable"], } function drawRrdTable(rows, unit) { - if (Object.prototype.hasOwnProperty.call(tables, "rrd_summary")) { - $.each(tables.rrd_summary.rows.all, function (i, row) { + if (Object.prototype.hasOwnProperty.call(rspamd.tables, "rrd_summary")) { + $.each(rspamd.tables.rrd_summary.rows.all, function (i, row) { row.val(rows[i], false, true); }); } else { @@ -199,6 +199,7 @@ define(["jquery", "d3evolution", "d3pie", "footable"], graphs.graph = initGraph(); } + rspamd.query("graph", { success: function (req_data) { var data = null; @@ -243,19 +244,16 @@ define(["jquery", "d3evolution", "d3pie", "footable"], }); }; - ui.setup = function (rspamd) { - // Handling mouse events on overlapping elements - $("#rrd-pie").mouseover(function () { - $("#rrd-pie,#rrd-pie-tooltip").css("z-index", "200"); - $("#rrd-table_toggle").css("z-index", "300"); - }); - $("#rrd-table_toggle").mouseover(function () { - $("#rrd-pie,#rrd-pie-tooltip").css("z-index", "0"); - $("#rrd-table_toggle").css("z-index", "0"); - }); - return rspamd.getSelector("selData"); - }; + // Handling mouse events on overlapping elements + $("#rrd-pie").mouseover(function () { + $("#rrd-pie,#rrd-pie-tooltip").css("z-index", "200"); + $("#rrd-table_toggle").css("z-index", "300"); + }); + $("#rrd-table_toggle").mouseover(function () { + $("#rrd-pie,#rrd-pie-tooltip").css("z-index", "0"); + $("#rrd-table_toggle").css("z-index", "0"); + }); return ui; }); diff --git a/interface/js/app/history.js b/interface/js/app/history.js index 3770f9457..4118bc61d 100644 --- a/interface/js/app/history.js +++ b/interface/js/app/history.js @@ -22,15 +22,15 @@ THE SOFTWARE. */ -/* global d3, FooTable */ +/* global FooTable */ -define(["jquery", "footable"], - function ($) { +define(["jquery", "app/rspamd", "d3", "footable"], + function ($, rspamd, d3) { "use strict"; var ui = {}; var prevVersion = null; - function process_history_legacy(rspamd, data) { + function process_history_legacy(data) { var items = []; var compare = function (e1, e2) { @@ -41,7 +41,7 @@ define(["jquery", "footable"], $.each(data, function (i, item) { item.time = rspamd.unix_time_format(item.unix_time); - rspamd.preprocess_item(rspamd, item); + rspamd.preprocess_item(item); item.symbols = Object.keys(item.symbols) .map(function (key) { return item.symbols[key]; @@ -292,7 +292,7 @@ define(["jquery", "footable"], legacy: columns_legacy }; - function process_history_data(rspamd, data) { + function process_history_data(data) { var process_functions = { 2: rspamd.process_history_v2, legacy: process_history_legacy @@ -306,7 +306,7 @@ define(["jquery", "footable"], } } - return pf(rspamd, data, "history"); + return pf(data, "history"); } function get_history_columns(data) { @@ -322,7 +322,7 @@ define(["jquery", "footable"], return func(); } - ui.getHistory = function (rspamd, tables) { + ui.getHistory = function () { rspamd.query("history", { success: function (req_data) { function differentVersions(neighbours_data) { @@ -355,18 +355,18 @@ define(["jquery", "footable"], data = [].concat.apply([], neighbours_data); $("#legacy-history-badge").show(); } - var o = process_history_data(rspamd, data); + var o = process_history_data(data); var items = o.items; rspamd.symbols.history = o.symbols; - if (Object.prototype.hasOwnProperty.call(tables, "history") && + if (Object.prototype.hasOwnProperty.call(rspamd.tables, "history") && version === prevVersion) { - tables.history.rows.load(items); + rspamd.tables.history.rows.load(items); } else { rspamd.destroyTable("history"); // Is there a way to get an event when the table is destroyed? setTimeout(function () { - rspamd.initHistoryTable(rspamd, data, items, "history", get_history_columns(data), false); + rspamd.initHistoryTable(data, items, "history", get_history_columns(data), false); }, 200); } prevVersion = version; @@ -379,38 +379,8 @@ define(["jquery", "footable"], }); }; - ui.setup = function (rspamd, tables) { - rspamd.set_page_size("history", $("#history_page_size").val()); - rspamd.bindHistoryTableEventHandlers("history", 8); - - $("#updateHistory").off("click"); - $("#updateHistory").on("click", function (e) { - e.preventDefault(); - ui.getHistory(rspamd, tables); - }); - - // @reset history log - $("#resetHistory").off("click"); - $("#resetHistory").on("click", function (e) { - e.preventDefault(); - if (!confirm("Are you sure you want to reset history log?")) { // eslint-disable-line no-alert - return; - } - rspamd.destroyTable("history"); - rspamd.destroyTable("errors"); - - rspamd.query("historyreset", { - success: function () { - ui.getHistory(rspamd, tables); - ui.getErrors(rspamd, tables); - }, - errorMessage: "Cannot reset history log" - }); - }); - }; - - function initErrorsTable(rspamd, tables, rows) { - tables.errors = FooTable.init("#errorsLog", { + function initErrorsTable(rows) { + rspamd.tables.errors = FooTable.init("#errorsLog", { columns: [ { sorted: true, @@ -443,7 +413,7 @@ define(["jquery", "footable"], }); } - ui.getErrors = function (rspamd, tables) { + ui.getErrors = function () { if (rspamd.read_only) return; rspamd.query("errors", { @@ -464,10 +434,10 @@ define(["jquery", "footable"], } }; }); - if (Object.prototype.hasOwnProperty.call(tables, "errors")) { - tables.errors.rows.load(rows); + if (Object.prototype.hasOwnProperty.call(rspamd.tables, "errors")) { + rspamd.tables.errors.rows.load(rows); } else { - initErrorsTable(rspamd, tables, rows); + initErrorsTable(rows); } } }); @@ -475,9 +445,38 @@ define(["jquery", "footable"], $("#updateErrors").off("click"); $("#updateErrors").on("click", function (e) { e.preventDefault(); - ui.getErrors(rspamd, tables); + ui.getErrors(); }); }; + + rspamd.set_page_size("history", $("#history_page_size").val()); + rspamd.bindHistoryTableEventHandlers("history", 8); + + $("#updateHistory").off("click"); + $("#updateHistory").on("click", function (e) { + e.preventDefault(); + ui.getHistory(); + }); + + // @reset history log + $("#resetHistory").off("click"); + $("#resetHistory").on("click", function (e) { + e.preventDefault(); + if (!confirm("Are you sure you want to reset history log?")) { // eslint-disable-line no-alert + return; + } + rspamd.destroyTable("history"); + rspamd.destroyTable("errors"); + + rspamd.query("historyreset", { + success: function () { + ui.getHistory(); + ui.getErrors(); + }, + errorMessage: "Cannot reset history log" + }); + }); + return ui; }); diff --git a/interface/js/app/rspamd.js b/interface/js/app/rspamd.js index 634dfcd1d..faec47f7f 100644 --- a/interface/js/app/rspamd.js +++ b/interface/js/app/rspamd.js @@ -23,13 +23,11 @@ THE SOFTWARE. */ -/* global jQuery, FooTable, Visibility */ +/* global jQuery, FooTable, require, Visibility */ -define(["jquery", "visibility", "nprogress", "stickytabs", "app/stats", "app/graph", "app/config", - "app/symbols", "app/history", "app/upload", "app/selectors"], -// eslint-disable-next-line max-params -function ($, visibility, NProgress, stickyTabs, tab_stat, tab_graph, tab_config, - tab_symbols, tab_history, tab_upload, tab_selectors) { +define(["jquery", "nprogress", "stickytabs", "visibility", + "bootstrap", "fontawesome"], +function ($, NProgress) { "use strict"; var ui = { chartLegend: [ @@ -62,7 +60,6 @@ function ($, visibility, NProgress, stickyTabs, tab_stat, tab_graph, tab_config, let pageSizeTimerId = null; let pageSizeInvocationCounter = 0; var locale = (localStorage.getItem("selected_locale") === "custom") ? localStorage.getItem("custom_locale") : null; - var selData = null; // Graph's dataset selector state NProgress.configure({ minimum: 0.01, @@ -111,6 +108,12 @@ function ($, visibility, NProgress, stickyTabs, tab_stat, tab_graph, tab_config, ui.connect(); } + // Get selectors' current state + function getSelector(id) { + var e = document.getElementById(id); + return e.options[e.selectedIndex].value; + } + function tabClick(id) { var tab_id = id; if ($(id).attr("disabled")) return; @@ -164,19 +167,20 @@ function ($, visibility, NProgress, stickyTabs, tab_stat, tab_graph, tab_config, switch (tab_id) { case "#status_nav": - (function () { + require(["app/stats"], (module) => { var refreshInterval = $(".dropdown-menu a.active.preset").data("value"); setAutoRefresh(refreshInterval, "status", - function () { return tab_stat.statWidgets(ui, graphs, checked_server); }); - if (id !== "#autoRefresh") tab_stat.statWidgets(ui, graphs, checked_server); + function () { return module.statWidgets(graphs, checked_server); }); + if (id !== "#autoRefresh") module.statWidgets(graphs, checked_server); $(".preset").show(); $(".history").hide(); $(".dynamic").hide(); - }()); + }); break; case "#throughput_nav": - (function () { + require(["app/graph"], (module) => { + const selData = getSelector("selData"); // Graph's dataset selector state var step = { day: 60000, week: 300000 @@ -188,26 +192,34 @@ function ($, visibility, NProgress, stickyTabs, tab_stat, tab_graph, tab_config, refreshInterval = null; } setAutoRefresh(refreshInterval, "throughput", - function () { return tab_graph.draw(ui, graphs, tables, neighbours, checked_server, selData); }); - if (id !== "#autoRefresh") tab_graph.draw(ui, graphs, tables, neighbours, checked_server, selData); + function () { return module.draw(graphs, neighbours, checked_server, selData); }); + if (id !== "#autoRefresh") module.draw(graphs, neighbours, checked_server, selData); $(".preset").hide(); $(".history").hide(); $(".dynamic").show(); - }()); + }); break; case "#configuration_nav": - tab_config.getActions(ui, checked_server); - tab_config.getMaps(ui, checked_server); + require(["app/config"], (module) => { + module.getActions(checked_server); + module.getMaps(checked_server); + }); break; case "#symbols_nav": - tab_symbols.getSymbols(ui, tables, checked_server); + require(["app/symbols"], (module) => module.getSymbols(checked_server)); + break; + case "#scan_nav": + require(["app/upload"]); + break; + case "#selectors_nav": + require(["app/selectors"], (module) => module.displayUI()); break; case "#history_nav": - (function () { + require(["app/history"], (module) => { function getHistoryAndErrors() { - tab_history.getHistory(ui, tables); - tab_history.getErrors(ui, tables); + module.getHistory(); + module.getErrors(); } var refreshInterval = $(".dropdown-menu a.active.history").data("value"); setAutoRefresh(refreshInterval, "history", @@ -217,7 +229,7 @@ function ($, visibility, NProgress, stickyTabs, tab_stat, tab_graph, tab_config, $(".preset").hide(); $(".history").show(); $(".dynamic").hide(); - }()); + }); break; case "#disconnect": disconnect(); @@ -237,12 +249,6 @@ function ($, visibility, NProgress, stickyTabs, tab_stat, tab_graph, tab_config, return sessionStorage.getItem("Password"); } - // Get selectors' current state - function getSelector(id) { - var e = document.getElementById(id); - return e.options[e.selectedIndex].value; - } - function get_compare_function(table) { var compare_functions = { magnitude: function (e1, e2) { @@ -319,7 +325,6 @@ function ($, visibility, NProgress, stickyTabs, tab_stat, tab_graph, tab_config, $('#selSrv [value="' + e.name + '"]').prop("disabled", true); } }); - if (!ui.read_only) tab_selectors.displayUI(ui); }, complete: function () { ajaxSetup(localStorage.getItem("ajax_timeout")); @@ -434,157 +439,6 @@ function ($, visibility, NProgress, stickyTabs, tab_stat, tab_graph, tab_config, // Public functions ui.alertMessage = alertMessage; - ui.setup = function () { - (function initSettings() { - var selected_locale = null; - var custom_locale = null; - const localeTextbox = ".popover #settings-popover #locale"; - - function validateLocale(saveToLocalStorage) { - function toggle_form_group_class(remove, add) { - $(localeTextbox).removeClass("is-" + remove).addClass("is-" + add); - } - - var now = new Date(); - - if (custom_locale.length) { - try { - now.toLocaleString(custom_locale); - - if (saveToLocalStorage) localStorage.setItem("custom_locale", custom_locale); - locale = (selected_locale === "custom") ? custom_locale : null; - toggle_form_group_class("invalid", "valid"); - } catch (err) { - locale = null; - toggle_form_group_class("valid", "invalid"); - } - } else { - if (saveToLocalStorage) localStorage.setItem("custom_locale", null); - locale = null; - $(localeTextbox).removeClass("is-valid is-invalid"); - } - - // Display date example - $(".popover #settings-popover #date-example").text( - (locale) - ? now.toLocaleString(locale) - : now.toLocaleString() - ); - } - - $("#settings").popover({ - container: "body", - placement: "bottom", - html: true, - sanitize: false, - content: function () { - // Using .clone() has the side-effect of producing elements with duplicate id attributes. - return $("#settings-popover").clone(); - } - // Restore the tooltip of the element that the popover is attached to. - }).attr("title", function () { - return $(this).attr("data-original-title"); - }); - $("#settings").on("click", function (e) { - e.preventDefault(); - }); - $("#settings").on("inserted.bs.popover", function () { - selected_locale = localStorage.getItem("selected_locale") || "browser"; - custom_locale = localStorage.getItem("custom_locale") || ""; - validateLocale(); - - $('.popover #settings-popover input:radio[name="locale"]').val([selected_locale]); - $(localeTextbox).val(custom_locale); - - ajaxSetup(localStorage.getItem("ajax_timeout"), true); - }); - $(document).on("change", '.popover #settings-popover input:radio[name="locale"]', function () { - selected_locale = this.value; - localStorage.setItem("selected_locale", selected_locale); - validateLocale(); - }); - $(document).on("input", localeTextbox, function () { - custom_locale = $(localeTextbox).val(); - validateLocale(true); - }); - $(document).on("input", ajaxTimeoutBox, function () { - ajaxSetup($(ajaxTimeoutBox).val(), false, true); - }); - $(document).on("click", ".popover #settings-popover #ajax-timeout-restore", function () { - ajaxSetup(null, true, true); - }); - - // Dismiss Bootstrap popover by clicking outside - $("body").on("click", function (e) { - $(".popover").each(function () { - if ( - // Popover's descendant - $(this).has(e.target).length || - // Button (or icon within a button) that triggers the popover. - $(e.target).closest("button").attr("aria-describedby") === this.id - ) return; - $("#settings").popover("hide"); - }); - }); - }()); - - $("#selData").change(function () { - selData = this.value; - tabClick("#throughput_nav"); - }); - - $(document).ajaxStart(function () { - $("#refresh > svg").addClass("fa-spin"); - }); - $(document).ajaxComplete(function () { - setTimeout(function () { - $("#refresh > svg").removeClass("fa-spin"); - }, 1000); - }); - - $('a[data-bs-toggle="tab"]').on("shown.bs.tab", function () { - tabClick("#" + $(this).attr("id")); - }); - $("#refresh, #disconnect").on("click", function (e) { - e.preventDefault(); - tabClick("#" + $(this).attr("id")); - }); - $(".dropdown-menu a").click(function (e) { - e.preventDefault(); - var classList = $(this).attr("class"); - var menuClass = (/\b(?:dynamic|history|preset)\b/).exec(classList)[0]; - $(".dropdown-menu a.active." + menuClass).removeClass("active"); - $(this).addClass("active"); - tabClick("#autoRefresh"); - }); - - $("#selSrv").change(function () { - checked_server = this.value; - $("#selSrv [value=\"" + checked_server + "\"]").prop("checked", true); - if (checked_server === "All SERVERS") { - $("#learnServers").show(); - } else { - $("#learnServers").hide(); - } - tabClick("#" + $("#tablist > .nav-item > .nav-link.active").attr("id")); - }); - - // Radio buttons - $(document).on("click", "input:radio[name=\"clusterName\"]", function () { - if (!this.disabled) { - checked_server = this.value; - tabClick("#status_nav"); - } - }); - tab_config.setup(ui); - tab_history.setup(ui, tables); - tab_selectors.setup(ui); - tab_symbols.setup(ui, tables); - tab_upload.setup(ui, tables); - selData = tab_graph.setup(ui); - - $("#loading").addClass("d-none"); - }; ui.connect = function () { // Prevent locking out of the WebUI if timeout is too low. @@ -749,6 +603,7 @@ function ($, visibility, NProgress, stickyTabs, tab_stat, tab_graph, tab_config, // Scan and History shared functions + ui.tables = tables; ui.unix_time_format = unix_time_format; ui.set_page_size = set_page_size; @@ -782,7 +637,7 @@ function ($, visibility, NProgress, stickyTabs, tab_stat, tab_graph, tab_config, }; - ui.initHistoryTable = function (rspamd, data, items, table, columns, expandFirst) { + ui.initHistoryTable = function (data, items, table, columns, expandFirst) { /* eslint-disable no-underscore-dangle */ FooTable.Cell.extend("collapse", function () { // call the original method @@ -911,7 +766,7 @@ function ($, visibility, NProgress, stickyTabs, tab_stat, tab_graph, tab_config, }); }; - ui.preprocess_item = function (rspamd, item) { + ui.preprocess_item = function (item) { function escape_HTML_array(arr) { arr.forEach(function (d, i) { arr[i] = ui.escapeHTML(d); }); } @@ -968,7 +823,7 @@ function ($, visibility, NProgress, stickyTabs, tab_stat, tab_graph, tab_config, }; }; - ui.process_history_v2 = function (rspamd, data, table) { + ui.process_history_v2 = function (data, table) { // Display no more than rcpt_lim recipients var rcpt_lim = 3; var items = []; @@ -1014,7 +869,7 @@ function ($, visibility, NProgress, stickyTabs, tab_stat, tab_graph, tab_config, return null; } - rspamd.preprocess_item(rspamd, item); + ui.preprocess_item(item); Object.values(item.symbols).forEach(function (sym) { sym.str = '<span class="symbol-default ' + get_symbol_class(sym.name, sym.score) + '"><strong>'; @@ -1079,5 +934,149 @@ function ($, visibility, NProgress, stickyTabs, tab_stat, tab_graph, tab_config, return null; }; + + (function initSettings() { + var selected_locale = null; + var custom_locale = null; + const localeTextbox = ".popover #settings-popover #locale"; + + function validateLocale(saveToLocalStorage) { + function toggle_form_group_class(remove, add) { + $(localeTextbox).removeClass("is-" + remove).addClass("is-" + add); + } + + var now = new Date(); + + if (custom_locale.length) { + try { + now.toLocaleString(custom_locale); + + if (saveToLocalStorage) localStorage.setItem("custom_locale", custom_locale); + locale = (selected_locale === "custom") ? custom_locale : null; + toggle_form_group_class("invalid", "valid"); + } catch (err) { + locale = null; + toggle_form_group_class("valid", "invalid"); + } + } else { + if (saveToLocalStorage) localStorage.setItem("custom_locale", null); + locale = null; + $(localeTextbox).removeClass("is-valid is-invalid"); + } + + // Display date example + $(".popover #settings-popover #date-example").text( + (locale) + ? now.toLocaleString(locale) + : now.toLocaleString() + ); + } + + $("#settings").popover({ + container: "body", + placement: "bottom", + html: true, + sanitize: false, + content: function () { + // Using .clone() has the side-effect of producing elements with duplicate id attributes. + return $("#settings-popover").clone(); + } + // Restore the tooltip of the element that the popover is attached to. + }).attr("title", function () { + return $(this).attr("data-original-title"); + }); + $("#settings").on("click", function (e) { + e.preventDefault(); + }); + $("#settings").on("inserted.bs.popover", function () { + selected_locale = localStorage.getItem("selected_locale") || "browser"; + custom_locale = localStorage.getItem("custom_locale") || ""; + validateLocale(); + + $('.popover #settings-popover input:radio[name="locale"]').val([selected_locale]); + $(localeTextbox).val(custom_locale); + + ajaxSetup(localStorage.getItem("ajax_timeout"), true); + }); + $(document).on("change", '.popover #settings-popover input:radio[name="locale"]', function () { + selected_locale = this.value; + localStorage.setItem("selected_locale", selected_locale); + validateLocale(); + }); + $(document).on("input", localeTextbox, function () { + custom_locale = $(localeTextbox).val(); + validateLocale(true); + }); + $(document).on("input", ajaxTimeoutBox, function () { + ajaxSetup($(ajaxTimeoutBox).val(), false, true); + }); + $(document).on("click", ".popover #settings-popover #ajax-timeout-restore", function () { + ajaxSetup(null, true, true); + }); + + // Dismiss Bootstrap popover by clicking outside + $("body").on("click", function (e) { + $(".popover").each(function () { + if ( + // Popover's descendant + $(this).has(e.target).length || + // Button (or icon within a button) that triggers the popover. + $(e.target).closest("button").attr("aria-describedby") === this.id + ) return; + $("#settings").popover("hide"); + }); + }); + }()); + + $("#selData").change(function () { + tabClick("#throughput_nav"); + }); + + $(document).ajaxStart(function () { + $("#refresh > svg").addClass("fa-spin"); + }); + $(document).ajaxComplete(function () { + setTimeout(function () { + $("#refresh > svg").removeClass("fa-spin"); + }, 1000); + }); + + $('a[data-bs-toggle="tab"]').on("shown.bs.tab", function () { + tabClick("#" + $(this).attr("id")); + }); + $("#refresh, #disconnect").on("click", function (e) { + e.preventDefault(); + tabClick("#" + $(this).attr("id")); + }); + $(".dropdown-menu a").click(function (e) { + e.preventDefault(); + var classList = $(this).attr("class"); + var menuClass = (/\b(?:dynamic|history|preset)\b/).exec(classList)[0]; + $(".dropdown-menu a.active." + menuClass).removeClass("active"); + $(this).addClass("active"); + tabClick("#autoRefresh"); + }); + + $("#selSrv").change(function () { + checked_server = this.value; + $("#selSrv [value=\"" + checked_server + "\"]").prop("checked", true); + if (checked_server === "All SERVERS") { + $("#learnServers").show(); + } else { + $("#learnServers").hide(); + } + tabClick("#" + $("#tablist > .nav-item > .nav-link.active").attr("id")); + }); + + // Radio buttons + $(document).on("click", "input:radio[name=\"clusterName\"]", function () { + if (!this.disabled) { + checked_server = this.value; + tabClick("#status_nav"); + } + }); + + $("#loading").addClass("d-none"); + return ui; }); diff --git a/interface/js/app/selectors.js b/interface/js/app/selectors.js index 8c7e5de76..8e9da052b 100644 --- a/interface/js/app/selectors.js +++ b/interface/js/app/selectors.js @@ -1,5 +1,5 @@ -define(["jquery"], - function ($) { +define(["jquery", "app/rspamd"], + function ($, rspamd) { "use strict"; var ui = {}; @@ -10,12 +10,12 @@ define(["jquery"], )); } - function get_server(rspamd) { + function get_server() { var checked_server = rspamd.getSelector("selSrv"); return (checked_server === "All SERVERS") ? "local" : checked_server; } - function checkMsg(rspamd, data) { + function checkMsg(data) { var selector = $("#selectorsSelArea").val(); rspamd.query("plugins/selectors/check_message?selector=" + encodeURIComponent(selector), { data: data, @@ -30,17 +30,17 @@ define(["jquery"], rspamd.alertMessage("alert-error", "Unexpected error processing message"); } }, - server: get_server(rspamd) + server: get_server() }); } - function checkSelectors(rspamd) { + function checkSelectors() { function toggle_form_group_class(remove, add) { $("#selectorsSelArea").removeClass("is-" + remove).addClass("is-" + add); enable_disable_check_btn(); } var selector = $("#selectorsSelArea").val(); - if (selector.length) { + if (selector.length && !rspamd.read_only ) { rspamd.query("plugins/selectors/check_selector?selector=" + encodeURIComponent(selector), { method: "GET", success: function (json) { @@ -50,7 +50,7 @@ define(["jquery"], toggle_form_group_class("valid", "invalid"); } }, - server: get_server(rspamd) + server: get_server() }); } else { $("#selectorsSelArea").removeClass("is-valid is-invalid"); @@ -58,7 +58,7 @@ define(["jquery"], } } - function buildLists(rspamd) { + function buildLists() { function build_table_from_json(json, table_id) { Object.keys(json).forEach(function (key) { var td = $("<td/>"); @@ -76,7 +76,7 @@ define(["jquery"], var json = neighbours_status[0].data; build_table_from_json(json, "#selectorsTable-" + list); }, - server: get_server(rspamd) + server: get_server() }); } @@ -84,61 +84,62 @@ define(["jquery"], getList("transforms"); } - ui.displayUI = function (rspamd) { - buildLists(rspamd); - checkSelectors(rspamd); + ui.displayUI = function () { + if (!rspamd.read_only && + !$("#selectorsTable-extractors>tbody>tr").length && + !$("#selectorsTable-transforms>tbody>tr").length) buildLists(); + if (!$("#selectorsSelArea").is(".is-valid, .is-invalid")) checkSelectors(); }; - ui.setup = function (rspamd) { - function toggleSidebar(side) { - $("#sidebar-" + side).toggleClass("collapsed"); - var contentClass = "col-lg-6"; - var openSidebarsCount = $("#sidebar-left").hasClass("collapsed") + - $("#sidebar-right").hasClass("collapsed"); - switch (openSidebarsCount) { - case 1: - contentClass = "col-lg-9"; - break; - case 2: - contentClass = "col-lg-12"; - break; - default: - } - $("#content").removeClass("col-lg-12 col-lg-9 col-lg-6") - .addClass(contentClass); + + function toggleSidebar(side) { + $("#sidebar-" + side).toggleClass("collapsed"); + var contentClass = "col-lg-6"; + var openSidebarsCount = $("#sidebar-left").hasClass("collapsed") + + $("#sidebar-right").hasClass("collapsed"); + switch (openSidebarsCount) { + case 1: + contentClass = "col-lg-9"; + break; + case 2: + contentClass = "col-lg-12"; + break; + default: } - $("#sidebar-tab-left>a").click(function () { - toggleSidebar("left"); - return false; - }); - $("#sidebar-tab-right>a").click(function () { - toggleSidebar("right"); - return false; - }); + $("#content").removeClass("col-lg-12 col-lg-9 col-lg-6") + .addClass(contentClass); + } + $("#sidebar-tab-left>a").click(function () { + toggleSidebar("left"); + return false; + }); + $("#sidebar-tab-right>a").click(function () { + toggleSidebar("right"); + return false; + }); - $("#selectorsMsgClean").on("click", function () { - $("#selectorsChkMsgBtn").attr("disabled", true); - $("#selectorsMsgArea").val(""); - return false; - }); - $("#selectorsClean").on("click", function () { - $("#selectorsSelArea").val(""); - checkSelectors(rspamd); - return false; - }); - $("#selectorsChkMsgBtn").on("click", function () { - $("#selectorsResArea").val(""); - checkMsg(rspamd, $("#selectorsMsgArea").val()); - return false; - }); + $("#selectorsMsgClean").on("click", function () { + $("#selectorsChkMsgBtn").attr("disabled", true); + $("#selectorsMsgArea").val(""); + return false; + }); + $("#selectorsClean").on("click", function () { + $("#selectorsSelArea").val(""); + checkSelectors(); + return false; + }); + $("#selectorsChkMsgBtn").on("click", function () { + $("#selectorsResArea").val(""); + checkMsg($("#selectorsMsgArea").val()); + return false; + }); - $("#selectorsMsgArea").on("input", function () { - enable_disable_check_btn(); - }); - $("#selectorsSelArea").on("input", function () { - checkSelectors(rspamd); - }); - }; + $("#selectorsMsgArea").on("input", function () { + enable_disable_check_btn(); + }); + $("#selectorsSelArea").on("input", function () { + checkSelectors(); + }); return ui; }); diff --git a/interface/js/app/stats.js b/interface/js/app/stats.js index d023f955e..f2460c816 100644 --- a/interface/js/app/stats.js +++ b/interface/js/app/stats.js @@ -22,10 +22,8 @@ THE SOFTWARE. */ -/* global d3 */ - -define(["jquery", "d3pie"], - function ($, D3Pie) { +define(["jquery", "app/rspamd", "d3pie", "d3"], + function ($, rspamd, D3Pie, d3) { "use strict"; // @ ms to date function msToTime(seconds) { @@ -222,7 +220,7 @@ define(["jquery", "d3pie"], } } - function getChart(rspamd, graphs, checked_server) { + function getChart(graphs, checked_server) { if (!graphs.chart) { graphs.chart = new D3Pie("chart", { labels: { @@ -264,7 +262,7 @@ define(["jquery", "d3pie"], // Public API var ui = { - statWidgets: function (rspamd, graphs, checked_server) { + statWidgets: function (graphs, checked_server) { rspamd.query("stat", { success: function (neighbours_status) { var neighbours_sum = { @@ -354,7 +352,7 @@ define(["jquery", "d3pie"], to_Credentials["All SERVERS"].data = neighbours_sum; sessionStorage.setItem("Credentials", JSON.stringify(to_Credentials)); displayStatWidgets(checked_server); - getChart(rspamd, graphs, checked_server); + getChart(graphs, checked_server); }); }, promises.length ? 100 : 0); }, diff --git a/interface/js/app/symbols.js b/interface/js/app/symbols.js index ed9966b34..8718599d7 100644 --- a/interface/js/app/symbols.js +++ b/interface/js/app/symbols.js @@ -24,12 +24,12 @@ /* global FooTable */ -define(["jquery", "footable"], - function ($) { +define(["jquery", "app/rspamd", "footable"], + function ($, rspamd) { "use strict"; var ui = {}; - function saveSymbols(rspamd, action, id, server) { + function saveSymbols(action, id, server) { var inputs = $("#" + id + " :input[data-role=\"numerictextbox\"]"); var url = action; var values = []; @@ -57,7 +57,7 @@ define(["jquery", "footable"], var digits = Number(number).toFixed(20).replace(/^-?\d*\.?|0+$/g, "").length; return (digits === 0 || digits > 4) ? 0.1 : 1.0 / Math.pow(10, digits); } - function process_symbols_data(rspamd, data) { + function process_symbols_data(data) { var items = []; var lookup = {}; var freqs = []; @@ -138,11 +138,11 @@ define(["jquery", "footable"], return [items, distinct_groups]; } // @get symbols into modal form - ui.getSymbols = function (rspamd, tables, checked_server) { + ui.getSymbols = function (checked_server) { rspamd.query("symbols", { success: function (json) { var data = json[0].data; - var items = process_symbols_data(rspamd, data); + var items = process_symbols_data(data); /* eslint-disable consistent-this, no-underscore-dangle, one-var-declaration-per-line */ FooTable.groupFilter = FooTable.Filtering.extend({ @@ -195,7 +195,7 @@ define(["jquery", "footable"], }); /* eslint-enable consistent-this, no-underscore-dangle, one-var-declaration-per-line */ - tables.symbols = FooTable.init("#symbolsTable", { + rspamd.tables.symbols = FooTable.init("#symbolsTable", { columns: [ {sorted:true, direction:"ASC", name:"group", title:"Group", style:{"font-size":"11px"}}, {name:"symbol", title:"Symbol", style:{"font-size":"11px"}}, @@ -238,23 +238,22 @@ define(["jquery", "footable"], .on("click", ":button", function () { var value = $(this).data("save"); if (!value) return; - saveSymbols(rspamd, "./savesymbols", "symbolsTable", value); + saveSymbols("./savesymbols", "symbolsTable", value); }); }; - ui.setup = function (rspamd, tables) { - $("#updateSymbols").on("click", function (e) { - e.preventDefault(); - var checked_server = rspamd.getSelector("selSrv"); - rspamd.query("symbols", { - success: function (data) { - var items = process_symbols_data(rspamd, data[0].data)[0]; - tables.symbols.rows.load(items); - }, - server: (checked_server === "All SERVERS") ? "local" : checked_server - }); + + $("#updateSymbols").on("click", function (e) { + e.preventDefault(); + var checked_server = rspamd.getSelector("selSrv"); + rspamd.query("symbols", { + success: function (data) { + var items = process_symbols_data(data[0].data)[0]; + rspamd.tables.symbols.rows.load(items); + }, + server: (checked_server === "All SERVERS") ? "local" : checked_server }); - }; + }); return ui; }); diff --git a/interface/js/app/upload.js b/interface/js/app/upload.js index 1145db785..269d32460 100644 --- a/interface/js/app/upload.js +++ b/interface/js/app/upload.js @@ -22,8 +22,10 @@ THE SOFTWARE. */ -define(["jquery"], - function ($) { +/* global require */ + +define(["jquery", "app/rspamd"], + function ($, rspamd) { "use strict"; var ui = {}; @@ -32,7 +34,7 @@ define(["jquery"], } // @upload text - function uploadText(rspamd, data, source, headers) { + function uploadText(data, source, headers) { var url = null; if (source === "spam") { url = "learnspam"; @@ -139,13 +141,13 @@ define(["jquery"], }]; } - function get_server(rspamd) { + function get_server() { var checked_server = rspamd.getSelector("selSrv"); return (checked_server === "All SERVERS") ? "local" : checked_server; } // @upload text - function scanText(rspamd, tables, data, headers) { + function scanText(data, headers) { rspamd.query("checkv2", { data: data, params: { @@ -169,20 +171,22 @@ define(["jquery"], rspamd.alertMessage("alert-success", "Data successfully scanned"); var rows_total = $("#historyTable_scan > tbody > tr:not(.footable-detail-row)").length + 1; - var o = rspamd.process_history_v2(rspamd, {rows:[json]}, "scan"); + var o = rspamd.process_history_v2({rows:[json]}, "scan"); var items = o.items; rspamd.symbols.scan.push(o.symbols[0]); - if (Object.prototype.hasOwnProperty.call(tables, "scan")) { - tables.scan.rows.load(items, true); + if (Object.prototype.hasOwnProperty.call(rspamd.tables, "scan")) { + rspamd.tables.scan.rows.load(items, true); scrollTop(rows_total); } else { rspamd.destroyTable("scan"); - // Is there a way to get an event when the table is destroyed? - setTimeout(function () { - rspamd.initHistoryTable(rspamd, data, items, "scan", columns_v2(), true); - scrollTop(rows_total); - }, 200); + require(["footable"], function () { + // Is there a way to get an event when the table is destroyed? + setTimeout(function () { + rspamd.initHistoryTable(data, items, "scan", columns_v2(), true); + scrollTop(rows_total); + }, 200); + }); } } else { rspamd.alertMessage("alert-error", "Cannot scan data"); @@ -200,11 +204,11 @@ define(["jquery"], rspamd.alertMessage("alert-error", "Cannot tokenize message: no text data"); } }, - server: get_server(rspamd) + server: get_server() }); } - function getFuzzyHashes(rspamd, data) { + function getFuzzyHashes(data) { function fillHashTable(rules) { $("#hashTable tbody").empty(); for (const [rule, hashes] of Object.entries(rules)) { @@ -232,76 +236,75 @@ define(["jquery"], rspamd.alertMessage("alert-error", "Unexpected error processing message"); } }, - server: get_server(rspamd) + server: get_server() }); } - ui.setup = function (rspamd, tables) { - rspamd.set_page_size("scan", $("#scan_page_size").val()); - rspamd.bindHistoryTableEventHandlers("scan", 3); - $("#cleanScanHistory").off("click"); - $("#cleanScanHistory").on("click", function (e) { - e.preventDefault(); - if (!confirm("Are you sure you want to clean scan history?")) { // eslint-disable-line no-alert - return; - } - rspamd.destroyTable("scan"); - rspamd.symbols.scan.length = 0; - $("#cleanScanHistory").attr("disabled", true); - }); + rspamd.set_page_size("scan", $("#scan_page_size").val()); + rspamd.bindHistoryTableEventHandlers("scan", 3); - function enable_disable_scan_btn() { - $("#scan button:not(#cleanScanHistory, #scanOptionsToggle)").prop("disabled", ($.trim($("textarea").val()).length === 0)); + $("#cleanScanHistory").off("click"); + $("#cleanScanHistory").on("click", function (e) { + e.preventDefault(); + if (!confirm("Are you sure you want to clean scan history?")) { // eslint-disable-line no-alert + return; } + rspamd.destroyTable("scan"); + rspamd.symbols.scan.length = 0; + $("#cleanScanHistory").attr("disabled", true); + }); + + function enable_disable_scan_btn() { + $("#scan button:not(#cleanScanHistory, #scanOptionsToggle)").prop("disabled", ($.trim($("textarea").val()).length === 0)); + } + enable_disable_scan_btn(); + $("textarea").on("input", function () { enable_disable_scan_btn(); - $("textarea").on("input", function () { - enable_disable_scan_btn(); - }); + }); - $("#scanClean").on("click", function () { - $("#scan button:not(#cleanScanHistory, #scanOptionsToggle)").attr("disabled", true); - $("#scanForm")[0].reset(); - $("#scanResult").hide(); - $("#scanOutput tbody").remove(); - $("html, body").animate({scrollTop:0}, 1000); - return false; - }); + $("#scanClean").on("click", function () { + $("#scan button:not(#cleanScanHistory, #scanOptionsToggle)").attr("disabled", true); + $("#scanForm")[0].reset(); + $("#scanResult").hide(); + $("#scanOutput tbody").remove(); + $("html, body").animate({scrollTop:0}, 1000); + return false; + }); - $(".card-close-btn").on("click", function () { - $(this).closest(".card").slideUp(); - }); + $(".card-close-btn").on("click", function () { + $(this).closest(".card").slideUp(); + }); - $("[data-upload]").on("click", function () { - var source = $(this).data("upload"); - var data = $("#scanMsgSource").val(); - var headers = {}; - if ($.trim(data).length > 0) { - if (source === "scan") { - headers = ["IP", "User", "From", "Rcpt", "Helo", "Hostname"].reduce(function (o, header) { - var value = $("#scan-opt-" + header.toLowerCase()).val(); - if (value !== "") o[header] = value; - return o; - }, {}); - if ($("#scan-opt-pass-all").prop("checked")) headers.Pass = "all"; - scanText(rspamd, tables, data, headers); - } else if (source === "compute-fuzzy") { - getFuzzyHashes(rspamd, data); - } else { - if (source === "fuzzy") { - headers = { - flag: $("#fuzzyFlagText").val(), - weight: $("#fuzzyWeightText").val() - }; - } - uploadText(rspamd, data, source, headers); - } + $("[data-upload]").on("click", function () { + var source = $(this).data("upload"); + var data = $("#scanMsgSource").val(); + var headers = {}; + if ($.trim(data).length > 0) { + if (source === "scan") { + headers = ["IP", "User", "From", "Rcpt", "Helo", "Hostname"].reduce(function (o, header) { + var value = $("#scan-opt-" + header.toLowerCase()).val(); + if (value !== "") o[header] = value; + return o; + }, {}); + if ($("#scan-opt-pass-all").prop("checked")) headers.Pass = "all"; + scanText(data, headers); + } else if (source === "compute-fuzzy") { + getFuzzyHashes(data); } else { - rspamd.alertMessage("alert-error", "Message source field cannot be blank"); + if (source === "fuzzy") { + headers = { + flag: $("#fuzzyFlagText").val(), + weight: $("#fuzzyWeightText").val() + }; + } + uploadText(data, source, headers); } - return false; - }); - }; + } else { + rspamd.alertMessage("alert-error", "Message source field cannot be blank"); + } + return false; + }); return ui; }); diff --git a/interface/js/main.js b/interface/js/main.js index 3b0b8de15..d57871b87 100644 --- a/interface/js/main.js +++ b/interface/js/main.js @@ -22,8 +22,9 @@ requirejs.config({ shim: { app: {deps:["jquery"]}, codejar: {exports: "CodeJar", deps:["linenumbers"]}, - bootstrap: {exports:"bootstrap"}, - d3evolution: {exports:"D3Evolution", deps:["d3", "jquery"]}, + bootstrap: {exports:"bootstrap", deps:["jquery"]}, // Popovers require jQuery + d3: {exports:"d3"}, + d3evolution: {exports:"D3Evolution", deps:["d3.global", "jquery"]}, d3pie: {exports:"D3Pie", deps:["d3.global", "jquery"]}, fontawesome: {exports: "FontAwesome", deps:["fontawesome_solid"]}, footable: {deps:["bootstrap", "jquery"]}, @@ -61,10 +62,7 @@ requirejs.onError = function (e) { }; // Load main UI -require(["app/rspamd", "fontawesome"], - function (rspamd) { - "use strict"; - rspamd.setup(); - rspamd.connect(); - } -); +require(["app/rspamd"], (rspamd) => { + "use strict"; + rspamd.connect() +}); |