Hikes loading next hike
This commit is contained in:
@ -2,6 +2,7 @@ import React, { PropTypes } from 'react';
|
|||||||
import { spring, Motion } from 'react-motion';
|
import { spring, Motion } from 'react-motion';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Button, Col, Row } from 'react-bootstrap';
|
import { Button, Col, Row } from 'react-bootstrap';
|
||||||
|
import { CompositeDisposable } from 'rx';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -53,6 +54,11 @@ const mapStateToProps = createSelector(
|
|||||||
);
|
);
|
||||||
|
|
||||||
class Question extends React.Component {
|
class Question extends React.Component {
|
||||||
|
constructor(...args) {
|
||||||
|
super(...args);
|
||||||
|
this._subscriptions = new CompositeDisposable();
|
||||||
|
}
|
||||||
|
|
||||||
static displayName = 'Questions';
|
static displayName = 'Questions';
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@ -72,6 +78,10 @@ class Question extends React.Component {
|
|||||||
shouldShakeQuestion: PropTypes.bool
|
shouldShakeQuestion: PropTypes.bool
|
||||||
};
|
};
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this._subscriptions.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
handleMouseUp(e, answer, info) {
|
handleMouseUp(e, answer, info) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if (!this.props.isPressed) {
|
if (!this.props.isPressed) {
|
||||||
@ -84,12 +94,15 @@ class Question extends React.Component {
|
|||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
releaseQuestion();
|
releaseQuestion();
|
||||||
answerQuestion({
|
const subscription = answerQuestion({
|
||||||
e,
|
e,
|
||||||
answer,
|
answer,
|
||||||
info,
|
info,
|
||||||
threshold: answerThreshold
|
threshold: answerThreshold
|
||||||
});
|
})
|
||||||
|
.subscribe();
|
||||||
|
|
||||||
|
this._subscriptions.add(subscription);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMouseMove(isPressed, { delta, moveQuestion }) {
|
handleMouseMove(isPressed, { delta, moveQuestion }) {
|
||||||
@ -101,17 +114,21 @@ class Question extends React.Component {
|
|||||||
|
|
||||||
onAnswer(answer, userAnswer, info) {
|
onAnswer(answer, userAnswer, info) {
|
||||||
const { isSignedIn, answerQuestion } = this.props;
|
const { isSignedIn, answerQuestion } = this.props;
|
||||||
|
const subscriptions = this._subscriptions;
|
||||||
return e => {
|
return e => {
|
||||||
if (e && e.preventDefault) {
|
if (e && e.preventDefault) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
return answerQuestion({
|
const subscription = answerQuestion({
|
||||||
answer,
|
answer,
|
||||||
userAnswer,
|
userAnswer,
|
||||||
info,
|
info,
|
||||||
isSignedIn
|
isSignedIn
|
||||||
});
|
})
|
||||||
|
.subscribe();
|
||||||
|
|
||||||
|
subscriptions.add(subscription);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Observable } from 'rx';
|
import { Observable } from 'rx';
|
||||||
// import { routeActions } from 'react-simple-router';
|
import { push } from 'react-router-redux';
|
||||||
|
|
||||||
import types from './types';
|
import types from './types';
|
||||||
import { getMouse } from './utils';
|
import { getMouse } from './utils';
|
||||||
@ -7,13 +7,9 @@ import { getMouse } from './utils';
|
|||||||
import { makeToast, updatePoints } from '../../../redux/actions';
|
import { makeToast, updatePoints } from '../../../redux/actions';
|
||||||
import { hikeCompleted, goToNextHike } from './actions';
|
import { hikeCompleted, goToNextHike } from './actions';
|
||||||
import { postJSON$ } from '../../../../utils/ajax-stream';
|
import { postJSON$ } from '../../../../utils/ajax-stream';
|
||||||
|
import { getCurrentHike } from './selectors';
|
||||||
|
|
||||||
export default () => ({ getState, dispatch }) => next => {
|
function handleAnswer(getState, dispatch, next, action) {
|
||||||
return function answerSaga(action) {
|
|
||||||
if (types.answerQuestion !== action.type) {
|
|
||||||
return next(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
e,
|
e,
|
||||||
answer,
|
answer,
|
||||||
@ -22,15 +18,15 @@ export default () => ({ getState, dispatch }) => next => {
|
|||||||
threshold
|
threshold
|
||||||
} = action.payload;
|
} = action.payload;
|
||||||
|
|
||||||
|
const state = getState();
|
||||||
|
const { id, name, challengeType, tests } = getCurrentHike(state);
|
||||||
const {
|
const {
|
||||||
app: { isSignedIn },
|
app: { isSignedIn },
|
||||||
hikesApp: {
|
hikesApp: {
|
||||||
currentQuestion,
|
currentQuestion,
|
||||||
currentHike: { id, name, challengeType },
|
|
||||||
tests = [],
|
|
||||||
delta = [ 0, 0 ]
|
delta = [ 0, 0 ]
|
||||||
}
|
}
|
||||||
} = getState();
|
} = state;
|
||||||
|
|
||||||
let finalAnswer;
|
let finalAnswer;
|
||||||
// drag answer, compute response
|
// drag answer, compute response
|
||||||
@ -64,7 +60,7 @@ export default () => ({ getState, dispatch }) => next => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Observable
|
return Observable
|
||||||
.just({ type: types.removeShake })
|
.just({ type: types.endShake })
|
||||||
.delay(500)
|
.delay(500)
|
||||||
.startWith({ type: types.startShake })
|
.startWith({ type: types.startShake })
|
||||||
.doOnNext(dispatch);
|
.doOnNext(dispatch);
|
||||||
@ -74,7 +70,8 @@ export default () => ({ getState, dispatch }) => next => {
|
|||||||
return Observable
|
return Observable
|
||||||
.just({ type: types.goToNextQuestion })
|
.just({ type: types.goToNextQuestion })
|
||||||
.delay(300)
|
.delay(300)
|
||||||
.startWith({ type: types.primeNextQuestion });
|
.startWith({ type: types.primeNextQuestion })
|
||||||
|
.doOnNext(dispatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
let updateUser$;
|
let updateUser$;
|
||||||
@ -120,6 +117,28 @@ export default () => ({ getState, dispatch }) => next => {
|
|||||||
.catch(error => Observable.just({
|
.catch(error => Observable.just({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
error
|
error
|
||||||
}));
|
}))
|
||||||
|
.doOnNext(dispatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default () => ({ getState, dispatch }) => next => {
|
||||||
|
return function answerSaga(action) {
|
||||||
|
if (action.type === types.answerQuestion) {
|
||||||
|
return handleAnswer(getState, dispatch, next, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
// let goToNextQuestion hit reducers first
|
||||||
|
const result = next(action);
|
||||||
|
if (action.type === types.goToNextHike) {
|
||||||
|
const { hikesApp: { currentHike } } = getState();
|
||||||
|
// if no next hike currentHike will equal '' which is falsy
|
||||||
|
if (currentHike) {
|
||||||
|
dispatch(push(`/videos/${currentHike}`));
|
||||||
|
} else {
|
||||||
|
dispatch(push('/map'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { handleActions } from 'redux-actions';
|
import { handleActions } from 'redux-actions';
|
||||||
import types from './types';
|
import types from './types';
|
||||||
import { findNextHike } from './utils';
|
import { findNextHikeName } from './utils';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
hikes: {
|
hikes: {
|
||||||
@ -79,7 +79,7 @@ export default handleActions(
|
|||||||
|
|
||||||
[types.goToNextHike]: state => ({
|
[types.goToNextHike]: state => ({
|
||||||
...state,
|
...state,
|
||||||
currentHike: findNextHike(state.hikes, state.currentHike),
|
currentHike: findNextHikeName(state.hikes, state.currentHike),
|
||||||
showQuestions: false,
|
showQuestions: false,
|
||||||
currentQuestion: 1,
|
currentQuestion: 1,
|
||||||
mouse: [ 0, 0 ]
|
mouse: [ 0, 0 ]
|
||||||
|
@ -42,21 +42,24 @@ export function getCurrentHike(hikes = {}, dashedName) {
|
|||||||
return hikes.entities[dashedName];
|
return hikes.entities[dashedName];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function findNextHike({ entities, results }, dashedName) {
|
// findNextHikeName(
|
||||||
|
// hikes: { results: String[] },
|
||||||
|
// dashedName: String
|
||||||
|
// ) => String
|
||||||
|
export function findNextHikeName({ results }, dashedName) {
|
||||||
if (!dashedName) {
|
if (!dashedName) {
|
||||||
log('find next hike no id provided');
|
log('find next hike no id provided');
|
||||||
return entities[results[0]];
|
return results[0];
|
||||||
}
|
}
|
||||||
const currentIndex = _.findIndex(
|
const currentIndex = _.findIndex(
|
||||||
results,
|
results,
|
||||||
({ dashedName: _dashedName }) => _dashedName === dashedName
|
_dashedName => _dashedName === dashedName
|
||||||
);
|
);
|
||||||
|
|
||||||
if (currentIndex >= results.length) {
|
if (currentIndex >= results.length) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
return results[currentIndex + 1];
|
||||||
return entities[results[currentIndex + 1]];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user