Feature(challenges): challenges define their own requires
This commit is contained in:
@ -1,5 +1,8 @@
|
|||||||
import { Scheduler, Observable } from 'rx';
|
import { Scheduler, Observable } from 'rx';
|
||||||
|
|
||||||
|
import {
|
||||||
|
challengeSelector
|
||||||
|
} from '../../common/app/routes/challenges/redux/selectors';
|
||||||
import { ajax$ } from '../../common/utils/ajax-stream';
|
import { ajax$ } from '../../common/utils/ajax-stream';
|
||||||
import throwers from '../rechallenge/throwers';
|
import throwers from '../rechallenge/throwers';
|
||||||
import transformers from '../rechallenge/transformers';
|
import transformers from '../rechallenge/transformers';
|
||||||
@ -25,10 +28,7 @@ const globalRequires = [{
|
|||||||
link: 'https://cdnjs.cloudflare.com/' +
|
link: 'https://cdnjs.cloudflare.com/' +
|
||||||
'ajax/libs/normalize/4.2.0/normalize.min.css'
|
'ajax/libs/normalize/4.2.0/normalize.min.css'
|
||||||
}, {
|
}, {
|
||||||
src: '/bower_components/jquery/dist/jquery.js',
|
src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.js'
|
||||||
script: true,
|
|
||||||
type: 'global',
|
|
||||||
crossDomain: false
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
const scriptCache = new Map();
|
const scriptCache = new Map();
|
||||||
@ -36,7 +36,7 @@ const linkCache = new Map();
|
|||||||
|
|
||||||
function cacheScript({ src } = {}, crossDomain = true) {
|
function cacheScript({ src } = {}, crossDomain = true) {
|
||||||
if (!src) {
|
if (!src) {
|
||||||
return Observable.throw(new Error('No source provided for script'));
|
throw new Error('No source provided for script');
|
||||||
}
|
}
|
||||||
if (scriptCache.has(src)) {
|
if (scriptCache.has(src)) {
|
||||||
return scriptCache.get(src);
|
return scriptCache.get(src);
|
||||||
@ -49,7 +49,6 @@ function cacheScript({ src } = {}, crossDomain = true) {
|
|||||||
})
|
})
|
||||||
.map(({ response }) => response)
|
.map(({ response }) => response)
|
||||||
.map(script => `<script>${script}</script>`)
|
.map(script => `<script>${script}</script>`)
|
||||||
.catch(createErrorObservable)
|
|
||||||
.shareReplay();
|
.shareReplay();
|
||||||
|
|
||||||
scriptCache.set(src, script$);
|
scriptCache.set(src, script$);
|
||||||
@ -71,7 +70,7 @@ function cacheLink({ link } = {}, crossDomain = true) {
|
|||||||
})
|
})
|
||||||
.map(({ response }) => response)
|
.map(({ response }) => response)
|
||||||
.map(script => `<style>${script}</style>`)
|
.map(script => `<style>${script}</style>`)
|
||||||
.catch(createErrorObservable)
|
.catch(() => Observable.just(''))
|
||||||
.shareReplay();
|
.shareReplay();
|
||||||
|
|
||||||
linkCache.set(link, link$);
|
linkCache.set(link, link$);
|
||||||
@ -94,8 +93,10 @@ export default function executeChallengeSaga(action$, getState) {
|
|||||||
))
|
))
|
||||||
.debounce(750)
|
.debounce(750)
|
||||||
.flatMapLatest(({ type }) => {
|
.flatMapLatest(({ type }) => {
|
||||||
const { files, required = [] } = getState().challengesApp;
|
const state = getState();
|
||||||
const finalRequires = [...required, ...globalRequires ];
|
const { files } = state.challengesApp;
|
||||||
|
const { challenge: { required = [] } } = challengeSelector(state);
|
||||||
|
const finalRequires = [...globalRequires, ...required ];
|
||||||
return createFileStream(files)
|
return createFileStream(files)
|
||||||
::throwers()
|
::throwers()
|
||||||
::transformers()
|
::transformers()
|
||||||
@ -121,7 +122,7 @@ export default function executeChallengeSaga(action$, getState) {
|
|||||||
.flatMap(source => {
|
.flatMap(source => {
|
||||||
const head$ = Observable.from(finalRequires)
|
const head$ = Observable.from(finalRequires)
|
||||||
.flatMap(required => {
|
.flatMap(required => {
|
||||||
if (required.script) {
|
if (required.src) {
|
||||||
return cacheScript(required, required.crossDomain);
|
return cacheScript(required, required.crossDomain);
|
||||||
}
|
}
|
||||||
if (required.link) {
|
if (required.link) {
|
||||||
|
@ -106,6 +106,25 @@
|
|||||||
"translations": {
|
"translations": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"default": "{}"
|
"default": "{}"
|
||||||
|
},
|
||||||
|
"required": {
|
||||||
|
"type": [{
|
||||||
|
"type": {
|
||||||
|
"link": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Used for css files"
|
||||||
|
},
|
||||||
|
"src": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Used for script files"
|
||||||
|
},
|
||||||
|
"crossDomain": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Files coming from FreeCodeCamp must mark this true"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"default": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"validations": [],
|
"validations": [],
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
"order": 3,
|
"order": 3,
|
||||||
"time": "5 hours",
|
"time": "5 hours",
|
||||||
"helpRoom": "Help",
|
"helpRoom": "Help",
|
||||||
|
"required": [
|
||||||
|
{ "link": "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css" }
|
||||||
|
],
|
||||||
"challenges": [
|
"challenges": [
|
||||||
{
|
{
|
||||||
"id": "bad87fee1348bd9acde08712",
|
"id": "bad87fee1348bd9acde08712",
|
||||||
|
Reference in New Issue
Block a user