Add data vis certification
This commit is contained in:
@ -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,
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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');
|
||||||
},
|
},
|
||||||
|
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 { 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;
|
||||||
|
@ -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"
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
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