Submit projects

This commit is contained in:
Berkeley Martinez
2016-06-08 11:11:13 -07:00
parent dc36396369
commit c8b0a6cf74
5 changed files with 95 additions and 48 deletions

View File

@ -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'

View File

@ -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) {

View File

@ -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;

View File

@ -86,7 +86,7 @@
"type": "array"
},
"challengeType": {
"type": "string"
"type": "number"
},
"MDNlinks": {
"type": "array"

View File

@ -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 (