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)
.filter(key =>
key.includes('projects') && !(

View File

@ -37,13 +37,18 @@ const mapStateToProps = createSelector(
isFrontEndCert,
isBackEndCert,
isDataVisCert,
isFullStackCert,
username
},
projects
) => ({
) => {
let modernProjects = projects.filter(p => !p.superBlock.includes('legacy'));
modernProjects.push(modernProjects.shift());
return {
allProjects: projects,
legacyProjects: projects.filter(p => p.superBlock.includes('legacy')),
modernProjects: projects.filter(p => !p.superBlock.includes('legacy')),
modernProjects: modernProjects,
userProjects: projects
.map(block => buildUserProjectsMap(block, completedChallenges))
.reduce((projects, current) => ({
@ -59,12 +64,14 @@ const mapStateToProps = createSelector(
'Data Visualization Projects': is2018DataVisCert,
'APIs and Microservices Projects': isApisMicroservicesCert,
'Information Security and Quality Assurance Projects': isInfosecQaCert,
'Full Stack Certification': isFullStackCert,
'Legacy Front End Projects': isFrontEndCert,
'Legacy Back End Projects': isBackEndCert,
'Legacy Data Visualization Projects': isDataVisCert
},
username
})
};
}
);
function mapDispatchToProps(dispatch) {
@ -178,12 +185,40 @@ class CertificationSettings extends PureComponent {
.length - 1;
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 (
<FullWidthRow key={superBlock}>
<h3 className='project-heading'>{ projectBlockName }</h3>
{description}
<Form
buttonText={ fullForm ? 'Claim Certification' : 'Save Progress' }
enableSubmit={ fullForm }
buttonText={ fullForm || isFullStack
? 'Claim Certification' : 'Save Progress' }
enableSubmit={ isFullStack ? isFullStackClaimable : fullForm }
formFields={ challengeTitles.concat([ 'id' ]) }
hideButton={isCertClaimed}
id={ superBlock }

View File

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

View File

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

View File

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

View File

@ -5,7 +5,6 @@ const superBlockCertTypeMap = {
'legacy-front-end': certTypes.frontEnd,
'legacy-back-end': certTypes.backEnd,
'legacy-data-visualization': certTypes.dataVis,
'legacy-full-stack': certTypes.fullStack,
// modern
'responsive-web-design': certTypes.respWebDesign,
@ -13,7 +12,8 @@ const superBlockCertTypeMap = {
'front-end-libraries': certTypes.frontEndLibs,
'data-visualization': certTypes.dataVis2018,
'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;

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