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,