PluginProbe
WebTotem Security / 2.1.7
WebTotem Security v2.1.7
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 2.2.4 All 109 releases
wt-security / htdocs / js / Chart.js

Chart.js in WebTotem Security 2.1.7, at htdocs/js/Chart.js

257 lines 7.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 const data = waf_chart;
2
3 async function drawLineChart(dataset) {
4 const attacksAccessor = (d) => d.attacks;
5 const blockedAccessor = (d) => d.blocked;
6 const biggerAccessor = (d) =>
7 d.attacks > d.blocked ? d.attacks : d.blocked;
8 const dateParser = d3.timeParse("%Y-%m-%d");
9 const xAccessor = (d) => dateParser(d.date);
10
11 const chartWrapper = document.getElementById('line-chart')
12 let dimensions = {
13 width: chartWrapper.offsetWidth,
14 height: 251,
15 margin: {
16 top: 15,
17 right: 15,
18 bottom: 40,
19 left: 60,
20 },
21 };
22 dimensions.boundedWidth =
23 dimensions.width - dimensions.margin.left - dimensions.margin.right;
24 dimensions.boundedHeight =
25 dimensions.height - dimensions.margin.top - dimensions.margin.bottom;
26
27 const wrapper = d3
28 .select("#line-chart")
29 .append("svg")
30 .attr("width", dimensions.width)
31 .attr("height", dimensions.height);
32
33 const bounds = wrapper
34 .append("g")
35 .style(
36 "transform",
37 `translate(${dimensions.margin.left - 10}px, ${
38 dimensions.margin.top
39 }px)`
40 );
41
42 const yScale = d3
43 .scaleLinear()
44 .domain(d3.extent(dataset, biggerAccessor))
45 .range([dimensions.boundedHeight, 0]);
46 const xScale = d3
47 .scaleTime()
48 .domain(d3.extent(dataset, xAccessor))
49 .range([0, dimensions.boundedWidth]);
50
51 function make_y_gridlines() {
52 return d3.axisLeft(yScale).ticks(5);
53 }
54
55 bounds
56 .append("g")
57 .attr("class", "grid")
58 .call(
59 make_y_gridlines().tickSize(-dimensions.boundedWidth).tickFormat("")
60 );
61
62 const area1 = d3
63 .area()
64 .x((d) => xScale(xAccessor(d)))
65 .y0(dimensions.height)
66 .y1((d) => yScale(attacksAccessor(d)));
67
68 const area2 = d3
69 .area()
70 .x((d) => xScale(xAccessor(d)))
71 .y0(dimensions.height)
72 .y1((d) => yScale(blockedAccessor(d)));
73
74 bounds
75 .append("linearGradient")
76 .attr("id", "area-gradient1")
77 .attr("gradientUnits", "userSpaceOnUse")
78 .attr("x1", 0)
79 .attr("y1", yScale(0))
80 .attr("x2", 0)
81 .attr("y2", yScale(100))
82 .selectAll("stop")
83 .data([
84 { offset: "0%", color: "#d46c6a", opacity: 0 },
85 { offset: "100%", color: "#d46c6a", opacity: 0.6 },
86 ])
87 .enter()
88 .append("stop")
89 .attr("offset", function (d) {
90 return d.offset;
91 })
92 .attr("stop-color", function (d) {
93 return d.color;
94 })
95 .attr("stop-opacity", function (d) {
96 return d.opacity;
97 });
98
99 bounds
100 .append("linearGradient")
101 .attr("id", "area-gradient2")
102 .attr("gradientUnits", "userSpaceOnUse")
103 .attr("x1", 0)
104 .attr("y1", yScale(0))
105 .attr("x2", 0)
106 .attr("y2", yScale(100))
107 .selectAll("stop")
108 .data([
109 { offset: "0%", color: "#bace3d", opacity: 0 },
110 { offset: "100%", color: "#bace3d", opacity: 0.6 },
111 ])
112 .enter()
113 .append("stop")
114 .attr("offset", function (d) {
115 return d.offset;
116 })
117 .attr("stop-color", function (d) {
118 return d.color;
119 })
120 .attr("stop-opacity", function (d) {
121 return d.opacity;
122 });
123
124 const lineGenerator1 = d3
125 .line()
126 .x((d) => xScale(xAccessor(d)))
127 .y((d) => yScale(attacksAccessor(d)));
128 const lineGenerator2 = d3
129 .line()
130 .x((d) => xScale(xAccessor(d)))
131 .y((d) => yScale(attacksAccessor(d)));
132
133 const line1 = bounds
134 .append("path")
135 .datum(dataset)
136 .attr("d", lineGenerator1(dataset))
137 .attr("class", "area")
138 .attr("d", area1)
139 .style("fill", "url(#area-gradient1)");
140
141 const line2 = bounds
142 .append("path")
143 .datum(dataset)
144 .attr("d", lineGenerator2(dataset))
145 .attr("class", "area")
146 .attr("d", area2)
147 .style("fill", "url(#area-gradient2)");
148
149 const yAxisGenerator = d3.axisLeft().scale(yScale);
150 const xAxisGenerator = d3.axisBottom().scale(xScale);
151 const yAxis = bounds.append("g").attr("class", "axis").call(yAxisGenerator);
152 const xAxis = bounds
153 .append("g")
154 .call(xAxisGenerator)
155 .attr("class", "axis")
156 .style("transform", `translateY(${dimensions.boundedHeight}px)`);
157
158 const listeningRect = bounds
159 .append("rect")
160 .attr("class", "listening-rect")
161 .attr("width", dimensions.boundedWidth)
162 .attr("height", dimensions.boundedHeight)
163 .on("mousemove", onMouseMove)
164 .on("mouseleave", onMouseLeave);
165
166 const tooltipAttacks = d3.select("#tooltipAttacks");
167 const tooltipBlocked = d3.select("#tooltipBlocked");
168 const tooltipCircle1 = bounds
169 .append("circle")
170 .attr("class", "tooltip-circle")
171 .attr("r", 4)
172 .attr("stroke", "#F3F5F6")
173 .attr("fill", "#1D293F")
174 .attr("stroke-width", 2)
175 .style("opacity", 0);
176 const tooltipCircle2 = bounds
177 .append("circle")
178 .attr("class", "tooltip-circle")
179 .attr("r", 4)
180 .attr("stroke", "#F3F5F6")
181 .attr("fill", "#1D293F")
182 .attr("stroke-width", 2)
183 .style("opacity", 0);
184 function onMouseMove() {
185 const mousePosition = d3.mouse(this);
186 const hoveredDate = xScale.invert(mousePosition[0]);
187
188 const getDistanceFromHoveredDate = (d) =>
189 Math.abs(xAccessor(d) - hoveredDate);
190 const closestIndex = d3.scan(
191 dataset,
192 (a, b) =>
193 getDistanceFromHoveredDate(a) - getDistanceFromHoveredDate(b)
194 );
195 const closestDataPoint = dataset[closestIndex];
196
197 const closestXValue = xAccessor(closestDataPoint);
198 const closestAttacksValue = attacksAccessor(closestDataPoint);
199 const closestBlockedValue = blockedAccessor(closestDataPoint);
200
201 const x = xScale(closestXValue) + dimensions.margin.left + 8;
202 const yAttacks =
203 yScale(closestAttacksValue) + dimensions.margin.top + 10;
204 const yBlocked =
205 yScale(closestBlockedValue) + dimensions.margin.top + 10;
206
207 tooltipAttacks.style(
208 "transform",
209 `translate(` +
210 `calc( -50% + ${x}px),` +
211 `calc(-100% + ${yAttacks}px)` +
212 `)`
213 );
214 tooltipBlocked.style(
215 "transform",
216 `translate(` +
217 `calc( -50% + ${x}px),` +
218 `calc(-100% + ${yBlocked}px)` +
219 `)`
220 );
221
222 tooltipAttacks.style("opacity", 1);
223 tooltipBlocked.style("opacity", 1);
224
225 tooltipAttacks.select("#countAttacks").html(closestAttacksValue);
226 tooltipBlocked.select("#countBlocked").html(closestBlockedValue);
227 tooltipCircle1
228 .attr("cx", xScale(closestXValue))
229 .attr("cy", yScale(closestAttacksValue))
230 .style("opacity", 1);
231 tooltipCircle2
232 .attr("cx", xScale(closestXValue))
233 .attr("cy", yScale(closestBlockedValue))
234 .style("opacity", 1);
235 }
236
237 function onMouseLeave() {
238 tooltipAttacks.style("opacity", 0);
239 tooltipBlocked.style("opacity", 0);
240
241 tooltipCircle1.style("opacity", 0);
242 tooltipCircle2.style("opacity", 0);
243 }
244 }
245
246 drawLineChart(data);
247
248 var resizeTimer;
249 window.onresize = function (event) {
250 clearTimeout(resizeTimer);
251 resizeTimer = setTimeout(function () {
252 var s = d3.select("#line-chart").selectAll("svg");
253 s = s.remove();
254 drawLineChart(data);
255 }, 10);
256 };
257