Add code storage on code execution
This commit is contained in:
51
client/sagas/code-storage-saga.js
Normal file
51
client/sagas/code-storage-saga.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import store from 'store';
|
||||||
|
|
||||||
|
import types from '../../common/app/routes/challenges/redux/types';
|
||||||
|
import {
|
||||||
|
savedCodeFound
|
||||||
|
} from '../../common/app/routes/challenges/redux/actions';
|
||||||
|
|
||||||
|
const legecyPrefixes = [
|
||||||
|
'Bonfire: ',
|
||||||
|
'Waypoint: ',
|
||||||
|
'Zipline: ',
|
||||||
|
'Basejump: ',
|
||||||
|
'Checkpoint: '
|
||||||
|
];
|
||||||
|
|
||||||
|
function getCode(id, legacy) {
|
||||||
|
if (store.has(id)) {
|
||||||
|
return store.get(id);
|
||||||
|
}
|
||||||
|
if (store.has(legacy)) {
|
||||||
|
const code = '' + store.get(legacy);
|
||||||
|
store.remove(legacy);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
return legecyPrefixes.reduce((code, prefix) => {
|
||||||
|
if (code) {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
return store.get(prefix + legacy + 'Val');
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function codeStorageSaga(actions$, getState) {
|
||||||
|
return actions$
|
||||||
|
.filter(({ type }) => (
|
||||||
|
type === types.saveCode ||
|
||||||
|
type === types.loadCode
|
||||||
|
))
|
||||||
|
.map(({ type }) => {
|
||||||
|
const { id = '', files = {}, legacyKey = '' } = getState().challengesApp;
|
||||||
|
if (type === types.saveCode) {
|
||||||
|
store.set(id, files);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const codeFound = getCode(id, legacyKey);
|
||||||
|
if (codeFound) {
|
||||||
|
return savedCodeFound(codeFound);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
@ -7,7 +7,8 @@ import types from '../../common/app/routes/challenges/redux/types';
|
|||||||
import {
|
import {
|
||||||
frameMain,
|
frameMain,
|
||||||
frameTests,
|
frameTests,
|
||||||
initOutput
|
initOutput,
|
||||||
|
saveCode
|
||||||
} from '../../common/app/routes/challenges/redux/actions';
|
} from '../../common/app/routes/challenges/redux/actions';
|
||||||
import { setExt, updateContents } from '../../common/utils/polyvinyl';
|
import { setExt, updateContents } from '../../common/utils/polyvinyl';
|
||||||
|
|
||||||
@ -116,7 +117,7 @@ export default function executeChallengeSaga(action$, getState) {
|
|||||||
frameMain(payload)
|
frameMain(payload)
|
||||||
];
|
];
|
||||||
if (type === types.executeChallenge) {
|
if (type === types.executeChallenge) {
|
||||||
actions.push(frameTests(payload));
|
actions.push(saveCode(), frameTests(payload));
|
||||||
}
|
}
|
||||||
return Observable.from(actions, null, null, Scheduler.default);
|
return Observable.from(actions, null, null, Scheduler.default);
|
||||||
})
|
})
|
||||||
|
@ -5,6 +5,7 @@ import hardGoToSaga from './hard-go-to-saga';
|
|||||||
import windowSaga from './window-saga';
|
import windowSaga from './window-saga';
|
||||||
import executeChallengeSaga from './execute-challenge-saga';
|
import executeChallengeSaga from './execute-challenge-saga';
|
||||||
import frameSaga from './frame-saga';
|
import frameSaga from './frame-saga';
|
||||||
|
import codeStorageSaga from './code-storage-saga';
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
errSaga,
|
errSaga,
|
||||||
@ -13,5 +14,6 @@ export default [
|
|||||||
hardGoToSaga,
|
hardGoToSaga,
|
||||||
windowSaga,
|
windowSaga,
|
||||||
executeChallengeSaga,
|
executeChallengeSaga,
|
||||||
frameSaga
|
frameSaga,
|
||||||
|
codeStorageSaga
|
||||||
];
|
];
|
||||||
|
@ -8,14 +8,24 @@ import Editor from './Editor.jsx';
|
|||||||
import SidePanel from './Side-Panel.jsx';
|
import SidePanel from './Side-Panel.jsx';
|
||||||
import Preview from './Preview.jsx';
|
import Preview from './Preview.jsx';
|
||||||
import { challengeSelector } from '../../redux/selectors';
|
import { challengeSelector } from '../../redux/selectors';
|
||||||
import { executeChallenge, updateMain, updateFile } from '../../redux/actions';
|
import {
|
||||||
|
executeChallenge,
|
||||||
|
updateMain,
|
||||||
|
updateFile,
|
||||||
|
loadCode
|
||||||
|
} from '../../redux/actions';
|
||||||
|
|
||||||
const mapStateToProps = createSelector(
|
const mapStateToProps = createSelector(
|
||||||
challengeSelector,
|
challengeSelector,
|
||||||
state => state.challengesApp.tests,
|
state => state.challengesApp.tests,
|
||||||
state => state.challengesApp.files,
|
state => state.challengesApp.files,
|
||||||
state => state.challengesApp.key,
|
state => state.challengesApp.key,
|
||||||
({ challenge, showPreview, mode }, tests, files = {}, key = '') => ({
|
(
|
||||||
|
{ showPreview, mode },
|
||||||
|
tests,
|
||||||
|
files = {},
|
||||||
|
key = ''
|
||||||
|
) => ({
|
||||||
content: files[key] && files[key].contents || '',
|
content: files[key] && files[key].contents || '',
|
||||||
file: files[key],
|
file: files[key],
|
||||||
showPreview,
|
showPreview,
|
||||||
@ -24,7 +34,12 @@ const mapStateToProps = createSelector(
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const bindableActions = { executeChallenge, updateFile, updateMain };
|
const bindableActions = {
|
||||||
|
executeChallenge,
|
||||||
|
updateFile,
|
||||||
|
updateMain,
|
||||||
|
loadCode
|
||||||
|
};
|
||||||
|
|
||||||
export class Challenge extends PureComponent {
|
export class Challenge extends PureComponent {
|
||||||
static displayName = 'Challenge';
|
static displayName = 'Challenge';
|
||||||
@ -35,12 +50,15 @@ export class Challenge extends PureComponent {
|
|||||||
mode: PropTypes.string,
|
mode: PropTypes.string,
|
||||||
updateFile: PropTypes.func,
|
updateFile: PropTypes.func,
|
||||||
executeChallenge: PropTypes.func,
|
executeChallenge: PropTypes.func,
|
||||||
updateMain: PropTypes.func
|
updateMain: PropTypes.func,
|
||||||
|
loadCode: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
this.props.loadCode();
|
||||||
this.props.updateMain();
|
this.props.updateMain();
|
||||||
}
|
}
|
||||||
|
|
||||||
renderPreview(showPreview) {
|
renderPreview(showPreview) {
|
||||||
if (!showPreview) {
|
if (!showPreview) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -56,3 +56,8 @@ export const updateTests = createAction(types.updateTests);
|
|||||||
|
|
||||||
export const initOutput = createAction(types.initOutput, loggerToStr);
|
export const initOutput = createAction(types.initOutput, loggerToStr);
|
||||||
export const updateOutput = createAction(types.updateOutput, loggerToStr);
|
export const updateOutput = createAction(types.updateOutput, loggerToStr);
|
||||||
|
|
||||||
|
// code storage
|
||||||
|
export const saveCode = createAction(types.saveCode);
|
||||||
|
export const loadCode = createAction(types.loadCode);
|
||||||
|
export const savedCodeFound = createAction(types.savedCodeFound);
|
||||||
|
@ -12,7 +12,9 @@ import {
|
|||||||
} from '../utils';
|
} from '../utils';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
|
id: '',
|
||||||
challenge: '',
|
challenge: '',
|
||||||
|
legacyKey: '',
|
||||||
currentStep: 0,
|
currentStep: 0,
|
||||||
previousStep: -1,
|
previousStep: -1,
|
||||||
filter: '',
|
filter: '',
|
||||||
@ -29,6 +31,9 @@ const mainReducer = handleActions(
|
|||||||
[types.updateCurrentChallenge]: (state, { payload: challenge }) => ({
|
[types.updateCurrentChallenge]: (state, { payload: challenge }) => ({
|
||||||
...state,
|
...state,
|
||||||
refresh: true,
|
refresh: true,
|
||||||
|
id: challenge.id,
|
||||||
|
// used mainly to find code storage
|
||||||
|
legacyKey: challenge.name,
|
||||||
challenge: challenge.dashedName,
|
challenge: challenge.dashedName,
|
||||||
key: getFileKey(challenge),
|
key: getFileKey(challenge),
|
||||||
tests: createTests(challenge)
|
tests: createTests(challenge)
|
||||||
@ -86,6 +91,9 @@ const filesReducer = handleActions(
|
|||||||
return files;
|
return files;
|
||||||
}, { ...state });
|
}, { ...state });
|
||||||
},
|
},
|
||||||
|
[types.savedCodeFound]: (state, { payload: files }) => ({
|
||||||
|
...files
|
||||||
|
}),
|
||||||
[types.updateCurrentChallenge]: (state, { payload: challenge }) => {
|
[types.updateCurrentChallenge]: (state, { payload: challenge }) => {
|
||||||
if (challenge.type === 'mod') {
|
if (challenge.type === 'mod') {
|
||||||
return challenge.files;
|
return challenge.files;
|
||||||
|
@ -28,5 +28,10 @@ export default createTypes([
|
|||||||
'frameTests',
|
'frameTests',
|
||||||
'updateOutput',
|
'updateOutput',
|
||||||
'initOutput',
|
'initOutput',
|
||||||
'updateTests'
|
'updateTests',
|
||||||
|
|
||||||
|
// code storage
|
||||||
|
'saveCode',
|
||||||
|
'loadCode',
|
||||||
|
'savedCodeFound'
|
||||||
], 'challenges');
|
], 'challenges');
|
||||||
|
Reference in New Issue
Block a user