PluginProbe
WebTotem Security / 2.3.24
WebTotem Security v2.3.24
3.0.2 3.0.1 3.0.0 trunk 1.0 1.1 1.2 1.3 1.3.1 1.3.2 1.3.3 2.0 2.1 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.1 2.2.2 2.2.3 All 110 releases
wt-security / htdocs / js / wtsec_Chart.js

wtsec_Chart.js in WebTotem Security 2.3.24, at htdocs/js/wtsec_Chart.js

602 lines 19.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 const isDarkThemeSet = ()=> {
2 return !!document.querySelector(".wtotem_theme—dark")}
3 ;
4
5 async function drawLineChart(dataset) {
6 var diagram = document.getElementById('wtotem_chart_diagram');
7 var days = diagram.dataset.days;
8
9 const attacksAccessor = (d) => d.attacks;
10 const blockedAccessor = (d) => d.blocked;
11 const biggerAccessor = (d) =>
12 d.attacks > d.blocked ? d.attacks : d.blocked;
13 const dateParser = (days <= 1) ? d3.timeParse("%Y-%m-%d %H:%m:%M"): d3.timeParse("%Y-%m-%d");
14 const xAccessor = (d) => dateParser(d.date);
15
16
17 const chartWrapper = document.getElementById('line-chart')
18 let dimensions = {
19 width: chartWrapper.offsetWidth,
20 height: 251,
21 margin: {
22 top: 15,
23 right: 15,
24 bottom: 40,
25 left: 60,
26 },
27 };
28 dimensions.boundedWidth =
29 dimensions.width - dimensions.margin.left - dimensions.margin.right;
30 dimensions.boundedHeight =
31 dimensions.height - dimensions.margin.top - dimensions.margin.bottom;
32
33 const wrapper = d3
34 .select("#line-chart")
35 .append("svg")
36 .attr("width", dimensions.width)
37 .attr("height", dimensions.height);
38
39 const bounds = wrapper
40 .append("g")
41 .style(
42 "transform",
43 `translate(${dimensions.margin.left - 10}px, ${
44 dimensions.margin.top
45 }px)`
46 );
47
48 const yScale = d3
49 .scaleLinear()
50 .domain(d3.extent(dataset, biggerAccessor))
51 .range([dimensions.boundedHeight, 0]);
52 const xScale = d3
53 .scaleTime()
54 .domain(d3.extent(dataset, xAccessor))
55 .range([0, dimensions.boundedWidth]);
56
57 function make_y_gridlines() {
58 return d3.axisLeft(yScale).ticks(5);
59 }
60
61 bounds
62 .append("g")
63 .attr("class", "grid")
64 .call(
65 make_y_gridlines().tickSize(-dimensions.boundedWidth).tickFormat("")
66 );
67
68 const area1 = d3
69 .area()
70 .x((d) => xScale(xAccessor(d)))
71 .y0(dimensions.height)
72 .y1((d) => yScale(attacksAccessor(d)));
73
74 const area2 = d3
75 .area()
76 .x((d) => xScale(xAccessor(d)))
77 .y0(dimensions.height)
78 .y1((d) => yScale(blockedAccessor(d)));
79
80 const isDarkTheme = isDarkThemeSet();
81 const minOpacity = isDarkTheme ? 0.2 : 0.1;
82 const maxOpacity = isDarkTheme ? 0.8 : 0.6;
83
84 bounds
85 .append("linearGradient")
86 .attr("id", "area-gradient1")
87 .attr("gradientUnits", "userSpaceOnUse")
88 .attr("x1", 0)
89 .attr("y1", yScale(0))
90 .attr("x2", 0)
91 .attr("y2", yScale(100))
92 .selectAll("stop")
93 .data([
94 { offset: "0%", color: "#d46c6a", opacity: minOpacity},
95 { offset: "100%", color: "#d46c6a", opacity: maxOpacity},
96 ])
97 .enter()
98 .append("stop")
99 .attr("offset", function (d) {
100 return d.offset;
101 })
102 .attr("stop-color", function (d) {
103 return d.color;
104 })
105 .attr("stop-opacity", function (d) {
106 return d.opacity;
107 });
108
109 bounds
110 .append("linearGradient")
111 .attr("id", "area-gradient2")
112 .attr("gradientUnits", "userSpaceOnUse")
113 .attr("x1", 0)
114 .attr("y1", yScale(0))
115 .attr("x2", 0)
116 .attr("y2", yScale(100))
117 .selectAll("stop")
118 .data([
119 { offset: "0%", color: "#bace3d", opacity: minOpacity },
120 { offset: "100%", color: "#bace3d", opacity: maxOpacity},
121 ])
122 .enter()
123 .append("stop")
124 .attr("offset", function (d) {
125 return d.offset;
126 })
127 .attr("stop-color", function (d) {
128 return d.color;
129 })
130 .attr("stop-opacity", function (d) {
131 return d.opacity;
132 });
133
134 const lineGenerator1 = d3
135 .line()
136 .x((d) => xScale(xAccessor(d)))
137 .y((d) => yScale(attacksAccessor(d)));
138 const lineGenerator2 = d3
139 .line()
140 .x((d) => xScale(xAccessor(d)))
141 .y((d) => yScale(attacksAccessor(d)));
142
143 const line1 = bounds
144 .append("path")
145 .datum(dataset)
146 .attr("d", lineGenerator1(dataset))
147 .attr("class", "area")
148 .attr("d", area1)
149 .style("fill", "url(#area-gradient1)");
150
151 const line2 = bounds
152 .append("path")
153 .datum(dataset)
154 .attr("d", lineGenerator2(dataset))
155 .attr("class", "area")
156 .attr("d", area2)
157 .style("fill", "url(#area-gradient2)");
158
159 const yAxisGenerator = d3.axisLeft().scale(yScale);
160 // const xAxisGenerator = d3.axisBottom().scale(xScale);
161
162 let dateFormat = (days <= 1) ? d3.timeFormat("%H:%M") : (days > 31) ? d3.timeFormat("%b %Y") : d3.timeFormat("%b %d");
163 const xAxisGenerator = (days <= 1) ? d3.axisBottom().scale(xScale).ticks(d3.timeHour.every(2)).tickFormat(dateFormat) :
164 (days > 31) ? d3.axisBottom().scale(xScale).ticks(d3.timeMonth.every(1)).tickFormat(dateFormat) :
165 (days <= 7) ? d3.axisBottom().scale(xScale).ticks(d3.timeDay.every(1)).tickFormat(dateFormat) :
166 d3.axisBottom().scale(xScale).ticks(9).tickFormat(dateFormat);
167 //const xAxisGenerator = d3.axisBottom().scale(xScale).ticks(ticks).tickFormat(dateFormat);
168
169 const yAxis = bounds.append("g").attr("class", "axis").call(yAxisGenerator);
170 const xAxis = bounds
171 .append("g")
172 .call(xAxisGenerator)
173 .attr("class", "axis chart-date")
174 .style("transform", `translateY(${dimensions.boundedHeight}px)`);
175
176 const listeningRect = bounds
177 .append("rect")
178 .attr("class", "listening-rect")
179 .attr("width", dimensions.boundedWidth)
180 .attr("height", dimensions.boundedHeight)
181 .on("mousemove", onMouseMove)
182 .on("mouseleave", onMouseLeave);
183
184 const tooltipAttacks = d3.select("#tooltipAttacks");
185 const tooltipBlocked = d3.select("#tooltipBlocked");
186 const tooltipCircle1 = bounds
187 .append("circle")
188 .attr("class", "tooltip-circle")
189 .attr("r", 4)
190 .attr("stroke", "#F3F5F6")
191 .attr("fill", "#1D293F")
192 .attr("stroke-width", 2)
193 .style("opacity", 0);
194 const tooltipCircle2 = bounds
195 .append("circle")
196 .attr("class", "tooltip-circle")
197 .attr("r", 4)
198 .attr("stroke", "#F3F5F6")
199 .attr("fill", "#1D293F")
200 .attr("stroke-width", 2)
201 .style("opacity", 0);
202 function onMouseMove() {
203 const mousePosition = d3.mouse(this);
204 const hoveredDate = xScale.invert(mousePosition[0]);
205
206 const getDistanceFromHoveredDate = (d) =>
207 Math.abs(xAccessor(d) - hoveredDate);
208 const closestIndex = d3.scan(
209 dataset,
210 (a, b) =>
211 getDistanceFromHoveredDate(a) - getDistanceFromHoveredDate(b)
212 );
213 const closestDataPoint = dataset[closestIndex];
214
215 const closestXValue = xAccessor(closestDataPoint);
216 const closestAttacksValue = attacksAccessor(closestDataPoint);
217 const closestBlockedValue = blockedAccessor(closestDataPoint);
218
219 const x = xScale(closestXValue) + dimensions.margin.left + 8;
220 const yAttacks =
221 yScale(closestAttacksValue) + dimensions.margin.top + 10;
222 const yBlocked =
223 yScale(closestBlockedValue) + dimensions.margin.top + 10;
224
225 tooltipAttacks.style(
226 "transform",
227 `translate(` +
228 `calc( -50% + ${x}px),` +
229 `calc(-100% + ${yAttacks}px)` +
230 `)`
231 );
232 tooltipBlocked.style(
233 "transform",
234 `translate(` +
235 `calc( -50% + ${x}px),` +
236 `calc(-100% + ${yBlocked}px)` +
237 `)`
238 );
239
240 tooltipAttacks.style("opacity", 1);
241 tooltipBlocked.style("opacity", 1);
242
243 tooltipAttacks.select("#countAttacks").html(closestAttacksValue);
244 tooltipBlocked.select("#countBlocked").html(closestBlockedValue);
245 tooltipCircle1
246 .attr("cx", xScale(closestXValue))
247 .attr("cy", yScale(closestAttacksValue))
248 .style("opacity", 1);
249 tooltipCircle2
250 .attr("cx", xScale(closestXValue))
251 .attr("cy", yScale(closestBlockedValue))
252 .style("opacity", 1);
253 }
254
255 function onMouseLeave() {
256 tooltipAttacks.style("opacity", 0);
257 tooltipBlocked.style("opacity", 0);
258
259 tooltipCircle1.style("opacity", 0);
260 tooltipCircle2.style("opacity", 0);
261 }
262 }
263
264 const drawWafChart = (data) => {
265 var firewallChart = d3.select("#line-chart").selectAll("svg")
266 firewallChart = firewallChart.remove();
267 drawLineChart(data);
268 };
269
270 if(typeof waf_chart == "object"){
271 drawWafChart(waf_chart);
272 }
273
274 var resizeTimerFirewallChart;
275 window.onresize = function (event) {
276 clearTimeout(resizeTimerFirewallChart);
277 resizeTimerFirewallChart = setTimeout(function () {
278 drawLineChart(waf_chart);
279 }, 10);
280 };
281
282 // server-status
283 async function drawServerStatusChart(id, elementSelector, tooltipSelector, tooltipValueSelector, color, dataset) {
284 const dataAccessor = (d) => d.value;
285
286 let diagram = document.querySelector(elementSelector);
287 let days = diagram.dataset.days;
288
289 const dateParser = (days <= 1) ? d3.timeParse("%Y-%m-%d %H:%m:%M"): d3.timeParse("%Y-%m-%d");
290
291 const xAccessor = (d) => dateParser(d.date);
292
293 const chartWrapper = document.querySelector(elementSelector);
294 let dimensions = {
295 width: chartWrapper.offsetWidth,
296 height: 251,
297 margin: {
298 top: 15,
299 right: 15,
300 bottom: 40,
301 left: 60,
302 },
303 };
304 dimensions.boundedWidth =
305 dimensions.width - dimensions.margin.left - dimensions.margin.right;
306 dimensions.boundedHeight =
307 dimensions.height - dimensions.margin.top - dimensions.margin.bottom;
308
309 const wrapper = d3
310 .select(elementSelector)
311 .append("svg")
312 .attr("width", dimensions.width)
313 .attr("height", dimensions.height);
314
315 const bounds = wrapper
316 .append("g")
317 .style(
318 "transform",
319 `translate(${dimensions.margin.left - 10}px, ${
320 dimensions.margin.top
321 }px)`
322 );
323
324 const yScale = d3
325 .scaleLinear()
326 .domain(d3.extent(dataset, dataAccessor))
327 .range([dimensions.boundedHeight, 0]);
328 const xScale = d3
329 .scaleTime()
330 .domain(d3.extent(dataset, xAccessor))
331 .range([0, dimensions.boundedWidth]);
332
333 function make_y_gridlines() {
334 return d3.axisLeft(yScale).ticks(5);
335 }
336
337 bounds
338 .append("g")
339 .attr("class", "grid")
340 .call(
341 make_y_gridlines().tickSize(-dimensions.boundedWidth).tickFormat("")
342 );
343
344 const area1 = d3
345 .area()
346 .x((d) => xScale(xAccessor(d)))
347 .y0(dimensions.height)
348 .y1((d) => yScale(dataAccessor(d)));
349
350 const gradientAreaId = "area-gradient-" + id;
351
352 const isDarkTheme = isDarkThemeSet();
353 const minOpacity = isDarkTheme ? 0.2 : 0.1;
354 const maxOpacity = isDarkTheme ? 0.8 : 0.6;
355
356 bounds
357 .append("linearGradient")
358 .attr("id", gradientAreaId)
359 .attr("gradientUnits", "userSpaceOnUse")
360 .attr("x1", 0)
361 .attr("y1", yScale(0))
362 .attr("x2", 0)
363 .attr("y2", yScale(100))
364 .selectAll("stop")
365 .data([
366 { offset: "0%", color: color, opacity: minOpacity },
367 { offset: "100%", color: color, opacity: maxOpacity },
368 ])
369 .enter()
370 .append("stop")
371 .attr("offset", function (d) {
372 return d.offset;
373 })
374 .attr("stop-color", function (d) {
375 return d.color;
376 })
377 .attr("stop-opacity", function (d) {
378 return d.opacity;
379 });
380
381 const lineGenerator1 = d3
382 .line()
383 .x((d) => xScale(xAccessor(d)))
384 .y((d) => yScale(dataAccessor(d)));
385
386 const line1 = bounds
387 .append("path")
388 .datum(dataset)
389 .attr("d", lineGenerator1(dataset))
390 .attr("class", "area")
391 .attr("d", area1)
392 .style("fill", "url(#"+gradientAreaId+")");
393
394 const yAxisGenerator = d3.axisLeft().scale(yScale);
395 // const xAxisGenerator = d3.axisBottom().scale(xScale);
396 let dateFormat = (days <= 1) ? d3.timeFormat("%H:%M") : (days > 31) ? d3.timeFormat("%b %Y") : d3.timeFormat("%b %d");
397 const xAxisGenerator = (days <= 1) ? d3.axisBottom().scale(xScale).ticks(d3.timeHour.every(2)).tickFormat(dateFormat) :
398 (days > 31) ? d3.axisBottom().scale(xScale).ticks(d3.timeMonth.every(1)).tickFormat(dateFormat) :
399 (days <= 7) ? d3.axisBottom().scale(xScale).ticks(d3.timeDay.every(1)).tickFormat(dateFormat) :
400 d3.axisBottom().scale(xScale).ticks(9).tickFormat(dateFormat);
401
402 const yAxis = bounds.append("g").attr("class", "axis").call(yAxisGenerator);
403 const xAxis = bounds
404 .append("g")
405 .call(xAxisGenerator)
406 .attr("class", "axis")
407 .style("transform", `translateY(${dimensions.boundedHeight}px)`);
408
409 const listeningRect = bounds
410 .append("rect")
411 .attr("class", "listening-rect")
412 .attr("width", dimensions.boundedWidth)
413 .attr("height", dimensions.boundedHeight)
414 .on("mousemove", onMouseMove)
415 .on("mouseleave", onMouseLeave);
416
417 const tooltipData = d3.select(tooltipSelector);
418 const tooltipCircle1 = bounds
419 .append("circle")
420 .attr("class", "tooltip-circle")
421 .attr("r", 4)
422 .attr("stroke", "#F3F5F6")
423 .attr("fill", "#1D293F")
424 .attr("stroke-width", 2)
425 .style("opacity", 0);
426
427 function onMouseMove() {
428 const mousePosition = d3.mouse(this);
429 const hoveredDate = xScale.invert(mousePosition[0]);
430
431 const getDistanceFromHoveredDate = (d) =>
432 Math.abs(xAccessor(d) - hoveredDate);
433 const closestIndex = d3.scan(
434 dataset,
435 (a, b) =>
436 getDistanceFromHoveredDate(a) - getDistanceFromHoveredDate(b)
437 );
438 const closestDataPoint = dataset[closestIndex];
439
440 const closestXValue = xAccessor(closestDataPoint);
441 const closestValue = dataAccessor(closestDataPoint);
442
443 const x = xScale(closestXValue) + dimensions.margin.left + 8;
444 const yAttacks =
445 yScale(closestValue) + dimensions.margin.top + 10;
446
447 tooltipData.style(
448 "transform",
449 `translate(` +
450 `calc( -50% + ${x}px),` +
451 `calc(-100% + ${yAttacks}px)` +
452 `)`
453 );
454
455 tooltipData.style("opacity", 1);
456
457 tooltipData.select(tooltipValueSelector).html(closestValue);
458 tooltipCircle1
459 .attr("cx", xScale(closestXValue))
460 .attr("cy", yScale(closestValue))
461 .style("opacity", 1);
462 }
463
464 function onMouseLeave() {
465 tooltipData.style("opacity", 0);
466 tooltipCircle1.style("opacity", 0);
467 }
468 }
469
470 const drawRamChart = (data) => {
471 const ramChartSelector = "#ram-chart";
472 const ramTooltipSelector = "#tooltipRam";
473 const ramTooltipValueSelector = "#countRam";
474 const ramChartColor = "#3d50df";
475
476
477 let chartRam = d3.select(ramChartSelector).selectAll("svg")
478 chartRam = chartRam.remove();
479
480 drawServerStatusChart("ram", ramChartSelector, ramTooltipSelector, ramTooltipValueSelector, ramChartColor, data);
481 }
482
483
484 if(typeof serverStatusRam == "object"){
485 drawRamChart(serverStatusRam);
486 }
487
488
489 const drawCpuChart = (data) => {
490 const cpuChartSelector = "#cpu-chart";
491 const cpuTooltipSelector = "#tooltipCpu";
492 const cpuTooltipValueSelector = "#countCpu";
493 const cpuChartColor = "#6d3594";
494
495 let chartCpu = d3.select(cpuChartSelector).selectAll("svg");
496 chartCpu = chartCpu.remove();
497
498 drawServerStatusChart("cpu", cpuChartSelector, cpuTooltipSelector, cpuTooltipValueSelector, cpuChartColor, data);
499 }
500
501 if(typeof serverStatusCpu == "object") {
502 drawCpuChart(serverStatusCpu);
503 }
504
505
506 var resizeTimerRamChart;
507 var resizeTimerCpuChart;
508
509 window.onresize = function (event) {
510
511 if (document.querySelector("#ram-chart") !== null) {
512 clearTimeout(resizeTimerRamChart);
513 resizeTimerRamChart = setTimeout(function () {
514 drawRamChart(serverStatusRam);
515 }, 10);
516 }
517
518 if (document.querySelector("#cpu-chart") !== null) {
519 clearTimeout(resizeTimerCpuChart);
520 resizeTimerCpuChart = setTimeout(function () {
521 drawCpuChart(serverStatusCpu);
522 }, 10);
523 }
524 };
525
526
527 const colorModeToggle = document.querySelector("#color_scheme_toggle");
528
529 const addThemeChangeEventListener = (callback)=>{
530 colorModeToggle.addEventListener("change", callback)
531 }
532
533
534
535 addThemeChangeEventListener(()=>{
536 drawCpuChart(serverStatusCpu);
537 drawRamChart(serverStatusRam);
538 });
539
540
541 // disk-chart
542
543 async function drawDiskChart_(elementSelector, data) {
544 // set the dimensions and margins of the graph
545 var width = 150
546 height = 150
547 margin = 1
548
549 // The radius of the pieplot is half the width or half the height (smallest one). I subtract a bit of margin.
550 var radius = Math.min(width, height) / 2 - margin
551
552 // append the svg object to the div called 'my_dataviz'
553 var svg = d3.select(elementSelector)
554 .append("svg")
555 .attr("width", width)
556 .attr("height", height)
557 .append("g")
558 .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
559
560 // Create dummy data
561 // var data = {a: 9, b: 20, c:30, d:8, e:12}
562
563 // set the color scale
564 var color = d3.scaleOrdinal()
565 .domain(data)
566 .range(["#5E6977", "#3D50DF"])
567
568 // Compute the position of each group on the pie:
569 var pie = d3.pie()
570 .value(function(d) {return d.value; })
571 var data_ready = pie(d3.entries(data))
572
573 // Build the pie chart: Basically, each part of the pie is a path that we build using the arc function.
574 svg
575 .selectAll('whatever')
576 .data(data_ready)
577 .enter()
578 .append('path')
579 .attr('d', d3.arc()
580 .innerRadius(30) // This is the size of the donut hole
581 .outerRadius(radius)
582 )
583 .attr('fill', function(d){ return(color(d.data.key)) })
584 .attr("stroke", "white")
585 .style("stroke-width", "15px")
586 .style("opacity", 1)
587
588 }
589
590
591 const drawDiskChart = (data) => {
592 const diskData = {use: data['use'], free: data['free']};
593 const discChartSelector = "#disk-chart";
594 drawDiskChart_(discChartSelector, diskData);
595 };
596
597 if(typeof serverStatusDiscUsage == "object") {
598 drawDiskChart(serverStatusDiscUsage);
599 }
600
601
602