Submit step
This commit is contained in:
@ -5,7 +5,7 @@ import { createSelector } from 'reselect';
|
|||||||
import PureComponent from 'react-pure-render/component';
|
import PureComponent from 'react-pure-render/component';
|
||||||
import ReactTransitionReplace from 'react-css-transition-replace';
|
import ReactTransitionReplace from 'react-css-transition-replace';
|
||||||
|
|
||||||
import { goToStep } from '../../redux/actions';
|
import { submitChallenge, goToStep } from '../../redux/actions';
|
||||||
import { challengeSelector } from '../../redux/selectors';
|
import { challengeSelector } from '../../redux/selectors';
|
||||||
import { Button, Col, Image, Row } from 'react-bootstrap';
|
import { Button, Col, Image, Row } from 'react-bootstrap';
|
||||||
|
|
||||||
@ -18,15 +18,25 @@ const mapStateToProps = createSelector(
|
|||||||
challenge,
|
challenge,
|
||||||
currentStep,
|
currentStep,
|
||||||
previousStep,
|
previousStep,
|
||||||
|
numOfSteps:
|
||||||
|
Array.isArray(challenge.description) ?
|
||||||
|
challenge.description.length :
|
||||||
|
0,
|
||||||
isGoingForward: currentStep > previousStep
|
isGoingForward: currentStep > previousStep
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const dispatchActions = {
|
const dispatchActions = {
|
||||||
goToStep
|
goToStep,
|
||||||
|
submitChallenge
|
||||||
};
|
};
|
||||||
|
|
||||||
export class StepChallenge extends PureComponent {
|
export class StepChallenge extends PureComponent {
|
||||||
|
constructor(...args) {
|
||||||
|
super(...args);
|
||||||
|
this.handleNextClick = this.handleNextClick.bind(this);
|
||||||
|
this.handleBackClick = this.handleBackClick.bind(this);
|
||||||
|
}
|
||||||
static displayName = 'StepChallenge';
|
static displayName = 'StepChallenge';
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
currentStep: 0,
|
currentStep: 0,
|
||||||
@ -38,9 +48,25 @@ export class StepChallenge extends PureComponent {
|
|||||||
currentStep: PropTypes.number,
|
currentStep: PropTypes.number,
|
||||||
previousStep: PropTypes.number,
|
previousStep: PropTypes.number,
|
||||||
isGoingForward: PropTypes.bool,
|
isGoingForward: PropTypes.bool,
|
||||||
goToStep: PropTypes.func
|
goToStep: PropTypes.func,
|
||||||
|
submitChallenge: PropTypes.func,
|
||||||
|
numOfSteps: PropTypes.number
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handleNextClick() {
|
||||||
|
const { numOfSteps, currentStep, submitChallenge, goToStep } = this.props;
|
||||||
|
const isLastStep = currentStep + 1 >= numOfSteps;
|
||||||
|
if (isLastStep) {
|
||||||
|
return submitChallenge();
|
||||||
|
}
|
||||||
|
return goToStep(currentStep + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleBackClick() {
|
||||||
|
const { currentStep, goToStep } = this.props;
|
||||||
|
goToStep(currentStep - 1);
|
||||||
|
}
|
||||||
|
|
||||||
renderActionButton(action) {
|
renderActionButton(action) {
|
||||||
if (!action) {
|
if (!action) {
|
||||||
return null;
|
return null;
|
||||||
@ -52,7 +78,8 @@ export class StepChallenge extends PureComponent {
|
|||||||
bsSize='large'
|
bsSize='large'
|
||||||
bsStyle='primary'
|
bsStyle='primary'
|
||||||
href={ action }
|
href={ action }
|
||||||
target='_blank'>
|
target='_blank'
|
||||||
|
>
|
||||||
Open link in new tab (this unlocks the next step)
|
Open link in new tab (this unlocks the next step)
|
||||||
</Button>
|
</Button>
|
||||||
<div className='spacer' />
|
<div className='spacer' />
|
||||||
@ -61,12 +88,12 @@ export class StepChallenge extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderBackButton(index) {
|
renderBackButton(index) {
|
||||||
const { goToStep } = this.props;
|
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
return (
|
return (
|
||||||
<Col
|
<Col
|
||||||
className='hidden-xs'
|
className='hidden-xs'
|
||||||
md={ 4 }>
|
md={ 4 }
|
||||||
|
>
|
||||||
{ ' ' }
|
{ ' ' }
|
||||||
</Col>
|
</Col>
|
||||||
);
|
);
|
||||||
@ -76,14 +103,14 @@ export class StepChallenge extends PureComponent {
|
|||||||
bsSize='large'
|
bsSize='large'
|
||||||
bsStyle='primary'
|
bsStyle='primary'
|
||||||
className='col-sm-4 col-xs-12'
|
className='col-sm-4 col-xs-12'
|
||||||
onClick={ () => goToStep(index - 1) }>
|
onClick={ this.handleBackClick }
|
||||||
|
>
|
||||||
Go to my previous step
|
Go to my previous step
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderNextButton(hasAction, index, numOfSteps, isCompleted) {
|
renderNextButton(hasAction, index, numOfSteps, isCompleted) {
|
||||||
const { goToStep } = this.props;
|
|
||||||
const isLastStep = index + 1 >= numOfSteps;
|
const isLastStep = index + 1 >= numOfSteps;
|
||||||
const btnClass = classnames({
|
const btnClass = classnames({
|
||||||
'col-sm-4 col-xs-12': true,
|
'col-sm-4 col-xs-12': true,
|
||||||
@ -94,7 +121,8 @@ export class StepChallenge extends PureComponent {
|
|||||||
bsSize='large'
|
bsSize='large'
|
||||||
bsStyle='primary'
|
bsStyle='primary'
|
||||||
className={ btnClass }
|
className={ btnClass }
|
||||||
onClick={ () => !isLastStep ? goToStep(index + 1) : () => {} }>
|
onClick={ this.handleNextClick }
|
||||||
|
>
|
||||||
{ isLastStep ? 'Finish challenge' : 'Go to my next step'}
|
{ isLastStep ? 'Finish challenge' : 'Go to my next step'}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
@ -108,12 +136,14 @@ export class StepChallenge extends PureComponent {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className=''
|
className=''
|
||||||
key={ imgUrl }>
|
key={ imgUrl }
|
||||||
|
>
|
||||||
<a href={ imgUrl }>
|
<a href={ imgUrl }>
|
||||||
<Image
|
<Image
|
||||||
alt={ imgAlt }
|
alt={ imgAlt }
|
||||||
responsive={ true }
|
responsive={ true }
|
||||||
src={ imgUrl } />
|
src={ imgUrl }
|
||||||
|
/>
|
||||||
</a>
|
</a>
|
||||||
<Row>
|
<Row>
|
||||||
<div className='spacer' />
|
<div className='spacer' />
|
||||||
@ -122,10 +152,12 @@ export class StepChallenge extends PureComponent {
|
|||||||
mdOffset={ 2 }
|
mdOffset={ 2 }
|
||||||
sm={ 10 }
|
sm={ 10 }
|
||||||
smOffset={ 1 }
|
smOffset={ 1 }
|
||||||
xs={ 12 }>
|
xs={ 12 }
|
||||||
|
>
|
||||||
<p
|
<p
|
||||||
className='challenge-step-description'
|
className='challenge-step-description'
|
||||||
dangerouslySetInnerHTML={{ __html: info }} />
|
dangerouslySetInnerHTML={{ __html: info }}
|
||||||
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<div className='spacer' />
|
<div className='spacer' />
|
||||||
@ -135,7 +167,8 @@ export class StepChallenge extends PureComponent {
|
|||||||
<Col
|
<Col
|
||||||
className='challenge-step-counter large-p text-center'
|
className='challenge-step-counter large-p text-center'
|
||||||
sm={ 4 }
|
sm={ 4 }
|
||||||
xs={ 12 }>
|
xs={ 12 }
|
||||||
|
>
|
||||||
( { currentStep + 1 } / { numOfSteps })
|
( { currentStep + 1 } / { numOfSteps })
|
||||||
</Col>
|
</Col>
|
||||||
{
|
{
|
||||||
@ -162,16 +195,19 @@ export class StepChallenge extends PureComponent {
|
|||||||
<Image
|
<Image
|
||||||
alt={ imgAlt }
|
alt={ imgAlt }
|
||||||
responsive={ true }
|
responsive={ true }
|
||||||
src={ imgUrl } />
|
src={ imgUrl }
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { challenge, currentStep, isGoingForward } = this.props;
|
const {
|
||||||
const numOfSteps = Array.isArray(challenge.description) ?
|
numOfSteps,
|
||||||
challenge.description.length :
|
challenge,
|
||||||
0;
|
currentStep,
|
||||||
|
isGoingForward
|
||||||
|
} = this.props;
|
||||||
const step = challenge.description[currentStep];
|
const step = challenge.description[currentStep];
|
||||||
const transitionName = 'challenge-step-' +
|
const transitionName = 'challenge-step-' +
|
||||||
(isGoingForward ? 'forward' : 'backward');
|
(isGoingForward ? 'forward' : 'backward');
|
||||||
@ -179,11 +215,13 @@ export class StepChallenge extends PureComponent {
|
|||||||
return (
|
return (
|
||||||
<Col
|
<Col
|
||||||
md={ 8 }
|
md={ 8 }
|
||||||
mdOffset={ 2 }>
|
mdOffset={ 2 }
|
||||||
|
>
|
||||||
<ReactTransitionReplace
|
<ReactTransitionReplace
|
||||||
transitionEnterTimeout={ transitionTimeout }
|
transitionEnterTimeout={ transitionTimeout }
|
||||||
transitionLeaveTimeout={ transitionTimeout }
|
transitionLeaveTimeout={ transitionTimeout }
|
||||||
transitionName={ transitionName }>
|
transitionName={ transitionName }
|
||||||
|
>
|
||||||
{ this.renderStep(step, currentStep, numOfSteps) }
|
{ this.renderStep(step, currentStep, numOfSteps) }
|
||||||
</ReactTransitionReplace>
|
</ReactTransitionReplace>
|
||||||
<div className='hidden'>
|
<div className='hidden'>
|
||||||
|
@ -129,7 +129,7 @@ function submitProject(type, state, { solution, githubLink }) {
|
|||||||
return Observable.merge(saveChallenge$, challengeCompleted$);
|
return Observable.merge(saveChallenge$, challengeCompleted$);
|
||||||
}
|
}
|
||||||
|
|
||||||
function submitSimpleProject(type, state) {
|
function submitSimpleChallenge(type, state) {
|
||||||
const {
|
const {
|
||||||
challenge: { id }
|
challenge: { id }
|
||||||
} = challengeSelector(state);
|
} = challengeSelector(state);
|
||||||
@ -169,9 +169,10 @@ function submitSimpleProject(type, state) {
|
|||||||
|
|
||||||
const submitTypes = {
|
const submitTypes = {
|
||||||
tests: submitModern,
|
tests: submitModern,
|
||||||
|
step: submitSimpleChallenge,
|
||||||
'project.frontEnd': submitProject,
|
'project.frontEnd': submitProject,
|
||||||
'project.backEnd': submitProject,
|
'project.backEnd': submitProject,
|
||||||
'project.simple': submitSimpleProject
|
'project.simple': submitSimpleChallenge
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function completionSaga(actions$, getState) {
|
export default function completionSaga(actions$, getState) {
|
||||||
|
Reference in New Issue
Block a user