Browse Source

Better update handling, especially when updating empty table to non-empty table

tags/1.5.4
andryyy 7 years ago
parent
commit
fcf5395e8a
2 changed files with 280 additions and 246 deletions
  1. 115
    96
      interface/js/app/history.js
  2. 165
    150
      interface/js/app/symbols.js

+ 115
- 96
interface/js/app/history.js View File

@@ -25,6 +25,7 @@
define(['jquery', 'footable', 'humanize'],
function($, _, Humanize) {
var interface = {};
var ft = {};

function unix_time_format(tm) {
var date = new Date(tm ? tm * 1000 : 0);
@@ -146,38 +147,36 @@ function($, _, Humanize) {
}, {
"name": "ip",
"title": "IP address",
"breakpoints": "xs sm",
"breakpoints": "xs sm md",
"style": {
"font-size": "11px",
"width": 150,
"maxWidth": 150
"minWidth": 150,
}
}, {
"name": "sender_mime",
"title": "From",
"breakpoints": "xs sm",
"breakpoints": "xs sm md",
"style": {
"font-size": "11px",
"width": 150,
"maxWidth": 150
"minWidth": 150,
}
}, {
"name": "rcpt_mime",
"title": "To",
"breakpoints": "xs sm",
"breakpoints": "xs sm md",
"style": {
"font-size": "11px",
"width": 150,
"maxWidth": 150
"word-break": "break-all",
"minWidth": 150,
"maxWidth": 300,
}
}, {
"name": "subject",
"title": "Subject",
"breakpoints": "xs sm",
"breakpoints": "xs sm md",
"style": {
"font-size": "11px",
"width": 150,
"maxWidth": 150
"minWidth": 150,
}
}, {
"name": "action",
@@ -207,7 +206,7 @@ function($, _, Humanize) {
}, {
"name": "size",
"title": "Message size",
"breakpoints": "xs sm",
"breakpoints": "xs sm md",
"style": {
"font-size": "11px",
"width": 90,
@@ -217,10 +216,10 @@ function($, _, Humanize) {
}, {
"name": "scan_time",
"title": "Scan time",
"breakpoints": "xs sm",
"breakpoints": "xs sm md",
"style": {
"font-size": "11px",
"maxWidth": 80
"maxWidth": 120
},
"sortValue": function(val) { return Number(val.options.sortValue); }
}, {
@@ -235,11 +234,10 @@ function($, _, Humanize) {
}, {
"name": "user",
"title": "Authenticated user",
"breakpoints": "xs sm",
"breakpoints": "xs sm md",
"style": {
"font-size": "11px",
"width": 100,
"maxWidth": 150
"minWidth": 150
}
}];
}
@@ -368,19 +366,6 @@ function($, _, Humanize) {
}

interface.getHistory = function (rspamd, tables) {
if (tables.history !== undefined) {
var history_length = document.getElementsByName('historyLog_length')[0];
if (history_length !== undefined) {
history_length = parseInt(history_length.value);
} else {
history_length = 10;
}
tables.history.destroy();
tables.history = undefined;
$('#historyLog').children('tbody').remove();
}


FooTable.actionFilter = FooTable.Filtering.extend({
construct : function(instance) {
this._super(instance);
@@ -443,8 +428,7 @@ function($, _, Humanize) {
},
success: function (data) {
var items = process_history_data(data);

$('#historyTable').footable({
ft.history = FooTable.init("#historyTable", {
"columns": get_history_columns(data),
"rows": items,
"paging": {
@@ -470,12 +454,6 @@ function($, _, Humanize) {
interface.getErrors = function(rspamd, tables) {
if (rspamd.read_only) return;

if (tables.errors) {
tables.errors.destroy();
$('#errorsLog').children('tbody').remove();
tables.errors = undefined;
}

var items = [];
$.ajax({
dataType: 'json',
@@ -489,70 +467,111 @@ function($, _, Humanize) {
},
success: function (data) {
$.each(data, function (i, item) {
items.push(
item.ts = unix_time_format(item.ts)
);
});
$('#errorsLog').footable({
"columns": [
{"sorted": true,"direction": "DESC","name":"ts","title":"Time","style":{"font-size":"11px","width":300,"maxWidth":300}},
{"name":"type","title":"Worker type","breakpoints":"xs sm","style":{"font-size":"11px","width":150,"maxWidth":150}},
{"name":"pid","title":"PID","breakpoints":"xs sm","style":{"font-size":"11px","width":110,"maxWidth":110}},
{"name":"module","title":"Module","style":{"font-size":"11px"}},
{"name":"id","title":"Internal ID","style":{"font-size":"11px"}},
{"name":"message","title":"Message","breakpoints":"xs sm","style":{"font-size":"11px"}},
],
"rows": data,
"paging": {
"enabled": true,
"limit": 5,
"size": 25
},
"filtering": {
"enabled": true,
"position": "left"
},
"sorting": {
"enabled": true
}
});
items.push(
item.ts = unix_time_format(item.ts)
);
});
ft.errors = FooTable.init("#errorsLog", {
"columns": [
{"sorted": true,"direction": "DESC","name":"ts","title":"Time","style":{"font-size":"11px","width":300,"maxWidth":300}},
{"name":"type","title":"Worker type","breakpoints":"xs sm","style":{"font-size":"11px","width":150,"maxWidth":150}},
{"name":"pid","title":"PID","breakpoints":"xs sm","style":{"font-size":"11px","width":110,"maxWidth":110}},
{"name":"module","title":"Module","style":{"font-size":"11px"}},
{"name":"id","title":"Internal ID","style":{"font-size":"11px"}},
{"name":"message","title":"Message","breakpoints":"xs sm","style":{"font-size":"11px"}},
],
"rows": data,
"paging": {
"enabled": true,
"limit": 5,
"size": 25
},
"filtering": {
"enabled": true,
"position": "left"
},
"sorting": {
"enabled": true
}
});
}
});
};

interface.setup = function(rspamd, tables) {
$('#updateHistory').on('click', function () {
interface.getHistory(rspamd, tables);
$('#updateHistory').on('click', function (e) {
e.preventDefault();
$.ajax({
dataType: 'json',
type: 'GET',
jsonp: false,
url: 'history',
beforeSend: function (xhr) {
xhr.setRequestHeader('Password', rspamd.getPassword());
},
success: function (data) {
var items = process_history_data(data);
ft.history.rows.load(items);
},
error: function (data) {
rspamd.alertMessage('alert-modal alert-error', data.statusText);
}
});
});
$('#updateErrors').on('click', function () {
interface.getErrors(rspamd, tables);
$('#updateErrors').on('click', function (e) {
e.preventDefault();
var items = [];
$.ajax({
dataType: 'json',
type: 'GET',
jsonp: false,
url: 'errors',
beforeSend: function (xhr) {
xhr.setRequestHeader('Password', rspamd.getPassword());
},
success: function (data) {
$.each(data, function (i, item) {
items.push(
item.ts = unix_time_format(item.ts)
);
});
ft.errors.rows.load(data);
},
error: function (data) {
rspamd.alertMessage('alert-modal alert-error', data.statusText);
}
});
});
// @reset history log
$('#resetHistory').on('click', function () {
if (!confirm("Are you sure you want to reset history log?")) {
return;
}
if (tables.history) {
tables.history.destroy();
tables.history = undefined;
$('#historyLog').children('tbody').remove();
}
$.ajax({
dataType: 'json',
type: 'GET',
jsonp: false,
url: 'historyreset',
beforeSend: function (xhr) {
xhr.setRequestHeader('Password', rspamd.getPassword());
},
success: function () {
interface.getHistory(rspamd, tables);
interface.getErrors(rspamd, tables);
},
error: function (data) {
rspamd.alertMessage('alert-modal alert-error', data.statusText);
}
});
// @reset history log
$('#resetHistory').on('click', function (e) {
e.preventDefault();
if (!confirm("Are you sure you want to reset history log?")) {
return;
}
if (ft.history) {
ft.history.destroy();
ft.history = undefined;
}
if (ft.errors) {
ft.errors.destroy();
ft.errors = undefined;
}
$.ajax({
dataType: 'json',
type: 'GET',
jsonp: false,
url: 'historyreset',
beforeSend: function (xhr) {
xhr.setRequestHeader('Password', rspamd.getPassword());
},
success: function () {
interface.getHistory(rspamd, tables);
interface.getErrors(rspamd, tables);
},
error: function (data) {
rspamd.alertMessage('alert-modal alert-error', data.statusText);
}
});
});
};
return interface;

+ 165
- 150
interface/js/app/symbols.js View File

@@ -25,6 +25,7 @@
define(['jquery', 'footable'],
function($) {
var interface = {}
var ft = {}

function saveSymbols(rspamd, action, id, is_cluster) {
var inputs = $('#' + id + ' :input[data-role="numerictextbox"]');
@@ -76,16 +77,84 @@ function($) {
return 1.0 / (Math.pow(10, digits));
}
}
function process_symbols_data(data) {
var items = [];
var lookup = {};
var freqs = [];
var distinct_groups = [];

$.each(data, function (i, group) {
$.each(group.rules, function (i, item) {
var max = 20;
var min = -20;
if (item.weight > max) {
max = item.weight * 2;
}
item.group = group.group
if (item.weight < min) {
min = item.weight * 2;
}
var label_class = '';
if (item.weight < 0) {
label_class = 'scorebar-ham';
} else {
label_class = 'scorebar-spam';
}
item.weight = '<input class="form-control input-sm mb-disabled ' + label_class +
'" data-role="numerictextbox" autocomplete="off" "type="number" class="input" min="' +
min + '" max="' +
max + '" step="' + decimalStep(item.weight) +
'" tabindex="1" value="' + Number(item.weight).toFixed(3) +
'" id="_sym_' + item.symbol + '"></input>'
if (!item.time) {
item.time = 0;
}
item.time = Number(item.time).toFixed(2) + 's'
if (!item.frequency) {
item.frequency = 0;
}
freqs.push(item.frequency);
item.frequency = Number(item.frequency).toFixed(2)
if (!(item.group in lookup)) {
lookup[item.group] = 1;
distinct_groups.push(item.group);
}
item.save = '<button type="button" data-save="local" class="btn btn-primary btn-sm mb-disabled">Save</button>' +
'&nbsp;<button data-save="cluster" type="button" class="btn btn-primary btn-sm mb-disabled">Save in cluster</button>';
items.push(item)
});
});

// For better mean calculations
var avg_freq = freqs.sort(function(a, b) {
return Number(a) < Number(b);
}).reduce(function(f1, acc) {
return f1 + acc;
}) / (freqs.length != 0 ? freqs.length : 1.0);
var mult = 1.0;
var exp = 0.0;

if (avg_freq > 0.0) {
while (mult * avg_freq < 1.0) {
mult *= 10;
exp ++;
}
}
$.each(items, function (i, item) {
item.frequency = Number(item.frequency) * mult;

if (exp > 0) {
item.frequency = item.frequency.toFixed(2) + 'e-' + exp;
}
else {
item.frequency = item.frequency.toFixed(2);
}
});
return [items, distinct_groups]
}
// @get symbols into modal form
interface.getSymbols = function(rspamd, tables, checked_server) {
var symbols = tables.symbols
if (symbols) {
symbols.destroy();
tables.symbols = undefined;
$('#symbolsTable').children('tbody').remove();
}

var items = [];
$.ajax({
dataType: 'json',
type: 'GET',
@@ -95,151 +164,81 @@ function($) {
xhr.setRequestHeader('Password', rspamd.getPassword());
},
success: function (data) {
var distinct_groups = [];
var lookup = {};
var freqs = [];

$.each(data, function (i, group) {
$.each(group.rules, function (i, item) {
var max = 20;
var min = -20;
if (item.weight > max) {
max = item.weight * 2;
}
item.group = group.group
if (item.weight < min) {
min = item.weight * 2;
}
var label_class = '';
if (item.weight < 0) {
label_class = 'scorebar-ham';
} else {
label_class = 'scorebar-spam';
}
item.weight = '<input class="form-control input-sm mb-disabled ' + label_class +
'" data-role="numerictextbox" autocomplete="off" "type="number" class="input" min="' +
min + '" max="' +
max + '" step="' + decimalStep(item.weight) +
'" tabindex="1" value="' + Number(item.weight).toFixed(3) +
'" id="_sym_' + item.symbol + '"></input>'
if (!item.time) {
item.time = 0;
}
item.time = Number(item.time).toFixed(2) + 's'
if (!item.frequency) {
item.frequency = 0;
}
freqs.push(item.frequency);
item.frequency = Number(item.frequency).toFixed(2)
if (!(item.group in lookup)) {
lookup[item.group] = 1;
distinct_groups.push(item.group);
}
item.save = '<button type="button" data-save="local" class="btn btn-primary btn-sm mb-disabled">Save</button>' +
'&nbsp;<button data-save="cluster" type="button" class="btn btn-primary btn-sm mb-disabled">Save in cluster</button>';
items.push(item)
});
});
// For better mean calculations
var avg_freq = freqs.sort(function(a, b) {
return Number(a) < Number(b);
}).reduce(function(f1, acc) {
return f1 + acc;
}) / (freqs.length != 0 ? freqs.length : 1.0);
var mult = 1.0;
var exp = 0.0;

if (avg_freq > 0.0) {
while (mult * avg_freq < 1.0) {
mult *= 10;
exp ++;
}
}
$.each(items, function (i, item) {
item.frequency = Number(item.frequency) * mult;

if (exp > 0) {
item.frequency = item.frequency.toFixed(2) + 'e-' + exp;
}
else {
item.frequency = item.frequency.toFixed(2);
}
});
var items = process_symbols_data(data);
FooTable.groupFilter = FooTable.Filtering.extend({
construct : function(instance) {
this._super(instance);
this.groups = distinct_groups;
this.def = 'Any group';
this.$group = null;
},
$create : function() {
this._super();
var self = this, $form_grp = $('<div/>', {
'class' : 'form-group'
}).append($('<label/>', {
'class' : 'sr-only',
text : 'Group'
})).prependTo(self.$form);
construct : function(instance) {
this._super(instance);
this.groups = items[1];
this.def = 'Any group';
this.$group = null;
},
$create : function() {
this._super();
var self = this, $form_grp = $('<div/>', {
'class' : 'form-group'
}).append($('<label/>', {
'class' : 'sr-only',
text : 'Group'
})).prependTo(self.$form);

self.$group = $('<select/>', {
'class' : 'form-control'
}).on('change', {
self : self
}, self._onStatusDropdownChanged).append(
$('<option/>', {
text : self.def
})).appendTo($form_grp);
self.$group = $('<select/>', {
'class' : 'form-control'
}).on('change', {
self : self
}, self._onStatusDropdownChanged).append(
$('<option/>', {
text : self.def
})).appendTo($form_grp);

$.each(self.groups, function(i, group) {
self.$group.append($('<option/>').text(group));
});
},
_onStatusDropdownChanged : function(e) {
var self = e.data.self, selected = $(this).val();
if (selected !== self.def) {
self.addFilter('group', selected, [ 'group' ]);
} else {
self.removeFilter('group');
}
self.filter();
},
draw : function() {
this._super();
var group = this.find('group');
if (group instanceof FooTable.Filter) {
this.$group.val(group.query.val());
} else {
this.$group.val(this.def);
}
}
$.each(self.groups, function(i, group) {
self.$group.append($('<option/>').text(group));
});
},
_onStatusDropdownChanged : function(e) {
var self = e.data.self, selected = $(this).val();
if (selected !== self.def) {
self.addFilter('group', selected, [ 'group' ]);
} else {
self.removeFilter('group');
}
self.filter();
},
draw : function() {
this._super();
var group = this.find('group');
if (group instanceof FooTable.Filter) {
this.$group.val(group.query.val());
} else {
this.$group.val(this.def);
}
}
});

$('#symbolsTable').footable({
"columns": [
{"sorted": true,"direction": "ASC", "name":"group","title":"Group","style":{"font-size":"11px"}},
{"name":"symbol","title":"Symbol","style":{"font-size":"11px"}},
{"name":"description","title":"Description","breakpoints":"xs sm","style":{"font-size":"11px"}},
{"name":"weight","title":"Score","style":{"font-size":"11px"}},
{"name":"frequency","title":"Frequency","breakpoints":"xs sm","style":{"font-size":"11px"}},
{"name":"time","title":"Avg. time","breakpoints":"xs sm","style":{"font-size":"11px"}},
{"name":"save","title":"Save","style":{"font-size":"11px"}},
],
"rows": items,
"paging": {
"enabled": true,
"limit": 5,
"size": 25
},
"filtering": {
"enabled": true,
"position": "left"
},
"sorting": {
"enabled": true
},
components: {
filtering: FooTable.groupFilter
}
ft.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"}},
{"name":"description","title":"Description","breakpoints":"xs sm","style":{"font-size":"11px"}},
{"name":"weight","title":"Score","style":{"font-size":"11px"}},
{"name":"frequency","title":"Frequency","breakpoints":"xs sm","style":{"font-size":"11px"}},
{"name":"time","title":"Avg. time","breakpoints":"xs sm","style":{"font-size":"11px"}},
{"name":"save","title":"Save","style":{"font-size":"11px"}},
],
"rows": items[0],
"paging": {
"enabled": true,
"limit": 5,
"size": 25
},
"filtering": {
"enabled": true,
"position": "left"
},
"sorting": {
"enabled": true
},
components: {
filtering: FooTable.groupFilter
}
}, function tableHook() {
$('#symbolsTable :button').on('click', function() {
var value = $(this).data('save');
@@ -258,8 +257,24 @@ function($) {
};

interface.setup = function(rspamd, tables) {
$('#updateSymbols').on('click', function () {
interface.getSymbols(rspamd, tables);
$('#updateSymbols').on('click', function (e) {
e.preventDefault();
$.ajax({
dataType: 'json',
type: 'GET',
jsonp: false,
url: 'symbols',
beforeSend: function (xhr) {
xhr.setRequestHeader('Password', rspamd.getPassword());
},
success: function (data) {
var items = process_symbols_data(data)[0];
ft.symbols.rows.load(items);
},
error: function (data) {
rspamd.alertMessage('alert-modal alert-error', data.statusText);
}
});
});
};


Loading…
Cancel
Save