See it running at http://bl.ocks.org/3529917
| id | name | priority | who | complexity | planned | time | status | outstanding | variance | |||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 01/02/2012 | T-024 | Organisation list in directory | MUST | Joe | Y | 5 | Complete | 1.5 | ||||
| 01/02/2012 | T-015 | Make term Commissions customisable | MUST | Natasha | Y | 6 | Complete | |||||
| 01/02/2012 | T-016 | Comments popup on select rates | MUST | Mike | Y | 3 | In Progress | 1 | 0 | |||
| 01/02/2012 | T-0169 | Upgrade Centos Box | MUST | Joe | Y | 2 | In Progress | 2 | -1 | 1 | ||
| 01/02/2012 | T-013 | Search in Documents on selected folder | MUST | Natasha | Y | 6 | In Progress | 1 | 0 | |||
| 01/02/2012 | T-014 | Separate Document system for LA and Legals | MUST | Joe | Y | 9 | In Progress | 7 | 3 | -3 | ||
| 01/02/2012 | T-017 | Demo of Look and Feel of Documents front end | MUST | Natasha | Y | 5 | In Progress | 2.5 | 1 | 1 | ||
| 01/02/2012 | T-021 | Fix error where forum filename is greater than 100chars | MUST | Mike | Y | 4 | Not Started | 0 | ||||
| 01/02/2012 | T-025 | Fix admin so structure of categories displayed | MUST | Mike | Y | 2.5 | Complete | 0.5 | ||||
| 01/02/2012 | T-027 | Reorganise git repos in Assembla | MUST | Joe | Y | 3 | Not Started | |||||
| 01/02/2012 | T-033 | Tree not showing correctly in documents | MUST | Natasha | Y | 1 | In Progress | 0.5 | ||||
| 01/02/2012 | T-052 | Add Cacheing | MUST | Mike | Y | 1.5 | Complete | |||||
| 01/02/2012 | T-055 | Allow custom ordering of document categories | MUST | Joe | Y | 0.5 | Not Started | |||||
| 01/02/2012 | T-056 | Pressing enter on date button triggers cancel | MUST | Joe | N | 1 | Not Started | |||||
| 01/02/2012 | T-057 | Ajax not working on IE when selecting org | MUST | Natasha | Y | 6 | Not Started | |||||
| 01/02/2012 | T-060 | Send Reminder Email as required | SHOULD | Mike | Y | 3 | Complete | 1 | ||||
| 01/02/2012 | T-061 | Attach Document to response in Forum | SHOULD | Joe | Y | 4 | Not Started | |||||
| 01/02/2012 | T-062 | Forum thread notifications | SHOULD | Natasha | Y | 9 | Complete | |||||
| 01/02/2012 | T-063 | Group email notification | SHOULD | Mike | Y | 8 | In Progress | 7 | 1 | |||
| 01/02/2012 | T-064 | Admin can see Who is logged in | SHOULD | Joe | N | 9 | Not Started | |||||
| 01/02/2012 | T-067 | Extend Audit Trail | SHOULD | Natasha | Y | 12 | Complete | -6 | ||||
| 01/02/2012 | T-068 | Maintenance Links | SHOULD | Mike | Y | 4 | Complete | -3 | ||||
| 01/02/2012 | T-094 | Browse prices button | SHOULD | Joe | Y | 6 | Not Started | |||||
| 01/02/2012 | T-095 | Group email to be only available to the administrator | SHOULD | Natasha | Y | 5 | Complete | -1 | ||||
| 01/02/2012 | T-096 | Update cribsheet | COULD | Mike | Y | 2 | Not Started | |||||
| 01/02/2012 | T-0103 | Awarded missing from Estimated Tab | COULD | Joe | Y | 7 | Complete | 3 | ||||
| 01/02/2012 | T-0105 | New cribsheet | COULD | Natasha | Y | 7 | Not Started | |||||
| 01/02/2012 | T-0111 | Document not being added on forum response | COULD | Mike | N | 6 | Not Started | |||||
| 01/02/2012 | T-0114 | Can't delete users once active | WISH | Joe | Y | 3 | Not Started | |||||
| 01/02/2012 | T-0125 | Add course organiser on notification | WISH | Natasha | Y | 2.5 | In Progress | 1 | ||||
| 01/02/2012 | T-0126 | Setup demonstration system for Demo | MUST | Joe | Y | 3 | Not Started | |||||
| 01/02/2012 | T-0133 | Fix forum pagination problem properly | MUST | Natasha | Y | 3 | Not Started | |||||
| 01/02/2012 | T-0145 | In Directory, tickbox to select all filtered users | MUST | Joe | Y | 3 | Complete | 0.5 | ||||
| 01/02/2012 | T-0146 | Merge user and user profile in admin | MUST | Natasha | Y | 2 | Not Started | |||||
| 01/02/2012 | T-0147 | Have multiple documents on an estimate | MUST | Mike | Y | 2 | Not Started |
| <html> | |
| <head> | |
| <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> | |
| <title>Kanban Treemap</title> | |
| <script src="http://d3js.org/d3.v2.js"></script> | |
| <script src=" https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> | |
| <link href='http://fonts.googleapis.com/css?family=Tienne' rel='stylesheet' type='text/css'> | |
| <style> | |
| body { text-align: center; margin: auto; } | |
| p.source { font-style: italic; } | |
| a { color: blue; } | |
| svg { | |
| display: block; | |
| margin: auto; | |
| } | |
| rect { | |
| fill: none; | |
| stroke: #fff; | |
| } | |
| .axis path, .axis line { | |
| fill: none; | |
| stroke: #000; | |
| shape-rendering: crispEdges; | |
| } | |
| sup, sub { | |
| line-height: 0; | |
| } | |
| q:before, | |
| blockquote:before { | |
| content: "“"; | |
| } | |
| q:after, | |
| blockquote:after { | |
| content: "â€"; | |
| } | |
| blockquote:before { | |
| position: absolute; | |
| left: 2em; | |
| } | |
| blockquote:after { | |
| position: absolute; | |
| } | |
| .bucket { | |
| width: 300px; | |
| height: 500px; | |
| float:left; | |
| } | |
| #bucket1, #bucket2, #bucket3 { | |
| width: 240px; | |
| height: 500px; | |
| margin: 30px; | |
| background: #bbb; | |
| } | |
| text { | |
| pointer-events: none; | |
| } | |
| .grandparent text { | |
| font-weight: bold; | |
| } | |
| rect { | |
| fill: none; | |
| stroke: #fff; | |
| } | |
| rect.parent, | |
| .grandparent rect { | |
| stroke-width: 2px; | |
| } | |
| .grandparent rect { | |
| fill: #fff; | |
| } | |
| .children rect.parent, | |
| .grandparent rect { | |
| cursor: pointer; | |
| } | |
| rect.parent { | |
| pointer-events: all; | |
| } | |
| .children:hover rect.child, | |
| .grandparent:hover rect { | |
| fill: #aaa; | |
| } | |
| </style> | |
| <script> | |
| $(document).ready(function() { | |
| $(":button").click(function() { | |
| alert("Handler for .click() called."); | |
| }); | |
| }); | |
| </script> | |
| <h1>Phoebe's Kanban Treemap</h1> | |
| <div class="bucket"><h3>Not Started</h3><div id="bucket1"></div></div> | |
| <div class="bucket"><h3>In Progress</h3><div id="bucket2"></div></div> | |
| <div class="bucket"><h3>Complete</h3><div id="bucket3"></div></div> | |
| <div id="filter"> | |
| Filter for <span id="who_filter"></span> | |
| Check to Highlight <span id="who_high"></span> | |
| </div> | |
| <script type="text/javascript"> | |
| var w = 240, | |
| h = 500, | |
| color = d3.scale.category20c(), | |
| root, | |
| node, | |
| master, | |
| data, | |
| bucket1_data, | |
| bucket2_data, | |
| bucket3_data, | |
| totals, | |
| total_time; | |
| var treemap1 = d3.layout.treemap() | |
| .children(function(d) { return d.values; }) | |
| .value(function(d) { return d.time; }); | |
| var treemap2 = d3.layout.treemap() | |
| .children(function(d) { return d.values; }) | |
| .value(function(d) { return d.time; }); | |
| var treemap3 = d3.layout.treemap() | |
| .children(function(d) { return d.values; }) | |
| .value(function(d) { return d.time; }); | |
| var svg_b1 = d3.select("#bucket1") | |
| .attr("width", w + "px") | |
| .attr("height", h + "px") | |
| .append("svg:svg") | |
| .append("svg:g"); | |
| var svg_b2 = d3.select("#bucket2") | |
| .attr("width", w + "px") | |
| .attr("height", h + "px") | |
| .append("svg:svg") | |
| .append("svg:g"); | |
| var svg_b3 = d3.select("#bucket3") | |
| .attr("width", w + "px") | |
| .attr("height", h + "px") | |
| .append("svg:svg") | |
| .append("svg:g"); | |
| //load csv and copy to global variable | |
| d3.csv("./data_project.csv",function(csv) { | |
| master=data=csv; | |
| init(master); | |
| }); | |
| d3.select("#filter").on("change", redraw); | |
| function init(){ | |
| var nested_data = d3.nest() | |
| .key(function(d) { return d.who}).sortKeys(d3.ascending) | |
| .rollup(function(leaves) { return leaves.length; }) | |
| .entries(master); | |
| // select list for filtering | |
| var list = d3.select("#who_filter").append("select") | |
| .attr("class", "filter") | |
| .attr("id", "who_select"); | |
| list.selectAll("option") | |
| .data(nested_data) | |
| .enter() | |
| .append("option") | |
| .attr("value", function(d) {return d.key;}) | |
| .text(function(d) { | |
| return d.key; }); | |
| // Buttons to highlight | |
| var checks = d3.select("#who_high") | |
| .data(nested_data) | |
| .enter().append("button") | |
| .attr("value", function(d) {return d.key;}) | |
| .text(function(d) { | |
| return d.key; }); | |
| datanest(); | |
| datadraw(); | |
| } | |
| function redraw(master){ | |
| filter(); | |
| //fonfilter(); | |
| //fonfilter2(); etc etc etc | |
| //nestswitcher..... use switch to choose appropriate nest. | |
| //visswitcher..... use switch to choose appropriate vis. maybe here http://stackoverflow.com/questions/6643015/switch-and-select-in-javascript | |
| datanest(); | |
| datadraw(); | |
| } | |
| function filter () { | |
| var who = $("#who_select").val(); | |
| data = master.filter(function(d) { return d.who == who;}); | |
| return data; | |
| } | |
| function datanest () { | |
| node = root = {values: d3.nest() | |
| .key(function(d) { return d.status; }) | |
| .entries(data)}; | |
| bucket1_data = root.values[0]; | |
| bucket2_data = root.values[1]; | |
| bucket3_data = root.values[2]; | |
| // calculate total size per bucket and overall | |
| totals = d3.nest() | |
| .key(function(d) { return d.status; }) | |
| .rollup(function(leaves) { | |
| return d3.sum(leaves, function(d) {return d.time;} );}) | |
| .map(data); | |
| total_time = totals["Complete"] + totals["In Progress"] + totals["Not Started"]; | |
| } | |
| function datadraw() { | |
| // calculate percentage of total for each bucket | |
| var pct_b1 = Math.round(h * totals["Not Started"] / total_time), | |
| pct_b2 = Math.round(h * totals["In Progress"] / total_time), | |
| pct_b3 = Math.round(h * totals["Complete"] / total_time); | |
| // resize treemps to they reflect the correct proportion of the overall time | |
| treemap1.size([w, pct_b1]); | |
| treemap2.size([w, pct_b2]); | |
| treemap3.size([w, pct_b3]); | |
| // filter gets the leaves | |
| celldraw(svg_b1.selectAll(".cell") | |
| .data(treemap1.nodes(bucket1_data).filter(function(d) { return !d.values; }) )); | |
| celldraw(svg_b2.selectAll(".cell") | |
| .data(treemap2.nodes(bucket2_data).filter(function(d) { return !d.values; }) )); | |
| celldraw(svg_b3.selectAll(".cell") | |
| .data(treemap3.nodes(bucket3_data).filter(function(d) { return !d.values; }) )); | |
| svg_b1.attr("transform", "translate(0,"+(h-pct_b1)+")"); | |
| svg_b2.attr("transform", "translate(0,"+(h-pct_b2)+")"); | |
| svg_b3.attr("transform", "translate(0,"+(h-pct_b3)+")"); | |
| } | |
| function celldraw(cell) { | |
| // enter new elements | |
| var cellEnter = cell.enter().append("g") | |
| .attr("class", "cell") | |
| // .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }) | |
| cellEnter.append("rect") | |
| cellEnter.append("text") | |
| // update remaining elements | |
| cell.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }) | |
| cell.select("rect") | |
| .attr("width", function(d) { return d.dx - 1; }) | |
| .attr("height", function(d) { return d.dy - 1; }) | |
| .attr("class", function(d) { return "cell "+ d.who; }) | |
| .style("fill", function(d) { return color(d.parent.key); }) | |
| cell.select("text") | |
| .attr("x", function(d) { return d.dx / 2; }) | |
| .attr("y", function(d) { return d.dy / 2; }) | |
| .attr("dy", ".35em") | |
| .attr("text-anchor", "middle") | |
| .text(function(d) { return d.id; }) | |
| .style("opacity", function(d) { d.w = this.getComputedTextLength(); return d.dx > d.w ? 1 : 0; }) | |
| // remove old elements | |
| cell.exit().remove() | |
| } | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment