using JSON dates internally and moment for parsing

This commit is contained in:
Radek Stepan 2014-10-30 22:12:02 -06:00
parent f2cd345bcf
commit 9d247206d3
7 changed files with 50 additions and 44 deletions

View File

@ -4,7 +4,7 @@
GitHub Burndown Chart as a service. Answers the question "are my projects on track"?
[![Build Status](http://img.shields.io/codeship/44524.svg?style=flat)](<URL_HERE>)
![Build Status](http://img.shields.io/codeship/31951cd0-42c7-0132-d601-5ea438edf284.svg?style=flat)
[![Coverage](http://img.shields.io/coveralls/radekstepan/burnchart/master.svg?style=flat)](<https://coveralls.io/r/radekstepan/burnchart>)
[![Dependencies](http://img.shields.io/david/radekstepan/burnchart.svg?style=flat)](https://david-dm.org/radekstepan/burnchart)
[![License](http://img.shields.io/badge/license-AGPL--3.0-red.svg?style=flat)](LICENSE)

File diff suppressed because one or more lines are too long

View File

@ -8,7 +8,7 @@
- [ ] 4 until GH fix milestone start date then provide an option to specify it; for example a text like this: `starts: 09-10-2014` in the description which we provide regex for in the config
- [ ] 5 be able to config options through ui that currently have to be hardcoded in the config
- [ ] 5 be able to delete added projects; on the project page listing all milestone, enable the cog at the bottom of the table, clicking it slides a link with a dustbin next to it which deletes the project
- [ ] 3 dates not parsing well with timezones, see ideal lines test file
- [ ] 3 check that we are using moment and toJSON all the way until chart view; tests checking res from github in milestones and issues
###Normal
@ -22,7 +22,7 @@
- [ ] 3 In add a project form autocomplete on my username, orgs I am member of and repos I have access to, use code from [elastic-med](https://github.com/intermine/intermine-apps-c/blob/master/elastic-med/src/components/search.coffee#L24-L46) to show the first option with Tab doing the autocomplete
- [ ] 4 show number of tasks, points, days left, progress bar in the header of a chart page, just like in Assembly
- [ ] 3 be able to specify milestone by name (will nicely show in title), so when we type in `owner/name/name` it should resolve the number
- [ ] 3 trendline is sometimes cutting into axes, but maybe it was just an interpolation
- [ ] 3 trendline is sometimes cutting into axes, see `rails/rails/36`
- [ ] 3 deal with Firebase timing out, are we still logged-in? Show a warning page telling the people to refresh the browser (adding a button to do the same)
- [ ] 3 use issue title to determine size
- [ ] 3 the app bundle (albeit uncompressed) clocks in at 1.5MB, reduce the size (`d3` is huge (use [grunt-smash](https://github.com/cvisco/grunt-smash), [docs here](https://github.com/mbostock/smash/wiki)))

View File

@ -25,8 +25,6 @@ module.exports = new Model
"chart":
# Days we are not working. Mon = 1
"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+)$/
# Process all issues as one size (ONE_SIZE) or use labels (LABELS).

View File

@ -1,5 +1,6 @@
_ = require 'lodash'
d3 = require 'd3'
_ = require 'lodash'
d3 = require 'd3'
moment = require 'moment'
config = require '../../models/config.coffee'
@ -11,7 +12,7 @@ module.exports =
# `total`: total number of points (open & closed issues)
actual: (issues, created_at, total) ->
head = [ {
'date': new Date created_at
'date': do moment(created_at).toJSON
'points': total
} ]
@ -25,7 +26,7 @@ module.exports =
max = size if size > max
# Dropping points remaining.
issue.date = new Date closed_at
issue.date = do moment(closed_at).toJSON
issue.points = total -= size
issue
@ -43,30 +44,29 @@ module.exports =
# `b`: milestone end date
# `total`: total number of points (open & closed issues)
ideal: (a, b, total) ->
# Swap?
# Swap if end is before the start...
[ b, a ] = [ a, b ] if b < a
# We start here adding days to `d`.
[ y, m, d ] = _.map a.match(config.data.chart.datetime)[1].split('-'), (v) -> parseInt v
# We want to end here.
cutoff = new Date(b)
a = moment a
# Do we have a due date?
b = if b? then moment b else do moment.utc
# Go through the beginning to the end skipping off days.
days = [] ; length = 0
do once = (inc = 0) ->
# A new day.
day = new Date y, m - 1, d + inc
# A new day. TODO: deal with hours and minutes!
day = a.add 1, 'days'
# Does this day count?
day_of = 7 if !day_of = day.getDay()
day_of = 7 unless day_of = do day.weekday
if day_of in config.data.chart.off_days
days.push { date: day, off_day: yes }
days.push { 'date': do day.toJSON, 'off_day': yes }
else
length += 1
days.push { date: day }
days.push { 'date': do day.toJSON }
# Go again?
once(inc + 1) unless day > cutoff
once(inc + 1) unless day > b
# Map points on the array of days now.
velocity = total / (length - 1)
@ -77,7 +77,7 @@ module.exports =
day
# Do we need to make a link to right now?
days.push { date: now, points: 0 } if (now = new Date) > cutoff
days.push { 'date': do now.toJSON, 'points': 0 } if (now = do moment.utc) > b
days
@ -85,15 +85,17 @@ module.exports =
trend: (actual, created_at, due_on) ->
return [] unless actual.length
start = +actual[0].date
[ first, ..., last ] = actual
start = moment first.date
# Values is a list of time from the start and points remaining.
values = _.map actual, ({ date, points }) ->
[ +date - start, points ]
[ moment(date).diff(start), points ]
# Now is an actual point too.
last = actual[actual.length - 1]
values.push [ + new Date - start, last.points ]
now = do moment.utc
values.push [ now.diff(start), last.points ]
# http://classroom.synonym.com/calculate-trendline-2709.html
b1 = 0 ; e = 0 ; c1 = 0
@ -105,30 +107,30 @@ module.exports =
slope = (a - (b1 * e)) / ((l * c1) - (Math.pow(b1, 2)))
intercept = (e - (slope * b1)) / l
fn = (x) -> slope * x + intercept
# Milestone always has a creation date.
created_at = new Date created_at
created_at = moment created_at
now = new Date
# Due date specified.
if due_on
due_on = new Date due_on
due_on = moment due_on
# In the past?
due_on = now if now > due_on
# No due date
else
due_on = now
a = created_at - start
b = due_on - start
a = created_at.diff start
b = due_on.diff start
[
{
'date': created_at
'points': fn(a)
'date': do created_at.toJSON
'points': fn a
}, {
'date': due_on
'points': fn(b)
'date': do due_on.toJSON
'points': fn b
}
]

View File

@ -48,12 +48,16 @@ module.exports = Ractive.extend
# Line generator.
line = d3.svg.line()
.interpolate("linear")
.x( (d) -> x(d.date) )
.x( (d) -> x(new Date(d.date)) ) # convert to Date only now
.y( (d) -> y(d.points) )
# Get the minimum and maximum date, and initial points.
x.domain([ ideal[0].date, ideal[ideal.length - 1].date ])
y.domain([ 0, ideal[0].points ]).nice()
[ first, ..., last ] = ideal
x.domain [
new Date(first.date)
new Date(last.date)
]
y.domain([ 0, first.points ]).nice()
# Add an SVG element with the desired dimensions and margin.
svg = d3.select(this.el.querySelector('#chart')).append("svg")
@ -93,9 +97,9 @@ module.exports = Ractive.extend
# Add a line showing where we are now.
svg.append("svg:line")
.attr("class", "today")
.attr("x1", x(new Date()))
.attr("x1", x(new Date))
.attr("y1", 0)
.attr("x2", x(new Date()))
.attr("x2", x(new Date))
.attr("y2", height)
# Add the ideal line path.
@ -131,7 +135,7 @@ module.exports = Ractive.extend
.attr("xlink:href", ({ html_url }) -> html_url )
.attr("xlink:show", 'new')
.append('svg:circle')
.attr("cx", ({ date }) -> x date )
.attr("cx", ({ date }) -> x new Date date )
.attr("cy", ({ points }) -> y points )
.attr("r", ({ radius }) -> 5 ) # fixed for now
.on('mouseover', tooltip.show)

View File

@ -18,17 +18,19 @@ module.exports =
do done
'lines - ideal': (done) ->
# Dates are coming in without timezone information, so UTC.
a = '2011-04-01T00:00:00Z'
b = '2011-04-03T00:00:00Z'
line = lines.ideal(a, b, 4)[ 0...3 ]
assert.deepEqual line, [
{ 'date': new Date('2011-04-01T06:00:00Z'), 'points': 4 }
{ 'date': new Date('2011-04-02T06:00:00Z'), 'points': 2 }
{ 'date': new Date('2011-04-03T06:00:00Z'), 'points': 0 }
{ 'date': '2011-04-02T00:00:00.000Z', 'points': 4 }
{ 'date': '2011-04-03T00:00:00.000Z', 'points': 2 }
{ 'date': '2011-04-04T00:00:00.000Z', 'points': 0 }
]
do done
'lines - trend': (done) ->