diff --git a/common/app/routes/Hikes/components/Hikes.jsx b/common/app/routes/Hikes/components/Hikes.jsx
index 0c538777fd..3b4d64b74c 100644
--- a/common/app/routes/Hikes/components/Hikes.jsx
+++ b/common/app/routes/Hikes/components/Hikes.jsx
@@ -1,32 +1,54 @@
import React, { PropTypes } from 'react';
import stampit from 'react-stampit';
import { Row } from 'react-bootstrap';
+import { contain } from 'thundercats-react';
// import debugFactory from 'debug';
import HikesMap from './Map.jsx';
// const debug = debugFactory('freecc:hikes');
-export default stampit(React, {
- displayName: 'Hikes',
-
- propTypes: {
- children: PropTypes.element
+export default contain(
+ {
+ store: 'hikesStore',
+ fetchAction: 'hikesActions.fetchHikes',
+ getPayload: ({ hikes, params }) => ({
+ isPrimed: (hikes && !!hikes.length),
+ dashedName: params.dashedName
+ })
},
+ stampit(React, {
+ displayName: 'Hikes',
- renderMap() {
- return (
-
- );
- },
+ propTypes: {
+ children: PropTypes.element,
+ currentHike: PropTypes.object,
+ hikes: PropTypes.array
+ },
- render() {
- return (
-
-
- { this.props.children || this.renderMap() }
-
-
- );
- }
-});
+ renderMap(hikes) {
+ return (
+
+ );
+ },
+
+ renderChild(children, hikes, currentHike) {
+ if (!children) {
+ return null;
+ }
+ return React.cloneElement(children, { hikes, currentHike });
+ },
+
+ render() {
+ const { hikes, children, currentHike } = this.props;
+ return (
+
+
+ { this.renderChild(children, hikes, currentHike) ||
+ this.renderMap(hikes) }
+
+
+ );
+ }
+ })
+);
diff --git a/common/app/routes/Hikes/components/Lecture.jsx b/common/app/routes/Hikes/components/Lecture.jsx
index c7c75b9f13..d2174e5bf3 100644
--- a/common/app/routes/Hikes/components/Lecture.jsx
+++ b/common/app/routes/Hikes/components/Lecture.jsx
@@ -1,94 +1,71 @@
import React, { PropTypes } from 'react';
import { Button, Col, Row, Panel } from 'react-bootstrap';
import { Navigation } from 'react-router';
-import { contain } from 'thundercats-react';
import stampit from 'react-stampit';
import Vimeo from 'react-vimeo';
import debugFactory from 'debug';
const debug = debugFactory('freecc:hikes');
-export default contain(
- {
- store: 'hikesStore',
- fetchAction: 'hikesActions.fetchCurrentHike',
- getPayload({ currentHike, params: { dashedName } }) {
- const filterRegex = new RegExp(dashedName, 'i');
- if (currentHike && filterRegex.test(currentHike.dashedName)) {
- return {
- isPrimed: true,
- dashedName
- };
- }
- return {
- isPrimed: false,
- dashedName: dashedName
- };
- }
+export default stampit(React, {
+ displayName: 'Lecture',
+
+ propTypes: {
+ currentHike: PropTypes.object,
+ params: PropTypes.object
},
- stampit(React, {
- displayName: 'Lecture',
- propTypes: {
- currentHike: PropTypes.object,
- dashedName: PropTypes.string,
- params: PropTypes.object
- },
+ handleError: debug,
- handleError: debug,
+ handleFinish() {
+ debug('loading questions');
+ const { dashedName } = this.props.params;
+ this.transitionTo(`/hikes/${dashedName}/questions/1`);
+ },
- handleFinish() {
- debug('loading questions');
- const { dashedName } = this.props.params;
- this.transitionTo(`/hikes/${dashedName}/questions/1`);
- },
+ renderTranscript(transcript, dashedName) {
+ return transcript.map((line, index) => (
+ { line }
+ ));
+ },
- renderTranscript(transcript) {
- return transcript.map((line, index) => (
- { line }
- )
- );
- },
+ render() {
+ const {
+ title,
+ challengeSeed = ['1'],
+ description = []
+ } = this.props.currentHike;
+ const { dashedName } = this.props.params;
- render() {
- const {
- title,
- challengeSeed = ['1'],
- description = []
- } = this.props.currentHike;
+ const [ id ] = challengeSeed;
- const [ id ] = challengeSeed;
-
- const videoTitle = { title }
;
- return (
-
-
-
-
+ const videoTitle = { title }
;
+ return (
+
+
+
+
+
+
+
+
+
+ { this.renderTranscript(description, dashedName) }
-
-
-
-
-
- { this.renderTranscript(description) }
-
-
-
-
-
-
-
-
- );
- }
- }).compose(Navigation)
-);
+
+
+
+
+
+
+ );
+ }
+}).compose(Navigation);
diff --git a/common/app/routes/Hikes/components/Map.jsx b/common/app/routes/Hikes/components/Map.jsx
index b94e68f6fa..a5acbe2032 100644
--- a/common/app/routes/Hikes/components/Map.jsx
+++ b/common/app/routes/Hikes/components/Map.jsx
@@ -1,47 +1,39 @@
import React, { PropTypes } from 'react';
import stampit from 'react-stampit';
import { Link } from 'react-router';
-import { contain } from 'thundercats-react';
import { ListGroup, ListGroupItem, Panel } from 'react-bootstrap';
-export default contain(
- {
- store: 'hikesStore',
- fetchAction: 'hikesActions.fetchHikes',
- getPayload: ({ hikes }) => ({ isPrimed: (hikes && !!hikes.length) })
+export default stampit(React, {
+ displayName: 'HikesMap',
+
+ propTypes: {
+ hikes: PropTypes.array
},
- stampit(React, {
- displayName: 'HikesMap',
- propTypes: {
- hikes: PropTypes.array
- },
-
- render() {
- const {
- hikes
- } = this.props;
-
- const vidElements = hikes.map(({ title, dashedName}) => {
- return (
-
-
- { title }
-
-
- );
- });
+ render() {
+ const {
+ hikes
+ } = this.props;
+ const vidElements = hikes.map(({ title, dashedName}) => {
return (
-
-
- Welcome To Hikes!
-
-
- { vidElements }
-
-
+
+
+ { title }
+
+
);
- }
- })
-);
+ });
+
+ return (
+
+
+ Welcome To Hikes!
+
+
+ { vidElements }
+
+
+ );
+ }
+});
diff --git a/common/app/routes/Hikes/components/Question.jsx b/common/app/routes/Hikes/components/Question.jsx
index 6621db6364..2524aa6748 100644
--- a/common/app/routes/Hikes/components/Question.jsx
+++ b/common/app/routes/Hikes/components/Question.jsx
@@ -1,7 +1,6 @@
import React, { PropTypes } from 'react';
import { Navigation, TransitionHook } from 'react-router';
import stampit from 'react-stampit';
-import { contain } from 'thundercats-react';
import debugFactory from 'debug';
import {
Button,
@@ -13,145 +12,121 @@ import {
const debug = debugFactory('freecc:hikes');
-export default contain(
- {
- store: 'hikesStore',
- map({ currentHike }) {
- const { tests = [] } = currentHike;
+export default stampit(React, {
+ state: { showInfo: false },
+ displayName: 'Question',
- return { currentHike, tests };
- },
- fetchAction: 'hikesActions.fetchCurrentHike',
- getPayload({ currentHike, params: { dashedName } }) {
- const filterRegex = new RegExp(dashedName, 'i');
- if (currentHike && filterRegex.test(currentHike.dashedName)) {
- return {
- isPrimed: true,
- dashedName
- };
- }
- return {
- isPrimed: false,
- dashedName: dashedName
- };
- }
+ propTypes: {
+ currentHike: PropTypes.object,
+ dashedName: PropTypes.string,
+ hikes: PropTypes.array,
+ params: PropTypes.object
},
- stampit(React, {
- state: { showInfo: false },
- displayName: 'Question',
- propTypes: {
- currentHike: PropTypes.object,
- dashedName: PropTypes.string,
- params: PropTypes.object,
- tests: PropTypes.array
- },
-
- onAnswer(answer, userAnswer, info, e) {
- if (e && e.preventDefault) {
- e.preventDefault();
- }
- if (answer === userAnswer) {
- debug('correct answer!');
- this.setState({ showInfo: true });
- }
- return debug('incorrect');
- },
-
- onCorrectAnswer() {
- const { hikes, currentHike } = this.props;
- const { dashedName, number } = this.props.params;
- const { difficulty, tests } = currentHike;
- const nextQuestionIndex = +number;
- this.setState({ showInfo: false }, () => {
- if (tests[nextQuestionIndex]) {
- return this.transitionTo(
- `/hikes/${ dashedName }/questions/${ nextQuestionIndex + 1 }`
- );
- }
- // next questions does not exit
- // find next hike
- //
- const nextHike = hikes
- // hikes is in oder of difficulty, lets get reverse order
- .reverse()
- // now lets find the hike with the difficulty right above this one
- .reduce((lowerHike, hike) => {
- if (hike.difficulty > difficulty) {
- return hike;
- }
- return lowerHike;
- }, null);
-
- if (nextHike) {
- return this.transitionTo(`${ nextHike.dashedName }`);
- }
- debug('next Hike was not found');
- });
- },
-
- routerWillLeave(/* nextState, router, cb[optional] */) {
- // TODO(berks): do animated transitions here stuff here
- },
-
- renderInfo(showInfo, info) {
- return (
-
-
-
- { info || 'correct!' }
-
-
-
-
-
-
- );
- },
-
- render() {
- const { showInfo } = this.state;
- const { tests } = this.props;
- const { number = '1' } = this.props.params;
-
- const [question, answer, info] = tests[number - 1] || [];
-
- return (
-
-
-
- { question }
-
- { this.renderInfo(showInfo, info) }
-
-
-
-
-
-
- );
+ onAnswer(answer, userAnswer, info, e) {
+ if (e && e.preventDefault) {
+ e.preventDefault();
}
- })
- .compose(Navigation)
- .compose(TransitionHook)
-);
+ if (answer === userAnswer) {
+ debug('correct answer!');
+ this.setState({ showInfo: true });
+ }
+ return debug('incorrect');
+ },
+
+ onCorrectAnswer() {
+ const { hikes, currentHike } = this.props;
+ const { dashedName, number } = this.props.params;
+ const { difficulty, tests } = currentHike;
+ const nextQuestionIndex = +number;
+ this.setState({ showInfo: false }, () => {
+ if (tests[nextQuestionIndex]) {
+ return this.transitionTo(
+ `/hikes/${ dashedName }/questions/${ nextQuestionIndex + 1 }`
+ );
+ }
+ // next questions does not exit
+ // find next hike
+ //
+ const nextHike = hikes
+ // hikes is in oder of difficulty, lets get reverse order
+ .reverse()
+ // now lets find the hike with the difficulty right above this one
+ .reduce((lowerHike, hike) => {
+ if (hike.difficulty > difficulty) {
+ return hike;
+ }
+ return lowerHike;
+ }, null);
+
+ if (nextHike) {
+ return this.transitionTo(`/hikes/${ nextHike.dashedName }`);
+ }
+ debug('next Hike was not found');
+ });
+ },
+
+ routerWillLeave(/* nextState, router, cb[optional] */) {
+ // TODO(berks): do animated transitions here stuff here
+ },
+
+ renderInfo(showInfo, info) {
+ return (
+
+
+
+ { info || 'correct!' }
+
+
+
+
+
+
+ );
+ },
+
+ render() {
+ const { showInfo } = this.state;
+ const { currentHike: { tests = [] } } = this.props;
+ const { number = '1' } = this.props.params;
+
+ const [question, answer, info] = tests[number - 1] || [];
+
+ return (
+
+
+
+ { question }
+
+ { this.renderInfo(showInfo, info) }
+
+
+
+
+
+
+ );
+ }
+})
+ .compose(Navigation)
+ .compose(TransitionHook);
diff --git a/common/app/routes/Hikes/flux/Actions.js b/common/app/routes/Hikes/flux/Actions.js
index 3bc31c5f79..4c85a4d1f0 100644
--- a/common/app/routes/Hikes/flux/Actions.js
+++ b/common/app/routes/Hikes/flux/Actions.js
@@ -8,28 +8,42 @@ const service = new Fetchr({
xhrPath: '/services'
});
+function getCurrentHike(hikes =[{}], dashedName, currentHike) {
+ if (!dashedName) {
+ return hikes[0];
+ }
+ const filterRegex = new RegExp(dashedName, 'i');
+
+ return hikes
+ .filter(({ dashedName }) => {
+ return filterRegex.test(dashedName);
+ })
+ .reduce((throwAway, hike) => {
+ return hike;
+ }, currentHike || {});
+}
+
export default Actions({
// start fetching hikes
fetchHikes: null,
// set hikes on store
- setHikes: null,
-
- fetchCurrentHike: null,
- setCurrentHike: null
+ setHikes: null
})
.refs({ displayName: 'HikesActions' })
.init(({ instance }) => {
// set up hikes fetching
instance.fetchHikes.subscribe(
- ({ isPrimed }) => {
+ ({ isPrimed, dashedName }) => {
if (isPrimed) {
return instance.setHikes({
transform: (oldState) => {
- const { hikes } = oldState;
- const newState = {
- currentHike: (oldState.currentHike || hikes[0] || {})
- };
- return assign({}, oldState, newState);
+ const { hikes, currentContext } = oldState;
+ const currentHike = getCurrentHike(
+ hikes,
+ dashedName,
+ currentContext
+ );
+ return assign({}, oldState, { currentHike });
}
});
}
@@ -40,38 +54,10 @@ export default Actions({
instance.setHikes({
set: {
hikes: hikes,
- currentHike: hikes[0] || {}
+ currentHike: getCurrentHike(hikes, dashedName)
}
});
});
}
);
-
- instance.fetchCurrentHike.subscribe(({ isPrimed, dashedName }) => {
- if (isPrimed) {
- return instance.setCurrentHike({
- transform: (oldState) => {
- const { hikes } = oldState;
- const filterRegex = new RegExp(dashedName, 'i');
- const potentialHike = hikes
- .filter(({ dashedName }) => {
- return filterRegex.test(dashedName);
- })
- .reduce((throwAway, hike) => {
- return hike;
- });
-
- // TODO(berks): do something when potential hike does not exist
- return assign({}, oldState, { currentHike: potentialHike });
- }
- });
- }
- service.read('hikes', { dashedName }, null, (err, hikes) => {
- if (err) {
- debug('error occurred fetching hike', err);
- }
- const [currentHike] = hikes;
- return instance.setCurrentHike({ set: { currentHike } });
- });
- });
});
diff --git a/common/app/routes/Hikes/flux/Store.js b/common/app/routes/Hikes/flux/Store.js
index 1af8badd67..4893148326 100644
--- a/common/app/routes/Hikes/flux/Store.js
+++ b/common/app/routes/Hikes/flux/Store.js
@@ -1,6 +1,5 @@
import { Store } from 'thundercats';
-const { fromMany } = Store;
const initialValue = {
hikes: [],
currentHike: {}
@@ -10,11 +9,9 @@ export default Store(initialValue)
.refs({ displayName: 'HikesStore'})
.init(({ instance, args }) => {
const [cat] = args;
- let {
- setHikes,
- setCurrentHike
- } = cat.getActions('hikesActions');
- instance.register(fromMany(setHikes, setCurrentHike));
+
+ let { setHikes } = cat.getActions('hikesActions');
+ instance.register(setHikes);
return instance;
});