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
43 var curr_day = d.getDate();
44 if (curr_day<10) { curr_day = '0' + curr_day; }
45 var curr_month = d.getMonth() + 1;
46 if (curr_month<10) { curr_month = '0' + curr_month; }
47 var curr_year = d.getFullYear();
48 return curr_year + "-" + curr_month + "-" + curr_day
52 var dToday = new Date();
53 dToday.setHours(0,0,0,0)
57 today = toDate(Today());
62 function UrlParams(params) {
66 for (var key in params) {
67 if (params.hasOwnProperty(key)) {
68 out.push(key + '=' + encodeURIComponent(params[key]));
76 function Macro(template, values) {
77 return templates[template].replace(/\$(\w+)\;/g,function (s,name) {
82 function ColumnMacro(column, values, macro = "column"){
83 var columnrec = columns[column]
86 if (columnrec.template_name) {
87 macro = columnrec.template_name
89 templatestr = columnrec.template
92 return templatestr.replace(/\$(\w+)\;/g,function (s,name) {
96 return Macro(macro,{VALUE:values[column]})
100 function HeaderMacro(column,macro = "header-column"){
101 var columnrec = columns[column]
103 var alias = columns[column].alias;
107 if (!(alias)) { alias = column }
108 return Macro(macro,{VALUE:alias})
111 function GetApi(onfinish,method,params) {
113 var req = new XMLHttpRequest();
115 req.onreadystatechange = function () {
116 if (this.readyState != 4) return;
117 if (this.status != 200) {
118 setTimeout(OnLoad,30000);
121 res = JSON.parse(this.responseText);
125 var url = urlbase+"?method="+method;
129 url = url + '&' + UrlParams(params)
133 req.open("GET", url, true);
134 req.withCredentials = true;
139 function UpdatePageProps(props) {
141 var logo = document.getElementById("brand");
142 logo.innerText = props["site-header"];
144 refresh = props["online_refresh"]
145 online_history = props["online_history"]
149 for (var i in res["columns"]) {
150 columns[res["columns"][i]["name"]] = {alias:res["columns"][i]["alias"],template:res["columns"][i]["template"],template_name:res["columns"][i]["template_name"]}
153 for (var i in res["templates"]) {
154 var mnemo = res["templates"][i]["mnemo"]
155 var body = res["templates"][i]["body"]
156 templates[mnemo] = body
159 dictionaries = res["dictionaries"]
162 for (var cat in cats) {
165 for (rep in category["reps"]) {
166 report = category["reps"][rep]
167 reps[report["mnemo"]] = report
168 reptext = Macro("menuitem",{ MNEMO:report["mnemo"], NAME:report["name"], DESCR:report["description"] })
169 innerHTML = innerHTML + reptext
171 grouptxt = Macro("menugroup",{ MNEMO:category["mnemo"], NAME:category["name"], DESCR:category["description"], MENUITEM: innerHTML})
172 menuInnerHTML = menuInnerHTML + grouptxt
174 menuInnerHTML = Macro("menuonline",{}) + menuInnerHTML
175 menuHTML = Macro("menu", { MENUGROUP: menuInnerHTML} )
176 var Left = document.getElementById("menu");
177 Left.innerHTML = menuHTML
183 function SetDates() {
184 var inp = document.getElementById("date-from")
185 inp.value = date_from
188 var inp = document.getElementById("date-to")
192 var inp = document.getElementById("report-button")
202 GetApi(UpdatePageProps,"get-base-config",null)
207 function ShowHide(id) {
208 var content = document.getElementById(id);
209 if (content.style.display === "block") {
210 content.style.display = "none";
212 content.style.display = "block";
216 function MergeTR(tr,th, macro = "column") {
219 if (!(th[i].startsWith('_'))) {
220 str = str + ColumnMacro(th[i],tr,macro)
226 function MergeTH(th, macro = "header-column") {
229 if (!(th[i].startsWith('_'))) {
230 str = str + HeaderMacro(th[i])
236 function ProduceRep(res) {
238 current_filter = res["filter"]
239 if (!current_filter) { current_filter = {} }
240 dictionary = res["dictionary"]
242 header_template = res["header"]
243 has_total = res["has_total"]
249 if (has_total == "1") {
255 table_row = Macro("table-row",{DATA:MergeTR(row_data,dictionary)})
256 innerHTML = innerHTML + table_row
259 headerHTML = Macro("header-row",{DATA:MergeTH(dictionary)})
261 if (has_total == "1") {
262 totalHTML = Macro("total-row",{DATA:MergeTR(total,dictionary)})
263 reportHTML = Macro("report-table-total",{HEADER:headerHTML,LINES:innerHTML,TOTAL:totalHTML})
265 reportHTML = Macro("report-table",{HEADER:headerHTML,LINES:innerHTML})
267 var body = document.getElementById("report-body")
268 body.innerHTML = reportHTML;
270 if (reps[current_rep].graph_x) {
272 var config = PrepareGraphDataset(data,reps[current_rep].graph_x,reps[current_rep].graph_y,reps[current_rep].graph_series)
273 config.options.responsive = true
275 config.options.scales = {
287 suggestedMin: 0, // minimum will be 0, unless there is a lower value.
298 function DrawGraph(config) {
299 var ctx = document.getElementById('canvas').getContext('2d')
300 var div = document.getElementById("report-graph");
301 canvas.width = div.style.width;
302 canvas.height = div.style.height;
303 window.Graph = new Chart(ctx, config);
306 function AssignColor(key) {
307 if (assigned_colors[key]) {
308 return assigned_colors[key]
311 if (graph_colors.length) {
312 var idx = Math.floor(Math.random() * graph_colors.length)
313 rand_color = graph_colors[idx]
314 graph_colors.splice(idx,1)
316 rand_color = "darkgray"
318 assigned_colors[key] = rand_color
322 function PrepareGraphDataset(data,graph_x,graph_y,graph_series) {
332 if (key == graph_x) {
333 if (!xvals.includes(Number(rec[key]))) {
334 xvals.push(Number(rec[key]))
337 if (key == graph_series) {
338 if (!series.includes(rec[key])) {
339 series.push(rec[key])
345 xvals.sort(function(a,b) { return a-b; })
348 for (var i in series) {
351 values[i].label = series[i]
352 values[i].fill = true
353 values[i].borderColor = AssignColor(values[i].label)
354 values[i].backgroundColor = AssignColor(values[i].label)
355 for (var j in xvals) {
356 values[i].data[j] = 0
360 for (var k in data) {
366 if (key == graph_x) {
367 xval = Number(rec[key])
369 if (key == graph_y) {
370 yval = Number(rec[key])
372 if (key == graph_series) {
376 var j = xvals.indexOf(xval)
377 var i = series.indexOf(dataset)
378 values[i].data[j] = yval
394 function AliasByName(dict,name) {
396 if (dict[i].name == name) { return dict[i].alias }
401 function AddTraffic(label,b) {
403 for (i in online_traffic) {
404 if (online_traffic[i].label == label) {
405 rec = online_traffic[i]
410 rec = { label: label, borderColor: AssignColor(label), backgroundColor: AssignColor(label), data: new Array(online_history).fill(0) }
411 online_traffic.push(rec)
413 rec.data[rec.data.length-1] += b
416 function ProduceOnline(res) {
418 if (!online_traffic) {
423 for (i = 1; i<=online_history; i++) {
425 time_labels.unshift(cur)
431 datasets: online_traffic,
448 suggestedMin: 0, // minimum will be 0, unless there is a lower value.
452 labelString: "Скорость, Кбит/c"
464 delta = (Date.now() - current_time)/1000
469 current_time = Date.now()
472 time_labels.push(current_time)
474 for (i = online_traffic.length-1; i>=0; i--) {
475 online_traffic[i].data.shift()
476 online_traffic[i].data.push(0)
479 dictionary = res["dictionary"]
481 header_template = res["header"]
487 var new_online_connections = []
489 dictionary.unshift("useralias")
492 user = row_data["_user"]
493 username = AliasByName(dictionaries['user_id'],user)
494 row_data["useralias"] = username
496 host = row_data["host"]
497 hostname = AliasByName(dictionaries['host_id'],host)
498 row_data["host"] = hostname
500 table_row = Macro("table-row",{DATA:MergeTR(row_data,dictionary)})
501 innerHTML = innerHTML + table_row
503 var bytes = Number(row_data['bytes'])
505 var idx = row_data["_ip"]+':'+row_data["_port"]
508 if (online_connections) {
509 last_bytes = online_connections[idx]
517 new_online_connections[idx] = bytes
519 AddTraffic(username,8*(bytes-last_bytes)/(1024*delta))
522 online_connections = new_online_connections
524 for (i = online_traffic.length-1; i>=0; i--) {
525 if (Math.max.apply(null,online_traffic[i].data) == 0) {
526 online_traffic.splice(i,1)
530 headerHTML = Macro("header-row",{DATA:MergeTH(dictionary)})
532 reportHTML = Macro("report-table",{HEADER:headerHTML,LINES:innerHTML})
534 var body = document.getElementById("report-body")
535 body.innerHTML = reportHTML;
537 timer = setTimeout(Online,refresh)
539 window.Graph.update()
543 function CancelRefresh() {
550 function ShowRep(id) {
553 var header = document.getElementById("report-name")
554 header.innerText = reps[id]["name"]
555 var body = document.getElementById("report-body")
556 body.innerText = "Отчет загружается..."
562 function ShowFilteredRep(id,filter) {
565 current_filter[i] = filter[i]
567 var header = document.getElementById("report-name")
568 header.innerText = reps[id]["name"]
569 var body = document.getElementById("report-body")
570 body.innerText = "Отчет загружается..."
576 function FilterSelect(name,dict,value) {
577 var str = '<select onchange="SetFilter(\''+name+'\',this);">'
579 if (dict[key].id==value) {
580 str = str + '<option selected value="'+dict[key].id+'">'+dict[key].name+"</option>"
582 str = str + '<option value="'+dict[key].id+'">'+dict[key].name+"</option>"
585 str = str + "</select>" + Macro("clear-filter",{NAME:name})
591 for (key in current_filter) {
592 var dict = dictionaries[key]
594 str = str + FilterSelect(key,dict,current_filter[key])
596 str = str + Macro("filter-display",{NAME:HeaderMacro(key),VALUE:current_filter[key]}) + Macro("clear-filter",{NAME:key})
602 function RefreshFilterPane() {
603 var filter = document.getElementById("report-dates")
605 filter.style.display = "block";
607 filter.style.display = "none";
609 var filter = document.getElementById("filter")
610 if (Object.keys(current_filter).length === 0) {
611 filter.style.display = "none";
612 filter.innerHTML = ''
614 filter.style.display = "inline-block";
615 filter.innerHTML = Filter()
620 online_traffic = null
621 var parameters = JSON.parse(JSON.stringify(current_filter))
622 parameters["mnemo"] = current_rep
623 parameters["date_from"] = date_from
624 parameters["date_to"] = date_to
625 GetApi(ProduceRep,"report",parameters);
626 var filter = document.getElementById("filter")
633 var header = document.getElementById("report-name")
634 header.innerText = "Активные соединения"
635 GetApi(ProduceOnline,"online",{});
639 function UpdateDates() {
640 var inp = document.getElementById("date-from")
641 date_from = inp.value
642 var inp = document.getElementById("date-to")
649 function DateLeft() {
651 var dFrom = new Date(date_from)
652 var dTo = new Date(date_to)
653 var delta = Math.round(((dTo.getTime() - dFrom.getTime()))/(86400*1000))
654 dTo.setDate(dTo.getDate() - (1 + delta))
655 dFrom.setDate(dFrom.getDate() - (1 + delta))
656 date_from = toDate(dFrom)
657 date_to = toDate(dTo)
661 function DateRight() {
664 var dFrom = new Date(date_from)
665 var dTo = new Date(date_to)
666 var delta = Math.round(((dTo.getTime() - dFrom.getTime()))/(86400*1000))
667 dFrom.setDate(dFrom.getDate() + 1 + delta)
668 dTo.setDate(dTo.getDate() + 1 + delta)
675 date_from = toDate(dFrom)
676 date_to = toDate(dTo)
680 function SetFilter(name,select) {
681 current_filter[name] = select.value;
684 function ClearFilter(name) {
685 delete current_filter[name];
689 function DisplayGraph(on) {
690 var selector = document.getElementById("page-selector")
692 selector.style.display="block"
694 selector.style.display="none"
695 Display('report-body')
699 function Display(id) {
700 var elements = document.getElementsByClassName('report-block');
701 for (i=0; i<elements.length; i++) {
702 if (elements[i].id == id) {
703 elements[i].style.display = "block"
705 elements[i].style.display = "none"