From c5aff0b16bd43a3eb54e6416cd438192df16d556 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Wed, 8 Jun 2016 18:48:30 -0700 Subject: [PATCH] Submit step challenge --- .../challenges/components/step/Step.jsx | 103 ++++++++++-------- common/app/routes/challenges/redux/actions.js | 2 +- common/app/routes/challenges/redux/reducer.js | 23 +++- common/app/routes/challenges/redux/types.js | 1 + 4 files changed, 78 insertions(+), 51 deletions(-) diff --git a/common/app/routes/challenges/components/step/Step.jsx b/common/app/routes/challenges/components/step/Step.jsx index 04a04a03a0..8e1b6f391c 100644 --- a/common/app/routes/challenges/components/step/Step.jsx +++ b/common/app/routes/challenges/components/step/Step.jsx @@ -5,29 +5,40 @@ import { createSelector } from 'reselect'; import PureComponent from 'react-pure-render/component'; import ReactTransitionReplace from 'react-css-transition-replace'; -import { submitChallenge, goToStep } from '../../redux/actions'; +import { + goToStep, + completeAction, + submitChallenge +} from '../../redux/actions'; import { challengeSelector } from '../../redux/selectors'; import { Button, Col, Image, Row } from 'react-bootstrap'; const transitionTimeout = 1000; const mapStateToProps = createSelector( challengeSelector, - state => state.challengesApp.currentStep, - state => state.challengesApp.previousStep, - ({ challenge }, currentStep, previousStep) => ({ - challenge, - currentStep, - previousStep, - numOfSteps: - Array.isArray(challenge.description) ? - challenge.description.length : - 0, - isGoingForward: currentStep > previousStep + state => state.challengesApp.currentIndex, + state => state.challengesApp.previousIndex, + state => state.challengesApp.isActionCompleted, + ( + { + challenge: { description = [] } + }, + currentIndex, + previousIndex, + isActionCompleted + ) => ({ + currentIndex, + isActionCompleted, + step: description[currentIndex], + steps: description, + numOfSteps: description.length, + isGoingForward: currentIndex > previousIndex }) ); const dispatchActions = { goToStep, + completeAction, submitChallenge }; @@ -38,36 +49,37 @@ export class StepChallenge extends PureComponent { this.handleBackClick = this.handleBackClick.bind(this); } static displayName = 'StepChallenge'; - static defaultProps = { - currentStep: 0, - previousStep: -1 - }; - static propTypes = { - challenge: PropTypes.object, - currentStep: PropTypes.number, - previousStep: PropTypes.number, + currentIndex: PropTypes.number, + step: PropTypes.array, + steps: PropTypes.array, + isActionCompleted: PropTypes.bool, isGoingForward: PropTypes.bool, + numOfSteps: PropTypes.number, goToStep: PropTypes.func, - submitChallenge: PropTypes.func, - numOfSteps: PropTypes.number + completeAction: PropTypes.func, + submitChallenge: PropTypes.func }; handleNextClick() { - const { numOfSteps, currentStep, submitChallenge, goToStep } = this.props; - const isLastStep = currentStep + 1 >= numOfSteps; + const { numOfSteps, currentIndex, submitChallenge, goToStep } = this.props; + const isLastStep = currentIndex + 1 >= numOfSteps; if (isLastStep) { return submitChallenge(); } - return goToStep(currentStep + 1); + return goToStep(currentIndex + 1); } handleBackClick() { - const { currentStep, goToStep } = this.props; - goToStep(currentStep - 1); + const { currentIndex, goToStep } = this.props; + goToStep(currentIndex - 1); } - renderActionButton(action) { + renderActionButton(action, completeAction) { + const isApiAction = action === '#'; + const buttonCopy = isApiAction ? + 'Confirm' : + 'Open link in new tab '; if (!action) { return null; } @@ -78,9 +90,10 @@ export class StepChallenge extends PureComponent { bsSize='large' bsStyle='primary' href={ action } + onClick={ completeAction } target='_blank' > - Open link in new tab (this unlocks the next step) + { buttonCopy } (this unlocks the next step)
@@ -121,6 +134,7 @@ export class StepChallenge extends PureComponent { bsSize='large' bsStyle='primary' className={ btnClass } + disabled={ hasAction && !isCompleted } onClick={ this.handleNextClick } > { isLastStep ? 'Finish challenge' : 'Go to my next step'} @@ -128,7 +142,13 @@ export class StepChallenge extends PureComponent { ); } - renderStep(step, currentStep, numOfSteps) { + renderStep({ + step, + currentIndex, + numOfSteps, + isActionCompleted, + completeAction + }) { if (!Array.isArray(step)) { return null; } @@ -162,21 +182,21 @@ export class StepChallenge extends PureComponent {
- { this.renderActionButton(action) } - { this.renderBackButton(currentStep) } + { this.renderActionButton(action, completeAction) } + { this.renderBackButton(currentIndex) } - ( { currentStep + 1 } / { numOfSteps }) + ( { currentIndex + 1 } / { numOfSteps }) { this.renderNextButton( !!action, - currentStep, + currentIndex, numOfSteps, - true + isActionCompleted ) }
@@ -202,16 +222,9 @@ export class StepChallenge extends PureComponent { } render() { - const { - numOfSteps, - challenge, - currentStep, - isGoingForward - } = this.props; - const step = challenge.description[currentStep]; + const { steps, isGoingForward } = this.props; const transitionName = 'challenge-step-' + (isGoingForward ? 'forward' : 'backward'); - return ( - { this.renderStep(step, currentStep, numOfSteps) } + { this.renderStep(this.props) }
- { this.renderImages(challenge.description) } + { this.renderImages(steps) }
diff --git a/common/app/routes/challenges/redux/actions.js b/common/app/routes/challenges/redux/actions.js index 2d20da0adb..0e62fc535c 100644 --- a/common/app/routes/challenges/redux/actions.js +++ b/common/app/routes/challenges/redux/actions.js @@ -6,7 +6,7 @@ import types from './types'; // step export const goToStep = createAction(types.goToStep); - +export const completeAction = createAction(types.completeAction); // challenges export const fetchChallenge = createAction(types.fetchChallenge); diff --git a/common/app/routes/challenges/redux/reducer.js b/common/app/routes/challenges/redux/reducer.js index cddf1cc9c0..34b5b21a9d 100644 --- a/common/app/routes/challenges/redux/reducer.js +++ b/common/app/routes/challenges/redux/reducer.js @@ -15,11 +15,16 @@ const initialState = { id: '', challenge: '', legacyKey: '', - currentStep: 0, - previousStep: -1, + // step + currentIndex: 0, + previousIndex: -1, + isActionCompleted: false, + // map filter: '', - files: {}, superBlocks: [], + // modern + files: {}, + // misc toast: 0 }; @@ -73,9 +78,17 @@ const mainReducer = handleActions( [types.resetStep]: () => initialState, [types.goToStep]: (state, { payload: step = 0 }) => ({ ...state, - currentStep: step, - previousStep: state.currentStep + currentIndex: step, + previousIndex: state.currentIndex, + isActionCompleted: false }), + + [types.completeAction]: state => ({ + ...state, + isActionCompleted: true + }), + + // classic/modern [types.initOutput]: (state, { payload: output }) => ({ ...state, output diff --git a/common/app/routes/challenges/redux/types.js b/common/app/routes/challenges/redux/types.js index 12a006b52f..c20039bfd3 100644 --- a/common/app/routes/challenges/redux/types.js +++ b/common/app/routes/challenges/redux/types.js @@ -3,6 +3,7 @@ import createTypes from '../../../utils/create-types'; export default createTypes([ // step 'goToStep', + 'completeAction', // challenges 'fetchChallenge',