seemingly working adding of errors and stats

This commit is contained in:
Radek Stepan 2014-10-20 19:51:15 -07:00
parent 5d6bed2759
commit 367f26e517
12 changed files with 317 additions and 178 deletions

View File

@ -6,10 +6,6 @@ build:
./node_modules/.bin/browserify -e ./src/app.coffee -o public/js/app.js -d
grunt
watch:
grunt
grunt watchify
serve:
cd public; python -m SimpleHTTPServer 8000

View File

@ -3,7 +3,7 @@
##Release: Assembly
- [ ] use Browserify as an app build pipeline
- [ ] sort milestones on index and project page based on priority (most delayed first); Trend - actual = different in days and those overdue come first
- [ ] sort milestones on index and project page based on priority (most delayed first); Trend - actual = difference in days and those overdue come first
1. in a projects collection observe the list prop and resort index; already sorted flag passed in as yes)
1. The index is not already sorted when sort order changes

File diff suppressed because one or more lines are too long

View File

@ -2,6 +2,7 @@
config = require '../models/config.coffee'
mediator = require '../modules/mediator.coffee'
stats = require '../modules/stats.coffee'
Model = require '../utils/model.coffee'
date = require '../utils/date.coffee'
search = require '../utils/search.coffee'
@ -12,7 +13,7 @@ module.exports = new Model
'name': 'models/projects'
'data':
'sortKey': 'priority'
'sortBy': 'priority'
find: (project) ->
_.find @data.list, project
@ -24,15 +25,34 @@ module.exports = new Model
add: (project) ->
@push 'list', project unless @exists project
# Find index of a project.
findIndex: ({ owner, name }) ->
_.findIndex @data.list, { owner, name }
addMilestone: (project, milestone) ->
if (idx = _.findIndex(@data.list, project)) > -1
# Add in the stats.
_.extend milestone, { 'stats': stats(milestone) }
if (idx = @findIndex(project)) > -1
if project.milestones?
@push "list.#{idx}.milestones", milestone
else
@set "list.#{idx}.milestones", [ milestone ]
else
# We are supposed to exist already.
throw 500
# Save an error from loading milestones or issues
saveError: (project, err) ->
if (idx = @findIndex(project)) > -1
if project.errors?
@push "list.#{idx}.errors", err
else
@set "list.#{idx}.errors", [ err ]
else
# We are supposed to exist already.
throw 500
clear: ->
@set 'list', []
@ -42,9 +62,10 @@ module.exports = new Model
index = @data.index or []
for p in @data.list
continue unless p.milestones?
for m in p.milestones
# Run a comparator here inserting into index.
@data.sortKey
console.log @data.sortBy, m
# Save the index.
@set 'index', index
@ -67,6 +88,6 @@ module.exports = new Model
# Reset our index and re-sort.
@observe 'sortKey', ->
# Use pop as Ractive is glitchy.
@pop 'index' while @data.index.length
( @pop 'index' while @data.index.length ) if @data.index?
# Run the sort again.
do @sort

View File

@ -116,10 +116,10 @@ module.exports =
[
{
date: created_at
points: fn(a)
'date': created_at
'points': fn(a)
}, {
date: due_on
points: fn(b)
'date': due_on
'points': fn(b)
}
]

25
src/modules/stats.coffee Normal file
View File

@ -0,0 +1,25 @@
# Progress in %.
progress = (a, b) -> 100 * (a / (b + a))
# Calculate the stats for a milestone.
# Is it on time? What is the progress?
module.exports = (milestone) ->
# Progress in points.
points = progress milestone.issues.closed.size, milestone.issues.open.size
# Milestones with no due date are always on track.
return { 'isOnTime': yes, 'progress': { points } } unless milestone.due_on
a = +new Date milestone.created_at
b = +new Date
c = +new Date milestone.due_on
# Progress in time.
time = progress b - a, c - b
isOnTime = points > time
{
'isOnTime': isOnTime
'progress': { points, time }
}

View File

@ -12,10 +12,10 @@
</td>
<td style="width:1%">
<div class="progress">
<span class="percent">{{Math.floor(format.progress(issues.closed.size, issues.open.size))}}%</span>
<span class="percent">{{Math.floor(stats.progress.points)}}%</span>
<span class="due">{{{ format.due(due_on) }}}</span>
<div class="outer bar">
<div class="inner bar {{format.onTime(number, due_on, created_at, issues.closed.size, issues.open.size)}}" style="width:{{format.progress(issues.closed.size, issues.open.size)}}%"></div>
<div class="inner bar {{(stats.isOnTime) ? 'green' : 'red'}}" style="width:{{stats.progress.points}}%"></div>
</div>
</div>
</td>

View File

@ -6,10 +6,10 @@
<table>
{{#projects.list}}
{{#if error}}
{{#if errors}}
<tr>
<td colspan="3" class="repo">
<div class="project">{{owner}}/{{name}} <span class="error" title="{{error}}"><Icons icon="attention"/></span></div>
<div class="project">{{owner}}/{{name}} <span class="error" title="{{errors.join('\n')}}"><Icons icon="attention"/></span></div>
</td>
</tr>
{{else}}
@ -23,10 +23,10 @@
</td>
<td style="width:1%">
<div class="progress">
<span class="percent">{{Math.floor(format.progress(issues.closed.size, issues.open.size))}}%</span>
<span class="percent">{{Math.floor(stats.progress.points)}}%</span>
<span class="due">{{{ format.due(due_on) }}}</span>
<div class="outer bar">
<div class="inner bar {{format.onTime(number, due_on, created_at, issues.closed.size, issues.open.size)}}" style="width:{{format.progress(issues.closed.size, issues.open.size)}}%"></div>
<div class="inner bar {{(stats.isOnTime) ? 'green' : 'red'}}" style="width:{{stats.progress.points}}%"></div>
</div>
</div>
</td>

View File

@ -2,48 +2,26 @@
module.exports =
# Progress in percentages.
'progress': _.memoize (a, b) ->
100 * (a / (b + a))
# Is a milestone on time?
'onTime': _.memoize (number, due_on, created_at, closed_size, open_size) ->
# Milestones with no due date are always on track.
return 'green' unless due_on
# Calculate the progress in days.
a = +new Date created_at
b = +new Date
c = +new Date due_on
# Progress in time.
time = @progress b - a, c - b
# Progress in size.
[ 'red', 'green' ][ +(@progress(closed_size, open_size) > time) ]
, (args...) -> # resolver
args.join '/'
# Time from now.
'fromNow': _.memoize (jsonDate) ->
fromNow: _.memoize (jsonDate) ->
moment(new Date(jsonDate)).fromNow()
# When is a milestone due?
'due': (jsonDate) ->
due: (jsonDate) ->
return '&nbsp;' unless jsonDate
[ 'due', @fromNow jsonDate ].join(' ')
# Markdown formatting.
'markdown': (markup) ->
markdown: (markup) ->
marked markup
# Format milestone title.
'title': (text) ->
title: (text) ->
if text.toLowerCase().indexOf('milestone') > -1
text
else
[ 'Milestone', text ].join(' ')
# Hex to decimal.
hexToDecimal: (hex) ->
hexToDec: (hex) ->
parseInt hex, 16

View File

@ -29,6 +29,6 @@ module.exports = Ractive.extend
onrender: ->
@observe 'icon', (icon) ->
if icon and hex = codes[icon]
@set 'code', format.hexToDecimal hex
@set 'code', format.hexToDec hex
else
@set 'code', null

View File

@ -9,7 +9,6 @@ milestones = require '../../modules/github/milestones.coffee'
issues = require '../../modules/github/issues.coffee'
mediator = require '../../modules/mediator.coffee'
module.exports = Ractive.extend
'name': 'views/pages/index'
@ -32,28 +31,41 @@ module.exports = Ractive.extend
done = do system.async
# For all projects.
async.map projects.data.list, (project, cb) ->
# Skip if we have milestones already.
return cb null, project if project.milestones
# Otherwise fetch them.
milestones.fetchAll project, (error, list) ->
# Fetch their milestones.
milestones.fetchAll project, (err, list) ->
# Save the error if project does not exist.
return cb null, _.extend project, { error } if error
# Now map in the issues.
async.map list, (milestone, cb) ->
issues.fetchAll _.extend(project, { 'milestone': milestone.number }), (err, obj) ->
cb err, _.extend milestone, { 'issues': obj }
, (error, list) ->
delete project.milestone # from fetchAll or do deep clone
# Save any errors.
return cb null, _.extend project, { error } if error
# Otherwise add the milestones.
cb null, _.extend project, { 'milestones': list }
if err
projects.saveError project, err
return do cb
, (err, data) =>
# TODO: Errors are saved on projects. Show them as a notification here too.
# Save the projects.
# Now add in the issues.
async.each list, (milestone, cb) ->
# Do we have this milestone already?
return cb null if _.find project.milestones, ({ number }) ->
milestone.number is number
# OK fetch all the issues for this milestone then.
issues.fetchAll
'owner': project.owner
'name': project.name
'milestone': milestone.number
, (err, obj) ->
# Save any errors on the project.
if err
projects.saveError project, err
return do cb
# Add in the issues to the milestone.
_.extend milestone, { 'issues': obj }
# Save the milestone.
projects.addMilestone project, milestone
# Done
do cb
, cb
, =>
do done
@set
'projects.list': data
'ready': yes
@set 'ready', yes

View File

@ -48,7 +48,8 @@ module.exports = Ractive.extend
return cb err if err
# Save the milestone with issues.
projects.addMilestone project, _.extend milestone, { 'issues': obj }
cb null
# Next.
do cb
, cb
# Run it.