fix(challenges): Add logic to toggle editor theme

Closes #16284
This commit is contained in:
huyenltnguyen
2018-01-15 13:01:49 +07:00
parent 49a5911fca
commit e1bda08c59
6 changed files with 34 additions and 32 deletions

View File

@ -10,8 +10,7 @@ const defaultOptions = {
lineNumbers: false, lineNumbers: false,
lineWrapping: true, lineWrapping: true,
mode: 'javascript', mode: 'javascript',
readOnly: 'nocursor', readOnly: 'nocursor'
theme: 'monokai'
}; };
const propTypes = { const propTypes = {

View File

@ -117,6 +117,10 @@
caret-color:#ABABAB; caret-color:#ABABAB;
} }
} }
.@{ns}-log .CodeMirror {
background-color: #282a36;
color: #f8f8f2;
}
.refresh-icon { .refresh-icon {
color: @icon-light-gray; color: @icon-light-gray;
} }

View File

@ -15,6 +15,8 @@ import {
challengeMetaSelector challengeMetaSelector
} from '../../redux'; } from '../../redux';
import { themeSelector } from '../../../../redux';
import { createFileSelector } from '../../../../files'; import { createFileSelector } from '../../../../files';
const envProps = typeof window !== 'undefined' ? Object.keys(window) : []; const envProps = typeof window !== 'undefined' ? Object.keys(window) : [];
@ -36,13 +38,16 @@ const options = {
const mapStateToProps = createSelector( const mapStateToProps = createSelector(
createFileSelector((_, { fileKey }) => fileKey || ''), createFileSelector((_, { fileKey }) => fileKey || ''),
challengeMetaSelector, challengeMetaSelector,
themeSelector,
( (
file, file,
{ mode } { mode },
theme
) => ({ ) => ({
content: file.contents || '// Happy Coding!', content: file.contents || '// Happy Coding!',
file: file, file: file,
mode: file.ext || mode || 'javascript' mode: file.ext || mode || 'javascript',
theme
}) })
); );
@ -56,15 +61,18 @@ const propTypes = {
executeChallenge: PropTypes.func.isRequired, executeChallenge: PropTypes.func.isRequired,
fileKey: PropTypes.string, fileKey: PropTypes.string,
mode: PropTypes.string, mode: PropTypes.string,
modernEditorUpdated: PropTypes.func.isRequired modernEditorUpdated: PropTypes.func.isRequired,
theme: PropTypes.string
}; };
export class Editor extends PureComponent { export class Editor extends PureComponent {
createOptions = createSelector( createOptions = createSelector(
state => state.executeChallenge, state => state.executeChallenge,
state => state.mode, state => state.mode,
(executeChallenge, mode) => ({ state => state.cmTheme,
(executeChallenge, mode, cmTheme) => ({
...options, ...options,
theme: cmTheme,
mode, mode,
// JSHint only works with javascript // JSHint only works with javascript
// we will need to switch to eslint to make this work with jsx // we will need to switch to eslint to make this work with jsx
@ -119,6 +127,7 @@ export class Editor extends PureComponent {
fileKey, fileKey,
mode mode
} = this.props; } = this.props;
const cmTheme = this.props.theme === 'default' ? 'default' : 'dracula';
return ( return (
<div <div
className={ `${ns}-editor` } className={ `${ns}-editor` }
@ -127,7 +136,7 @@ export class Editor extends PureComponent {
<NoSSR onSSR={ <CodeMirrorSkeleton content={ content } /> }> <NoSSR onSSR={ <CodeMirrorSkeleton content={ content } /> }>
<Codemirror <Codemirror
onChange={ content => modernEditorUpdated(fileKey, content) } onChange={ content => modernEditorUpdated(fileKey, content) }
options={ this.createOptions({ executeChallenge, mode }) } options={ this.createOptions({ executeChallenge, mode, cmTheme }) }
ref='editor' ref='editor'
value={ content } value={ content }
/> />

View File

@ -16,6 +16,8 @@ import {
keySelector keySelector
} from '../../redux'; } from '../../redux';
import { themeSelector } from '../../../../redux';
import { filesSelector } from '../../../../files'; import { filesSelector } from '../../../../files';
const envProps = typeof window !== 'undefined' ? Object.keys(window) : []; const envProps = typeof window !== 'undefined' ? Object.keys(window) : [];
@ -38,15 +40,18 @@ const mapStateToProps = createSelector(
filesSelector, filesSelector,
challengeMetaSelector, challengeMetaSelector,
keySelector, keySelector,
themeSelector,
( (
files = {}, files = {},
{ mode = 'javascript'}, { mode = 'javascript'},
key key,
theme
) => ({ ) => ({
content: files[key] && files[key].contents || '// Happy Coding!', content: files[key] && files[key].contents || '// Happy Coding!',
file: files[key], file: files[key],
fileKey: key, fileKey: key,
mode mode,
theme
}) })
); );
@ -60,15 +65,18 @@ const propTypes = {
content: PropTypes.string, content: PropTypes.string,
executeChallenge: PropTypes.func.isRequired, executeChallenge: PropTypes.func.isRequired,
fileKey: PropTypes.string.isRequired, fileKey: PropTypes.string.isRequired,
mode: PropTypes.string mode: PropTypes.string,
theme: PropTypes.string
}; };
export class Editor extends PureComponent { export class Editor extends PureComponent {
createOptions = createSelector( createOptions = createSelector(
state => state.executeChallenge, state => state.executeChallenge,
state => state.mode, state => state.mode,
(executeChallenge, mode) => ({ state => state.cmTheme,
(executeChallenge, mode, cmTheme) => ({
...options, ...options,
theme: cmTheme,
mode, mode,
extraKeys: { extraKeys: {
Esc() { Esc() {
@ -120,6 +128,7 @@ export class Editor extends PureComponent {
classicEditorUpdated, classicEditorUpdated,
mode mode
} = this.props; } = this.props;
const cmTheme = this.props.theme === 'default' ? 'default' : 'dracula';
return ( return (
<div <div
className={ `${ns}-editor` } className={ `${ns}-editor` }
@ -128,7 +137,7 @@ export class Editor extends PureComponent {
<NoSSR onSSR={ <CodeMirrorSkeleton content={ content } /> }> <NoSSR onSSR={ <CodeMirrorSkeleton content={ content } /> }>
<Codemirror <Codemirror
onChange={ change => classicEditorUpdated(fileKey, change) } onChange={ change => classicEditorUpdated(fileKey, change) }
options={ this.createOptions({ executeChallenge, mode }) } options={ this.createOptions({ executeChallenge, mode, cmTheme }) }
ref='editor' ref='editor'
value={ content } value={ content }
/> />

View File

@ -16,26 +16,6 @@
padding-right: 5px; padding-right: 5px;
} }
.night {
.@{ns}-editor .CodeMirror {
background-color:#242424;
color:#ABABAB;
&-gutters {
background-color:#242424;
color:#ABABAB;
}
.cm-bracket, .cm-tag {
color:#5CAFD6;
}
.cm-property, .cm-string {
color:#B5753A;
}
.cm-keyword, .cm-attribute {
color:#9BBBDC;
}
}
}
.@{ns}-editor { .@{ns}-editor {
.max-element-height(); .max-element-height();
width: 100%; width: 100%;

View File

@ -2,6 +2,7 @@ link(rel='stylesheet', type='text/css' href='/css/lato.css')
link(rel='stylesheet', type='text/css' href='/css/ubuntu.css') link(rel='stylesheet', type='text/css' href='/css/ubuntu.css')
link(rel='stylesheet', href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css') link(rel='stylesheet', href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css')
link(rel='stylesheet', href='https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.30.0/codemirror.min.css') link(rel='stylesheet', href='https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.30.0/codemirror.min.css')
link(rel='stylesheet', href='https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.30.0/theme/dracula.min.css')
link(rel='stylesheet', href='https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.30.0/addon/lint/lint.min.css') link(rel='stylesheet', href='https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.30.0/addon/lint/lint.min.css')
link(rel='stylesheet', href=rev('/css', 'main.css')) link(rel='stylesheet', href=rev('/css', 'main.css'))