From def746a5dda265e113940ee13329ad3b45efd187 Mon Sep 17 00:00:00 2001 From: moisseev Date: Tue, 20 Aug 2019 14:36:19 +0300 Subject: [PATCH] [WebUI] Rework scan results display --- .eslintrc.json | 2 +- interface/css/rspamd.css | 12 +- interface/index.html | 45 ++-- interface/js/app/history.js | 433 +++--------------------------------- interface/js/app/rspamd.js | 404 ++++++++++++++++++++++++++++++++- interface/js/app/upload.js | 161 +++++++++----- 6 files changed, 566 insertions(+), 491 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index c9fa15153..bfc3fd6a5 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -24,7 +24,7 @@ "singleLine": { "afterColon": false } }], "max-params": ["warn", 6], - "max-statements": ["warn", 33], + "max-statements": ["warn", 44], "max-statements-per-line": ["error", { "max": 2 }], "multiline-comment-style": "off", "multiline-ternary": ["error", "always-multiline"], diff --git a/interface/css/rspamd.css b/interface/css/rspamd.css index 9a0438d78..0e7c877d9 100644 --- a/interface/css/rspamd.css +++ b/interface/css/rspamd.css @@ -502,17 +502,17 @@ td.maps-cell { } /* history table */ -#historyTable > tbody > tr > td, -#historyTable > thead > tr > th { +#historyTable_scan > tbody > tr > td, +#historyTable_scan > thead > tr > th, +#historyTable_history > tbody > tr > td, +#historyTable_history > thead > tr > th { padding: 4px; } -#historyTable > thead > tr > th { +#historyTable_scan > thead > tr > th, +#historyTable_history > thead > tr > th { padding-right: 20px; } -#selSymOrder { - height: auto; -} .widget-title-form label { font-size: 12px; font-weight: normal; diff --git a/interface/index.html b/interface/index.html index cb22f3064..84aa211cd 100644 --- a/interface/index.html +++ b/interface/index.html @@ -219,20 +219,6 @@ - + +
+
+
+ + + + + +
+ +
Scan results history
+
+
+
+
+
+
+
@@ -281,8 +292,8 @@
- - @@ -301,7 +312,7 @@
-
+
diff --git a/interface/js/app/history.js b/interface/js/app/history.js index 49e228e3a..a7d656f27 100644 --- a/interface/js/app/history.js +++ b/interface/js/app/history.js @@ -27,245 +27,21 @@ define(["jquery", "footable", "humanize"], function ($, _, Humanize) { "use strict"; - var page_size = { - errors: 25, - history: 25 - }; - - function set_page_size(n, callback) { - if (n !== page_size.history && n > 0) { - page_size.history = n; - if (callback) { - return callback(n); - } - } - return null; - } - - set_page_size($("#history_page_size").val()); - var ui = {}; var prevVersion = null; - var htmlEscapes = { - "&": "&", - "<": "<", - ">": ">", - "\"": """, - "'": "'", - "/": "/", - "`": "`", - "=": "=" - }; - var htmlEscaper = /[&<>"'/`=]/g; - var symbols = []; - var symbolDescriptions = {}; - - var escapeHTML = function (string) { - return String(string).replace(htmlEscaper, function (match) { - return htmlEscapes[match]; - }); - }; - - var escape_HTML_array = function (arr) { - arr.forEach(function (d, i) { arr[i] = escapeHTML(d); }); - }; - - function unix_time_format(tm) { - var date = new Date(tm ? tm * 1000 : 0); - return date.toLocaleString(); - } - - function preprocess_item(item) { - for (var prop in item) { - if (!{}.hasOwnProperty.call(item, prop)) continue; - switch (prop) { - case "rcpt_mime": - case "rcpt_smtp": - escape_HTML_array(item[prop]); - break; - case "symbols": - Object.keys(item.symbols).forEach(function (key) { - var sym = item.symbols[key]; - if (!sym.name) { - sym.name = key; - } - sym.name = escapeHTML(sym.name); - if (sym.description) { - sym.description = escapeHTML(sym.description); - } - - if (sym.options) { - escape_HTML_array(sym.options); - } - }); - break; - default: - if (typeof item[prop] === "string") { - item[prop] = escapeHTML(item[prop]); - } - } - } - - if (item.action === "clean" || item.action === "no action") { - item.action = "
" + item.action + "
"; - } else if (item.action === "rewrite subject" || item.action === "add header" || item.action === "probable spam") { - item.action = "
" + item.action + "
"; - } else if (item.action === "spam" || item.action === "reject") { - item.action = "
" + item.action + "
"; - } else { - item.action = "
" + item.action + "
"; - } - - var score_content = (item.score < item.required_score) - ? "" + item.score.toFixed(2) + " / " + item.required_score + "" - : "" + item.score.toFixed(2) + " / " + item.required_score + ""; - - item.score = { - options: { - sortValue: item.score - }, - value: score_content - }; - } - - function getSelector(id) { - var e = document.getElementById(id); - return e.options[e.selectedIndex].value; - } - - function get_compare_function() { - var compare_functions = { - magnitude: function (e1, e2) { - return Math.abs(e2.score) - Math.abs(e1.score); - }, - name: function (e1, e2) { - return e1.name.localeCompare(e2.name); - }, - score: function (e1, e2) { - return e2.score - e1.score; - } - }; - - return compare_functions[getSelector("selSymOrder")]; - } - - function sort_symbols(o, compare_function) { - return Object.keys(o) - .map(function (key) { - return o[key]; - }) - .sort(compare_function) - .map(function (e) { return e.str; }) - .join("
\n"); - } - - function process_history_v2(data) { - // Display no more than rcpt_lim recipients - var rcpt_lim = 3; - var items = []; - var unsorted_symbols = []; - var compare_function = get_compare_function(); - - $("#selSymOrder, label[for='selSymOrder']").show(); - - $.each(data.rows, - function (i, item) { - function more(p) { - var l = item[p].length; - return (l > rcpt_lim) ? " … (" + l + ")" : ""; - } - function format_rcpt(smtp, mime) { - var full = ""; - var shrt = ""; - if (smtp) { - full = "[" + item.rcpt_smtp.join(", ") + "] "; - shrt = "[" + item.rcpt_smtp.slice(0, rcpt_lim).join(",​") + more("rcpt_smtp") + "]"; - if (mime) { - full += " "; - shrt += " "; - } - } - if (mime) { - full += item.rcpt_mime.join(", "); - shrt += item.rcpt_mime.slice(0, rcpt_lim).join(",​") + more("rcpt_mime"); - } - return {full:full, shrt:shrt}; - } - - function get_symbol_class(name, score) { - if (name.match(/^GREYLIST$/)) { - return "symbol-special"; - } - - if (score < 0) { - return "symbol-negative"; - } else if (score > 0) { - return "symbol-positive"; - } - return null; - } - - preprocess_item(item); - Object.keys(item.symbols).forEach(function (key) { - var sym = item.symbols[key]; - sym.str = ''; - - if (sym.description) { - sym.str += '' + - sym.name + " (" + sym.score + ")"; - // Store description for tooltip - symbolDescriptions[key] = sym.description; - } else { - sym.str += sym.name + " (" + sym.score + ")"; - } - - if (sym.options) { - sym.str += " [" + sym.options.join(",") + "]"; - } - }); - unsorted_symbols.push(item.symbols); - item.symbols = sort_symbols(item.symbols, compare_function); - item.time = { - value: unix_time_format(item.unix_time), - options: { - sortValue: item.unix_time - } - }; - item.time_real = item.time_real.toFixed(3); - item.id = item["message-id"]; - - var rcpt = {}; - if (!item.rcpt_mime.length) { - rcpt = format_rcpt(true, false); - } else if ($(item.rcpt_mime).not(item.rcpt_smtp).length !== 0 || $(item.rcpt_smtp).not(item.rcpt_mime).length !== 0) { - rcpt = format_rcpt(true, true); - } else { - rcpt = format_rcpt(false, true); - } - item.rcpt_mime_short = rcpt.shrt; - item.rcpt_mime = rcpt.full; - - if (item.sender_mime !== item.sender_smtp) { - item.sender_mime = "[" + item.sender_smtp + "] " + item.sender_mime; - } - items.push(item); - }); - return {items:items, symbols:unsorted_symbols}; - } - - function process_history_legacy(data) { + function process_history_legacy(rspamd, data) { var items = []; var compare = function (e1, e2) { return e1.name.localeCompare(e2.name); }; - $("#selSymOrder, label[for='selSymOrder']").hide(); + $("#selSymOrder_history, label[for='selSymOrder_history']").hide(); $.each(data, function (i, item) { - item.time = unix_time_format(item.unix_time); - preprocess_item(item); + item.time = rspamd.unix_time_format(item.unix_time); + rspamd.preprocess_item(rspamd, item); item.symbols = Object.keys(item.symbols) .map(function (key) { return item.symbols[key]; @@ -274,7 +50,7 @@ define(["jquery", "footable", "humanize"], .map(function (e) { return e.name; }) .join(", "); item.time = { - value: unix_time_format(item.unix_time), + value: rspamd.unix_time_format(item.unix_time), options: { sortValue: item.unix_time } @@ -362,10 +138,10 @@ define(["jquery", "footable", "humanize"], name: "symbols", title: "Symbols

" + 'Sort by:
' + - '
' + - '' + - '' + - '' + + '
' + + '' + + '' + + '' + "
", breakpoints: "all", style: { @@ -500,17 +276,16 @@ define(["jquery", "footable", "humanize"], }]; } - var process_functions = { - 2: process_history_v2, - legacy: process_history_legacy - }; - var columns = { 2: columns_v2, legacy: columns_legacy }; - function process_history_data(data) { + function process_history_data(rspamd, data) { + var process_functions = { + 2: rspamd.process_history_v2, + legacy: process_history_legacy + }; var pf = process_functions.legacy; if (data.version) { @@ -520,7 +295,7 @@ define(["jquery", "footable", "humanize"], } } - return pf(data); + return pf(rspamd, data, "history"); } function get_history_columns(data) { @@ -536,136 +311,7 @@ define(["jquery", "footable", "humanize"], return func(); } - function drawTooltips() { - // Update symbol description tooltips - $.each(symbolDescriptions, function (key, description) { - $("abbr[data-sym-key=" + key + "]").tooltip({ - placement: "bottom", - html: true, - title: description - }); - }); - } - - function initHistoryTable(rspamd, tables, data, items) { - /* eslint-disable consistent-this, no-underscore-dangle, one-var-declaration-per-line */ - FooTable.actionFilter = FooTable.Filtering.extend({ - construct: function (instance) { - this._super(instance); - this.actions = ["reject", "add header", "greylist", - "no action", "soft reject", "rewrite subject"]; - this.def = "Any action"; - this.$action = null; - }, - $create: function () { - this._super(); - var self = this, $form_grp = $("
", { - class: "form-group" - }).append($("