2016-05-09 13:42:39 -07:00
|
|
|
import React, { PropTypes } from 'react';
|
|
|
|
import { compose } from 'redux';
|
|
|
|
import { contain } from 'redux-epic';
|
|
|
|
import { connect } from 'react-redux';
|
|
|
|
import { createSelector } from 'reselect';
|
2016-03-05 21:06:04 -08:00
|
|
|
import PureComponent from 'react-pure-render/component';
|
|
|
|
|
2016-05-13 22:34:40 -07:00
|
|
|
import Classic from './classic/Classic.jsx';
|
2016-03-09 14:43:48 -08:00
|
|
|
import Step from './step/Step.jsx';
|
2016-06-03 18:37:53 -07:00
|
|
|
import Project from './project/Project.jsx';
|
2016-06-13 12:26:30 -07:00
|
|
|
import Video from './video/Video.jsx';
|
2016-06-03 18:37:53 -07:00
|
|
|
|
2016-06-13 21:08:22 -07:00
|
|
|
import {
|
|
|
|
fetchChallenge,
|
|
|
|
fetchChallenges,
|
2016-06-20 21:12:41 -07:00
|
|
|
replaceChallenge,
|
|
|
|
resetUi
|
2016-06-13 21:08:22 -07:00
|
|
|
} from '../redux/actions';
|
2016-05-10 13:17:57 -07:00
|
|
|
import { challengeSelector } from '../redux/selectors';
|
2016-07-20 16:30:39 -07:00
|
|
|
import { updateTitle } from '../../../redux/actions';
|
2016-05-09 13:42:39 -07:00
|
|
|
|
2016-06-03 14:12:56 -07:00
|
|
|
const views = {
|
|
|
|
step: Step,
|
2016-06-03 18:37:53 -07:00
|
|
|
classic: Classic,
|
2016-06-07 20:41:42 -07:00
|
|
|
project: Project,
|
2016-06-13 12:26:30 -07:00
|
|
|
simple: Project,
|
|
|
|
video: Video
|
2016-06-03 14:12:56 -07:00
|
|
|
};
|
|
|
|
|
2016-05-09 13:42:39 -07:00
|
|
|
const bindableActions = {
|
2016-06-01 15:52:08 -07:00
|
|
|
fetchChallenge,
|
2016-06-13 21:08:22 -07:00
|
|
|
fetchChallenges,
|
2016-06-20 21:12:41 -07:00
|
|
|
replaceChallenge,
|
2016-07-20 16:30:39 -07:00
|
|
|
resetUi,
|
|
|
|
updateTitle
|
2016-05-09 13:42:39 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
const mapStateToProps = createSelector(
|
|
|
|
challengeSelector,
|
2016-05-10 13:17:57 -07:00
|
|
|
state => state.challengesApp.challenge,
|
2016-06-20 21:08:07 -07:00
|
|
|
state => state.challengesApp.superBlocks,
|
2016-08-05 20:51:52 -07:00
|
|
|
({ challenge: { title } = {}, viewType }, challenge, superBlocks = []) => ({
|
|
|
|
title,
|
2016-06-03 14:12:56 -07:00
|
|
|
challenge,
|
2016-06-20 21:08:07 -07:00
|
|
|
viewType,
|
|
|
|
areChallengesLoaded: superBlocks.length > 0
|
2016-06-03 14:12:56 -07:00
|
|
|
})
|
2016-05-09 13:42:39 -07:00
|
|
|
);
|
2016-03-09 14:43:48 -08:00
|
|
|
|
2016-05-09 13:42:39 -07:00
|
|
|
const fetchOptions = {
|
|
|
|
fetchAction: 'fetchChallenge',
|
2016-06-09 16:02:51 -07:00
|
|
|
getActionArgs({ params: { block, dashedName } }) {
|
|
|
|
return [ dashedName, block ];
|
2016-05-09 13:42:39 -07:00
|
|
|
},
|
|
|
|
isPrimed({ challenge }) {
|
2016-05-10 13:17:57 -07:00
|
|
|
return !!challenge;
|
2016-05-09 13:42:39 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
export class Challenges extends PureComponent {
|
2016-03-05 21:06:04 -08:00
|
|
|
static displayName = 'Challenges';
|
2016-06-13 21:08:22 -07:00
|
|
|
|
2016-06-01 15:52:08 -07:00
|
|
|
static propTypes = {
|
2016-08-05 20:51:52 -07:00
|
|
|
title: PropTypes.string,
|
2016-09-02 22:09:21 -07:00
|
|
|
viewType: PropTypes.string,
|
2016-06-01 15:52:08 -07:00
|
|
|
isStep: PropTypes.bool,
|
2016-07-20 16:30:39 -07:00
|
|
|
fetchChallenges: PropTypes.func.isRequired,
|
|
|
|
replaceChallenge: PropTypes.func.isRequired,
|
|
|
|
params: PropTypes.object.isRequired,
|
2016-06-20 21:12:41 -07:00
|
|
|
areChallengesLoaded: PropTypes.bool,
|
2016-07-20 16:30:39 -07:00
|
|
|
resetUi: PropTypes.func.isRequired,
|
|
|
|
updateTitle: PropTypes.func.isRequired
|
2016-06-01 15:52:08 -07:00
|
|
|
};
|
2016-03-05 21:06:04 -08:00
|
|
|
|
2016-07-20 16:30:39 -07:00
|
|
|
componentWillMount() {
|
2016-08-05 20:51:52 -07:00
|
|
|
this.props.updateTitle(this.props.title);
|
2016-06-20 21:12:41 -07:00
|
|
|
}
|
2016-07-20 16:30:39 -07:00
|
|
|
|
2016-06-01 15:52:08 -07:00
|
|
|
componentDidMount() {
|
2016-06-20 21:08:07 -07:00
|
|
|
if (!this.props.areChallengesLoaded) {
|
|
|
|
this.props.fetchChallenges();
|
|
|
|
}
|
2016-06-01 15:52:08 -07:00
|
|
|
}
|
|
|
|
|
2016-07-20 16:30:39 -07:00
|
|
|
componentWillUnmount() {
|
|
|
|
this.props.resetUi();
|
|
|
|
}
|
|
|
|
|
2016-06-13 21:08:22 -07:00
|
|
|
componentWillReceiveProps(nextProps) {
|
2016-07-20 16:30:39 -07:00
|
|
|
const { block, dashedName } = nextProps.params;
|
|
|
|
const { resetUi, updateTitle, replaceChallenge } = this.props;
|
|
|
|
if (this.props.params.dashedName !== dashedName) {
|
2016-08-05 20:51:52 -07:00
|
|
|
updateTitle(nextProps.title);
|
2016-07-20 16:30:39 -07:00
|
|
|
resetUi();
|
|
|
|
replaceChallenge({ dashedName, block });
|
2016-06-13 21:08:22 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-03 14:12:56 -07:00
|
|
|
renderView(viewType) {
|
|
|
|
const View = views[viewType] || Classic;
|
|
|
|
return <View />;
|
2016-03-05 21:06:04 -08:00
|
|
|
}
|
2016-06-01 15:52:08 -07:00
|
|
|
|
|
|
|
render() {
|
2016-06-03 14:12:56 -07:00
|
|
|
const { viewType } = this.props;
|
2016-06-01 15:52:08 -07:00
|
|
|
return (
|
|
|
|
<div>
|
2016-06-03 14:12:56 -07:00
|
|
|
{ this.renderView(viewType) }
|
2016-06-01 15:52:08 -07:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
2016-03-05 21:06:04 -08:00
|
|
|
}
|
2016-05-09 13:42:39 -07:00
|
|
|
|
|
|
|
export default compose(
|
|
|
|
connect(mapStateToProps, bindableActions),
|
|
|
|
contain(fetchOptions)
|
|
|
|
)(Challenges);
|