mirror of
https://github.com/status-im/burnchart.git
synced 2025-01-19 07:03:27 +00:00
fixes #3
This commit is contained in:
parent
7ccdc7232e
commit
9a7f6f1ec9
129
app.coffee
129
app.coffee
@ -78,75 +78,82 @@ app.get '/burndown', (req, res) ->
|
|||||||
when 'milestones' then store.milestones = store.milestones.concat data
|
when 'milestones' then store.milestones = store.milestones.concat data
|
||||||
|
|
||||||
# Are we done?
|
# Are we done?
|
||||||
if resources is 0
|
if resources is 0
|
||||||
# Store the current milestone and its size.
|
# Do we actually have an open milestone?
|
||||||
current = { 'milestone': {}, 'diff': +Infinity, 'size': 0 }
|
if store.milestones.length > 0
|
||||||
|
# Store the current milestone and its size.
|
||||||
|
current = { 'milestone': {}, 'diff': +Infinity, 'size': 0 }
|
||||||
|
|
||||||
# Determine the 'current' milestone
|
# Determine the 'current' milestone
|
||||||
now = new Date().getTime()
|
now = new Date().getTime()
|
||||||
for milestone in store.milestones
|
for milestone in store.milestones
|
||||||
due = milestone['due_on']
|
# JS expects more accuracy.
|
||||||
# JS expects more accuracy.
|
due = Issues.dateToTime milestone['due_on']
|
||||||
due = Issues.dateToTime due
|
# Is this the 'current' one?
|
||||||
# Is this the 'current' one?
|
diff = due - now
|
||||||
diff = due - now
|
if diff > 0 and diff < current.diff
|
||||||
if diff > 0 and diff < current.diff
|
current.milestone = milestone ; current.diff = diff ; current.due = due
|
||||||
current.milestone = milestone ; current.diff = diff ; current.due = due
|
|
||||||
|
|
||||||
# Create n dict with all dates in the milestone span.
|
# Create n dict with all dates in the milestone span.
|
||||||
days = {} ; totalDays = 0
|
days = {} ; totalDays = 0
|
||||||
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] = { 'issue': {}, '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.
|
||||||
totalDays += 1
|
totalDays += 1
|
||||||
|
|
||||||
# Now go through the issues and place them to the appropriate days.
|
# Now go through the issues and place them to the appropriate days.
|
||||||
for issue in store.issues
|
for issue in store.issues
|
||||||
# This milestone?
|
# This milestone?
|
||||||
if issue.milestone?.number is current.milestone.number
|
if issue.milestone?.number is current.milestone.number
|
||||||
# Has a size label?
|
# Has a size label?
|
||||||
if issue.labels?
|
if issue.labels?
|
||||||
issue.size = do (issue) ->
|
issue.size = do (issue) ->
|
||||||
for label in issue.labels
|
for label in issue.labels
|
||||||
if label.name.indexOf("size ") is 0
|
if label.name.indexOf("size ") is 0
|
||||||
return parseInt label.name[5...]
|
return parseInt label.name[5...]
|
||||||
|
|
||||||
if issue.size?
|
if issue.size?
|
||||||
# Increase the total size of the milestone.
|
# Increase the total size of the milestone.
|
||||||
current.size += issue.size
|
current.size += issue.size
|
||||||
# Is it closed?
|
# Is it closed?
|
||||||
if issue.closed_at?
|
if issue.closed_at?
|
||||||
closed = Issues.dateToTime issue.closed_at
|
closed = Issues.dateToTime issue.closed_at
|
||||||
# Find when was it closed (will be made faster)
|
# Find when was it closed (will be made faster)
|
||||||
day = do () ->
|
day = do () ->
|
||||||
for day, x of days
|
for day, x of days
|
||||||
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]['issue'] = 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 an issue closed? Reduce the total for this milestone.
|
||||||
if d['issue'].size? then current['size'] -= d['issue'].size
|
if d['issue'].size? then current['size'] -= d['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
|
||||||
|
|
||||||
# Finally send to client.
|
# Finally send to client.
|
||||||
res.render 'burndown',
|
res.render 'burndown',
|
||||||
'days': days
|
'days': days
|
||||||
'project': Issues.config.project_name
|
'project': Issues.config.project_name
|
||||||
, (html) -> res.send html, 'Content-Type': 'text/html', 200
|
, (html) -> res.send html, 'Content-Type': 'text/html', 200
|
||||||
|
|
||||||
|
else
|
||||||
|
# No current milestone.
|
||||||
|
res.render 'empty',
|
||||||
|
'project': Issues.config.project_name
|
||||||
|
, (html) -> res.send html, 'Content-Type': 'text/html', 200
|
||||||
|
|
||||||
|
|
||||||
# Get Milestones, Opened and Closed Tickets.
|
# Get Milestones, Opened and Closed Tickets.
|
||||||
|
54
templates/empty.eco
Normal file
54
templates/empty.eco
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
|
||||||
|
<title>Burndown App</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" type="text/css" href="css/style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header class="navbar blue blue2 navbar-fixed-top">
|
||||||
|
<div class="navbar-inner">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<ul class="nav pull-left">
|
||||||
|
<li><a><i class="icon-white icon-fire"></i> Burndown App</a></li>
|
||||||
|
</ul>
|
||||||
|
<ul class="nav pull-right">
|
||||||
|
<li><a><i class="icon-white icon-book"></i> <%= @project %></a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section class="container-fluid pad40">
|
||||||
|
<section class="row-fluid">
|
||||||
|
<div class="span2 sideBar">
|
||||||
|
<br>
|
||||||
|
<ul>
|
||||||
|
<li class="active">
|
||||||
|
<figure>
|
||||||
|
<a href="/burndown"><i class="icon-signal"></i> Burndown Chart</a>
|
||||||
|
</figure>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<figure>
|
||||||
|
<a href="/issues"><i class="icon-tasks"></i> Issues</a>
|
||||||
|
</figure>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<section class="span10 content borBox">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="page-header">
|
||||||
|
<h1>All issues are closed</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
x
Reference in New Issue
Block a user