fix(client): update current challenge for all challenges

This commit is contained in:
Valeriy S
2019-02-06 14:30:54 +03:00
committed by Stuart Taylor
parent ba9e45023d
commit f6fa754906
7 changed files with 81 additions and 53 deletions

View File

@ -7,6 +7,7 @@ import { graphql } from 'gatsby';
import {
executeChallenge,
challengeMounted,
challengeTestsSelector,
consoleOutputSelector,
initTests,
@ -42,12 +43,15 @@ const reduxFormPropTypes = {
};
const propTypes = {
challengeMounted: PropTypes.func.isRequired,
description: PropTypes.string,
executeChallenge: PropTypes.func.isRequired,
id: PropTypes.string,
initTests: PropTypes.func.isRequired,
output: PropTypes.string,
tests: PropTypes.array,
title: PropTypes.string,
updateChallengeMeta: PropTypes.func.isRequired,
...reduxFormPropTypes
};
@ -67,6 +71,7 @@ const mapStateToProps = createSelector(
);
const mapDispatchToActions = {
challengeMounted,
executeChallenge,
initTests,
updateChallengeMeta
@ -89,6 +94,7 @@ export class BackEnd extends Component {
componentDidMount() {
const {
challengeMounted,
initTests,
updateChallengeMeta,
data: {
@ -101,6 +107,7 @@ export class BackEnd extends Component {
} = this.props;
initTests(tests);
updateChallengeMeta({ ...challengeMeta, challengeType });
challengeMounted(challengeMeta.id);
window.addEventListener('resize', this.updateDimensions);
}
@ -119,6 +126,7 @@ export class BackEnd extends Component {
}
} = prevProps;
const {
challengeMounted,
initTests,
updateChallengeMeta,
data: {
@ -133,6 +141,7 @@ export class BackEnd extends Component {
if (prevTitle !== currentTitle) {
initTests(tests);
updateChallengeMeta({ ...challengeMeta, challengeType });
challengeMounted(challengeMeta.id);
}
}

View File

@ -166,6 +166,11 @@ class ShowClassic extends Component {
}
}
componentWillUnmount() {
const { createFiles } = this.props;
createFiles({});
}
getChallenge = () => this.props.data.challengeNode;
getBlockNameTitle() {

View File

@ -8,8 +8,8 @@ import Helmet from 'react-helmet';
import { randomCompliment } from '../utils/get-words';
import { ChallengeNode } from '../../../redux/propTypes';
import {
challengeMounted,
updateChallengeMeta,
createFiles,
updateSuccessMessage,
openModal,
updateProjectFormValues
@ -32,7 +32,7 @@ const mapDispatchToProps = dispatch =>
bindActionCreators(
{
updateChallengeMeta,
createFiles,
challengeMounted,
updateProjectFormValues,
updateSuccessMessage,
openCompletionModal: () => openModal('completion')
@ -41,7 +41,7 @@ const mapDispatchToProps = dispatch =>
);
const propTypes = {
createFiles: PropTypes.func.isRequired,
challengeMounted: PropTypes.func.isRequired,
data: PropTypes.shape({
challengeNode: ChallengeNode
}),
@ -57,34 +57,42 @@ const propTypes = {
export class Project extends Component {
componentDidMount() {
const {
createFiles,
data: { challengeNode: { title, challengeType } },
challengeMounted,
data: {
challengeNode: { title, challengeType }
},
pageContext: { challengeMeta },
updateChallengeMeta,
updateSuccessMessage
} = this.props;
createFiles({});
updateSuccessMessage(randomCompliment());
return updateChallengeMeta({ ...challengeMeta, title, challengeType });
updateChallengeMeta({ ...challengeMeta, title, challengeType });
challengeMounted(challengeMeta.id);
}
componentDidUpdate(prevProps) {
const { data: { challengeNode: { title: prevTitle } } } = prevProps;
const {
createFiles,
data: { challengeNode: { title: currentTitle, challengeType } },
data: {
challengeNode: { title: prevTitle }
}
} = prevProps;
const {
challengeMounted,
data: {
challengeNode: { title: currentTitle, challengeType }
},
pageContext: { challengeMeta },
updateChallengeMeta,
updateSuccessMessage
} = this.props;
updateSuccessMessage(randomCompliment());
if (prevTitle !== currentTitle) {
createFiles({});
updateChallengeMeta({
...challengeMeta,
title: currentTitle,
challengeType
});
challengeMounted(challengeMeta.id);
}
}
@ -133,7 +141,10 @@ export class Project extends Component {
Project.displayName = 'Project';
Project.propTypes = propTypes;
export default connect(mapStateToProps, mapDispatchToProps)(Project);
export default connect(
mapStateToProps,
mapDispatchToProps
)(Project);
export const query = graphql`
query ProjectChallenge($slug: String!) {

View File

@ -89,6 +89,10 @@ function saveCodeEpic(action$, state$) {
function loadCodeEpic(action$, state$) {
return action$.pipe(
ofType(types.challengeMounted),
filter(() => {
const files = challengeFilesSelector(state$.value);
return Object.keys(files).length > 0;
}),
switchMap(({ payload: id }) => {
let finalFiles;
const state = state$.value;

View File

@ -1,36 +0,0 @@
import { of } from 'rxjs';
import { ofType } from 'redux-observable';
import { types } from './';
import { filter, switchMap, catchError, mapTo } from 'rxjs/operators';
import {
isSignedInSelector,
currentChallengeIdSelector,
updateComplete,
updateFailed
} from '../../../redux';
import postUpdate$ from '../utils/postUpdate$';
function currentChallengeEpic(action$, state$) {
return action$.pipe(
ofType(types.challengeMounted),
filter(() => isSignedInSelector(state$.value)),
filter(
({ payload }) => payload !== currentChallengeIdSelector(state$.value)
),
switchMap(({ payload }) => {
const update = {
endpoint: '/update-my-current-challenge',
payload: {
currentChallengeId: payload
}
};
return postUpdate$(update).pipe(
mapTo(updateComplete()),
catchError(() => of(updateFailed(update)))
);
})
);
}
export default currentChallengeEpic;

View File

@ -0,0 +1,35 @@
import { put, select, call, takeEvery } from 'redux-saga/effects';
import {
isSignedInSelector,
currentChallengeIdSelector,
updateComplete,
updateFailed
} from '../../../redux';
import { post } from '../../../utils/ajax';
function* currentChallengeSaga({ payload }) {
const isSignedIn = yield select(isSignedInSelector);
const currentChallengeId = yield select(currentChallengeIdSelector);
if (isSignedIn && payload !== currentChallengeId) {
const update = {
endpoint: '/update-my-current-challenge',
payload: {
currentChallengeId: payload
}
};
try {
yield call(post, update.endpoint, update.payload);
yield put(updateComplete());
} catch {
yield put(updateFailed(update));
}
}
}
export function createCurrentChallengeSaga(types) {
return [
takeEvery(types.challengeMounted, currentChallengeSaga)
];
}

View File

@ -10,10 +10,10 @@ import completionEpic from './completion-epic';
import codeLockEpic from './code-lock-epic';
import createQuestionEpic from './create-question-epic';
import codeStorageEpic from './code-storage-epic';
import currentChallengeEpic from './current-challenge-epic';
import { createIdToNameMapSaga } from './id-to-name-map-saga';
import { createExecuteChallengeSaga } from './execute-challenge-saga';
import { createCurrentChallengeSaga } from './current-challenge-saga';
export const ns = 'challenge';
export const backendNS = 'backendChallenge';
@ -85,13 +85,13 @@ export const epics = [
codeLockEpic,
completionEpic,
createQuestionEpic,
codeStorageEpic,
currentChallengeEpic
codeStorageEpic
];
export const sagas = [
...createIdToNameMapSaga(types),
...createExecuteChallengeSaga(types)
...createExecuteChallengeSaga(types),
...createCurrentChallengeSaga(types)
];
export const createFiles = createAction(types.createFiles, challengeFiles =>
@ -300,7 +300,7 @@ export const reducer = handleActions(
...state,
currentTab: payload
}),
[types.executeChallenge]: (state, { payload }) => ({
[types.executeChallenge]: state => ({
...state,
currentTab: 3
})