diff --git a/api/prisma/schema.prisma b/api/prisma/schema.prisma index dde5727582e..76deade4a00 100644 --- a/api/prisma/schema.prisma +++ b/api/prisma/schema.prisma @@ -105,6 +105,7 @@ model user { emailVerifyTTL DateTime? // Null | Undefined externalId String githubProfile String? // Undefined + isA2EnglishCert Boolean? // Undefined isApisMicroservicesCert Boolean? // Undefined isBackEndCert Boolean? // Undefined isBanned Boolean? // Undefined diff --git a/api/src/plugins/__fixtures__/user.ts b/api/src/plugins/__fixtures__/user.ts index b37c81da212..b2ac60299f0 100644 --- a/api/src/plugins/__fixtures__/user.ts +++ b/api/src/plugins/__fixtures__/user.ts @@ -28,6 +28,7 @@ export const newUser = (email: string) => ({ id: expect.stringMatching(mongodbIdRe), is2018DataVisCert: false, is2018FullStackCert: false, + isA2EnglishCert: false, isApisMicroservicesCert: false, isBackEndCert: false, isBanned: false, diff --git a/api/src/routes/helpers/user-utils.ts b/api/src/routes/helpers/user-utils.ts index 8c6c2c13857..b690820a8c4 100644 --- a/api/src/routes/helpers/user-utils.ts +++ b/api/src/routes/helpers/user-utils.ts @@ -7,6 +7,7 @@ import { pick, omit } from 'lodash-es'; const nullableFlags = [ 'is2018DataVisCert', 'is2018FullStackCert', + 'isA2EnglishCert', 'isApisMicroservicesCert', 'isBackEndCert', 'isCheater', diff --git a/api/src/routes/protected/certificate.test.ts b/api/src/routes/protected/certificate.test.ts index d0d0c007fa0..75fe718baa9 100644 --- a/api/src/routes/protected/certificate.test.ts +++ b/api/src/routes/protected/certificate.test.ts @@ -292,6 +292,7 @@ describe('certificate routes', () => { } }, isCertMap: { + isA2EnglishCert: false, isRespWebDesignCert: true, isRespWebDesignCertV9: false, isJavascriptCertV9: false, diff --git a/api/src/routes/protected/certificate.ts b/api/src/routes/protected/certificate.ts index 95b1dad59cd..ad1d8aab8ea 100644 --- a/api/src/routes/protected/certificate.ts +++ b/api/src/routes/protected/certificate.ts @@ -21,6 +21,7 @@ import { SHOW_UPCOMING_CHANGES } from '../../utils/env.js'; import { isKnownCertSlug } from '../helpers/certificate-utils.js'; const { + a2EnglishId, legacyFrontEndChallengeId, legacyBackEndChallengeId, legacyDataVisId, @@ -160,13 +161,15 @@ function createCertTypeIds(challenges: ReturnType) { challenges ), [certTypes.javascriptV9]: getCertById(javascriptV9Id, challenges), - [certTypes.respWebDesignV9]: getCertById(respWebDesignV9Id, challenges) + [certTypes.respWebDesignV9]: getCertById(respWebDesignV9Id, challenges), // upcoming + [certTypes.a2English]: getCertById(a2EnglishId, challenges) }; } interface CertI { + isA2EnglishCert?: boolean; isRespWebDesignCert?: boolean; isJsAlgoDataStructCert?: boolean; isJsAlgoDataStructCertV8?: boolean; @@ -192,6 +195,7 @@ interface CertI { function getUserIsCertMap(user: CertI) { const { + isA2EnglishCert = false, isRespWebDesignCert = false, isJsAlgoDataStructCert = false, isJsAlgoDataStructCertV8 = false, @@ -216,6 +220,7 @@ function getUserIsCertMap(user: CertI) { } = user; return { + isA2EnglishCert, isRespWebDesignCert, isJsAlgoDataStructCert, isJsAlgoDataStructCertV8, @@ -383,6 +388,7 @@ export const protectedCertificateRoutes: FastifyPluginCallbackTypebox = ( completedChallenges: true, is2018DataVisCert: true, is2018FullStackCert: true, + isA2EnglishCert: true, isApisMicroservicesCert: true, isBackEndCert: true, isDataVisCert: true, diff --git a/api/src/routes/protected/user.test.ts b/api/src/routes/protected/user.test.ts index 71d1e21ba46..196a038b8ff 100644 --- a/api/src/routes/protected/user.test.ts +++ b/api/src/routes/protected/user.test.ts @@ -274,6 +274,7 @@ const publicUserData = { githubProfile: testUserData.githubProfile, is2018DataVisCert: testUserData.is2018DataVisCert, is2018FullStackCert: testUserData.is2018FullStackCert, // TODO: should this be returned? The client doesn't use it at the moment. + isA2EnglishCert: testUserData.isA2EnglishCert, isApisMicroservicesCert: testUserData.isApisMicroservicesCert, isBackEndCert: testUserData.isBackEndCert, isCheater: testUserData.isCheater, @@ -326,6 +327,7 @@ const sessionUserData = { const baseProgressData = { currentChallengeId: '', + isA2EnglishCert: false, isRespWebDesignCert: false, is2018DataVisCert: false, isFrontEndLibsCert: false, @@ -998,6 +1000,7 @@ describe('userRoutes', () => { yearsTopContributor: [], is2018DataVisCert: false, is2018FullStackCert: false, + isA2EnglishCert: false, isApisMicroservicesCert: false, isBackEndCert: false, isCheater: false, diff --git a/api/src/routes/protected/user.ts b/api/src/routes/protected/user.ts index de2c6cfc4c6..530b1ff0034 100644 --- a/api/src/routes/protected/user.ts +++ b/api/src/routes/protected/user.ts @@ -667,6 +667,7 @@ export const userGetRoutes: FastifyPluginCallbackTypebox = ( id: true, is2018DataVisCert: true, is2018FullStackCert: true, + isA2EnglishCert: true, isApisMicroservicesCert: true, isBackEndCert: true, isCheater: true, diff --git a/api/src/routes/public/certificate.ts b/api/src/routes/public/certificate.ts index 51d5f74acc5..ebca823245c 100644 --- a/api/src/routes/public/certificate.ts +++ b/api/src/routes/public/certificate.ts @@ -60,6 +60,7 @@ export const unprotectedCertificateRoutes: FastifyPluginCallbackTypebox = ( select: { isBanned: true, isCheater: true, + isA2EnglishCert: true, isFrontEndCert: true, isBackEndCert: true, isFullStackCert: true, diff --git a/api/src/routes/public/user.test.ts b/api/src/routes/public/user.test.ts index 5182200e207..2b2674c7158 100644 --- a/api/src/routes/public/user.test.ts +++ b/api/src/routes/public/user.test.ts @@ -187,6 +187,7 @@ const publicUserData = { githubProfile: testUserData.githubProfile, is2018DataVisCert: testUserData.is2018DataVisCert, is2018FullStackCert: testUserData.is2018FullStackCert, // TODO: should this be returned? The client doesn't use it at the moment. + isA2EnglishCert: testUserData.isA2EnglishCert, isApisMicroservicesCert: testUserData.isApisMicroservicesCert, isBackEndCert: testUserData.isBackEndCert, isCheater: testUserData.isCheater, diff --git a/api/src/schemas/types.ts b/api/src/schemas/types.ts index 4f73088adc3..6cfb806e5fc 100644 --- a/api/src/schemas/types.ts +++ b/api/src/schemas/types.ts @@ -6,6 +6,7 @@ export const genericError = Type.Object({ }); export const isCertMap = Type.Object({ + isA2EnglishCert: Type.Boolean(), isRespWebDesignCert: Type.Boolean(), isRespWebDesignCertV9: Type.Boolean(), isJavascriptCertV9: Type.Boolean(), diff --git a/api/src/schemas/user/get-session-user.ts b/api/src/schemas/user/get-session-user.ts index dc665286633..227db236092 100644 --- a/api/src/schemas/user/get-session-user.ts +++ b/api/src/schemas/user/get-session-user.ts @@ -68,6 +68,7 @@ export const getSessionUser = { id: Type.String(), is2018DataVisCert: Type.Boolean(), is2018FullStackCert: Type.Boolean(), + isA2EnglishCert: Type.Boolean(), isApisMicroservicesCert: Type.Boolean(), isBackEndCert: Type.Boolean(), isCheater: Type.Boolean(), diff --git a/api/src/schemas/users/get-public-profile.ts b/api/src/schemas/users/get-public-profile.ts index e8f8856836a..7a8ad26d5fc 100644 --- a/api/src/schemas/users/get-public-profile.ts +++ b/api/src/schemas/users/get-public-profile.ts @@ -52,6 +52,7 @@ export const getPublicProfile = { githubProfile: Type.Optional(Type.String()), is2018DataVisCert: Type.Boolean(), is2018FullStackCert: Type.Boolean(), + isA2EnglishCert: Type.Boolean(), isApisMicroservicesCert: Type.Boolean(), isBackEndCert: Type.Boolean(), isCheater: Type.Boolean(), diff --git a/api/src/utils/create-user.ts b/api/src/utils/create-user.ts index 07b0124417d..9700ce557c6 100644 --- a/api/src/utils/create-user.ts +++ b/api/src/utils/create-user.ts @@ -16,6 +16,7 @@ export const createResetProperties = () => ({ currentChallengeId: '', is2018DataVisCert: false, is2018FullStackCert: false, + isA2EnglishCert: false, isApisMicroservicesCert: false, isBackEndCert: false, isCollegeAlgebraPyCertV8: false, diff --git a/client/config/cert-and-project-map.ts b/client/config/cert-and-project-map.ts index 8ef9f35548a..85a5065937e 100644 --- a/client/config/cert-and-project-map.ts +++ b/client/config/cert-and-project-map.ts @@ -903,7 +903,7 @@ const allStandardCerts = [ certSlug: Certification.A2English, projects: [ { - id: '651dd3e06ffb500e3f2ce478', + id: '6721db5d9f0c116e6a0fe25a', title: 'A2 English for Developers Certification Exam', link: `${a2EnglishBase}/a2-english-for-developers-certification-exam/a2-english-for-developers-certification-exam`, certSlug: Certification.A2English diff --git a/client/src/client-only-routes/show-settings.tsx b/client/src/client-only-routes/show-settings.tsx index 7fec556bced..1d498b3c6ad 100644 --- a/client/src/client-only-routes/show-settings.tsx +++ b/client/src/client-only-routes/show-settings.tsx @@ -122,6 +122,7 @@ export function ShowSettings(props: ShowSettingsProps): JSX.Element { completedChallenges, email, is2018DataVisCert, + isA2EnglishCert, isApisMicroservicesCert, isJavascriptCertV9, isJsAlgoDataStructCert, @@ -190,6 +191,7 @@ export function ShowSettings(props: ShowSettingsProps): JSX.Element { completedChallenges={completedChallenges} createFlashMessage={createFlashMessage} is2018DataVisCert={is2018DataVisCert} + isA2EnglishCert={isA2EnglishCert} isApisMicroservicesCert={isApisMicroservicesCert} isBackEndCert={isBackEndCert} isDataAnalysisPyCertV7={isDataAnalysisPyCertV7} diff --git a/client/src/components/profile/components/utils/certification.ts b/client/src/components/profile/components/utils/certification.ts index b371d549699..65703a29c8d 100644 --- a/client/src/components/profile/components/utils/certification.ts +++ b/client/src/components/profile/components/utils/certification.ts @@ -3,6 +3,7 @@ import { User } from '../../../../redux/prop-types'; export const getCertifications = (user: User) => { const { + isA2EnglishCert, isRespWebDesignCert, isRespWebDesignCertV9, is2018DataVisCert, @@ -28,6 +29,7 @@ export const getCertifications = (user: User) => { return { hasModernCert: + isA2EnglishCert || isRespWebDesignCert || isRespWebDesignCertV9 || is2018DataVisCert || @@ -52,6 +54,11 @@ export const getCertifications = (user: User) => { isInfosecQaCert, isFullStackCert, currentCerts: [ + { + show: isA2EnglishCert, + title: 'A2 English for Developers Certification', + certSlug: Certification.A2English + }, { show: isRespWebDesignCert, title: 'Responsive Web Design Certification', diff --git a/client/src/components/profile/profile.test.tsx b/client/src/components/profile/profile.test.tsx index cbdd4da2fee..2db2e01beeb 100644 --- a/client/src/components/profile/profile.test.tsx +++ b/client/src/components/profile/profile.test.tsx @@ -54,6 +54,7 @@ const userProps = { yearsTopContributor: [], isDonating: false, is2018DataVisCert: true, + isA2EnglishCert: true, isApisMicroservicesCert: true, isBackEndCert: true, isDataVisCert: true, diff --git a/client/src/components/settings/certification.test.tsx b/client/src/components/settings/certification.test.tsx index b655f8eafd3..6ad1fcee1d9 100644 --- a/client/src/components/settings/certification.test.tsx +++ b/client/src/components/settings/certification.test.tsx @@ -262,6 +262,7 @@ const defaultTestProps = { ], createFlashMessage: createFlashMessage, is2018DataVisCert: false, + isA2EnglishCert: false, isApisMicroservicesCert: false, isBackEndCert: false, isDataVisCert: true, diff --git a/client/src/components/settings/certification.tsx b/client/src/components/settings/certification.tsx index 12c91d9e7c7..5a498f0188f 100644 --- a/client/src/components/settings/certification.tsx +++ b/client/src/components/settings/certification.tsx @@ -47,6 +47,7 @@ const mapDispatchToProps = { const createCertifiedMap = ({ is2018DataVisCert, + isA2EnglishCert, isApisMicroservicesCert, isJavascriptCertV9, isJsAlgoDataStructCert, @@ -97,7 +98,7 @@ const createCertifiedMap = ({ [Certification.PythonV9]: false, [Certification.RelationalDbV9]: false, [Certification.BackEndDevApisV9]: false, - [Certification.A2English]: false, + [Certification.A2English]: isA2EnglishCert, [Certification.B1English]: false, [Certification.A2Spanish]: false, [Certification.A2Chinese]: false, diff --git a/client/src/redux/prop-types.ts b/client/src/redux/prop-types.ts index 217710814b5..69d12c72a4b 100644 --- a/client/src/redux/prop-types.ts +++ b/client/src/redux/prop-types.ts @@ -432,6 +432,7 @@ export type ProfileUI = { export type ClaimedCertifications = { is2018DataVisCert: boolean; + isA2EnglishCert: boolean; isApisMicroservicesCert: boolean; isBackEndCert: boolean; isDataVisCert: boolean; diff --git a/client/utils/index.ts b/client/utils/index.ts index 8a5870ad4a3..de373c2bd3e 100644 --- a/client/utils/index.ts +++ b/client/utils/index.ts @@ -22,7 +22,8 @@ const idToPath = new Map( '68e008aa5f80c6099d47b3a2': Certification.FrontEndDevLibsV9, '68e6bd5020effa1586e79855': Certification.PythonV9, '68e6bd5120effa1586e79856': Certification.RelationalDbV9, - '68e6bd5120effa1586e79857': Certification.BackEndDevApisV9 + '68e6bd5120effa1586e79857': Certification.BackEndDevApisV9, + '651dd7e01d697d0aab7833b7': Certification.A2English }) ); diff --git a/curriculum/challenges/english/certifications/a2-english-for-developers.yml b/curriculum/challenges/english/certifications/a2-english-for-developers.yml index 8d6cc52f23c..fc94429f389 100644 --- a/curriculum/challenges/english/certifications/a2-english-for-developers.yml +++ b/curriculum/challenges/english/certifications/a2-english-for-developers.yml @@ -1,4 +1,3 @@ ---- id: 651dd7e01d697d0aab7833b7 title: A2 English for Developers Certification certification: a2-english-for-developers diff --git a/shared/config/certification-settings.ts b/shared/config/certification-settings.ts index dc0105aa637..b2efc7a151a 100644 --- a/shared/config/certification-settings.ts +++ b/shared/config/certification-settings.ts @@ -119,7 +119,8 @@ export const certTypes = { collegeAlgebraPyV8: 'isCollegeAlgebraPyCertV8', foundationalCSharpV8: 'isFoundationalCSharpCertV8', jsAlgoDataStructV8: 'isJsAlgoDataStructCertV8', - javascriptV9: 'isJavascriptCertV9' + javascriptV9: 'isJavascriptCertV9', + a2English: 'isA2EnglishCert' } as const; export const certIds = { @@ -147,7 +148,8 @@ export const certIds = { frontEndLibsV9Id: '68e008aa5f80c6099d47b3a2', pythonV9Id: '68e6bd5020effa1586e79855', relationalDbV9Id: '68e6bd5120effa1586e79856', - backEndDevApisV9Id: '68e6bd5120effa1586e79857' + backEndDevApisV9Id: '68e6bd5120effa1586e79857', + a2EnglishId: '651dd7e01d697d0aab7833b7' }; export const completionHours = { @@ -171,7 +173,8 @@ export const completionHours = { [certTypes.collegeAlgebraPyV8]: 300, [certTypes.foundationalCSharpV8]: 300, [certTypes.jsAlgoDataStructV8]: 300, - [certTypes.javascriptV9]: 300 + [certTypes.javascriptV9]: 300, + [certTypes.a2English]: 300 }; export const certSlugTypeMap = { @@ -200,7 +203,8 @@ export const certSlugTypeMap = { // upcoming [Certification.RespWebDesignV9]: certTypes.respWebDesignV9, - [Certification.JsV9]: certTypes.javascriptV9 + [Certification.JsV9]: certTypes.javascriptV9, + [Certification.A2English]: certTypes.a2English }; export const superBlockCertTypeMap = { @@ -229,9 +233,10 @@ export const superBlockCertTypeMap = { // post-modern // TODO: use enum - [SuperBlocks.RespWebDesignNew]: certTypes.respWebDesign + [SuperBlocks.RespWebDesignNew]: certTypes.respWebDesign, // upcoming + [SuperBlocks.A2English]: certTypes.a2English }; export const certTypeIdMap = { @@ -255,7 +260,8 @@ export const certTypeIdMap = { [certTypes.collegeAlgebraPyV8]: certIds.collegeAlgebraPyV8Id, [certTypes.foundationalCSharpV8]: certIds.foundationalCSharpV8Id, [certTypes.jsAlgoDataStructV8]: certIds.jsAlgoDataStructV8Id, - [certTypes.javascriptV9]: certIds.javascriptV9Id + [certTypes.javascriptV9]: certIds.javascriptV9Id, + [certTypes.a2English]: certIds.a2EnglishId }; export const certTypeTitleMap = { @@ -280,7 +286,8 @@ export const certTypeTitleMap = { [certTypes.collegeAlgebraPyV8]: 'College Algebra with Python', [certTypes.foundationalCSharpV8]: 'Foundational C# with Microsoft', [certTypes.jsAlgoDataStructV8]: 'JavaScript Algorithms and Data Structures', - [certTypes.javascriptV9]: 'JavaScript' + [certTypes.javascriptV9]: 'JavaScript', + [certTypes.a2English]: 'A2 English for Developers' }; export const superBlockToCertMap: { diff --git a/tools/scripts/seed/user-data.js b/tools/scripts/seed/user-data.js index 317351651db..4aee17693a2 100644 --- a/tools/scripts/seed/user-data.js +++ b/tools/scripts/seed/user-data.js @@ -220,6 +220,7 @@ module.exports.fullyCertifiedUser = { sendQuincyEmail: null, currentChallengeId: '', isHonest: true, + isA2EnglishCert: true, isFrontEndCert: true, isDataVisCert: true, isBackEndCert: true,