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