fix(dev): rename superBlock with v7 to certSlug (#41738)

* fix(dev): rename superBlock with v7 to slug

* improve name slug -> certSlug

* superBlockTitle -> superBlock

* correct teeny, tiny mistake

* fix: correct slug to certSlug in certLocation

* refactor currentCerts

* rename showCert cert -> certSlug and various
This commit is contained in:
Shaun Hamilton
2021-04-23 20:29:17 +01:00
committed by GitHub
parent 99cecfb581
commit d3f59e6d5d
16 changed files with 251 additions and 254 deletions

View File

@ -15,7 +15,7 @@ import { getChallenges } from '../utils/get-curriculum';
import { import {
completionHours, completionHours,
certTypes, certTypes,
superBlockCertTypeMap, certSlugTypeMap,
certTypeTitleMap, certTypeTitleMap,
certTypeIdMap, certTypeIdMap,
certIds, certIds,
@ -51,7 +51,7 @@ export default function bootCertificate(app) {
const verifyCert = createVerifyCert(certTypeIds, app); const verifyCert = createVerifyCert(certTypeIds, app);
api.put('/certificate/verify', ifNoUser401, ifNoSuperBlock404, verifyCert); api.put('/certificate/verify', ifNoUser401, ifNoSuperBlock404, verifyCert);
api.get('/certificate/showCert/:username/:cert', showCert); api.get('/certificate/showCert/:username/:certSlug', showCert);
app.use(api); app.use(api);
} }
@ -66,9 +66,11 @@ export function getFallbackFrontEndDate(completedChallenges, completedDate) {
return latestCertDate ? latestCertDate : completedDate; return latestCertDate ? latestCertDate : completedDate;
} }
const certSlugs = Object.keys(certSlugTypeMap);
function ifNoSuperBlock404(req, res, next) { function ifNoSuperBlock404(req, res, next) {
const { superBlock } = req.body; const { certSlug } = req.body;
if (superBlock && superBlocks.includes(superBlock)) { if (certSlug && certSlugs.includes(certSlug)) {
return next(); return next();
} }
return res.status(404).end(); return res.status(404).end();
@ -130,8 +132,6 @@ function getCertById(anId, allChallenges) {
}))[0]; }))[0];
} }
const superBlocks = Object.keys(superBlockCertTypeMap);
function sendCertifiedEmail( function sendCertifiedEmail(
{ {
email = '', email = '',
@ -223,11 +223,11 @@ function createVerifyCert(certTypeIds, app) {
const { Email } = app.models; const { Email } = app.models;
return function verifyCert(req, res, next) { return function verifyCert(req, res, next) {
const { const {
body: { superBlock }, body: { certSlug },
user user
} = req; } = req;
log(superBlock); log(certSlug);
let certType = superBlockCertTypeMap[superBlock]; let certType = certSlugTypeMap[certSlug];
log(certType); log(certType);
return Observable.of(certTypeIds[certType]) return Observable.of(certTypeIds[certType])
.flatMap(challenge => { .flatMap(challenge => {
@ -335,9 +335,9 @@ function createShowCert(app) {
} }
return function showCert(req, res, next) { return function showCert(req, res, next) {
let { username, cert } = req.params; let { username, certSlug } = req.params;
username = username.toLowerCase(); username = username.toLowerCase();
const certType = superBlockCertTypeMap[cert]; const certType = certSlugTypeMap[certSlug];
const certId = certTypeIdMap[certType]; const certId = certTypeIdMap[certType];
const certTitle = certTypeTitleMap[certType]; const certTitle = certTypeTitleMap[certType];
const completionTime = completionHours[certType] || 300; const completionTime = completionHours[certType] || 300;

View File

@ -132,6 +132,7 @@ exports.createPages = function createPages({ graphql, actions, reporter }) {
); );
// Create intro pages // Create intro pages
// TODO: Remove allMarkdownRemark (populate from elsewhere)
result.data.allMarkdownRemark.edges.forEach(edge => { result.data.allMarkdownRemark.edges.forEach(edge => {
const { const {
node: { frontmatter, fields } node: { frontmatter, fields }

View File

@ -33,6 +33,7 @@ import envData from '../../../config/env.json';
import RedirectHome from '../components/RedirectHome'; import RedirectHome from '../components/RedirectHome';
import { Loader, Spacer } from '../components/helpers'; import { Loader, Spacer } from '../components/helpers';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import { User } from '../redux/propTypes';
const { clientLocale } = envData; const { clientLocale } = envData;
@ -48,7 +49,7 @@ const propTypes = {
date: PropTypes.number date: PropTypes.number
}), }),
certDashedName: PropTypes.string, certDashedName: PropTypes.string,
certName: PropTypes.string, certSlug: PropTypes.string,
createFlashMessage: PropTypes.func.isRequired, createFlashMessage: PropTypes.func.isRequired,
executeGA: PropTypes.func, executeGA: PropTypes.func,
fetchProfileForUser: PropTypes.func, fetchProfileForUser: PropTypes.func,
@ -58,48 +59,27 @@ const propTypes = {
errored: PropTypes.bool errored: PropTypes.bool
}), }),
isDonating: PropTypes.bool, isDonating: PropTypes.bool,
isValidCert: PropTypes.bool,
location: PropTypes.shape({ location: PropTypes.shape({
pathname: PropTypes.string pathname: PropTypes.string
}), }),
showCert: PropTypes.func.isRequired, showCert: PropTypes.func.isRequired,
signedInUserName: PropTypes.string, signedInUserName: PropTypes.string,
user: PropTypes.shape({ user: User,
completedChallenges: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.string,
solution: PropTypes.string,
githubLink: PropTypes.string,
files: PropTypes.arrayOf(
PropTypes.shape({
contents: PropTypes.string,
ext: PropTypes.string,
key: PropTypes.string,
name: PropTypes.string,
path: PropTypes.string
})
)
})
),
profileUI: PropTypes.shape({
showName: PropTypes.bool
}),
username: PropTypes.string
}),
userFetchState: PropTypes.shape({ userFetchState: PropTypes.shape({
complete: PropTypes.bool complete: PropTypes.bool
}), }),
userFullName: PropTypes.string, userFullName: PropTypes.string,
username: PropTypes.string, username: PropTypes.string
validCertName: PropTypes.bool
}; };
const requestedUserSelector = (state, { username = '' }) => const requestedUserSelector = (state, { username = '' }) =>
userByNameSelector(username.toLowerCase())(state); userByNameSelector(username.toLowerCase())(state);
const validCertNames = certMap.map(cert => cert.slug); const validCertSlugs = certMap.map(cert => cert.certSlug);
const mapStateToProps = (state, props) => { const mapStateToProps = (state, props) => {
const validCertName = validCertNames.some(name => name === props.certName); const isValidCert = validCertSlugs.some(slug => slug === props.certSlug);
return createSelector( return createSelector(
showCertSelector, showCertSelector,
showCertFetchStateSelector, showCertFetchStateSelector,
@ -110,7 +90,7 @@ const mapStateToProps = (state, props) => {
(cert, fetchState, signedInUserName, userFetchState, isDonating, user) => ({ (cert, fetchState, signedInUserName, userFetchState, isDonating, user) => ({
cert, cert,
fetchState, fetchState,
validCertName, isValidCert,
signedInUserName, signedInUserName,
userFetchState, userFetchState,
isDonating, isDonating,
@ -132,9 +112,9 @@ const ShowCertification = props => {
const [isDonationClosed, setIsDonationClosed] = useState(false); const [isDonationClosed, setIsDonationClosed] = useState(false);
useEffect(() => { useEffect(() => {
const { username, certName, validCertName, showCert } = props; const { username, certSlug, isValidCert, showCert } = props;
if (validCertName) { if (isValidCert) {
showCert({ username, certName }); showCert({ username, certSlug });
} }
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
@ -208,13 +188,13 @@ const ShowCertification = props => {
const { const {
cert, cert,
fetchState, fetchState,
validCertName, isValidCert,
createFlashMessage, createFlashMessage,
signedInUserName, signedInUserName,
location: { pathname } location: { pathname }
} = props; } = props;
if (!validCertName) { if (!isValidCert) {
createFlashMessage(standardErrorMessage); createFlashMessage(standardErrorMessage);
return <RedirectHome />; return <RedirectHome />;
} }

View File

@ -125,8 +125,8 @@ const ShowProjectLinks = props => {
]; ];
return legacyCerts.map((cert, ind) => { return legacyCerts.map((cert, ind) => {
const mapToUse = projectMap[cert.title] || legacyProjectMap[cert.title]; const mapToUse = projectMap[cert.title] || legacyProjectMap[cert.title];
const { superBlock } = first(mapToUse); const { certSlug } = first(mapToUse);
const certLocation = `/certification/${username}/${superBlock}`; const certLocation = `/certification/${username}/${certSlug}`;
return ( return (
<li key={ind}> <li key={ind}>
<a <a

View File

@ -9,6 +9,7 @@ import { useTranslation } from 'react-i18next';
import { certificatesByNameSelector } from '../../../redux'; import { certificatesByNameSelector } from '../../../redux';
import { ButtonSpacer, FullWidthRow, Link, Spacer } from '../../helpers'; import { ButtonSpacer, FullWidthRow, Link, Spacer } from '../../helpers';
import './certifications.css'; import './certifications.css';
import { CurrentCertsType } from '../../../redux/propTypes';
const mapStateToProps = (state, props) => const mapStateToProps = (state, props) =>
createSelector( createSelector(
@ -21,19 +22,11 @@ const mapStateToProps = (state, props) =>
}) })
)(state, props); )(state, props);
const certArrayTypes = PropTypes.arrayOf(
PropTypes.shape({
show: PropTypes.bool,
title: PropTypes.string,
showURL: PropTypes.string
})
);
const propTypes = { const propTypes = {
currentCerts: certArrayTypes, currentCerts: CurrentCertsType,
hasLegacyCert: PropTypes.bool, hasLegacyCert: PropTypes.bool,
hasModernCert: PropTypes.bool, hasModernCert: PropTypes.bool,
legacyCerts: certArrayTypes, legacyCerts: CurrentCertsType,
username: PropTypes.string username: PropTypes.string
}; };
@ -45,7 +38,7 @@ function renderCertShow(username, cert) {
<Link <Link
className='btn btn-lg btn-primary btn-block' className='btn btn-lg btn-primary btn-block'
external={true} external={true}
to={`/certification/${username}/${cert.showURL}`} to={`/certification/${username}/${cert.certSlug}`}
> >
View {cert.title} View {cert.title}
</Link> </Link>

View File

@ -289,15 +289,15 @@ export class CertificationSettings extends Component {
t, t,
verifyCert verifyCert
} = this.props; } = this.props;
const { superBlock } = first(projectMap[certName]); const { certSlug } = first(projectMap[certName]);
const certLocation = `/certification/${username}/${superBlock}`; const certLocation = `/certification/${username}/${certSlug}`;
const createClickHandler = superBlock => e => { const createClickHandler = certSlug => e => {
e.preventDefault(); e.preventDefault();
if (isCert) { if (isCert) {
return navigate(certLocation); return navigate(certLocation);
} }
return isHonest return isHonest
? verifyCert(superBlock) ? verifyCert(certSlug)
: createFlashMessage(honestyInfoMessage); : createFlashMessage(honestyInfoMessage);
}; };
return projectMap[certName] return projectMap[certName]
@ -312,13 +312,13 @@ export class CertificationSettings extends Component {
</tr> </tr>
)) ))
.concat([ .concat([
<tr key={`cert-${superBlock}-button`}> <tr key={`cert-${certSlug}-button`}>
<td colSpan={2}> <td colSpan={2}>
<Button <Button
block={true} block={true}
bsStyle='primary' bsStyle='primary'
href={certLocation} href={certLocation}
onClick={createClickHandler(superBlock)} onClick={createClickHandler(certSlug)}
> >
{isCert ? t('buttons.show-cert') : t('buttons.claim-cert')} {isCert ? t('buttons.show-cert') : t('buttons.claim-cert')}
</Button> </Button>
@ -336,13 +336,13 @@ export class CertificationSettings extends Component {
updateLegacyCert updateLegacyCert
} = this.props; } = this.props;
let legacyTitle; let legacyTitle;
let superBlock; let certSlug;
let certs = Object.keys(legacyProjectMap); let certs = Object.keys(legacyProjectMap);
let loopBreak = false; let loopBreak = false;
for (let certTitle of certs) { for (let certTitle of certs) {
for (let chalTitle of legacyProjectMap[certTitle]) { for (let chalTitle of legacyProjectMap[certTitle]) {
if (chalTitle.title === Object.keys(formChalObj)[0]) { if (chalTitle.title === Object.keys(formChalObj)[0]) {
superBlock = chalTitle.superBlock; certSlug = chalTitle.certSlug;
loopBreak = true; loopBreak = true;
legacyTitle = certTitle; legacyTitle = certTitle;
break; break;
@ -392,16 +392,16 @@ export class CertificationSettings extends Component {
if (isProjectSectionComplete) { if (isProjectSectionComplete) {
return isHonest return isHonest
? verifyCert(superBlock) ? verifyCert(certSlug)
: createFlashMessage(honestyInfoMessage); : createFlashMessage(honestyInfoMessage);
} }
return updateLegacyCert({ challengesToUpdate, superBlock }); return updateLegacyCert({ challengesToUpdate, certSlug });
} }
renderLegacyCertifications = certName => { renderLegacyCertifications = certName => {
const { username, createFlashMessage, completedChallenges, t } = this.props; const { username, createFlashMessage, completedChallenges, t } = this.props;
const { superBlock } = first(legacyProjectMap[certName]); const { certSlug } = first(legacyProjectMap[certName]);
const certLocation = `/certification/${username}/${superBlock}`; const certLocation = `/certification/${username}/${certSlug}`;
const challengeTitles = legacyProjectMap[certName].map(item => item.title); const challengeTitles = legacyProjectMap[certName].map(item => item.title);
const isCertClaimed = this.getUserIsCertMap()[certName]; const isCertClaimed = this.getUserIsCertMap()[certName];
const initialObject = {}; const initialObject = {};
@ -446,7 +446,7 @@ export class CertificationSettings extends Component {
}; };
return ( return (
<FullWidthRow key={superBlock}> <FullWidthRow key={certSlug}>
<Spacer /> <Spacer />
<h3 className='text-center'>{certName}</h3> <h3 className='text-center'>{certName}</h3>
<Form <Form
@ -456,7 +456,7 @@ export class CertificationSettings extends Component {
enableSubmit={fullForm} enableSubmit={fullForm}
formFields={formFields} formFields={formFields}
hideButton={isCertClaimed} hideButton={isCertClaimed}
id={superBlock} id={certSlug}
initialValues={{ initialValues={{
...initialObject ...initialObject
}} }}
@ -470,7 +470,7 @@ export class CertificationSettings extends Component {
bsStyle='primary' bsStyle='primary'
className={'col-xs-12'} className={'col-xs-12'}
href={certLocation} href={certLocation}
id={'button-' + superBlock} id={'button-' + certSlug}
onClick={createClickHandler(certLocation)} onClick={createClickHandler(certLocation)}
style={buttonStyle} style={buttonStyle}
target='_blank' target='_blank'
@ -507,10 +507,10 @@ export class CertificationSettings extends Component {
isJsAlgoDataStructCert && isJsAlgoDataStructCert &&
isRespWebDesignCert; isRespWebDesignCert;
// Keep the settings page slug as full-stack rather than // Keep the settings page certSlug as full-stack rather than
// legacy-full-stack so we don't break existing links // legacy-full-stack so we don't break existing links
const superBlock = 'full-stack'; const certSlug = 'full-stack';
const certLocation = `/certification/${username}/${superBlock}`; const certLocation = `/certification/${username}/${certSlug}`;
const buttonStyle = { const buttonStyle = {
marginBottom: '30px', marginBottom: '30px',
@ -518,17 +518,17 @@ export class CertificationSettings extends Component {
fontSize: '18px' fontSize: '18px'
}; };
const createClickHandler = superBlock => e => { const createClickHandler = certSlug => e => {
e.preventDefault(); e.preventDefault();
if (isFullStackCert) { if (isFullStackCert) {
return navigate(certLocation); return navigate(certLocation);
} }
return isHonest return isHonest
? verifyCert(superBlock) ? verifyCert(certSlug)
: createFlashMessage(honestyInfoMessage); : createFlashMessage(honestyInfoMessage);
}; };
return ( return (
<FullWidthRow key={superBlock}> <FullWidthRow key={certSlug}>
<Spacer /> <Spacer />
<h3 className='text-center'>Legacy Full Stack Certification</h3> <h3 className='text-center'>Legacy Full Stack Certification</h3>
<div> <div>
@ -554,8 +554,8 @@ export class CertificationSettings extends Component {
bsStyle='primary' bsStyle='primary'
className={'col-xs-12'} className={'col-xs-12'}
href={certLocation} href={certLocation}
id={'button-' + superBlock} id={'button-' + certSlug}
onClick={createClickHandler(superBlock)} onClick={createClickHandler(certSlug)}
style={buttonStyle} style={buttonStyle}
target='_blank' target='_blank'
> >
@ -569,7 +569,7 @@ export class CertificationSettings extends Component {
bsStyle='primary' bsStyle='primary'
className={'col-xs-12'} className={'col-xs-12'}
disabled={true} disabled={true}
id={'button-' + superBlock} id={'button-' + certSlug}
style={buttonStyle} style={buttonStyle}
target='_blank' target='_blank'
> >

View File

@ -12,7 +12,7 @@ class Certification extends Component {
return ( return (
<Router> <Router>
<ShowCertification <ShowCertification
path={withPrefix('/certification/:username/:certName')} path={withPrefix('/certification/:username/:certSlug')}
/> />
<RedirectHome default={true} /> <RedirectHome default={true} />
</Router> </Router>

View File

@ -266,81 +266,81 @@ export const certificatesByNameSelector = username => state => {
{ {
show: isRespWebDesignCert, show: isRespWebDesignCert,
title: 'Responsive Web Design Certification', title: 'Responsive Web Design Certification',
showURL: 'responsive-web-design' certSlug: 'responsive-web-design'
}, },
{ {
show: isJsAlgoDataStructCert, show: isJsAlgoDataStructCert,
title: 'JavaScript Algorithms and Data Structures Certification', title: 'JavaScript Algorithms and Data Structures Certification',
showURL: 'javascript-algorithms-and-data-structures' certSlug: 'javascript-algorithms-and-data-structures'
}, },
{ {
show: isFrontEndLibsCert, show: isFrontEndLibsCert,
title: 'Front End Libraries Certification', title: 'Front End Libraries Certification',
showURL: 'front-end-libraries' certSlug: 'front-end-libraries'
}, },
{ {
show: is2018DataVisCert, show: is2018DataVisCert,
title: 'Data Visualization Certification', title: 'Data Visualization Certification',
showURL: 'data-visualization' certSlug: 'data-visualization'
}, },
{ {
show: isApisMicroservicesCert, show: isApisMicroservicesCert,
title: 'APIs and Microservices Certification', title: 'APIs and Microservices Certification',
showURL: 'apis-and-microservices' certSlug: 'apis-and-microservices'
}, },
{ {
show: isQaCertV7, show: isQaCertV7,
title: ' Quality Assurance Certification', title: ' Quality Assurance Certification',
showURL: 'quality-assurance-v7' certSlug: 'quality-assurance-v7'
}, },
{ {
show: isInfosecCertV7, show: isInfosecCertV7,
title: 'Information Security Certification', title: 'Information Security Certification',
showURL: 'information-security-v7' certSlug: 'information-security-v7'
}, },
{ {
show: isSciCompPyCertV7, show: isSciCompPyCertV7,
title: 'Scientific Computing with Python Certification', title: 'Scientific Computing with Python Certification',
showURL: 'scientific-computing-with-python-v7' certSlug: 'scientific-computing-with-python-v7'
}, },
{ {
show: isDataAnalysisPyCertV7, show: isDataAnalysisPyCertV7,
title: 'Data Analysis with Python Certification', title: 'Data Analysis with Python Certification',
showURL: 'data-analysis-with-python-v7' certSlug: 'data-analysis-with-python-v7'
}, },
{ {
show: isMachineLearningPyCertV7, show: isMachineLearningPyCertV7,
title: 'Machine Learning with Python Certification', title: 'Machine Learning with Python Certification',
showURL: 'machine-learning-with-python-v7' certSlug: 'machine-learning-with-python-v7'
} }
], ],
legacyCerts: [ legacyCerts: [
{ {
show: isFrontEndCert, show: isFrontEndCert,
title: 'Front End Certification', title: 'Front End Certification',
showURL: 'legacy-front-end' certSlug: 'legacy-front-end'
}, },
{ {
show: isBackEndCert, show: isBackEndCert,
title: 'Back End Certification', title: 'Back End Certification',
showURL: 'legacy-back-end' certSlug: 'legacy-back-end'
}, },
{ {
show: isDataVisCert, show: isDataVisCert,
title: 'Data Visualization Certification', title: 'Data Visualization Certification',
showURL: 'legacy-data-visualization' certSlug: 'legacy-data-visualization'
}, },
{ {
show: isInfosecQaCert, show: isInfosecQaCert,
title: 'Information Security and Quality Assurance Certification', title: 'Information Security and Quality Assurance Certification',
// Keep the current public profile cert slug // Keep the current public profile cert slug
showURL: 'information-security-and-quality-assurance' certSlug: 'information-security-and-quality-assurance'
}, },
{ {
show: isFullStackCert, show: isFullStackCert,
title: 'Full Stack Certification', title: 'Full Stack Certification',
// Keep the current public profile cert slug // Keep the current public profile cert slug
showURL: 'full-stack' certSlug: 'full-stack'
} }
] ]
}; };

View File

@ -124,3 +124,11 @@ export const User = PropTypes.shape({
username: PropTypes.string, username: PropTypes.string,
website: PropTypes.string website: PropTypes.string
}); });
export const CurrentCertsType = PropTypes.arrayOf(
PropTypes.shape({
show: PropTypes.bool,
title: PropTypes.string,
certSlug: PropTypes.string
})
);

View File

@ -5,9 +5,9 @@ import { createFlashMessage } from '../components/Flash/redux';
import { getShowCert } from '../utils/ajax'; import { getShowCert } from '../utils/ajax';
import { showCertComplete, showCertError } from '.'; import { showCertComplete, showCertError } from '.';
function* getShowCertSaga({ payload: { username, certName: cert } }) { function* getShowCertSaga({ payload: { username, certSlug } }) {
try { try {
const { data: response } = yield call(getShowCert, username, cert); const { data: response } = yield call(getShowCert, username, certSlug);
const { messages } = response; const { messages } = response;
if (messages && messages.length) { if (messages && messages.length) {
for (let i = 0; i < messages.length; i++) { for (let i = 0; i < messages.length; i++) {

View File

@ -27,143 +27,143 @@ const certMap = [
{ {
id: '561add10cb82ac38a17513be', id: '561add10cb82ac38a17513be',
title: 'Legacy Front End', title: 'Legacy Front End',
slug: 'legacy-front-end', certSlug: 'legacy-front-end',
flag: 'isFrontEndCert', flag: 'isFrontEndCert',
projects: [ projects: [
{ {
id: 'bd7158d8c242eddfaeb5bd13', id: 'bd7158d8c242eddfaeb5bd13',
title: 'Build a Personal Portfolio Webpage', title: 'Build a Personal Portfolio Webpage',
link: `${legacyFrontEndBase}/build-a-personal-portfolio-webpage`, link: `${legacyFrontEndBase}/build-a-personal-portfolio-webpage`,
superBlock: 'legacy-front-end' certSlug: 'legacy-front-end'
}, },
{ {
id: 'bd7158d8c442eddfaeb5bd13', id: 'bd7158d8c442eddfaeb5bd13',
title: 'Build a Random Quote Machine', title: 'Build a Random Quote Machine',
link: `${legacyFrontEndBase}/build-a-random-quote-machine`, link: `${legacyFrontEndBase}/build-a-random-quote-machine`,
superBlock: 'legacy-front-end' certSlug: 'legacy-front-end'
}, },
{ {
id: 'bd7158d8c442eddfaeb5bd0f', id: 'bd7158d8c442eddfaeb5bd0f',
title: 'Build a 25 + 5 Clock', title: 'Build a 25 + 5 Clock',
link: `${legacyFrontEndBase}/build-a-25--5-clock`, link: `${legacyFrontEndBase}/build-a-25--5-clock`,
superBlock: 'legacy-front-end' certSlug: 'legacy-front-end'
}, },
{ {
id: 'bd7158d8c442eddfaeb5bd17', id: 'bd7158d8c442eddfaeb5bd17',
title: 'Build a JavaScript Calculator', title: 'Build a JavaScript Calculator',
link: `${legacyFrontEndBase}/build-a-javascript-calculator`, link: `${legacyFrontEndBase}/build-a-javascript-calculator`,
superBlock: 'legacy-front-end' certSlug: 'legacy-front-end'
}, },
{ {
id: 'bd7158d8c442eddfaeb5bd10', id: 'bd7158d8c442eddfaeb5bd10',
title: 'Show the Local Weather', title: 'Show the Local Weather',
link: `${legacyFrontEndBase}/show-the-local-weather`, link: `${legacyFrontEndBase}/show-the-local-weather`,
superBlock: 'legacy-front-end' certSlug: 'legacy-front-end'
}, },
{ {
id: 'bd7158d8c442eddfaeb5bd1f', id: 'bd7158d8c442eddfaeb5bd1f',
title: 'Use the TwitchTV JSON API', title: 'Use the TwitchTV JSON API',
link: `${legacyFrontEndBase}/use-the-twitchtv-json-api`, link: `${legacyFrontEndBase}/use-the-twitchtv-json-api`,
superBlock: 'legacy-front-end' certSlug: 'legacy-front-end'
}, },
{ {
id: 'bd7158d8c442eddfaeb5bd18', id: 'bd7158d8c442eddfaeb5bd18',
title: 'Stylize Stories on Camper News', title: 'Stylize Stories on Camper News',
link: `${legacyFrontEndBase}/stylize-stories-on-camper-news`, link: `${legacyFrontEndBase}/stylize-stories-on-camper-news`,
superBlock: 'legacy-front-end' certSlug: 'legacy-front-end'
}, },
{ {
id: 'bd7158d8c442eddfaeb5bd19', id: 'bd7158d8c442eddfaeb5bd19',
title: 'Build a Wikipedia Viewer', title: 'Build a Wikipedia Viewer',
link: `${legacyFrontEndBase}/build-a-wikipedia-viewer`, link: `${legacyFrontEndBase}/build-a-wikipedia-viewer`,
superBlock: 'legacy-front-end' certSlug: 'legacy-front-end'
}, },
{ {
id: 'bd7158d8c442eedfaeb5bd1c', id: 'bd7158d8c442eedfaeb5bd1c',
title: 'Build a Tic Tac Toe Game', title: 'Build a Tic Tac Toe Game',
link: `${legacyFrontEndBase}/build-a-tic-tac-toe-game`, link: `${legacyFrontEndBase}/build-a-tic-tac-toe-game`,
superBlock: 'legacy-front-end' certSlug: 'legacy-front-end'
}, },
{ {
id: 'bd7158d8c442eddfaeb5bd1c', id: 'bd7158d8c442eddfaeb5bd1c',
title: 'Build a Simon Game', title: 'Build a Simon Game',
link: `${legacyFrontEndBase}/build-a-simon-game`, link: `${legacyFrontEndBase}/build-a-simon-game`,
superBlock: 'legacy-front-end' certSlug: 'legacy-front-end'
} }
] ]
}, },
{ {
id: '660add10cb82ac38a17513be', id: '660add10cb82ac38a17513be',
title: 'Legacy Back End', title: 'Legacy Back End',
slug: 'legacy-back-end', certSlug: 'legacy-back-end',
flag: 'isBackEndCert', flag: 'isBackEndCert',
projects: [ projects: [
{ {
id: 'bd7158d8c443edefaeb5bdef', id: 'bd7158d8c443edefaeb5bdef',
title: 'Timestamp Microservice', title: 'Timestamp Microservice',
link: `${legacyBackEndBase}/timestamp-microservice`, link: `${legacyBackEndBase}/timestamp-microservice`,
superBlock: 'legacy-back-end' certSlug: 'legacy-back-end'
}, },
{ {
id: 'bd7158d8c443edefaeb5bdff', id: 'bd7158d8c443edefaeb5bdff',
title: 'Request Header Parser Microservice', title: 'Request Header Parser Microservice',
link: `${legacyBackEndBase}/request-header-parser-microservice`, link: `${legacyBackEndBase}/request-header-parser-microservice`,
superBlock: 'legacy-back-end' certSlug: 'legacy-back-end'
}, },
{ {
id: 'bd7158d8c443edefaeb5bd0e', id: 'bd7158d8c443edefaeb5bd0e',
title: 'URL Shortener Microservice', title: 'URL Shortener Microservice',
link: `${legacyBackEndBase}/url-shortener-microservice`, link: `${legacyBackEndBase}/url-shortener-microservice`,
superBlock: 'legacy-back-end' certSlug: 'legacy-back-end'
}, },
{ {
id: 'bd7158d8c443edefaeb5bdee', id: 'bd7158d8c443edefaeb5bdee',
title: 'Image Search Abstraction Layer', title: 'Image Search Abstraction Layer',
link: `${legacyBackEndBase}/image-search-abstraction-layer`, link: `${legacyBackEndBase}/image-search-abstraction-layer`,
superBlock: 'legacy-back-end' certSlug: 'legacy-back-end'
}, },
{ {
id: 'bd7158d8c443edefaeb5bd0f', id: 'bd7158d8c443edefaeb5bd0f',
title: 'File Metadata Microservice', title: 'File Metadata Microservice',
link: `${legacyBackEndBase}/file-metadata-microservice`, link: `${legacyBackEndBase}/file-metadata-microservice`,
superBlock: 'legacy-back-end' certSlug: 'legacy-back-end'
}, },
{ {
id: 'bd7158d8c443eddfaeb5bdef', id: 'bd7158d8c443eddfaeb5bdef',
title: 'Build a Voting App', title: 'Build a Voting App',
link: `${legacyBackEndBase}/build-a-voting-app`, link: `${legacyBackEndBase}/build-a-voting-app`,
superBlock: 'legacy-back-end' certSlug: 'legacy-back-end'
}, },
{ {
id: 'bd7158d8c443eddfaeb5bdff', id: 'bd7158d8c443eddfaeb5bdff',
title: 'Build a Nightlife Coordination App', title: 'Build a Nightlife Coordination App',
link: `${legacyBackEndBase}/build-a-nightlife-coordination-app`, link: `${legacyBackEndBase}/build-a-nightlife-coordination-app`,
superBlock: 'legacy-back-end' certSlug: 'legacy-back-end'
}, },
{ {
id: 'bd7158d8c443eddfaeb5bd0e', id: 'bd7158d8c443eddfaeb5bd0e',
title: 'Chart the Stock Market', title: 'Chart the Stock Market',
link: `${legacyBackEndBase}/chart-the-stock-market`, link: `${legacyBackEndBase}/chart-the-stock-market`,
superBlock: 'legacy-back-end' certSlug: 'legacy-back-end'
}, },
{ {
id: 'bd7158d8c443eddfaeb5bd0f', id: 'bd7158d8c443eddfaeb5bd0f',
title: 'Manage a Book Trading Club', title: 'Manage a Book Trading Club',
link: `${legacyBackEndBase}/manage-a-book-trading-club`, link: `${legacyBackEndBase}/manage-a-book-trading-club`,
superBlock: 'legacy-back-end' certSlug: 'legacy-back-end'
}, },
{ {
id: 'bd7158d8c443eddfaeb5bdee', id: 'bd7158d8c443eddfaeb5bdee',
title: 'Build a Pinterest Clone', title: 'Build a Pinterest Clone',
link: `${legacyBackEndBase}/build-a-pinterest-clone`, link: `${legacyBackEndBase}/build-a-pinterest-clone`,
superBlock: 'legacy-back-end' certSlug: 'legacy-back-end'
} }
] ]
}, },
{ {
id: '561add10cb82ac38a17213bd', id: '561add10cb82ac38a17213bd',
title: 'Legacy Full Stack', title: 'Legacy Full Stack',
slug: 'full-stack', certSlug: 'full-stack',
flag: 'isFullStackCert' flag: 'isFullStackCert'
// Requirements are other certs and is // Requirements are other certs and is
// handled elsewhere // handled elsewhere
@ -171,68 +171,68 @@ const certMap = [
{ {
id: '561add10cb82ac39a17513bc', id: '561add10cb82ac39a17513bc',
title: 'Legacy Data Visualization', title: 'Legacy Data Visualization',
slug: 'legacy-data-visualization', certSlug: 'legacy-data-visualization',
flag: 'isDataVisCert', flag: 'isDataVisCert',
projects: [ projects: [
{ {
id: 'bd7157d8c242eddfaeb5bd13', id: 'bd7157d8c242eddfaeb5bd13',
title: 'Build a Markdown Previewer', title: 'Build a Markdown Previewer',
link: `${legacyDataVisBase}/build-a-markdown-previewer`, link: `${legacyDataVisBase}/build-a-markdown-previewer`,
superBlock: 'legacy-data-visualization' certSlug: 'legacy-data-visualization'
}, },
{ {
id: 'bd7156d8c242eddfaeb5bd13', id: 'bd7156d8c242eddfaeb5bd13',
title: 'Build a Camper Leaderboard', title: 'Build a Camper Leaderboard',
link: `${legacyDataVisBase}/build-a-camper-leaderboard`, link: `${legacyDataVisBase}/build-a-camper-leaderboard`,
superBlock: 'legacy-data-visualization' certSlug: 'legacy-data-visualization'
}, },
{ {
id: 'bd7155d8c242eddfaeb5bd13', id: 'bd7155d8c242eddfaeb5bd13',
title: 'Build a Recipe Box', title: 'Build a Recipe Box',
link: `${legacyDataVisBase}/build-a-recipe-box`, link: `${legacyDataVisBase}/build-a-recipe-box`,
superBlock: 'legacy-data-visualization' certSlug: 'legacy-data-visualization'
}, },
{ {
id: 'bd7154d8c242eddfaeb5bd13', id: 'bd7154d8c242eddfaeb5bd13',
title: 'Build the Game of Life', title: 'Build the Game of Life',
link: `${legacyDataVisBase}/build-the-game-of-life`, link: `${legacyDataVisBase}/build-the-game-of-life`,
superBlock: 'legacy-data-visualization' certSlug: 'legacy-data-visualization'
}, },
{ {
id: 'bd7153d8c242eddfaeb5bd13', id: 'bd7153d8c242eddfaeb5bd13',
title: 'Build a Roguelike Dungeon Crawler Game', title: 'Build a Roguelike Dungeon Crawler Game',
link: `${legacyDataVisBase}/build-a-roguelike-dungeon-crawler-game`, link: `${legacyDataVisBase}/build-a-roguelike-dungeon-crawler-game`,
superBlock: 'legacy-data-visualization' certSlug: 'legacy-data-visualization'
}, },
{ {
id: 'bd7168d8c242eddfaeb5bd13', id: 'bd7168d8c242eddfaeb5bd13',
title: 'Visualize Data with a Bar Chart', title: 'Visualize Data with a Bar Chart',
link: `${legacyDataVisBase}/visualize-data-with-a-bar-chart`, link: `${legacyDataVisBase}/visualize-data-with-a-bar-chart`,
superBlock: 'legacy-data-visualization' certSlug: 'legacy-data-visualization'
}, },
{ {
id: 'bd7178d8c242eddfaeb5bd13', id: 'bd7178d8c242eddfaeb5bd13',
title: 'Visualize Data with a Scatterplot Graph', title: 'Visualize Data with a Scatterplot Graph',
link: `${legacyDataVisBase}/visualize-data-with-a-scatterplot-graph`, link: `${legacyDataVisBase}/visualize-data-with-a-scatterplot-graph`,
superBlock: 'legacy-data-visualization' certSlug: 'legacy-data-visualization'
}, },
{ {
id: 'bd7188d8c242eddfaeb5bd13', id: 'bd7188d8c242eddfaeb5bd13',
title: 'Visualize Data with a Heat Map', title: 'Visualize Data with a Heat Map',
link: `${legacyDataVisBase}/visualize-data-with-a-heat-map`, link: `${legacyDataVisBase}/visualize-data-with-a-heat-map`,
superBlock: 'legacy-data-visualization' certSlug: 'legacy-data-visualization'
}, },
{ {
id: 'bd7198d8c242eddfaeb5bd13', id: 'bd7198d8c242eddfaeb5bd13',
title: 'Show National Contiguity with a Force Directed Graph', title: 'Show National Contiguity with a Force Directed Graph',
link: `${legacyDataVisBase}/show-national-contiguity-with-a-force-directed-graph`, link: `${legacyDataVisBase}/show-national-contiguity-with-a-force-directed-graph`,
superBlock: 'legacy-data-visualization' certSlug: 'legacy-data-visualization'
}, },
{ {
id: 'bd7108d8c242eddfaeb5bd13', id: 'bd7108d8c242eddfaeb5bd13',
title: 'Map Data Across the Globe', title: 'Map Data Across the Globe',
link: `${legacyDataVisBase}/map-data-across-the-globe`, link: `${legacyDataVisBase}/map-data-across-the-globe`,
superBlock: 'legacy-data-visualization' certSlug: 'legacy-data-visualization'
} }
] ]
}, },
@ -240,7 +240,7 @@ const certMap = [
id: '561add10cb82ac38a17213bc', id: '561add10cb82ac38a17213bc',
title: 'Legacy Information Security and Quality Assurance', title: 'Legacy Information Security and Quality Assurance',
// Keep this as information-security-and-quality-assurance // Keep this as information-security-and-quality-assurance
slug: 'information-security-and-quality-assurance', certSlug: 'information-security-and-quality-assurance',
flag: 'isInfosecQaCert', flag: 'isInfosecQaCert',
projects: [ projects: [
// Keep this as information-security-and-quality-assurance // Keep this as information-security-and-quality-assurance
@ -248,335 +248,335 @@ const certMap = [
id: '587d8249367417b2b2512c41', id: '587d8249367417b2b2512c41',
title: 'Metric-Imperial Converter', title: 'Metric-Imperial Converter',
link: `${legacyInfosecQaBase}/metric-imperial-converter`, link: `${legacyInfosecQaBase}/metric-imperial-converter`,
superBlock: 'information-security-and-quality-assurance' certSlug: 'information-security-and-quality-assurance'
}, },
{ {
id: '587d8249367417b2b2512c42', id: '587d8249367417b2b2512c42',
title: 'Issue Tracker', title: 'Issue Tracker',
link: `${legacyInfosecQaBase}/issue-tracker`, link: `${legacyInfosecQaBase}/issue-tracker`,
superBlock: 'information-security-and-quality-assurance' certSlug: 'information-security-and-quality-assurance'
}, },
{ {
id: '587d824a367417b2b2512c43', id: '587d824a367417b2b2512c43',
title: 'Personal Library', title: 'Personal Library',
link: `${legacyInfosecQaBase}/personal-library`, link: `${legacyInfosecQaBase}/personal-library`,
superBlock: 'information-security-and-quality-assurance' certSlug: 'information-security-and-quality-assurance'
}, },
{ {
id: '587d824a367417b2b2512c44', id: '587d824a367417b2b2512c44',
title: 'Stock Price Checker', title: 'Stock Price Checker',
link: `${legacyInfosecQaBase}/stock-price-checker`, link: `${legacyInfosecQaBase}/stock-price-checker`,
superBlock: 'information-security-and-quality-assurance' certSlug: 'information-security-and-quality-assurance'
}, },
{ {
id: '587d824a367417b2b2512c45', id: '587d824a367417b2b2512c45',
title: 'Anonymous Message Board', title: 'Anonymous Message Board',
link: `${legacyInfosecQaBase}/anonymous-message-board`, link: `${legacyInfosecQaBase}/anonymous-message-board`,
superBlock: 'information-security-and-quality-assurance' certSlug: 'information-security-and-quality-assurance'
} }
] ]
}, },
{ {
id: '561add10cb82ac38a17513bc', id: '561add10cb82ac38a17513bc',
title: 'Responsive Web Design', title: 'Responsive Web Design',
slug: 'responsive-web-design', certSlug: 'responsive-web-design',
flag: 'isRespWebDesignCert', flag: 'isRespWebDesignCert',
projects: [ projects: [
{ {
id: 'bd7158d8c442eddfaeb5bd18', id: 'bd7158d8c442eddfaeb5bd18',
title: 'Build a Tribute Page', title: 'Build a Tribute Page',
link: `${responsiveWebBase}/build-a-tribute-page`, link: `${responsiveWebBase}/build-a-tribute-page`,
superBlock: 'responsive-web-design' certSlug: 'responsive-web-design'
}, },
{ {
id: '587d78af367417b2b2512b03', id: '587d78af367417b2b2512b03',
title: 'Build a Survey Form', title: 'Build a Survey Form',
link: `${responsiveWebBase}/build-a-survey-form`, link: `${responsiveWebBase}/build-a-survey-form`,
superBlock: 'responsive-web-design' certSlug: 'responsive-web-design'
}, },
{ {
id: '587d78af367417b2b2512b04', id: '587d78af367417b2b2512b04',
title: 'Build a Product Landing Page', title: 'Build a Product Landing Page',
link: `${responsiveWebBase}/build-a-product-landing-page`, link: `${responsiveWebBase}/build-a-product-landing-page`,
superBlock: 'responsive-web-design' certSlug: 'responsive-web-design'
}, },
{ {
id: '587d78b0367417b2b2512b05', id: '587d78b0367417b2b2512b05',
title: 'Build a Technical Documentation Page', title: 'Build a Technical Documentation Page',
link: `${responsiveWebBase}/build-a-technical-documentation-page`, link: `${responsiveWebBase}/build-a-technical-documentation-page`,
superBlock: 'responsive-web-design' certSlug: 'responsive-web-design'
}, },
{ {
id: 'bd7158d8c242eddfaeb5bd13', id: 'bd7158d8c242eddfaeb5bd13',
title: 'Build a Personal Portfolio Webpage', title: 'Build a Personal Portfolio Webpage',
link: `${responsiveWebBase}/build-a-personal-portfolio-webpage`, link: `${responsiveWebBase}/build-a-personal-portfolio-webpage`,
superBlock: 'responsive-web-design' certSlug: 'responsive-web-design'
} }
] ]
}, },
{ {
id: '561abd10cb81ac38a17513bc', id: '561abd10cb81ac38a17513bc',
title: 'JavaScript Algorithms and Data Structures', title: 'JavaScript Algorithms and Data Structures',
slug: 'javascript-algorithms-and-data-structures', certSlug: 'javascript-algorithms-and-data-structures',
flag: 'isJsAlgoDataStructCert', flag: 'isJsAlgoDataStructCert',
projects: [ projects: [
{ {
id: 'aaa48de84e1ecc7c742e1124', id: 'aaa48de84e1ecc7c742e1124',
title: 'Palindrome Checker', title: 'Palindrome Checker',
link: `${jsAlgoBase}/palindrome-checker`, link: `${jsAlgoBase}/palindrome-checker`,
superBlock: 'javascript-algorithms-and-data-structures' certSlug: 'javascript-algorithms-and-data-structures'
}, },
{ {
id: 'a7f4d8f2483413a6ce226cac', id: 'a7f4d8f2483413a6ce226cac',
title: 'Roman Numeral Converter', title: 'Roman Numeral Converter',
link: `${jsAlgoBase}/roman-numeral-converter`, link: `${jsAlgoBase}/roman-numeral-converter`,
superBlock: 'javascript-algorithms-and-data-structures' certSlug: 'javascript-algorithms-and-data-structures'
}, },
{ {
id: '56533eb9ac21ba0edf2244e2', id: '56533eb9ac21ba0edf2244e2',
title: 'Caesars Cipher', title: 'Caesars Cipher',
link: `${jsAlgoBase}/caesars-cipher`, link: `${jsAlgoBase}/caesars-cipher`,
superBlock: 'javascript-algorithms-and-data-structures' certSlug: 'javascript-algorithms-and-data-structures'
}, },
{ {
id: 'aff0395860f5d3034dc0bfc9', id: 'aff0395860f5d3034dc0bfc9',
title: 'Telephone Number Validator', title: 'Telephone Number Validator',
link: `${jsAlgoBase}/telephone-number-validator`, link: `${jsAlgoBase}/telephone-number-validator`,
superBlock: 'javascript-algorithms-and-data-structures' certSlug: 'javascript-algorithms-and-data-structures'
}, },
{ {
id: 'aa2e6f85cab2ab736c9a9b24', id: 'aa2e6f85cab2ab736c9a9b24',
title: 'Cash Register', title: 'Cash Register',
link: `${jsAlgoBase}/cash-register`, link: `${jsAlgoBase}/cash-register`,
superBlock: 'javascript-algorithms-and-data-structures' certSlug: 'javascript-algorithms-and-data-structures'
} }
] ]
}, },
{ {
id: '561acd10cb82ac38a17513bc', id: '561acd10cb82ac38a17513bc',
title: 'Front End Libraries', title: 'Front End Libraries',
slug: 'front-end-libraries', certSlug: 'front-end-libraries',
flag: 'isFrontEndLibsCert', flag: 'isFrontEndLibsCert',
projects: [ projects: [
{ {
id: 'bd7158d8c442eddfaeb5bd13', id: 'bd7158d8c442eddfaeb5bd13',
title: 'Build a Random Quote Machine', title: 'Build a Random Quote Machine',
link: `${feLibsBase}/build-a-random-quote-machine`, link: `${feLibsBase}/build-a-random-quote-machine`,
superBlock: 'front-end-libraries' certSlug: 'front-end-libraries'
}, },
{ {
id: 'bd7157d8c242eddfaeb5bd13', id: 'bd7157d8c242eddfaeb5bd13',
title: 'Build a Markdown Previewer', title: 'Build a Markdown Previewer',
link: `${feLibsBase}/build-a-markdown-previewer`, link: `${feLibsBase}/build-a-markdown-previewer`,
superBlock: 'front-end-libraries' certSlug: 'front-end-libraries'
}, },
{ {
id: '587d7dbc367417b2b2512bae', id: '587d7dbc367417b2b2512bae',
title: 'Build a Drum Machine', title: 'Build a Drum Machine',
link: `${feLibsBase}/build-a-drum-machine`, link: `${feLibsBase}/build-a-drum-machine`,
superBlock: 'front-end-libraries' certSlug: 'front-end-libraries'
}, },
{ {
id: 'bd7158d8c442eddfaeb5bd17', id: 'bd7158d8c442eddfaeb5bd17',
title: 'Build a JavaScript Calculator', title: 'Build a JavaScript Calculator',
link: `${feLibsBase}/build-a-javascript-calculator`, link: `${feLibsBase}/build-a-javascript-calculator`,
superBlock: 'front-end-libraries' certSlug: 'front-end-libraries'
}, },
{ {
id: 'bd7158d8c442eddfaeb5bd0f', id: 'bd7158d8c442eddfaeb5bd0f',
title: 'Build a 25 + 5 Clock', title: 'Build a 25 + 5 Clock',
link: `${feLibsBase}/build-a-25--5-clock`, link: `${feLibsBase}/build-a-25--5-clock`,
superBlock: 'front-end-libraries' certSlug: 'front-end-libraries'
} }
] ]
}, },
{ {
id: '5a553ca864b52e1d8bceea14', id: '5a553ca864b52e1d8bceea14',
title: 'Data Visualization', title: 'Data Visualization',
slug: 'data-visualization', certSlug: 'data-visualization',
flag: 'is2018DataVisCert', flag: 'is2018DataVisCert',
projects: [ projects: [
{ {
id: 'bd7168d8c242eddfaeb5bd13', id: 'bd7168d8c242eddfaeb5bd13',
title: 'Visualize Data with a Bar Chart', title: 'Visualize Data with a Bar Chart',
link: `${dataVisBase}/visualize-data-with-a-bar-chart`, link: `${dataVisBase}/visualize-data-with-a-bar-chart`,
superBlock: 'data-visualization' certSlug: 'data-visualization'
}, },
{ {
id: 'bd7178d8c242eddfaeb5bd13', id: 'bd7178d8c242eddfaeb5bd13',
title: 'Visualize Data with a Scatterplot Graph', title: 'Visualize Data with a Scatterplot Graph',
link: `${dataVisBase}/visualize-data-with-a-scatterplot-graph`, link: `${dataVisBase}/visualize-data-with-a-scatterplot-graph`,
superBlock: 'data-visualization' certSlug: 'data-visualization'
}, },
{ {
id: 'bd7188d8c242eddfaeb5bd13', id: 'bd7188d8c242eddfaeb5bd13',
title: 'Visualize Data with a Heat Map', title: 'Visualize Data with a Heat Map',
link: `${dataVisBase}/visualize-data-with-a-heat-map`, link: `${dataVisBase}/visualize-data-with-a-heat-map`,
superBlock: 'data-visualization' certSlug: 'data-visualization'
}, },
{ {
id: '587d7fa6367417b2b2512bbf', id: '587d7fa6367417b2b2512bbf',
title: 'Visualize Data with a Choropleth Map', title: 'Visualize Data with a Choropleth Map',
link: `${dataVisBase}/visualize-data-with-a-choropleth-map`, link: `${dataVisBase}/visualize-data-with-a-choropleth-map`,
superBlock: 'data-visualization' certSlug: 'data-visualization'
}, },
{ {
id: '587d7fa6367417b2b2512bc0', id: '587d7fa6367417b2b2512bc0',
title: 'Visualize Data with a Treemap Diagram', title: 'Visualize Data with a Treemap Diagram',
link: `${dataVisBase}/visualize-data-with-a-treemap-diagram`, link: `${dataVisBase}/visualize-data-with-a-treemap-diagram`,
superBlock: 'data-visualization' certSlug: 'data-visualization'
} }
] ]
}, },
{ {
id: '561add10cb82ac38a17523bc', id: '561add10cb82ac38a17523bc',
title: 'APIs and Microservices', title: 'APIs and Microservices',
slug: 'apis-and-microservices', certSlug: 'apis-and-microservices',
flag: 'isApisMicroservicesCert', flag: 'isApisMicroservicesCert',
projects: [ projects: [
{ {
id: 'bd7158d8c443edefaeb5bdef', id: 'bd7158d8c443edefaeb5bdef',
title: 'Timestamp Microservice', title: 'Timestamp Microservice',
link: `${apiMicroBase}/timestamp-microservice`, link: `${apiMicroBase}/timestamp-microservice`,
superBlock: 'apis-and-microservices' certSlug: 'apis-and-microservices'
}, },
{ {
id: 'bd7158d8c443edefaeb5bdff', id: 'bd7158d8c443edefaeb5bdff',
title: 'Request Header Parser Microservice', title: 'Request Header Parser Microservice',
link: `${apiMicroBase}/request-header-parser-microservice`, link: `${apiMicroBase}/request-header-parser-microservice`,
superBlock: 'apis-and-microservices' certSlug: 'apis-and-microservices'
}, },
{ {
id: 'bd7158d8c443edefaeb5bd0e', id: 'bd7158d8c443edefaeb5bd0e',
title: 'URL Shortener Microservice', title: 'URL Shortener Microservice',
link: `${apiMicroBase}/url-shortener-microservice`, link: `${apiMicroBase}/url-shortener-microservice`,
superBlock: 'apis-and-microservices' certSlug: 'apis-and-microservices'
}, },
{ {
id: '5a8b073d06fa14fcfde687aa', id: '5a8b073d06fa14fcfde687aa',
title: 'Exercise Tracker', title: 'Exercise Tracker',
link: `${apiMicroBase}/exercise-tracker`, link: `${apiMicroBase}/exercise-tracker`,
superBlock: 'apis-and-microservices' certSlug: 'apis-and-microservices'
}, },
{ {
id: 'bd7158d8c443edefaeb5bd0f', id: 'bd7158d8c443edefaeb5bd0f',
title: 'File Metadata Microservice', title: 'File Metadata Microservice',
link: `${apiMicroBase}/file-metadata-microservice`, link: `${apiMicroBase}/file-metadata-microservice`,
superBlock: 'apis-and-microservices' certSlug: 'apis-and-microservices'
} }
] ]
}, },
{ {
id: '5e611829481575a52dc59c0e', id: '5e611829481575a52dc59c0e',
title: 'Quality Assurance', title: 'Quality Assurance',
slug: 'quality-assurance-v7', certSlug: 'quality-assurance-v7',
flag: 'isQaCertV7', flag: 'isQaCertV7',
projects: [ projects: [
{ {
id: '587d8249367417b2b2512c41', id: '587d8249367417b2b2512c41',
title: 'Metric-Imperial Converter', title: 'Metric-Imperial Converter',
link: `${qaBase}/metric-imperial-converter`, link: `${qaBase}/metric-imperial-converter`,
superBlock: 'quality-assurance-v7' certSlug: 'quality-assurance-v7'
}, },
{ {
id: '587d8249367417b2b2512c42', id: '587d8249367417b2b2512c42',
title: 'Issue Tracker', title: 'Issue Tracker',
link: `${qaBase}/issue-tracker`, link: `${qaBase}/issue-tracker`,
superBlock: 'quality-assurance-v7' certSlug: 'quality-assurance-v7'
}, },
{ {
id: '587d824a367417b2b2512c43', id: '587d824a367417b2b2512c43',
title: 'Personal Library', title: 'Personal Library',
link: `${qaBase}/personal-library`, link: `${qaBase}/personal-library`,
superBlock: 'quality-assurance-v7' certSlug: 'quality-assurance-v7'
}, },
{ {
id: '5e601bf95ac9d0ecd8b94afd', id: '5e601bf95ac9d0ecd8b94afd',
title: 'Sudoku Solver', title: 'Sudoku Solver',
link: `${qaBase}/sudoku-solver`, link: `${qaBase}/sudoku-solver`,
superBlock: 'quality-assurance-v7' certSlug: 'quality-assurance-v7'
}, },
{ {
id: '5e601c0d5ac9d0ecd8b94afe', id: '5e601c0d5ac9d0ecd8b94afe',
title: 'American British Translator', title: 'American British Translator',
link: `${qaBase}/american-british-translator`, link: `${qaBase}/american-british-translator`,
superBlock: 'quality-assurance-v7' certSlug: 'quality-assurance-v7'
} }
] ]
}, },
{ {
id: '5e44431b903586ffb414c951', id: '5e44431b903586ffb414c951',
title: 'Scientific Computing with Python', title: 'Scientific Computing with Python',
slug: 'scientific-computing-with-python-v7', certSlug: 'scientific-computing-with-python-v7',
flag: 'isSciCompPyCertV7', flag: 'isSciCompPyCertV7',
projects: [ projects: [
{ {
id: '5e44412c903586ffb414c94c', id: '5e44412c903586ffb414c94c',
title: 'Arithmetic Formatter', title: 'Arithmetic Formatter',
link: `${sciCompPyBase}/arithmetic-formatter`, link: `${sciCompPyBase}/arithmetic-formatter`,
superBlock: 'scientific-computing-with-python-v7' certSlug: 'scientific-computing-with-python-v7'
}, },
{ {
id: '5e444136903586ffb414c94d', id: '5e444136903586ffb414c94d',
title: 'Time Calculator', title: 'Time Calculator',
link: `${sciCompPyBase}/time-calculator`, link: `${sciCompPyBase}/time-calculator`,
superBlock: 'scientific-computing-with-python-v7' certSlug: 'scientific-computing-with-python-v7'
}, },
{ {
id: '5e44413e903586ffb414c94e', id: '5e44413e903586ffb414c94e',
title: 'Budget App', title: 'Budget App',
link: `${sciCompPyBase}/budget-app`, link: `${sciCompPyBase}/budget-app`,
superBlock: 'scientific-computing-with-python-v7' certSlug: 'scientific-computing-with-python-v7'
}, },
{ {
id: '5e444147903586ffb414c94f', id: '5e444147903586ffb414c94f',
title: 'Polygon Area Calculator', title: 'Polygon Area Calculator',
link: `${sciCompPyBase}/polygon-area-calculator`, link: `${sciCompPyBase}/polygon-area-calculator`,
superBlock: 'scientific-computing-with-python-v7' certSlug: 'scientific-computing-with-python-v7'
}, },
{ {
id: '5e44414f903586ffb414c950', id: '5e44414f903586ffb414c950',
title: 'Probability Calculator', title: 'Probability Calculator',
link: `${sciCompPyBase}/probability-calculator`, link: `${sciCompPyBase}/probability-calculator`,
superBlock: 'scientific-computing-with-python-v7' certSlug: 'scientific-computing-with-python-v7'
} }
] ]
}, },
{ {
id: '5e46fc95ac417301a38fb934', id: '5e46fc95ac417301a38fb934',
title: 'Data Analysis with Python', title: 'Data Analysis with Python',
slug: 'data-analysis-with-python-v7', certSlug: 'data-analysis-with-python-v7',
flag: 'isDataAnalysisPyCertV7', flag: 'isDataAnalysisPyCertV7',
projects: [ projects: [
{ {
id: '5e46f7e5ac417301a38fb928', id: '5e46f7e5ac417301a38fb928',
title: 'Mean-Variance-Standard Deviation Calculator', title: 'Mean-Variance-Standard Deviation Calculator',
link: `${dataAnalysisPyBase}/mean-variance-standard-deviation-calculator`, link: `${dataAnalysisPyBase}/mean-variance-standard-deviation-calculator`,
superBlock: 'data-analysis-with-python-v7' certSlug: 'data-analysis-with-python-v7'
}, },
{ {
id: '5e46f7e5ac417301a38fb929', id: '5e46f7e5ac417301a38fb929',
title: 'Demographic Data Analyzer', title: 'Demographic Data Analyzer',
link: `${dataAnalysisPyBase}/demographic-data-analyzer`, link: `${dataAnalysisPyBase}/demographic-data-analyzer`,
superBlock: 'data-analysis-with-python-v7' certSlug: 'data-analysis-with-python-v7'
}, },
{ {
id: '5e46f7f8ac417301a38fb92a', id: '5e46f7f8ac417301a38fb92a',
title: 'Medical Data Visualizer', title: 'Medical Data Visualizer',
link: `${dataAnalysisPyBase}/medical-data-visualizer`, link: `${dataAnalysisPyBase}/medical-data-visualizer`,
superBlock: 'data-analysis-with-python-v7' certSlug: 'data-analysis-with-python-v7'
}, },
{ {
id: '5e46f802ac417301a38fb92b', id: '5e46f802ac417301a38fb92b',
title: 'Page View Time Series Visualizer', title: 'Page View Time Series Visualizer',
link: `${dataAnalysisPyBase}/page-view-time-series-visualizer`, link: `${dataAnalysisPyBase}/page-view-time-series-visualizer`,
superBlock: 'data-analysis-with-python-v7' certSlug: 'data-analysis-with-python-v7'
}, },
{ {
id: '5e4f5c4b570f7e3a4949899f', id: '5e4f5c4b570f7e3a4949899f',
title: 'Sea Level Predictor', title: 'Sea Level Predictor',
link: `${dataAnalysisPyBase}/sea-level-predictor`, link: `${dataAnalysisPyBase}/sea-level-predictor`,
superBlock: 'data-analysis-with-python-v7' certSlug: 'data-analysis-with-python-v7'
} }
] ]
}, },
@ -584,76 +584,76 @@ const certMap = [
{ {
id: '5e6021435ac9d0ecd8b94b00', id: '5e6021435ac9d0ecd8b94b00',
title: 'Information Security', title: 'Information Security',
slug: 'information-security-v7', certSlug: 'information-security-v7',
flag: 'isInfosecCertV7', flag: 'isInfosecCertV7',
projects: [ projects: [
{ {
id: '587d824a367417b2b2512c44', id: '587d824a367417b2b2512c44',
title: 'Stock Price Checker', title: 'Stock Price Checker',
link: `${infoSecBase}/stock-price-checker`, link: `${infoSecBase}/stock-price-checker`,
superBlock: 'information-security-v7' certSlug: 'information-security-v7'
}, },
{ {
id: '587d824a367417b2b2512c45', id: '587d824a367417b2b2512c45',
title: 'Anonymous Message Board', title: 'Anonymous Message Board',
link: `${infoSecBase}/anonymous-message-board`, link: `${infoSecBase}/anonymous-message-board`,
superBlock: 'information-security-v7' certSlug: 'information-security-v7'
}, },
{ {
id: '5e46f979ac417301a38fb932', id: '5e46f979ac417301a38fb932',
title: 'Port Scanner', title: 'Port Scanner',
link: `${infoSecBase}/port-scanner`, link: `${infoSecBase}/port-scanner`,
superBlock: 'information-security-v7' certSlug: 'information-security-v7'
}, },
{ {
id: '5e46f983ac417301a38fb933', id: '5e46f983ac417301a38fb933',
title: 'SHA-1 Password Cracker', title: 'SHA-1 Password Cracker',
link: `${infoSecBase}/sha-1-password-cracker`, link: `${infoSecBase}/sha-1-password-cracker`,
superBlock: 'information-security-v7' certSlug: 'information-security-v7'
}, },
{ {
id: '5e601c775ac9d0ecd8b94aff', id: '5e601c775ac9d0ecd8b94aff',
title: 'Secure Real Time Multiplayer Game', title: 'Secure Real Time Multiplayer Game',
link: `${infoSecBase}/secure-real-time-multiplayer-game`, link: `${infoSecBase}/secure-real-time-multiplayer-game`,
superBlock: 'information-security-v7' certSlug: 'information-security-v7'
} }
] ]
}, },
{ {
id: '5e46fc95ac417301a38fb935', id: '5e46fc95ac417301a38fb935',
title: 'Machine Learning with Python', title: 'Machine Learning with Python',
slug: 'machine-learning-with-python-v7', certSlug: 'machine-learning-with-python-v7',
flag: 'isMachineLearningPyCertV7', flag: 'isMachineLearningPyCertV7',
projects: [ projects: [
{ {
id: '5e46f8d6ac417301a38fb92d', id: '5e46f8d6ac417301a38fb92d',
title: 'Rock Paper Scissors', title: 'Rock Paper Scissors',
link: `${machineLearningPyBase}/rock-paper-scissors`, link: `${machineLearningPyBase}/rock-paper-scissors`,
superBlock: 'machine-learning-with-python-v7' certSlug: 'machine-learning-with-python-v7'
}, },
{ {
id: '5e46f8dcac417301a38fb92e', id: '5e46f8dcac417301a38fb92e',
title: 'Cat and Dog Image Classifier', title: 'Cat and Dog Image Classifier',
link: `${machineLearningPyBase}/cat-and-dog-image-classifier`, link: `${machineLearningPyBase}/cat-and-dog-image-classifier`,
superBlock: 'machine-learning-with-python-v7' certSlug: 'machine-learning-with-python-v7'
}, },
{ {
id: '5e46f8e3ac417301a38fb92f', id: '5e46f8e3ac417301a38fb92f',
title: 'Book Recommendation Engine using KNN', title: 'Book Recommendation Engine using KNN',
link: `${machineLearningPyBase}/book-recommendation-engine-using-knn`, link: `${machineLearningPyBase}/book-recommendation-engine-using-knn`,
superBlock: 'machine-learning-with-python-v7' certSlug: 'machine-learning-with-python-v7'
}, },
{ {
id: '5e46f8edac417301a38fb930', id: '5e46f8edac417301a38fb930',
title: 'Linear Regression Health Costs Calculator', title: 'Linear Regression Health Costs Calculator',
link: `${machineLearningPyBase}/linear-regression-health-costs-calculator`, link: `${machineLearningPyBase}/linear-regression-health-costs-calculator`,
superBlock: 'machine-learning-with-python-v7' certSlug: 'machine-learning-with-python-v7'
}, },
{ {
id: '5e46f8edac417301a38fb931', id: '5e46f8edac417301a38fb931',
title: 'Neural Network SMS Text Classifier', title: 'Neural Network SMS Text Classifier',
link: `${machineLearningPyBase}/neural-network-sms-text-classifier`, link: `${machineLearningPyBase}/neural-network-sms-text-classifier`,
superBlock: 'machine-learning-with-python-v7' certSlug: 'machine-learning-with-python-v7'
} }
] ]
} }

View File

@ -19,10 +19,11 @@ import { Spacer } from '../../components/helpers';
import { import {
currentChallengeIdSelector, currentChallengeIdSelector,
userFetchStateSelector, userFetchStateSelector,
isSignedInSelector isSignedInSelector,
userSelector
} from '../../redux'; } from '../../redux';
import { resetExpansion, toggleBlock } from './redux'; import { resetExpansion, toggleBlock } from './redux';
import { MarkdownRemark, AllChallengeNode } from '../../redux/propTypes'; import { MarkdownRemark, AllChallengeNode, User } from '../../redux/propTypes';
import './intro.css'; import './intro.css';
@ -47,7 +48,8 @@ const propTypes = {
}), }),
resetExpansion: PropTypes.func, resetExpansion: PropTypes.func,
t: PropTypes.func, t: PropTypes.func,
toggleBlock: PropTypes.func toggleBlock: PropTypes.func,
user: User
}; };
configureAnchors({ offset: -40, scrollDuration: 0 }); configureAnchors({ offset: -40, scrollDuration: 0 });
@ -57,10 +59,12 @@ const mapStateToProps = state => {
currentChallengeIdSelector, currentChallengeIdSelector,
isSignedInSelector, isSignedInSelector,
userFetchStateSelector, userFetchStateSelector,
(currentChallengeId, isSignedIn, fetchState) => ({ userSelector,
(currentChallengeId, isSignedIn, fetchState, user) => ({
currentChallengeId, currentChallengeId,
isSignedIn, isSignedIn,
fetchState fetchState,
user
}) })
)(state); )(state);
}; };
@ -137,12 +141,12 @@ class SuperBlockIntroductionPage extends Component {
allChallengeNode: { edges } allChallengeNode: { edges }
}, },
isSignedIn, isSignedIn,
t t,
user
} = this.props; } = this.props;
const nodesForSuperBlock = edges.map(({ node }) => node); const nodesForSuperBlock = edges.map(({ node }) => node);
const blockDashedNames = uniq(nodesForSuperBlock.map(({ block }) => block)); const blockDashedNames = uniq(nodesForSuperBlock.map(({ block }) => block));
const i18nSuperBlock = t(`intro:${superBlock}.title`); const i18nSuperBlock = t(`intro:${superBlock}.title`);
return ( return (
@ -168,14 +172,18 @@ class SuperBlockIntroductionPage extends Component {
challenges={nodesForSuperBlock.filter( challenges={nodesForSuperBlock.filter(
node => node.block === blockDashedName node => node.block === blockDashedName
)} )}
superBlockDashedName={superBlock} superBlock={superBlock}
/> />
{blockDashedName !== 'project-euler' ? <Spacer /> : null} {blockDashedName !== 'project-euler' ? <Spacer /> : null}
</Fragment> </Fragment>
))} ))}
{superBlock !== 'coding-interview-prep' && ( {superBlock !== 'coding-interview-prep' && (
<div> <div>
<CertChallenge superBlock={superBlock} title={title} /> <CertChallenge
superBlock={superBlock}
title={title}
user={user}
/>
</div> </div>
)} )}
</div> </div>

View File

@ -40,7 +40,7 @@ const propTypes = {
completedChallenges: PropTypes.arrayOf(PropTypes.string), completedChallenges: PropTypes.arrayOf(PropTypes.string),
executeGA: PropTypes.func, executeGA: PropTypes.func,
isExpanded: PropTypes.bool, isExpanded: PropTypes.bool,
superBlockDashedName: PropTypes.string, superBlock: PropTypes.string,
t: PropTypes.func, t: PropTypes.func,
toggleBlock: PropTypes.func.isRequired toggleBlock: PropTypes.func.isRequired
}; };
@ -90,7 +90,7 @@ export class Block extends Component {
completedChallenges, completedChallenges,
challenges, challenges,
isExpanded, isExpanded,
superBlockDashedName, superBlock,
t t
} = this.props; } = this.props;
@ -123,9 +123,7 @@ export class Block extends Component {
); );
}); });
const blockIntroObj = t( const blockIntroObj = t(`intro:${superBlock}.blocks.${blockDashedName}`);
`intro:${superBlockDashedName}.blocks.${blockDashedName}`
);
const blockTitle = blockIntroObj ? blockIntroObj.title : null; const blockTitle = blockIntroObj ? blockIntroObj.title : null;
const blockIntroArr = blockIntroObj ? blockIntroObj.intro : []; const blockIntroArr = blockIntroObj ? blockIntroObj.intro : [];
const { const {
@ -144,7 +142,7 @@ export class Block extends Component {
<span className='block-link-icon'>#</span> <span className='block-link-icon'>#</span>
</h3> </h3>
</a> </a>
{!isAuditedCert(curriculumLocale, superBlockDashedName) && ( {!isAuditedCert(curriculumLocale, superBlock) && (
<div className='block-cta-wrapper'> <div className='block-cta-wrapper'>
<Link <Link
className='block-title-translation-cta' className='block-title-translation-cta'
@ -172,7 +170,7 @@ export class Block extends Component {
<span className='block-link-icon'>#</span> <span className='block-link-icon'>#</span>
</h3> </h3>
</a> </a>
{!isAuditedCert(curriculumLocale, superBlockDashedName) && ( {!isAuditedCert(curriculumLocale, superBlock) && (
<div className='block-cta-wrapper'> <div className='block-cta-wrapper'>
<Link <Link
className='block-title-translation-cta' className='block-title-translation-cta'

View File

@ -8,21 +8,29 @@ import { withTranslation } from 'react-i18next';
import CertificationIcon from '../../../assets/icons/CertificationIcon'; import CertificationIcon from '../../../assets/icons/CertificationIcon';
import GreenPass from '../../../assets/icons/GreenPass'; import GreenPass from '../../../assets/icons/GreenPass';
import GreenNotCompleted from '../../../assets/icons/GreenNotCompleted'; import GreenNotCompleted from '../../../assets/icons/GreenNotCompleted';
import { userSelector } from '../../../redux'; import { certificatesByNameSelector } from '../../../redux';
import { User } from '../../../redux/propTypes'; import { CurrentCertsType, User } from '../../../redux/propTypes';
import { certMap } from '../../../resources/certAndProjectMap'; import { certMap } from '../../../resources/certAndProjectMap';
import {
certSlugTypeMap,
superBlockCertTypeMap
} from '../../../../../config/certification-settings';
const propTypes = { const propTypes = {
currentCerts: CurrentCertsType,
superBlock: PropTypes.string, superBlock: PropTypes.string,
t: PropTypes.func, t: PropTypes.func,
title: PropTypes.string, title: PropTypes.string,
user: User user: User
}; };
const mapStateToProps = state => { const mapStateToProps = (state, props) => {
return createSelector(userSelector, user => ({ return createSelector(
user certificatesByNameSelector(props.user.username),
}))(state); ({ currentCerts }) => ({
currentCerts
})
)(state, props);
}; };
export class CertChallenge extends Component { export class CertChallenge extends Component {
@ -31,37 +39,16 @@ export class CertChallenge extends Component {
superBlock, superBlock,
t, t,
title, title,
user: { user: { username },
is2018DataVisCert, currentCerts
isApisMicroservicesCert,
isFrontEndLibsCert,
isQaCertV7,
isInfosecCertV7,
isJsAlgoDataStructCert,
isRespWebDesignCert,
isSciCompPyCertV7,
isDataAnalysisPyCertV7,
isMachineLearningPyCertV7,
username
}
} = this.props; } = this.props;
const userCertificates = {
'responsive-web-design': isRespWebDesignCert,
'javascript-algorithms-and-data-structures': isJsAlgoDataStructCert,
'front-end-libraries': isFrontEndLibsCert,
'data-visualization': is2018DataVisCert,
'apis-and-microservices': isApisMicroservicesCert,
'quality-assurance': isQaCertV7,
'information-security': isInfosecCertV7,
'scientific-computing-with-python': isSciCompPyCertV7,
'data-analysis-with-python': isDataAnalysisPyCertV7,
'machine-learning-with-python': isMachineLearningPyCertV7
};
const cert = certMap.find(x => x.title === title); const cert = certMap.find(x => x.title === title);
const isCertified = userCertificates[superBlock]; const isCertified = currentCerts.find(
const certLocation = `/certification/${username}/${cert.slug}`; cert =>
certSlugTypeMap[cert.certSlug] === superBlockCertTypeMap[superBlock]
).show;
const certLocation = `/certification/${username}/${cert.certSlug}`;
const certCheckmarkStyle = { height: '40px', width: '40px' }; const certCheckmarkStyle = { height: '40px', width: '40px' };
const i18nSuperBlock = t(`intro:${superBlock}.title`); const i18nSuperBlock = t(`intro:${superBlock}.title`);
const i18nCertText = t(`intro:misc-text.certification`, { const i18nCertText = t(`intro:misc-text.certification`, {

View File

@ -47,8 +47,8 @@ export function getUserProfile(username) {
return get(`/api/users/get-public-profile?username=${username}`); return get(`/api/users/get-public-profile?username=${username}`);
} }
export function getShowCert(username, cert) { export function getShowCert(username, certSlug) {
return get(`/certificate/showCert/${username}/${cert}`); return get(`/certificate/showCert/${username}/${certSlug}`);
} }
export function getUsernameExists(username) { export function getUsernameExists(username) {
@ -114,8 +114,8 @@ export function putUserUpdateEmail(email) {
return put('/update-my-email', { email }); return put('/update-my-email', { email });
} }
export function putVerifyCert(superBlock) { export function putVerifyCert(certSlug) {
return put('/certificate/verify', { superBlock }); return put('/certificate/verify', { certSlug });
} }
/** DELETE **/ /** DELETE **/

View File

@ -52,7 +52,7 @@ const completionHours = {
[certTypes.machineLearningPyV7]: 300 [certTypes.machineLearningPyV7]: 300
}; };
const superBlockCertTypeMap = { const certSlugTypeMap = {
// legacy // legacy
'legacy-front-end': certTypes.frontEnd, 'legacy-front-end': certTypes.frontEnd,
'legacy-back-end': certTypes.backEnd, 'legacy-back-end': certTypes.backEnd,
@ -75,6 +75,27 @@ const superBlockCertTypeMap = {
'machine-learning-with-python-v7': certTypes.machineLearningPyV7 'machine-learning-with-python-v7': certTypes.machineLearningPyV7
}; };
const superBlockCertTypeMap = {
// legacy
'legacy-front-end': certTypes.frontEnd,
'legacy-back-end': certTypes.backEnd,
'legacy-data-visualization': certTypes.dataVis,
'information-security-and-quality-assurance': certTypes.infosecQa,
'full-stack': certTypes.fullStack,
// modern
'responsive-web-design': certTypes.respWebDesign,
'javascript-algorithms-and-data-structures': certTypes.jsAlgoDataStruct,
'front-end-libraries': certTypes.frontEndLibs,
'data-visualization': certTypes.dataVis2018,
'apis-and-microservices': certTypes.apisMicroservices,
'quality-assurance': certTypes.qaV7,
'information-security': certTypes.infosecV7,
'scientific-computing-with-python': certTypes.sciCompPyV7,
'data-analysis-with-python': certTypes.dataAnalysisPyV7,
'machine-learning-with-python': certTypes.machineLearningPyV7
};
const certTypeIdMap = { const certTypeIdMap = {
[certTypes.frontEnd]: certIds.legacyFrontEndChallengeId, [certTypes.frontEnd]: certIds.legacyFrontEndChallengeId,
[certTypes.backEnd]: certIds.legacyBackEndChallengeId, [certTypes.backEnd]: certIds.legacyBackEndChallengeId,
@ -115,6 +136,7 @@ exports.oldDataVizId = '561add10cb82ac38a17513b3';
exports.completionHours = completionHours; exports.completionHours = completionHours;
exports.certTypes = certTypes; exports.certTypes = certTypes;
exports.superBlockCertTypeMap = superBlockCertTypeMap; exports.superBlockCertTypeMap = superBlockCertTypeMap;
exports.certSlugTypeMap = certSlugTypeMap;
exports.certIds = certIds; exports.certIds = certIds;
exports.certTypeIdMap = certTypeIdMap; exports.certTypeIdMap = certTypeIdMap;
exports.certTypeTitleMap = certTypeTitleMap; exports.certTypeTitleMap = certTypeTitleMap;