diff --git a/packages/learn/gatsby-node.js b/packages/learn/gatsby-node.js
index 26391d45b1..72cb020fae 100644
--- a/packages/learn/gatsby-node.js
+++ b/packages/learn/gatsby-node.js
@@ -115,6 +115,7 @@ exports.createPages = ({ graphql, boundActionCreators }) => {
component: views[viewTypes[challengeType]],
context: {
challengeMeta: {
+ challengeType,
template,
required,
nextChallengePath,
diff --git a/packages/learn/src/templates/Challenges/backend/Show.js b/packages/learn/src/templates/Challenges/backend/Show.js
index a8323a8a1d..4e1999fb21 100644
--- a/packages/learn/src/templates/Challenges/backend/Show.js
+++ b/packages/learn/src/templates/Challenges/backend/Show.js
@@ -14,7 +14,8 @@ import {
challengeTestsSelector,
consoleOutputSelector,
initTests,
- updateChallengeMeta
+ updateChallengeMeta,
+ backendNS
} from '../redux';
import {
@@ -72,12 +73,7 @@ const options = {
};
export class BackEnd extends PureComponent {
- constructor(...props) {
- super(...props);
-
- this.handleSubmit = this.handleSubmit.bind(this);
- }
- componentDidMount() {
+componentDidMount() {
const {
initTests,
updateChallengeMeta,
@@ -101,18 +97,17 @@ export class BackEnd extends PureComponent {
updateChallengeMeta(challengeMeta);
}
}
- handleSubmit(values) {
- console.log('backend', values);
- }
render() {
const {
data: { challengeNode: { fields: { blockName }, title, description } },
output,
tests,
- submitting
+ submitting,
+ executeChallenge
} = this.props;
+ // TODO: Should be tied to user.isSigned
const buttonCopy = submitting
? 'Submit and go to my next challenge'
: "I've completed this challenge";
@@ -128,9 +123,9 @@ export class BackEnd extends PureComponent {
diff --git a/packages/learn/src/templates/Challenges/project/Tool-Panel.js b/packages/learn/src/templates/Challenges/project/Tool-Panel.js
index 978642cd91..d04772d33b 100644
--- a/packages/learn/src/templates/Challenges/project/Tool-Panel.js
+++ b/packages/learn/src/templates/Challenges/project/Tool-Panel.js
@@ -21,9 +21,7 @@ import ProjectForm from './ProjectForm';
// signInLoadingSelector,
// challengeSelector
// } from '../../../../redux';
-import { challengeTypes } from '../../../../utils/challengeTypes';
-
-const { frontEndProject } = challengeTypes;
+import { frontEndProject } from '../../../../utils/challengeTypes';
const propTypes = {
challengeType: PropTypes.number,
diff --git a/packages/learn/src/templates/Challenges/redux/execute-challenge-epic.js b/packages/learn/src/templates/Challenges/redux/execute-challenge-epic.js
index 3983bfd28f..9d26527315 100644
--- a/packages/learn/src/templates/Challenges/redux/execute-challenge-epic.js
+++ b/packages/learn/src/templates/Challenges/redux/execute-challenge-epic.js
@@ -16,6 +16,7 @@ import _ from 'lodash';
import {
types,
+ challengeMetaSelector,
challengeTestsSelector,
initConsole,
updateConsole,
@@ -23,13 +24,15 @@ import {
updateTests,
disableJSOnError
} from './';
-import { buildFromFiles } from '../utils/build';
+import { buildFromFiles, buildBackendChallenge } from '../utils/build';
import {
runTestsInTestFrame,
createTestFramer,
createMainFramer
} from '../utils/frame.js';
+import { backend } from '../../../../utils/challengeTypes';
+
const executeDebounceTimeout = 750;
function updateMainEpic(actions, { getState }, { document }) {
@@ -90,14 +93,14 @@ function executeChallengeEpic(action$, { getState }, { document }) {
// .filter(() => !codeLockedSelector(getState()))
switchMap(() => {
const state = getState();
- // const { challengeType } = challengeSelector(state);
- // if (challengeType === backend) {
- // return buildBackendChallenge(state)
- // .do(frameTests)
- // .ignoreElements()
- // .startWith(initOutput('// running test'))
- // .catch(createErrorObservable);
- // }
+ const { challengeType } = challengeMetaSelector(state);
+ if (challengeType === backend) {
+ return buildBackendChallenge(state)
+ .do(frameTests)
+ .ignoreElements()
+ .startWith(initConsole('// running test'))
+ .catch(err => disableJSOnError(err));
+ }
return buildFromFiles(state, false)
.do(frameTests)
.ignoreElements()
diff --git a/packages/learn/src/templates/Challenges/redux/index.js b/packages/learn/src/templates/Challenges/redux/index.js
index eb39ae917c..88b4580116 100644
--- a/packages/learn/src/templates/Challenges/redux/index.js
+++ b/packages/learn/src/templates/Challenges/redux/index.js
@@ -8,6 +8,7 @@ import executeChallengeEpic from './execute-challenge-epic';
import codeLockEpic from './code-lock-epic';
const ns = 'challenge';
+export const backendNS = 'backendChallenge';
const initialState = {
challengeFiles: {},
@@ -95,6 +96,7 @@ export const checkChallenge = createAction(types.checkChallenge);
export const executeChallenge = createAction(types.executeChallenge);
export const submitChallenge = createAction(types.submitChallenge);
+export const backendFormValuesSelector = state => state.form[backendNS];
export const challengeFilesSelector = state => state[ns].challengeFiles;
export const challengeMetaSelector = state => state[ns].challengeMeta;
export const challengeTestsSelector = state => state[ns].challengeTests;
diff --git a/packages/learn/src/templates/Challenges/utils/build.js b/packages/learn/src/templates/Challenges/utils/build.js
index ceeff39e09..0d95cf33d3 100644
--- a/packages/learn/src/templates/Challenges/utils/build.js
+++ b/packages/learn/src/templates/Challenges/utils/build.js
@@ -1,12 +1,15 @@
+import { combineLatest } from 'rxjs/observable/combineLatest';
+import { map } from 'rxjs/operators/map';
import identity from 'lodash/identity';
-// import { fetchScript } from './fetch-and-cache.js';
+import { fetchScript } from './fetch-and-cache.js';
import throwers from '../rechallenge/throwers';
import {
challengeFilesSelector,
isJSEnabledSelector,
challengeMetaSelector,
- disableJSOnError
+ disableJSOnError,
+ backendFormValuesSelector
} from '../redux';
import {
applyTransformers,
@@ -19,11 +22,11 @@ import { createFileStream, pipe } from './polyvinyl';
const jQuery = {
src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js'
};
-// const frameRunner = {
-// src: '/js/frame-runner.js',
-// crossDomain: false,
-// cacheBreaker: true
-// };
+const frameRunner = {
+ src: '/js/frame-runner.js',
+ crossDomain: false,
+ cacheBreaker: true
+};
const globalRequires = [
{
link:
@@ -56,14 +59,16 @@ export function buildFromFiles(state, shouldProxyConsole) {
.catch(err => disableJSOnError(err));
}
-// export function buildBackendChallenge(state) {
-// const { solution: url } = backendFormValuesSelector(state);
-// return Observable.combineLatest(
-// fetchScript(frameRunner),
-// fetchScript(jQuery)
-// ).map(([frameRunner, jQuery]) => ({
-// build: jQuery + frameRunner,
-// sources: { url },
-// checkChallengePayload: { solution: url }
-// }));
-// }
+export function buildBackendChallenge(state) {
+ const { solution: { value: url } } = backendFormValuesSelector(state);
+ return combineLatest(
+ fetchScript(frameRunner),
+ fetchScript(jQuery)
+ ).pipe(
+ map(([frameRunner, jQuery]) => ({
+ build: jQuery + frameRunner,
+ sources: { url },
+ checkChallengePayload: { solution: url }
+ })
+ ));
+}
diff --git a/packages/learn/src/templates/Challenges/utils/fetch-and-cache.js b/packages/learn/src/templates/Challenges/utils/fetch-and-cache.js
index 203281e94a..36ae631bcd 100644
--- a/packages/learn/src/templates/Challenges/utils/fetch-and-cache.js
+++ b/packages/learn/src/templates/Challenges/utils/fetch-and-cache.js
@@ -1,5 +1,5 @@
import { Observable } from 'rxjs';
-import { ajax$ } from '../utils/ajax-stream';
+import { ajax$ } from './ajax-stream';
// value used to break browser ajax caching
const cacheBreakerValue = Math.random();
diff --git a/packages/learn/utils/challengeTypes.js b/packages/learn/utils/challengeTypes.js
index abee41dc03..166f62d5a7 100644
--- a/packages/learn/utils/challengeTypes.js
+++ b/packages/learn/utils/challengeTypes.js
@@ -10,6 +10,10 @@ const step = 7;
const quiz = 8;
const invalid = 9;
+// individual exports
+exports.backend = backend;
+exports.frontEndProject = frontEndProject;
+
exports.challengeTypes = {
html,
js,