Add data vis certification
This commit is contained in:
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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');
|
||||
},
|
||||
|
6
server/utils/certTypes.json
Normal file
6
server/utils/certTypes.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"frontEnd": "isFrontEndCert",
|
||||
"backEnd": "isBackEndCert",
|
||||
"dataVis": "isDataVisCert",
|
||||
"fullStack": "isFullStackCert"
|
||||
}
|
@ -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;
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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
|
||||
|
6
server/views/certificate/data-vis.jade
Normal file
6
server/views/certificate/data-vis.jade
Normal 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
|
Reference in New Issue
Block a user