feat(full-stack): Full Stack Certification

This commit is contained in:
NitronR
2018-08-02 20:13:10 +05:30
committed by mrugesh mohapatra
parent 903e28ee6a
commit 3518ff9e8e
7 changed files with 145 additions and 60 deletions

View File

@ -119,6 +119,14 @@ export function projectsSelector(state) {
]), ]),
[] []
); );
blocks['full-stack-projects'] = {
dashedName: 'full-stack',
title: 'Full Stack Certification',
time: '1800 hours',
challenges: [],
superBlock: 'full-stack'
};
return Object.keys(blocks) return Object.keys(blocks)
.filter(key => .filter(key =>
key.includes('projects') && !( key.includes('projects') && !(

View File

@ -37,34 +37,41 @@ const mapStateToProps = createSelector(
isFrontEndCert, isFrontEndCert,
isBackEndCert, isBackEndCert,
isDataVisCert, isDataVisCert,
isFullStackCert,
username username
}, },
projects projects
) => ({ ) => {
allProjects: projects, let modernProjects = projects.filter(p => !p.superBlock.includes('legacy'));
legacyProjects: projects.filter(p => p.superBlock.includes('legacy')), modernProjects.push(modernProjects.shift());
modernProjects: projects.filter(p => !p.superBlock.includes('legacy')),
userProjects: projects return {
.map(block => buildUserProjectsMap(block, completedChallenges)) allProjects: projects,
.reduce((projects, current) => ({ legacyProjects: projects.filter(p => p.superBlock.includes('legacy')),
...projects, modernProjects: modernProjects,
...current userProjects: projects
}), {}), .map(block => buildUserProjectsMap(block, completedChallenges))
blockNameIsCertMap: { .reduce((projects, current) => ({
'Responsive Web Design Projects': isRespWebDesignCert, ...projects,
/* eslint-disable max-len */ ...current
'JavaScript Algorithms and Data Structures Projects': isJsAlgoDataStructCert, }), {}),
/* eslint-enable max-len */ blockNameIsCertMap: {
'Front End Libraries Projects': isFrontEndLibsCert, 'Responsive Web Design Projects': isRespWebDesignCert,
'Data Visualization Projects': is2018DataVisCert, /* eslint-disable max-len */
'APIs and Microservices Projects': isApisMicroservicesCert, 'JavaScript Algorithms and Data Structures Projects': isJsAlgoDataStructCert,
'Information Security and Quality Assurance Projects': isInfosecQaCert, /* eslint-enable max-len */
'Legacy Front End Projects': isFrontEndCert, 'Front End Libraries Projects': isFrontEndLibsCert,
'Legacy Back End Projects': isBackEndCert, 'Data Visualization Projects': is2018DataVisCert,
'Legacy Data Visualization Projects': isDataVisCert 'APIs and Microservices Projects': isApisMicroservicesCert,
}, 'Information Security and Quality Assurance Projects': isInfosecQaCert,
username 'Full Stack Certification': isFullStackCert,
}) 'Legacy Front End Projects': isFrontEndCert,
'Legacy Back End Projects': isBackEndCert,
'Legacy Data Visualization Projects': isDataVisCert
},
username
};
}
); );
function mapDispatchToProps(dispatch) { function mapDispatchToProps(dispatch) {
@ -178,12 +185,40 @@ class CertificationSettings extends PureComponent {
.length - 1; .length - 1;
const fullForm = completedProjects === challengeTitles.length; const fullForm = completedProjects === challengeTitles.length;
let isFullStack = superBlock === 'full-stack';
let isFullStackClaimable = false;
let description = '';
if (isFullStack) {
isFullStackClaimable = Object.keys(blockNameIsCertMap).every(function(e) {
if (e.indexOf('Full Stack') !== -1 || e.indexOf('Legacy') !== -1) {
return true;
}
return blockNameIsCertMap[e];
});
description = (<div>
Once you've earned the following freeCodeCamp certifications,
you'll be able to claim The Full Stack Developer Certification:
<ul>
<li>Responsive Web Design</li>
<li>Algorithms and Data Structures</li>
<li>Front End Libraries</li>
<li>Data Visualization</li>
<li>APIs and Microservices</li>
<li>Information Security and Quality Assurance</li>
</ul>
</div>);
}
return ( return (
<FullWidthRow key={superBlock}> <FullWidthRow key={superBlock}>
<h3 className='project-heading'>{ projectBlockName }</h3> <h3 className='project-heading'>{ projectBlockName }</h3>
{description}
<Form <Form
buttonText={ fullForm ? 'Claim Certification' : 'Save Progress' } buttonText={ fullForm || isFullStack
enableSubmit={ fullForm } ? 'Claim Certification' : 'Save Progress' }
enableSubmit={ isFullStack ? isFullStackClaimable : fullForm }
formFields={ challengeTitles.concat([ 'id' ]) } formFields={ challengeTitles.concat([ 'id' ]) }
hideButton={isCertClaimed} hideButton={isCertClaimed}
id={ superBlock } id={ superBlock }

View File

@ -23,7 +23,8 @@ import {
jsAlgoDataStructId, jsAlgoDataStructId,
dataVis2018Id, dataVis2018Id,
apisMicroservicesId, apisMicroservicesId,
infosecQaId infosecQaId,
fullStackId
} from '../utils/constantStrings.json'; } from '../utils/constantStrings.json';
import certTypes from '../utils/certTypes.json'; import certTypes from '../utils/certTypes.json';
import superBlockCertTypeMap from '../utils/superBlockCertTypeMap'; import superBlockCertTypeMap from '../utils/superBlockCertTypeMap';
@ -59,14 +60,14 @@ const certIds = {
[certTypes.jsAlgoDataStruct]: jsAlgoDataStructId, [certTypes.jsAlgoDataStruct]: jsAlgoDataStructId,
[certTypes.dataVis2018]: dataVis2018Id, [certTypes.dataVis2018]: dataVis2018Id,
[certTypes.apisMicroservices]: apisMicroservicesId, [certTypes.apisMicroservices]: apisMicroservicesId,
[certTypes.infosecQa]: infosecQaId [certTypes.infosecQa]: infosecQaId,
[certTypes.fullStack]: fullStackId
}; };
const certViews = { const certViews = {
[certTypes.frontEnd]: 'certificate/legacy/front-end.jade', [certTypes.frontEnd]: 'certificate/legacy/front-end.jade',
[certTypes.backEnd]: 'certificate/legacy/back-end.jade', [certTypes.backEnd]: 'certificate/legacy/back-end.jade',
[certTypes.dataVis]: 'certificate/legacy/data-visualization.jade', [certTypes.dataVis]: 'certificate/legacy/data-visualization.jade',
[certTypes.fullStack]: 'certificate/legacy/full-stack.jade',
[certTypes.respWebDesign]: 'certificate/responsive-web-design.jade', [certTypes.respWebDesign]: 'certificate/responsive-web-design.jade',
[certTypes.frontEndLibs]: 'certificate/front-end-libraries.jade', [certTypes.frontEndLibs]: 'certificate/front-end-libraries.jade',
@ -75,7 +76,8 @@ const certViews = {
[certTypes.dataVis2018]: 'certificate/data-visualization.jade', [certTypes.dataVis2018]: 'certificate/data-visualization.jade',
[certTypes.apisMicroservices]: 'certificate/apis-and-microservices.jade', [certTypes.apisMicroservices]: 'certificate/apis-and-microservices.jade',
[certTypes.infosecQa]: [certTypes.infosecQa]:
'certificate/information-security-and-quality-assurance.jade' 'certificate/information-security-and-quality-assurance.jade',
[certTypes.fullStack]: 'certificate/full-stack.jade'
}; };
const certText = { const certText = {
@ -178,7 +180,8 @@ export default function certificate(app) {
apisMicroservicesId, apisMicroservicesId,
Challenge Challenge
), ),
[certTypes.infosecQa]: getIdsForCert$(infosecQaId, Challenge) [certTypes.infosecQa]: getIdsForCert$(infosecQaId, Challenge),
[certTypes.fullStack]: getIdsForCert$(fullStackId, Challenge)
}; };
const superBlocks = Object.keys(superBlockCertTypeMap); const superBlocks = Object.keys(superBlockCertTypeMap);
@ -207,7 +210,7 @@ export default function certificate(app) {
router.get( router.get(
'/:username/full-stack-certification', '/:username/full-stack-certification',
(req, res) => res.redirect( (req, res) => res.redirect(
`/certification/${req.params.username}/legacy-full-stack` `/certification/${req.params.username}/full-stack`
) )
); );
@ -254,39 +257,45 @@ export default function certificate(app) {
return user.getCompletedChallenges$() return user.getCompletedChallenges$()
.flatMap(() => certTypeIds[certType]) .flatMap(() => certTypeIds[certType])
.flatMap(challenge => { .flatMap(challenge => {
const {
id,
tests,
challengeType
} = challenge;
const certName = certText[certType]; const certName = certText[certType];
if (user[certType]) { if (user[certType]) {
return Observable.just(alreadyClaimedMessage(certName)); return Observable.just(alreadyClaimedMessage(certName));
} }
if (!user[certType] && !isCertified(tests, user.completedChallenges)) {
return Observable.just(notCertifiedMessage(certName)); let updateData = {
} $set: {
if (!user.name) { [certType]: true
return Observable.just(noNameMessage); }
} };
const updateData = {
$push: { if (challenge) {
const {
id,
tests,
challengeType
} = challenge;
if (!user[certType] &&
!isCertified(tests, user.completedChallenges)) {
return Observable.just(notCertifiedMessage(certName));
}
updateData['$push'] = {
completedChallenges: { completedChallenges: {
id, id,
completedDate: new Date(), completedDate: new Date(),
challengeType challengeType
} }
}, };
$set: { user.completedChallenges[
[certType]: true user.completedChallenges.length - 1
} ] = { id, completedDate: new Date() };
}; }
if (!user.name) {
return Observable.just(noNameMessage);
}
// set here so sendCertifiedEmail works properly // set here so sendCertifiedEmail works properly
// not used otherwise // not used otherwise
user[certType] = true; user[certType] = true;
user.completedChallenges[
user.completedChallenges.length - 1
] = { id, completedDate: new Date() };
return Observable.combineLatest( return Observable.combineLatest(
// update user data // update user data
user.update$(updateData), user.update$(updateData),

View File

@ -2,11 +2,11 @@
"frontEnd": "isFrontEndCert", "frontEnd": "isFrontEndCert",
"backEnd": "isBackEndCert", "backEnd": "isBackEndCert",
"dataVis": "isDataVisCert", "dataVis": "isDataVisCert",
"fullStack": "isFullStackCert",
"respWebDesign": "isRespWebDesignCert", "respWebDesign": "isRespWebDesignCert",
"frontEndLibs": "isFrontEndLibsCert", "frontEndLibs": "isFrontEndLibsCert",
"dataVis2018": "is2018DataVisCert", "dataVis2018": "is2018DataVisCert",
"jsAlgoDataStruct": "isJsAlgoDataStructCert", "jsAlgoDataStruct": "isJsAlgoDataStructCert",
"apisMicroservices": "isApisMicroservicesCert", "apisMicroservices": "isApisMicroservicesCert",
"infosecQa": "isInfosecQaCert" "infosecQa": "isInfosecQaCert",
} "fullStack": "isFullStackCert"
}

View File

@ -10,5 +10,6 @@
"dataVis2018Id": "5a553ca864b52e1d8bceea14", "dataVis2018Id": "5a553ca864b52e1d8bceea14",
"jsAlgoDataStructId": "561abd10cb81ac38a17513bc", "jsAlgoDataStructId": "561abd10cb81ac38a17513bc",
"apisMicroservicesId": "561add10cb82ac38a17523bc", "apisMicroservicesId": "561add10cb82ac38a17523bc",
"infosecQaId": "561add10cb82ac38a17213bc" "infosecQaId": "561add10cb82ac38a17213bc",
"fullStackId": "561add10cb82ac38a17213bd"
} }

View File

@ -5,7 +5,6 @@ const superBlockCertTypeMap = {
'legacy-front-end': certTypes.frontEnd, 'legacy-front-end': certTypes.frontEnd,
'legacy-back-end': certTypes.backEnd, 'legacy-back-end': certTypes.backEnd,
'legacy-data-visualization': certTypes.dataVis, 'legacy-data-visualization': certTypes.dataVis,
'legacy-full-stack': certTypes.fullStack,
// modern // modern
'responsive-web-design': certTypes.respWebDesign, 'responsive-web-design': certTypes.respWebDesign,
@ -13,7 +12,8 @@ const superBlockCertTypeMap = {
'front-end-libraries': certTypes.frontEndLibs, 'front-end-libraries': certTypes.frontEndLibs,
'data-visualization': certTypes.dataVis2018, 'data-visualization': certTypes.dataVis2018,
'apis-and-microservices': certTypes.apisMicroservices, 'apis-and-microservices': certTypes.apisMicroservices,
'information-security-and-quality-assurance': certTypes.infosecQa 'information-security-and-quality-assurance': certTypes.infosecQa,
'full-stack': certTypes.fullStack
}; };
export default superBlockCertTypeMap; export default superBlockCertTypeMap;

View File

@ -0,0 +1,32 @@
meta(name='viewport', content='width=device-width, initial-scale=1')
link(rel='stylesheet', href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css')
include styles
.certificate-wrapper.container
.row
header
.col-md-5.col-sm-12
.logo
img(class='img-responsive', src='https://s3.amazonaws.com/freecodecamp/freecodecamp_logo.svg', alt="freeCodeCamp's Logo")
.col-md-7.col-sm-12
.issue-date Issued&nbsp;
strong #{date}
section.information
.information-container
h3 This certifies that
h1
strong= name
h3 has successfully completed freeCodeCamp's
h1
strong Full Stack
h4 Developer Certification, representing approximately 1800 hours of coursework
footer
.row.signatures
img(class='img-responsive', src='https://i.imgur.com/OJFVJKg.png', alt="Quincy Larson's Signature")
p
strong Quincy Larson
p Executive Director, freeCodeCamp.org
.row
p.verify Verify this certification at: https://www.freecodecamp.org/certification/#{username}/responsive-web-design