upgrade to Ractive 0.6.0

This commit is contained in:
Radek Stepan 2014-10-02 21:00:31 -07:00
parent 622633f418
commit d0732da5c9
15 changed files with 267 additions and 238 deletions

View File

@ -1,10 +1,10 @@
# burnchart.io
#burnchart.io
## Concept
##Concept
GitHub Burndown Chart as a service. Public repos are free, for private access auth via GitHub and pay.
## Notes
##Notes
- *payment gateways* in Canada: [Shopify](http://www.shopify.com/payment-gateways/canada), [Chargify](http://chargify.com/payment-gateways/) list; I get free processing on first $1000 with [Stripe](https://education.github.com/pack/offers)
- start people on a *Community* plan showing them a comparison table to upgrade to a better offering
@ -17,17 +17,17 @@ GitHub Burndown Chart as a service. Public repos are free, for private access au
- let people vote on features they want to see fast: [tally.tl](http://tally.tl/).
- use [readme.io](https://readme.io/) for documentation
## Plans
##Plans
### Community
###Community
- your repos are saved locally
- no auto-updates to milestones, everything fetched on page load
- no private repos
### Business
###Business
- you need to pay for a license to use the app for business purposes
- repos, milestones saved remotely
- auto-update with new information
- private repos
- private repos

View File

@ -2,7 +2,7 @@
##Release: MVP
- [ ] upgrade to Ractive [0.6.0](https://github.com/ractivejs/ractive/blob/dev/CHANGELOG.md)
- [x] upgrade to Ractive [0.6.0](https://github.com/ractivejs/ractive/blob/dev/CHANGELOG.md)
- [ ] create a 500/400/loading system messages
- [ ] slide top menu on page load too
- [ ] deal with Firebase timing out, are we still logged-in?

View File

@ -40835,7 +40835,7 @@ Router.prototype.mount = function(routes, path) {
Header: Header,
Notify: Notify
},
init: function() {
onrender: function() {
return router.init('/');
}
});
@ -40891,39 +40891,44 @@ Router.prototype.mount = function(routes, path) {
'data': {
'list': []
},
init: function() {
var _this = this;
localforage.getItem('projects', function(projects) {
if (projects == null) {
projects = [];
load: function(projects) {
if (projects == null) {
projects = [];
}
return async.each(projects, function(project, cb) {
return mediator.fire('!projects/add', project);
}, function(err) {
if (err) {
throw err;
}
return async.each(projects, function(project, cb) {
return mediator.fire('!projects/add', project);
}, function(err) {
if (err) {
throw err;
}
});
});
this.observe('list', function(projects) {
},
add: function(repo, add) {
var _this = this;
return request.allMilestones(repo, function(err, res) {
var milestones;
if (err) {
return done(err);
}
milestones = _.pluckMany(res, config.get('fields.milestone'));
_this.push('list', _.merge(repo, {
milestones: milestones
}));
return done();
});
},
clear: function() {
return this.set('list', []);
},
onconstruct: function() {
localforage.getItem('projects', _.bind(this.load, this));
mediator.on('!projects/add', _.bind(this.add, this));
return mediator.on('!projects/clear', _.bind(this.clear, this));
},
onrender: function() {
return this.observe('list', function(projects) {
return localforage.setItem('projects', projects);
});
mediator.on('!projects/add', function(repo, done) {
return request.allMilestones(repo, function(err, res) {
var milestones;
if (err) {
return done(err);
}
milestones = _.pluckMany(res, config.get('fields.milestone'));
_this.push('list', _.merge(repo, {
milestones: milestones
}));
return done();
});
});
return mediator.on('!projects/clear', function() {
return _this.set('list', []);
});
}
});
@ -41566,7 +41571,7 @@ Router.prototype.mount = function(routes, path) {
// router.coffee
root.require.register('burnchart/src/modules/router.js', function(exports, require, module) {
var el, mediator, route, router, system,
var el, mediator, route, routes, system,
__slice = [].slice;
mediator = require('./mediator');
@ -41587,7 +41592,7 @@ Router.prototype.mount = function(routes, path) {
});
};
module.exports = window.router = router = Router({
routes = {
'/': _.partial(route, 'index'),
'/new/project': _.partial(route, 'new'),
'/:owner/:name': _.partial(route, 'project'),
@ -41606,6 +41611,10 @@ Router.prototype.mount = function(routes, path) {
window.location.hash = '#';
return _.delay(done, 3e3);
}
};
module.exports = Router(routes).configure({
'strict': false
});
});
@ -41791,15 +41800,17 @@ Router.prototype.mount = function(routes, path) {
'user': user,
'icon': 'fire-station'
},
init: function() {
var _this = this;
this.on('!login', function() {
onconstruct: function() {
return this.on('!login', function() {
return firebase.login(function(err) {
if (err) {
throw err;
}
});
});
},
onrender: function() {
var _this = this;
return system.observe('loading', function(ya) {
return _this.set('icon', ya ? 'spinner1' : 'fire-station');
});
@ -41861,7 +41872,7 @@ Router.prototype.mount = function(routes, path) {
module.exports = Ractive.extend({
'template': require('../templates/icons'),
'isolated': true,
init: function() {
onrender: function() {
return this.observe('icon', function(icon) {
var hex;
if (icon && (hex = codes[icon])) {
@ -41892,7 +41903,7 @@ Router.prototype.mount = function(routes, path) {
Icons: Icons
},
'adapt': [Ractive.adaptors.Ractive],
init: function() {
onconstruct: function() {
return this.set('milestones', _.filter(projects.get('list'), {
'owner': this.get('owner'),
'name': this.get('name')
@ -41916,48 +41927,47 @@ Router.prototype.mount = function(routes, path) {
module.exports = Ractive.extend({
'template': require('../templates/notify'),
'data': {
'top': HEIGHT
},
init: function() {
var defaults, hidden, hide, show,
_this = this;
hidden = true;
defaults = {
'top': HEIGHT,
'hidden': true,
'defaults': {
'text': '',
'type': '',
'system': false,
'icon': 'megaphone',
'ttl': 5e3
};
show = function(opts) {
var pos;
hidden = false;
_this.set(opts = _.defaults(opts, defaults));
pos = [0, 50][+opts.system];
_this.animate('top', pos, {
'easing': d3.ease('bounce'),
'duration': 800
});
if (!opts.ttl) {
return;
}
},
show: function(opts) {
var pos;
this.set('hidden', false);
this.set(opts = _.defaults(opts, this.data.defaults));
pos = [0, 50][+opts.system];
this.animate('top', pos, {
'easing': d3.ease('bounce'),
'duration': 800
});
if (!opts.ttl) {
return;
}
return _.delay(_.bind(this.hide, this), opts.ttl);
},
hide: function() {
var _this = this;
if (this.data.hidden) {
return;
}
this.set('hidden', true);
return this.animate('top', HEIGHT, {
'easing': d3.ease('back'),
'complete': function() {
return _this.set('text', null);
}
return _.delay(hide, opts.ttl);
};
hide = function() {
if (hidden) {
return;
}
hidden = true;
return _this.animate('top', HEIGHT, {
'easing': d3.ease('back'),
'complete': function() {
return _this.set('text', null);
}
});
};
mediator.on('!app/notify', show);
mediator.on('!app/notify/hide', hide);
return this.on('close', hide);
});
},
onconstruct: function() {
mediator.on('!app/notify', _.bind(this.show, this));
mediator.on('!app/notify/hide', _.bind(this.hide, this));
return this.on('close', this.hide);
},
'components': {
Icons: Icons
@ -41986,7 +41996,7 @@ Router.prototype.mount = function(routes, path) {
'data': {
format: format
},
init: function() {
onrender: function() {
var name, owner, route, _ref,
_this = this;
_ref = this.get('route'), owner = _ref[0], name = _ref[1], milestone = _ref[2];
@ -42036,8 +42046,8 @@ Router.prototype.mount = function(routes, path) {
'data': {
format: format
},
init: function() {
return document.title = 'BurnChart: GitHub Burndown Chart as a Service';
onrender: function() {
return document.title = 'Burnchart: GitHub Burndown Chart as a Service';
}
});
@ -42059,7 +42069,7 @@ Router.prototype.mount = function(routes, path) {
user: user
},
'adapt': [Ractive.adaptors.Ractive],
init: function() {
onrender: function() {
var autocomplete;
document.title = 'Add a new project';
autocomplete = function(value) {};
@ -42093,7 +42103,7 @@ Router.prototype.mount = function(routes, path) {
'components': {
Milestones: Milestones
},
init: function() {
onrender: function() {
var name, owner, _ref;
_ref = this.get('route'), owner = _ref[0], name = _ref[1];
return document.title = "" + owner + "/" + name;

View File

@ -27,7 +27,7 @@
Header: Header,
Notify: Notify
},
init: function() {
onrender: function() {
return router.init('/');
}
});
@ -83,39 +83,44 @@
'data': {
'list': []
},
init: function() {
var _this = this;
localforage.getItem('projects', function(projects) {
if (projects == null) {
projects = [];
load: function(projects) {
if (projects == null) {
projects = [];
}
return async.each(projects, function(project, cb) {
return mediator.fire('!projects/add', project);
}, function(err) {
if (err) {
throw err;
}
return async.each(projects, function(project, cb) {
return mediator.fire('!projects/add', project);
}, function(err) {
if (err) {
throw err;
}
});
});
this.observe('list', function(projects) {
},
add: function(repo, add) {
var _this = this;
return request.allMilestones(repo, function(err, res) {
var milestones;
if (err) {
return done(err);
}
milestones = _.pluckMany(res, config.get('fields.milestone'));
_this.push('list', _.merge(repo, {
milestones: milestones
}));
return done();
});
},
clear: function() {
return this.set('list', []);
},
onconstruct: function() {
localforage.getItem('projects', _.bind(this.load, this));
mediator.on('!projects/add', _.bind(this.add, this));
return mediator.on('!projects/clear', _.bind(this.clear, this));
},
onrender: function() {
return this.observe('list', function(projects) {
return localforage.setItem('projects', projects);
});
mediator.on('!projects/add', function(repo, done) {
return request.allMilestones(repo, function(err, res) {
var milestones;
if (err) {
return done(err);
}
milestones = _.pluckMany(res, config.get('fields.milestone'));
_this.push('list', _.merge(repo, {
milestones: milestones
}));
return done();
});
});
return mediator.on('!projects/clear', function() {
return _this.set('list', []);
});
}
});
@ -758,7 +763,7 @@
// router.coffee
root.require.register('burnchart/src/modules/router.js', function(exports, require, module) {
var el, mediator, route, router, system,
var el, mediator, route, routes, system,
__slice = [].slice;
mediator = require('./mediator');
@ -779,7 +784,7 @@
});
};
module.exports = window.router = router = Router({
routes = {
'/': _.partial(route, 'index'),
'/new/project': _.partial(route, 'new'),
'/:owner/:name': _.partial(route, 'project'),
@ -798,6 +803,10 @@
window.location.hash = '#';
return _.delay(done, 3e3);
}
};
module.exports = Router(routes).configure({
'strict': false
});
});
@ -983,15 +992,17 @@
'user': user,
'icon': 'fire-station'
},
init: function() {
var _this = this;
this.on('!login', function() {
onconstruct: function() {
return this.on('!login', function() {
return firebase.login(function(err) {
if (err) {
throw err;
}
});
});
},
onrender: function() {
var _this = this;
return system.observe('loading', function(ya) {
return _this.set('icon', ya ? 'spinner1' : 'fire-station');
});
@ -1053,7 +1064,7 @@
module.exports = Ractive.extend({
'template': require('../templates/icons'),
'isolated': true,
init: function() {
onrender: function() {
return this.observe('icon', function(icon) {
var hex;
if (icon && (hex = codes[icon])) {
@ -1084,7 +1095,7 @@
Icons: Icons
},
'adapt': [Ractive.adaptors.Ractive],
init: function() {
onconstruct: function() {
return this.set('milestones', _.filter(projects.get('list'), {
'owner': this.get('owner'),
'name': this.get('name')
@ -1108,48 +1119,47 @@
module.exports = Ractive.extend({
'template': require('../templates/notify'),
'data': {
'top': HEIGHT
},
init: function() {
var defaults, hidden, hide, show,
_this = this;
hidden = true;
defaults = {
'top': HEIGHT,
'hidden': true,
'defaults': {
'text': '',
'type': '',
'system': false,
'icon': 'megaphone',
'ttl': 5e3
};
show = function(opts) {
var pos;
hidden = false;
_this.set(opts = _.defaults(opts, defaults));
pos = [0, 50][+opts.system];
_this.animate('top', pos, {
'easing': d3.ease('bounce'),
'duration': 800
});
if (!opts.ttl) {
return;
}
},
show: function(opts) {
var pos;
this.set('hidden', false);
this.set(opts = _.defaults(opts, this.data.defaults));
pos = [0, 50][+opts.system];
this.animate('top', pos, {
'easing': d3.ease('bounce'),
'duration': 800
});
if (!opts.ttl) {
return;
}
return _.delay(_.bind(this.hide, this), opts.ttl);
},
hide: function() {
var _this = this;
if (this.data.hidden) {
return;
}
this.set('hidden', true);
return this.animate('top', HEIGHT, {
'easing': d3.ease('back'),
'complete': function() {
return _this.set('text', null);
}
return _.delay(hide, opts.ttl);
};
hide = function() {
if (hidden) {
return;
}
hidden = true;
return _this.animate('top', HEIGHT, {
'easing': d3.ease('back'),
'complete': function() {
return _this.set('text', null);
}
});
};
mediator.on('!app/notify', show);
mediator.on('!app/notify/hide', hide);
return this.on('close', hide);
});
},
onconstruct: function() {
mediator.on('!app/notify', _.bind(this.show, this));
mediator.on('!app/notify/hide', _.bind(this.hide, this));
return this.on('close', this.hide);
},
'components': {
Icons: Icons
@ -1178,7 +1188,7 @@
'data': {
format: format
},
init: function() {
onrender: function() {
var name, owner, route, _ref,
_this = this;
_ref = this.get('route'), owner = _ref[0], name = _ref[1], milestone = _ref[2];
@ -1228,8 +1238,8 @@
'data': {
format: format
},
init: function() {
return document.title = 'BurnChart: GitHub Burndown Chart as a Service';
onrender: function() {
return document.title = 'Burnchart: GitHub Burndown Chart as a Service';
}
});
@ -1251,7 +1261,7 @@
user: user
},
'adapt': [Ractive.adaptors.Ractive],
init: function() {
onrender: function() {
var autocomplete;
document.title = 'Add a new project';
autocomplete = function(value) {};
@ -1285,7 +1295,7 @@
'components': {
Milestones: Milestones
},
init: function() {
onrender: function() {
var name, owner, _ref;
_ref = this.get('route'), owner = _ref[0], name = _ref[1];
return document.title = "" + owner + "/" + name;

View File

@ -14,7 +14,7 @@ App = Ractive.extend
'components': { Header, Notify }
init: ->
onrender: ->
router.init '/'
module.exports = new App()

View File

@ -10,35 +10,41 @@ module.exports = new Model
'data':
'list': []
init: ->
# Initialize with items stored locally.
localforage.getItem 'projects', (projects=[]) =>
# Fetch milestones for each of these projects.
async.each projects, (project, cb) ->
mediator.fire '!projects/add', project
, (err) ->
throw err if err
load: (projects=[]) ->
# Fetch milestones for each of these projects.
async.each projects, (project, cb) ->
mediator.fire '!projects/add', project
, (err) ->
throw err if err
add: (repo, add) ->
# TODO: warn when we are adding an existing repo (or
# silently go to index again).
# Fetch milestones (which validates repo too).
request.allMilestones repo, (err, res) =>
return done err if err
# Pluck these fields for milestones.
milestones = _.pluckMany res, config.get('fields.milestone')
# Push to the stack.
@push 'list', _.merge repo, { milestones }
# Call back.
do done
clear: ->
@set 'list', []
onconstruct: ->
# Initialize with items stored locally.
localforage.getItem 'projects', _.bind @load, @
mediator.on '!projects/add', _.bind @add, @
mediator.on '!projects/clear', _.bind @clear, @
onrender: ->
# Persist projects in local storage.
@observe 'list', (projects) ->
localforage.setItem 'projects', projects
mediator.on '!projects/add', (repo, done) =>
# TODO: warn when we are adding an existing repo (or
# silently go to index again).
# Fetch milestones (which validates repo too).
request.allMilestones repo, (err, res) =>
return done err if err
# Pluck these fields for milestones.
milestones = _.pluckMany res, config.get('fields.milestone')
# Push to the stack.
@push 'list', _.merge repo, { milestones }
# Call back.
do done
mediator.on '!projects/clear', =>
@set 'list', []

View File

@ -7,7 +7,7 @@ route = (page, args...) ->
Page = require "../views/pages/#{page}"
new Page { el, 'data': { 'route': args } }
module.exports = window.router = router = Router
routes =
'/': _.partial route, 'index'
'/new/project': _.partial route, 'new'
'/:owner/:name': _.partial route, 'project'
@ -25,4 +25,8 @@ module.exports = window.router = router = Router
'type': 'warn'
window.location.hash = '#'
_.delay done, 3e3
_.delay done, 3e3
# Flatiron Director router.
module.exports = Router(routes).configure
'strict': no # allow trailing slashes

View File

@ -12,12 +12,13 @@ module.exports = Ractive.extend
# Default app icon.
'icon': 'fire-station'
init: ->
onconstruct: ->
# Login user.
@on '!login', ->
firebase.login (err) ->
throw err if err
onrender: ->
# Switch loading icon with app icon.
system.observe 'loading', (ya) =>
@set 'icon', if ya then 'spinner1' else 'fire-station'

View File

@ -21,7 +21,7 @@ module.exports = Ractive.extend
'isolated': yes
init: ->
onrender: ->
@observe 'icon', (icon) ->
if icon and hex = codes[icon]
@set 'code', utils.hexToDecimal hex

View File

@ -10,7 +10,7 @@ module.exports = Ractive.extend
'adapt': [ Ractive.adaptors.Ractive ]
init: ->
onconstruct: ->
@set 'milestones', _.filter projects.get('list'),
'owner': @get 'owner'
'name': @get 'name'

View File

@ -9,53 +9,51 @@ module.exports = Ractive.extend
'data':
'top': HEIGHT
init: ->
hidden = yes
defaults =
'hidden': yes
'defaults':
'text': ''
'type': ''
'system': no
'icon': 'megaphone'
'ttl': 5e3
# Show a notification.
show = (opts) =>
hidden = no
# Set the opts.
@set opts = _.defaults opts, defaults
# Which position to slide to?
pos = [ 0, 50 ][ +opts.system ] # 0px or 50% from top
# Slide into view.
@animate 'top', pos,
'easing': d3.ease('bounce')
'duration': 800
# If no ttl then show permanently.
return unless opts.ttl
# Show a notification.
show: (opts) ->
@set 'hidden', no
# Set the opts.
@set opts = _.defaults opts, @data.defaults
# Which position to slide to?
pos = [ 0, 50 ][ +opts.system ] # 0px or 50% from top
# Slide into view.
@animate 'top', pos,
'easing': d3.ease('bounce')
'duration': 800
# If no ttl then show permanently.
return unless opts.ttl
# Slide out of the view.
_.delay hide, opts.ttl
# Slide out of the view.
_.delay _.bind(@hide, @), opts.ttl
# Hide a notification.
hide = =>
return if hidden
hidden = yes
@animate 'top', HEIGHT,
'easing': d3.ease('back')
'complete': =>
# Reset the text when all is done.
@set 'text', null
# Hide a notification.
hide: ->
return if @data.hidden
@set 'hidden', yes
@animate 'top', HEIGHT,
'easing': d3.ease('back')
'complete': =>
# Reset the text when all is done.
@set 'text', null
onconstruct: ->
# On outside messages.
mediator.on '!app/notify', show
mediator.on '!app/notify/hide', hide
mediator.on '!app/notify', _.bind @show, @
mediator.on '!app/notify/hide', _.bind @hide, @
# Close us prematurely...
@on 'close', hide
@on 'close', @hide
'components': { Icons }

View File

@ -11,7 +11,7 @@ module.exports = Ractive.extend
'data': { format }
init: ->
onrender: ->
[ owner, name, milestone ] = @get 'route'
route = { owner, name, milestone }

View File

@ -10,5 +10,5 @@ module.exports = Ractive.extend
'data': { format }
init: ->
document.title = 'BurnChart: GitHub Burndown Chart as a Service'
onrender: ->
document.title = 'Burnchart: GitHub Burndown Chart as a Service'

View File

@ -9,7 +9,7 @@ module.exports = Ractive.extend
'adapt': [ Ractive.adaptors.Ractive ]
init: ->
onrender: ->
document.title = 'Add a new project'
# TODO: autocomplete on our username if we are logged in or based

View File

@ -6,7 +6,7 @@ module.exports = Ractive.extend
'components': { Milestones }
init: ->
onrender: ->
[ owner, name ] = @get 'route'
document.title = "#{owner}/#{name}"