#122 switch to google firebase

This commit is contained in:
Radek Stepan 2016-09-30 20:19:39 -04:00
parent c3896a3598
commit f5c5d33f77
12 changed files with 634 additions and 597 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "burnchart", "name": "burnchart",
"version": "3.2.2", "version": "3.2.3",
"description": "GitHub Burndown Chart as a Service", "description": "GitHub Burndown Chart as a Service",
"author": "Radek Stepan <dev@radekstepan.com> (http://radekstepan.com)", "author": "Radek Stepan <dev@radekstepan.com> (http://radekstepan.com)",
"license": "AGPL-3.0", "license": "AGPL-3.0",
@ -31,7 +31,7 @@
"d3": "^3.5.12", "d3": "^3.5.12",
"d3-tip": "^0.6.7", "d3-tip": "^0.6.7",
"deep-diff": "^0.3.3", "deep-diff": "^0.3.3",
"firebase": "^2.3.2", "firebase": "^3.4.1",
"less": "^2.5.3", "less": "^2.5.3",
"lesshat": "^3.0.2", "lesshat": "^3.0.2",
"lodash": "^3.10.1", "lodash": "^3.10.1",

View File

@ -991,13 +991,20 @@ ul li {
-moz-box-shadow: inset 0 1px 2px rgba(221, 225, 237, 0.2); -moz-box-shadow: inset 0 1px 2px rgba(221, 225, 237, 0.2);
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; border-top: 1px solid #dde1ed;
text-align: right;
font-family: 'MuseoSlab500Regular', serif; font-family: 'MuseoSlab500Regular', serif;
font-size: 14px; font-size: 14px;
} }
#page #content #projects .footer .icon { #page #content #projects .footer .icon {
color: #aaafbf; color: #aaafbf;
} }
#page #content #projects .footer > a:first-child {
float: right;
}
#page #content #projects .footer:after {
clear: both;
display: block;
content: "";
}
#page #content .protip { #page #content .protip {
border: 1px solid #EFEFEF; border: 1px solid #EFEFEF;
-webkit-border-radius: 2px; -webkit-border-radius: 2px;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,12 @@
export default { export default {
// Firebase app name. // Firebase.
"firebase": "burnchart", "firebase": {
apiKey: "AIzaSyD_kfzkAPA87PoRFIZa8JEzZkT66CqUDpU",
authDomain: "burnchart.firebaseapp.com",
databaseURL: "https://burnchart.firebaseio.com",
storageBucket: "firebase-burnchart.appspot.com",
messagingSenderId: "185222099419"
},
// Data source provider. // Data source provider.
"provider": "github", "provider": "github",
// Fields to keep from GH responses. // Fields to keep from GH responses.

View File

@ -35,7 +35,7 @@ export default class Header extends React.Component {
// Sign-in/out. // Sign-in/out.
let user; let user;
if (props.user != null && 'uid' in props.user) { if (props.user && props.user.github) {
user = ( user = (
<div className="right"> <div className="right">
<a onClick={this._onSignOut}> <a onClick={this._onSignOut}>

View File

@ -22,6 +22,10 @@ export default class Milestones extends React.Component {
actions.emit('projects.sort'); actions.emit('projects.sort');
} }
_onRefresh() {
actions.emit('projects.load');
}
render() { render() {
let { projects, project } = this.props; let { projects, project } = this.props;
@ -117,6 +121,7 @@ export default class Milestones extends React.Component {
</table> </table>
<div className="footer"> <div className="footer">
<a onClick={this.props.onToggleMode}>Edit Projects</a> <a onClick={this.props.onToggleMode}>Edit Projects</a>
<a onClick={this._onRefresh}>Refresh Projects</a>
</div> </div>
</div> </div>
); );

View File

@ -29,7 +29,7 @@ export default {
// Get a repo. // Get a repo.
repo: (user, { owner, name }, cb) => { repo: (user, { owner, name }, cb) => {
let token = (user && user.github != null) ? user.github.accessToken : null; let token = (user && user.credential != null) ? user.credential.accessToken : null;
let data = _.defaults({ let data = _.defaults({
'path': `/repos/${owner}/${name}`, 'path': `/repos/${owner}/${name}`,
'headers': headers(token) 'headers': headers(token)
@ -46,7 +46,7 @@ export default {
var [ cb ] = args; var [ cb ] = args;
} }
let token = (user && user.github != null) ? user.github.accessToken : null; let token = (user && user.credential != null) ? user.credential.accessToken : null;
let data = _.defaults({ let data = _.defaults({
'path': owner ? `/users/${owner}/repos` : '/user/repos', 'path': owner ? `/users/${owner}/repos` : '/user/repos',
'headers': headers(token) 'headers': headers(token)
@ -57,7 +57,7 @@ export default {
// Get all open milestones. // Get all open milestones.
allMilestones: (user, { owner, name }, cb) => { allMilestones: (user, { owner, name }, cb) => {
let token = (user && user.github != null) ? user.github.accessToken : null; let token = (user && user.credential != null) ? user.credential.accessToken : null;
let data = _.defaults({ let data = _.defaults({
'path': `/repos/${owner}/${name}/milestones`, 'path': `/repos/${owner}/${name}/milestones`,
'query': { 'state': 'open', 'sort': 'due_date', 'direction': 'asc' }, 'query': { 'state': 'open', 'sort': 'due_date', 'direction': 'asc' },
@ -69,7 +69,7 @@ export default {
// Get one open milestone. // Get one open milestone.
oneMilestone: (user, { owner, name, milestone }, cb) => { oneMilestone: (user, { owner, name, milestone }, cb) => {
let token = (user && user.github != null) ? user.github.accessToken : null; let token = (user && user.credential != null) ? user.credential.accessToken : null;
let data = _.defaults({ let data = _.defaults({
'path': `/repos/${owner}/${name}/milestones/${milestone}`, 'path': `/repos/${owner}/${name}/milestones/${milestone}`,
'query': { 'state': 'open', 'sort': 'due_date', 'direction': 'asc' }, 'query': { 'state': 'open', 'sort': 'due_date', 'direction': 'asc' },
@ -81,7 +81,7 @@ export default {
// Get all issues for a state.. // Get all issues for a state..
allIssues: (user, { owner, name, milestone }, query, cb) => { allIssues: (user, { owner, name, milestone }, query, cb) => {
let token = (user && user.github != null) ? user.github.accessToken : null; let token = (user && user.credential != null) ? user.credential.accessToken : null;
let data = _.defaults({ let data = _.defaults({
'path': `/repos/${owner}/${name}/issues`, 'path': `/repos/${owner}/${name}/issues`,
'query': _.extend(query, { milestone, 'per_page': '100' }), 'query': _.extend(query, { milestone, 'per_page': '100' }),

View File

@ -1,5 +1,6 @@
import _ from 'lodash'; import _ from 'lodash';
import Firebase from 'firebase'; import firebase from 'firebase/app';
import 'firebase/auth';
import Store from '../lib/Store.js'; import Store from '../lib/Store.js';
@ -28,32 +29,36 @@ class AppStore extends Store {
(fn in this) && this[fn](obj); (fn in this) && this[fn](obj);
}); });
client = new Firebase(`https://${config.firebase}.firebaseio.com`); // Initialize Firebase
client = firebase.initializeApp(config.firebase);
// When user is already authenticated. actions.emit('user.ready', {});
client.onAuth((data={}) => actions.emit('user.ready', data));
} }
onUserSignin() { onUserSignin() {
client.authWithOAuthPopup("github", (err, data) => { const provider = new firebase.auth.GithubAuthProvider();
if (!err) return actions.emit('firebase.auth', data); // See https://developer.github.com/v3/oauth/#scopes
provider.addScope('repo');
client.auth().signInWithPopup(provider).then((res) => {
actions.emit('user.ready', {
'github': res.user.providerData[0],
'credential': res.credential,
});
}).catch((err) => {
// Handle Errors here.
actions.emit('system.notify', { actions.emit('system.notify', {
'text': err.toString(), 'text': 'message' in err ? err.message : err.toString(),
'type': 'alert', 'type': 'alert',
'system': true 'system': true
}); });
}, {
'rememberMe': true,
// See https://developer.github.com/v3/oauth/#scopes
'scope': 'repo'
}); });
} }
// Sign-out a user. // Sign-out a user.
onUserSignout() { onUserSignout() {
this.set('user', {}); actions.emit('user.ready', {}); // projectsStore references user
client.unauth(); client.auth().signOut();
} }
// Called by Firebase. // Called by Firebase.

View File

@ -64,6 +64,9 @@ class ProjectsStore extends Store {
onProjectsLoad(args) { onProjectsLoad(args) {
let projects = this.get('list'); let projects = this.get('list');
// Reset first.
projects = _.each(projects, (p) => delete p.errors);
// Wait for the user to get resolved. // Wait for the user to get resolved.
this.get('user', this.cb((user) => { // async this.get('user', this.cb((user) => { // async
if (args) { if (args) {

View File

@ -490,13 +490,22 @@ ul {
color: #aaafbf; color: #aaafbf;
.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; border-top: 1px solid #dde1ed;
text-align: right;
font-family: @serif_font; font-family: @serif_font;
font-size: 14px; font-size: 14px;
.icon { .icon {
color: #aaafbf; color: #aaafbf;
} }
> a:first-child {
float: right;
}
&:after {
clear: both;
display: block;
content: "";
}
} }
} }