2016-03-05 21:06:04 -08:00
|
|
|
import React, { PropTypes } from 'react';
|
|
|
|
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';
|
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,
|
2016-05-27 17:11:25 -07:00
|
|
|
state => state.challengesApp.output,
|
2016-05-13 20:04:56 -07:00
|
|
|
(
|
|
|
|
{ challenge: { title, description } = {} },
|
|
|
|
windowHeight,
|
|
|
|
navHeight,
|
|
|
|
tests,
|
2016-05-27 17:11:25 -07:00
|
|
|
output
|
2016-05-13 20:04:56 -07:00
|
|
|
) => ({
|
|
|
|
title,
|
|
|
|
description,
|
|
|
|
height: windowHeight - navHeight - 20,
|
|
|
|
tests,
|
2016-05-27 17:11:25 -07:00
|
|
|
output
|
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,
|
2016-05-27 17:11:25 -07:00
|
|
|
output: PropTypes.string
|
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 } />
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return (
|
|
|
|
<p
|
|
|
|
className='wrappable'
|
|
|
|
dangerouslySetInnerHTML= {{ __html: line }}
|
|
|
|
key={ line.slice(-6) + index }/>
|
|
|
|
);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
2016-05-27 17:11:25 -07:00
|
|
|
const {
|
|
|
|
title,
|
|
|
|
description,
|
|
|
|
height,
|
|
|
|
tests = [],
|
|
|
|
output
|
|
|
|
} = this.props;
|
2016-03-05 21:06:04 -08:00
|
|
|
const style = {
|
|
|
|
overflowX: 'hidden',
|
|
|
|
overflowY: 'auto'
|
|
|
|
};
|
|
|
|
if (height) {
|
|
|
|
style.height = height + 'px';
|
|
|
|
}
|
|
|
|
return (
|
|
|
|
<div
|
|
|
|
ref='panel'
|
|
|
|
style={ style }>
|
|
|
|
<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 }>
|
|
|
|
{ this.renderDescription(description, this.descriptionRegex) }
|
|
|
|
</Col>
|
|
|
|
</Row>
|
|
|
|
</div>
|
|
|
|
<ToolPanel />
|
2016-05-27 17:11:25 -07:00
|
|
|
<Output output={ output }/>
|
2016-03-05 21:06:04 -08:00
|
|
|
<br />
|
2016-05-27 22:21:52 -07:00
|
|
|
<TestSuite tests={ tests } />
|
2016-03-05 21:06:04 -08:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default connect(mapStateToProps)(SidePanel);
|