diff --git a/client/package-lock.json b/client/package-lock.json
index 775d03bb41..7b42127fcf 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -16613,9 +16613,9 @@
}
},
"react-hotkeys": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/react-hotkeys/-/react-hotkeys-2.0.0.tgz",
- "integrity": "sha512-3n3OU8vLX/pfcJrR3xJ1zlww6KS1kEJt0Whxc4FiGV+MJrQ1mYSYI3qS/11d2MJDFm8IhOXMTFQirfu6AVOF6Q==",
+ "version": "2.0.0-pre9",
+ "resolved": "https://registry.npmjs.org/react-hotkeys/-/react-hotkeys-2.0.0-pre9.tgz",
+ "integrity": "sha512-YujzB+kGB5F6rq6/NkNN2t3uSwYfBsC9qWligGKyDe7roMSmzFYO2N88mwSc+9zmHhy/ZrDyB+aqbzVIaK8haw==",
"requires": {
"prop-types": "^15.6.1"
},
diff --git a/client/package.json b/client/package.json
index 8eb26b0134..34d2587b18 100644
--- a/client/package.json
+++ b/client/package.json
@@ -53,7 +53,7 @@
"react-final-form": "^6.3.0",
"react-ga": "^2.6.0",
"react-helmet": "^5.2.1",
- "react-hotkeys": "^2.0.0",
+ "react-hotkeys": "^2.0.0-pre9",
"react-identicons": "^1.1.7",
"react-instantsearch-dom": "^5.7.0",
"react-monaco-editor": "^0.30.1",
diff --git a/client/src/templates/Challenges/classic/Editor.js b/client/src/templates/Challenges/classic/Editor.js
index 8e82b2a873..e496fc83ae 100644
--- a/client/src/templates/Challenges/classic/Editor.js
+++ b/client/src/templates/Challenges/classic/Editor.js
@@ -3,7 +3,6 @@ import PropTypes from 'prop-types';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
-import { navigate } from 'gatsby';
import { executeChallenge, updateFile } from '../redux';
import { userSelector, isDonationModalOpenSelector } from '../../../redux';
@@ -13,13 +12,12 @@ const MonacoEditor = React.lazy(() => import('react-monaco-editor'));
const propTypes = {
canFocus: PropTypes.bool,
+ containerRef: PropTypes.any.isRequired,
contents: PropTypes.string,
dimensions: PropTypes.object,
executeChallenge: PropTypes.func.isRequired,
ext: PropTypes.string,
fileKey: PropTypes.string,
- nextChallengePath: PropTypes.string.isRequired,
- prevChallengePath: PropTypes.string.isRequired,
theme: PropTypes.string,
updateFile: PropTypes.func.isRequired
};
@@ -123,26 +121,13 @@ class Editor extends Component {
run: this.props.executeChallenge
});
this._editor.addAction({
- id: 'navigate-prev',
- label: 'Navigate to previous challenge',
- keybindings: [
- /* eslint-disable no-bitwise */
- monaco.KeyMod.chord(
- monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.US_COMMA
- )
- ],
- run: () => navigate(this.props.prevChallengePath)
- });
- this._editor.addAction({
- id: 'navigate-next',
- label: 'Navigate to next challenge',
- keybindings: [
- /* eslint-disable no-bitwise */
- monaco.KeyMod.chord(
- monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.US_DOT
- )
- ],
- run: () => navigate(this.props.nextChallengePath)
+ id: 'leave-editor',
+ label: 'Leave editor',
+ keybindings: [monaco.KeyCode.Escape],
+ run: () => {
+ if (this.props.containerRef.current)
+ this.props.containerRef.current.focus();
+ }
});
};
diff --git a/client/src/templates/Challenges/classic/Show.js b/client/src/templates/Challenges/classic/Show.js
index eb56ea0d79..409dcaae2d 100644
--- a/client/src/templates/Challenges/classic/Show.js
+++ b/client/src/templates/Challenges/classic/Show.js
@@ -19,6 +19,7 @@ import VideoModal from '../components/VideoModal';
import ResetModal from '../components/ResetModal';
import MobileLayout from './MobileLayout';
import DesktopLayout from './DesktopLayout';
+import Hotkeys from '../components/Hotkeys';
import { getGuideUrl } from '../utils';
import { challengeTypes } from '../../../../utils/challengeTypes';
@@ -32,7 +33,8 @@ import {
initTests,
updateChallengeMeta,
challengeMounted,
- consoleOutputSelector
+ consoleOutputSelector,
+ executeChallenge
} from '../redux';
import './classic.css';
@@ -51,7 +53,8 @@ const mapDispatchToProps = dispatch =>
initConsole,
initTests,
updateChallengeMeta,
- challengeMounted
+ challengeMounted,
+ executeChallenge
},
dispatch
);
@@ -62,6 +65,7 @@ const propTypes = {
data: PropTypes.shape({
challengeNode: ChallengeNode
}),
+ executeChallenge: PropTypes.func.isRequired,
files: PropTypes.shape({
key: PropTypes.string
}),
@@ -99,6 +103,8 @@ class ShowClassic extends Component {
this.state = {
resizing: false
};
+
+ this.containerRef = React.createRef();
}
onResize() {
this.setState({ resizing: true });
@@ -219,19 +225,13 @@ class ShowClassic extends Component {
}
renderEditor() {
- const {
- files,
- pageContext: {
- challengeMeta: { prevChallengePath, nextChallengePath }
- }
- } = this.props;
+ const { files } = this.props;
const challengeFile = first(Object.keys(files).map(key => files[key]));
return (
challengeFile && (