Make structure changes to hikes

This commit is contained in:
Berkeley Martinez
2015-12-22 19:33:25 -08:00
parent 65b6715f68
commit 22cb610279
11 changed files with 154 additions and 116 deletions

View File

@ -4,11 +4,21 @@ import debugFactory from 'debug';
const debug = debugFactory('freecc:app:actions');
export default Actions({
shouldBindMethods: true,
refs: { displayName: 'AppActions' },
setTitle(title = 'Learn To Code') {
return { title: title + '| Free Code Camp' };
return { title: title + ' | Free Code Camp' };
},
setUser({
getUser({ isPrimed }) {
if (isPrimed) {
return null;
}
debug('fetching user data');
return this.readService$('user', null, null)
.map(function({
username,
picture,
progressTimestamps = [],
@ -22,28 +32,14 @@ export default Actions({
isFrontEndCert,
isFullStackCert
};
})
.catch(err => {
console.error(err);
});
},
getUser: null,
updateRoute(route) {
return { route };
},
goBack: 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);
});
});
return appActions;
});
});

View File

@ -18,15 +18,15 @@ export default Store({
value: initValue
},
init({ instance: appStore, args: [cat] }) {
const { updateRoute, setUser, setTitle } = cat.getActions('appActions');
const { updateRoute, getUser, setTitle } = cat.getActions('appActions');
const register = createRegistrar(appStore);
let { setHikes } = cat.getActions('hikesActions');
const { fetchHikes } = cat.getActions('hikesActions');
// app
register(setter(fromMany(setUser, setTitle, updateRoute)));
register(setter(fromMany(getUser, setTitle, updateRoute)));
// hikes
register(setHikes);
register(fetchHikes);
return appStore;
}

View File

@ -0,0 +1,56 @@
import React, { PropTypes } from 'react';
import {
Col,
Panel,
Row
} from 'react-bootstrap';
import Lecture from './Lecture.jsx';
import Questions from './Questions.jsx';
export default React.createClass({
displayName: 'Hike',
propTypes: {
showQuestions: PropTypes.bool,
currentHike: PropTypes.object
},
renderBody(showQuestions, currentHike) {
if (showQuestions) {
return (
<Questions hike={ currentHike }/>
);
}
const {
challengeSeed: [ id ] = ['1'],
description = []
} = currentHike;
return (
<Lecture
description={ description }
id={ id } />
);
},
render() {
const { currentHike, showQuestions } = this.props;
const { title } = currentHike;
const videoTitle = <h2>{ title }</h2>;
return (
<Col xs={ 12 }>
<Row>
<Panel
className={ 'text-center' }
title={ videoTitle }>
{ this.renderBody(showQuestions, currentHike) }
</Panel>
</Row>
</Col>
);
}
});

View File

@ -9,7 +9,10 @@ import HikesMap from './Map.jsx';
export default contain(
{
store: 'hikesStore',
store: 'appStore',
map(state) {
return state.hikesApp;
},
actions: ['appActions'],
fetchAction: 'hikesActions.fetchHikes',
getPayload: ({ hikes, params }) => ({
@ -54,8 +57,12 @@ export default contain(
return (
<div>
<Row style={ preventOverflow }>
{ this.renderChild(children, hikes, currentHike) ||
this.renderMap(hikes) }
{
// render sub-route
this.renderChild(children, hikes, currentHike) ||
// if no sub-route render hikes map
this.renderMap(hikes)
}
</Row>
</div>
);

View File

@ -1,5 +1,5 @@
import React, { PropTypes } from 'react';
import { Button, Col, Row, Panel } from 'react-bootstrap';
import { Button, Col, Row } from 'react-bootstrap';
import { History } from 'react-router';
import Vimeo from 'react-vimeo';
import debugFactory from 'debug';
@ -19,8 +19,6 @@ export default React.createClass({
handleFinish() {
debug('loading questions');
const { dashedName } = this.props.params;
this.history.pushState(null, `/hikes/${dashedName}/questions/1`);
},
renderTranscript(transcript, dashedName) {
@ -31,7 +29,6 @@ export default React.createClass({
render() {
const {
title,
challengeSeed = ['1'],
description = []
} = this.props.currentHike;
@ -39,31 +36,22 @@ export default React.createClass({
const [ id ] = challengeSeed;
const videoTitle = <h2>{ title }</h2>;
return (
<Col xs={ 12 }>
<Row>
<Panel className={ 'text-center' } title={ videoTitle }>
<Vimeo
onError={ this.handleError }
onFinish= { this.handleFinish }
videoId={ id } />
</Panel>
</Row>
<Row>
<Col xs={ 12 }>
<Panel>
{ this.renderTranscript(description, dashedName) }
</Panel>
<Panel>
<Button
block={ true }
bsSize='large'
onClick={ this.handleFinish }>
Take me to the Questions
</Button>
</Panel>
</Col>
</Row>
</Col>
);

View File

@ -11,7 +11,7 @@ export default React.createClass({
render() {
const {
hikes
hikes = [{}]
} = this.props;
const vidElements = hikes.map(({ title, dashedName}) => {

View File

@ -16,7 +16,7 @@ const debug = debugFactory('freecc:hikes');
const ANSWER_THRESHOLD = 200;
export default React.createClass({
displayName: 'Question',
displayName: 'Questions',
mixins: [
History,

View File

@ -25,18 +25,11 @@ function getCurrentHike(hikes = [{}], dashedName, currentHike) {
}
export default Actions({
// start fetching hikes
fetchHikes: null,
// set hikes on store
setHikes: null
})
.refs({ displayName: 'HikesActions' })
.init(({ instance: hikeActions, args: [services] }) => {
// set up hikes fetching
hikeActions.fetchHikes.subscribe(
({ isPrimed, dashedName }) => {
refs: { displayName: 'HikesActions' },
shouldBindMethods: true,
fetchHikes({ isPrimed, dashedName }) {
if (isPrimed) {
return hikeActions.setHikes({
return {
transform: (state) => {
const { hikesApp: oldState } = state;
@ -49,25 +42,24 @@ export default Actions({
const hikesApp = { ...oldState, currentHike };
return Object.assign({}, state, { hikesApp });
}
});
}
services.read('hikes', null, null, (err, hikes) => {
if (err) {
return console.error(err);
};
}
return this.readService$('hikes', null, null)
.map(hikes => {
const hikesApp = {
hikes,
currentHike: getCurrentHike(hikes, dashedName)
};
hikeActions.setHikes({
return {
transform(oldState) {
return Object.assign({}, oldState, { hikesApp });
}
});
};
})
.catch(err => {
console.error(err);
});
}
);
});
});

View File

@ -1,2 +1 @@
export { default as HikesActions } from './Actions';
export { default as HikesStore } from './Store';

View File

@ -1,6 +1,5 @@
import Hikes from './components/Hikes.jsx';
import Lecture from './components/Lecture.jsx';
import Question from './components/Question.jsx';
import Hike from './components/Hike.jsx';
/*
* show video /hikes/someVideo
@ -12,9 +11,6 @@ export default {
component: Hikes,
childRoutes: [{
path: ':dashedName',
component: Lecture
}, {
path: ':dashedName/questions/:number',
component: Question
component: Hike
}]
};

View File

@ -1,9 +1,13 @@
import helmet from 'helmet';
const trusted = [
let trusted = [
"'self'"
];
if (process.env.NODE_ENV !== 'production') {
trusted.push('ws://localhost:3001');
}
export default function csp() {
return helmet.csp({
defaultSrc: trusted,