Files
freeCodeCamp/common/app/routes/challenges/redux/completion-saga.js

123 lines
3.2 KiB
JavaScript
Raw Normal View History

2016-06-01 15:52:08 -07:00
import { Observable } from 'rx';
2016-06-01 15:52:08 -07:00
import types from './types';
import {
moveToNextChallenge,
clearSavedCode
} from './actions';
2016-06-01 15:52:08 -07:00
import { challengeSelector } from './selectors';
import {
createErrorObservable,
updateUserPoints,
updateUserChallenge
} from '../../../redux/actions';
import { backEndProject } from '../../../utils/challengeTypes';
import { makeToast } from '../../../toasts/redux/actions';
2016-06-01 15:52:08 -07:00
import { postJSON$ } from '../../../../utils/ajax-stream';
function postChallenge(url, username, _csrf, challengeInfo) {
const body = { ...challengeInfo, _csrf };
const saveChallenge$ = postJSON$(url, body)
2016-06-01 15:52:08 -07:00
.retry(3)
.flatMap(({ points, lastUpdated, completedDate }) => {
return Observable.of(
updateUserPoints(username, points),
updateUserChallenge(
username,
{ ...challengeInfo, lastUpdated, completedDate }
),
clearSavedCode()
);
2016-06-01 15:52:08 -07:00
})
.catch(createErrorObservable);
const challengeCompleted$ = Observable.of(moveToNextChallenge());
2016-06-01 15:52:08 -07:00
return Observable.merge(saveChallenge$, challengeCompleted$);
}
2016-06-07 20:41:42 -07:00
function submitModern(type, state) {
const { tests } = state.challengesApp;
if (tests.length > 0 && tests.every(test => test.pass && !test.err)) {
if (type === types.checkChallenge) {
2016-10-17 21:38:16 +01:00
return Observable.just(null);
2016-06-07 20:41:42 -07:00
}
if (type === types.submitChallenge) {
const { challenge: { id } } = challengeSelector(state);
const {
app: { user, csrfToken },
challengesApp: { files }
} = state;
const challengeInfo = { id, files };
return postChallenge(
'/modern-challenge-completed',
user,
csrfToken,
challengeInfo
);
2016-06-07 20:41:42 -07:00
}
}
return Observable.just(
makeToast({ message: 'Keep trying.' })
);
2016-06-07 20:41:42 -07:00
}
2016-06-08 11:11:13 -07:00
function submitProject(type, state, { solution, githubLink }) {
const {
challenge: { id, challengeType }
} = challengeSelector(state);
const {
app: { user, csrfToken }
2016-06-08 11:11:13 -07:00
} = state;
const challengeInfo = { id, challengeType, solution };
2016-06-08 11:11:13 -07:00
if (challengeType === backEndProject) {
challengeInfo.githubLink = githubLink;
2016-06-08 11:11:13 -07:00
}
return postChallenge(
'/project-completed',
user,
csrfToken,
challengeInfo
);
2016-06-07 20:41:42 -07:00
}
2016-06-08 15:40:32 -07:00
function submitSimpleChallenge(type, state) {
const {
challenge: { id }
} = challengeSelector(state);
const {
app: { user, csrfToken }
} = state;
const challengeInfo = { id };
return postChallenge(
'/challenge-completed',
user,
csrfToken,
challengeInfo
);
}
2016-06-07 20:41:42 -07:00
const submitTypes = {
tests: submitModern,
2016-06-08 15:40:32 -07:00
step: submitSimpleChallenge,
video: submitSimpleChallenge,
2016-06-08 11:11:13 -07:00
'project.frontEnd': submitProject,
'project.backEnd': submitProject,
2016-06-08 15:40:32 -07:00
'project.simple': submitSimpleChallenge
2016-06-07 20:41:42 -07:00
};
2016-06-01 15:52:08 -07:00
export default function completionSaga(actions$, getState) {
return actions$
.filter(({ type }) => (
type === types.checkChallenge ||
2016-06-09 16:02:51 -07:00
type === types.submitChallenge
2016-06-01 15:52:08 -07:00
))
2016-06-07 20:41:42 -07:00
.flatMap(({ type, payload }) => {
2016-06-01 15:52:08 -07:00
const state = getState();
2016-06-07 20:41:42 -07:00
const { submitType } = challengeSelector(state);
const submitter = submitTypes[submitType] ||
(() => Observable.just(null));
return submitter(type, state, payload);
2016-06-01 15:52:08 -07:00
});
}