From b945fc94a4efcf9f6052700b9fcc1e200895d869 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Fri, 17 Jul 2015 22:33:46 -0700 Subject: [PATCH] Move flux contianer to top level hike comp Removes all the lower level hikes Finishing questions takes you to next hike BUG: sometimes it takes you an incorrect next challenge --- common/app/routes/Hikes/components/Hikes.jsx | 62 +++-- .../app/routes/Hikes/components/Lecture.jsx | 131 ++++----- common/app/routes/Hikes/components/Map.jsx | 66 ++--- .../app/routes/Hikes/components/Question.jsx | 253 ++++++++---------- common/app/routes/Hikes/flux/Actions.js | 64 ++--- common/app/routes/Hikes/flux/Store.js | 9 +- 6 files changed, 267 insertions(+), 318 deletions(-) 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; });