show issues closed on that day onhover, add y axis, close #2
This commit is contained in:
parent
b358005f0f
commit
d245e1bd85
11
app.coffee
11
app.coffee
|
@ -99,7 +99,7 @@ app.get '/burndown', (req, res) ->
|
||||||
day = Issues.dateToTime current.milestone.created_at # TODO: shift this to the start of the day and deal with time shifts.
|
day = Issues.dateToTime current.milestone.created_at # TODO: shift this to the start of the day and deal with time shifts.
|
||||||
while day < current.due
|
while day < current.due
|
||||||
# Save the day.
|
# Save the day.
|
||||||
days[day] = { 'issue': {}, 'actual': 0, 'ideal': 0 }
|
days[day] = { 'issues': [], 'actual': 0, 'ideal': 0 }
|
||||||
# Shift by a day.
|
# Shift by a day.
|
||||||
day += 1000 * 60 * 60 * 24
|
day += 1000 * 60 * 60 * 24
|
||||||
# Increase the total count.
|
# Increase the total count.
|
||||||
|
@ -128,20 +128,21 @@ app.get '/burndown', (req, res) ->
|
||||||
if closed < day then return day
|
if closed < day then return day
|
||||||
|
|
||||||
# Save it.
|
# Save it.
|
||||||
if day? then days[day]['issue'] = issue
|
if day? then days[day]['issues'].push issue
|
||||||
|
|
||||||
# Calculate the predicted daily velocity.
|
# Calculate the predicted daily velocity.
|
||||||
dailyIdeal = current['size'] / totalDays ; ideal = current['size']
|
dailyIdeal = current['size'] / totalDays ; ideal = current['size']
|
||||||
|
|
||||||
# Go through the days and save the number of outstanding issues size.
|
# Go through the days and save the number of outstanding issues size.
|
||||||
for day, d of days
|
for day, d of days
|
||||||
# Does this day have an issue closed? Reduce the total for this milestone.
|
# Does this day have any closed issues? Reduce the total for this milestone.
|
||||||
if d['issue'].size? then current['size'] -= d['issue'].size
|
for issue in d['issues']
|
||||||
|
current['size'] -= issue.size
|
||||||
# Save the oustanding count for that day.
|
# Save the oustanding count for that day.
|
||||||
days[day].actual = current['size']
|
days[day].actual = current['size']
|
||||||
# Save the predicted velocity for that day.
|
# Save the predicted velocity for that day.
|
||||||
ideal -= dailyIdeal
|
ideal -= dailyIdeal
|
||||||
days[day].ideal = ideal
|
days[day].ideal = ideal # preserve the accurateness so we get a straight line
|
||||||
|
|
||||||
# Finally send to client.
|
# Finally send to client.
|
||||||
res.render 'burndown',
|
res.render 'burndown',
|
||||||
|
|
BIN
example.png
BIN
example.png
Binary file not shown.
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 108 KiB |
|
@ -71,6 +71,10 @@
|
||||||
.rickshaw_graph .detail .dot.active {
|
.rickshaw_graph .detail .dot.active {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
.rickshaw_graph .detail ul {
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
/* graph */
|
/* graph */
|
||||||
|
|
||||||
|
|
|
@ -65,10 +65,19 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
var ideal = [], actual = [], i = 0;
|
var ideal = [], actual = [], issues = {}, i = 0;
|
||||||
<% for day, data of @days: %>
|
<% for day, data of @days: %>
|
||||||
ideal.push({ 'x': <%= day / 1000 %>, 'y': <%= data['ideal'] %> });
|
ideal.push({ 'x': <%= day / 1000 %>, 'y': <%= data['ideal'] %> });
|
||||||
actual.push({ 'x': <%= day / 1000 %>, 'y': <%= data['actual'] %> });
|
actual.push({ 'x': <%= day / 1000 %>, 'y': <%= data['actual'] %> });
|
||||||
|
|
||||||
|
// Fill up issues object.
|
||||||
|
<% if data['issues'].length > 0: %>
|
||||||
|
issues[<%= day %>] = [];
|
||||||
|
<% for issue in data['issues']: %>
|
||||||
|
issues[<%= day %>].push('<%= issue['title'] %>');
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
@ -94,14 +103,41 @@
|
||||||
var hoverDetail = new Rickshaw.Graph.HoverDetail({
|
var hoverDetail = new Rickshaw.Graph.HoverDetail({
|
||||||
graph: graph,
|
graph: graph,
|
||||||
xFormatter: function(d) { return new Date(d * 1000).toUTCString() },
|
xFormatter: function(d) { return new Date(d * 1000).toUTCString() },
|
||||||
yFormatter: function(y) { return Math.round(y) + " points left" }
|
formatter: function(series, stamp, points) {
|
||||||
|
if (series.name == 'Ideal') {
|
||||||
|
return '<p>Ideally ' + Math.round(points) + ' points left</p>'
|
||||||
|
} else {
|
||||||
|
var left = '<p>' + Math.round(points) + ' points left</p>';
|
||||||
|
// Have we closed any issues today?
|
||||||
|
var iss = issues[stamp * 1000];
|
||||||
|
if (iss) {
|
||||||
|
var string = '<ul>';
|
||||||
|
for (var i = 0; i < iss.length; i++) {
|
||||||
|
string += '<li><span class="icon-ok icon-white"></span> ' + unescape(iss[i]) + '</li>';
|
||||||
|
}
|
||||||
|
string += '</ul>';
|
||||||
|
return left + string;
|
||||||
|
} else {
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Axes.
|
// Axes.
|
||||||
var axes = new Rickshaw.Graph.Axis.Time({
|
var xAxis = new Rickshaw.Graph.Axis.Time({
|
||||||
graph: graph
|
graph: graph,
|
||||||
|
ticksTreatment: 'glow'
|
||||||
});
|
});
|
||||||
axes.render();
|
|
||||||
|
var yAxis = new Rickshaw.Graph.Axis.Y({
|
||||||
|
graph: graph,
|
||||||
|
tickFormat: Rickshaw.Fixtures.Number.formatKMBT,
|
||||||
|
ticksTreatment: 'glow'
|
||||||
|
});
|
||||||
|
|
||||||
|
xAxis.render();
|
||||||
|
yAxis.render();
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue