Add data vis certification

This commit is contained in:
Berkeley Martinez
2016-01-11 15:58:37 -08:00
parent f8e06fb2bc
commit a7f04cdc11
8 changed files with 120 additions and 80 deletions

View File

@ -123,6 +123,11 @@
"defaut": false,
"description": "Camper is front end certified"
},
"isDataVisCert": {
"type": "boolean",
"defaut": false,
"description": "Camper is data visualization certified"
},
"isBackEndCert": {
"type": "boolean",
"default": false,

View File

@ -15,6 +15,7 @@ import {
import {
frontEndChallengeId,
dataVisChallengeId,
backEndChallengeId
} from '../utils/constantStrings.json';
@ -22,6 +23,8 @@ import {
completeCommitment$
} from '../utils/commit';
import certTypes from '../utils/certTypes.json';
const debug = debugFactory('freecc:certification');
const sendMessageToNonUser = ifNoUserSend(
'must be logged in to complete.'
@ -35,46 +38,47 @@ function isCertified(ids, { completedChallenges }) {
});
}
function getIdsForCert$(id, Challenge) {
return observeQuery(
Challenge,
'findById',
id,
{
id: true,
tests: true,
name: true,
challengeType: true
}
)
.shareReplay();
}
export default function certificate(app) {
const router = app.loopback.Router();
const { Challenge } = app.models;
const frontEndChallengeIds$ = observeQuery(
Challenge,
'findById',
frontEndChallengeId,
{
id: true,
tests: true,
name: true,
challengeType: true
}
)
.shareReplay();
const backEndChallengeIds$ = observeQuery(
Challenge,
'findById',
backEndChallengeId,
{
id: true,
tests: true,
name: true,
challengeType: true
}
)
.shareReplay();
const certTypeIds = {
[certTypes.frontEnd]: getIdsForCert$(frontEndChallengeId, Challenge),
[certTypes.backEnd]: getIdsForCert$(dataVisChallengeId, Challenge),
[certTypes.dataVis]: getIdsForCert$(backEndChallengeId, Challenge)
};
router.post(
'/certificate/verify/front-end',
ifNoUser401,
verifyCert
verifyCert.bind(null, certTypes.frontEnd)
);
router.post(
'/certificate/verify/back-end',
ifNoUser401,
verifyCert
verifyCert.bind(null, certTypes.backEnd)
);
router.post(
'/certificate/verify/data-visualization',
ifNoUser401,
verifyCert.bind(null, certTypes.dataVis)
);
router.post(
@ -85,14 +89,10 @@ export default function certificate(app) {
app.use(router);
function verifyCert(req, res, next) {
const isFront = req.path.split('/').pop() === 'front-end';
function verifyCert(certType, req, res, next) {
Observable.just({})
.flatMap(() => {
if (isFront) {
return frontEndChallengeIds$;
}
return backEndChallengeIds$;
return certTypeIds[certType];
})
.flatMap(challenge => {
const { user } = req;
@ -103,29 +103,17 @@ export default function certificate(app) {
challengeType
} = challenge;
if (
isFront &&
!user.isFrontEndCert &&
isCertified(tests, user) ||
!isFront &&
!user.isBackEndCert &&
!user[certType] &&
isCertified(tests, user)
) {
debug('certified');
if (isFront) {
user.isFrontEndCert = true;
} else {
user.isBackEndCert = true;
}
user[certType] = true;
user.completedChallenges.push({
id,
name,
completedDate: new Date(),
challengeType
});
return saveUser(user)
// If user has commited to nonprofit,
// this will complete his pledge
@ -146,8 +134,7 @@ export default function certificate(app) {
.subscribe(
user => {
if (
isFront && user.isFrontEndCert ||
!isFront && user.isBackEndCert
user[certType]
) {
return res.status(200).send(true);
}

View File

@ -6,14 +6,37 @@ import debugFactory from 'debug';
import {
frontEndChallengeId,
dataVisChallengeId,
backEndChallengeId
} from '../utils/constantStrings.json';
import certTypes from '../utils/certTypes.json';
import { ifNoUser401, ifNoUserRedirectTo } from '../utils/middleware';
import { observeQuery } from '../utils/rx';
import { calcCurrentStreak, calcLongestStreak } from '../utils/user-stats';
const debug = debugFactory('freecc:boot:user');
const sendNonUserToMap = ifNoUserRedirectTo('/map');
const certIds = {
[certTypes.frontEnd]: frontEndChallengeId,
[certTypes.dataVis]: dataVisChallengeId,
[certTypes.backEnd]: backEndChallengeId
};
const certViews = {
[certTypes.frontEnd]: 'certificate/front-end.jade',
[certTypes.dataVis]: 'certificate/data-vis.jade',
[certTypes.backEnd]: 'certificate/back-end.jade',
[certTypes.fullStack]: 'certificate/full-stack.jade'
};
const certText = {
[certTypes.fronEnd]: 'Front End certified',
[certTypes.dataVis]: 'Data Vis Certified',
[certTypes.backEnd]: 'Back End Certified',
[certTypes.fullStack]: 'Full Stack Certified'
};
function replaceScriptTags(value) {
return value
@ -80,7 +103,17 @@ module.exports = function(app) {
// Ensure these are the last routes!
router.get(
'/:username/front-end-certification',
showCert
showCert.bind(null, certTypes.frontEnd)
);
router.get(
'/:username/data-visualization-certification',
showCert.bind(null, certTypes.dataVis)
);
router.get(
'/:username/back-end-certification',
showCert.bind(null, certTypes.backEnd)
);
router.get(
@ -88,11 +121,6 @@ module.exports = function(app) {
(req, res) => res.redirect(req.url.replace('full-stack', 'back-end'))
);
router.get(
'/:username/back-end-certification',
showCert
);
router.get('/:username', returnUser);
app.use(router);
@ -207,6 +235,7 @@ module.exports = function(app) {
pledge: profileUser.pledge,
isFrontEndCert: profileUser.isFrontEndCert,
isDataVisCert: profileUser.isDataVisCert,
isBackEndCert: profileUser.isBackEndCert,
isFullStackCert: profileUser.isFullStackCert,
isHonest: profileUser.isHonest,
@ -237,11 +266,9 @@ module.exports = function(app) {
);
}
function showCert(req, res, next) {
function showCert(certType, req, res, next) {
const username = req.params.username.toLowerCase();
const { user } = req;
const whichCert = req.path.split('/').pop();
const showFront = whichCert === 'front-end-certification';
Observable.just(user)
.flatMap(user => {
if (user && user.username === username) {
@ -250,8 +277,9 @@ module.exports = function(app) {
return findUserByUsername$(username, {
isGithubCool: true,
isFrontEndCert: true,
isFullStackCert: true,
isDataVisCert: true,
isBackEndCert: true,
isFullStackCert: true,
isHonest: true,
completedChallenges: true,
username: true,
@ -294,33 +322,29 @@ module.exports = function(app) {
return res.redirect('back');
}
if (
showFront && user.isFrontEndCert ||
!showFront && user.isBackEndCert
) {
if (user[certType]) {
// find challenge in user profile
// if not found supply empty object
// if found grab date
// if no date use todays date
var { completedDate = new Date() } =
_.find(user.completedChallenges, {
id: showFront ?
frontEndChallengeId :
backEndChallengeId
}) || {};
_.find(
user.completedChallenges,
{ id: certIds[certType] }
) || {};
return res.render(
showFront ?
'certificate/front-end.jade' :
'certificate/back-end.jade',
certViews[certType],
{
username: user.username,
date: moment(new Date(completedDate))
.format('MMMM, Do YYYY'),
date: moment(new Date(completedDate)).format('MMMM, Do YYYY'),
name: user.name
}
);
}
req.flash('errors', {
msg: showFront ?
`Looks like user ${username} is not Front End certified` :
`Looks like user ${username} is not Back End certified`
msg: `Looks like user ${username} is not ${certText[certType]}`
});
res.redirect('back');
},

View File

@ -0,0 +1,6 @@
{
"frontEnd": "isFrontEndCert",
"backEnd": "isBackEndCert",
"dataVis": "isDataVisCert",
"fullStack": "isFullStackCert"
}

View File

@ -8,7 +8,13 @@ const debug = debugFactory('freecc:utils/commit');
export { commitGoals };
export function completeCommitment$(user) {
const { isFrontEndCert, isFullStackCert } = user;
const {
isFrontEndCert,
isDataVisCert,
isBackEndCert,
isFullStackCert
} = user;
return Observable.fromNodeCallback(user.pledge, user)()
.flatMap(pledge => {
if (!pledge) {
@ -18,8 +24,10 @@ export function completeCommitment$(user) {
const { goal } = pledge;
if (
isFrontEndCert && goal === commitGoals.frontEndCert ||
isFullStackCert && goal === commitGoals.fullStackCert
(isFrontEndCert && goal === commitGoals.frontEndCert) ||
(isDataVisCert && goal === commitGoals.dataVisCert) ||
(isBackEndCert && goal === commitGoals.backEndCert) ||
(isFullStackCert && goal === commitGoals.fullStackCert)
) {
debug('marking goal complete');
pledge.isCompleted = true;

View File

@ -1,5 +1,6 @@
{
"gitHubUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1521.3 Safari/537.36",
"frontEndChallengeId": "561add10cb82ac38a17513be",
"dataVisChallengeId": "561add10cb82ac38a17513b3",
"backEndChallengeId": "660add10cb82ac38a17513be"
}

View File

@ -67,6 +67,9 @@ block content
.spacer
if isFrontEndCert
a.btn.btn-primary(href='/' + username + '/front-end-certification') View My Front End Development Certification
if isDataVisCert
.button-spacer
a.btn.btn-success(href='/' + username + '/data-visualization-certification') View My Data Visualization Certification
if isBackEndCert
.button-spacer
a.btn.btn-success(href='/' + username + '/back-end-certification') View My Back End Development Certification

View File

@ -0,0 +1,6 @@
include font
#name.cert-name= name
img#cert.img-abs(src='http://i.imgur.com/l7tIptn.jpg')
.cert-date= date
.cert-link verify this certification at: http://freecodecamp.com/#{username}/data-vis-certification
include script