4 "salmon", "lightcoral", "crimson", "red", "darkred", "orangered",
5 "gold", "orange", "yellow", "darkkhaki", "lime", "green", "greenyellow",
6 "springgreen", "olive", "cyan", "turquoise", "teal", "lightskyblue",
7 "dodgerblue", "royalblue", "blue", "navy", "violet", "fuchsia",
8 "darkviolet", "purple", "deeppink", "gray", "darkslategray", "sandybrown",
9 "goldenrod", "chocolate", "saddlebrown", "maroon", "rosybrown", "sienna",
10 "brown", "dimgray", "mediumvioletred", "indigo", "orchid", "mediumpurple",
11 "steelblue", "powderblue", "lightseagreen", "cadetblue", "aquamarine",
12 "olivedrab", "chartreuse", "darkolivegreen", "tomato", "firebrick"
32 online_connections = null
44 var curr_day = d.getDate();
45 if (curr_day<10) { curr_day = '0' + curr_day; }
46 var curr_month = d.getMonth() + 1;
47 if (curr_month<10) { curr_month = '0' + curr_month; }
48 var curr_year = d.getFullYear();
49 return curr_year + "-" + curr_month + "-" + curr_day
53 var dToday = new Date();
54 dToday.setHours(0,0,0,0)
58 today = toDate(Today());
63 function UrlParams(params) {
67 for (var key in params) {
68 if (params.hasOwnProperty(key)) {
69 out.push(key + '=' + encodeURIComponent(params[key]));
77 function Macro(template, values) {
78 return templates[template].replace(/\$(\w+)\;/g,function (s,name) {
83 function ColumnMacro(column, values, macro = "column"){
84 var columnrec = columns[column]
87 if (columnrec.template_name) {
88 macro = columnrec.template_name
90 templatestr = columnrec.template
93 return templatestr.replace(/\$(\w+)\;/g,function (s,name) {
97 return Macro(macro,{VALUE:values[column]})
101 function HeaderMacro(column,macro = "header-column"){
102 var columnrec = columns[column]
104 var alias = columns[column].alias;
108 if (!(alias)) { alias = column }
109 return Macro(macro,{VALUE:alias})
112 function GetApi(onfinish,method,params) {
114 var req = new XMLHttpRequest();
116 req.onreadystatechange = function () {
117 if (this.readyState != 4) return;
118 if (this.status != 200) {
119 setTimeout(OnLoad,30000);
122 res = JSON.parse(this.responseText);
126 var url = urlbase+"?method="+method;
130 url = url + '&' + UrlParams(params)
134 req.open("GET", url, true);
135 req.withCredentials = true;
140 function UpdatePageProps(props) {
142 var logo = document.getElementById("brand");
143 logo.innerText = props["site-header"];
145 refresh = props["online_refresh"]
146 online_history = props["online_history"]
148 start_date = new Date(props["start_date"])
149 start_date.setHours(0,0,0,0)
153 for (var i in res["columns"]) {
154 columns[res["columns"][i]["name"]] = {alias:res["columns"][i]["alias"],template:res["columns"][i]["template"],template_name:res["columns"][i]["template_name"]}
157 for (var i in res["templates"]) {
158 var mnemo = res["templates"][i]["mnemo"]
159 var body = res["templates"][i]["body"]
160 templates[mnemo] = body
163 dictionaries = res["dictionaries"]
166 for (var cat in cats) {
169 for (rep in category["reps"]) {
170 report = category["reps"][rep]
171 reps[report["mnemo"]] = report
172 reptext = Macro("menuitem",{ MNEMO:report["mnemo"], NAME:report["name"], DESCR:report["description"] })
173 innerHTML = innerHTML + reptext
175 grouptxt = Macro("menugroup",{ MNEMO:category["mnemo"], NAME:category["name"], DESCR:category["description"], MENUITEM: innerHTML})
176 menuInnerHTML = menuInnerHTML + grouptxt
178 menuInnerHTML = Macro("menuonline",{}) + menuInnerHTML
179 menuHTML = Macro("menu", { MENUGROUP: menuInnerHTML} )
180 var Left = document.getElementById("menu");
181 Left.innerHTML = menuHTML
187 function SetDates() {
188 var inp = document.getElementById("date-from")
189 inp.value = date_from
192 var inp = document.getElementById("date-to")
196 var inp = document.getElementById("report-button")
206 GetApi(UpdatePageProps,"get-base-config",null)
211 function ShowHide(id) {
212 var content = document.getElementById(id);
213 if (content.style.display === "block") {
214 content.style.display = "none";
216 content.style.display = "block";
220 function MergeTR(tr,th, macro = "column") {
223 if (!(th[i].startsWith('_'))) {
224 str = str + ColumnMacro(th[i],tr,macro)
230 function MergeTH(th, macro = "header-column") {
233 if (!(th[i].startsWith('_'))) {
234 str = str + HeaderMacro(th[i])
240 function ProduceRep(res) {
242 current_filter = res["filter"]
243 if (!current_filter) { current_filter = {} }
244 dictionary = res["dictionary"]
246 header_template = res["header"]
247 has_total = res["has_total"]
253 if (has_total == "1") {
259 table_row = Macro("table-row",{DATA:MergeTR(row_data,dictionary)})
260 innerHTML = innerHTML + table_row
263 headerHTML = Macro("header-row",{DATA:MergeTH(dictionary)})
265 if (has_total == "1") {
266 totalHTML = Macro("total-row",{DATA:MergeTR(total,dictionary)})
267 reportHTML = Macro("report-table-total",{HEADER:headerHTML,LINES:innerHTML,TOTAL:totalHTML})
269 reportHTML = Macro("report-table",{HEADER:headerHTML,LINES:innerHTML})
271 var body = document.getElementById("report-body")
272 body.innerHTML = reportHTML;
274 if (reps[current_rep].graph_x) {
276 var config = PrepareGraphDataset(data,reps[current_rep].graph_x,reps[current_rep].graph_y,reps[current_rep].graph_series)
277 config.options.responsive = true
279 config.options.scales = {
291 suggestedMin: 0, // minimum will be 0, unless there is a lower value.
302 function DrawGraph(config) {
303 var ctx = document.getElementById('canvas').getContext('2d')
304 var div = document.getElementById("report-graph");
305 canvas.width = div.style.width;
306 canvas.height = div.style.height;
307 window.Graph = new Chart(ctx, config);
310 function AssignColor(key) {
311 if (assigned_colors[key]) {
312 return assigned_colors[key]
315 if (graph_colors.length) {
316 var idx = Math.floor(Math.random() * graph_colors.length)
317 rand_color = graph_colors[idx]
318 graph_colors.splice(idx,1)
320 rand_color = "darkgray"
322 assigned_colors[key] = rand_color
326 function PrepareGraphDataset(data,graph_x,graph_y,graph_series) {
336 if (key == graph_x) {
337 if (!xvals.includes(Number(rec[key]))) {
338 xvals.push(Number(rec[key]))
341 if (key == graph_series) {
342 if (!series.includes(rec[key])) {
343 series.push(rec[key])
349 xvals.sort(function(a,b) { return a-b; })
352 for (var i in series) {
355 values[i].label = series[i]
356 values[i].fill = true
357 values[i].borderColor = AssignColor(values[i].label)
358 values[i].backgroundColor = AssignColor(values[i].label)
359 for (var j in xvals) {
360 values[i].data[j] = 0
364 for (var k in data) {
370 if (key == graph_x) {
371 xval = Number(rec[key])
373 if (key == graph_y) {
374 yval = Number(rec[key])
376 if (key == graph_series) {
380 var j = xvals.indexOf(xval)
381 var i = series.indexOf(dataset)
382 values[i].data[j] = yval
398 function AliasByName(dict,name) {
400 if (dict[i].name == name) { return dict[i].alias }
405 function AddTraffic(label,b) {
407 for (i in online_traffic) {
408 if (online_traffic[i].label == label) {
409 rec = online_traffic[i]
414 rec = { label: label, borderColor: AssignColor(label), backgroundColor: AssignColor(label), data: new Array(online_history).fill(0) }
415 online_traffic.push(rec)
417 rec.data[rec.data.length-1] += b
420 function ProduceOnline(res) {
422 if (!online_traffic) {
427 for (i = 1; i<=online_history; i++) {
429 time_labels.unshift(cur)
435 datasets: online_traffic,
452 suggestedMin: 0, // minimum will be 0, unless there is a lower value.
456 labelString: "Скорость, Кбит/c"
468 delta = (Date.now() - current_time)/1000
473 current_time = Date.now()
476 time_labels.push(current_time)
478 for (i = online_traffic.length-1; i>=0; i--) {
479 online_traffic[i].data.shift()
480 online_traffic[i].data.push(0)
483 dictionary = res["dictionary"]
485 header_template = res["header"]
491 var new_online_connections = []
493 dictionary.unshift("useralias")
496 user = row_data["_user"]
497 username = AliasByName(dictionaries['user_id'],user)
498 row_data["useralias"] = username
500 host = row_data["host"]
501 hostname = AliasByName(dictionaries['host_id'],host)
502 row_data["host"] = hostname
504 table_row = Macro("table-row",{DATA:MergeTR(row_data,dictionary)})
505 innerHTML = innerHTML + table_row
507 var bytes = Number(row_data['bytes'])
509 var idx = row_data["_ip"]+':'+row_data["_port"]
512 if (online_connections) {
513 last_bytes = online_connections[idx]
521 new_online_connections[idx] = bytes
523 AddTraffic(username,8*(bytes-last_bytes)/(1024*delta))
526 online_connections = new_online_connections
528 for (i = online_traffic.length-1; i>=0; i--) {
529 if (Math.max.apply(null,online_traffic[i].data) == 0) {
530 online_traffic.splice(i,1)
534 headerHTML = Macro("header-row",{DATA:MergeTH(dictionary)})
536 reportHTML = Macro("report-table",{HEADER:headerHTML,LINES:innerHTML})
538 var body = document.getElementById("report-body")
539 body.innerHTML = reportHTML;
541 timer = setTimeout(Online,refresh)
543 window.Graph.update()
547 function CancelRefresh() {
554 function ShowRep(id) {
557 var header = document.getElementById("report-name")
558 header.innerText = reps[id]["name"]
559 var body = document.getElementById("report-body")
560 body.innerText = "Отчет загружается..."
566 function ShowFilteredRep(id,filter) {
569 current_filter[i] = filter[i]
571 var header = document.getElementById("report-name")
572 header.innerText = reps[id]["name"]
573 var body = document.getElementById("report-body")
574 body.innerText = "Отчет загружается..."
580 function FilterSelect(name,dict,value) {
581 var str = '<select onchange="SetFilter(\''+name+'\',this);">'
583 if (dict[key].id==value) {
584 str = str + '<option selected value="'+dict[key].id+'">'+dict[key].name+"</option>"
586 str = str + '<option value="'+dict[key].id+'">'+dict[key].name+"</option>"
589 str = str + "</select>" + Macro("clear-filter",{NAME:name})
595 for (key in current_filter) {
596 var dict = dictionaries[key]
598 str = str + FilterSelect(key,dict,current_filter[key])
600 str = str + Macro("filter-display",{NAME:HeaderMacro(key),VALUE:current_filter[key]}) + Macro("clear-filter",{NAME:key})
606 function RefreshFilterPane() {
607 var filter = document.getElementById("report-dates")
609 filter.style.display = "block";
611 filter.style.display = "none";
613 var filter = document.getElementById("filter")
614 if (Object.keys(current_filter).length === 0) {
615 filter.style.display = "none";
616 filter.innerHTML = ''
618 filter.style.display = "inline-block";
619 filter.innerHTML = Filter()
624 online_traffic = null
625 var parameters = JSON.parse(JSON.stringify(current_filter))
626 parameters["mnemo"] = current_rep
627 parameters["date_from"] = date_from
628 parameters["date_to"] = date_to
629 GetApi(ProduceRep,"report",parameters);
630 var filter = document.getElementById("filter")
637 var header = document.getElementById("report-name")
638 header.innerText = "Активные соединения"
639 GetApi(ProduceOnline,"online",{});
643 function UpdateDates() {
644 var inp = document.getElementById("date-from")
645 date_from = inp.value
646 var inp = document.getElementById("date-to")
653 function DateLeft() {
655 var dFrom = new Date(date_from)
656 var dTo = new Date(date_to)
657 var delta = Math.round(((dTo.getTime() - dFrom.getTime()))/(86400*1000))
658 dTo.setDate(dTo.getDate() - (1 + delta))
659 dFrom.setDate(dFrom.getDate() - (1 + delta))
660 if (dTo<start_date) {
663 if (dFrom<start_date) {
666 date_from = toDate(dFrom)
667 date_to = toDate(dTo)
671 function DateRight() {
674 var dFrom = new Date(date_from)
675 var dTo = new Date(date_to)
676 var delta = Math.round(((dTo.getTime() - dFrom.getTime()))/(86400*1000))
677 dFrom.setDate(dFrom.getDate() + 1 + delta)
678 dTo.setDate(dTo.getDate() + 1 + delta)
685 date_from = toDate(dFrom)
686 date_to = toDate(dTo)
690 function SetFilter(name,select) {
691 current_filter[name] = select.value;
694 function ClearFilter(name) {
695 delete current_filter[name];
699 function DisplayGraph(on) {
700 var selector = document.getElementById("page-selector")
702 selector.style.display="block"
704 selector.style.display="none"
705 Display('report-body')
709 function Display(id) {
710 var elements = document.getElementsByClassName('report-block');
711 for (i=0; i<elements.length; i++) {
712 if (elements[i].id == id) {
713 elements[i].style.display = "block"
715 elements[i].style.display = "none"