diff --git a/api-server/common/utils/legacyProjectData.js b/api-server/common/utils/legacyProjectData.js index 17c84c58bc..302d0c222f 100644 --- a/api-server/common/utils/legacyProjectData.js +++ b/api-server/common/utils/legacyProjectData.js @@ -93,7 +93,9 @@ const legacyInfosecQaProjects = { '587d824a367417b2b2512c45' ], title: 'Legacy Information Security and Quality Assurance Projects', - superBlock: 'legacy-information-security-and-quality-assurance' + // Keep the settings page "Show Certification" button + // pointing to information-security-and-quality-assurance + superBlock: 'information-security-and-quality-assurance' }; const legacyProjects = [ diff --git a/api-server/server/boot/certificate.js b/api-server/server/boot/certificate.js index a91ee1f488..3da834af89 100644 --- a/api-server/server/boot/certificate.js +++ b/api-server/server/boot/certificate.js @@ -15,17 +15,17 @@ import { legacyBackEndChallengeId, legacyDataVisId, legacyInfosecQaId, + legacyFullStackId, respWebDesignId, frontEndLibsId, jsAlgoDataStructId, dataVis2018Id, apisMicroservicesId, - infosecId, - qaId, - fullStackId, - sciCompPyId, - dataAnalysisPyId, - machineLearningPyId + qa2020Id, + infosec2020Id, + sciCompPy2020Id, + dataAnalysisPy2020Id, + machineLearningPy2020Id } from '../utils/constantStrings.json'; import { oldDataVizId } from '../../../config/misc'; import certTypes from '../utils/certTypes.json'; @@ -106,6 +106,7 @@ function createCertTypeIds(app) { [certTypes.backEnd]: getIdsForCert$(legacyBackEndChallengeId, Challenge), [certTypes.dataVis]: getIdsForCert$(legacyDataVisId, Challenge), [certTypes.infosecQa]: getIdsForCert$(legacyInfosecQaId, Challenge), + [certTypes.fullStack]: getIdsForCert$(legacyFullStackId, Challenge), // modern [certTypes.respWebDesign]: getIdsForCert$(respWebDesignId, Challenge), @@ -116,13 +117,15 @@ function createCertTypeIds(app) { apisMicroservicesId, Challenge ), - [certTypes.qa]: getIdsForCert$(qaId, Challenge), - [certTypes.infosec]: getIdsForCert$(infosecId, Challenge), - [certTypes.fullStack]: getIdsForCert$(fullStackId, Challenge), - [certTypes.sciCompPy]: getIdsForCert$(sciCompPyId, Challenge), - [certTypes.dataAnalysisPy]: getIdsForCert$(dataAnalysisPyId, Challenge), - [certTypes.machineLearningPy]: getIdsForCert$( - machineLearningPyId, + [certTypes.qa2020]: getIdsForCert$(qa2020Id, Challenge), + [certTypes.infosec2020]: getIdsForCert$(infosec2020Id, Challenge), + [certTypes.sciCompPy2020]: getIdsForCert$(sciCompPy2020Id, Challenge), + [certTypes.dataAnalysisPy2020]: getIdsForCert$( + dataAnalysisPy2020Id, + Challenge + ), + [certTypes.machineLearningPy2020]: getIdsForCert$( + machineLearningPy2020Id, Challenge ) }; @@ -139,17 +142,17 @@ const certIds = { [certTypes.backEnd]: legacyBackEndChallengeId, [certTypes.dataVis]: legacyDataVisId, [certTypes.infosecQa]: legacyInfosecQaId, + [certTypes.fullStack]: legacyFullStackId, [certTypes.respWebDesign]: respWebDesignId, [certTypes.frontEndLibs]: frontEndLibsId, [certTypes.jsAlgoDataStruct]: jsAlgoDataStructId, [certTypes.dataVis2018]: dataVis2018Id, [certTypes.apisMicroservices]: apisMicroservicesId, - [certTypes.qa]: qaId, - [certTypes.infosec]: infosecId, - [certTypes.fullStack]: fullStackId, - [certTypes.sciCompPy]: sciCompPyId, - [certTypes.dataAnalysisPy]: dataAnalysisPyId, - [certTypes.machineLearningPy]: machineLearningPyId + [certTypes.qa2020]: qa2020Id, + [certTypes.infosec2020]: infosec2020Id, + [certTypes.sciCompPy2020]: sciCompPy2020Id, + [certTypes.dataAnalysisPy2020]: dataAnalysisPy2020Id, + [certTypes.machineLearningPy2020]: machineLearningPy2020Id }; const certText = { @@ -157,17 +160,17 @@ const certText = { [certTypes.backEnd]: 'Legacy Back End', [certTypes.dataVis]: 'Legacy Data Visualization', [certTypes.infosecQa]: 'Legacy Information Security and Quality Assurance', - [certTypes.fullStack]: 'Full Stack', + [certTypes.fullStack]: 'Legacy Full Stack', [certTypes.respWebDesign]: 'Responsive Web Design', [certTypes.frontEndLibs]: 'Front End Libraries', [certTypes.jsAlgoDataStruct]: 'JavaScript Algorithms and Data Structures', [certTypes.dataVis2018]: 'Data Visualization', [certTypes.apisMicroservices]: 'APIs and Microservices', - [certTypes.qa]: 'Quality Assurance', - [certTypes.infosec]: 'Information Security', - [certTypes.sciCompPy]: 'Scientific Computing with Python', - [certTypes.dataAnalysisPy]: 'Data Analysis with Python', - [certTypes.machineLearningPy]: 'Machine Learning with Python' + [certTypes.qa2020]: 'Quality Assurance', + [certTypes.infosec2020]: 'Information Security', + [certTypes.sciCompPy2020]: 'Scientific Computing with Python', + [certTypes.dataAnalysisPy2020]: 'Data Analysis with Python', + [certTypes.machineLearningPy2020]: 'Machine Learning with Python' }; const completionHours = { @@ -181,11 +184,11 @@ const completionHours = { [certTypes.jsAlgoDataStruct]: 300, [certTypes.dataVis2018]: 300, [certTypes.apisMicroservices]: 300, - [certTypes.qa]: 300, - [certTypes.infosec]: 300, - [certTypes.sciCompPy]: 400, - [certTypes.dataAnalysisPy]: 400, - [certTypes.machineLearningPy]: 400 + [certTypes.qa2020]: 300, + [certTypes.infosec2020]: 300, + [certTypes.sciCompPy2020]: 400, + [certTypes.dataAnalysisPy2020]: 400, + [certTypes.machineLearningPy2020]: 400 }; function getIdsForCert$(id, Challenge) { diff --git a/api-server/server/utils/certTypes.json b/api-server/server/utils/certTypes.json index 08bcc02366..8da768e284 100644 --- a/api-server/server/utils/certTypes.json +++ b/api-server/server/utils/certTypes.json @@ -8,10 +8,10 @@ "jsAlgoDataStruct": "isJsAlgoDataStructCert", "apisMicroservices": "isApisMicroservicesCert", "infosecQa": "isInfosecQaCert", - "qa": "is2020QaCert", - "infosec": "is2020InfosecCert", - "fullStack": "isFullStackCert", - "sciCompPy": "is2020SciCompPyCert", - "dataAnalysisPy": "is2020DataAnalysisPyCert", - "machineLearningPy": "is2020MachineLearningPyCert" + "qa2020": "is2020QaCert", + "infosec2020": "is2020InfosecCert", + "sciCompPy2020": "is2020SciCompPyCert", + "dataAnalysisPy2020": "is2020DataAnalysisPyCert", + "machineLearningPy2020": "is2020MachineLearningPyCert", + "fullStack": "isFullStackCert" } diff --git a/api-server/server/utils/constantStrings.json b/api-server/server/utils/constantStrings.json index 841ec89951..b29380e23c 100644 --- a/api-server/server/utils/constantStrings.json +++ b/api-server/server/utils/constantStrings.json @@ -5,16 +5,16 @@ "legacyBackEndChallengeId": "660add10cb82ac38a17513be", "legacyDataVisId": "561add10cb82ac39a17513bc", "legacyInfosecQaId": "561add10cb82ac38a17213bc", + "legacyFullStackId": "561add10cb82ac38a17213bd", "respWebDesignId": "561add10cb82ac38a17513bc", "frontEndLibsId": "561acd10cb82ac38a17513bc", "dataVis2018Id": "5a553ca864b52e1d8bceea14", "jsAlgoDataStructId": "561abd10cb81ac38a17513bc", "apisMicroservicesId": "561add10cb82ac38a17523bc", - "qaId": "5e611829481575a52dc59c0e", - "infosecId": "5e6021435ac9d0ecd8b94b00", - "fullStackId": "561add10cb82ac38a17213bd", - "sciCompPyId": "5e44431b903586ffb414c951", - "dataAnalysisPyId": "5e46fc95ac417301a38fb934", - "machineLearningPyId": "5e46fc95ac417301a38fb935" + "qa2020Id": "5e611829481575a52dc59c0e", + "infosec2020Id": "5e6021435ac9d0ecd8b94b00", + "sciCompPy2020Id": "5e44431b903586ffb414c951", + "dataAnalysisPy2020Id": "5e46fc95ac417301a38fb934", + "machineLearningPy2020Id": "5e46fc95ac417301a38fb935" } diff --git a/api-server/server/utils/superBlockCertTypeMap.js b/api-server/server/utils/superBlockCertTypeMap.js index 6180755686..dcaa626b42 100644 --- a/api-server/server/utils/superBlockCertTypeMap.js +++ b/api-server/server/utils/superBlockCertTypeMap.js @@ -5,7 +5,10 @@ const superBlockCertTypeMap = { 'legacy-front-end': certTypes.frontEnd, 'legacy-back-end': certTypes.backEnd, 'legacy-data-visualization': certTypes.dataVis, - 'legacy-information-security-and-quality-assurance': certTypes.infosecQa, + // Keep these slugs the same so we don't + // break existing links + 'information-security-and-quality-assurance': certTypes.infosecQa, + 'full-stack': certTypes.fullStack, // modern 'responsive-web-design': certTypes.respWebDesign, @@ -13,12 +16,11 @@ const superBlockCertTypeMap = { 'front-end-libraries': certTypes.frontEndLibs, 'data-visualization': certTypes.dataVis2018, 'apis-and-microservices': certTypes.apisMicroservices, - 'quality-assurance': certTypes.qa, - 'information-security': certTypes.infosec, - 'full-stack': certTypes.fullStack, - 'scientific-computing-with-python': certTypes.sciCompPy, - 'data-analysis-with-python': certTypes.dataAnalysisPy, - 'machine-learning-with-python': certTypes.machineLearningPy + '2020-quality-assurance': certTypes.qa2020, + '2020-information-security': certTypes.infosec2020, + '2020-scientific-computing-with-python': certTypes.sciCompPy2020, + '2020-data-analysis-with-python': certTypes.dataAnalysisPy2020, + '2020-machine-learning-with-python': certTypes.machineLearningPy2020 }; export default superBlockCertTypeMap; diff --git a/client/src/client-only-routes/ShowCertification.js b/client/src/client-only-routes/ShowCertification.js index 5e9a939982..23c28fa87b 100644 --- a/client/src/client-only-routes/ShowCertification.js +++ b/client/src/client-only-routes/ShowCertification.js @@ -18,7 +18,7 @@ import { isDonatingSelector, executeGA } from '../redux'; -import validCertNames from '../../utils/validCertNames'; +import { certMap } from '../../src/resources/certAndProjectMap'; import { createFlashMessage } from '../components/Flash/redux'; import standardErrorMessage from '../utils/standardErrorMessage'; import reallyWeirdErrorMessage from '../utils/reallyWeirdErrorMessage'; @@ -56,6 +56,8 @@ const propTypes = { validCertName: PropTypes.bool }; +const validCertNames = certMap.map(cert => cert.slug); + const mapStateToProps = (state, { certName }) => { const validCertName = validCertNames.some(name => name === certName); return createSelector( diff --git a/client/src/components/settings/Certification.js b/client/src/components/settings/Certification.js index c99ea8fc7e..826720192b 100644 --- a/client/src/components/settings/Certification.js +++ b/client/src/components/settings/Certification.js @@ -13,7 +13,10 @@ import { import { Link, navigate } from 'gatsby'; import { createSelector } from 'reselect'; -import { projectMap, legacyProjectMap } from '../../resources/certProjectMap'; +import { + projectMap, + legacyProjectMap +} from '../../resources/certAndProjectMap'; import SectionHeader from './SectionHeader'; import SolutionViewer from './SolutionViewer'; @@ -120,7 +123,7 @@ const isCertMapSelector = createSelector( 'JavaScript Algorithms and Data Structures': isJsAlgoDataStructCert, 'Front End Libraries': isFrontEndLibsCert, 'Data Visualization': is2018DataVisCert, - "API's and Microservices": isApisMicroservicesCert, + 'APIs and Microservices': isApisMicroservicesCert, 'Quality Assurance': is2020QaCert, 'Information Security': is2020InfosecCert, 'Scientific Computing with Python': is2020SciCompPyCert, @@ -462,7 +465,7 @@ export class CertificationSettings extends Component { ); }; - renderFullStack = () => { + renderLegacyFullStack = () => { const { isFullStackCert, username, @@ -485,6 +488,8 @@ export class CertificationSettings extends Component { isJsAlgoDataStructCert && isRespWebDesignCert; + // Keep the settings page slug as full-stack rather than + // legacy-full-stack so we don't break existing links const superBlock = 'full-stack'; const certLocation = `/certification/${username}/${superBlock}`; @@ -507,7 +512,7 @@ export class CertificationSettings extends Component { return ( -

Legacy Full Stack Certification

+

Legacy Full Stack Certification

Once you've earned the following freeCodeCamp certifications, you'll @@ -564,8 +569,8 @@ export class CertificationSettings extends Component {

Certifications {certifications.map(this.renderCertifications)} - {this.renderFullStack()} Legacy Certifications + {this.renderLegacyFullStack()} {legacyCertifications.map(this.renderLegacyCertifications)} {isOpen ? ( state => { is2020MachineLearningPyCert, hasLegacyCert: isFrontEndCert || isBackEndCert || isDataVisCert || isInfosecQaCert, + isFullStackCert, currentCerts: [ - { - show: isFullStackCert, - title: 'Full Stack Certification', - showURL: 'full-stack' - }, { show: isRespWebDesignCert, title: 'Responsive Web Design Certification', @@ -272,27 +268,27 @@ export const certificatesByNameSelector = username => state => { { show: is2020QaCert, title: ' Quality Assurance Certification', - showURL: 'quality-assurance' + showURL: '2020-quality-assurance' }, { show: is2020InfosecCert, title: 'Information Security Certification', - showURL: 'information-security' + showURL: '2020-information-security' }, { show: is2020SciCompPyCert, title: 'Scientific Computing with Python Certification', - showURL: 'scientific-computing-with-python' + showURL: '2020-scientific-computing-with-python' }, { show: is2020DataAnalysisPyCert, title: 'Data Analysis with Python Certification', - showURL: 'data-analysis-with-python' + showURL: '2020-data-analysis-with-python' }, { show: is2020MachineLearningPyCert, title: 'Machine Learning with Python Certification', - showURL: 'machine-learning-with-python' + showURL: '2020-machine-learning-with-python' } ], legacyCerts: [ @@ -314,7 +310,14 @@ export const certificatesByNameSelector = username => state => { { show: isInfosecQaCert, title: 'Information Security and Quality Assurance Certification', - showURL: 'legacy-information-security-and-quality-assurance' + // Keep the current public profile cert slug + showURL: 'information-security-and-quality-assurance' + }, + { + show: isFullStackCert, + title: 'Full Stack Certification', + // Keep the current public profile cert slug + showURL: 'full-stack' } ] }; diff --git a/client/src/resources/certAndProjectMap.js b/client/src/resources/certAndProjectMap.js new file mode 100644 index 0000000000..49eda1ebab --- /dev/null +++ b/client/src/resources/certAndProjectMap.js @@ -0,0 +1,676 @@ +const responsiveWebBase = + '/learn/responsive-web-design/responsive-web-design-projects'; +const jsAlgoBase = + '/learn/javascript-algorithms-and-data-structures/' + + 'javascript-algorithms-and-data-structures-projects'; +const feLibsBase = '/learn/front-end-libraries/front-end-libraries-projects'; +const dataVisBase = '/learn/data-visualization/data-visualization-projects'; +const apiMicroBase = + '/learn/apis-and-microservices/apis-and-microservices-projects'; +const qaBase = 'learn/quality-assurance/quality-assurance-projects'; +const infoSecBase = '/learn/information-security/information-security-projects'; +const sciCompPyBase = + '/learn/scientific-computing-with-python/' + + 'scientific-computing-with-python-projects'; +const dataAnalysisPyBase = + '/learn/data-analysis-with-python/data-analysis-with-python-projects'; +const machineLearningPyBase = + '/learn/machine-learning-with-python/machine-learning-with-python-projects'; +const legacyFrontEndBase = ''; +const legacyBackEndBase = ''; +const legacyDataVisBase = ''; +const legacyInfosecQaBase = ''; + +// TODO: generate this automatically in a separate file +// from the md/meta.json files for each cert and projects +const certMap = [ + { + id: '561add10cb82ac38a17513be', + title: 'Legacy Front End', + slug: 'legacy-front-end', + flag: 'isFrontEndCert', + projects: [ + { + id: 'bd7158d8c242eddfaeb5bd13', + title: 'Build a Personal Portfolio Webpage', + link: `${legacyFrontEndBase}/build-a-personal-portfolio-webpage`, + superBlock: 'legacy-front-end' + }, + { + id: 'bd7158d8c442eddfaeb5bd13', + title: 'Build a Random Quote Machine', + link: `${legacyFrontEndBase}/build-a-random-quote-machine`, + superBlock: 'legacy-front-end' + }, + { + id: 'bd7158d8c442eddfaeb5bd0f', + title: 'Build a Pomodoro Clock', + link: `${legacyFrontEndBase}/build-a-pomodoro-clock`, + superBlock: 'legacy-front-end' + }, + { + id: 'bd7158d8c442eddfaeb5bd17', + title: 'Build a JavaScript Calculator', + link: `${legacyFrontEndBase}/build-a-javascript-calculator`, + superBlock: 'legacy-front-end' + }, + { + id: 'bd7158d8c442eddfaeb5bd10', + title: 'Show the Local Weather', + link: `${legacyFrontEndBase}/show-the-local-weather`, + superBlock: 'legacy-front-end' + }, + { + id: 'bd7158d8c442eddfaeb5bd1f', + title: 'Use the TwitchTV JSON API', + link: `${legacyFrontEndBase}/use-the-twitchtv-json-api`, + superBlock: 'legacy-front-end' + }, + { + id: 'bd7158d8c442eddfaeb5bd18', + title: 'Stylize Stories on Camper News', + link: `${legacyFrontEndBase}/stylize-stories-on-camper-news`, + superBlock: 'legacy-front-end' + }, + { + id: 'bd7158d8c442eddfaeb5bd19', + title: 'Build a Wikipedia Viewer', + link: `${legacyFrontEndBase}/build-a-wikipedia-viewer`, + superBlock: 'legacy-front-end' + }, + { + id: 'bd7158d8c442eedfaeb5bd1c', + title: 'Build a Tic Tac Toe Game', + link: `${legacyFrontEndBase}/build-a-tic-tac-toe-game`, + superBlock: 'legacy-front-end' + }, + { + id: 'bd7158d8c442eddfaeb5bd1c', + title: 'Build a Simon Game', + link: `${legacyFrontEndBase}/build-a-simon-game`, + superBlock: 'legacy-front-end' + } + ] + }, + { + id: '660add10cb82ac38a17513be', + title: 'Legacy Back End', + slug: 'legacy-back-end', + flag: 'isBackEndCert', + projects: [ + { + id: 'bd7158d8c443edefaeb5bdef', + title: 'Timestamp Microservice', + link: `${legacyBackEndBase}/timestamp-microservice`, + superBlock: 'legacy-back-end' + }, + { + id: 'bd7158d8c443edefaeb5bdff', + title: 'Request Header Parser Microservice', + link: `${legacyBackEndBase}/request-header-parser-microservice`, + superBlock: 'legacy-back-end' + }, + { + id: 'bd7158d8c443edefaeb5bd0e', + title: 'URL Shortener Microservice', + link: `${legacyBackEndBase}/url-shortener-microservice`, + superBlock: 'legacy-back-end' + }, + { + id: 'bd7158d8c443edefaeb5bdee', + title: 'Image Search Abstraction Layer', + link: `${legacyBackEndBase}/image-search-abstraction-layer`, + superBlock: 'legacy-back-end' + }, + { + id: 'bd7158d8c443edefaeb5bd0f', + title: 'File Metadata Microservice', + link: `${legacyBackEndBase}/file-metadata-microservice`, + superBlock: 'legacy-back-end' + }, + { + id: 'bd7158d8c443eddfaeb5bdef', + title: 'Build a Voting App', + link: `${legacyBackEndBase}/build-a-voting-app`, + superBlock: 'legacy-back-end' + }, + { + id: 'bd7158d8c443eddfaeb5bdff', + title: 'Build a Nightlife Coordination App', + link: `${legacyBackEndBase}/build-a-nightlife-coordination-app`, + superBlock: 'legacy-back-end' + }, + { + id: 'bd7158d8c443eddfaeb5bd0e', + title: 'Chart the Stock Market', + link: `${legacyBackEndBase}/chart-the-stock-market`, + superBlock: 'legacy-back-end' + }, + { + id: 'bd7158d8c443eddfaeb5bd0f', + title: 'Manage a Book Trading Club', + link: `${legacyBackEndBase}/manage-a-book-trading-club`, + superBlock: 'legacy-back-end' + }, + { + id: 'bd7158d8c443eddfaeb5bdee', + title: 'Build a Pinterest Clone', + link: `${legacyBackEndBase}/build-a-pinterest-clone`, + superBlock: 'legacy-back-end' + } + ] + }, + { + id: '561add10cb82ac38a17213bd', + title: 'Legacy Full Stack', + slug: 'full-stack', + flag: 'isFullStackCert' + // Requirements are other certs and is + // handled elsewhere + }, + { + id: '561add10cb82ac39a17513bc', + title: 'Legacy Data Visualization', + slug: 'legacy-data-visualization', + flag: 'isDataVisCert', + projects: [ + { + id: 'bd7157d8c242eddfaeb5bd13', + title: 'Build a Markdown Previewer', + link: `${legacyDataVisBase}/build-a-markdown-previewer`, + superBlock: 'legacy-data-visualization' + }, + { + id: 'bd7156d8c242eddfaeb5bd13', + title: 'Build a Camper Leaderboard', + link: `${legacyDataVisBase}/build-a-camper-leaderboard`, + superBlock: 'legacy-data-visualization' + }, + { + id: 'bd7155d8c242eddfaeb5bd13', + title: 'Build a Recipe Box', + link: `${legacyDataVisBase}/build-a-recipe-box`, + superBlock: 'legacy-data-visualization' + }, + { + id: 'bd7154d8c242eddfaeb5bd13', + title: 'Build the Game of Life', + link: `${legacyDataVisBase}/build-the-game-of-life`, + superBlock: 'legacy-data-visualization' + }, + { + id: 'bd7153d8c242eddfaeb5bd13', + title: 'Build a Roguelike Dungeon Crawler Game', + link: `${legacyDataVisBase}/build-a-roguelike-dungeon-crawler-game`, + superBlock: 'legacy-data-visualization' + }, + { + id: 'bd7168d8c242eddfaeb5bd13', + title: 'Visualize Data with a Bar Chart', + link: `${legacyDataVisBase}/visualize-data-with-a-bar-chart`, + superBlock: 'legacy-data-visualization' + }, + { + id: 'bd7178d8c242eddfaeb5bd13', + title: 'Visualize Data with a Scatterplot Graph', + link: `${legacyDataVisBase}/visualize-data-with-a-scatterplot-graph`, + superBlock: 'legacy-data-visualization' + }, + { + id: 'bd7188d8c242eddfaeb5bd13', + title: 'Visualize Data with a Heat Map', + link: `${legacyDataVisBase}/visualize-data-with-a-heat-map`, + superBlock: 'legacy-data-visualization' + }, + { + id: 'bd7198d8c242eddfaeb5bd13', + title: 'Show National Contiguity with a Force Directed Graph', + link: `${legacyDataVisBase}/show-national-contiguity-with-a-force-directed-graph`, + superBlock: 'legacy-data-visualization' + }, + { + id: 'bd7108d8c242eddfaeb5bd13', + title: 'Map Data Across the Globe', + link: `${legacyDataVisBase}/map-data-across-the-globe`, + superBlock: 'legacy-data-visualization' + } + ] + }, + { + id: '561add10cb82ac38a17213bc', + title: 'Legacy Information Security and Quality Assurance', + // Keep this as information-security-and-quality-assurance + slug: 'information-security-and-quality-assurance', + flag: 'isInfosecQaCert', + projects: [ + // Keep this as information-security-and-quality-assurance + { + id: '587d8249367417b2b2512c41', + title: 'Metric-Imperial Converter', + link: `${legacyInfosecQaBase}/metric-imperial-converter`, + superBlock: 'information-security-and-quality-assurance' + }, + { + id: '587d8249367417b2b2512c42', + title: 'Issue Tracker', + link: `${legacyInfosecQaBase}/issue-tracker`, + superBlock: 'information-security-and-quality-assurance' + }, + { + id: '587d824a367417b2b2512c43', + title: 'Personal Library', + link: `${legacyInfosecQaBase}/personal-library`, + superBlock: 'information-security-and-quality-assurance' + }, + { + id: '587d824a367417b2b2512c44', + title: 'Stock Price Checker', + link: `${legacyInfosecQaBase}/stock-price-checker`, + superBlock: 'information-security-and-quality-assurance' + }, + { + id: '587d824a367417b2b2512c45', + title: 'Anonymous Message Board', + link: `${legacyInfosecQaBase}/anonymous-message-board`, + superBlock: 'information-security-and-quality-assurance' + } + ] + }, + { + id: '561add10cb82ac38a17513bc', + title: 'Responsive Web Design', + slug: 'responsive-web-design', + flag: 'isRespWebDesignCert', + projects: [ + { + id: 'bd7158d8c442eddfaeb5bd18', + title: 'Build a Tribute Page', + link: `${responsiveWebBase}/build-a-tribute-page`, + superBlock: 'responsive-web-design' + }, + { + id: '587d78af367417b2b2512b03', + title: 'Build a Survey Form', + link: `${responsiveWebBase}/build-a-survey-form`, + superBlock: 'responsive-web-design' + }, + { + id: '587d78af367417b2b2512b04', + title: 'Build a Product Landing Page', + link: `${responsiveWebBase}/build-a-product-landing-page`, + superBlock: 'responsive-web-design' + }, + { + id: '587d78b0367417b2b2512b05', + title: 'Build a Technical Documentation Page', + link: `${responsiveWebBase}/build-a-technical-documentation-page`, + superBlock: 'responsive-web-design' + }, + { + id: 'bd7158d8c242eddfaeb5bd13', + title: 'Build a Personal Portfolio Webpage', + link: `${responsiveWebBase}/build-a-personal-portfolio-webpage`, + superBlock: 'responsive-web-design' + } + ] + }, + { + id: '561abd10cb81ac38a17513bc', + title: 'JavaScript Algorithms and Data Structures', + slug: 'javascript-algorithms-and-data-structures', + flag: 'isJsAlgoDataStructCert', + projects: [ + { + id: 'aaa48de84e1ecc7c742e1124', + title: 'Palindrome Checker', + link: `${jsAlgoBase}/palindrome-checker`, + superBlock: 'javascript-algorithms-and-data-structures' + }, + { + id: 'a7f4d8f2483413a6ce226cac', + title: 'Roman Numeral Converter', + link: `${jsAlgoBase}/roman-numeral-converter`, + superBlock: 'javascript-algorithms-and-data-structures' + }, + { + id: '56533eb9ac21ba0edf2244e2', + title: 'Caesars Cipher', + link: `${jsAlgoBase}/caesars-cipher`, + superBlock: 'javascript-algorithms-and-data-structures' + }, + { + id: 'aff0395860f5d3034dc0bfc9', + title: 'Telephone Number Validator', + link: `${jsAlgoBase}/telephone-number-validator`, + superBlock: 'javascript-algorithms-and-data-structures' + }, + { + id: 'aa2e6f85cab2ab736c9a9b24', + title: 'Cash Register', + link: `${jsAlgoBase}/cash-register`, + superBlock: 'javascript-algorithms-and-data-structures' + } + ] + }, + { + id: '561acd10cb82ac38a17513bc', + title: 'Front End Libraries', + slug: 'front-end-libraries', + flag: 'isFrontEndLibsCert', + projects: [ + { + id: 'bd7158d8c442eddfaeb5bd13', + title: 'Build a Random Quote Machine', + link: `${feLibsBase}/build-a-random-quote-machine`, + superBlock: 'front-end-libraries' + }, + { + id: 'bd7157d8c242eddfaeb5bd13', + title: 'Build a Markdown Previewer', + link: `${feLibsBase}/build-a-markdown-previewer`, + superBlock: 'front-end-libraries' + }, + { + id: '587d7dbc367417b2b2512bae', + title: 'Build a Drum Machine', + link: `${feLibsBase}/build-a-drum-machine`, + superBlock: 'front-end-libraries' + }, + { + id: 'bd7158d8c442eddfaeb5bd17', + title: 'Build a JavaScript Calculator', + link: `${feLibsBase}/build-a-javascript-calculator`, + superBlock: 'front-end-libraries' + }, + { + id: 'bd7158d8c442eddfaeb5bd0f', + title: 'Build a Pomodoro Clock', + link: `${feLibsBase}/build-a-pomodoro-clock`, + superBlock: 'front-end-libraries' + } + ] + }, + { + id: '5a553ca864b52e1d8bceea14', + title: 'Data Visualization', + slug: 'data-visualization', + flag: 'is2018DataVisCert', + projects: [ + { + id: 'bd7168d8c242eddfaeb5bd13', + title: 'Visualize Data with a Bar Chart', + link: `${dataVisBase}/visualize-data-with-a-bar-chart`, + superBlock: 'data-visualization' + }, + { + id: 'bd7178d8c242eddfaeb5bd13', + title: 'Visualize Data with a Scatterplot Graph', + link: `${dataVisBase}/visualize-data-with-a-scatterplot-graph`, + superBlock: 'data-visualization' + }, + { + id: 'bd7188d8c242eddfaeb5bd13', + title: 'Visualize Data with a Heat Map', + link: `${dataVisBase}/visualize-data-with-a-heat-map`, + superBlock: 'data-visualization' + }, + { + id: '587d7fa6367417b2b2512bbf', + title: 'Visualize Data with a Choropleth Map', + link: `${dataVisBase}/visualize-data-with-a-choropleth-map`, + superBlock: 'data-visualization' + }, + { + id: '587d7fa6367417b2b2512bc0', + title: 'Visualize Data with a Treemap Diagram', + link: `${dataVisBase}/visualize-data-with-a-treemap-diagram`, + superBlock: 'data-visualization' + } + ] + }, + { + id: '561add10cb82ac38a17523bc', + title: 'APIs and Microservices', + slug: 'apis-and-microservices', + flag: 'isApisMicroservicesCert', + projects: [ + { + id: 'bd7158d8c443edefaeb5bdef', + title: 'Timestamp Microservice', + link: `${apiMicroBase}/timestamp-microservice`, + superBlock: 'apis-and-microservices' + }, + { + id: 'bd7158d8c443edefaeb5bdff', + title: 'Request Header Parser Microservice', + link: `${apiMicroBase}/request-header-parser-microservice`, + superBlock: 'apis-and-microservices' + }, + { + id: 'bd7158d8c443edefaeb5bd0e', + title: 'URL Shortener Microservice', + link: `${apiMicroBase}/url-shortener-microservice`, + superBlock: 'apis-and-microservices' + }, + { + id: '5a8b073d06fa14fcfde687aa', + title: 'Exercise Tracker', + link: `${apiMicroBase}/exercise-tracker`, + superBlock: 'apis-and-microservices' + }, + { + id: 'bd7158d8c443edefaeb5bd0f', + title: 'File Metadata Microservice', + link: `${apiMicroBase}/file-metadata-microservice`, + superBlock: 'apis-and-microservices' + } + ] + }, + { + id: '5e611829481575a52dc59c0e', + title: 'Quality Assurance', + slug: '2020-quality-assurance', + flag: 'is2020QaCert', + projects: [ + { + id: '587d8249367417b2b2512c41', + title: 'Metric-Imperial Converter', + link: `${qaBase}/metric-imperial-converter`, + superBlock: '2020-quality-assurance' + }, + { + id: '587d8249367417b2b2512c42', + title: 'Issue Tracker', + link: `${qaBase}/issue-tracker`, + superBlock: '2020-quality-assurance' + }, + { + id: '587d824a367417b2b2512c43', + title: 'Personal Library', + link: `${qaBase}/personal-library`, + superBlock: '2020-quality-assurance' + }, + { + id: '5e601bf95ac9d0ecd8b94afd', + title: 'Sudoku Solver', + link: `${qaBase}/sudoku-solver`, + superBlock: '2020-quality-assurance' + }, + { + id: '5e601c0d5ac9d0ecd8b94afe', + title: 'American British Translator', + link: `${qaBase}/american-british-translator`, + superBlock: '2020-quality-assurance' + } + ] + }, + { + id: '5e6021435ac9d0ecd8b94b00', + title: 'Information Security', + slug: '2020-information-security', + flag: 'is2020InfosecCert', + projects: [ + { + id: '587d824a367417b2b2512c44', + title: 'Stock Price Checker', + link: `${infoSecBase}/stock-price-checker`, + superBlock: '2020-information-security' + }, + { + id: '587d824a367417b2b2512c45', + title: 'Anonymous Message Board', + link: `${infoSecBase}/anonymous-message-board`, + superBlock: '2020-information-security' + }, + { + id: '5e46f979ac417301a38fb932', + title: 'Port Scanner', + link: `${infoSecBase}/port-scanner`, + superBlock: '2020-information-security' + }, + { + id: '5e46f983ac417301a38fb933', + title: 'SHA-1 Password Cracker', + link: `${infoSecBase}/sha-1-password-cracker`, + superBlock: '2020-information-security' + }, + { + id: '5e601c775ac9d0ecd8b94aff', + title: 'Secure Real Time Multiplayer Game', + link: `${infoSecBase}/secure-real-time-multiplayer-game`, + superBlock: '2020-information-security' + } + ] + }, + { + id: '5e44431b903586ffb414c951', + title: 'Scientific Computing with Python', + slug: '2020-scientific-computing-with-python', + flag: 'is2020SciCompPyCert', + projects: [ + { + id: '5e44412c903586ffb414c94c', + title: 'Arithmetic Formatter', + link: `${sciCompPyBase}/arithmetic-formatter`, + superBlock: '2020-scientific-computing-with-python' + }, + { + id: '5e444136903586ffb414c94d', + title: 'Time Calculator', + link: `${sciCompPyBase}/time-calculator`, + superBlock: '2020-scientific-computing-with-python' + }, + { + id: '5e44413e903586ffb414c94e', + title: 'Budget App', + link: `${sciCompPyBase}/budget-app`, + superBlock: '2020-scientific-computing-with-python' + }, + { + id: '5e444147903586ffb414c94f', + title: 'Polygon Area Calculator', + link: `${sciCompPyBase}/polygon-area-calculator`, + superBlock: '2020-scientific-computing-with-python' + }, + { + id: '5e44414f903586ffb414c950', + title: 'Probability Calculator', + link: `${sciCompPyBase}/probability-calculator`, + superBlock: '2020-scientific-computing-with-python' + } + ] + }, + { + id: '5e46fc95ac417301a38fb934', + title: 'Data Analysis with Python', + slug: '2020-data-analysis-with-python', + flag: 'is2020DataAnalysisPyCert', + projects: [ + { + id: '5e46f7e5ac417301a38fb928', + title: 'Mean-Variance-Standard Deviation Calculator', + link: `${dataAnalysisPyBase}/mean-variance-standard-deviation-calculator`, + superBlock: '2020-data-analysis-with-python' + }, + { + id: '5e46f7e5ac417301a38fb929', + title: 'Demographic Data Analyzer', + link: `${dataAnalysisPyBase}/demographic-data-analyzer`, + superBlock: '2020-data-analysis-with-python' + }, + { + id: '5e46f7f8ac417301a38fb92a', + title: 'Medical Data Visualizer', + link: `${dataAnalysisPyBase}/medical-data-visualizer`, + superBlock: '2020-data-analysis-with-python' + }, + { + id: '5e46f802ac417301a38fb92b', + title: 'Page View Time Series Visualizer', + link: `${dataAnalysisPyBase}/page-view-time-series-visualizer`, + superBlock: '2020-data-analysis-with-python' + }, + { + id: '5e4f5c4b570f7e3a4949899f', + title: 'Sea Level Predictor', + link: `${dataAnalysisPyBase}/sea-level-predictor`, + superBlock: '2020-scientific-computing-with-python' + } + ] + }, + { + id: '5e46fc95ac417301a38fb935', + title: 'Machine Learning with Python', + slug: '2020-machine-learning-with-python', + flag: 'is2020MachineLearningPyCert', + projects: [ + { + id: '5e46f8d6ac417301a38fb92d', + title: 'Rock Paper Scissors', + link: `${machineLearningPyBase}/rock-paper-scissors`, + superBlock: '2020-machine-learning-with-python' + }, + { + id: '5e46f8dcac417301a38fb92e', + title: 'Cat and Dog Image Classifier', + link: `${machineLearningPyBase}/cat-and-dog-image-classifier`, + superBlock: '2020-machine-learning-with-python' + }, + { + id: '5e46f8e3ac417301a38fb92f', + title: 'Book Recommendation Engine using KNN', + link: `${machineLearningPyBase}/book-recommendation-engine-using-knn`, + superBlock: '2020-machine-learning-with-python' + }, + { + id: '5e46f8edac417301a38fb930', + title: 'Linear Regression Health Costs Calculator', + link: `${machineLearningPyBase}/linear-regression-health-costs-calculator`, + superBlock: '2020-machine-learning-with-python' + }, + { + id: '5e46f8edac417301a38fb931', + title: 'Neural Network SMS Text Classifier', + link: `${machineLearningPyBase}/neural-network-sms-text-classifier`, + superBlock: '2020-machine-learning-with-python' + } + ] + } +]; + +const legacyProjectMap = {}; +const projectMap = {}; + +certMap.forEach(cert => { + // Filter out Legacy Full Stack so inputs for project + // URLs aren't rendered on the settings page + if (cert.title !== 'Legacy Full Stack') { + if (cert.title.startsWith('Legacy')) { + legacyProjectMap[cert.title] = cert.projects; + } else { + projectMap[cert.title] = cert.projects; + } + } +}); + +export { certMap, legacyProjectMap, projectMap }; diff --git a/client/src/resources/certProjectMap.js b/client/src/resources/certProjectMap.js deleted file mode 100644 index 21d76e6300..0000000000 --- a/client/src/resources/certProjectMap.js +++ /dev/null @@ -1,566 +0,0 @@ -const responsiveWebBase = - '/learn/responsive-web-design/responsive-web-design-projects'; -const jsAlgoBase = - '/learn/javascript-algorithms-and-data-structures/' + - 'javascript-algorithms-and-data-structures-projects'; -const feLibsBase = '/learn/front-end-libraries/front-end-libraries-projects'; -const dataVisBase = '/learn/data-visualization/data-visualization-projects'; -const apiMicroBase = - '/learn/apis-and-microservices/apis-and-microservices-projects'; -const qaBase = 'learn/quality-assurance/quality-assurance-projects'; -const infoSecBase = '/learn/information-security/information-security-projects'; -const sciCompPyBase = - '/learn/scientific-computing-with-python/' + - 'scientific-computing-with-python-projects'; -const dataAnalysisPyBase = - '/learn/data-analysis-with-python/data-analysis-with-python-projects'; -const machineLearningPyBase = - '/learn/machine-learning-with-python/machine-learning-with-python-projects'; -const legacyFrontEndBase = ''; -const legacyBackEndBase = ''; -const legacyDataVisBase = ''; -const legacyInfosecQaBase = ''; - -export const legacyProjectMap = { - 'Legacy Front End': [ - { - id: 'bd7158d8c242eddfaeb5bd13', - title: 'Build a Personal Portfolio Webpage', - link: `${legacyFrontEndBase}/build-a-personal-portfolio-webpage`, - superBlock: 'legacy-front-end' - }, - { - id: 'bd7158d8c442eddfaeb5bd13', - title: 'Build a Random Quote Machine', - link: `${legacyFrontEndBase}/build-a-random-quote-machine`, - superBlock: 'legacy-front-end' - }, - { - id: 'bd7158d8c442eddfaeb5bd0f', - title: 'Build a Pomodoro Clock', - link: `${legacyFrontEndBase}/build-a-pomodoro-clock`, - superBlock: 'legacy-front-end' - }, - { - id: 'bd7158d8c442eddfaeb5bd17', - title: 'Build a JavaScript Calculator', - link: `${legacyFrontEndBase}/build-a-javascript-calculator`, - superBlock: 'legacy-front-end' - }, - { - id: 'bd7158d8c442eddfaeb5bd10', - title: 'Show the Local Weather', - link: `${legacyFrontEndBase}/show-the-local-weather`, - superBlock: 'legacy-front-end' - }, - { - id: 'bd7158d8c442eddfaeb5bd1f', - title: 'Use the TwitchTV JSON API', - link: `${legacyFrontEndBase}/use-the-twitchtv-json-api`, - superBlock: 'legacy-front-end' - }, - { - id: 'bd7158d8c442eddfaeb5bd18', - title: 'Stylize Stories on Camper News', - link: `${legacyFrontEndBase}/stylize-stories-on-camper-news`, - superBlock: 'legacy-front-end' - }, - { - id: 'bd7158d8c442eddfaeb5bd19', - title: 'Build a Wikipedia Viewer', - link: `${legacyFrontEndBase}/build-a-wikipedia-viewer`, - superBlock: 'legacy-front-end' - }, - { - id: 'bd7158d8c442eedfaeb5bd1c', - title: 'Build a Tic Tac Toe Game', - link: `${legacyFrontEndBase}/build-a-tic-tac-toe-game`, - superBlock: 'legacy-front-end' - }, - { - id: 'bd7158d8c442eddfaeb5bd1c', - title: 'Build a Simon Game', - link: `${legacyFrontEndBase}/build-a-simon-game`, - superBlock: 'legacy-front-end' - } - ], - 'Legacy Back End': [ - { - id: 'bd7158d8c443edefaeb5bdef', - title: 'Timestamp Microservice', - link: `${legacyBackEndBase}/timestamp-microservice`, - superBlock: 'legacy-back-end' - }, - { - id: 'bd7158d8c443edefaeb5bdff', - title: 'Request Header Parser Microservice', - link: `${legacyBackEndBase}/request-header-parser-microservice`, - superBlock: 'legacy-back-end' - }, - { - id: 'bd7158d8c443edefaeb5bd0e', - title: 'URL Shortener Microservice', - link: `${legacyBackEndBase}/url-shortener-microservice`, - superBlock: 'legacy-back-end' - }, - { - id: 'bd7158d8c443edefaeb5bdee', - title: 'Image Search Abstraction Layer', - link: `${legacyBackEndBase}/image-search-abstraction-layer`, - superBlock: 'legacy-back-end' - }, - { - id: 'bd7158d8c443edefaeb5bd0f', - title: 'File Metadata Microservice', - link: `${legacyBackEndBase}/file-metadata-microservice`, - superBlock: 'legacy-back-end' - }, - { - id: 'bd7158d8c443eddfaeb5bdef', - title: 'Build a Voting App', - link: `${legacyBackEndBase}/build-a-voting-app`, - superBlock: 'legacy-back-end' - }, - { - id: 'bd7158d8c443eddfaeb5bdff', - title: 'Build a Nightlife Coordination App', - link: `${legacyBackEndBase}/build-a-nightlife-coordination-app`, - superBlock: 'legacy-back-end' - }, - { - id: 'bd7158d8c443eddfaeb5bd0e', - title: 'Chart the Stock Market', - link: `${legacyBackEndBase}/chart-the-stock-market`, - superBlock: 'legacy-back-end' - }, - { - id: 'bd7158d8c443eddfaeb5bd0f', - title: 'Manage a Book Trading Club', - link: `${legacyBackEndBase}/manage-a-book-trading-club`, - superBlock: 'legacy-back-end' - }, - { - id: 'bd7158d8c443eddfaeb5bdee', - title: 'Build a Pinterest Clone', - link: `${legacyBackEndBase}/build-a-pinterest-clone`, - superBlock: 'legacy-back-end' - } - ], - 'Legacy Data Visualization': [ - { - id: 'bd7157d8c242eddfaeb5bd13', - title: 'Build a Markdown Previewer', - link: `${legacyDataVisBase}/build-a-markdown-previewer`, - superBlock: 'legacy-data-visualization' - }, - { - id: 'bd7156d8c242eddfaeb5bd13', - title: 'Build a Camper Leaderboard', - link: `${legacyDataVisBase}/build-a-camper-leaderboard`, - superBlock: 'legacy-data-visualization' - }, - { - id: 'bd7155d8c242eddfaeb5bd13', - title: 'Build a Recipe Box', - link: `${legacyDataVisBase}/build-a-recipe-box`, - superBlock: 'legacy-data-visualization' - }, - { - id: 'bd7154d8c242eddfaeb5bd13', - title: 'Build the Game of Life', - link: `${legacyDataVisBase}/build-the-game-of-life`, - superBlock: 'legacy-data-visualization' - }, - { - id: 'bd7153d8c242eddfaeb5bd13', - title: 'Build a Roguelike Dungeon Crawler Game', - link: `${legacyDataVisBase}/build-a-roguelike-dungeon-crawler-game`, - superBlock: 'legacy-data-visualization' - }, - { - id: 'bd7168d8c242eddfaeb5bd13', - title: 'Visualize Data with a Bar Chart', - link: `${legacyDataVisBase}/visualize-data-with-a-bar-chart`, - superBlock: 'legacy-data-visualization' - }, - { - id: 'bd7178d8c242eddfaeb5bd13', - title: 'Visualize Data with a Scatterplot Graph', - link: `${legacyDataVisBase}/visualize-data-with-a-scatterplot-graph`, - superBlock: 'legacy-data-visualization' - }, - { - id: 'bd7188d8c242eddfaeb5bd13', - title: 'Visualize Data with a Heat Map', - link: `${legacyDataVisBase}/visualize-data-with-a-heat-map`, - superBlock: 'legacy-data-visualization' - }, - { - id: 'bd7198d8c242eddfaeb5bd13', - title: 'Show National Contiguity with a Force Directed Graph', - link: `${legacyDataVisBase}/show-national-contiguity-with-a-force-directed-graph`, - superBlock: 'legacy-data-visualization' - }, - { - id: 'bd7108d8c242eddfaeb5bd13', - title: 'Map Data Across the Globe', - link: `${legacyDataVisBase}/map-data-across-the-globe`, - superBlock: 'legacy-data-visualization' - } - ], - 'Legacy Information Security and Quality Assurance': [ - { - id: '587d8249367417b2b2512c41', - title: 'Metric-Imperial Converter', - link: `${legacyInfosecQaBase}/metric-imperial-converter`, - superBlock: 'legacy-information-security-and-quality-assurance' - }, - { - id: '587d8249367417b2b2512c42', - title: 'Issue Tracker', - link: `${legacyInfosecQaBase}/issue-tracker`, - superBlock: 'legacy-information-security-and-quality-assurance' - }, - { - id: '587d824a367417b2b2512c43', - title: 'Personal Library', - link: `${legacyInfosecQaBase}/personal-library`, - superBlock: 'legacy-information-security-and-quality-assurance' - }, - { - id: '587d824a367417b2b2512c44', - title: 'Stock Price Checker', - link: `${legacyInfosecQaBase}/stock-price-checker`, - superBlock: 'legacy-information-security-and-quality-assurance' - }, - { - id: '587d824a367417b2b2512c45', - title: 'Anonymous Message Board', - link: `${legacyInfosecQaBase}/anonymous-message-board`, - superBlock: 'legacy-information-security-and-quality-assurance' - } - ] -}; - -export const projectMap = { - 'Responsive Web Design': [ - { - id: 'bd7158d8c442eddfaeb5bd18', - title: 'Build a Tribute Page', - link: `${responsiveWebBase}/build-a-tribute-page`, - superBlock: 'responsive-web-design' - }, - { - id: '587d78af367417b2b2512b03', - title: 'Build a Survey Form', - link: `${responsiveWebBase}/build-a-survey-form`, - superBlock: 'responsive-web-design' - }, - { - id: '587d78af367417b2b2512b04', - title: 'Build a Product Landing Page', - link: `${responsiveWebBase}/build-a-product-landing-page`, - superBlock: 'responsive-web-design' - }, - { - id: '587d78b0367417b2b2512b05', - title: 'Build a Technical Documentation Page', - link: `${responsiveWebBase}/build-a-technical-documentation-page`, - superBlock: 'responsive-web-design' - }, - { - id: 'bd7158d8c242eddfaeb5bd13', - title: 'Build a Personal Portfolio Webpage', - link: `${responsiveWebBase}/build-a-personal-portfolio-webpage`, - superBlock: 'responsive-web-design' - } - ], - 'JavaScript Algorithms and Data Structures': [ - { - id: 'aaa48de84e1ecc7c742e1124', - title: 'Palindrome Checker', - link: `${jsAlgoBase}/palindrome-checker`, - superBlock: 'javascript-algorithms-and-data-structures' - }, - { - id: 'a7f4d8f2483413a6ce226cac', - title: 'Roman Numeral Converter', - link: `${jsAlgoBase}/roman-numeral-converter`, - superBlock: 'javascript-algorithms-and-data-structures' - }, - { - id: '56533eb9ac21ba0edf2244e2', - title: 'Caesars Cipher', - link: `${jsAlgoBase}/caesars-cipher`, - superBlock: 'javascript-algorithms-and-data-structures' - }, - { - id: 'aff0395860f5d3034dc0bfc9', - title: 'Telephone Number Validator', - link: `${jsAlgoBase}/telephone-number-validator`, - superBlock: 'javascript-algorithms-and-data-structures' - }, - { - id: 'aa2e6f85cab2ab736c9a9b24', - title: 'Cash Register', - link: `${jsAlgoBase}/cash-register`, - superBlock: 'javascript-algorithms-and-data-structures' - } - ], - 'Front End Libraries': [ - { - id: 'bd7158d8c442eddfaeb5bd13', - title: 'Build a Random Quote Machine', - link: `${feLibsBase}/build-a-random-quote-machine`, - superBlock: 'front-end-libraries' - }, - { - id: 'bd7157d8c242eddfaeb5bd13', - title: 'Build a Markdown Previewer', - link: `${feLibsBase}/build-a-markdown-previewer`, - superBlock: 'front-end-libraries' - }, - { - id: '587d7dbc367417b2b2512bae', - title: 'Build a Drum Machine', - link: `${feLibsBase}/build-a-drum-machine`, - superBlock: 'front-end-libraries' - }, - { - id: 'bd7158d8c442eddfaeb5bd17', - title: 'Build a JavaScript Calculator', - link: `${feLibsBase}/build-a-javascript-calculator`, - superBlock: 'front-end-libraries' - }, - { - id: 'bd7158d8c442eddfaeb5bd0f', - title: 'Build a Pomodoro Clock', - link: `${feLibsBase}/build-a-pomodoro-clock`, - superBlock: 'front-end-libraries' - } - ], - 'Data Visualization': [ - { - id: 'bd7168d8c242eddfaeb5bd13', - title: 'Visualize Data with a Bar Chart', - link: `${dataVisBase}/visualize-data-with-a-bar-chart`, - superBlock: 'data-visualization' - }, - { - id: 'bd7178d8c242eddfaeb5bd13', - title: 'Visualize Data with a Scatterplot Graph', - link: `${dataVisBase}/visualize-data-with-a-scatterplot-graph`, - superBlock: 'data-visualization' - }, - { - id: 'bd7188d8c242eddfaeb5bd13', - title: 'Visualize Data with a Heat Map', - link: `${dataVisBase}/visualize-data-with-a-heat-map`, - superBlock: 'data-visualization' - }, - { - id: '587d7fa6367417b2b2512bbf', - title: 'Visualize Data with a Choropleth Map', - link: `${dataVisBase}/visualize-data-with-a-choropleth-map`, - superBlock: 'data-visualization' - }, - { - id: '587d7fa6367417b2b2512bc0', - title: 'Visualize Data with a Treemap Diagram', - link: `${dataVisBase}/visualize-data-with-a-treemap-diagram`, - superBlock: 'data-visualization' - } - ], - "API's and Microservices": [ - { - id: 'bd7158d8c443edefaeb5bdef', - title: 'Timestamp Microservice', - link: `${apiMicroBase}/timestamp-microservice`, - superBlock: 'apis-and-microservices' - }, - { - id: 'bd7158d8c443edefaeb5bdff', - title: 'Request Header Parser Microservice', - link: `${apiMicroBase}/request-header-parser-microservice`, - superBlock: 'apis-and-microservices' - }, - { - id: 'bd7158d8c443edefaeb5bd0e', - title: 'URL Shortener Microservice', - link: `${apiMicroBase}/url-shortener-microservice`, - superBlock: 'apis-and-microservices' - }, - { - id: '5a8b073d06fa14fcfde687aa', - title: 'Exercise Tracker', - link: `${apiMicroBase}/exercise-tracker`, - superBlock: 'apis-and-microservices' - }, - { - id: 'bd7158d8c443edefaeb5bd0f', - title: 'File Metadata Microservice', - link: `${apiMicroBase}/file-metadata-microservice`, - superBlock: 'apis-and-microservices' - } - ], - 'Quality Assurance': [ - { - id: '587d8249367417b2b2512c41', - title: 'Metric-Imperial Converter', - link: `${qaBase}/metric-imperial-converter`, - superBlock: 'quality-assurance' - }, - { - id: '587d8249367417b2b2512c42', - title: 'Issue Tracker', - link: `${qaBase}/issue-tracker`, - superBlock: 'quality-assurance' - }, - { - id: '587d824a367417b2b2512c43', - title: 'Personal Library', - link: `${qaBase}/personal-library`, - superBlock: 'quality-assurance' - }, - { - id: '5e601bf95ac9d0ecd8b94afd', - title: 'Sudoku Solver', - link: `${qaBase}/sudoku-solver`, - superBlock: 'quality-assurance' - }, - { - id: '5e601c0d5ac9d0ecd8b94afe', - title: 'American British Translator', - link: `${qaBase}/american-british-translator`, - superBlock: 'quality-assurance' - } - ], - 'Information Security': [ - { - id: '587d824a367417b2b2512c44', - title: 'Stock Price Checker', - link: `${infoSecBase}/stock-price-checker`, - superBlock: 'information-security' - }, - { - id: '587d824a367417b2b2512c45', - title: 'Anonymous Message Board', - link: `${infoSecBase}/anonymous-message-board`, - superBlock: 'information-security' - }, - { - id: '5e46f979ac417301a38fb932', - title: 'Port Scanner', - link: `${infoSecBase}/port-scanner`, - superBlock: 'information-security' - }, - { - id: '5e46f983ac417301a38fb933', - title: 'SHA-1 Password Cracker', - link: `${infoSecBase}/sha-1-password-cracker`, - superBlock: 'information-security' - }, - { - id: '5e601c775ac9d0ecd8b94aff', - title: 'Secure Real Time Multiplayer Game', - link: `${infoSecBase}/secure-real-time-multiplayer-game`, - superBlock: 'information-security' - } - ], - 'Scientific Computing with Python': [ - { - id: '5e44412c903586ffb414c94c', - title: 'Arithmetic Formatter', - link: `${sciCompPyBase}/arithmetic-formatter`, - superBlock: 'scientific-computing-with-python' - }, - { - id: '5e444136903586ffb414c94d', - title: 'Time Calculator', - link: `${sciCompPyBase}/time-calculator`, - superBlock: 'scientific-computing-with-python' - }, - { - id: '5e44413e903586ffb414c94e', - title: 'Budget App', - link: `${sciCompPyBase}/budget-app`, - superBlock: 'scientific-computing-with-python' - }, - { - id: '5e444147903586ffb414c94f', - title: 'Polygon Area Calculator', - link: `${sciCompPyBase}/polygon-area-calculator`, - superBlock: 'scientific-computing-with-python' - }, - { - id: '5e44414f903586ffb414c950', - title: 'Probability Calculator', - link: `${sciCompPyBase}/probability-calculator`, - superBlock: 'scientific-computing-with-python' - } - ], - 'Data Analysis with Python': [ - { - id: '5e46f7e5ac417301a38fb928', - title: 'Mean-Variance-Standard Deviation Calculator', - link: `${dataAnalysisPyBase}/mean-variance-standard-deviation-calculator`, - superBlock: 'data-analysis-with-python' - }, - { - id: '5e46f7e5ac417301a38fb929', - title: 'Demographic Data Analyzer', - link: `${dataAnalysisPyBase}/demographic-data-analyzer`, - superBlock: 'data-analysis-with-python' - }, - { - id: '5e46f7f8ac417301a38fb92a', - title: 'Medical Data Visualizer', - link: `${dataAnalysisPyBase}/medical-data-visualizer`, - superBlock: 'data-analysis-with-python' - }, - { - id: '5e46f802ac417301a38fb92b', - title: 'Page View Time Series Visualizer', - link: `${dataAnalysisPyBase}/page-view-time-series-visualizer`, - superBlock: 'data-analysis-with-python' - }, - { - id: '5e4f5c4b570f7e3a4949899f', - title: 'Sea Level Predictor', - link: `${dataAnalysisPyBase}/sea-level-predictor`, - superBlock: 'scientific-computing-with-python' - } - ], - 'Machine Learning with Python': [ - { - id: '5e46f8d6ac417301a38fb92d', - title: 'Rock Paper Scissors', - link: `${machineLearningPyBase}/rock-paper-scissors`, - superBlock: 'machine-learning-with-python' - }, - { - id: '5e46f8dcac417301a38fb92e', - title: 'Cat and Dog Image Classifier', - link: `${machineLearningPyBase}/cat-and-dog-image-classifier`, - superBlock: 'machine-learning-with-python' - }, - { - id: '5e46f8e3ac417301a38fb92f', - title: 'Book Recommendation Engine using KNN', - link: `${machineLearningPyBase}/book-recommendation-engine-using-knn`, - superBlock: 'machine-learning-with-python' - }, - { - id: '5e46f8edac417301a38fb930', - title: 'Linear Regression Health Costs Calculator', - link: `${machineLearningPyBase}/linear-regression-health-costs-calculator`, - superBlock: 'machine-learning-with-python' - }, - { - id: '5e46f8edac417301a38fb931', - title: 'Neural Network SMS Text Classifier', - link: `${machineLearningPyBase}/neural-network-sms-text-classifier`, - superBlock: 'machine-learning-with-python' - } - ] -}; diff --git a/client/utils/challengeTypes.js b/client/utils/challengeTypes.js index 037b6b2c03..df4e4b3ee7 100644 --- a/client/utils/challengeTypes.js +++ b/client/utils/challengeTypes.js @@ -120,11 +120,11 @@ exports.helpCategory = { 'take-home-projects': 'Certification Projects', 'rosetta-code': 'JavaScript', 'project-euler': 'JavaScript', - 'scientific-computing-with-python': 'Certification Projects', + 'scientific-computing-with-python': 'Python', 'scientific-computing-with-python-projects': 'Certification Projects', - 'data-analysis-with-python': 'Certification Projects', + 'data-analysis-with-python': 'Python', 'data-analysis-with-python-projects': 'Certification Projects', - 'machine-learning-with-python': 'Certification Projects', + 'machine-learning-with-python': 'Python', 'machine-learning-with-python-projects': 'Certification Projects', 'python-for-everybody': 'Python', tensorflow: 'Python', diff --git a/client/utils/validCertNames.js b/client/utils/validCertNames.js deleted file mode 100644 index d751ecfdbc..0000000000 --- a/client/utils/validCertNames.js +++ /dev/null @@ -1,17 +0,0 @@ -export default [ - 'responsive-web-design', - 'javascript-algorithms-and-data-structures', - 'front-end-libraries', - 'data-visualization', - 'apis-and-microservices', - 'full-stack', - 'scientific-computing-with-python', - 'data-analysis-with-python', - 'machine-learning-with-python', - 'information-security', - 'quality-assurance', - 'legacy-front-end', - 'legacy-back-end', - 'legacy-data-visualization', - 'legacy-information-security-and-quality-assurance' -]; diff --git a/curriculum/challenges/_meta/apis-and-microservices-certificate/meta.json b/curriculum/challenges/_meta/apis-and-microservices-certificate/meta.json index 4be9c9bc2f..e8f9c6d064 100644 --- a/curriculum/challenges/_meta/apis-and-microservices-certificate/meta.json +++ b/curriculum/challenges/_meta/apis-and-microservices-certificate/meta.json @@ -1,5 +1,5 @@ { - "name": "API's and Microservices Certificate", + "name": "APIs and Microservices Certificate", "dashedName": "apis-and-microservices-certificate", "order": 5, "time": "", @@ -10,7 +10,7 @@ "challengeOrder": [ [ "561add10cb82ac38a17523bc", - "API's and Microservices Certificate" + "APIs and Microservices Certificate" ] ], "isPrivate": true, diff --git a/curriculum/challenges/_meta/data-analysis-with-python-certificate/meta.json b/curriculum/challenges/_meta/data-analysis-with-python-certificate/meta.json index 4aee5eed58..9f1c86016b 100644 --- a/curriculum/challenges/_meta/data-analysis-with-python-certificate/meta.json +++ b/curriculum/challenges/_meta/data-analysis-with-python-certificate/meta.json @@ -1,6 +1,6 @@ { "name": "Data Analysis with Python Certificate", - "dashedName": "data-analysis-with-python-certificate", + "dashedName": "2020-data-analysis-with-python-certificate", "order": 8, "time": "", "template": "", @@ -14,5 +14,5 @@ ] ], "isPrivate": true, - "fileName": "12-certificates/data-analysis-with-python-certificate.json" + "fileName": "12-certificates/2020-data-analysis-with-python-certificate.json" } \ No newline at end of file diff --git a/curriculum/challenges/_meta/information-security-certificate/meta.json b/curriculum/challenges/_meta/information-security-certificate/meta.json index e01447a453..57b38de78e 100644 --- a/curriculum/challenges/_meta/information-security-certificate/meta.json +++ b/curriculum/challenges/_meta/information-security-certificate/meta.json @@ -1,6 +1,6 @@ { "name": "Information Security Certificate", - "dashedName": "information-security-certificate", + "dashedName": "2020-information-security-certificate", "order": 9, "time": "", "template": "", @@ -14,5 +14,5 @@ ] ], "isPrivate": true, - "fileName": "12-certificates/information-security-certificate.json" + "fileName": "12-certificates/2020-information-security-certificate.json" } \ No newline at end of file diff --git a/curriculum/challenges/_meta/information-security-projects/meta.json b/curriculum/challenges/_meta/information-security-projects/meta.json index 886cb6b6b9..386d9daa22 100644 --- a/curriculum/challenges/_meta/information-security-projects/meta.json +++ b/curriculum/challenges/_meta/information-security-projects/meta.json @@ -16,10 +16,6 @@ "587d824a367417b2b2512c45", "Anonymous Message Board" ], - [ - "5e601c775ac9d0ecd8b94aff", - "Secure Real Time Multiplayer Game" - ], [ "5e46f979ac417301a38fb932", "Port Scanner" @@ -27,6 +23,10 @@ [ "5e46f983ac417301a38fb933", "SHA-1 Password Cracker" + ], + [ + "5e601c775ac9d0ecd8b94aff", + "Secure Real Time Multiplayer Game" ] ], "helpRoom": "HelpBackend", diff --git a/curriculum/challenges/_meta/full-stack-certificate/meta.json b/curriculum/challenges/_meta/legacy-full-stack-certificate/meta.json similarity index 58% rename from curriculum/challenges/_meta/full-stack-certificate/meta.json rename to curriculum/challenges/_meta/legacy-full-stack-certificate/meta.json index 58469fde97..1a876447ff 100644 --- a/curriculum/challenges/_meta/full-stack-certificate/meta.json +++ b/curriculum/challenges/_meta/legacy-full-stack-certificate/meta.json @@ -1,5 +1,5 @@ { - "name": "Full Stack Certificate", + "name": "Legacy Full Stack Certificate", "dashedName": "full-stack-certificate", "order": 5, "time": "", @@ -10,9 +10,9 @@ "challengeOrder": [ [ "561add10cb82ac38a17213bd", - "Full Stack Certificate" + "Legacy Full Stack Certificate" ] ], "isPrivate": true, - "fileName": "12-certificates/full-stack-certificate.json" + "fileName": "12-certificates/legacy-full-stack-certificate/full-stack-certificate.english.json" } diff --git a/curriculum/challenges/_meta/legacy-information-security-and-quality-assurance-certificate/meta.json b/curriculum/challenges/_meta/legacy-information-security-and-quality-assurance-certificate/meta.json index 8c4c188945..22d53ab893 100644 --- a/curriculum/challenges/_meta/legacy-information-security-and-quality-assurance-certificate/meta.json +++ b/curriculum/challenges/_meta/legacy-information-security-and-quality-assurance-certificate/meta.json @@ -1,6 +1,6 @@ { "name": "Legacy Information Security and Quality Assurance Certificate", - "dashedName": "legacy-information-security-and-quality-assurance-certificate", + "dashedName": "information-security-and-quality-assurance-certificate", "order": 1, "time": "", "template": "", @@ -14,5 +14,5 @@ ] ], "isPrivate": true, - "fileName": "12-certificates/legacy-information-security-and-quality-assurance-certificate.json" + "fileName": "12-certificates/information-security-and-quality-assurance-certificate.json" } \ No newline at end of file diff --git a/curriculum/challenges/_meta/machine-learning-with-python-certificate/meta.json b/curriculum/challenges/_meta/machine-learning-with-python-certificate/meta.json index d32f5c7911..ddd3485500 100644 --- a/curriculum/challenges/_meta/machine-learning-with-python-certificate/meta.json +++ b/curriculum/challenges/_meta/machine-learning-with-python-certificate/meta.json @@ -1,6 +1,6 @@ { "name": "Machine Learning with Python Certificate", - "dashedName": "machine-learning-with-python-certificate", + "dashedName": "2020-machine-learning-with-python-certificate", "order": 10, "time": "", "template": "", @@ -14,5 +14,5 @@ ] ], "isPrivate": true, - "fileName": "12-certificates/machine-learning-with-python-certificate.json" + "fileName": "12-certificates/2020-machine-learning-with-python-certificate.json" } \ No newline at end of file diff --git a/curriculum/challenges/_meta/quality-assurance-certificate/meta.json b/curriculum/challenges/_meta/quality-assurance-certificate/meta.json index 8e14a591b2..8b98dd1d4f 100644 --- a/curriculum/challenges/_meta/quality-assurance-certificate/meta.json +++ b/curriculum/challenges/_meta/quality-assurance-certificate/meta.json @@ -1,6 +1,6 @@ { "name": "Quality Assurance Certificate", - "dashedName": "quality-assurance-certificate", + "dashedName": "2020-quality-assurance-certificate", "order": 6, "time": "", "template": "", @@ -14,5 +14,5 @@ ] ], "isPrivate": true, - "fileName": "12-certificates/quality-assurance-certificate.json" + "fileName": "12-certificates/2020-quality-assurance-certificate.json" } \ No newline at end of file diff --git a/curriculum/challenges/_meta/scientific-computing-with-python-certificate/meta.json b/curriculum/challenges/_meta/scientific-computing-with-python-certificate/meta.json index 5394a3f108..93388e8006 100644 --- a/curriculum/challenges/_meta/scientific-computing-with-python-certificate/meta.json +++ b/curriculum/challenges/_meta/scientific-computing-with-python-certificate/meta.json @@ -1,6 +1,6 @@ { "name": "Scientific Computing with Python Certificate", - "dashedName": "scientific-computing-with-python-certificate", + "dashedName": "2020-scientific-computing-with-python-certificate", "order": 7, "time": "", "template": "", @@ -14,5 +14,5 @@ ] ], "isPrivate": true, - "fileName": "12-certificates/scientific-computing-with-python-certificate.json" + "fileName": "12-certificates/2020-scientific-computing-with-python-certificate.json" } \ No newline at end of file diff --git a/curriculum/challenges/english/12-certificates/apis-and-microservices-certificate/apis-and-microservices-certificate.english.md b/curriculum/challenges/english/12-certificates/apis-and-microservices-certificate/apis-and-microservices-certificate.english.md index f531273059..d87bbfec14 100644 --- a/curriculum/challenges/english/12-certificates/apis-and-microservices-certificate/apis-and-microservices-certificate.english.md +++ b/curriculum/challenges/english/12-certificates/apis-and-microservices-certificate/apis-and-microservices-certificate.english.md @@ -1,6 +1,6 @@ --- id: 561add10cb82ac38a17523bc -title: API's and Microservices Certificate +title: APIs and Microservices Certificate challengeType: 7 isHidden: false isPrivate: true diff --git a/curriculum/challenges/english/12-certificates/information-security-certificate/information-security-certificate.english.md b/curriculum/challenges/english/12-certificates/information-security-certificate/information-security-certificate.english.md index 63383edb08..ea9bde8976 100644 --- a/curriculum/challenges/english/12-certificates/information-security-certificate/information-security-certificate.english.md +++ b/curriculum/challenges/english/12-certificates/information-security-certificate/information-security-certificate.english.md @@ -27,10 +27,10 @@ tests: title: Anonymous Message Board - id: 5e46f979ac417301a38fb932 title: Port Scanner - - id: 5e601c775ac9d0ecd8b94aff - title: Secure Real Time Multiplayer Game - id: 5e46f983ac417301a38fb933 title: SHA-1 Password Cracker + - id: 5e601c775ac9d0ecd8b94aff + title: Secure Real Time Multiplayer Game ```
diff --git a/curriculum/challenges/english/12-certificates/full-stack-certificate/full-stack-certificate.english.md b/curriculum/challenges/english/12-certificates/legacy-full-stack-certificate/legacy-full-stack-certificate.english.md similarity index 96% rename from curriculum/challenges/english/12-certificates/full-stack-certificate/full-stack-certificate.english.md rename to curriculum/challenges/english/12-certificates/legacy-full-stack-certificate/legacy-full-stack-certificate.english.md index 6826f02679..95d5bee65e 100644 --- a/curriculum/challenges/english/12-certificates/full-stack-certificate/full-stack-certificate.english.md +++ b/curriculum/challenges/english/12-certificates/legacy-full-stack-certificate/legacy-full-stack-certificate.english.md @@ -1,6 +1,6 @@ --- id: 561add10cb82ac38a17213bd -title: Full Stack Certificate +title: Legacy Full Stack Certificate challengeType: 7 isHidden: false isPrivate: true diff --git a/tools/scripts/build/__snapshots__/create-redirects.test.js.snap b/tools/scripts/build/__snapshots__/create-redirects.test.js.snap index fbaf15ba0a..655686ee61 100644 --- a/tools/scripts/build/__snapshots__/create-redirects.test.js.snap +++ b/tools/scripts/build/__snapshots__/create-redirects.test.js.snap @@ -43,7 +43,6 @@ https://freecodecamp-org.netlify.com/* https://www.freecodecamp.org/:spla /:username/front-end-certification /certification/:username/legacy-front-end 301 /:username/data-visualization-certification /certification/:username/legacy-data-visualization 301 /:username/back-end-certification /certification/:username/legacy-back-end 301 -/:username/information-security-and-quality-assurance /certification/:username/legacy-information-security-and-quality-assurance 301 /:username/full-stack-certification /certification/:username/full-stack 301 # unsubscribe redirects diff --git a/tools/scripts/build/create-redirects.js b/tools/scripts/build/create-redirects.js index f3d2dc3cc1..a74f64f0ab 100644 --- a/tools/scripts/build/create-redirects.js +++ b/tools/scripts/build/create-redirects.js @@ -64,7 +64,6 @@ https://freecodecamp-org.netlify.com/* https://www.freecodecamp.org/:spla /:username/front-end-certification /certification/:username/legacy-front-end 301 /:username/data-visualization-certification /certification/:username/legacy-data-visualization 301 /:username/back-end-certification /certification/:username/legacy-back-end 301 -/:username/information-security-and-quality-assurance /certification/:username/legacy-information-security-and-quality-assurance 301 /:username/full-stack-certification /certification/:username/full-stack 301 # unsubscribe redirects diff --git a/utils/index.js b/utils/index.js index 6365d9e39d..9c9667d7f7 100644 --- a/utils/index.js +++ b/utils/index.js @@ -14,7 +14,7 @@ const idToTitle = new Map( '561add10cb82ac38a17513be': 'Legacy Front End', '561add10cb82ac38a17213bc': 'Legacy Information Security and Quality Assurance', - '561add10cb82ac38a17213bd': 'Full Stack', + '561add10cb82ac38a17213bd': 'Legacy Full Stack', '5e44431b903586ffb414c951': 'Scientific Computing with Python', '5e46fc95ac417301a38fb934': 'Data Analysis with Python', '5e46fc95ac417301a38fb935': 'Machine Learning with Python' @@ -23,8 +23,25 @@ const idToTitle = new Map( const idToPath = new Map(); +// Keep the timeline slugs the same so +// we don't break existing links +const specialPaths = { + 'Legacy Full Stack': 'Full Stack', + 'Legacy Information Security and Quality Assurance': + 'Information Security and Quality Assurance', + 'Scientific Computing with Python': '2020 Scientific Computing with Python', + 'Data Analysis with Python': '2020 Data Analysis with Python', + 'Machine Learning with Python': '2020 Machine Learning with Python', + 'Quality Assurance': '2020 Quality Assurance', + 'Information Security': '2020 Information Security' +}; + for (const [id, title] of idToTitle) { - idToPath.set(id, dasherize(title)); + if (specialPaths[title]) { + idToPath.set(id, dasherize(specialPaths[title])); + } else { + idToPath.set(id, dasherize(title)); + } } export const getCertIds = () => idToPath.keys();