feat(full-stack): Full Stack Certification
This commit is contained in:
committed by
mrugesh mohapatra
parent
903e28ee6a
commit
3518ff9e8e
@ -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') && !(
|
||||
|
@ -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 }
|
||||
|
@ -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),
|
||||
|
@ -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"
|
||||
}
|
@ -10,5 +10,6 @@
|
||||
"dataVis2018Id": "5a553ca864b52e1d8bceea14",
|
||||
"jsAlgoDataStructId": "561abd10cb81ac38a17513bc",
|
||||
"apisMicroservicesId": "561add10cb82ac38a17523bc",
|
||||
"infosecQaId": "561add10cb82ac38a17213bc"
|
||||
"infosecQaId": "561add10cb82ac38a17213bc",
|
||||
"fullStackId": "561add10cb82ac38a17213bd"
|
||||
}
|
||||
|
@ -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;
|
||||
|
32
server/views/certificate/full-stack.jade
Normal file
32
server/views/certificate/full-stack.jade
Normal 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
|
||||
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
|
Reference in New Issue
Block a user