mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-09-24 23:01:18 +08:00
refactor: use cert as key (#64293)
This commit is contained in:
@@ -6,7 +6,7 @@ import { getChallenges } from '../../utils/get-challenges.js';
|
||||
import {
|
||||
certIds,
|
||||
certSlugTypeMap,
|
||||
certTypeTitleMap,
|
||||
certToTitleMap,
|
||||
certTypes,
|
||||
currentCertifications,
|
||||
legacyCertifications,
|
||||
@@ -298,7 +298,7 @@ export const protectedCertificateRoutes: FastifyPluginCallbackTypebox = (
|
||||
}
|
||||
|
||||
const certType = certSlugTypeMap[certSlug];
|
||||
const certName = certTypeTitleMap[certType];
|
||||
const certName = certToTitleMap[certSlug];
|
||||
|
||||
const user = await fastify.prisma.user.findUnique({
|
||||
where: { id: req.user?.id }
|
||||
|
||||
@@ -4,7 +4,7 @@ import { find } from 'lodash-es';
|
||||
import * as schemas from '../../schemas.js';
|
||||
import {
|
||||
certSlugTypeMap,
|
||||
certTypeTitleMap,
|
||||
certToTitleMap,
|
||||
certTypeIdMap,
|
||||
completionHours,
|
||||
oldDataVizId
|
||||
@@ -53,7 +53,7 @@ export const unprotectedCertificateRoutes: FastifyPluginCallbackTypebox = (
|
||||
|
||||
const certType = certSlugTypeMap[certSlug];
|
||||
const certId = certTypeIdMap[certType];
|
||||
const certTitle = certTypeTitleMap[certType];
|
||||
const certTitle = certToTitleMap[certSlug];
|
||||
const completionTime = completionHours[certType] || 300;
|
||||
const user = await fastify.prisma.user.findFirst({
|
||||
where: { username },
|
||||
@@ -180,16 +180,15 @@ export const unprotectedCertificateRoutes: FastifyPluginCallbackTypebox = (
|
||||
}
|
||||
|
||||
if (!user[certType]) {
|
||||
const cert = certTypeTitleMap[certType];
|
||||
logger.info(
|
||||
`User ${username} has not completed the ${cert} certification.`
|
||||
`User ${username} has not completed the ${certTitle} certification.`
|
||||
);
|
||||
return reply.send({
|
||||
messages: [
|
||||
{
|
||||
type: 'info',
|
||||
message: 'flash.user-not-certified',
|
||||
variables: { username, cert }
|
||||
variables: { username, cert: certTitle }
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@ import { createSelector } from 'reselect';
|
||||
import { liveCerts } from '../../config/cert-and-project-map';
|
||||
import {
|
||||
certTypeIdMap,
|
||||
certTypeTitleMap
|
||||
certToTitleMap
|
||||
} from '../../../shared-dist/config/certification-settings.js';
|
||||
|
||||
import { randomBetween } from '../utils/random-between';
|
||||
@@ -238,18 +238,10 @@ export const claimableCertsSelector = createSelector([userSelector], user => {
|
||||
},
|
||||
{}
|
||||
);
|
||||
// Invert certTypeIdMap ({[userFlag]: certId} => {[certId]: userFlag}) to get certType from id
|
||||
const invertedCertTypeIdMap = Object.entries(certTypeIdMap).reduce(
|
||||
(acc, [userFlag, certId]) => {
|
||||
acc[certId] = userFlag;
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
);
|
||||
|
||||
const claimable = [];
|
||||
|
||||
for (const { id, projects } of liveCerts) {
|
||||
for (const { id, projects, certSlug } of liveCerts) {
|
||||
if (!projects) continue;
|
||||
if (isClaimedById[id]) continue;
|
||||
|
||||
@@ -258,8 +250,7 @@ export const claimableCertsSelector = createSelector([userSelector], user => {
|
||||
completedChallengeIds.includes(id)
|
||||
);
|
||||
|
||||
const certType = invertedCertTypeIdMap[id];
|
||||
const certTitle = certTypeTitleMap[certType];
|
||||
const certTitle = certToTitleMap[certSlug];
|
||||
if (allProjectsComplete) {
|
||||
claimable.push({
|
||||
certTitle
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { Certification, linkedInCredentialIds } from './certification-settings';
|
||||
import {
|
||||
Certification,
|
||||
linkedInCredentialIds,
|
||||
certToTitleMap
|
||||
} from './certification-settings';
|
||||
|
||||
describe('linkedInCredentialIds', () => {
|
||||
it('should contain a value for all certifications', () => {
|
||||
@@ -9,3 +13,12 @@ describe('linkedInCredentialIds', () => {
|
||||
expect(linkedInCredentialIdsKeys).toEqual(allCertifications);
|
||||
});
|
||||
});
|
||||
|
||||
describe('certToTitleMap', () => {
|
||||
it('should not contain duplicate titles', () => {
|
||||
const titles = Object.values(certToTitleMap);
|
||||
const uniqueTitles = Array.from(new Set(titles));
|
||||
|
||||
expect(titles.length).toBe(uniqueTitles.length);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -269,31 +269,47 @@ export const certTypeIdMap = {
|
||||
[certTypes.a2English]: certIds.a2EnglishId
|
||||
};
|
||||
|
||||
export const certTypeTitleMap = {
|
||||
[certTypes.frontEnd]: 'Legacy Front End',
|
||||
[certTypes.backEnd]: 'Legacy Back End',
|
||||
[certTypes.dataVis]: 'Legacy Data Visualization',
|
||||
[certTypes.infosecQa]: 'Legacy Information Security and Quality Assurance',
|
||||
[certTypes.fullStack]: 'Legacy Full Stack',
|
||||
[certTypes.respWebDesign]: 'Legacy Responsive Web Design V8',
|
||||
[certTypes.respWebDesignV9]: 'Responsive Web Design',
|
||||
[certTypes.frontEndDevLibs]: 'Front End Development Libraries V8',
|
||||
[certTypes.jsAlgoDataStruct]:
|
||||
// TODO: use i18n keys instead of hardcoded titles
|
||||
export const certToTitleMap: Record<Certification, string> = {
|
||||
// Legacy certifications
|
||||
[Certification.LegacyFrontEnd]: 'Legacy Front End',
|
||||
[Certification.JsAlgoDataStruct]:
|
||||
'Legacy JavaScript Algorithms and Data Structures V7',
|
||||
[certTypes.dataVis2018]: 'Data Visualization V8',
|
||||
[certTypes.apisMicroservices]: 'Back End Development and APIs V8',
|
||||
[certTypes.qaV7]: 'Quality Assurance',
|
||||
[certTypes.infosecV7]: 'Information Security',
|
||||
[certTypes.sciCompPyV7]: 'Scientific Computing with Python',
|
||||
[certTypes.dataAnalysisPyV7]: 'Data Analysis with Python',
|
||||
[certTypes.machineLearningPyV7]: 'Machine Learning with Python',
|
||||
[certTypes.relationalDatabaseV8]: 'Relational Database V8',
|
||||
[certTypes.collegeAlgebraPyV8]: 'College Algebra with Python',
|
||||
[certTypes.foundationalCSharpV8]: 'Foundational C# with Microsoft',
|
||||
[certTypes.jsAlgoDataStructV8]:
|
||||
[Certification.LegacyBackEnd]: 'Legacy Back End',
|
||||
[Certification.LegacyDataVis]: 'Legacy Data Visualization',
|
||||
[Certification.LegacyInfoSecQa]:
|
||||
'Legacy Information Security and Quality Assurance',
|
||||
[Certification.LegacyFullStack]: 'Legacy Full Stack',
|
||||
|
||||
// Current certifications
|
||||
[Certification.RespWebDesign]: 'Legacy Responsive Web Design V8',
|
||||
[Certification.JsAlgoDataStructNew]:
|
||||
'Legacy JavaScript Algorithms and Data Structures V8',
|
||||
[certTypes.javascriptV9]: 'JavaScript',
|
||||
[certTypes.a2English]: 'A2 English for Developers'
|
||||
[Certification.FrontEndDevLibs]: 'Front End Development Libraries V8',
|
||||
[Certification.DataVis]: 'Data Visualization V8',
|
||||
[Certification.BackEndDevApis]: 'Back End Development and APIs V8',
|
||||
[Certification.QualityAssurance]: 'Quality Assurance',
|
||||
[Certification.InfoSec]: 'Information Security',
|
||||
[Certification.SciCompPy]: 'Scientific Computing with Python',
|
||||
[Certification.DataAnalysisPy]: 'Data Analysis with Python',
|
||||
[Certification.MachineLearningPy]: 'Machine Learning with Python',
|
||||
[Certification.RelationalDb]: 'Relational Database V8',
|
||||
[Certification.CollegeAlgebraPy]: 'College Algebra with Python',
|
||||
[Certification.FoundationalCSharp]: 'Foundational C# with Microsoft',
|
||||
[Certification.A2English]: 'A2 English for Developers',
|
||||
|
||||
// Upcoming certifications
|
||||
[Certification.RespWebDesignV9]: 'Responsive Web Design',
|
||||
[Certification.JsV9]: 'JavaScript',
|
||||
[Certification.FrontEndDevLibsV9]: 'Front End Development Libraries',
|
||||
[Certification.PythonV9]: 'Python',
|
||||
[Certification.RelationalDbV9]: 'Relational Database',
|
||||
[Certification.BackEndDevApisV9]: 'Back End Development and APIs',
|
||||
[Certification.FullStackDeveloperV9]: 'Full Stack Developer',
|
||||
[Certification.B1English]: 'B1 English for Developers',
|
||||
[Certification.A2Spanish]: 'A2 Professional Spanish',
|
||||
[Certification.A2Chinese]: 'A2 Professional Chinese',
|
||||
[Certification.A1Chinese]: 'A1 Professional Chinese'
|
||||
};
|
||||
|
||||
export const superBlockToCertMap: {
|
||||
|
||||
@@ -174,7 +174,7 @@ export const canSaveToDB = (challengeType: number): boolean =>
|
||||
challengeType === challengeTypes.multifileCertProject ||
|
||||
challengeType === challengeTypes.multifilePythonCertProject;
|
||||
|
||||
export const dailyCodingChallengeTypes = [
|
||||
const dailyCodingChallengeTypes = [
|
||||
challengeTypes.dailyChallengeJs,
|
||||
challengeTypes.dailyChallengePy
|
||||
];
|
||||
@@ -182,7 +182,7 @@ export const dailyCodingChallengeTypes = [
|
||||
export const getIsDailyCodingChallenge = (challengeType: number): boolean =>
|
||||
dailyCodingChallengeTypes.includes(challengeType);
|
||||
|
||||
export const dailyCodingChallengeLanguages = {
|
||||
const dailyCodingChallengeLanguages = {
|
||||
[challengeTypes.dailyChallengeJs]: 'javascript',
|
||||
[challengeTypes.dailyChallengePy]: 'python'
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user