add user stores/actions
construct fetchr on every request
This commit is contained in:
@ -1,8 +1,9 @@
|
|||||||
import Rx from 'rx';
|
import Rx from 'rx';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import Fetchr from 'fetchr';
|
||||||
|
import debugFactory from 'debug';
|
||||||
import { Router } from 'react-router';
|
import { Router } from 'react-router';
|
||||||
import { history } from 'react-router/lib/BrowserHistory';
|
import { history } from 'react-router/lib/BrowserHistory';
|
||||||
import debugFactory from 'debug';
|
|
||||||
import { hydrate } from 'thundercats';
|
import { hydrate } from 'thundercats';
|
||||||
import { Render } from 'thundercats-react';
|
import { Render } from 'thundercats-react';
|
||||||
|
|
||||||
@ -11,6 +12,9 @@ import { app$ } from '../common/app';
|
|||||||
const debug = debugFactory('fcc:client');
|
const debug = debugFactory('fcc:client');
|
||||||
const DOMContianer = document.getElementById('fcc');
|
const DOMContianer = document.getElementById('fcc');
|
||||||
const catState = window.__fcc__.data || {};
|
const catState = window.__fcc__.data || {};
|
||||||
|
const services = new Fetchr({
|
||||||
|
xhrPath: '/services'
|
||||||
|
});
|
||||||
|
|
||||||
Rx.longStackSupport = !!debug.enabled;
|
Rx.longStackSupport = !!debug.enabled;
|
||||||
|
|
||||||
@ -18,7 +22,7 @@ Rx.longStackSupport = !!debug.enabled;
|
|||||||
app$(history)
|
app$(history)
|
||||||
.flatMap(
|
.flatMap(
|
||||||
({ AppCat }) => {
|
({ AppCat }) => {
|
||||||
const appCat = AppCat();
|
const appCat = AppCat(null, services);
|
||||||
return hydrate(appCat, catState)
|
return hydrate(appCat, catState)
|
||||||
.map(() => appCat);
|
.map(() => appCat);
|
||||||
},
|
},
|
||||||
|
@ -1,28 +1,37 @@
|
|||||||
import React, { PropTypes } from 'react';
|
import React, { PropTypes } from 'react';
|
||||||
|
import { contain } from 'thundercats-react';
|
||||||
import { Row } from 'react-bootstrap';
|
import { Row } from 'react-bootstrap';
|
||||||
|
|
||||||
import { Nav } from './components/Nav';
|
import { Nav } from './components/Nav';
|
||||||
import { Footer } from './components/Footer';
|
import { Footer } from './components/Footer';
|
||||||
|
|
||||||
export default class extends React.Component {
|
export default contain(
|
||||||
constructor(props) {
|
{
|
||||||
super(props);
|
store: 'appStore',
|
||||||
}
|
fetchAction: 'appActions.getUser',
|
||||||
|
getPayload(props) {
|
||||||
|
return {
|
||||||
|
isPrimed: !!props.username
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
React.createClass({
|
||||||
|
displayName: 'FreeCodeCamp',
|
||||||
|
|
||||||
static displayName = 'FreeCodeCamp'
|
propTypes: {
|
||||||
static propTypes = {
|
children: PropTypes.node
|
||||||
children: PropTypes.node
|
},
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Nav />
|
<Nav />
|
||||||
<Row>
|
<Row>
|
||||||
{ this.props.children }
|
{ this.props.children }
|
||||||
</Row>
|
</Row>
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
);
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import { Cat } from 'thundercats';
|
import { Cat } from 'thundercats';
|
||||||
import { HikesActions, HikesStore } from './routes/Hikes/flux';
|
import { HikesActions, HikesStore } from './routes/Hikes/flux';
|
||||||
|
import { AppActions, AppStore } from './flux';
|
||||||
|
|
||||||
export default Cat()
|
export default Cat()
|
||||||
.init(({ instance }) => {
|
.init(({ instance: cat, args: [services] }) => {
|
||||||
instance.register(HikesActions);
|
cat.register(AppActions, null, services);
|
||||||
instance.register(HikesStore, null, instance);
|
cat.register(AppStore, null, cat);
|
||||||
|
cat.register(HikesActions, null, services);
|
||||||
|
cat.register(HikesStore, null, cat);
|
||||||
});
|
});
|
||||||
|
31
common/app/flux/Actions.js
Normal file
31
common/app/flux/Actions.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { Actions } from 'thundercats';
|
||||||
|
import debugFactory from 'debug';
|
||||||
|
|
||||||
|
const debug = debugFactory('freecc:app:actions');
|
||||||
|
|
||||||
|
export default Actions({
|
||||||
|
setUser({ username, picture, progressTimestamps = [] }) {
|
||||||
|
return {
|
||||||
|
username,
|
||||||
|
picture,
|
||||||
|
points: progressTimestamps.length
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getUser: null
|
||||||
|
})
|
||||||
|
.refs({ displayName: 'AppActions' })
|
||||||
|
.init(({ instance: appActions, args: [services] }) => {
|
||||||
|
appActions.getUser.subscribe(({ isPrimed }) => {
|
||||||
|
if (isPrimed) {
|
||||||
|
debug('isPrimed');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
services.read('user', null, null, (err, user) => {
|
||||||
|
if (err) {
|
||||||
|
return debug('user service error');
|
||||||
|
}
|
||||||
|
debug('user service returned successful');
|
||||||
|
return appActions.setUser(user);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
18
common/app/flux/Store.js
Normal file
18
common/app/flux/Store.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { Store } from 'thundercats';
|
||||||
|
|
||||||
|
const { createRegistrar, setter } = Store;
|
||||||
|
const initValue = {
|
||||||
|
username: null,
|
||||||
|
picture: null,
|
||||||
|
points: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Store(initValue)
|
||||||
|
.refs({ displayName: 'AppStore' })
|
||||||
|
.init(({ instance: appStore, args: [cat] }) => {
|
||||||
|
const { setUser } = cat.getActions('appActions');
|
||||||
|
const register = createRegistrar(appStore);
|
||||||
|
register(setter(setUser));
|
||||||
|
|
||||||
|
return appStore;
|
||||||
|
});
|
2
common/app/flux/index.js
Normal file
2
common/app/flux/index.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export AppActions from './Actions';
|
||||||
|
export AppStore from './Store';
|
@ -1,12 +1,8 @@
|
|||||||
import { Actions } from 'thundercats';
|
import { Actions } from 'thundercats';
|
||||||
import assign from 'object.assign';
|
import assign from 'object.assign';
|
||||||
import debugFactory from 'debug';
|
import debugFactory from 'debug';
|
||||||
import Fetchr from 'fetchr';
|
|
||||||
|
|
||||||
const debug = debugFactory('freecc:hikes:actions');
|
const debug = debugFactory('freecc:hikes:actions');
|
||||||
const service = new Fetchr({
|
|
||||||
xhrPath: '/services'
|
|
||||||
});
|
|
||||||
|
|
||||||
function getCurrentHike(hikes =[{}], dashedName, currentHike) {
|
function getCurrentHike(hikes =[{}], dashedName, currentHike) {
|
||||||
if (!dashedName) {
|
if (!dashedName) {
|
||||||
@ -36,7 +32,7 @@ export default Actions({
|
|||||||
setHikes: null
|
setHikes: null
|
||||||
})
|
})
|
||||||
.refs({ displayName: 'HikesActions' })
|
.refs({ displayName: 'HikesActions' })
|
||||||
.init(({ instance }) => {
|
.init(({ instance, args: [services] }) => {
|
||||||
// set up hikes fetching
|
// set up hikes fetching
|
||||||
instance.fetchHikes.subscribe(
|
instance.fetchHikes.subscribe(
|
||||||
({ isPrimed, dashedName }) => {
|
({ isPrimed, dashedName }) => {
|
||||||
@ -53,7 +49,7 @@ export default Actions({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
service.read('hikes', null, null, (err, hikes) => {
|
services.read('hikes', null, null, (err, hikes) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
debug('an error occurred fetching hikes', err);
|
debug('an error occurred fetching hikes', err);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Router from 'react-router';
|
import Router from 'react-router';
|
||||||
|
import Fetchr from 'fetchr';
|
||||||
import Location from 'react-router/lib/Location';
|
import Location from 'react-router/lib/Location';
|
||||||
import debugFactory from 'debug';
|
import debugFactory from 'debug';
|
||||||
import { app$ } from '../../common/app';
|
import { app$ } from '../../common/app';
|
||||||
import { RenderToString } from 'thundercats-react';
|
import { RenderToString } from 'thundercats-react';
|
||||||
|
|
||||||
const debug = debugFactory('freecc:servereact');
|
const debug = debugFactory('freecc:react-server');
|
||||||
|
|
||||||
// add routes here as they slowly get reactified
|
// add routes here as they slowly get reactified
|
||||||
// remove their individual controllers
|
// remove their individual controllers
|
||||||
@ -25,6 +26,7 @@ export default function reactSubRouter(app) {
|
|||||||
app.use(router);
|
app.use(router);
|
||||||
|
|
||||||
function serveReactApp(req, res, next) {
|
function serveReactApp(req, res, next) {
|
||||||
|
const services = new Fetchr({ req });
|
||||||
const location = new Location(req.path, req.query);
|
const location = new Location(req.path, req.query);
|
||||||
|
|
||||||
// returns a router wrapped app
|
// returns a router wrapped app
|
||||||
@ -42,7 +44,7 @@ export default function reactSubRouter(app) {
|
|||||||
// prefetches data and sets up it up for current state
|
// prefetches data and sets up it up for current state
|
||||||
debug('rendering to string');
|
debug('rendering to string');
|
||||||
return RenderToString(
|
return RenderToString(
|
||||||
AppCat(),
|
AppCat(null, services),
|
||||||
React.createElement(Router, initialState)
|
React.createElement(Router, initialState)
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
import Fetchr from 'fetchr';
|
import Fetchr from 'fetchr';
|
||||||
import getHikesService from '../services/hikes';
|
import getHikesService from '../services/hikes';
|
||||||
|
import getUserServices from '../services/user';
|
||||||
|
|
||||||
export default function bootServices(app) {
|
export default function bootServices(app) {
|
||||||
const hikesService = getHikesService(app);
|
const hikesService = getHikesService(app);
|
||||||
|
const userServices = getUserServices(app);
|
||||||
Fetchr.registerFetcher(hikesService);
|
Fetchr.registerFetcher(hikesService);
|
||||||
|
Fetchr.registerFetcher(userServices);
|
||||||
app.use('/services', Fetchr.middleware());
|
app.use('/services', Fetchr.middleware());
|
||||||
}
|
}
|
||||||
|
30
server/services/user.js
Normal file
30
server/services/user.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import debugFactory from 'debug';
|
||||||
|
import assign from 'object.assign';
|
||||||
|
|
||||||
|
const censor = '**********************:P********';
|
||||||
|
const debug = debugFactory('freecc:services:user');
|
||||||
|
const protectedUserFields = {
|
||||||
|
id: censor,
|
||||||
|
password: censor,
|
||||||
|
profiles: censor
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function userServices(/* app */) {
|
||||||
|
return {
|
||||||
|
name: 'user',
|
||||||
|
read: (req, resource, params, config, cb) => {
|
||||||
|
let { user } = req;
|
||||||
|
if (user) {
|
||||||
|
debug('user is signed in');
|
||||||
|
// Zalgo!!!
|
||||||
|
return process.nextTick(() => {
|
||||||
|
cb(null, assign({}, user.toJSON(), protectedUserFields));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
debug('user is not signed in');
|
||||||
|
return process.nextTick(() => {
|
||||||
|
cb(null, {});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
Reference in New Issue
Block a user