fix(client): challenge SSR and styles

This commit is contained in:
Valeriy S
2019-01-23 12:24:05 +03:00
committed by Stuart Taylor
parent 18a42f37cd
commit 4987f986a9
8 changed files with 85 additions and 85 deletions

View File

@ -30,12 +30,16 @@ class Header extends Component {
<header className={this.state.isMenuOpened ? 'opened' : null}> <header className={this.state.isMenuOpened ? 'opened' : null}>
<nav id='top-nav'> <nav id='top-nav'>
<Media query='(min-width: 735px)'> <Media query='(min-width: 735px)'>
<Fragment> {matches =>
<Link className='home-link' to='/'> matches && (
<NavLogo /> <Fragment>
</Link> <Link className='home-link' to='/'>
{disableSettings ? null : <FCCSearch />} <NavLogo />
</Fragment> </Link>
{disableSettings ? null : <FCCSearch />}
</Fragment>
)
}
</Media> </Media>
<ul id='top-right-nav'> <ul id='top-right-nav'>
@ -58,16 +62,20 @@ class Header extends Component {
</ul> </ul>
</nav> </nav>
<Media query='(max-width: 734px)'> <Media defaultMatches={false} query='(max-width: 734px)'>
<div className='mobile-menu'> {matches =>
<Link className='home-link' to='/'> matches && (
<NavLogo /> <div className='mobile-menu'>
</Link> <Link className='home-link' to='/'>
{disableSettings ? null : <FCCSearch />} <NavLogo />
<span className='menu-button' onClick={this.toggleClass}> </Link>
Menu {disableSettings ? null : <FCCSearch />}
</span> <span className='menu-button' onClick={this.toggleClass}>
</div> Menu
</span>
</div>
)
}
</Media> </Media>
</header> </header>
); );

View File

@ -5,10 +5,7 @@ import { connect } from 'react-redux';
import ToolPanel from '../components/Tool-Panel'; import ToolPanel from '../components/Tool-Panel';
import { createStructuredSelector } from 'reselect'; import { createStructuredSelector } from 'reselect';
import { import { currentTabSelector, moveToTab } from '../redux';
currentTabSelector,
moveToTab,
} from '../redux';
import { bindActionCreators } from 'redux'; import { bindActionCreators } from 'redux';
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
@ -18,24 +15,23 @@ const mapStateToProps = createStructuredSelector({
const mapDispatchToProps = dispatch => const mapDispatchToProps = dispatch =>
bindActionCreators( bindActionCreators(
{ {
moveToTab, moveToTab
}, },
dispatch dispatch
); );
const propTypes = { const propTypes = {
moveToTab: PropTypes.func,
currentTab: PropTypes.number, currentTab: PropTypes.number,
instructions: PropTypes.element,
editor: PropTypes.element, editor: PropTypes.element,
testOutput: PropTypes.element,
hasPreview: PropTypes.bool,
preview: PropTypes.element,
guideUrl: PropTypes.string, guideUrl: PropTypes.string,
hasPreview: PropTypes.bool,
instructions: PropTypes.element,
moveToTab: PropTypes.func,
preview: PropTypes.element,
testOutput: PropTypes.element,
videoUrl: PropTypes.string videoUrl: PropTypes.string
}; };
class MobileLayout extends Component { class MobileLayout extends Component {
render() { render() {
const { const {
@ -60,21 +56,17 @@ class MobileLayout extends Component {
<Tabs <Tabs
activeKey={currentTab} activeKey={currentTab}
defaultActiveKey={1} defaultActiveKey={1}
id='challege-page-tabs' id='challenge-page-tabs'
onSelect={(key) => moveToTab(key)} onSelect={moveToTab}
> >
<TabPane eventKey={1} title='Instructions'> <TabPane eventKey={1} title='Instructions'>
{ instructions } {instructions}
</TabPane> </TabPane>
<TabPane eventKey={2} title='Code' {...editorTabPaneProps}> <TabPane eventKey={2} title='Code' {...editorTabPaneProps}>
<div className='challege-edittor-wrapper'> <div className='challenge-editor-wrapper'>{editor}</div>
{editor}
</div>
</TabPane> </TabPane>
<TabPane eventKey={3} title='Tests' {...editorTabPaneProps}> <TabPane eventKey={3} title='Tests' {...editorTabPaneProps}>
<div className='challege-edittor-wrapper'> <div className='challenge-editor-wrapper'>{testOutput}</div>
{testOutput}
</div>
</TabPane> </TabPane>
{hasPreview && ( {hasPreview && (
<TabPane eventKey={4} title='Preview'> <TabPane eventKey={4} title='Preview'>
@ -82,11 +74,7 @@ class MobileLayout extends Component {
</TabPane> </TabPane>
)} )}
</Tabs> </Tabs>
<ToolPanel <ToolPanel guideUrl={guideUrl} isMobile={true} videoUrl={videoUrl} />
guideUrl={guideUrl}
isMobile={true}
videoUrl={videoUrl}
/>
</Fragment> </Fragment>
); );
} }
@ -95,4 +83,7 @@ class MobileLayout extends Component {
MobileLayout.displayName = 'MobileLayout'; MobileLayout.displayName = 'MobileLayout';
MobileLayout.propTypes = propTypes; MobileLayout.propTypes = propTypes;
export default connect(mapStateToProps, mapDispatchToProps)(MobileLayout); export default connect(
mapStateToProps,
mapDispatchToProps
)(MobileLayout);

View File

@ -72,7 +72,7 @@ const propTypes = {
output: PropTypes.string, output: PropTypes.string,
pageContext: PropTypes.shape({ pageContext: PropTypes.shape({
challengeMeta: PropTypes.shape({ challengeMeta: PropTypes.shape({
nextchallengePath: PropTypes.string nextChallengePath: PropTypes.string
}) })
}), }),
tests: PropTypes.arrayOf( tests: PropTypes.arrayOf(
@ -178,7 +178,9 @@ class ShowClassic extends Component {
} }
getGuideUrl() { getGuideUrl() {
const {fields: { slug }} = this.getChallenge(); const {
fields: { slug }
} = this.getChallenge();
return createGuideUrl(slug); return createGuideUrl(slug);
} }
@ -201,7 +203,7 @@ class ShowClassic extends Component {
const { const {
fields: { blockName }, fields: { blockName },
description, description,
instructions, instructions
} = this.getChallenge(); } = this.getChallenge();
return ( return (
@ -221,8 +223,8 @@ class ShowClassic extends Component {
renderEditor() { renderEditor() {
const { files } = this.props; const { files } = this.props;
const challengeFile = first(Object.keys(files).map(key => files[key])); const challengeFile = first(Object.keys(files).map(key => files[key]));
return challengeFile && ( return (
<Editor {...challengeFile} fileKey={challengeFile.key} /> challengeFile && <Editor {...challengeFile} fileKey={challengeFile.key} />
); );
} }
@ -230,7 +232,7 @@ class ShowClassic extends Component {
const { output } = this.props; const { output } = this.props;
return ( return (
<Output <Output
defaultOutput={` defaultOutput={`
/** /**
* Your test output will go here. * Your test output will go here.
*/ */
@ -242,10 +244,7 @@ class ShowClassic extends Component {
renderPreview() { renderPreview() {
return ( return (
<Preview <Preview className='full-height' disableIframe={this.state.resizing} />
className='full-height'
disableIframe={this.state.resizing}
/>
); );
} }
@ -255,31 +254,33 @@ class ShowClassic extends Component {
<Helmet <Helmet
title={`Learn ${this.getBlockNameTitle()} | freeCodeCamp.org`} title={`Learn ${this.getBlockNameTitle()} | freeCodeCamp.org`}
/> />
<Media query={{ maxWidth: MAX_MOBILE_WIDTH }}> <Media defaultMatches={false} query={{ maxWidth: MAX_MOBILE_WIDTH }}>
{matches => {matches =>
matches matches ? (
? ( <MobileLayout
<MobileLayout editor={this.renderEditor()}
instructions={this.renderInstructionsPanel({ showToolPanel: false })} guideUrl={this.getGuideUrl()}
editor={this.renderEditor()} hasPreview={this.hasPreview()}
testOutput={this.renderTestOutput()} instructions={this.renderInstructionsPanel({
hasPreview={this.hasPreview()} showToolPanel: false
preview={this.renderPreview()} })}
guideUrl={this.getGuideUrl()} preview={this.renderPreview()}
videoUrl={this.getVideoUrl()} testOutput={this.renderTestOutput()}
/> videoUrl={this.getVideoUrl()}
) />
: ( ) : (
<DesktopLayout <DesktopLayout
instructions={this.renderInstructionsPanel({ showToolPanel: true })} challengeFile={this.getChallengeFile()}
editor={this.renderEditor()} editor={this.renderEditor()}
testOutput={this.renderTestOutput()} hasPreview={this.hasPreview()}
hasPreview={this.hasPreview()} instructions={this.renderInstructionsPanel({
preview={this.renderPreview()} showToolPanel: true
resizeProps={this.resizeProps} })}
challengeFile={this.getChallengeFile()} preview={this.renderPreview()}
/> resizeProps={this.resizeProps}
) testOutput={this.renderTestOutput()}
/>
)
} }
</Media> </Media>
<CompletionModal /> <CompletionModal />

View File

@ -31,21 +31,21 @@
letter-spacing: 0.02em; letter-spacing: 0.02em;
} }
#challege-page-tabs .nav-tabs { #challenge-page-tabs .nav-tabs {
margin-left: 2px; margin-left: 2px;
display: flex; display: flex;
} }
#challege-page-tabs .nav-tabs > li { #challenge-page-tabs .nav-tabs > li {
flex: 1; flex: 1;
text-align: center; text-align: center;
} }
#challege-page-tabs .nav-tabs > li > a { #challenge-page-tabs .nav-tabs > li > a {
padding: 5px 10px; padding: 5px 10px;
} }
.challege-edittor-wrapper { .challenge-editor-wrapper {
height: calc(100vh - 112px); height: calc(100vh - 112px);
overflow: hidden; overflow: hidden;
} }

View File

@ -10,7 +10,7 @@
width: 30vh; width: 30vh;
} }
@media screen, (max-width: 767px) { @media screen and (max-width: 767px) {
.challenge-success-modal .btn-lg { .challenge-success-modal .btn-lg {
font-size: 16px; font-size: 16px;
} }

View File

@ -1,4 +1,4 @@
@media screen, (max-width: 767px) { @media screen and (max-width: 767px) {
.help-modal .btn-lg { .help-modal .btn-lg {
font-size: 16px; font-size: 16px;
} }

View File

@ -10,7 +10,7 @@
text-shadow: none; text-shadow: none;
} }
@media screen, (max-width: 767px) { @media screen and (max-width: 767px) {
.reset-modal .btn-lg { .reset-modal .btn-lg {
font-size: 16px; font-size: 16px;
} }

View File

@ -1,4 +1,4 @@
@media screen, (max-width: 767px) { @media screen and (max-width: 767px) {
.intro-layout-container { .intro-layout-container {
padding: 0 10px; padding: 0 10px;
} }