work with both labels and single points
This commit is contained in:
parent
eff268e1de
commit
b364f0cda5
|
@ -54,6 +54,7 @@ GitHub Burndown Chart as a service. Public repos are free, for private access au
|
|||
- [ ] allow people to submit suggestions via GitHub Issues
|
||||
- [ ] find a way where, as a group, we can share repo data by trusting the other repo members that use our platform
|
||||
- [ ] support Jira & Gitlab
|
||||
- [x] closed issues can be moved to a newly created milestone, this messes up the chart since we assume milestone is created first!
|
||||
|
||||
## Notes
|
||||
|
||||
|
|
|
@ -436,7 +436,7 @@ table {
|
|||
}@keyframes spin{0%{-webkit-transform:rotate(0);-moz-transform:rotate(0);-o-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0)}
|
||||
100%{-webkit-transform:rotate(360deg);-moz-transform:rotate(360deg);-o-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg)}
|
||||
}
|
||||
#chart{height:200px;position:relative;}
|
||||
#chart{height:300px;position:relative;}
|
||||
#chart #tooltip{position:absolute;top:0;left:0}
|
||||
#chart svg path.line{fill:none;stroke-width:1px;clip-path:url("#clip");}
|
||||
#chart svg path.line.actual{stroke:#64584c;stroke-width:3px}
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
}@keyframes spin{0%{-webkit-transform:rotate(0);-moz-transform:rotate(0);-o-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0)}
|
||||
100%{-webkit-transform:rotate(360deg);-moz-transform:rotate(360deg);-o-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg)}
|
||||
}
|
||||
#chart{height:200px;position:relative;}
|
||||
#chart{height:300px;position:relative;}
|
||||
#chart #tooltip{position:absolute;top:0;left:0}
|
||||
#chart svg path.line{fill:none;stroke-width:1px;clip-path:url("#clip");}
|
||||
#chart svg path.line.actual{stroke:#64584c;stroke-width:3px}
|
||||
|
|
|
@ -40038,7 +40038,7 @@ if (typeof exports === 'object') {
|
|||
"milestone": ["closed_issues", "created_at", "description", "due_on", "number", "open_issues", "title", "updated_at"]
|
||||
},
|
||||
"chart": {
|
||||
"off_days": [6, 7],
|
||||
"off_days": [],
|
||||
"datetime": /^(\d{4}-\d{2}-\d{2})T(.*)/,
|
||||
"size_label": /^size (\d+)$/,
|
||||
"location": /^#!((\/[^\/]+){2,3})$/,
|
||||
|
@ -40141,8 +40141,8 @@ if (typeof exports === 'object') {
|
|||
var head, max, min, range, rest;
|
||||
head = [
|
||||
{
|
||||
date: new Date(created_at),
|
||||
points: total
|
||||
'date': new Date(created_at),
|
||||
'points': total
|
||||
}
|
||||
];
|
||||
min = +Infinity;
|
||||
|
@ -40156,10 +40156,9 @@ if (typeof exports === 'object') {
|
|||
if (size > max) {
|
||||
max = size;
|
||||
}
|
||||
return _.extend({}, issue, {
|
||||
date: new Date(closed_at),
|
||||
points: total -= size
|
||||
});
|
||||
issue.date = new Date(closed_at);
|
||||
issue.points = total -= size;
|
||||
return issue;
|
||||
});
|
||||
range = d3.scale.linear().domain([min, max]).range([5, 8]);
|
||||
rest = _.map(rest, function(issue) {
|
||||
|
@ -40262,10 +40261,10 @@ if (typeof exports === 'object') {
|
|||
document.querySelector('#svg').innerHTML = '';
|
||||
_ref = document.querySelector('#chart').getBoundingClientRect(), height = _ref.height, width = _ref.width;
|
||||
margin = {
|
||||
top: 30,
|
||||
right: 30,
|
||||
bottom: 40,
|
||||
left: 50
|
||||
'top': 30,
|
||||
'right': 30,
|
||||
'bottom': 40,
|
||||
'left': 50
|
||||
};
|
||||
width -= margin.left + margin.right;
|
||||
height -= margin.top + margin.bottom;
|
||||
|
@ -40411,7 +40410,7 @@ if (typeof exports === 'object') {
|
|||
};
|
||||
return async.parallel([_.partial(one_status, 'open'), _.partial(one_status, 'closed')], cb);
|
||||
},
|
||||
'filter': function(collection, regex, cb) {
|
||||
'filter': function(collection, cb) {
|
||||
var filtered, total;
|
||||
total = 0;
|
||||
switch (config.get('chart.points')) {
|
||||
|
@ -40430,7 +40429,7 @@ if (typeof exports === 'object') {
|
|||
}
|
||||
issue.size = _.reduce(labels, function(sum, label) {
|
||||
var matches;
|
||||
if (!(matches = label.name.match(regex))) {
|
||||
if (!(matches = label.name.match(config.get('chart.size_label')))) {
|
||||
return sum;
|
||||
}
|
||||
return sum += parseInt(matches[1]);
|
||||
|
@ -40531,11 +40530,11 @@ if (typeof exports === 'object') {
|
|||
return issues.get_all(opts, cb);
|
||||
}, function(all, cb) {
|
||||
return async.map(all, function(array, cb) {
|
||||
return issues.filter(array, opts.size_label, function(err, filtered, total) {
|
||||
return issues.filter(array, function(err, filtered, total) {
|
||||
return cb(err, [filtered, total]);
|
||||
});
|
||||
}, function(err, _arg) {
|
||||
var closed, open;
|
||||
var closed, open, start;
|
||||
open = _arg[0], closed = _arg[1];
|
||||
if (err) {
|
||||
return cb(err);
|
||||
|
@ -40544,15 +40543,18 @@ if (typeof exports === 'object') {
|
|||
return cb('No matching issues found');
|
||||
}
|
||||
opts.issues = {
|
||||
closed: {
|
||||
'closed': {
|
||||
'points': closed[1],
|
||||
'data': closed[0]
|
||||
},
|
||||
open: {
|
||||
'open': {
|
||||
'points': open[1],
|
||||
'data': open[0]
|
||||
}
|
||||
};
|
||||
if ((start = closed[0][0].closed_at) < opts.milestone.created_at) {
|
||||
opts.milestone.created_at = start;
|
||||
}
|
||||
return cb(null);
|
||||
});
|
||||
}, function(cb) {
|
||||
|
@ -40759,7 +40761,7 @@ if (typeof exports === 'object') {
|
|||
// showChart.mustache
|
||||
root.require.register('burnchart/src/templates/pages/showChart.js', function(exports, require, module) {
|
||||
|
||||
module.exports = ["<div id=\"content\" class=\"wrap\">"," <div id=\"chart\">"," <div id=\"tooltip\"></div>"," <div id=\"svg\"></div>"," </div>","</div>"].join("\n");
|
||||
module.exports = ["<div id=\"content\" class=\"wrap\">"," <div id=\"chart\">"," <div id=\"svg\"></div>"," </div>","</div>"].join("\n");
|
||||
});
|
||||
|
||||
// projects.mustache
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
"milestone": ["closed_issues", "created_at", "description", "due_on", "number", "open_issues", "title", "updated_at"]
|
||||
},
|
||||
"chart": {
|
||||
"off_days": [6, 7],
|
||||
"off_days": [],
|
||||
"datetime": /^(\d{4}-\d{2}-\d{2})T(.*)/,
|
||||
"size_label": /^size (\d+)$/,
|
||||
"location": /^#!((\/[^\/]+){2,3})$/,
|
||||
|
@ -175,8 +175,8 @@
|
|||
var head, max, min, range, rest;
|
||||
head = [
|
||||
{
|
||||
date: new Date(created_at),
|
||||
points: total
|
||||
'date': new Date(created_at),
|
||||
'points': total
|
||||
}
|
||||
];
|
||||
min = +Infinity;
|
||||
|
@ -190,10 +190,9 @@
|
|||
if (size > max) {
|
||||
max = size;
|
||||
}
|
||||
return _.extend({}, issue, {
|
||||
date: new Date(closed_at),
|
||||
points: total -= size
|
||||
});
|
||||
issue.date = new Date(closed_at);
|
||||
issue.points = total -= size;
|
||||
return issue;
|
||||
});
|
||||
range = d3.scale.linear().domain([min, max]).range([5, 8]);
|
||||
rest = _.map(rest, function(issue) {
|
||||
|
@ -296,10 +295,10 @@
|
|||
document.querySelector('#svg').innerHTML = '';
|
||||
_ref = document.querySelector('#chart').getBoundingClientRect(), height = _ref.height, width = _ref.width;
|
||||
margin = {
|
||||
top: 30,
|
||||
right: 30,
|
||||
bottom: 40,
|
||||
left: 50
|
||||
'top': 30,
|
||||
'right': 30,
|
||||
'bottom': 40,
|
||||
'left': 50
|
||||
};
|
||||
width -= margin.left + margin.right;
|
||||
height -= margin.top + margin.bottom;
|
||||
|
@ -445,7 +444,7 @@
|
|||
};
|
||||
return async.parallel([_.partial(one_status, 'open'), _.partial(one_status, 'closed')], cb);
|
||||
},
|
||||
'filter': function(collection, regex, cb) {
|
||||
'filter': function(collection, cb) {
|
||||
var filtered, total;
|
||||
total = 0;
|
||||
switch (config.get('chart.points')) {
|
||||
|
@ -464,7 +463,7 @@
|
|||
}
|
||||
issue.size = _.reduce(labels, function(sum, label) {
|
||||
var matches;
|
||||
if (!(matches = label.name.match(regex))) {
|
||||
if (!(matches = label.name.match(config.get('chart.size_label')))) {
|
||||
return sum;
|
||||
}
|
||||
return sum += parseInt(matches[1]);
|
||||
|
@ -565,11 +564,11 @@
|
|||
return issues.get_all(opts, cb);
|
||||
}, function(all, cb) {
|
||||
return async.map(all, function(array, cb) {
|
||||
return issues.filter(array, opts.size_label, function(err, filtered, total) {
|
||||
return issues.filter(array, function(err, filtered, total) {
|
||||
return cb(err, [filtered, total]);
|
||||
});
|
||||
}, function(err, _arg) {
|
||||
var closed, open;
|
||||
var closed, open, start;
|
||||
open = _arg[0], closed = _arg[1];
|
||||
if (err) {
|
||||
return cb(err);
|
||||
|
@ -578,15 +577,18 @@
|
|||
return cb('No matching issues found');
|
||||
}
|
||||
opts.issues = {
|
||||
closed: {
|
||||
'closed': {
|
||||
'points': closed[1],
|
||||
'data': closed[0]
|
||||
},
|
||||
open: {
|
||||
'open': {
|
||||
'points': open[1],
|
||||
'data': open[0]
|
||||
}
|
||||
};
|
||||
if ((start = closed[0][0].closed_at) < opts.milestone.created_at) {
|
||||
opts.milestone.created_at = start;
|
||||
}
|
||||
return cb(null);
|
||||
});
|
||||
}, function(cb) {
|
||||
|
@ -793,7 +795,7 @@
|
|||
// showChart.mustache
|
||||
root.require.register('burnchart/src/templates/pages/showChart.js', function(exports, require, module) {
|
||||
|
||||
module.exports = ["<div id=\"content\" class=\"wrap\">"," <div id=\"chart\">"," <div id=\"tooltip\"></div>"," <div id=\"svg\"></div>"," </div>","</div>"].join("\n");
|
||||
module.exports = ["<div id=\"content\" class=\"wrap\">"," <div id=\"chart\">"," <div id=\"svg\"></div>"," </div>","</div>"].join("\n");
|
||||
});
|
||||
|
||||
// projects.mustache
|
||||
|
|
|
@ -21,12 +21,13 @@ module.exports = new Model
|
|||
]
|
||||
# Chart configuration.
|
||||
"chart":
|
||||
"off_days": [ 6, 7 ]
|
||||
# Days we are not working.
|
||||
"off_days": [ ]
|
||||
# How do we parse GitHub dates?
|
||||
"datetime": /^(\d{4}-\d{2}-\d{2})T(.*)/
|
||||
# How does a size label look like?
|
||||
"size_label": /^size (\d+)$/
|
||||
# How do we specify which user/repo/(milestone) we want?
|
||||
"location": /^#!((\/[^\/]+){2,3})$/
|
||||
# Process all issues as one size.
|
||||
# Process all issues as one size or use labels.
|
||||
"points": 'ALL_ONE_SIZE'
|
|
@ -4,10 +4,13 @@ config = require '../models/config'
|
|||
module.exports =
|
||||
|
||||
# A graph of closed issues.
|
||||
# `collection`: issues
|
||||
# `created_at`: milestone start date
|
||||
# `total`: total number of points (open & closed issues)
|
||||
'actual': (collection, created_at, total, cb) ->
|
||||
head = [ {
|
||||
date: new Date(created_at)
|
||||
points: total
|
||||
'date': new Date created_at
|
||||
'points': total
|
||||
} ]
|
||||
|
||||
min = +Infinity ; max = -Infinity
|
||||
|
@ -20,9 +23,9 @@ module.exports =
|
|||
max = size if size > max
|
||||
|
||||
# Dropping points remaining.
|
||||
_.extend {}, issue,
|
||||
date: new Date(closed_at)
|
||||
points: total -= size
|
||||
issue.date = new Date closed_at
|
||||
issue.points = total -= size
|
||||
issue
|
||||
|
||||
# Now add a radius in a range (will be used for a circle).
|
||||
range = d3.scale.linear().domain([ min, max ]).range([ 5, 8 ])
|
||||
|
@ -125,14 +128,14 @@ module.exports =
|
|||
# Get available space.
|
||||
{ height, width } = document.querySelector('#chart').getBoundingClientRect()
|
||||
|
||||
margin = { top: 30, right: 30, bottom: 40, left: 50 }
|
||||
margin = { 'top': 30, 'right': 30, 'bottom': 40, 'left': 50 }
|
||||
width -= margin.left + margin.right
|
||||
height -= margin.top + margin.bottom
|
||||
|
||||
# Scales.
|
||||
x = d3.time.scale().range([ 0, width ])
|
||||
y = d3.scale.linear().range([ height, 0 ])
|
||||
|
||||
|
||||
# Axes.
|
||||
xAxis = d3.svg.axis().scale(x)
|
||||
.orient("bottom")
|
||||
|
@ -225,9 +228,8 @@ module.exports =
|
|||
|
||||
# Show when we closed an issue.
|
||||
svg.selectAll("a.issue")
|
||||
.data(actual[1...]) # skip the starting point
|
||||
.data(actual.slice(1)) # skip the starting point
|
||||
.enter()
|
||||
|
||||
# A wrapping link.
|
||||
.append('svg:a')
|
||||
.attr("xlink:href", ({ html_url }) -> html_url )
|
||||
|
|
|
@ -31,10 +31,10 @@ module.exports =
|
|||
], cb
|
||||
|
||||
# Filter an array of incoming issues based on a regex & save size on them.
|
||||
'filter': (collection, regex, cb) ->
|
||||
'filter': (collection, cb) ->
|
||||
# The total size of all issues.
|
||||
total = 0
|
||||
|
||||
|
||||
# Which point counting mode are we in?
|
||||
switch config.get 'chart.points'
|
||||
# All issues are the same size
|
||||
|
@ -53,7 +53,7 @@ module.exports =
|
|||
# Determine the total issue size from all labels.
|
||||
issue.size = _.reduce labels, (sum, label) ->
|
||||
# Not matching.
|
||||
return sum unless matches = label.name.match(regex)
|
||||
return sum unless matches = label.name.match config.get 'chart.size_label'
|
||||
# Increase sum.
|
||||
sum += parseInt matches[1]
|
||||
, 0
|
||||
|
@ -63,5 +63,5 @@ module.exports =
|
|||
|
||||
# Are we saving it?
|
||||
!!issue.size
|
||||
|
||||
|
||||
cb null, filtered, total
|
|
@ -21,7 +21,7 @@ module.exports = (opts, cb) ->
|
|||
# Filter them to labeled ones.
|
||||
(all, cb) ->
|
||||
async.map all, (array, cb) ->
|
||||
issues.filter array, opts.size_label, (err, filtered, total) ->
|
||||
issues.filter array, (err, filtered, total) ->
|
||||
cb err, [ filtered, total ]
|
||||
, (err, [ open, closed ]) ->
|
||||
return cb err if err
|
||||
|
@ -29,8 +29,12 @@ module.exports = (opts, cb) ->
|
|||
return cb 'No matching issues found' if open[1] + closed[1] is 0
|
||||
# Save the open/closed on us first.
|
||||
opts.issues =
|
||||
closed: { 'points': closed[1], 'data': closed[0] }
|
||||
open: { 'points': open[1], 'data': open[0] }
|
||||
'closed': { 'points': closed[1], 'data': closed[0] }
|
||||
'open': { 'points': open[1], 'data': open[0] }
|
||||
# Do we need to move the milestone start date?
|
||||
if (start = closed[0][0].closed_at) < opts.milestone.created_at
|
||||
opts.milestone.created_at = start
|
||||
|
||||
cb null
|
||||
|
||||
# Create actual and ideal lines & render.
|
||||
|
|
|
@ -10,7 +10,7 @@ $background2 = #CC9485
|
|||
|
||||
// where D3 renders to
|
||||
#chart
|
||||
height: 200px
|
||||
height: 300px
|
||||
position: relative
|
||||
|
||||
// position will be adjusted dynamically
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<div id="content" class="wrap">
|
||||
<div id="chart">
|
||||
<div id="tooltip"></div>
|
||||
<div id="svg"></div>
|
||||
</div>
|
||||
</div>
|
Loading…
Reference in New Issue