Files
freeCodeCamp/common/app/routes/challenges/components/classic/Side-Panel.jsx

155 lines
3.7 KiB
JavaScript
Raw Normal View History

2016-03-05 21:06:04 -08:00
import React, { PropTypes } from 'react';
import ReactDom from 'react-dom';
2016-03-05 21:06:04 -08:00
import { createSelector } from 'reselect';
import { connect } from 'react-redux';
import PureComponent from 'react-pure-render/component';
import { Col, Row } from 'react-bootstrap';
import TestSuite from './Test-Suite.jsx';
import Output from './Output.jsx';
import ToolPanel from './Tool-Panel.jsx';
2016-05-13 22:34:40 -07:00
import { challengeSelector } from '../../redux/selectors';
import {
openBugModal,
updateHint,
executeChallenge
} from '../../redux/actions';
import { makeToast } from '../../../../toasts/redux/actions';
2016-07-11 17:44:50 -07:00
import { toggleHelpChat } from '../../../../redux/actions';
2016-03-05 21:06:04 -08:00
2016-07-11 17:44:50 -07:00
const bindableActions = {
makeToast,
executeChallenge,
updateHint,
toggleHelpChat,
openBugModal
2016-07-11 17:44:50 -07:00
};
2016-03-05 21:06:04 -08:00
const mapStateToProps = createSelector(
2016-05-13 20:04:56 -07:00
challengeSelector,
2016-03-05 21:06:04 -08:00
state => state.app.windowHeight,
state => state.app.navHeight,
2016-05-13 20:04:56 -07:00
state => state.challengesApp.tests,
state => state.challengesApp.output,
state => state.challengesApp.hintIndex,
2016-05-13 20:04:56 -07:00
(
{ challenge: { title, description, hints = [] } = {} },
2016-05-13 20:04:56 -07:00
windowHeight,
navHeight,
tests,
output,
hintIndex
2016-05-13 20:04:56 -07:00
) => ({
title,
description,
height: windowHeight - navHeight - 20,
tests,
output,
hint: hints[hintIndex]
2016-05-13 20:04:56 -07:00
})
2016-03-05 21:06:04 -08:00
);
export class SidePanel extends PureComponent {
constructor(...args) {
super(...args);
this.descriptionRegex = /\<blockquote|\<ol|\<h4|\<table/;
}
static displayName = 'SidePanel';
static propTypes = {
description: PropTypes.arrayOf(PropTypes.string),
2016-05-13 20:04:56 -07:00
height: PropTypes.number,
tests: PropTypes.arrayOf(PropTypes.object),
title: PropTypes.string,
output: PropTypes.string,
hints: PropTypes.string,
updateHint: PropTypes.func,
2016-07-11 17:44:50 -07:00
makeToast: PropTypes.func,
toggleHelpChat: PropTypes.func,
openBugModal: PropTypes.func
2016-03-05 21:06:04 -08:00
};
2016-05-13 20:04:56 -07:00
renderDescription(description = [ 'Happy Coding!' ], descriptionRegex) {
2016-03-05 21:06:04 -08:00
return description.map((line, index) => {
if (descriptionRegex.test(line)) {
return (
<div
dangerouslySetInnerHTML={{ __html: line }}
key={ line.slice(-6) + index }
/>
2016-03-05 21:06:04 -08:00
);
}
return (
<p
className='wrappable'
dangerouslySetInnerHTML= {{ __html: line }}
key={ line.slice(-6) + index }
/>
2016-03-05 21:06:04 -08:00
);
});
}
componentWillReceiveProps(nextProps) {
if (this.props.title !== nextProps.title) {
ReactDom.findDOMNode(this).scrollTop = 0;
}
}
2016-03-05 21:06:04 -08:00
render() {
const {
title,
description,
height,
tests = [],
output,
hint,
executeChallenge,
updateHint,
2016-07-11 17:44:50 -07:00
makeToast,
toggleHelpChat,
openBugModal
} = this.props;
2016-07-30 01:04:40 +05:30
const style = {};
2016-03-05 21:06:04 -08:00
if (height) {
style.height = height + 'px';
}
return (
<div
2016-07-30 01:04:40 +05:30
className='challenges-instructions-panel'
2016-03-05 21:06:04 -08:00
ref='panel'
style={ style }
>
2016-03-05 21:06:04 -08:00
<div>
<h4 className='text-center challenge-instructions-title'>
2016-05-13 20:04:56 -07:00
{ title || 'Happy Coding!' }
2016-03-05 21:06:04 -08:00
</h4>
<hr />
<Row>
<Col
className='challenge-instructions'
xs={ 12 }
>
2016-03-05 21:06:04 -08:00
{ this.renderDescription(description, this.descriptionRegex) }
</Col>
</Row>
</div>
<ToolPanel
executeChallenge={ executeChallenge }
hint={ hint }
makeToast={ makeToast }
openBugModal={ openBugModal }
2016-07-11 17:44:50 -07:00
toggleHelpChat={ toggleHelpChat }
updateHint={ updateHint }
/>
<Output output={ output }/>
2016-03-05 21:06:04 -08:00
<br />
<TestSuite tests={ tests } />
2016-03-05 21:06:04 -08:00
</div>
);
}
}
export default connect(
mapStateToProps,
bindableActions
)(SidePanel);