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, "defaut": false,
"description": "Camper is front end certified" "description": "Camper is front end certified"
}, },
"isDataVisCert": {
"type": "boolean",
"defaut": false,
"description": "Camper is data visualization certified"
},
"isBackEndCert": { "isBackEndCert": {
"type": "boolean", "type": "boolean",
"default": false, "default": false,

View File

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

View File

@ -6,14 +6,37 @@ import debugFactory from 'debug';
import { import {
frontEndChallengeId, frontEndChallengeId,
dataVisChallengeId,
backEndChallengeId backEndChallengeId
} from '../utils/constantStrings.json'; } from '../utils/constantStrings.json';
import certTypes from '../utils/certTypes.json';
import { ifNoUser401, ifNoUserRedirectTo } from '../utils/middleware'; import { ifNoUser401, ifNoUserRedirectTo } from '../utils/middleware';
import { observeQuery } from '../utils/rx'; import { observeQuery } from '../utils/rx';
import { calcCurrentStreak, calcLongestStreak } from '../utils/user-stats'; import { calcCurrentStreak, calcLongestStreak } from '../utils/user-stats';
const debug = debugFactory('freecc:boot:user'); const debug = debugFactory('freecc:boot:user');
const sendNonUserToMap = ifNoUserRedirectTo('/map'); 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) { function replaceScriptTags(value) {
return value return value
@ -80,7 +103,17 @@ module.exports = function(app) {
// Ensure these are the last routes! // Ensure these are the last routes!
router.get( router.get(
'/:username/front-end-certification', '/: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( router.get(
@ -88,11 +121,6 @@ module.exports = function(app) {
(req, res) => res.redirect(req.url.replace('full-stack', 'back-end')) (req, res) => res.redirect(req.url.replace('full-stack', 'back-end'))
); );
router.get(
'/:username/back-end-certification',
showCert
);
router.get('/:username', returnUser); router.get('/:username', returnUser);
app.use(router); app.use(router);
@ -207,6 +235,7 @@ module.exports = function(app) {
pledge: profileUser.pledge, pledge: profileUser.pledge,
isFrontEndCert: profileUser.isFrontEndCert, isFrontEndCert: profileUser.isFrontEndCert,
isDataVisCert: profileUser.isDataVisCert,
isBackEndCert: profileUser.isBackEndCert, isBackEndCert: profileUser.isBackEndCert,
isFullStackCert: profileUser.isFullStackCert, isFullStackCert: profileUser.isFullStackCert,
isHonest: profileUser.isHonest, 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 username = req.params.username.toLowerCase();
const { user } = req; const { user } = req;
const whichCert = req.path.split('/').pop();
const showFront = whichCert === 'front-end-certification';
Observable.just(user) Observable.just(user)
.flatMap(user => { .flatMap(user => {
if (user && user.username === username) { if (user && user.username === username) {
@ -250,8 +277,9 @@ module.exports = function(app) {
return findUserByUsername$(username, { return findUserByUsername$(username, {
isGithubCool: true, isGithubCool: true,
isFrontEndCert: true, isFrontEndCert: true,
isFullStackCert: true, isDataVisCert: true,
isBackEndCert: true, isBackEndCert: true,
isFullStackCert: true,
isHonest: true, isHonest: true,
completedChallenges: true, completedChallenges: true,
username: true, username: true,
@ -294,33 +322,29 @@ module.exports = function(app) {
return res.redirect('back'); return res.redirect('back');
} }
if ( if (user[certType]) {
showFront && user.isFrontEndCert ||
!showFront && user.isBackEndCert // 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() } = var { completedDate = new Date() } =
_.find(user.completedChallenges, { _.find(
id: showFront ? user.completedChallenges,
frontEndChallengeId : { id: certIds[certType] }
backEndChallengeId ) || {};
}) || {};
return res.render( return res.render(
showFront ? certViews[certType],
'certificate/front-end.jade' :
'certificate/back-end.jade',
{ {
username: user.username, username: user.username,
date: moment(new Date(completedDate)) date: moment(new Date(completedDate)).format('MMMM, Do YYYY'),
.format('MMMM, Do YYYY'),
name: user.name name: user.name
} }
); );
} }
req.flash('errors', { req.flash('errors', {
msg: showFront ? msg: `Looks like user ${username} is not ${certText[certType]}`
`Looks like user ${username} is not Front End certified` :
`Looks like user ${username} is not Back End certified`
}); });
res.redirect('back'); 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 { commitGoals };
export function completeCommitment$(user) { export function completeCommitment$(user) {
const { isFrontEndCert, isFullStackCert } = user; const {
isFrontEndCert,
isDataVisCert,
isBackEndCert,
isFullStackCert
} = user;
return Observable.fromNodeCallback(user.pledge, user)() return Observable.fromNodeCallback(user.pledge, user)()
.flatMap(pledge => { .flatMap(pledge => {
if (!pledge) { if (!pledge) {
@ -18,8 +24,10 @@ export function completeCommitment$(user) {
const { goal } = pledge; const { goal } = pledge;
if ( if (
isFrontEndCert && goal === commitGoals.frontEndCert || (isFrontEndCert && goal === commitGoals.frontEndCert) ||
isFullStackCert && goal === commitGoals.fullStackCert (isDataVisCert && goal === commitGoals.dataVisCert) ||
(isBackEndCert && goal === commitGoals.backEndCert) ||
(isFullStackCert && goal === commitGoals.fullStackCert)
) { ) {
debug('marking goal complete'); debug('marking goal complete');
pledge.isCompleted = true; 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", "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", "frontEndChallengeId": "561add10cb82ac38a17513be",
"dataVisChallengeId": "561add10cb82ac38a17513b3",
"backEndChallengeId": "660add10cb82ac38a17513be" "backEndChallengeId": "660add10cb82ac38a17513be"
} }

View File

@ -67,6 +67,9 @@ block content
.spacer .spacer
if isFrontEndCert if isFrontEndCert
a.btn.btn-primary(href='/' + username + '/front-end-certification') View My Front End Development Certification 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 if isBackEndCert
.button-spacer .button-spacer
a.btn.btn-success(href='/' + username + '/back-end-certification') View My Back End Development Certification 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