Submit projects
This commit is contained in:
@ -39,7 +39,7 @@ const backEndFieldValidators = {
|
||||
githubLink: makeRequired(isValidURL)
|
||||
};
|
||||
|
||||
export function SolutionInput({ solution }) {
|
||||
export function SolutionInput({ solution, placeholder }) {
|
||||
return (
|
||||
<FormGroup
|
||||
controlId='solution'
|
||||
@ -47,7 +47,7 @@ export function SolutionInput({ solution }) {
|
||||
>
|
||||
<FormControl
|
||||
name='solution'
|
||||
placeholder='https://codepen.io/your-pen-here'
|
||||
placeholder={ placeholder }
|
||||
type='url'
|
||||
{ ...solution}
|
||||
/>
|
||||
@ -55,7 +55,10 @@ export function SolutionInput({ solution }) {
|
||||
);
|
||||
}
|
||||
|
||||
SolutionInput.propTypes = { solution: PropTypes.object };
|
||||
SolutionInput.propTypes = {
|
||||
solution: PropTypes.object,
|
||||
placeholder: PropTypes.string
|
||||
};
|
||||
|
||||
export function _FrontEndForm({
|
||||
fields,
|
||||
@ -72,7 +75,14 @@ export function _FrontEndForm({
|
||||
name='NewFrontEndProject'
|
||||
onSubmit={ handleSubmit(submitChallenge)}
|
||||
>
|
||||
{ isSubmitting ? <SolutionInput { ...fields }/> : null }
|
||||
{
|
||||
isSubmitting ?
|
||||
<SolutionInput
|
||||
placeholder='https://codepen/your-project'
|
||||
{ ...fields }
|
||||
/> :
|
||||
null
|
||||
}
|
||||
<Button
|
||||
block={ true }
|
||||
bsStyle='primary'
|
||||
@ -113,7 +123,14 @@ export function _BackEndForm({
|
||||
name='NewBackEndProject'
|
||||
onSubmit={ handleSubmit(submitChallenge)}
|
||||
>
|
||||
{ isSubmitting ? <SolutionInput solution={ solution }/> : null }
|
||||
{
|
||||
isSubmitting ?
|
||||
<SolutionInput
|
||||
placeholder='https://your-app.com'
|
||||
solution={ solution }
|
||||
/> :
|
||||
null
|
||||
}
|
||||
{ isSubmitting ?
|
||||
<FormGroup
|
||||
controlId='githubLink'
|
||||
|
@ -15,6 +15,8 @@ import {
|
||||
import { getNextChallenge } from '../utils';
|
||||
import { challengeSelector } from './selectors';
|
||||
|
||||
import { backEndProject } from '../../../utils/challengeTypes';
|
||||
import { randomCompliment } from '../../../utils/get-words';
|
||||
import { postJSON$ } from '../../../../utils/ajax-stream';
|
||||
|
||||
function completedChallenge(state) {
|
||||
@ -84,13 +86,53 @@ function submitModern(type, state) {
|
||||
}));
|
||||
}
|
||||
|
||||
function submitFrontEnd() {
|
||||
return Observable.just(null);
|
||||
function submitProject(type, state, { solution, githubLink }) {
|
||||
const {
|
||||
challenge: { id, challengeType }
|
||||
} = challengeSelector(state);
|
||||
const {
|
||||
app: { isSignedIn, csrfToken }
|
||||
} = state;
|
||||
const body = {
|
||||
id,
|
||||
challengeType,
|
||||
solution,
|
||||
_csrf: csrfToken
|
||||
};
|
||||
if (challengeType === backEndProject) {
|
||||
body.githubLink = githubLink;
|
||||
}
|
||||
const saveChallenge$ = postJSON$('/project-completed', body)
|
||||
.retry(3)
|
||||
.flatMap(({ alreadyCompleted, points }) => {
|
||||
return Observable.of(
|
||||
makeToast({
|
||||
message:
|
||||
'Challenge saved.' +
|
||||
(alreadyCompleted ? '' : ' First time Completed!'),
|
||||
title: 'Saved',
|
||||
type: 'info'
|
||||
}),
|
||||
updatePoints(points)
|
||||
);
|
||||
})
|
||||
.catch(createErrorObservable);
|
||||
|
||||
const challengeCompleted$ = Observable.of(
|
||||
makeToast({
|
||||
title: randomCompliment(),
|
||||
message: isSignedIn ? ' Saving...' : 'Moving on to next challenge.',
|
||||
type: 'success'
|
||||
})
|
||||
// moveToNextChallenge()
|
||||
);
|
||||
return Observable.merge(saveChallenge$, challengeCompleted$);
|
||||
}
|
||||
|
||||
const submitTypes = {
|
||||
tests: submitModern,
|
||||
'project.frontEnd': submitFrontEnd
|
||||
'project.frontEnd': submitProject,
|
||||
'project.backEnd': submitProject
|
||||
};
|
||||
|
||||
export default function completionSaga(actions$, getState) {
|
||||
|
@ -1,11 +1,11 @@
|
||||
export const html = '0';
|
||||
export const js = '1';
|
||||
export const oldVideo = '2';
|
||||
export const simpleProject = '2';
|
||||
export const zipline = '3';
|
||||
export const frontEndProject = '3';
|
||||
export const basejump = '4';
|
||||
export const backEndProject = '4';
|
||||
export const bonfire = '5';
|
||||
export const video = '6';
|
||||
export const step = '7';
|
||||
export const html = 0;
|
||||
export const js = 1;
|
||||
export const oldVideo = 2;
|
||||
export const simpleProject = 2;
|
||||
export const zipline = 3;
|
||||
export const frontEndProject = 3;
|
||||
export const basejump = 4;
|
||||
export const backEndProject = 4;
|
||||
export const bonfire = 5;
|
||||
export const video = 6;
|
||||
export const step = 7;
|
||||
|
@ -86,7 +86,7 @@
|
||||
"type": "array"
|
||||
},
|
||||
"challengeType": {
|
||||
"type": "string"
|
||||
"type": "number"
|
||||
},
|
||||
"MDNlinks": {
|
||||
"type": "array"
|
||||
|
@ -69,15 +69,23 @@ module.exports = function(app) {
|
||||
);
|
||||
|
||||
router.post(
|
||||
'/completed-challenge/',
|
||||
'/completed-challenge',
|
||||
send200toNonUser,
|
||||
completedChallenge
|
||||
);
|
||||
|
||||
// deprecate endpoint
|
||||
// remove once new endpoint is live
|
||||
router.post(
|
||||
'/completed-zipline-or-basejump',
|
||||
send200toNonUser,
|
||||
completedZiplineOrBasejump
|
||||
projectCompleted
|
||||
);
|
||||
|
||||
router.post(
|
||||
'/project-completed',
|
||||
send200toNonUser,
|
||||
projectCompleted
|
||||
);
|
||||
|
||||
app.use(router);
|
||||
@ -136,9 +144,6 @@ module.exports = function(app) {
|
||||
|
||||
function completedChallenge(req, res, next) {
|
||||
req.checkBody('id', 'id must be an ObjectId').isMongoId();
|
||||
req.checkBody('name', 'name must be at least 3 characters')
|
||||
.isString()
|
||||
.isLength({ min: 3 });
|
||||
req.checkBody('challengeType', 'challengeType must be an integer')
|
||||
.isNumber();
|
||||
|
||||
@ -158,24 +163,12 @@ module.exports = function(app) {
|
||||
return req.user.getChallengeMap$()
|
||||
.flatMap(() => {
|
||||
const completedDate = Date.now();
|
||||
const {
|
||||
id,
|
||||
name,
|
||||
challengeType,
|
||||
solution,
|
||||
timezone
|
||||
} = req.body;
|
||||
const { id, solution, timezone } = req.body;
|
||||
|
||||
const { alreadyCompleted, updateData } = buildUserUpdate(
|
||||
req.user,
|
||||
id,
|
||||
{
|
||||
id,
|
||||
challengeType,
|
||||
solution,
|
||||
name,
|
||||
completedDate
|
||||
},
|
||||
{ id, solution, completedDate },
|
||||
timezone
|
||||
);
|
||||
|
||||
@ -197,15 +190,11 @@ module.exports = function(app) {
|
||||
.subscribe(() => {}, next);
|
||||
}
|
||||
|
||||
function completedZiplineOrBasejump(req, res, next) {
|
||||
function projectCompleted(req, res, next) {
|
||||
const type = accepts(req).type('html', 'json', 'text');
|
||||
req.checkBody('id', 'id must be an ObjectId').isMongoId();
|
||||
req.checkBody('name', 'Name must be at least 3 characters')
|
||||
.isString()
|
||||
.isLength({ min: 3 });
|
||||
req.checkBody('challengeType', 'must be a number')
|
||||
.isNumber();
|
||||
req.checkBody('solution', 'solution must be a url').isURL();
|
||||
req.checkBody('challengeType', 'must be a number').isNumber();
|
||||
req.checkBody('solution', 'solution must be a URL').isURL();
|
||||
|
||||
const errors = req.validationErrors(true);
|
||||
|
||||
@ -221,9 +210,8 @@ module.exports = function(app) {
|
||||
|
||||
const completedChallenge = _.pick(
|
||||
body,
|
||||
[ 'id', 'name', 'solution', 'githubLink', 'challengeType' ]
|
||||
[ 'id', 'solution', 'githubLink', 'challengeType' ]
|
||||
);
|
||||
completedChallenge.challengeType = +completedChallenge.challengeType;
|
||||
completedChallenge.completedDate = Date.now();
|
||||
|
||||
if (
|
||||
|
Reference in New Issue
Block a user