stop saving rubbish on chart page

This commit is contained in:
Radek Stepan 2014-10-12 17:30:18 -07:00
parent 30e19811a8
commit 7bddd337fe
8 changed files with 381 additions and 143 deletions

View File

@ -15,6 +15,7 @@
###Error Handling
- [ ] second visit to a different milestone comes out blank
- [ ] verify that project exists on project page when fetching it remotely (add behind the scenes)
- [ ] deal with Firebase timing out, are we still logged-in?
- [ ] visiting a chart page saves the project if it isn't saved already

View File

@ -39141,17 +39141,16 @@ Router.prototype.mount = function(routes, path) {
return user.reset();
},
onrender: function() {
var client,
_this = this;
var client;
this.set('client', client = new Firebase("https://" + config.data.firebase + ".firebaseio.com"));
return this.auth = new FirebaseSimpleLogin(client, function(err, obj) {
user.set('loaded', true);
if (err) {
throw err;
}
if (obj) {
return user.set(obj);
user.set(obj);
}
return user.set('ready', true);
});
}
});
@ -39360,7 +39359,7 @@ Router.prototype.mount = function(routes, path) {
// request.coffee
root.require.register('burnchart/src/modules/github/request.js', function(exports, require, module) {
var defaults, error, headers, request, response, user;
var defaults, error, headers, isReady, isValid, ready, request, response, stack, user;
user = require('../../models/user');
@ -39385,54 +39384,92 @@ Router.prototype.mount = function(routes, path) {
module.exports = {
repo: function(_arg, cb) {
var data, name, owner;
var name, owner;
owner = _arg.owner, name = _arg.name;
data = _.defaults({
'path': "/repos/" + owner + "/" + name,
'headers': headers(user.data.token)
}, defaults.github);
return request(data, cb);
if (!isValid({
owner: owner,
name: name
})) {
return cb('Request is malformed');
}
return ready(function() {
var data;
data = _.defaults({
'path': "/repos/" + owner + "/" + name,
'headers': headers(user.data.accessToken)
}, defaults.github);
return request(data, cb);
});
},
allMilestones: function(_arg, cb) {
var data, name, owner;
var name, owner;
owner = _arg.owner, name = _arg.name;
data = _.defaults({
'path': "/repos/" + owner + "/" + name + "/milestones",
'query': {
'state': 'open',
'sort': 'due_date',
'direction': 'asc'
},
'headers': headers(user.data.token)
}, defaults.github);
return request(data, cb);
if (!isValid({
owner: owner,
name: name
})) {
return cb('Request is malformed');
}
return ready(function() {
var data;
data = _.defaults({
'path': "/repos/" + owner + "/" + name + "/milestones",
'query': {
'state': 'open',
'sort': 'due_date',
'direction': 'asc'
},
'headers': headers(user.data.accessToken)
}, defaults.github);
return request(data, cb);
});
},
oneMilestone: function(_arg, cb) {
var data, milestone, name, owner;
var milestone, name, owner;
owner = _arg.owner, name = _arg.name, milestone = _arg.milestone;
data = _.defaults({
'path': "/repos/" + owner + "/" + name + "/milestones/" + milestone,
'query': {
'state': 'open',
'sort': 'due_date',
'direction': 'asc'
},
'headers': headers(user.data.token)
}, defaults.github);
return request(data, cb);
if (!isValid({
owner: owner,
name: name,
milestone: milestone
})) {
return cb('Request is malformed');
}
return ready(function() {
var data;
data = _.defaults({
'path': "/repos/" + owner + "/" + name + "/milestones/" + milestone,
'query': {
'state': 'open',
'sort': 'due_date',
'direction': 'asc'
},
'headers': headers(user.data.accessToken)
}, defaults.github);
return request(data, cb);
});
},
allIssues: function(_arg, query, cb) {
var data, milestone, name, owner;
var milestone, name, owner;
owner = _arg.owner, name = _arg.name, milestone = _arg.milestone;
data = _.defaults({
'path': "/repos/" + owner + "/" + name + "/issues",
'query': _.extend(query, {
milestone: milestone,
'per_page': '100'
}),
'headers': headers(user.data.token)
}, defaults.github);
return request(data, cb);
if (!isValid({
owner: owner,
name: name,
milestone: milestone
})) {
return cb('Request is malformed');
}
return ready(function() {
var data;
data = _.defaults({
'path': "/repos/" + owner + "/" + name + "/issues",
'query': _.extend(query, {
milestone: milestone,
'per_page': '100'
}),
'headers': headers(user.data.accessToken)
}, defaults.github);
return request(data, cb);
});
}
};
@ -39484,16 +39521,62 @@ Router.prototype.mount = function(routes, path) {
headers = function(token) {
var h;
h = _.extend({}, {
h = {
'Content-Type': 'application/json',
'Accept': 'application/vnd.github.v3'
});
};
if (token != null) {
h.Authorization = "token " + token;
}
return h;
};
isValid = function(obj) {
var key, rules, val;
rules = {
'owner': function(val) {
return val != null;
},
'name': function(val) {
return val != null;
},
'milestone': function(val) {
return _.isInt(val);
}
};
for (key in obj) {
val = obj[key];
if (key in rules && !rules[key](val)) {
return false;
}
}
return true;
};
isReady = user.data.ready;
stack = [];
ready = function(cb) {
if (isReady) {
return cb();
} else {
return stack.push(cb);
}
};
user.observe('ready', function(val) {
var _results;
isReady = val;
if (val) {
_results = [];
while (stack.length) {
_results.push(stack.shift()());
}
return _results;
}
});
error = function(err) {
var message;
switch (false) {
@ -39758,7 +39841,7 @@ Router.prototype.mount = function(routes, path) {
// header.mustache
root.require.register('burnchart/src/templates/header.js', function(exports, require, module) {
module.exports = ["<div id=\"head\">"," {{#with user}}"," {{#loaded}}"," <div class=\"right\" intro=\"fade\">"," {{#displayName}}"," {{displayName}} logged in"," {{else}}"," <a class=\"github\" on-click=\"!login\"><Icons icon=\"github\"/> Sign In</a>"," {{/displayName}}"," </div>"," {{/loaded}}"," {{/with}}",""," <a id=\"icon\" href=\"#\">"," <Icons icon=\"{{icon}}\"/>"," </a>",""," <!--"," <div class=\"q\">"," <Icons icon=\"search\"/>"," <Icons icon=\"down-open\"/>"," <input type=\"text\" placeholder=\"Jump to...\">"," </div>"," -->",""," <ul>"," <li><a href=\"#new/project\" class=\"add\"><Icons icon=\"plus-circled\"/> Add a Project</a></li>"," <li><a href=\"#\" class=\"faq\">FAQ</a></li>"," <li><a href=\"#reset\">DB Reset</a></li>"," <li><a href=\"#notify\">Notify</a></li>"," </ul>","</div>"].join("\n");
module.exports = ["<div id=\"head\">"," {{#with user}}"," {{#ready}}"," <div class=\"right\" intro=\"fade\">"," {{#displayName}}"," {{displayName}} logged in"," {{else}}"," <a class=\"github\" on-click=\"!login\"><Icons icon=\"github\"/> Sign In</a>"," {{/displayName}}"," </div>"," {{/ready}}"," {{/with}}",""," <a id=\"icon\" href=\"#\">"," <Icons icon=\"{{icon}}\"/>"," </a>",""," <!--"," <div class=\"q\">"," <Icons icon=\"search\"/>"," <Icons icon=\"down-open\"/>"," <input type=\"text\" placeholder=\"Jump to...\">"," </div>"," -->",""," <ul>"," <li><a href=\"#new/project\" class=\"add\"><Icons icon=\"plus-circled\"/> Add a Project</a></li>"," <li><a href=\"#\" class=\"faq\">FAQ</a></li>"," <li><a href=\"#reset\">DB Reset</a></li>"," <li><a href=\"#notify\">Notify</a></li>"," </ul>","</div>"].join("\n");
});
// hero.mustache
@ -39907,6 +39990,9 @@ Router.prototype.mount = function(routes, path) {
});
return obj;
});
},
'isInt': function(val) {
return !isNaN(val) && parseInt(Number(val)) === val && !isNaN(parseInt(val, 10));
}
});
@ -40290,6 +40376,7 @@ Router.prototype.mount = function(routes, path) {
var done, fetchIssues, fetchMilestone, milestone, name, obj, owner, project, _ref,
_this = this;
_ref = this.get('route'), owner = _ref[0], name = _ref[1], milestone = _ref[2];
milestone = parseInt(milestone);
document.title = "" + owner + "/" + name + "/" + milestone;
project = projects.find({
owner: owner,
@ -40309,13 +40396,19 @@ Router.prototype.mount = function(routes, path) {
}
done = system.async();
fetchMilestone = function(cb) {
return milestones.fetch(_.extend(project, {
return milestones.fetch({
owner: owner,
name: name,
milestone: milestone
}), cb);
}, cb);
};
fetchIssues = function(milestone, cb) {
return issues.fetchAll(project, function(err, obj) {
return cb(err, _.extend(milestone, {
fetchIssues = function(data, cb) {
return issues.fetchAll({
owner: owner,
name: name,
milestone: milestone
}, function(err, obj) {
return cb(err, _.extend(data, {
'issues': obj
}));
});
@ -40330,7 +40423,11 @@ Router.prototype.mount = function(routes, path) {
'ttl': null
});
}
projects.push('list', data);
if (project.milestones == null) {
project.milestones = [];
}
project.milestones.push(data);
projects.update('list');
return _this.set({
'milestone': data,
'ready': true

View File

@ -93,17 +93,16 @@
return user.reset();
},
onrender: function() {
var client,
_this = this;
var client;
this.set('client', client = new Firebase("https://" + config.data.firebase + ".firebaseio.com"));
return this.auth = new FirebaseSimpleLogin(client, function(err, obj) {
user.set('loaded', true);
if (err) {
throw err;
}
if (obj) {
return user.set(obj);
user.set(obj);
}
return user.set('ready', true);
});
}
});
@ -312,7 +311,7 @@
// request.coffee
root.require.register('burnchart/src/modules/github/request.js', function(exports, require, module) {
var defaults, error, headers, request, response, user;
var defaults, error, headers, isReady, isValid, ready, request, response, stack, user;
user = require('../../models/user');
@ -337,54 +336,92 @@
module.exports = {
repo: function(_arg, cb) {
var data, name, owner;
var name, owner;
owner = _arg.owner, name = _arg.name;
data = _.defaults({
'path': "/repos/" + owner + "/" + name,
'headers': headers(user.data.token)
}, defaults.github);
return request(data, cb);
if (!isValid({
owner: owner,
name: name
})) {
return cb('Request is malformed');
}
return ready(function() {
var data;
data = _.defaults({
'path': "/repos/" + owner + "/" + name,
'headers': headers(user.data.accessToken)
}, defaults.github);
return request(data, cb);
});
},
allMilestones: function(_arg, cb) {
var data, name, owner;
var name, owner;
owner = _arg.owner, name = _arg.name;
data = _.defaults({
'path': "/repos/" + owner + "/" + name + "/milestones",
'query': {
'state': 'open',
'sort': 'due_date',
'direction': 'asc'
},
'headers': headers(user.data.token)
}, defaults.github);
return request(data, cb);
if (!isValid({
owner: owner,
name: name
})) {
return cb('Request is malformed');
}
return ready(function() {
var data;
data = _.defaults({
'path': "/repos/" + owner + "/" + name + "/milestones",
'query': {
'state': 'open',
'sort': 'due_date',
'direction': 'asc'
},
'headers': headers(user.data.accessToken)
}, defaults.github);
return request(data, cb);
});
},
oneMilestone: function(_arg, cb) {
var data, milestone, name, owner;
var milestone, name, owner;
owner = _arg.owner, name = _arg.name, milestone = _arg.milestone;
data = _.defaults({
'path': "/repos/" + owner + "/" + name + "/milestones/" + milestone,
'query': {
'state': 'open',
'sort': 'due_date',
'direction': 'asc'
},
'headers': headers(user.data.token)
}, defaults.github);
return request(data, cb);
if (!isValid({
owner: owner,
name: name,
milestone: milestone
})) {
return cb('Request is malformed');
}
return ready(function() {
var data;
data = _.defaults({
'path': "/repos/" + owner + "/" + name + "/milestones/" + milestone,
'query': {
'state': 'open',
'sort': 'due_date',
'direction': 'asc'
},
'headers': headers(user.data.accessToken)
}, defaults.github);
return request(data, cb);
});
},
allIssues: function(_arg, query, cb) {
var data, milestone, name, owner;
var milestone, name, owner;
owner = _arg.owner, name = _arg.name, milestone = _arg.milestone;
data = _.defaults({
'path': "/repos/" + owner + "/" + name + "/issues",
'query': _.extend(query, {
milestone: milestone,
'per_page': '100'
}),
'headers': headers(user.data.token)
}, defaults.github);
return request(data, cb);
if (!isValid({
owner: owner,
name: name,
milestone: milestone
})) {
return cb('Request is malformed');
}
return ready(function() {
var data;
data = _.defaults({
'path': "/repos/" + owner + "/" + name + "/issues",
'query': _.extend(query, {
milestone: milestone,
'per_page': '100'
}),
'headers': headers(user.data.accessToken)
}, defaults.github);
return request(data, cb);
});
}
};
@ -436,16 +473,62 @@
headers = function(token) {
var h;
h = _.extend({}, {
h = {
'Content-Type': 'application/json',
'Accept': 'application/vnd.github.v3'
});
};
if (token != null) {
h.Authorization = "token " + token;
}
return h;
};
isValid = function(obj) {
var key, rules, val;
rules = {
'owner': function(val) {
return val != null;
},
'name': function(val) {
return val != null;
},
'milestone': function(val) {
return _.isInt(val);
}
};
for (key in obj) {
val = obj[key];
if (key in rules && !rules[key](val)) {
return false;
}
}
return true;
};
isReady = user.data.ready;
stack = [];
ready = function(cb) {
if (isReady) {
return cb();
} else {
return stack.push(cb);
}
};
user.observe('ready', function(val) {
var _results;
isReady = val;
if (val) {
_results = [];
while (stack.length) {
_results.push(stack.shift()());
}
return _results;
}
});
error = function(err) {
var message;
switch (false) {
@ -710,7 +793,7 @@
// header.mustache
root.require.register('burnchart/src/templates/header.js', function(exports, require, module) {
module.exports = ["<div id=\"head\">"," {{#with user}}"," {{#loaded}}"," <div class=\"right\" intro=\"fade\">"," {{#displayName}}"," {{displayName}} logged in"," {{else}}"," <a class=\"github\" on-click=\"!login\"><Icons icon=\"github\"/> Sign In</a>"," {{/displayName}}"," </div>"," {{/loaded}}"," {{/with}}",""," <a id=\"icon\" href=\"#\">"," <Icons icon=\"{{icon}}\"/>"," </a>",""," <!--"," <div class=\"q\">"," <Icons icon=\"search\"/>"," <Icons icon=\"down-open\"/>"," <input type=\"text\" placeholder=\"Jump to...\">"," </div>"," -->",""," <ul>"," <li><a href=\"#new/project\" class=\"add\"><Icons icon=\"plus-circled\"/> Add a Project</a></li>"," <li><a href=\"#\" class=\"faq\">FAQ</a></li>"," <li><a href=\"#reset\">DB Reset</a></li>"," <li><a href=\"#notify\">Notify</a></li>"," </ul>","</div>"].join("\n");
module.exports = ["<div id=\"head\">"," {{#with user}}"," {{#ready}}"," <div class=\"right\" intro=\"fade\">"," {{#displayName}}"," {{displayName}} logged in"," {{else}}"," <a class=\"github\" on-click=\"!login\"><Icons icon=\"github\"/> Sign In</a>"," {{/displayName}}"," </div>"," {{/ready}}"," {{/with}}",""," <a id=\"icon\" href=\"#\">"," <Icons icon=\"{{icon}}\"/>"," </a>",""," <!--"," <div class=\"q\">"," <Icons icon=\"search\"/>"," <Icons icon=\"down-open\"/>"," <input type=\"text\" placeholder=\"Jump to...\">"," </div>"," -->",""," <ul>"," <li><a href=\"#new/project\" class=\"add\"><Icons icon=\"plus-circled\"/> Add a Project</a></li>"," <li><a href=\"#\" class=\"faq\">FAQ</a></li>"," <li><a href=\"#reset\">DB Reset</a></li>"," <li><a href=\"#notify\">Notify</a></li>"," </ul>","</div>"].join("\n");
});
// hero.mustache
@ -859,6 +942,9 @@
});
return obj;
});
},
'isInt': function(val) {
return !isNaN(val) && parseInt(Number(val)) === val && !isNaN(parseInt(val, 10));
}
});
@ -1242,6 +1328,7 @@
var done, fetchIssues, fetchMilestone, milestone, name, obj, owner, project, _ref,
_this = this;
_ref = this.get('route'), owner = _ref[0], name = _ref[1], milestone = _ref[2];
milestone = parseInt(milestone);
document.title = "" + owner + "/" + name + "/" + milestone;
project = projects.find({
owner: owner,
@ -1261,13 +1348,19 @@
}
done = system.async();
fetchMilestone = function(cb) {
return milestones.fetch(_.extend(project, {
return milestones.fetch({
owner: owner,
name: name,
milestone: milestone
}), cb);
}, cb);
};
fetchIssues = function(milestone, cb) {
return issues.fetchAll(project, function(err, obj) {
return cb(err, _.extend(milestone, {
fetchIssues = function(data, cb) {
return issues.fetchAll({
owner: owner,
name: name,
milestone: milestone
}, function(err, obj) {
return cb(err, _.extend(data, {
'issues': obj
}));
});
@ -1282,7 +1375,11 @@
'ttl': null
});
}
projects.push('list', data);
if (project.milestones == null) {
project.milestones = [];
}
project.milestones.push(data);
projects.update('list');
return _this.set({
'milestone': data,
'ready': true

View File

@ -26,10 +26,10 @@ module.exports = new Model
@set 'client', client = new Firebase "https://#{config.data.firebase}.firebaseio.com"
# Check if we have a user in session.
@auth = new FirebaseSimpleLogin client, (err, obj) =>
user.set 'loaded', yes
@auth = new FirebaseSimpleLogin client, (err, obj) ->
throw err if err
# Save user.
user.set obj if obj
user.set obj if obj
# Say we are done.
user.set 'ready', yes

View File

@ -19,42 +19,54 @@ module.exports =
# Get a repo.
repo: ({ owner, name }, cb) ->
data = _.defaults
'path': "/repos/#{owner}/#{name}"
'headers': headers user.data.token
, defaults.github
return cb 'Request is malformed' unless isValid { owner, name }
request data, cb
ready ->
data = _.defaults
'path': "/repos/#{owner}/#{name}"
'headers': headers user.data.accessToken
, defaults.github
request data, cb
# Get all open milestones.
allMilestones: ({ owner, name }, cb) ->
data = _.defaults
'path': "/repos/#{owner}/#{name}/milestones"
'query': { 'state': 'open', 'sort': 'due_date', 'direction': 'asc' }
'headers': headers user.data.token
, defaults.github
allMilestones: ({ owner, name }, cb) ->
return cb 'Request is malformed' unless isValid { owner, name }
request data, cb
ready ->
data = _.defaults
'path': "/repos/#{owner}/#{name}/milestones"
'query': { 'state': 'open', 'sort': 'due_date', 'direction': 'asc' }
'headers': headers user.data.accessToken
, defaults.github
request data, cb
# Get one open milestone.
oneMilestone: ({ owner, name, milestone }, cb) ->
data = _.defaults
'path': "/repos/#{owner}/#{name}/milestones/#{milestone}"
'query': { 'state': 'open', 'sort': 'due_date', 'direction': 'asc' }
'headers': headers user.data.token
, defaults.github
return cb 'Request is malformed' unless isValid { owner, name, milestone }
request data, cb
ready ->
data = _.defaults
'path': "/repos/#{owner}/#{name}/milestones/#{milestone}"
'query': { 'state': 'open', 'sort': 'due_date', 'direction': 'asc' }
'headers': headers user.data.accessToken
, defaults.github
request data, cb
# Get all issues for a state.
allIssues: ({ owner, name, milestone }, query, cb) ->
data = _.defaults
'path': "/repos/#{owner}/#{name}/issues"
'query': _.extend query, { milestone, 'per_page': '100' }
'headers': headers user.data.token
, defaults.github
allIssues: ({ owner, name, milestone }, query, cb) ->
return cb 'Request is malformed' unless isValid { owner, name, milestone }
request data, cb
ready ->
data = _.defaults
'path': "/repos/#{owner}/#{name}/issues"
'query': _.extend query, { milestone, 'per_page': '100' }
'headers': headers user.data.accessToken
, defaults.github
request data, cb
# Make a request using SuperAgent.
request = ({ protocol, host, path, query, headers }, cb) ->
@ -99,13 +111,37 @@ response = (err, data, cb) ->
# Give us headers.
headers = (token) ->
# The defaults.
h = _.extend {},
h =
'Content-Type': 'application/json'
'Accept': 'application/vnd.github.v3'
# Add token?
h.Authorization = "token #{token}" if token?
h
isValid = (obj) ->
rules =
'owner': (val) -> val?
'name': (val) -> val?
'milestone': (val) -> _.isInt val
( return no for key, val of obj when key of rules and not rules[key](val) )
yes
# Switch when user is ready.
isReady = user.data.ready
# A stack of requests to execute once ready.
stack = []
ready = (cb) ->
if isReady then do cb else stack.push cb
# Observe user's readiness.
user.observe 'ready', (val) ->
isReady = val
# Clear the stack?
( do stack.shift() while stack.length ) if val
# Parse an error.
error = (err) ->
switch

View File

@ -1,6 +1,6 @@
<div id="head">
{{#with user}}
{{#loaded}}
{{#ready}}
<div class="right" intro="fade">
{{#displayName}}
{{displayName}} logged in
@ -8,7 +8,7 @@
<a class="github" on-click="!login"><Icons icon="github"/> Sign In</a>
{{/displayName}}
</div>
{{/loaded}}
{{/ready}}
{{/with}}
<a id="icon" href="#">

View File

@ -5,4 +5,7 @@ _.mixin
obj = {}
_.each keys, (key) ->
obj[key] = item[key]
obj
obj
'isInt': (val) ->
not isNaN(val) and parseInt(Number(val)) is val and not isNaN(parseInt(val, 10))

View File

@ -22,6 +22,8 @@ module.exports = Ractive.extend
onrender: ->
[ owner, name, milestone ] = @get 'route'
milestone = parseInt milestone
document.title = "#{owner}/#{name}/#{milestone}"
# Get the associated project.
@ -38,11 +40,11 @@ module.exports = Ractive.extend
done = do system.async
fetchMilestone = (cb) ->
milestones.fetch _.extend(project, { milestone }), cb
milestones.fetch { owner, name, milestone }, cb
fetchIssues = (milestone, cb) ->
issues.fetchAll project, (err, obj) ->
cb err, _.extend milestone, { 'issues': obj }
fetchIssues = (data, cb) ->
issues.fetchAll { owner, name, milestone }, (err, obj) ->
cb err, _.extend data, { 'issues': obj }
async.waterfall [
# Get the milestone.
@ -59,7 +61,9 @@ module.exports = Ractive.extend
} if err
# Save the milestone.
projects.push 'list', data
project.milestones ?= []
project.milestones.push data
projects.update 'list'
# Show the page.
@set