a really messy codeabase trying to determine milestone progress

This commit is contained in:
Radek Stepan 2014-10-09 19:21:23 -07:00
parent be2acdd564
commit 7f7c64d9c8
12 changed files with 481 additions and 351 deletions

View File

@ -2,11 +2,6 @@
##Release: MVP
###Main
1. Now we fetch all milestones for our repo if we don't have any cached already. This calculates the points for each milestone.
1. Continue with page-specific actions.
###GitHub
- [ ] progress needs to be calculated based on strategy even on homepage, then sort the milestones based on priority
@ -46,9 +41,11 @@
- [ ] focus on form fields style
- [ ] switch off `user-select` on buttons
- [ ] make async pages transition so that there is no "jumping" on the page
###Misc
- [ ] calculate by how many % are we late/on time so we can sort the milestones in projects
- [ ] vendor module so we can proxy require all `window` libs
- [ ] implement search box that quickly takes you to a chart (and may hide "pro actions")
- [ ] show hero box or projects with a fade in and only when known
@ -61,6 +58,7 @@
- [ ] make tests work again
- [ ] use minified builds in production
- [ ] move project to Assembly
- [ ] make the names consistent, reuse code, template etc.
##Future Releases

View File

@ -478,47 +478,48 @@ ul li{display:inline-block}
#title .title{border-bottom:3px solid #aaafbf;margin:30px 0 -3px 0;display:inline-block;padding-bottom:20px}
#title .sub{font-size:16px;font-weight:bold;margin:0 20px}
#title .description{display:inline-block;font-family:'MuseoSlab500Regular',serif;white-space:nowrap;color:#b1b6c4}
#content{padding:20px;margin-top:20px;}
#content #hero{background:url("../img/hires/2.jpg") center;-webkit-background-size:cover;-moz-background-size:cover;background-size:cover;-webkit-border-radius:2px;border-radius:2px;margin-bottom:30px;}
#content #hero .content{-webkit-border-radius:2px;border-radius:2px;color:#fff;padding:30px;background:rgba(0,0,0,0.3);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.2);box-shadow:inset 0 1px 2px rgba(0,0,0,0.2);}
#content #hero .content h2{margin-bottom:20px;margin-left:140px}
#content #hero .content p{font-family:'MuseoSlab500Regular',serif;font-size:18px;line-height:24px;margin-left:140px;text-align:justify;text-justify:inter-word}
#content #hero .content .address{font-size:120px;float:left}
#content #hero .content .cta{text-align:center;margin-top:10px;}
#content #hero .content .cta a{font-family:'MuseoSlab500Regular',serif;padding:11px 20px;-webkit-border-radius:2px;border-radius:2px;display:inline-block;margin:0 4px;}
#content #hero .content .cta a.primary{font-weight:bold;background:#c1041c;color:#fff}
#content #hero .content .cta a.secondary{background:#fff;color:#c1041c}
#content #add h2{color:#3e4457}
#content #add p{font-family:'MuseoSlab500Regular',serif;color:#b1b6c4;margin-top:10px;line-height:20px;text-align:justify;text-justify:inter-word;}
#content #add p a{color:#3e4457}
#content #add .form{margin-top:20px;}
#content #add .form table{width:100%;}
#content #add .form table tr td:first-child{width:100%}
#content #add .form input{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:10px;width:100%;-webkit-border-radius:2px 0 0 2px;border-radius:2px 0 0 2px;border:1px solid #dde1ed;border-right:0;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.2);box-shadow:inset 0 1px 2px rgba(0,0,0,0.2)}
#content #add .form a{margin-left:-2px;font-family:'MuseoSlab500Regular',serif;padding:11px 20px;-webkit-border-radius:0 2px 2px 0;border-radius:0 2px 2px 0;display:inline-block;font-weight:bold;background:#c1041c;color:#fff}
#content #projects{border:1px solid #cdcecf;-webkit-border-radius:2px;border-radius:2px;}
#content #projects h2{color:#3e4457;display:inline-block}
#content #projects .sort{float:right;line-height:30px}
#content #projects table{width:100%;}
#content #projects table tr td{background:#fcfcfc;padding:20px 30px;border-bottom:1px solid #eaecf2;}
#content #projects table tr td .project{color:inherit}
#content #projects table tr td .milestone .icon{font-size:10px;margin:0}
#content #projects table tr td .progress{width:200px;}
#content #projects table tr td .progress .percent,#content #projects table tr td .progress .due{color:#9399ad;font-size:13px}
#content #projects table tr td .progress .percent{float:right}
#content #projects table tr td .progress .bar{-webkit-border-radius:4px;border-radius:4px;background:#eaecf2;height:10px;width:100%;}
#content #projects table tr td .progress .bar.inner{-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.2);box-shadow:inset 0 1px 2px rgba(0,0,0,0.2)}
#content #projects table tr td .progress .bar.red{background:#c1041c}
#content #projects table tr td .progress .bar.green{background:#00b361}
#content #projects table tr td .progress .due.red{color:#c1041c;font-weight:bold}
#content #projects table tr td:first-child{color:#3e4457;font-weight:bold}
#content #projects table tr:nth-child(2) td{background:#fefefe}
#content #projects table tr:last-child td{border:0}
#content #projects table tr.done td{background:#ebf6f1;}
#content #projects table tr.done td .milestone,#content #projects table tr.done td .percent,#content #projects table tr.done td .due{color:#00b361}
#content #projects .header,#content #projects .footer{padding:20px 30px}
#content #projects .header{-webkit-box-shadow:0 1px 2px rgba(221,225,237,0.5);box-shadow:0 1px 2px rgba(221,225,237,0.5);margin-bottom:2px;border-bottom:1px solid #dde1ed;}
#content #projects .header a{font-family:'MuseoSlab500Regular',serif}
#content #projects .footer{background:#f9fafb;color:#aaafbf;-webkit-box-shadow:inset 0 1px 2px rgba(221,225,237,0.2);box-shadow:inset 0 1px 2px rgba(221,225,237,0.2);border-top:1px solid #dde1ed;text-align:right;font-family:'MuseoSlab500Regular',serif;}
#content #projects .footer .icon{color:#aaafbf}
#page{padding-bottom:80px;}
#page #content{padding:20px;margin-top:20px;}
#page #content #hero{background:url("../img/hires/2.jpg") center;-webkit-background-size:cover;-moz-background-size:cover;background-size:cover;-webkit-border-radius:2px;border-radius:2px;margin-bottom:30px;}
#page #content #hero .content{-webkit-border-radius:2px;border-radius:2px;color:#fff;padding:30px;background:rgba(0,0,0,0.3);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.2);box-shadow:inset 0 1px 2px rgba(0,0,0,0.2);}
#page #content #hero .content h2{margin-bottom:20px;margin-left:140px}
#page #content #hero .content p{font-family:'MuseoSlab500Regular',serif;font-size:18px;line-height:24px;margin-left:140px;text-align:justify;text-justify:inter-word}
#page #content #hero .content .address{font-size:120px;float:left}
#page #content #hero .content .cta{text-align:center;margin-top:10px;}
#page #content #hero .content .cta a{font-family:'MuseoSlab500Regular',serif;padding:11px 20px;-webkit-border-radius:2px;border-radius:2px;display:inline-block;margin:0 4px;}
#page #content #hero .content .cta a.primary{font-weight:bold;background:#c1041c;color:#fff}
#page #content #hero .content .cta a.secondary{background:#fff;color:#c1041c}
#page #content #add h2{color:#3e4457}
#page #content #add p{font-family:'MuseoSlab500Regular',serif;color:#b1b6c4;margin-top:10px;line-height:20px;text-align:justify;text-justify:inter-word;}
#page #content #add p a{color:#3e4457}
#page #content #add .form{margin-top:20px;}
#page #content #add .form table{width:100%;}
#page #content #add .form table tr td:first-child{width:100%}
#page #content #add .form input{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:10px;width:100%;-webkit-border-radius:2px 0 0 2px;border-radius:2px 0 0 2px;border:1px solid #dde1ed;border-right:0;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.2);box-shadow:inset 0 1px 2px rgba(0,0,0,0.2)}
#page #content #add .form a{margin-left:-2px;font-family:'MuseoSlab500Regular',serif;padding:11px 20px;-webkit-border-radius:0 2px 2px 0;border-radius:0 2px 2px 0;display:inline-block;font-weight:bold;background:#c1041c;color:#fff}
#page #content #projects{border:1px solid #cdcecf;-webkit-border-radius:2px;border-radius:2px;}
#page #content #projects h2{color:#3e4457;display:inline-block}
#page #content #projects .sort{float:right;line-height:30px}
#page #content #projects table{width:100%;}
#page #content #projects table tr td{background:#fcfcfc;padding:20px 30px;border-bottom:1px solid #eaecf2;}
#page #content #projects table tr td .project{color:inherit}
#page #content #projects table tr td .milestone .icon{font-size:10px;margin:0}
#page #content #projects table tr td .progress{width:200px;}
#page #content #projects table tr td .progress .percent,#page #content #projects table tr td .progress .due{color:#9399ad;font-size:13px}
#page #content #projects table tr td .progress .percent{float:right}
#page #content #projects table tr td .progress .bar{-webkit-border-radius:4px;border-radius:4px;background:#eaecf2;height:10px;width:100%;}
#page #content #projects table tr td .progress .bar.inner{-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.2);box-shadow:inset 0 1px 2px rgba(0,0,0,0.2)}
#page #content #projects table tr td .progress .bar.red{background:#c1041c}
#page #content #projects table tr td .progress .bar.green{background:#00b361}
#page #content #projects table tr td .progress .due.red{color:#c1041c;font-weight:bold}
#page #content #projects table tr td:first-child{color:#3e4457;font-weight:bold}
#page #content #projects table tr:nth-child(2) td{background:#fefefe}
#page #content #projects table tr:last-child td{border:0}
#page #content #projects table tr.done td{background:#ebf6f1;}
#page #content #projects table tr.done td .milestone,#page #content #projects table tr.done td .percent,#page #content #projects table tr.done td .due{color:#00b361}
#page #content #projects .header,#page #content #projects .footer{padding:20px 30px}
#page #content #projects .header{-webkit-box-shadow:0 1px 2px rgba(221,225,237,0.5);box-shadow:0 1px 2px rgba(221,225,237,0.5);margin-bottom:2px;border-bottom:1px solid #dde1ed;}
#page #content #projects .header a{font-family:'MuseoSlab500Regular',serif}
#page #content #projects .footer{background:#f9fafb;color:#aaafbf;-webkit-box-shadow:inset 0 1px 2px rgba(221,225,237,0.2);box-shadow:inset 0 1px 2px rgba(221,225,237,0.2);border-top:1px solid #dde1ed;text-align:right;font-family:'MuseoSlab500Regular',serif;}
#page #content #projects .footer .icon{color:#aaafbf}
#footer{position:absolute;width:100%;bottom:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-top:1px solid #f3f4f8;text-align:center;padding:30px;margin-top:30px;font-family:'MuseoSlab500Regular',serif}

View File

@ -71,47 +71,48 @@ ul li{display:inline-block}
#title .title{border-bottom:3px solid #aaafbf;margin:30px 0 -3px 0;display:inline-block;padding-bottom:20px}
#title .sub{font-size:16px;font-weight:bold;margin:0 20px}
#title .description{display:inline-block;font-family:'MuseoSlab500Regular',serif;white-space:nowrap;color:#b1b6c4}
#content{padding:20px;margin-top:20px;}
#content #hero{background:url("../img/hires/2.jpg") center;-webkit-background-size:cover;-moz-background-size:cover;background-size:cover;-webkit-border-radius:2px;border-radius:2px;margin-bottom:30px;}
#content #hero .content{-webkit-border-radius:2px;border-radius:2px;color:#fff;padding:30px;background:rgba(0,0,0,0.3);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.2);box-shadow:inset 0 1px 2px rgba(0,0,0,0.2);}
#content #hero .content h2{margin-bottom:20px;margin-left:140px}
#content #hero .content p{font-family:'MuseoSlab500Regular',serif;font-size:18px;line-height:24px;margin-left:140px;text-align:justify;text-justify:inter-word}
#content #hero .content .address{font-size:120px;float:left}
#content #hero .content .cta{text-align:center;margin-top:10px;}
#content #hero .content .cta a{font-family:'MuseoSlab500Regular',serif;padding:11px 20px;-webkit-border-radius:2px;border-radius:2px;display:inline-block;margin:0 4px;}
#content #hero .content .cta a.primary{font-weight:bold;background:#c1041c;color:#fff}
#content #hero .content .cta a.secondary{background:#fff;color:#c1041c}
#content #add h2{color:#3e4457}
#content #add p{font-family:'MuseoSlab500Regular',serif;color:#b1b6c4;margin-top:10px;line-height:20px;text-align:justify;text-justify:inter-word;}
#content #add p a{color:#3e4457}
#content #add .form{margin-top:20px;}
#content #add .form table{width:100%;}
#content #add .form table tr td:first-child{width:100%}
#content #add .form input{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:10px;width:100%;-webkit-border-radius:2px 0 0 2px;border-radius:2px 0 0 2px;border:1px solid #dde1ed;border-right:0;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.2);box-shadow:inset 0 1px 2px rgba(0,0,0,0.2)}
#content #add .form a{margin-left:-2px;font-family:'MuseoSlab500Regular',serif;padding:11px 20px;-webkit-border-radius:0 2px 2px 0;border-radius:0 2px 2px 0;display:inline-block;font-weight:bold;background:#c1041c;color:#fff}
#content #projects{border:1px solid #cdcecf;-webkit-border-radius:2px;border-radius:2px;}
#content #projects h2{color:#3e4457;display:inline-block}
#content #projects .sort{float:right;line-height:30px}
#content #projects table{width:100%;}
#content #projects table tr td{background:#fcfcfc;padding:20px 30px;border-bottom:1px solid #eaecf2;}
#content #projects table tr td .project{color:inherit}
#content #projects table tr td .milestone .icon{font-size:10px;margin:0}
#content #projects table tr td .progress{width:200px;}
#content #projects table tr td .progress .percent,#content #projects table tr td .progress .due{color:#9399ad;font-size:13px}
#content #projects table tr td .progress .percent{float:right}
#content #projects table tr td .progress .bar{-webkit-border-radius:4px;border-radius:4px;background:#eaecf2;height:10px;width:100%;}
#content #projects table tr td .progress .bar.inner{-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.2);box-shadow:inset 0 1px 2px rgba(0,0,0,0.2)}
#content #projects table tr td .progress .bar.red{background:#c1041c}
#content #projects table tr td .progress .bar.green{background:#00b361}
#content #projects table tr td .progress .due.red{color:#c1041c;font-weight:bold}
#content #projects table tr td:first-child{color:#3e4457;font-weight:bold}
#content #projects table tr:nth-child(2) td{background:#fefefe}
#content #projects table tr:last-child td{border:0}
#content #projects table tr.done td{background:#ebf6f1;}
#content #projects table tr.done td .milestone,#content #projects table tr.done td .percent,#content #projects table tr.done td .due{color:#00b361}
#content #projects .header,#content #projects .footer{padding:20px 30px}
#content #projects .header{-webkit-box-shadow:0 1px 2px rgba(221,225,237,0.5);box-shadow:0 1px 2px rgba(221,225,237,0.5);margin-bottom:2px;border-bottom:1px solid #dde1ed;}
#content #projects .header a{font-family:'MuseoSlab500Regular',serif}
#content #projects .footer{background:#f9fafb;color:#aaafbf;-webkit-box-shadow:inset 0 1px 2px rgba(221,225,237,0.2);box-shadow:inset 0 1px 2px rgba(221,225,237,0.2);border-top:1px solid #dde1ed;text-align:right;font-family:'MuseoSlab500Regular',serif;}
#content #projects .footer .icon{color:#aaafbf}
#page{padding-bottom:80px;}
#page #content{padding:20px;margin-top:20px;}
#page #content #hero{background:url("../img/hires/2.jpg") center;-webkit-background-size:cover;-moz-background-size:cover;background-size:cover;-webkit-border-radius:2px;border-radius:2px;margin-bottom:30px;}
#page #content #hero .content{-webkit-border-radius:2px;border-radius:2px;color:#fff;padding:30px;background:rgba(0,0,0,0.3);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.2);box-shadow:inset 0 1px 2px rgba(0,0,0,0.2);}
#page #content #hero .content h2{margin-bottom:20px;margin-left:140px}
#page #content #hero .content p{font-family:'MuseoSlab500Regular',serif;font-size:18px;line-height:24px;margin-left:140px;text-align:justify;text-justify:inter-word}
#page #content #hero .content .address{font-size:120px;float:left}
#page #content #hero .content .cta{text-align:center;margin-top:10px;}
#page #content #hero .content .cta a{font-family:'MuseoSlab500Regular',serif;padding:11px 20px;-webkit-border-radius:2px;border-radius:2px;display:inline-block;margin:0 4px;}
#page #content #hero .content .cta a.primary{font-weight:bold;background:#c1041c;color:#fff}
#page #content #hero .content .cta a.secondary{background:#fff;color:#c1041c}
#page #content #add h2{color:#3e4457}
#page #content #add p{font-family:'MuseoSlab500Regular',serif;color:#b1b6c4;margin-top:10px;line-height:20px;text-align:justify;text-justify:inter-word;}
#page #content #add p a{color:#3e4457}
#page #content #add .form{margin-top:20px;}
#page #content #add .form table{width:100%;}
#page #content #add .form table tr td:first-child{width:100%}
#page #content #add .form input{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:10px;width:100%;-webkit-border-radius:2px 0 0 2px;border-radius:2px 0 0 2px;border:1px solid #dde1ed;border-right:0;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.2);box-shadow:inset 0 1px 2px rgba(0,0,0,0.2)}
#page #content #add .form a{margin-left:-2px;font-family:'MuseoSlab500Regular',serif;padding:11px 20px;-webkit-border-radius:0 2px 2px 0;border-radius:0 2px 2px 0;display:inline-block;font-weight:bold;background:#c1041c;color:#fff}
#page #content #projects{border:1px solid #cdcecf;-webkit-border-radius:2px;border-radius:2px;}
#page #content #projects h2{color:#3e4457;display:inline-block}
#page #content #projects .sort{float:right;line-height:30px}
#page #content #projects table{width:100%;}
#page #content #projects table tr td{background:#fcfcfc;padding:20px 30px;border-bottom:1px solid #eaecf2;}
#page #content #projects table tr td .project{color:inherit}
#page #content #projects table tr td .milestone .icon{font-size:10px;margin:0}
#page #content #projects table tr td .progress{width:200px;}
#page #content #projects table tr td .progress .percent,#page #content #projects table tr td .progress .due{color:#9399ad;font-size:13px}
#page #content #projects table tr td .progress .percent{float:right}
#page #content #projects table tr td .progress .bar{-webkit-border-radius:4px;border-radius:4px;background:#eaecf2;height:10px;width:100%;}
#page #content #projects table tr td .progress .bar.inner{-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.2);box-shadow:inset 0 1px 2px rgba(0,0,0,0.2)}
#page #content #projects table tr td .progress .bar.red{background:#c1041c}
#page #content #projects table tr td .progress .bar.green{background:#00b361}
#page #content #projects table tr td .progress .due.red{color:#c1041c;font-weight:bold}
#page #content #projects table tr td:first-child{color:#3e4457;font-weight:bold}
#page #content #projects table tr:nth-child(2) td{background:#fefefe}
#page #content #projects table tr:last-child td{border:0}
#page #content #projects table tr.done td{background:#ebf6f1;}
#page #content #projects table tr.done td .milestone,#page #content #projects table tr.done td .percent,#page #content #projects table tr.done td .due{color:#00b361}
#page #content #projects .header,#page #content #projects .footer{padding:20px 30px}
#page #content #projects .header{-webkit-box-shadow:0 1px 2px rgba(221,225,237,0.5);box-shadow:0 1px 2px rgba(221,225,237,0.5);margin-bottom:2px;border-bottom:1px solid #dde1ed;}
#page #content #projects .header a{font-family:'MuseoSlab500Regular',serif}
#page #content #projects .footer{background:#f9fafb;color:#aaafbf;-webkit-box-shadow:inset 0 1px 2px rgba(221,225,237,0.2);box-shadow:inset 0 1px 2px rgba(221,225,237,0.2);border-top:1px solid #dde1ed;text-align:right;font-family:'MuseoSlab500Regular',serif;}
#page #content #projects .footer .icon{color:#aaafbf}
#footer{position:absolute;width:100%;bottom:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-top:1px solid #f3f4f8;text-align:center;padding:30px;margin-top:30px;font-family:'MuseoSlab500Regular',serif}

View File

@ -39104,7 +39104,7 @@ Router.prototype.mount = function(routes, path) {
"datetime": /^(\d{4}-\d{2}-\d{2})T(.*)/,
"size_label": /^size (\d+)$/,
"location": /^#!((\/[^\/]+){2,3})$/,
"points": 'ONE_SIZE'
"points": 'LABELS'
}
}
});
@ -39894,7 +39894,7 @@ Router.prototype.mount = function(routes, path) {
// milestones.mustache
root.require.register('burnchart/src/templates/milestones.js', function(exports, require, module) {
module.exports = ["<div id=\"projects\">"," <div class=\"header\">"," <a href=\"#\" class=\"sort\"><Icons icon=\"sort-alphabet\"/> Sorted by priority</a>"," <h2>Milestones</h2>"," </div>",""," <table>"," {{#project.milestones}}"," <tr>"," <td>"," <a class=\"milestone\" href=\"#{{project.owner}}/{{project.name}}/{{number}}\">{{ title }}</a>"," </td>"," <td style=\"width:1%\">"," <div class=\"progress\">"," <span class=\"percent\">{{Math.floor(format.progress(closed_issues, open_issues))}}%</span>"," <span class=\"due\">{{{ format.due(due_on) }}}</span>"," <div class=\"outer bar\">"," <div class=\"inner bar {{format.onTime(this)}}\" style=\"width:{{format.progress(closed_issues, open_issues)}}%\"></div>"," </div>"," </div>"," </td>"," </tr>"," {{/project.milestones}}"," </table>",""," <div class=\"footer\">"," <a href=\"#\"><Icons icon=\"cog\"/> Edit</a>"," </div>","</div>"].join("\n");
module.exports = ["<div id=\"projects\">"," <div class=\"header\">"," <a href=\"#\" class=\"sort\"><Icons icon=\"sort-alphabet\"/> Sorted by priority</a>"," <h2>Milestones</h2>"," </div>",""," <table>"," {{#project.milestones}}"," <tr>"," <td>"," <a class=\"milestone\" href=\"#{{project.owner}}/{{project.name}}/{{number}}\">{{ title }}</a>"," </td>"," <td style=\"width:1%\">"," <div class=\"progress\">"," <span class=\"percent\">{{Math.floor(progress)}}%</span>"," <span class=\"due\">{{{ due }}}</span>"," <div class=\"outer bar\">"," <div class=\"inner bar {{on_time}}\" style=\"width:{{progress}}%\"></div>"," </div>"," </div>"," </td>"," </tr>"," {{/project.milestones}}"," </table>",""," <div class=\"footer\">"," <a href=\"#\"><Icons icon=\"cog\"/> Edit</a>"," </div>","</div>"].join("\n");
});
// notify.mustache
@ -39924,7 +39924,7 @@ Router.prototype.mount = function(routes, path) {
// project.mustache
root.require.register('burnchart/src/templates/pages/project.js', function(exports, require, module) {
module.exports = ["{{#ready}}"," <div id=\"title\">"," <div class=\"wrap\">"," <h2 class=\"title\">{{route.join('/')}}</h2>"," </div>"," </div>",""," <div id=\"content\" class=\"wrap\">"," <Milestones project=\"{{project}}\"/>"," </div>","{{/ready}}"].join("\n");
module.exports = ["<div intro=\"fade\">"," {{#ready}}"," <div id=\"title\">"," <div class=\"wrap\">"," <h2 class=\"title\">{{route.join('/')}}</h2>"," </div>"," </div>",""," <div id=\"content\" class=\"wrap\">"," <Milestones project=\"{{project}}\"/>"," </div>"," {{/ready}}","</div>"].join("\n");
});
// projects.mustache
@ -39956,16 +39956,15 @@ Router.prototype.mount = function(routes, path) {
return 100 * (a / (b + a));
}),
'onTime': _.memoize(function(milestone) {
var a, b, c, points, time;
var a, b, c, time;
if (!milestone.due_on) {
return 'green';
}
points = this.progress(milestone.closed_issues, milestone.open_issues);
a = +new Date(milestone.created_at);
b = +(new Date);
c = +new Date(milestone.due_on);
time = this.progress(b - a, c - b);
return ['red', 'green'][+(points > time)];
return ['red', 'green'][+(milestone.progress > time)];
}, function(m) {
return [m.created_at, m.number].join('/');
}),
@ -40375,7 +40374,7 @@ Router.prototype.mount = function(routes, path) {
// project.coffee
root.require.register('burnchart/src/views/pages/project.js', function(exports, require, module) {
var Milestones, mediator, milestone, projects, system;
var Milestones, config, format, issues, mediator, milestones, projects, system;
Milestones = require('../milestones');
@ -40383,10 +40382,16 @@ Router.prototype.mount = function(routes, path) {
system = require('../../models/system');
milestone = require('../../modules/milestone');
config = require('../../models/config');
milestones = require('../../modules/milestone');
issues = require('../../modules/issues');
mediator = require('../../modules/mediator');
format = require('../../utils/format');
module.exports = Ractive.extend({
'name': 'views/pages/project',
'template': require('../../templates/pages/project'),
@ -40412,28 +40417,67 @@ Router.prototype.mount = function(routes, path) {
return this.set('ready', true);
}
done = system.async();
return milestone.getAll(project, function(err, warn, list) {
done();
if (err) {
return mediator.fire('!app/notify', {
'text': err.toString(),
'type': 'alert',
'system': true,
'ttl': null
});
return milestones.getAll(project, function(err, warn, list) {
if (err || warn) {
done();
if (err) {
return mediator.fire('!app/notify', {
'text': err.toString(),
'type': 'alert',
'system': true,
'ttl': null
});
}
if (warn) {
return mediator.fire('!app/notify', {
'text': warn.toString(),
'type': 'warn',
'system': true,
'ttl': null
});
}
}
if (warn) {
return mediator.fire('!app/notify', {
'text': warn.toString(),
'type': 'warn',
'system': true,
'ttl': null
});
switch (config.data.chart.points) {
case 'ONE_SIZE':
list = _.map(list, function(m) {
m.progress = format.progress(m.closed_issues, m.open_issues);
m.on_time = format.onTime(m);
m.due = format.due(m.due_on);
return m;
});
done();
return _this.set({
'project.milestones': list,
'ready': true
});
case 'LABELS':
return async.map(list, function(m, cb) {
return issues.get_all(_.extend(project, {
'milestone': m
}), function(err, arr) {
if (err) {
return cb(err);
}
return issues.filter(arr, function(err, filtered, total) {
return console.log(filtered, total);
});
});
}, function(err, list) {
done();
if (err) {
return mediator.fire('!app/notify', {
'text': err.toString(),
'type': 'alert',
'system': true,
'ttl': null
});
}
return this.set({
'project.milestones': list,
'ready': true
});
});
}
return _this.set({
'project.milestones': list,
'ready': true
});
});
}
});

View File

@ -56,7 +56,7 @@
"datetime": /^(\d{4}-\d{2}-\d{2})T(.*)/,
"size_label": /^size (\d+)$/,
"location": /^#!((\/[^\/]+){2,3})$/,
"points": 'ONE_SIZE'
"points": 'LABELS'
}
}
});
@ -846,7 +846,7 @@
// milestones.mustache
root.require.register('burnchart/src/templates/milestones.js', function(exports, require, module) {
module.exports = ["<div id=\"projects\">"," <div class=\"header\">"," <a href=\"#\" class=\"sort\"><Icons icon=\"sort-alphabet\"/> Sorted by priority</a>"," <h2>Milestones</h2>"," </div>",""," <table>"," {{#project.milestones}}"," <tr>"," <td>"," <a class=\"milestone\" href=\"#{{project.owner}}/{{project.name}}/{{number}}\">{{ title }}</a>"," </td>"," <td style=\"width:1%\">"," <div class=\"progress\">"," <span class=\"percent\">{{Math.floor(format.progress(closed_issues, open_issues))}}%</span>"," <span class=\"due\">{{{ format.due(due_on) }}}</span>"," <div class=\"outer bar\">"," <div class=\"inner bar {{format.onTime(this)}}\" style=\"width:{{format.progress(closed_issues, open_issues)}}%\"></div>"," </div>"," </div>"," </td>"," </tr>"," {{/project.milestones}}"," </table>",""," <div class=\"footer\">"," <a href=\"#\"><Icons icon=\"cog\"/> Edit</a>"," </div>","</div>"].join("\n");
module.exports = ["<div id=\"projects\">"," <div class=\"header\">"," <a href=\"#\" class=\"sort\"><Icons icon=\"sort-alphabet\"/> Sorted by priority</a>"," <h2>Milestones</h2>"," </div>",""," <table>"," {{#project.milestones}}"," <tr>"," <td>"," <a class=\"milestone\" href=\"#{{project.owner}}/{{project.name}}/{{number}}\">{{ title }}</a>"," </td>"," <td style=\"width:1%\">"," <div class=\"progress\">"," <span class=\"percent\">{{Math.floor(progress)}}%</span>"," <span class=\"due\">{{{ due }}}</span>"," <div class=\"outer bar\">"," <div class=\"inner bar {{on_time}}\" style=\"width:{{progress}}%\"></div>"," </div>"," </div>"," </td>"," </tr>"," {{/project.milestones}}"," </table>",""," <div class=\"footer\">"," <a href=\"#\"><Icons icon=\"cog\"/> Edit</a>"," </div>","</div>"].join("\n");
});
// notify.mustache
@ -876,7 +876,7 @@
// project.mustache
root.require.register('burnchart/src/templates/pages/project.js', function(exports, require, module) {
module.exports = ["{{#ready}}"," <div id=\"title\">"," <div class=\"wrap\">"," <h2 class=\"title\">{{route.join('/')}}</h2>"," </div>"," </div>",""," <div id=\"content\" class=\"wrap\">"," <Milestones project=\"{{project}}\"/>"," </div>","{{/ready}}"].join("\n");
module.exports = ["<div intro=\"fade\">"," {{#ready}}"," <div id=\"title\">"," <div class=\"wrap\">"," <h2 class=\"title\">{{route.join('/')}}</h2>"," </div>"," </div>",""," <div id=\"content\" class=\"wrap\">"," <Milestones project=\"{{project}}\"/>"," </div>"," {{/ready}}","</div>"].join("\n");
});
// projects.mustache
@ -908,16 +908,15 @@
return 100 * (a / (b + a));
}),
'onTime': _.memoize(function(milestone) {
var a, b, c, points, time;
var a, b, c, time;
if (!milestone.due_on) {
return 'green';
}
points = this.progress(milestone.closed_issues, milestone.open_issues);
a = +new Date(milestone.created_at);
b = +(new Date);
c = +new Date(milestone.due_on);
time = this.progress(b - a, c - b);
return ['red', 'green'][+(points > time)];
return ['red', 'green'][+(milestone.progress > time)];
}, function(m) {
return [m.created_at, m.number].join('/');
}),
@ -1327,7 +1326,7 @@
// project.coffee
root.require.register('burnchart/src/views/pages/project.js', function(exports, require, module) {
var Milestones, mediator, milestone, projects, system;
var Milestones, config, format, issues, mediator, milestones, projects, system;
Milestones = require('../milestones');
@ -1335,10 +1334,16 @@
system = require('../../models/system');
milestone = require('../../modules/milestone');
config = require('../../models/config');
milestones = require('../../modules/milestone');
issues = require('../../modules/issues');
mediator = require('../../modules/mediator');
format = require('../../utils/format');
module.exports = Ractive.extend({
'name': 'views/pages/project',
'template': require('../../templates/pages/project'),
@ -1364,28 +1369,67 @@
return this.set('ready', true);
}
done = system.async();
return milestone.getAll(project, function(err, warn, list) {
done();
if (err) {
return mediator.fire('!app/notify', {
'text': err.toString(),
'type': 'alert',
'system': true,
'ttl': null
});
return milestones.getAll(project, function(err, warn, list) {
if (err || warn) {
done();
if (err) {
return mediator.fire('!app/notify', {
'text': err.toString(),
'type': 'alert',
'system': true,
'ttl': null
});
}
if (warn) {
return mediator.fire('!app/notify', {
'text': warn.toString(),
'type': 'warn',
'system': true,
'ttl': null
});
}
}
if (warn) {
return mediator.fire('!app/notify', {
'text': warn.toString(),
'type': 'warn',
'system': true,
'ttl': null
});
switch (config.data.chart.points) {
case 'ONE_SIZE':
list = _.map(list, function(m) {
m.progress = format.progress(m.closed_issues, m.open_issues);
m.on_time = format.onTime(m);
m.due = format.due(m.due_on);
return m;
});
done();
return _this.set({
'project.milestones': list,
'ready': true
});
case 'LABELS':
return async.map(list, function(m, cb) {
return issues.get_all(_.extend(project, {
'milestone': m
}), function(err, arr) {
if (err) {
return cb(err);
}
return issues.filter(arr, function(err, filtered, total) {
return console.log(filtered, total);
});
});
}, function(err, list) {
done();
if (err) {
return mediator.fire('!app/notify', {
'text': err.toString(),
'type': 'alert',
'system': true,
'ttl': null
});
}
return this.set({
'project.milestones': list,
'ready': true
});
});
}
return _this.set({
'project.milestones': list,
'ready': true
});
});
}
});

View File

@ -31,5 +31,5 @@ module.exports = new Model
"size_label": /^size (\d+)$/
# How do we specify which user/repo/(milestone) we want?
"location": /^#!((\/[^\/]+){2,3})$/
# Process all issues as one size or use labels.
"points": 'ONE_SIZE'
# Process all issues as one size (ONE_SIZE) or use labels (LABELS).
"points": 'LABELS'

View File

@ -11,7 +11,7 @@ module.exports =
# Concat them here.
results = []
# One pageful fetch (next pages in series).
do fetch_page = (page = 1) ->
do fetch_page = (page=1) ->
request.allIssues opts, {
'milestone': opts.milestone.number,
state, page

View File

@ -184,203 +184,206 @@ ul
white-space: nowrap
color: #B1B6C4
#content
padding: 20px
margin-top: 20px
#page
padding-bottom: 80px // height of the footer
#content
padding: 20px
margin-top: 20px
#hero
background: url('../img/hires/2.jpg') center
background-size: cover
border-radius: 2px
margin-bottom: 30px
.content
#hero
background: url('../img/hires/2.jpg') center
background-size: cover
border-radius: 2px
color: #FFF
padding: 30px
background: rgba(#000, 30%)
box-shadow: inset 0 1px 2px rgba(#000, 20%)
margin-bottom: 30px
.content
border-radius: 2px
color: #FFF
padding: 30px
background: rgba(#000, 30%)
box-shadow: inset 0 1px 2px rgba(#000, 20%)
h2
margin-bottom: 20px
margin-left: 140px
p
font-family: $serif_font
font-size: 18px
line-height: 24px
margin-left: 140px
text-align: justify
text-justify: inter-word
.address
font-size: 120px
float: left
.cta
text-align: center
margin-top: 10px
a
font-family: $serif_font
padding: 11px 20px
border-radius: 2px
display: inline-block
margin: 0 4px
&.primary
font-weight: bold
background: $strong_color
color: #FFF
&.secondary
background: #FFF
color: $strong_color
#add
h2
margin-bottom: 20px
margin-left: 140px
color: #3E4457
p
font-family: $serif_font
font-size: 18px
line-height: 24px
margin-left: 140px
color: #B1B6C4
margin-top: 10px
line-height: 20px
text-align: justify
text-justify: inter-word
.address
font-size: 120px
float: left
a
color: #3E4457
.cta
text-align: center
margin-top: 10px
.form
margin-top: 20px
table
width: 100%
tr
td
&:first-child
width: 100%
input
box-sizing: border-box
padding: 10px
width: 100%
border-radius: 2px 0 0 2px
border: 1px solid #DDE1ED
border-right: 0
box-shadow: inset 0 1px 2px rgba(#000, 20%)
a
margin-left: -2px
font-family: $serif_font
padding: 11px 20px
border-radius: 2px
border-radius: 0 2px 2px 0
display: inline-block
margin: 0 4px
font-weight: bold
background: $strong_color
color: #FFF
&.primary
font-weight: bold
background: $strong_color
color: #FFF
&.secondary
background: #FFF
color: $strong_color
#projects
border: 1px solid #CDCECF
border-radius: 2px
#add
h2
color: #3E4457
p
font-family: $serif_font
color: #B1B6C4
margin-top: 10px
line-height: 20px
text-align: justify
text-justify: inter-word
a
h2
color: #3E4457
display: inline-block
.sort
float: right
line-height: 30px
.form
margin-top: 20px
table
width: 100%
tr
tr
td
background: #FCFCFC
padding: 20px 30px
border-bottom: 1px solid #EAECF2
.project
color: inherit
.milestone
.icon
font-size: 10px
margin: 0
.progress
width: 200px
.percent, .due
color: darken(#C1C4D0, 20%)
font-size: 13px
.percent
float: right
.bar
border-radius: 4px
background: #EAECF2
height: 10px
width: 100%
&.inner
box-shadow: inset 0 1px 2px rgba(#000, 20%)
&.red
background: $strong_color
&.green
background: #00B361
.due
&.red
color: $strong_color
font-weight: bold
&:first-child
width: 100%
color: #3E4457
font-weight: bold
input
box-sizing: border-box
padding: 10px
width: 100%
border-radius: 2px 0 0 2px
border: 1px solid #DDE1ED
border-right: 0
box-shadow: inset 0 1px 2px rgba(#000, 20%)
&:nth-child(2)
td
background: lighten(#FCFCFC, 60%)
a
margin-left: -2px
font-family: $serif_font
padding: 11px 20px
border-radius: 0 2px 2px 0
display: inline-block
font-weight: bold
background: $strong_color
color: #FFF
&:last-child
td
border: 0
#projects
border: 1px solid #CDCECF
border-radius: 2px
&.done
td
background: #EBF6F1
h2
color: #3E4457
display: inline-block
.milestone, .percent, .due
color: #00B361
.sort
float: right
line-height: 30px
.header, .footer
padding: 20px 30px
table
width: 100%
.header
box-shadow: 0 1px 2px rgba(#DDE1ED, 50%)
margin-bottom: 2px
border-bottom: 1px solid #DDE1ED
tr
td
background: #FCFCFC
padding: 20px 30px
border-bottom: 1px solid #EAECF2
a
font-family: $serif_font
.project
color: inherit
.milestone
.icon
font-size: 10px
margin: 0
.progress
width: 200px
.percent, .due
color: darken(#C1C4D0, 20%)
font-size: 13px
.percent
float: right
.bar
border-radius: 4px
background: #EAECF2
height: 10px
width: 100%
&.inner
box-shadow: inset 0 1px 2px rgba(#000, 20%)
&.red
background: $strong_color
&.green
background: #00B361
.due
&.red
color: $strong_color
font-weight: bold
&:first-child
color: #3E4457
font-weight: bold
&:nth-child(2)
td
background: lighten(#FCFCFC, 60%)
&:last-child
td
border: 0
&.done
td
background: #EBF6F1
.milestone, .percent, .due
color: #00B361
.header, .footer
padding: 20px 30px
.header
box-shadow: 0 1px 2px rgba(#DDE1ED, 50%)
margin-bottom: 2px
border-bottom: 1px solid #DDE1ED
a
font-family: $serif_font
.footer
background: #F9FAFB
color: #AAAFBF
box-shadow: inset 0 1px 2px rgba(#DDE1ED, 20%)
border-top: 1px solid #DDE1ED
text-align: right
font-family: $serif_font
.icon
.footer
background: #F9FAFB
color: #AAAFBF
box-shadow: inset 0 1px 2px rgba(#DDE1ED, 20%)
border-top: 1px solid #DDE1ED
text-align: right
font-family: $serif_font
.icon
color: #AAAFBF
#footer
position: absolute

View File

@ -12,10 +12,10 @@
</td>
<td style="width:1%">
<div class="progress">
<span class="percent">{{Math.floor(format.progress(closed_issues, open_issues))}}%</span>
<span class="due">{{{ format.due(due_on) }}}</span>
<span class="percent">{{Math.floor(progress)}}%</span>
<span class="due">{{{ due }}}</span>
<div class="outer bar">
<div class="inner bar {{format.onTime(this)}}" style="width:{{format.progress(closed_issues, open_issues)}}%"></div>
<div class="inner bar {{on_time}}" style="width:{{progress}}%"></div>
</div>
</div>
</td>

View File

@ -1,11 +1,13 @@
{{#ready}}
<div id="title">
<div class="wrap">
<h2 class="title">{{route.join('/')}}</h2>
<div intro="fade">
{{#ready}}
<div id="title">
<div class="wrap">
<h2 class="title">{{route.join('/')}}</h2>
</div>
</div>
</div>
<div id="content" class="wrap">
<Milestones project="{{project}}"/>
</div>
{{/ready}}
<div id="content" class="wrap">
<Milestones project="{{project}}"/>
</div>
{{/ready}}
</div>

View File

@ -11,9 +11,6 @@ module.exports =
# Milestones with no due date are always on track.
return 'green' unless milestone.due_on
# Progress in points.
points = @progress milestone.closed_issues, milestone.open_issues
# Calculate the progress in days.
a = +new Date milestone.created_at
b = +new Date
@ -22,7 +19,7 @@ module.exports =
# Progress in time.
time = @progress b - a, c - b
[ 'red', 'green' ][ +(points > time) ]
[ 'red', 'green' ][ +(milestone.progress > time) ]
, (m) -> # resolver
[ m.created_at, m.number ].join '/'

View File

@ -1,9 +1,12 @@
Milestones = require '../milestones'
projects = require '../../models/projects'
system = require '../../models/system'
milestone = require '../../modules/milestone'
mediator = require '../../modules/mediator'
projects = require '../../models/projects'
system = require '../../models/system'
config = require '../../models/config'
milestones = require '../../modules/milestone'
issues = require '../../modules/issues'
mediator = require '../../modules/mediator'
format = require '../../utils/format'
module.exports = Ractive.extend
@ -33,24 +36,61 @@ module.exports = Ractive.extend
# We are loading the milestones then.
done = do system.async
milestone.getAll project, (err, warn, list) =>
do done
milestones.getAll project, (err, warn, list) =>
if err or warn
do done
return mediator.fire '!app/notify', {
'text': do err.toString
'type': 'alert'
'system': yes
'ttl': null
} if err
return mediator.fire '!app/notify', {
'text': do err.toString
'type': 'alert'
'system': yes
'ttl': null
} if err
return mediator.fire '!app/notify', {
'text': do warn.toString
'type': 'warn'
'system': yes
'ttl': null
} if warn
return mediator.fire '!app/notify', {
'text': do warn.toString
'type': 'warn'
'system': yes
'ttl': null
} if warn
# Save the milestones.
@set
'project.milestones': list
'ready': yes
# Calculate progress in all milestones.
switch config.data.chart.points
when 'ONE_SIZE'
list = _.map list, (m) ->
m.progress = format.progress m.closed_issues, m.open_issues
m.on_time = format.onTime m
m.due = format.due m.due_on
m
# Now we are done.
do done
# Save the milestones.
@set
'project.milestones': list
'ready': yes
when 'LABELS'
# We need to fetch all issues per milestone.
async.map list, (m, cb) ->
issues.get_all _.extend(project, { 'milestone': m }), (err, arr) ->
return cb err if err
issues.filter arr, (err, filtered, total) ->
console.log filtered, total
, (err, list) ->
# Now we are done.
do done
return mediator.fire '!app/notify', {
'text': do err.toString
'type': 'alert'
'system': yes
'ttl': null
} if err
# Save the milestones.
@set
'project.milestones': list
'ready': yes