7 "salmon", "lightcoral", "crimson", "red", "darkred", "orangered",
8 "gold", "orange", "yellow", "darkkhaki", "lime", "green", "greenyellow",
9 "springgreen", "olive", "cyan", "turquoise", "teal", "lightskyblue",
10 "dodgerblue", "royalblue", "blue", "navy", "violet", "fuchsia",
11 "darkviolet", "purple", "deeppink", "gray", "darkslategray", "sandybrown",
12 "goldenrod", "chocolate", "saddlebrown", "maroon", "rosybrown", "sienna",
13 "brown", "dimgray", "mediumvioletred", "indigo", "orchid", "mediumpurple",
14 "steelblue", "powderblue", "lightseagreen", "cadetblue", "aquamarine",
15 "olivedrab", "chartreuse", "darkolivegreen", "tomato", "firebrick"
35 online_connections = null
46 var curr_day = d.getDate();
47 var curr_month = d.getMonth() + 1;
48 var curr_year = d.getFullYear();
49 today = curr_year + "-" + curr_month + "-" + curr_day;
54 function UrlParams(params) {
58 for (var key in params) {
59 if (params.hasOwnProperty(key)) {
60 out.push(key + '=' + encodeURIComponent(params[key]));
68 function Macro(template, values) {
69 return templates[template].replace(/\$(\w+)\;/g,function (s,name) {
74 function ColumnMacro(column, values, macro = "column"){
75 var columnrec = columns[column]
78 if (columnrec.template_name) {
79 macro = columnrec.template_name
81 templatestr = columnrec.template
84 return templatestr.replace(/\$(\w+)\;/g,function (s,name) {
88 return Macro(macro,{VALUE:values[column]})
92 function HeaderMacro(column,macro = "header-column"){
93 var columnrec = columns[column]
95 var alias = columns[column].alias;
99 if (!(alias)) { alias = column }
100 return Macro(macro,{VALUE:alias})
103 function GetApi(onfinish,method,params) {
105 var req = new XMLHttpRequest();
107 req.onreadystatechange = function () {
108 if (this.readyState != 4) return;
109 if (this.status != 200) {
110 setTimeout(OnLoad,30000);
113 res = JSON.parse(this.responseText);
117 var url = urlbase+"?method="+method;
121 url = url + '&' + UrlParams(params)
125 req.open("GET", url, true);
126 req.withCredentials = true;
131 function UpdatePageProps(props) {
133 var logo = document.getElementById("brand");
134 logo.innerText = props["site-header"];
138 for (var i in res["columns"]) {
139 columns[res["columns"][i]["name"]] = {alias:res["columns"][i]["alias"],template:res["columns"][i]["template"],template_name:res["columns"][i]["template_name"]}
142 for (var i in res["templates"]) {
143 var mnemo = res["templates"][i]["mnemo"]
144 var body = res["templates"][i]["body"]
145 templates[mnemo] = body
148 dictionaries = res["dictionaries"]
151 for (var cat in cats) {
154 for (rep in category["reps"]) {
155 report = category["reps"][rep]
156 reps[report["mnemo"]] = report
157 reptext = Macro("menuitem",{ MNEMO:report["mnemo"], NAME:report["name"], DESCR:report["description"] })
158 innerHTML = innerHTML + reptext
160 grouptxt = Macro("menugroup",{ MNEMO:category["mnemo"], NAME:category["name"], DESCR:category["description"], MENUITEM: innerHTML})
161 menuInnerHTML = menuInnerHTML + grouptxt
163 menuInnerHTML = Macro("menuonline",{}) + menuInnerHTML
164 menuHTML = Macro("menu", { MENUGROUP: menuInnerHTML} )
165 var Left = document.getElementById("menu");
166 Left.innerHTML = menuHTML
172 function SetDates() {
173 var inp = document.getElementById("date-from")
174 inp.value = date_from
177 var inp = document.getElementById("date-to")
181 var inp = document.getElementById("report-button")
191 GetApi(UpdatePageProps,"get-base-config",null)
196 function ShowHide(id) {
197 var content = document.getElementById(id);
198 if (content.style.display === "block") {
199 content.style.display = "none";
201 content.style.display = "block";
205 function MergeTR(tr,th, macro = "column") {
208 if (!(th[i].startsWith('_'))) {
209 str = str + ColumnMacro(th[i],tr,macro)
215 function MergeTH(th, macro = "header-column") {
218 if (!(th[i].startsWith('_'))) {
219 str = str + HeaderMacro(th[i])
225 function ProduceRep(res) {
227 current_filter = res["filter"]
228 if (!current_filter) { current_filter = {} }
229 dictionary = res["dictionary"]
231 header_template = res["header"]
232 has_total = res["has_total"]
238 if (has_total == "1") {
244 table_row = Macro("table-row",{DATA:MergeTR(row_data,dictionary)})
245 innerHTML = innerHTML + table_row
248 headerHTML = Macro("header-row",{DATA:MergeTH(dictionary)})
250 if (has_total == "1") {
251 totalHTML = Macro("total-row",{DATA:MergeTR(total,dictionary)})
252 reportHTML = Macro("report-table-total",{HEADER:headerHTML,LINES:innerHTML,TOTAL:totalHTML})
254 reportHTML = Macro("report-table",{HEADER:headerHTML,LINES:innerHTML})
256 var body = document.getElementById("report-body")
257 body.innerHTML = reportHTML;
259 if (reps[current_rep].graph_x) {
261 var config = PrepareGraphDataset(data,reps[current_rep].graph_x,reps[current_rep].graph_y,reps[current_rep].graph_series)
262 config.options.responsive = true
264 config.options.scales = {
276 suggestedMin: 0, // minimum will be 0, unless there is a lower value.
287 function DrawGraph(config) {
288 var ctx = document.getElementById('canvas').getContext('2d')
289 var div = document.getElementById("report-graph");
290 canvas.width = div.style.width;
291 canvas.height = div.style.height;
292 window.Graph = new Chart(ctx, config);
295 function AssignColor(key) {
296 if (assigned_colors[key]) {
297 return assigned_colors[key]
300 if (graph_colors.length) {
301 var idx = Math.floor(Math.random() * graph_colors.length)
302 rand_color = graph_colors[idx]
303 graph_colors.splice(idx,1)
305 rand_color = "darkgray"
307 assigned_colors[key] = rand_color
311 function PrepareGraphDataset(data,graph_x,graph_y,graph_series) {
321 if (key == graph_x) {
322 if (!xvals.includes(Number(rec[key]))) {
323 xvals.push(Number(rec[key]))
326 if (key == graph_series) {
327 if (!series.includes(rec[key])) {
328 series.push(rec[key])
334 xvals.sort(function(a,b) { return a-b; })
337 for (var i in series) {
340 values[i].label = series[i]
341 values[i].fill = true
342 values[i].borderColor = AssignColor(values[i].label)
343 values[i].backgroundColor = AssignColor(values[i].label)
344 for (var j in xvals) {
345 values[i].data[j] = 0
349 for (var k in data) {
355 if (key == graph_x) {
356 xval = Number(rec[key])
358 if (key == graph_y) {
359 yval = Number(rec[key])
361 if (key == graph_series) {
365 var j = xvals.indexOf(xval)
366 var i = series.indexOf(dataset)
367 values[i].data[j] = yval
383 function AliasByName(dict,name) {
385 if (dict[i].name == name) { return dict[i].alias }
390 function AddTraffic(label,b) {
392 for (i in online_traffic) {
393 if (online_traffic[i].label == label) {
394 rec = online_traffic[i]
399 rec = { label: label, borderColor: AssignColor(label), backgroundColor: AssignColor(label), data: new Array(online_history).fill(0) }
400 online_traffic.push(rec)
402 rec.data[rec.data.length-1] += b
405 function ProduceOnline(res) {
407 if (!online_traffic) {
412 for (i = 1; i<=online_history; i++) {
414 time_labels.unshift(cur)
420 datasets: online_traffic,
437 suggestedMin: 0, // minimum will be 0, unless there is a lower value.
441 labelString: "Скорость, Кбит/c"
453 delta = (Date.now() - current_time)/1000
458 current_time = Date.now()
461 time_labels.push(current_time)
463 for (i = online_traffic.length-1; i>=0; i--) {
464 online_traffic[i].data.shift()
465 online_traffic[i].data.push(0)
468 dictionary = res["dictionary"]
470 header_template = res["header"]
476 var new_online_connections = []
478 dictionary.unshift("useralias")
481 user = row_data["_user"]
482 username = AliasByName(dictionaries['user_id'],user)
483 row_data["useralias"] = username
485 host = row_data["host"]
486 hostname = AliasByName(dictionaries['host_id'],host)
487 row_data["host"] = hostname
489 table_row = Macro("table-row",{DATA:MergeTR(row_data,dictionary)})
490 innerHTML = innerHTML + table_row
492 var bytes = Number(row_data['bytes'])
494 var idx = row_data["_ip"]+':'+row_data["_port"]
497 if (online_connections) {
498 last_bytes = online_connections[idx]
506 new_online_connections[idx] = bytes
508 AddTraffic(username,8*(bytes-last_bytes)/(1024*delta))
511 online_connections = new_online_connections
513 for (i = online_traffic.length-1; i>=0; i--) {
514 if (Math.max.apply(null,online_traffic[i].data) == 0) {
515 online_traffic.splice(i,1)
519 headerHTML = Macro("header-row",{DATA:MergeTH(dictionary)})
521 reportHTML = Macro("report-table",{HEADER:headerHTML,LINES:innerHTML})
523 var body = document.getElementById("report-body")
524 body.innerHTML = reportHTML;
526 timer = setTimeout(Online,refresh)
528 window.Graph.update()
532 function CancelRefresh() {
539 function ShowRep(id) {
542 var header = document.getElementById("report-name")
543 header.innerText = reps[id]["name"]
544 var body = document.getElementById("report-body")
545 body.innerText = "Отчет загружается..."
551 function ShowFilteredRep(id,filter) {
554 current_filter[i] = filter[i]
556 var header = document.getElementById("report-name")
557 header.innerText = reps[id]["name"]
558 var body = document.getElementById("report-body")
559 body.innerText = "Отчет загружается..."
565 function FilterSelect(name,dict,value) {
566 var str = '<select onchange="SetFilter(\''+name+'\',this);">'
568 if (dict[key].id==value) {
569 str = str + '<option selected value="'+dict[key].id+'">'+dict[key].name+"</option>"
571 str = str + '<option value="'+dict[key].id+'">'+dict[key].name+"</option>"
574 str = str + "</select>" + Macro("clear-filter",{NAME:name})
580 for (key in current_filter) {
581 var dict = dictionaries[key]
583 str = str + FilterSelect(key,dict,current_filter[key])
585 str = str + Macro("filter-display",{NAME:HeaderMacro(key),VALUE:current_filter[key]}) + Macro("clear-filter",{NAME:key})
591 function RefreshFilterPane() {
592 var filter = document.getElementById("report-dates")
594 filter.style.display = "block";
596 filter.style.display = "none";
598 var filter = document.getElementById("filter")
599 if (Object.keys(current_filter).length === 0) {
600 filter.style.display = "none";
601 filter.innerHTML = ''
603 filter.style.display = "inline-block";
604 filter.innerHTML = Filter()
609 online_traffic = null
610 var parameters = JSON.parse(JSON.stringify(current_filter))
611 parameters["mnemo"] = current_rep
612 parameters["date_from"] = date_from
613 parameters["date_to"] = date_to
614 GetApi(ProduceRep,"report",parameters);
615 var filter = document.getElementById("filter")
622 var header = document.getElementById("report-name")
623 header.innerText = "Активные соединения"
624 GetApi(ProduceOnline,"online",{});
628 function UpdateDates() {
629 var inp = document.getElementById("date-from")
630 date_from = inp.value
631 var inp = document.getElementById("date-to")
638 function SetFilter(name,select) {
639 current_filter[name] = select.value;
642 function ClearFilter(name) {
643 delete current_filter[name];
647 function DisplayGraph(on) {
648 var selector = document.getElementById("page-selector")
650 selector.style.display="block"
652 selector.style.display="none"
653 Display('report-body')
657 function Display(id) {
658 var elements = document.getElementsByClassName('report-block');
659 for (i=0; i<elements.length; i++) {
660 if (elements[i].id == id) {
661 elements[i].style.display = "block"
663 elements[i].style.display = "none"