save project with a loading sign and a notification
This commit is contained in:
parent
f108813d29
commit
51be190aea
61
TODO.md
61
TODO.md
|
@ -2,36 +2,57 @@
|
||||||
|
|
||||||
##Release: MVP
|
##Release: MVP
|
||||||
|
|
||||||
- [ ] create a 500/400/loading system messages
|
###GitHub
|
||||||
- [ ] deal with Firebase timing out, are we still logged-in?
|
|
||||||
- [ ] mediator `!app/notify/edit` will edit the current notification
|
|
||||||
- [ ] verify that project exists on project page when fetching it remotely (add behind the scenes)
|
|
||||||
- [ ] need to show status (receiving information etc.) per repo
|
|
||||||
- [ ] provide a documentation site
|
|
||||||
- [ ] visiting a chart page saves the project if it isn't saved already
|
|
||||||
- [ ] landing page for the project and put message on my repo
|
|
||||||
- [ ] Handle [404](https://www.firebase.com/docs/hosting/guide/url-redirects-rewrites.html#section-404) on routes; from catch all check if '/' or go 404 controller
|
|
||||||
- [ ] allow `pushState` when [Firebase hosted](https://www.firebase.com/docs/hosting/guide/url-redirects-rewrites.html#section-rewrites)
|
|
||||||
- [ ] progress needs to be calculated based on strategy even on homepage, then sort the milestones based on priority
|
- [ ] progress needs to be calculated based on strategy even on homepage, then sort the milestones based on priority
|
||||||
- [ ] calculate left margin based on the total number of points text width
|
|
||||||
- [ ] Do not show login/logged-in state when we are still fetching that information from Firebase
|
###Notifications
|
||||||
|
|
||||||
|
- [ ] create a 500/400/loading system messages
|
||||||
|
- [ ] mediator `!app/notify/edit` will edit the current notification
|
||||||
|
- [ ] need to show status (receiving information etc.) per repo
|
||||||
|
|
||||||
|
###Error Handling
|
||||||
|
|
||||||
|
- [ ] 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
|
||||||
|
- [ ] Check that we have not run out of requests to make
|
||||||
|
- [ ] can we get more than 1 notification at a time?
|
||||||
|
- [x] Validate repo input and show a loading sign of sorts
|
||||||
|
|
||||||
|
###Bugs
|
||||||
|
|
||||||
- [ ] local storage is getting reset
|
- [ ] local storage is getting reset
|
||||||
- [ ] a bit of a freeze when fetching `mbostock/d3`
|
- [ ] a bit of a freeze when fetching `mbostock/d3`
|
||||||
- [ ] Validate repo input and show a loading sign of sorts
|
|
||||||
- [ ] Check that we have not run out of requests to make
|
###Docs
|
||||||
- [ ] Show loading sign on top of [browser window](https://github.com/buunguyen/topbar) which is unobtrusive enough we can show it immediately.
|
|
||||||
|
- [ ] landing page for the project and put message on my repo
|
||||||
|
- [ ] provide a documentation site
|
||||||
|
|
||||||
|
###Routing
|
||||||
|
|
||||||
|
- [ ] Handle [404](https://www.firebase.com/docs/hosting/guide/url-redirects-rewrites.html#section-404) on routes; from catch all check if '/' or go 404 controller
|
||||||
|
- [ ] allow `pushState` when [Firebase hosted](https://www.firebase.com/docs/hosting/guide/url-redirects-rewrites.html#section-rewrites)
|
||||||
|
|
||||||
|
###Style
|
||||||
|
|
||||||
|
- [ ] focus on form fields style
|
||||||
|
- [ ] switch off user select on buttons
|
||||||
|
|
||||||
|
###Misc
|
||||||
|
|
||||||
|
- [ ] show hero box or projects with a fade in and only when known
|
||||||
|
- [ ] calculate left margin based on the total number of points text width
|
||||||
- [ ] show a countdown clock towards the end of the milestone or show overdue
|
- [ ] show a countdown clock towards the end of the milestone or show overdue
|
||||||
- [ ] highlight for a moment recently changed milestone
|
|
||||||
- [ ] smooth animation when transitioning between icons and notifications
|
|
||||||
- [ ] show logged-in state only after it is known
|
|
||||||
- [ ] trigger success topbar when we have completed a milestone on chart page; show plain when we are behind
|
- [ ] trigger success topbar when we have completed a milestone on chart page; show plain when we are behind
|
||||||
- [ ] on chart page show a little progress bar in the title
|
- [ ] on chart page show a little progress bar in the title
|
||||||
- [ ] use tap plugin for Ractive
|
- [ ] use tap plugin for Ractive
|
||||||
- [x] logged-in state fade into view independent of page loading
|
|
||||||
- [x] upgrade to Ractive [0.6.0](https://github.com/ractivejs/ractive/blob/dev/CHANGELOG.md)
|
|
||||||
|
|
||||||
##Future Releases
|
##Future Releases
|
||||||
|
|
||||||
|
- [ ] smooth animation when transitioning between icons and notifications
|
||||||
- [ ] show animated lines when drawing the chart
|
- [ ] show animated lines when drawing the chart
|
||||||
- [ ] highlight changes from past fetch
|
- [ ] highlight changes from past fetch
|
||||||
- [ ] In add a project form autocomplete on my username, orgs I am member of and repos I have access to
|
- [ ] In add a project form autocomplete on my username, orgs I am member of and repos I have access to
|
||||||
|
|
|
@ -41004,7 +41004,7 @@ Router.prototype.mount = function(routes, path) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
add: function(repo, add) {
|
add: function(repo, done) {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
return request.allMilestones(repo, function(err, res) {
|
return request.allMilestones(repo, function(err, res) {
|
||||||
var milestones;
|
var milestones;
|
||||||
|
@ -41772,7 +41772,7 @@ Router.prototype.mount = function(routes, path) {
|
||||||
// new.mustache
|
// new.mustache
|
||||||
root.require.register('burnchart/src/templates/pages/new.js', function(exports, require, module) {
|
root.require.register('burnchart/src/templates/pages/new.js', function(exports, require, module) {
|
||||||
|
|
||||||
module.exports = ["<div id=\"content\" class=\"wrap\">"," <div id=\"add\">"," <div class=\"header\">"," <h2>Add a Project</h2>"," <p>Type in the name of the repository as you would normally. If you'd like to add a private GitHub project, <a href=\"#\">Sign In</a> first.</p>"," </div>",""," <div class=\"form\">"," <table>"," <tr>"," <td>"," <input type=\"text\" placeholder=\"user/repo\" autocomplete=\"off\" value=\"{{value}}\">"," </td>"," <td>"," <a on-click=\"submit\">Add</a>"," </td>"," </tr>"," </table>"," </div>"," </div>","</div>"].join("\n");
|
module.exports = ["<div id=\"content\" class=\"wrap\">"," <div id=\"add\">"," <div class=\"header\">"," <h2>Add a Project</h2>"," <p>Type in the name of the repository as you would normally. If you'd like to add a private GitHub project, <a href=\"#\">Sign In</a> first.</p>"," </div>",""," <div class=\"form\">"," <table>"," <tr>"," <td>"," <input type=\"text\" placeholder=\"user/repo\" autocomplete=\"off\" value=\"{{value}}\" on-keyup=\"submit:{{value}}\">"," </td>"," <td>"," <a on-click=\"submit:{{value}}\">Add</a>"," </td>"," </tr>"," </table>"," </div>"," </div>","</div>"].join("\n");
|
||||||
});
|
});
|
||||||
|
|
||||||
// project.mustache
|
// project.mustache
|
||||||
|
@ -41849,6 +41849,21 @@ Router.prototype.mount = function(routes, path) {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// key.coffee
|
||||||
|
root.require.register('burnchart/src/utils/key.js', function(exports, require, module) {
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
is: function(evt) {
|
||||||
|
var _ref;
|
||||||
|
return (_ref = evt.original.type) === 'keyup' || _ref === 'keydown';
|
||||||
|
},
|
||||||
|
isEnter: function(evt) {
|
||||||
|
return evt.original.which === 13;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
// mixins.coffee
|
// mixins.coffee
|
||||||
root.require.register('burnchart/src/utils/mixins.js', function(exports, require, module) {
|
root.require.register('burnchart/src/utils/mixins.js', function(exports, require, module) {
|
||||||
|
|
||||||
|
@ -42158,12 +42173,16 @@ Router.prototype.mount = function(routes, path) {
|
||||||
// new.coffee
|
// new.coffee
|
||||||
root.require.register('burnchart/src/views/pages/new.js', function(exports, require, module) {
|
root.require.register('burnchart/src/views/pages/new.js', function(exports, require, module) {
|
||||||
|
|
||||||
var mediator, user;
|
var key, mediator, system, user;
|
||||||
|
|
||||||
mediator = require('../../modules/mediator');
|
mediator = require('../../modules/mediator');
|
||||||
|
|
||||||
|
system = require('../../models/system');
|
||||||
|
|
||||||
user = require('../../models/user');
|
user = require('../../models/user');
|
||||||
|
|
||||||
|
key = require('../../utils/key');
|
||||||
|
|
||||||
module.exports = Ractive.extend({
|
module.exports = Ractive.extend({
|
||||||
'template': require('../../templates/pages/new'),
|
'template': require('../../templates/pages/new'),
|
||||||
'data': {
|
'data': {
|
||||||
|
@ -42171,6 +42190,25 @@ Router.prototype.mount = function(routes, path) {
|
||||||
user: user
|
user: user
|
||||||
},
|
},
|
||||||
'adapt': [Ractive.adaptors.Ractive],
|
'adapt': [Ractive.adaptors.Ractive],
|
||||||
|
submit: function(evt, value) {
|
||||||
|
var done, name, owner, _ref;
|
||||||
|
if (key.is(evt) && !key.isEnter(evt)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_ref = value.split('/'), owner = _ref[0], name = _ref[1];
|
||||||
|
done = system.async();
|
||||||
|
return mediator.fire('!projects/add', {
|
||||||
|
owner: owner,
|
||||||
|
name: name
|
||||||
|
}, function(err) {
|
||||||
|
done();
|
||||||
|
mediator.fire('!app/notify', {
|
||||||
|
'text': err || ("Project " + value + " saved."),
|
||||||
|
'type': err ? 'error' : 'success'
|
||||||
|
});
|
||||||
|
return window.location.hash = '#';
|
||||||
|
});
|
||||||
|
},
|
||||||
onrender: function() {
|
onrender: function() {
|
||||||
var autocomplete;
|
var autocomplete;
|
||||||
document.title = 'Add a new project';
|
document.title = 'Add a new project';
|
||||||
|
@ -42178,16 +42216,8 @@ Router.prototype.mount = function(routes, path) {
|
||||||
this.observe('value', _.debounce(autocomplete, 200), {
|
this.observe('value', _.debounce(autocomplete, 200), {
|
||||||
'init': false
|
'init': false
|
||||||
});
|
});
|
||||||
return this.on('submit', function() {
|
this.el.querySelector('input').focus();
|
||||||
var name, owner, _ref;
|
return this.on('submit', this.submit);
|
||||||
_ref = this.get('value').split('/'), owner = _ref[0], name = _ref[1];
|
|
||||||
return mediator.fire('!projects/add', {
|
|
||||||
owner: owner,
|
|
||||||
name: name
|
|
||||||
}, function() {
|
|
||||||
return window.location.hash = '#';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
add: function(repo, add) {
|
add: function(repo, done) {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
return request.allMilestones(repo, function(err, res) {
|
return request.allMilestones(repo, function(err, res) {
|
||||||
var milestones;
|
var milestones;
|
||||||
|
@ -863,7 +863,7 @@
|
||||||
// new.mustache
|
// new.mustache
|
||||||
root.require.register('burnchart/src/templates/pages/new.js', function(exports, require, module) {
|
root.require.register('burnchart/src/templates/pages/new.js', function(exports, require, module) {
|
||||||
|
|
||||||
module.exports = ["<div id=\"content\" class=\"wrap\">"," <div id=\"add\">"," <div class=\"header\">"," <h2>Add a Project</h2>"," <p>Type in the name of the repository as you would normally. If you'd like to add a private GitHub project, <a href=\"#\">Sign In</a> first.</p>"," </div>",""," <div class=\"form\">"," <table>"," <tr>"," <td>"," <input type=\"text\" placeholder=\"user/repo\" autocomplete=\"off\" value=\"{{value}}\">"," </td>"," <td>"," <a on-click=\"submit\">Add</a>"," </td>"," </tr>"," </table>"," </div>"," </div>","</div>"].join("\n");
|
module.exports = ["<div id=\"content\" class=\"wrap\">"," <div id=\"add\">"," <div class=\"header\">"," <h2>Add a Project</h2>"," <p>Type in the name of the repository as you would normally. If you'd like to add a private GitHub project, <a href=\"#\">Sign In</a> first.</p>"," </div>",""," <div class=\"form\">"," <table>"," <tr>"," <td>"," <input type=\"text\" placeholder=\"user/repo\" autocomplete=\"off\" value=\"{{value}}\" on-keyup=\"submit:{{value}}\">"," </td>"," <td>"," <a on-click=\"submit:{{value}}\">Add</a>"," </td>"," </tr>"," </table>"," </div>"," </div>","</div>"].join("\n");
|
||||||
});
|
});
|
||||||
|
|
||||||
// project.mustache
|
// project.mustache
|
||||||
|
@ -940,6 +940,21 @@
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// key.coffee
|
||||||
|
root.require.register('burnchart/src/utils/key.js', function(exports, require, module) {
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
is: function(evt) {
|
||||||
|
var _ref;
|
||||||
|
return (_ref = evt.original.type) === 'keyup' || _ref === 'keydown';
|
||||||
|
},
|
||||||
|
isEnter: function(evt) {
|
||||||
|
return evt.original.which === 13;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
// mixins.coffee
|
// mixins.coffee
|
||||||
root.require.register('burnchart/src/utils/mixins.js', function(exports, require, module) {
|
root.require.register('burnchart/src/utils/mixins.js', function(exports, require, module) {
|
||||||
|
|
||||||
|
@ -1249,12 +1264,16 @@
|
||||||
// new.coffee
|
// new.coffee
|
||||||
root.require.register('burnchart/src/views/pages/new.js', function(exports, require, module) {
|
root.require.register('burnchart/src/views/pages/new.js', function(exports, require, module) {
|
||||||
|
|
||||||
var mediator, user;
|
var key, mediator, system, user;
|
||||||
|
|
||||||
mediator = require('../../modules/mediator');
|
mediator = require('../../modules/mediator');
|
||||||
|
|
||||||
|
system = require('../../models/system');
|
||||||
|
|
||||||
user = require('../../models/user');
|
user = require('../../models/user');
|
||||||
|
|
||||||
|
key = require('../../utils/key');
|
||||||
|
|
||||||
module.exports = Ractive.extend({
|
module.exports = Ractive.extend({
|
||||||
'template': require('../../templates/pages/new'),
|
'template': require('../../templates/pages/new'),
|
||||||
'data': {
|
'data': {
|
||||||
|
@ -1262,6 +1281,25 @@
|
||||||
user: user
|
user: user
|
||||||
},
|
},
|
||||||
'adapt': [Ractive.adaptors.Ractive],
|
'adapt': [Ractive.adaptors.Ractive],
|
||||||
|
submit: function(evt, value) {
|
||||||
|
var done, name, owner, _ref;
|
||||||
|
if (key.is(evt) && !key.isEnter(evt)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_ref = value.split('/'), owner = _ref[0], name = _ref[1];
|
||||||
|
done = system.async();
|
||||||
|
return mediator.fire('!projects/add', {
|
||||||
|
owner: owner,
|
||||||
|
name: name
|
||||||
|
}, function(err) {
|
||||||
|
done();
|
||||||
|
mediator.fire('!app/notify', {
|
||||||
|
'text': err || ("Project " + value + " saved."),
|
||||||
|
'type': err ? 'error' : 'success'
|
||||||
|
});
|
||||||
|
return window.location.hash = '#';
|
||||||
|
});
|
||||||
|
},
|
||||||
onrender: function() {
|
onrender: function() {
|
||||||
var autocomplete;
|
var autocomplete;
|
||||||
document.title = 'Add a new project';
|
document.title = 'Add a new project';
|
||||||
|
@ -1269,16 +1307,8 @@
|
||||||
this.observe('value', _.debounce(autocomplete, 200), {
|
this.observe('value', _.debounce(autocomplete, 200), {
|
||||||
'init': false
|
'init': false
|
||||||
});
|
});
|
||||||
return this.on('submit', function() {
|
this.el.querySelector('input').focus();
|
||||||
var name, owner, _ref;
|
return this.on('submit', this.submit);
|
||||||
_ref = this.get('value').split('/'), owner = _ref[0], name = _ref[1];
|
|
||||||
return mediator.fire('!projects/add', {
|
|
||||||
owner: owner,
|
|
||||||
name: name
|
|
||||||
}, function() {
|
|
||||||
return window.location.hash = '#';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ module.exports = new Model
|
||||||
, (err) ->
|
, (err) ->
|
||||||
throw err if err
|
throw err if err
|
||||||
|
|
||||||
add: (repo, add) ->
|
add: (repo, done) ->
|
||||||
# TODO: warn when we are adding an existing repo (or
|
# TODO: warn when we are adding an existing repo (or
|
||||||
# silently go to index again).
|
# silently go to index again).
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,10 @@
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" placeholder="user/repo" autocomplete="off" value="{{value}}">
|
<input type="text" placeholder="user/repo" autocomplete="off" value="{{value}}" on-keyup="submit:{{value}}">
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a on-click="submit">Add</a>
|
<a on-click="submit:{{value}}">Add</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -12,15 +12,14 @@ module.exports = Ractive.extend
|
||||||
'hidden': yes
|
'hidden': yes
|
||||||
'defaults':
|
'defaults':
|
||||||
'text': ''
|
'text': ''
|
||||||
'type': ''
|
'type': '' # bland grey style
|
||||||
'system': no
|
'system': no
|
||||||
'icon': 'megaphone'
|
'icon': 'megaphone'
|
||||||
'ttl': 5e3
|
'ttl': 5e3
|
||||||
|
|
||||||
# Show a notification.
|
# Show a notification.
|
||||||
show: (opts) ->
|
show: (opts) ->
|
||||||
@set 'hidden', no
|
@set 'hidden', no
|
||||||
|
|
||||||
# Set the opts.
|
# Set the opts.
|
||||||
@set opts = _.defaults opts, @data.defaults
|
@set opts = _.defaults opts, @data.defaults
|
||||||
# Which position to slide to?
|
# Which position to slide to?
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
mediator = require '../../modules/mediator'
|
mediator = require '../../modules/mediator'
|
||||||
|
system = require '../../models/system'
|
||||||
user = require '../../models/user'
|
user = require '../../models/user'
|
||||||
|
key = require '../../utils/key'
|
||||||
|
|
||||||
module.exports = Ractive.extend
|
module.exports = Ractive.extend
|
||||||
|
|
||||||
|
@ -9,6 +11,26 @@ module.exports = Ractive.extend
|
||||||
|
|
||||||
'adapt': [ Ractive.adaptors.Ractive ]
|
'adapt': [ Ractive.adaptors.Ractive ]
|
||||||
|
|
||||||
|
# Listen to Enter keypress or Submit button click.
|
||||||
|
submit: (evt, value) ->
|
||||||
|
return if key.is(evt) and not key.isEnter(evt)
|
||||||
|
|
||||||
|
[ owner, name ] = value.split('/')
|
||||||
|
|
||||||
|
done = do system.async
|
||||||
|
|
||||||
|
# Save repo.
|
||||||
|
mediator.fire '!projects/add', { owner, name }, (err) ->
|
||||||
|
do done
|
||||||
|
|
||||||
|
mediator.fire '!app/notify',
|
||||||
|
'text': err or "Project #{value} saved."
|
||||||
|
'type': if err then 'error' else 'success'
|
||||||
|
|
||||||
|
# Redirect to the dashboard.
|
||||||
|
# TODO: trigger a named route
|
||||||
|
window.location.hash = '#'
|
||||||
|
|
||||||
onrender: ->
|
onrender: ->
|
||||||
document.title = 'Add a new project'
|
document.title = 'Add a new project'
|
||||||
|
|
||||||
|
@ -18,14 +40,7 @@ module.exports = Ractive.extend
|
||||||
|
|
||||||
@observe 'value', _.debounce(autocomplete, 200), { 'init': no }
|
@observe 'value', _.debounce(autocomplete, 200), { 'init': no }
|
||||||
|
|
||||||
# TODO: focus on the input field
|
# Focus on the input field.
|
||||||
|
do @el.querySelector('input').focus
|
||||||
|
|
||||||
# TODO: listen to Enter keypress.
|
@on 'submit', @submit
|
||||||
@on 'submit', ->
|
|
||||||
[ owner, name ] = @get('value').split('/')
|
|
||||||
|
|
||||||
# TODO: save repo & persist.
|
|
||||||
mediator.fire '!projects/add', { owner, name }, ->
|
|
||||||
# Redirect to the dashboard.
|
|
||||||
# TODO: trigger a named route
|
|
||||||
window.location.hash = '#'
|
|
Loading…
Reference in New Issue