Mercurial > roundup-cc
comparison graph.html @ 1:2df45f6ecd81
new appereance (solid and dotted lines), resonsive layout, new legend,
new structure, cronjob-friendly
dynamic generation of search-strings, dynamic recognition of error-values,
ignores non-numeric priority-IDs
author | sean |
---|---|
date | Tue, 14 Apr 2015 13:32:12 +0200 |
parents | 3f139db894f1 |
children | f198a92dd37f |
comparison
equal
deleted
inserted
replaced
0:3f139db894f1 | 1:2df45f6ecd81 |
---|---|
1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
2 <html> | 2 <html> |
3 <head> | 3 <head> |
4 <title> Issues </title> | 4 <title> Issues </title> |
5 <style type = text/css> | 5 <style type = text/css> |
6 | |
7 * { | |
8 font-family: "Sans-serif"; | |
9 font-size: 14px; | |
10 } | |
11 | |
6 .svg div{ | 12 .svg div{ |
7 font: 10px sans-serif; | 13 font: 10px; |
8 text-align: right; | 14 text-align: right; |
9 float: left; | 15 float: left; |
10 display: block; | 16 display: block; |
11 padding: 10px; | 17 padding: 10px; |
12 margin: 10px; | 18 margin: 10px; |
21 stroke-width: 1px; | 27 stroke-width: 1px; |
22 } | 28 } |
23 | 29 |
24 .line { | 30 .line { |
25 fill: none; | 31 fill: none; |
26 stroke-width: 2px; | 32 stroke-width: 3px; |
33 opacity: 1; | |
27 } | 34 } |
28 | 35 |
29 .line.critical { | 36 .line.critical { |
30 stroke: red; | 37 stroke: red; |
31 } | 38 } |
49 .line.bug.legend { | 56 .line.bug.legend { |
50 fill: violet; | 57 fill: violet; |
51 } | 58 } |
52 | 59 |
53 .line.feature { | 60 .line.feature { |
54 stroke: green; | 61 stroke: chartreuse; |
62 style: stroke-dasharray; | |
55 } | 63 } |
56 | 64 |
57 .line.feature.legend { | 65 .line.feature.legend { |
58 fill: green; | 66 fill: chartreuse; |
59 } | 67 } |
60 | 68 |
61 .line.wish { | 69 .line.wish { |
62 stroke: blue; | 70 stroke: blue; |
63 } | 71 } |
73 | 81 |
74 .grid path { | 82 .grid path { |
75 stroke-width: 0; | 83 stroke-width: 0; |
76 } | 84 } |
77 | 85 |
78 .title { | |
79 font: 15px sans-serif; | |
80 } | |
81 | |
82 .legend{ | |
83 font: 15px sans-serif; | |
84 } | |
85 | |
86 </style> | 86 </style> |
87 </head> | 87 </head> |
88 <body> | 88 <body> |
89 <div id="burndown_chart"></div> | 89 <div id="content" style="display: inline-block"></div> |
90 <script type="text/javascript" src="d3.v3.min.js"></script> | 90 <script type="text/javascript" src="d3.v3.min.js"></script> |
91 <script type="text/javascript"> | 91 <script type="text/javascript"> |
92 | 92 |
93 window.onresize = function(){ | |
94 document.getElementById("content").innerHTML = ""; | |
95 makeChart(); | |
96 }; | |
93 | 97 |
94 var critical=[]; | 98 var critical=[]; |
95 var urgent=[]; | 99 var urgent=[]; |
96 var bug=[]; | 100 var bug=[]; |
97 var feature=[]; | 101 var feature=[]; |
98 var wish=[]; | 102 var wish=[]; |
99 var timestamp=[]; | 103 var timestamp=[]; |
100 | 104 |
105 | |
106 | |
101 function assignIssueToDate(issueArray, dateArray){ | 107 function assignIssueToDate(issueArray, dateArray){ |
102 a = []; | 108 a = []; |
103 for (var i = 0; i < issueArray.length; i++) { | 109 for (var i = 0; i < issueArray.length; i++) { |
104 a.push({points: issueArray[i].points, date : dateArray[i].date}); | 110 a.push({points: issueArray[i].points, date : dateArray[i].date}); |
105 } | 111 } |
106 | 112 |
107 return a; | 113 return a; |
108 } | 114 } |
109 | 115 |
116 function limitDatesOnXAxis(limit){ | |
117 if ( timestamp.length < limit ){ | |
118 return timestamp.length; | |
119 } else { | |
120 return limit; | |
121 } | |
122 } | |
110 | 123 |
111 function maxInObject( array ){ | 124 function maxInObject( array ){ |
112 var maxVal = 0; | 125 var maxVal = 0; |
113 for (var i = 0; i < array.length; i++) { | 126 for (var i = 0; i < array.length; i++) { |
114 if (maxVal < array[i].points){ | 127 if (maxVal < array[i].points){ |
152 .ticks( ticknumber ); | 165 .ticks( ticknumber ); |
153 } | 166 } |
154 | 167 |
155 | 168 |
156 //append a svg_path. pretty generic | 169 //append a svg_path. pretty generic |
157 function draw_line(svg, data_array, css_class, line_object){ | 170 function draw_line(svg, data_array, css_class, line_object, lineShape){ |
158 svg.append("path") | 171 svg.append("path") |
159 .datum(assignIssueToDate(data_array, timestamp)) | 172 .datum(assignIssueToDate(data_array, timestamp)) |
160 .attr("class", css_class) | 173 .attr("class", css_class) |
174 .style("stroke-dasharray", (lineShape)) | |
161 .attr("d", line_object); | 175 .attr("d", line_object); |
162 } | 176 } |
163 | 177 |
164 | 178 |
165 //helper for the legend | 179 function makeLegend(svg, width){ |
166 function draw_legend_line(svg, width, Ypos, text){ | 180 |
167 svg.append("svg:text") | 181 var legend_distance = width+40; |
168 .attr("class", "legend") | 182 var top_distance = 20; |
169 .attr("x", width+50) | 183 var distance_steps = 50; |
170 .attr("y", Ypos) | 184 |
171 .text(text); | 185 |
172 | 186 function set_propper_distance(steps){ |
173 svg.append("rect") | 187 top_distance += steps; |
174 .attr("class", "line " + text.toLowerCase() + " legend") | 188 return top_distance; |
175 .attr("x", width+30) | 189 } |
176 .attr("y", Ypos-12) | 190 |
177 .attr("width", 15) | 191 function draw_legend_line(svg, width, Ypos, text, issues){ |
178 .attr("height", 15); | 192 svg.append("svg:text") |
179 } | 193 .attr("class", "legend") |
194 .attr("x", width-30 ) | |
195 .attr("y", Ypos) | |
196 .text(text + ":"); | |
197 | |
198 svg.append("svg:text") | |
199 .attr("class", "legend") | |
200 .attr("x", width+35 ) | |
201 .attr("y", Ypos) | |
202 .text(issues); | |
203 | |
204 svg.append("rect") | |
205 .attr("class", "line " + text.toLowerCase() + " legend") | |
206 .attr("x", width-30) | |
207 .attr("y", Ypos-20) | |
208 .attr("width", 100) | |
209 .attr("height", 2); | |
210 } | |
211 | |
212 draw_legend_line(svg, legend_distance, set_propper_distance(distance_steps), "Critical", critical[critical.length-1].points); | |
213 draw_legend_line(svg, legend_distance, set_propper_distance(distance_steps), "Urgent", urgent[urgent.length-1].points); | |
214 draw_legend_line(svg, legend_distance, set_propper_distance(distance_steps), "Bug", bug[bug.length-1].points); | |
215 draw_legend_line(svg, legend_distance, set_propper_distance(distance_steps), "Feature", feature[feature.length-1].points); | |
216 draw_legend_line(svg, legend_distance, set_propper_distance(distance_steps), "Wish", wish[wish.length-1].points); | |
217 } | |
218 | |
180 | 219 |
181 | 220 |
182 //draw the chart | 221 //draw the chart |
183 function makeChart(){ | 222 function makeChart(){ |
184 | 223 |
185 //declaration | 224 //declaration |
186 var sizeOfSystemBorders = 50; | 225 var sizeOfSystemBorders = 50; |
187 var margin = {top: 20, right: 200, bottom: 200, left: 65}, | 226 var margin = {top: 20, right: 100, bottom: 90, left: 60}, |
188 width = (document.documentElement.clientWidth-sizeOfSystemBorders) - margin.left - margin.right, | 227 width = (document.documentElement.clientWidth-sizeOfSystemBorders) - margin.left - margin.right, |
189 height = (document.documentElement.clientHeight-sizeOfSystemBorders) - (margin.top) - margin.bottom; | 228 height = (document.documentElement.clientHeight-sizeOfSystemBorders) - margin.top - margin.bottom; |
190 | 229 |
191 var x = d3.time.scale() | 230 var x = d3.time.scale() |
192 .range([0, width]); | 231 .range([0, width]); |
193 | 232 |
194 var y = d3.scale.linear() | 233 var y = d3.scale.linear() |
195 .range([height, 0]); | 234 .range([height, 0]); |
196 | 235 |
197 var base_line = d3.svg.line() | 236 var base_line = d3.svg.line() |
198 .x(function(d) { return x(d.date); }) | 237 .x(function(d) { return x(d.date); }) |
199 .y(function(d) { return y(d.points); }); | 238 .y(function(d) { return y(d.points); }); |
200 | |
201 var color_hash = { 0 : ["apple", "green"], | |
202 1 : ["mango", "orange"], | |
203 2 : ["cherry", "red"] | |
204 }; | |
205 | 239 |
206 //lines | 240 //lines |
207 var criticalLine = base_line; | 241 var criticalLine = base_line; |
208 var urgentLine = base_line; | 242 var urgentLine = base_line; |
209 var bugLine = base_line; | 243 var bugLine = base_line; |
211 var wishLine = base_line; | 245 var wishLine = base_line; |
212 var timestampLine = base_line; | 246 var timestampLine = base_line; |
213 | 247 |
214 | 248 |
215 //set domain of y axis | 249 //set domain of y axis |
216 | |
217 var yDomain = [ ]; | 250 var yDomain = [ ]; |
218 yDomain[0] = 0; | 251 yDomain[0] = 0; |
219 yDomain[1] = getMaxIssues(); | 252 yDomain[1] = getMaxIssues(); |
220 y.domain(d3.extent(yDomain, function(d){return d; })); | 253 y.domain(d3.extent(yDomain, function(d){return d; })); |
221 | 254 |
224 | 257 |
225 | 258 |
226 var xAxis = d3.svg.axis() | 259 var xAxis = d3.svg.axis() |
227 .scale(x) | 260 .scale(x) |
228 .orient("bottom") | 261 .orient("bottom") |
229 .tickFormat(d3.time.format.iso); | 262 .ticks(limitDatesOnXAxis(10)) |
263 .tickFormat(d3.time.format("%d.%m:%H:%M")); | |
264 // .tickFormat(d3.time.format("%X")); | |
265 // .tickFormat(d3.time.format.iso); | |
230 | 266 |
231 | 267 |
232 var yAxis = d3.svg.axis() | 268 var yAxis = d3.svg.axis() |
233 .scale(y) | 269 .scale(y) |
234 .orient("left"); | 270 .orient("left"); |
235 | 271 |
236 | 272 |
237 var svg = d3.select("body") | 273 var svg = d3.select("#content") |
238 .append("svg") | 274 .append("svg") |
239 .attr("class", "svg") | 275 .attr("class", "svg") |
240 .attr("width", width + margin.left + margin.right) | 276 .attr("width", width + margin.left + margin.right) |
241 .attr("height", height + margin.top + margin.bottom) | 277 .attr("height", height + margin.top + margin.bottom) |
242 .append("g") | 278 .append("g") |
257 | 293 |
258 | 294 |
259 // Draw the y Grid lines | 295 // Draw the y Grid lines |
260 svg.append("g") | 296 svg.append("g") |
261 .attr("class", "grid") | 297 .attr("class", "grid") |
262 .call(makeGrid(y, "left", getMaxIssues()) | 298 .call(makeGrid(y, "left", function(){return Math.min(getMaxIssues(), 50);}()) |
263 .tickSize(-width, 0, 0) | 299 .tickSize(-width, 0, 0) |
264 .tickFormat("") | 300 .tickFormat("") |
265 ); | 301 ); |
266 | 302 |
267 | 303 |
270 .attr("class", "x axis") | 306 .attr("class", "x axis") |
271 .attr("transform", "translate(0," + height + ")") | 307 .attr("transform", "translate(0," + height + ")") |
272 .call(xAxis) | 308 .call(xAxis) |
273 .selectAll("text") | 309 .selectAll("text") |
274 .style("text-anchor", "end") | 310 .style("text-anchor", "end") |
275 .attr("dx", "-.8em") | 311 .attr("dx", "-.5em") |
276 .attr("dy", ".15em") | 312 .attr("dy", ".1em") |
277 .attr("transform", function() { | 313 .attr("transform", function() { |
278 return "rotate(-65)"; | 314 return "rotate(-65)"; |
279 }); | 315 }); |
280 | 316 |
281 | 317 |
301 | 337 |
302 | 338 |
303 //Titel und Legende | 339 //Titel und Legende |
304 | 340 |
305 svg.append("svg:text") | 341 svg.append("svg:text") |
306 .attr("class", "title") | 342 .attr("class", "text") |
307 .attr("x", 10) | 343 .attr("x", 10) |
308 .attr("y", -5) | 344 .attr("y", -5) |
309 .text("Issues Nach Zeit"); | 345 .text("Issues Nach Zeit"); |
310 | 346 |
311 | 347 |
312 draw_legend_line(svg, width, 50, "Critical"); | 348 draw_line(svg, wish, "line wish", wishLine, "0, 0"); |
313 draw_legend_line(svg, width, 70, "Urgent"); | 349 draw_line(svg, feature, "line feature", featureLine, "3, 3"); |
314 draw_legend_line(svg, width, 90, "Bug"); | 350 draw_line(svg, bug, "line bug", bugLine, "7, 7"); |
315 draw_legend_line(svg, width, 110, "Feature"); | 351 draw_line(svg, urgent, "line urgent", urgentLine, "13, 13"); |
316 draw_legend_line(svg, width, 130, "Wish"); | 352 draw_line(svg, critical, "line critical", criticalLine, "17, 17"); |
317 | 353 |
318 | 354 |
319 draw_line(svg, critical, "line critical", criticalLine); | 355 makeLegend(svg, width); |
320 draw_line(svg, urgent, "line urgent", urgentLine); | 356 |
321 draw_line(svg, bug, "line bug", bugLine); | |
322 draw_line(svg, feature, "line feature", featureLine); | |
323 draw_line(svg, wish, "line wish", wishLine); | |
324 | 357 |
325 } | 358 } |
326 | 359 |
327 makeChart(); | 360 makeChart(); |
328 | 361 |