diff options
Diffstat (limited to 'interface/js/app/symbols.js')
-rw-r--r-- | interface/js/app/symbols.js | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/interface/js/app/symbols.js b/interface/js/app/symbols.js new file mode 100644 index 0000000..1e3fb5d --- /dev/null +++ b/interface/js/app/symbols.js @@ -0,0 +1,260 @@ +/* + The MIT License (MIT) + + Copyright (C) 2017 Vsevolod Stakhov <vsevolod@highsecure.ru> + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + +/* global FooTable */ + +define(["jquery", "app/common", "footable"], + ($, common) => { + "use strict"; + const ui = {}; + let altered = {}; + + function clear_altered() { + $("#save-alert").addClass("d-none"); + altered = {}; + } + + function saveSymbols(server) { + $("#save-alert button").attr("disabled", true); + + const values = []; + Object.entries(altered).forEach(([key, value]) => values.push({name: key, value: value})); + + common.query("./savesymbols", { + success: function () { + clear_altered(); + common.alertMessage("alert-modal alert-success", "Symbols successfully saved"); + }, + complete: () => $("#save-alert button").removeAttr("disabled", true), + errorMessage: "Save symbols error", + method: "POST", + params: { + data: JSON.stringify(values), + dataType: "json", + }, + server: server + }); + } + + function process_symbols_data(data) { + const items = []; + const lookup = {}; + const freqs = []; + const distinct_groups = []; + + data.forEach((group) => { + group.rules.forEach((item) => { + const formatter = new Intl.NumberFormat("en", { + minimumFractionDigits: 2, + maximumFractionDigits: 6, + useGrouping: false + }); + item.group = group.group; + let label_class = ""; + if (item.weight < 0) { + label_class = "scorebar-ham"; + } else if (item.weight > 0) { + label_class = "scorebar-spam"; + } + item.weight = '<input class="form-control input-sm mb-disabled scorebar ' + label_class + + '" autocomplete="off" type="number" step="0.01" tabindex="1" ' + + 'value="' + formatter.format(item.weight) + '" 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); + } + items.push(item); + }); + }); + + // For better mean calculations + const avg_freq = freqs + .sort((a, b) => Number(a) < Number(b)) + .reduce((f1, acc) => f1 + acc) / (freqs.length !== 0 ? freqs.length : 1.0); + let mult = 1.0; + let exp = 0.0; + + if (avg_freq > 0.0) { + while (mult * avg_freq < 1.0) { + mult *= 10; + exp++; + } + } + $.each(items, (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 + ui.getSymbols = function (checked_server) { + clear_altered(); + common.query("symbols", { + success: function (json) { + const [{data}] = json; + const items = process_symbols_data(data); + + /* eslint-disable consistent-this, no-underscore-dangle, one-var-declaration-per-line */ + FooTable.groupFilter = FooTable.Filtering.extend({ + construct: function (instance) { + this._super(instance); + [,this.groups] = items; + this.def = "Any group"; + this.$group = null; + }, + $create: function () { + this._super(); + const self = this; + const $form_grp = $("<div/>", { + class: "form-group" + }).append($("<label/>", { + class: "sr-only", + text: "Group" + })).prependTo(self.$form); + + self.$group = $("<select/>", { + class: "form-select" + }).on("change", { + self: self + }, self._onStatusDropdownChanged).append( + $("<option/>", { + text: self.def + })).appendTo($form_grp); + + $.each(self.groups, (i, group) => { + self.$group.append($("<option/>").text(group)); + }); + }, + _onStatusDropdownChanged: function (e) { + const {self} = e.data; + const selected = $(this).val(); + if (selected !== self.def) { + self.addFilter("group", selected, ["group"]); + } else { + self.removeFilter("group"); + } + self.filter(); + }, + draw: function () { + this._super(); + const group = this.find("group"); + if (group instanceof FooTable.Filter) { + this.$group.val(group.query.val()); + } else { + this.$group.val(this.def); + } + } + }); + /* eslint-enable consistent-this, no-underscore-dangle, one-var-declaration-per-line */ + + common.tables.symbols = FooTable.init("#symbolsTable", { + columns: [ + {sorted: true, direction: "ASC", name: "group", title: "Group"}, + {name: "symbol", title: "Symbol"}, + {name: "description", title: "Description", breakpoints: "xs sm"}, + {name: "weight", title: "Score"}, + {name: "frequency", + title: "Frequency", + breakpoints: "xs sm", + sortValue: function (value) { return Number(value).toFixed(2); }}, + {name: "time", title: "Avg. time", breakpoints: "xs sm"}, + ], + rows: items[0], + paging: { + enabled: true, + limit: 5, + size: 25 + }, + filtering: { + enabled: true, + position: "left", + connectors: false + }, + sorting: { + enabled: true + }, + components: { + filtering: FooTable.groupFilter + }, + on: { + "ready.ft.table": function () { + if (common.read_only) { + $(".mb-disabled").attr("disabled", true); + } + } + } + }); + }, + server: (checked_server === "All SERVERS") ? "local" : checked_server + }); + }; + + + $("#updateSymbols").on("click", (e) => { + e.preventDefault(); + clear_altered(); + const checked_server = common.getSelector("selSrv"); + common.query("symbols", { + success: function (data) { + const [items] = process_symbols_data(data[0].data); + common.tables.symbols.rows.load(items); + }, + server: (checked_server === "All SERVERS") ? "local" : checked_server + }); + }); + + $("#symbolsTable") + .on("input", ".scorebar", ({target}) => { + const t = $(target); + t.removeClass("scorebar-ham scorebar-spam"); + if (target.value < 0) { + t.addClass("scorebar-ham"); + } else if (target.value > 0) { + t.addClass("scorebar-spam"); + } + }) + .on("change", ".scorebar", ({target}) => { + altered[$(target).attr("id").substring(5)] = parseFloat(target.value); + $("#save-alert").removeClass("d-none"); + }); + + $("#save-alert button") + .on("click", ({target}) => saveSymbols($(target).data("save"))); + + return ui; + }); |