diff --git a/api-server/src/server/boot/certificate.js b/api-server/src/server/boot/certificate.js index ac93246c96a..c3046741f50 100644 --- a/api-server/src/server/boot/certificate.js +++ b/api-server/src/server/boot/certificate.js @@ -41,7 +41,7 @@ const { machineLearningPyV7Id, relationalDatabaseV8Id, collegeAlgebraPyV8Id, - foundationalCSharpId + foundationalCSharpV8Id } = certIds; const log = debug('fcc:certification'); @@ -134,8 +134,8 @@ function createCertTypeIds(allChallenges) { collegeAlgebraPyV8Id, allChallenges ), - [certTypes.foundationalCSharp]: getCertById( - foundationalCSharpId, + [certTypes.foundationalCSharpV8]: getCertById( + foundationalCSharpV8Id, allChallenges ) }; @@ -174,7 +174,8 @@ function sendCertifiedEmail( isDataAnalysisPyCertV7, isMachineLearningPyCertV7, isRelationalDatabaseCertV8, - isCollegeAlgebraPyCertV8 + isCollegeAlgebraPyCertV8, + isFoundationalCSharpCertV8 }, send$ ) { @@ -191,7 +192,8 @@ function sendCertifiedEmail( !isDataAnalysisPyCertV7 || !isMachineLearningPyCertV7 || !isRelationalDatabaseCertV8 || - !isCollegeAlgebraPyCertV8 + !isCollegeAlgebraPyCertV8 || + !isFoundationalCSharpCertV8 ) { return Observable.just(false); } diff --git a/api-server/src/server/boot/user.js b/api-server/src/server/boot/user.js index bf5cd2dabb5..73fea8d3475 100644 --- a/api-server/src/server/boot/user.js +++ b/api-server/src/server/boot/user.js @@ -366,6 +366,7 @@ function postResetProgress(req, res, next) { isMachineLearningPyCertV7: false, isRelationalDatabaseCertV8: false, isCollegeAlgebraPyCertV8: false, + isFoundationalCSharpCertV8: false, completedChallenges: [], completedExams: [], savedChallenges: [], diff --git a/api-server/src/server/utils/certTypes.json b/api-server/src/server/utils/certTypes.json index f44b084a77a..27af67a6579 100644 --- a/api-server/src/server/utils/certTypes.json +++ b/api-server/src/server/utils/certTypes.json @@ -15,5 +15,6 @@ "machineLearningPyV7": "isMachineLearningPyCertV7", "fullStack": "isFullStackCert", "relationalDatabaseV8": "isRelationalDatabaseV8", - "collegeAlgebraPyV8": "isCollegeAlgebraPyCertV8" + "collegeAlgebraPyV8": "isCollegeAlgebraPyCertV8", + "foundationalCSharpV8": "isFoundationalCSharpCertV8" } diff --git a/client/config/cert-and-project-map.ts b/client/config/cert-and-project-map.ts index a5d4869ee0b..7c9b7593e45 100644 --- a/client/config/cert-and-project-map.ts +++ b/client/config/cert-and-project-map.ts @@ -747,7 +747,6 @@ const allStandardCerts = [ } ] }, - // Upcoming Certifications { id: '647e3159823e0ef219c7359b', title: 'Foundational C# with Microsoft', @@ -761,6 +760,7 @@ const allStandardCerts = [ } ] }, + // Upcoming Certifications { id: '64514fda6c245de4d11eb7bb', title: 'Example Certification', diff --git a/client/i18n/locales/english/intro.json b/client/i18n/locales/english/intro.json index 6b2472c958e..f0ee1fae883 100644 --- a/client/i18n/locales/english/intro.json +++ b/client/i18n/locales/english/intro.json @@ -1017,7 +1017,7 @@ } }, "foundational-c-sharp-with-microsoft": { - "title": "Foundational C# with Microsoft", + "title": "(New) Foundational C# with Microsoft", "intro": [ "This course offers a comprehensive introduction to C# programming, covering its core concepts, syntax, and practical application in software development.", "Through hands-on exercises and projects, you will learn the fundamentals of C#, including variables, data types, control structures, and object-oriented programming principles.", diff --git a/client/i18n/locales/english/translations.json b/client/i18n/locales/english/translations.json index c9d8688ddfe..ef9cfd61e51 100644 --- a/client/i18n/locales/english/translations.json +++ b/client/i18n/locales/english/translations.json @@ -116,6 +116,9 @@ } }, "certification-heading": "Earn free verified certifications in:", + "core-certs-heading": "Earn free verified certifications with freeCodeCamp's core curriculum:", + "professional-certs-heading": "Earn free professional certifications:", + "interview-prep-heading": "Prepare for the developer interview job search:", "faq": "Frequently asked questions:", "faqs": [ { diff --git a/client/src/client-only-routes/show-certification.tsx b/client/src/client-only-routes/show-certification.tsx index b37dc5bac27..b7e3c885854 100644 --- a/client/src/client-only-routes/show-certification.tsx +++ b/client/src/client-only-routes/show-certification.tsx @@ -303,7 +303,7 @@ const ShowCertification = (props: ShowCertificationProps): JSX.Element => { ); const isMicrosoftCert = - certTitle === certTypeTitleMap[certTypes.foundationalCSharp]; + certTitle === certTypeTitleMap[certTypes.foundationalCSharpV8]; return ( diff --git a/client/src/client-only-routes/show-settings.tsx b/client/src/client-only-routes/show-settings.tsx index 6fce71ded4c..f0e4e418d43 100644 --- a/client/src/client-only-routes/show-settings.tsx +++ b/client/src/client-only-routes/show-settings.tsx @@ -213,6 +213,7 @@ export function ShowSettings(props: ShowSettingsProps): JSX.Element { isDataAnalysisPyCertV7={isDataAnalysisPyCertV7} isDataVisCert={isDataVisCert} isCollegeAlgebraPyCertV8={isCollegeAlgebraPyCertV8} + isFoundationalCSharpCertV8={isFoundationalCSharpCertV8} isFrontEndCert={isFrontEndCert} isFrontEndLibsCert={isFrontEndLibsCert} isFullStackCert={isFullStackCert} @@ -225,7 +226,6 @@ export function ShowSettings(props: ShowSettingsProps): JSX.Element { isRelationalDatabaseCertV8={isRelationalDatabaseCertV8} isRespWebDesignCert={isRespWebDesignCert} isSciCompPyCertV7={isSciCompPyCertV7} - isFoundationalCSharpCertV8={isFoundationalCSharpCertV8} username={username} verifyCert={verifyCert} /> diff --git a/client/src/components/Map/index.tsx b/client/src/components/Map/index.tsx index 9ca1ac33d7c..d5541434768 100644 --- a/client/src/components/Map/index.tsx +++ b/client/src/components/Map/index.tsx @@ -1,10 +1,12 @@ import i18next from 'i18next'; import React from 'react'; +import { useTranslation } from 'react-i18next'; import { + SuperBlockStages, SuperBlocks, - createFlatSuperBlockMap, - getFirstNotAuditedSuperBlock + getFirstNotAuditedSuperBlock, + superBlockOrder } from '../../../../config/superblocks'; import { generateIconComponent } from '../../assets/icons'; import LinkButton from '../../assets/icons/link-button'; @@ -29,16 +31,18 @@ const linkSpacingStyle = { gap: '15px' }; -const flatSuperBlockMap = createFlatSuperBlockMap({ - showNewCurriculum, - showUpcomingChanges -}); const firstNotAuditedSuperBlock = getFirstNotAuditedSuperBlock({ language: curriculumLocale, showNewCurriculum, showUpcomingChanges }); +const coreCurriculum = [ + ...superBlockOrder[SuperBlockStages.FrontEnd], + ...superBlockOrder[SuperBlockStages.Backend], + ...superBlockOrder[SuperBlockStages.Python] +]; + function MapLi({ superBlock, landing = false @@ -81,10 +85,33 @@ function MapLi({ } function Map({ forLanding = false }: MapProps): React.ReactElement { + const { t } = useTranslation(); + return (
+

+ {t('landing.core-certs-heading')} +

+ +

+ {t('landing.professional-certs-heading')} +

+
    + {superBlockOrder[SuperBlockStages.Professional].map((superBlock, i) => ( + + ))} +
+ +

+ {t('landing.interview-prep-heading')} +

+
    + {superBlockOrder[SuperBlockStages.Extra].map((superBlock, i) => ( ))}
diff --git a/client/src/components/landing/components/certifications.tsx b/client/src/components/landing/components/certifications.tsx index 6616c7207fc..72f2288ee18 100644 --- a/client/src/components/landing/components/certifications.tsx +++ b/client/src/components/landing/components/certifications.tsx @@ -1,13 +1,10 @@ import { Col } from '@freecodecamp/react-bootstrap'; import React from 'react'; -import { useTranslation } from 'react-i18next'; import Map from '../../Map/index'; import { Spacer } from '../../helpers'; import BigCallToAction from './big-call-to-action'; const Certifications = (): JSX.Element => { - const { t } = useTranslation(); - return ( { smOffset={1} xs={12} > -

{t('landing.certification-heading')}

diff --git a/client/src/components/profile/profile.test.tsx b/client/src/components/profile/profile.test.tsx index 05befd5ce46..ce08042aef7 100644 --- a/client/src/components/profile/profile.test.tsx +++ b/client/src/components/profile/profile.test.tsx @@ -66,7 +66,8 @@ const userProps = { isDataAnalysisPyCertV7: true, isMachineLearningPyCertV7: true, isRelationalDatabaseCertV8: true, - isCollegeAlgebraPyCertV8: true + isCollegeAlgebraPyCertV8: true, + isFoundationalCSharpVertV8: true }, // eslint-disable-next-line @typescript-eslint/no-empty-function navigate: () => {} diff --git a/client/src/components/settings/certification.test.tsx b/client/src/components/settings/certification.test.tsx index d19a67eecee..ba8699e9699 100644 --- a/client/src/components/settings/certification.test.tsx +++ b/client/src/components/settings/certification.test.tsx @@ -276,6 +276,7 @@ const defaultTestProps = { isMachineLearningPyCertV7: false, isRelationalDatabaseCertV8: false, isCollegeAlgebraPyCertV8: false, + isFoundationalCSharpCertV8: false, username: 'developmentuser', verifyCert: verifyCert, isEmailVerified: false diff --git a/client/src/components/settings/certification.tsx b/client/src/components/settings/certification.tsx index 5abc24064b4..49ee33097d0 100644 --- a/client/src/components/settings/certification.tsx +++ b/client/src/components/settings/certification.tsx @@ -122,11 +122,11 @@ const isCertMapSelector = createSelector( 'Machine Learning with Python': isMachineLearningPyCertV7, 'Relational Database': isRelationalDatabaseCertV8, 'College Algebra with Python': isCollegeAlgebraPyCertV8, + 'Foundational C# with Microsoft': isFoundationalCSharpCertV8, 'Legacy Front End': isFrontEndCert, 'Legacy Data Visualization': isDataVisCert, 'Legacy Back End': isBackEndCert, 'Legacy Information Security and Quality Assurance': isInfosecQaCert, - 'Foundational C# with Microsoft': isFoundationalCSharpCertV8, // TODO: remove Example Certification? Also, include Upcoming Python // Certification. 'Example Certification': false, diff --git a/client/src/pages/certification.css b/client/src/pages/certification.css index 262888f6b6c..c826f2eb4e9 100644 --- a/client/src/pages/certification.css +++ b/client/src/pages/certification.css @@ -125,14 +125,15 @@ .certification-namespace .dual-logo svg { max-width: 70%; + height: auto; } .certification-namespace .fcc-logo svg { - max-width: 350px; + width: 350px; } .certification-namespace .ms-logo svg { - max-width: 300px; + width: 300px; } .certification-namespace .information { diff --git a/client/src/redux/index.js b/client/src/redux/index.js index 5eb2ea6f2cd..109efa81303 100644 --- a/client/src/redux/index.js +++ b/client/src/redux/index.js @@ -317,26 +317,38 @@ export const reducer = handleActions( submittedchallenges = submittedChallenge.challArray; } const { appUsername } = state; - return { - ...state, - completionCount: state.completionCount + 1, - user: { - ...state.user, - [appUsername]: { - ...state.user[appUsername], - completedChallenges: uniqBy( - [ - ...submittedchallenges, - ...state.user[appUsername].completedChallenges - ], - 'id' - ), - savedChallenges: - savedChallenges ?? savedChallengesSelector(state[MainApp]), - examResults + + return examResults && !examResults.passed + ? { + ...state, + user: { + ...state.user, + [appUsername]: { + ...state.user[appUsername], + examResults + } + } } - } - }; + : { + ...state, + completionCount: state.completionCount + 1, + user: { + ...state.user, + [appUsername]: { + ...state.user[appUsername], + completedChallenges: uniqBy( + [ + ...submittedchallenges, + ...state.user[appUsername].completedChallenges + ], + 'id' + ), + savedChallenges: + savedChallenges ?? savedChallengesSelector(state[MainApp]), + examResults + } + } + }; }, [actionTypes.setMsUsername]: (state, { payload }) => { const { appUsername } = state; diff --git a/client/src/redux/prop-types.ts b/client/src/redux/prop-types.ts index e6f55f8e5f5..bea27f5674f 100644 --- a/client/src/redux/prop-types.ts +++ b/client/src/redux/prop-types.ts @@ -253,6 +253,7 @@ export type ClaimedCertifications = { isDataVisCert: boolean; isEmailVerified: boolean; isCollegeAlgebraPyCertV8: boolean; + isFoundationalCSharpCertV8: boolean; isFrontEndCert: boolean; isFrontEndLibsCert: boolean; isFullStackCert: boolean; @@ -265,7 +266,6 @@ export type ClaimedCertifications = { isSciCompPyCertV7: boolean; isDataAnalysisPyCertV7: boolean; isMachineLearningPyCertV7: boolean; - isFoundationalCSharpCertV8: boolean; }; type SavedChallenges = SavedChallenge[]; diff --git a/client/src/redux/selectors.js b/client/src/redux/selectors.js index 3e1ad582c8b..28e5152cd6b 100644 --- a/client/src/redux/selectors.js +++ b/client/src/redux/selectors.js @@ -124,7 +124,8 @@ export const certificatesByNameSelector = username => state => { isDataAnalysisPyCertV7, isMachineLearningPyCertV7, isRelationalDatabaseCertV8, - isCollegeAlgebraPyCertV8 + isCollegeAlgebraPyCertV8, + isFoundationalCSharpCertV8 } = userByNameSelector(username)(state); return { hasModernCert: @@ -140,7 +141,8 @@ export const certificatesByNameSelector = username => state => { isDataAnalysisPyCertV7 || isMachineLearningPyCertV7 || isRelationalDatabaseCertV8 || - isCollegeAlgebraPyCertV8, + isCollegeAlgebraPyCertV8 || + isFoundationalCSharpCertV8, hasLegacyCert: isFrontEndCert || isBackEndCert || isDataVisCert || isInfosecQaCert, isFullStackCert, @@ -204,6 +206,11 @@ export const certificatesByNameSelector = username => state => { show: isCollegeAlgebraPyCertV8, title: 'College Algebra with Python Certification', certSlug: Certification.CollegeAlgebraPy + }, + { + show: isFoundationalCSharpCertV8, + title: 'Foundational C# with Microsoft Certification', + certSlug: Certification.FoundationalCSharp } ], legacyCerts: [ diff --git a/config/certification-settings.ts b/config/certification-settings.ts index 68548048742..5ba1526a022 100644 --- a/config/certification-settings.ts +++ b/config/certification-settings.ts @@ -24,8 +24,8 @@ export enum Certification { InfoSec = 'information-security-v7', MachineLearningPy = 'machine-learning-with-python-v7', CollegeAlgebraPy = 'college-algebra-with-python-v8', - // Upcoming certifications FoundationalCSharp = 'foundational-c-sharp-with-microsoft', + // Upcoming certifications UpcomingPython = 'upcoming-python-v8', // Legacy certifications LegacyFrontEnd = 'legacy-front-end', @@ -49,7 +49,8 @@ export const currentCertifications = [ Certification.DataAnalysisPy, Certification.InfoSec, Certification.MachineLearningPy, - Certification.CollegeAlgebraPy + Certification.CollegeAlgebraPy, + Certification.FoundationalCSharp ] as const; // "Legacy" certifications are another class of standard certifications. They're @@ -63,10 +64,7 @@ export const legacyCertifications = [ // "Upcoming" certifications are standard certifications that are not live unless // showUpcomingChanges is true. -export const upcomingCertifications = [ - Certification.UpcomingPython, - Certification.FoundationalCSharp -] as const; +export const upcomingCertifications = [Certification.UpcomingPython] as const; export const certTypes = { frontEnd: 'isFrontEndCert', @@ -86,7 +84,7 @@ export const certTypes = { fullStack: 'isFullStackCert', relationalDatabaseV8: 'isRelationalDatabaseCertV8', collegeAlgebraPyV8: 'isCollegeAlgebraPyCertV8', - foundationalCSharp: 'isFoundationalCSharpCertV8' + foundationalCSharpV8: 'isFoundationalCSharpCertV8' } as const; export const certIds = { @@ -107,7 +105,7 @@ export const certIds = { machineLearningPyV7Id: '5e46fc95ac417301a38fb935', relationalDatabaseV8Id: '606243f50267e718b1e755f4', collegeAlgebraPyV8Id: '61531b20cc9dfa2741a5b800', - foundationalCSharpId: '647f7da207d29547b3bee1ba' + foundationalCSharpV8Id: '647f7da207d29547b3bee1ba' }; export const completionHours = { @@ -128,7 +126,7 @@ export const completionHours = { [certTypes.machineLearningPyV7]: 300, [certTypes.relationalDatabaseV8]: 300, [certTypes.collegeAlgebraPyV8]: 300, - [certTypes.foundationalCSharp]: 300 + [certTypes.foundationalCSharpV8]: 300 }; export const certSlugTypeMap = { @@ -152,7 +150,7 @@ export const certSlugTypeMap = { [Certification.MachineLearningPy]: certTypes.machineLearningPyV7, [Certification.RelationalDb]: certTypes.relationalDatabaseV8, [Certification.CollegeAlgebraPy]: certTypes.collegeAlgebraPyV8, - [Certification.FoundationalCSharp]: certTypes.foundationalCSharp + [Certification.FoundationalCSharp]: certTypes.foundationalCSharpV8 }; export const superBlockCertTypeMap = { @@ -176,7 +174,7 @@ export const superBlockCertTypeMap = { [SuperBlocks.MachineLearningPy]: certTypes.machineLearningPyV7, [SuperBlocks.RelationalDb]: certTypes.relationalDatabaseV8, [SuperBlocks.CollegeAlgebraPy]: certTypes.collegeAlgebraPyV8, - [SuperBlocks.FoundationalCSharp]: certTypes.foundationalCSharp, + [SuperBlocks.FoundationalCSharp]: certTypes.foundationalCSharpV8, // post-modern // TODO: use enum @@ -202,7 +200,7 @@ export const certTypeIdMap = { [certTypes.machineLearningPyV7]: certIds.machineLearningPyV7Id, [certTypes.relationalDatabaseV8]: certIds.relationalDatabaseV8Id, [certTypes.collegeAlgebraPyV8]: certIds.collegeAlgebraPyV8Id, - [certTypes.foundationalCSharp]: certIds.foundationalCSharpId + [certTypes.foundationalCSharpV8]: certIds.foundationalCSharpV8Id }; export const certTypeTitleMap = { @@ -223,7 +221,7 @@ export const certTypeTitleMap = { [certTypes.machineLearningPyV7]: 'Machine Learning with Python', [certTypes.relationalDatabaseV8]: 'Relational Database', [certTypes.collegeAlgebraPyV8]: 'College Algebra with Python', - [certTypes.foundationalCSharp]: 'Foundational C# with Microsoft' + [certTypes.foundationalCSharpV8]: 'Foundational C# with Microsoft' }; export const oldDataVizId = '561add10cb82ac38a17513b3'; diff --git a/config/superblocks.ts b/config/superblocks.ts index a4538609aa6..b5fd34b1f5f 100644 --- a/config/superblocks.ts +++ b/config/superblocks.ts @@ -35,6 +35,7 @@ export enum SuperBlockStages { FrontEnd, Backend, Python, + Professional, Extra, Legacy, New, @@ -66,6 +67,7 @@ export const superBlockOrder: SuperBlockOrder = { SuperBlocks.MachineLearningPy, SuperBlocks.CollegeAlgebraPy ], + [SuperBlockStages.Professional]: [SuperBlocks.FoundationalCSharp], [SuperBlockStages.Extra]: [ SuperBlocks.CodingInterviewPrep, SuperBlocks.ProjectEuler @@ -75,7 +77,6 @@ export const superBlockOrder: SuperBlockOrder = { [SuperBlockStages.Upcoming]: [ SuperBlocks.JsAlgoDataStructNew, SuperBlocks.TheOdinProject, - SuperBlocks.FoundationalCSharp, SuperBlocks.ExampleCertification, SuperBlocks.UpcomingPython ] @@ -95,55 +96,55 @@ export const notAuditedSuperBlocks: NotAuditedSuperBlocks = { SuperBlocks.InfoSec, SuperBlocks.MachineLearningPy, SuperBlocks.CollegeAlgebraPy, + SuperBlocks.FoundationalCSharp, SuperBlocks.CodingInterviewPrep, SuperBlocks.ProjectEuler, SuperBlocks.JsAlgoDataStructNew, SuperBlocks.TheOdinProject, - SuperBlocks.FoundationalCSharp, SuperBlocks.UpcomingPython ], [Languages.Chinese]: [ SuperBlocks.CollegeAlgebraPy, + SuperBlocks.FoundationalCSharp, SuperBlocks.CodingInterviewPrep, SuperBlocks.ProjectEuler, SuperBlocks.JsAlgoDataStructNew, SuperBlocks.TheOdinProject, - SuperBlocks.FoundationalCSharp, SuperBlocks.UpcomingPython ], [Languages.ChineseTraditional]: [ SuperBlocks.CollegeAlgebraPy, + SuperBlocks.FoundationalCSharp, SuperBlocks.CodingInterviewPrep, SuperBlocks.ProjectEuler, SuperBlocks.JsAlgoDataStructNew, SuperBlocks.TheOdinProject, - SuperBlocks.FoundationalCSharp, SuperBlocks.UpcomingPython ], [Languages.Italian]: [ + SuperBlocks.FoundationalCSharp, SuperBlocks.JsAlgoDataStructNew, SuperBlocks.TheOdinProject, - SuperBlocks.FoundationalCSharp, SuperBlocks.UpcomingPython ], [Languages.Portuguese]: [ - SuperBlocks.JsAlgoDataStructNew, SuperBlocks.FoundationalCSharp, + SuperBlocks.JsAlgoDataStructNew, SuperBlocks.UpcomingPython ], [Languages.Ukrainian]: [ + SuperBlocks.FoundationalCSharp, SuperBlocks.CodingInterviewPrep, SuperBlocks.ProjectEuler, SuperBlocks.JsAlgoDataStructNew, - SuperBlocks.FoundationalCSharp, SuperBlocks.UpcomingPython ], [Languages.Japanese]: [ SuperBlocks.CollegeAlgebraPy, + SuperBlocks.FoundationalCSharp, SuperBlocks.ProjectEuler, SuperBlocks.JsAlgoDataStructNew, SuperBlocks.TheOdinProject, - SuperBlocks.FoundationalCSharp, SuperBlocks.UpcomingPython ], [Languages.German]: [ @@ -157,11 +158,11 @@ export const notAuditedSuperBlocks: NotAuditedSuperBlocks = { SuperBlocks.InfoSec, SuperBlocks.MachineLearningPy, SuperBlocks.CollegeAlgebraPy, + SuperBlocks.FoundationalCSharp, SuperBlocks.CodingInterviewPrep, SuperBlocks.ProjectEuler, SuperBlocks.JsAlgoDataStructNew, SuperBlocks.TheOdinProject, - SuperBlocks.FoundationalCSharp, SuperBlocks.UpcomingPython ], [Languages.Arabic]: [ @@ -174,11 +175,11 @@ export const notAuditedSuperBlocks: NotAuditedSuperBlocks = { SuperBlocks.InfoSec, SuperBlocks.MachineLearningPy, SuperBlocks.CollegeAlgebraPy, + SuperBlocks.FoundationalCSharp, SuperBlocks.CodingInterviewPrep, SuperBlocks.ProjectEuler, SuperBlocks.JsAlgoDataStructNew, SuperBlocks.TheOdinProject, - SuperBlocks.FoundationalCSharp, SuperBlocks.UpcomingPython ], [Languages.Swahili]: [ @@ -191,10 +192,10 @@ export const notAuditedSuperBlocks: NotAuditedSuperBlocks = { SuperBlocks.InfoSec, SuperBlocks.MachineLearningPy, SuperBlocks.CollegeAlgebraPy, + SuperBlocks.FoundationalCSharp, SuperBlocks.CodingInterviewPrep, SuperBlocks.ProjectEuler, SuperBlocks.TheOdinProject, - SuperBlocks.FoundationalCSharp, SuperBlocks.RespWebDesign, SuperBlocks.FrontEndDevLibs, SuperBlocks.JsAlgoDataStructNew, diff --git a/curriculum/challenges/_meta/add-logic-to-c-sharp-console-applications/meta.json b/curriculum/challenges/_meta/add-logic-to-c-sharp-console-applications/meta.json index 04fc841a74e..541848efa81 100644 --- a/curriculum/challenges/_meta/add-logic-to-c-sharp-console-applications/meta.json +++ b/curriculum/challenges/_meta/add-logic-to-c-sharp-console-applications/meta.json @@ -1,6 +1,6 @@ { "name": "Add Logic to C# Console Applications", - "isUpcomingChange": true, + "isUpcomingChange": false, "dashedName": "add-logic-to-c-sharp-console-applications", "helpCategory": "HTML-CSS", "order": 2, diff --git a/curriculum/challenges/_meta/create-and-run-simple-c-sharp-console-applications/meta.json b/curriculum/challenges/_meta/create-and-run-simple-c-sharp-console-applications/meta.json index 01fdd301226..8a4b03c65ef 100644 --- a/curriculum/challenges/_meta/create-and-run-simple-c-sharp-console-applications/meta.json +++ b/curriculum/challenges/_meta/create-and-run-simple-c-sharp-console-applications/meta.json @@ -1,6 +1,6 @@ { "name": "Create and Run Simple C# Console Applications", - "isUpcomingChange": true, + "isUpcomingChange": false, "dashedName": "create-and-run-simple-c-sharp-console-applications", "helpCategory": "HTML-CSS", "order": 1, diff --git a/curriculum/challenges/_meta/create-methods-in-c-sharp-console-applications/meta.json b/curriculum/challenges/_meta/create-methods-in-c-sharp-console-applications/meta.json index 9b5aec40f14..3c4ea737ffd 100644 --- a/curriculum/challenges/_meta/create-methods-in-c-sharp-console-applications/meta.json +++ b/curriculum/challenges/_meta/create-methods-in-c-sharp-console-applications/meta.json @@ -1,6 +1,6 @@ { "name": "Create Methods in C# Console Applications", - "isUpcomingChange": true, + "isUpcomingChange": false, "dashedName": "create-methods-in-c-sharp-console-applications", "helpCategory": "HTML-CSS", "order": 4, diff --git a/curriculum/challenges/_meta/debug-c-sharp-console-applications/meta.json b/curriculum/challenges/_meta/debug-c-sharp-console-applications/meta.json index cc96a996d9e..631090dc68a 100644 --- a/curriculum/challenges/_meta/debug-c-sharp-console-applications/meta.json +++ b/curriculum/challenges/_meta/debug-c-sharp-console-applications/meta.json @@ -1,6 +1,6 @@ { "name": "Debug C# Console Applications", - "isUpcomingChange": true, + "isUpcomingChange": false, "dashedName": "debug-c-sharp-console-applications", "helpCategory": "HTML-CSS", "order": 5, diff --git a/curriculum/challenges/_meta/foundational-c-sharp-with-microsoft-certification-exam/meta.json b/curriculum/challenges/_meta/foundational-c-sharp-with-microsoft-certification-exam/meta.json index 40b34a10674..a62c0181866 100644 --- a/curriculum/challenges/_meta/foundational-c-sharp-with-microsoft-certification-exam/meta.json +++ b/curriculum/challenges/_meta/foundational-c-sharp-with-microsoft-certification-exam/meta.json @@ -1,6 +1,6 @@ { "name": "Foundational C# with Microsoft Certification Exam", - "isUpcomingChange": true, + "isUpcomingChange": false, "dashedName": "foundational-c-sharp-with-microsoft-certification-exam", "helpCategory": "HTML-CSS", "order": 6, diff --git a/curriculum/challenges/_meta/work-with-variable-data-in-c-sharp-console-applications/meta.json b/curriculum/challenges/_meta/work-with-variable-data-in-c-sharp-console-applications/meta.json index 0dd86f38ac3..319525aca59 100644 --- a/curriculum/challenges/_meta/work-with-variable-data-in-c-sharp-console-applications/meta.json +++ b/curriculum/challenges/_meta/work-with-variable-data-in-c-sharp-console-applications/meta.json @@ -1,6 +1,6 @@ { "name": "Work with Variable Data in C# Console Applications", - "isUpcomingChange": true, + "isUpcomingChange": false, "dashedName": "work-with-variable-data-in-c-sharp-console-applications", "helpCategory": "HTML-CSS", "order": 3, diff --git a/curriculum/challenges/_meta/write-your-first-code-using-c-sharp/meta.json b/curriculum/challenges/_meta/write-your-first-code-using-c-sharp/meta.json index 4ea1cf3800f..d74e30157da 100644 --- a/curriculum/challenges/_meta/write-your-first-code-using-c-sharp/meta.json +++ b/curriculum/challenges/_meta/write-your-first-code-using-c-sharp/meta.json @@ -1,6 +1,6 @@ { "name": "Write Your First Code Using C#", - "isUpcomingChange": true, + "isUpcomingChange": false, "dashedName": "write-your-first-code-using-c-sharp", "helpCategory": "HTML-CSS", "order": 0, diff --git a/curriculum/utils.test.ts b/curriculum/utils.test.ts index 5f67e41ae2f..be9e0d913bd 100644 --- a/curriculum/utils.test.ts +++ b/curriculum/utils.test.ts @@ -22,12 +22,12 @@ const mockSuperBlocks = [ SuperBlocks.InfoSec, SuperBlocks.MachineLearningPy, SuperBlocks.CollegeAlgebraPy, + SuperBlocks.FoundationalCSharp, SuperBlocks.CodingInterviewPrep, SuperBlocks.ProjectEuler, SuperBlocks.RespWebDesign, SuperBlocks.JsAlgoDataStructNew, SuperBlocks.TheOdinProject, - SuperBlocks.FoundationalCSharp, SuperBlocks.ExampleCertification ]; @@ -44,12 +44,12 @@ const fullSuperOrder = { [SuperBlocks.InfoSec]: 9, [SuperBlocks.MachineLearningPy]: 10, [SuperBlocks.CollegeAlgebraPy]: 11, - [SuperBlocks.CodingInterviewPrep]: 12, - [SuperBlocks.ProjectEuler]: 13, - [SuperBlocks.RespWebDesign]: 14, - [SuperBlocks.JsAlgoDataStructNew]: 15, - [SuperBlocks.TheOdinProject]: 16, - [SuperBlocks.FoundationalCSharp]: 17, + [SuperBlocks.FoundationalCSharp]: 12, + [SuperBlocks.CodingInterviewPrep]: 13, + [SuperBlocks.ProjectEuler]: 14, + [SuperBlocks.RespWebDesign]: 15, + [SuperBlocks.JsAlgoDataStructNew]: 16, + [SuperBlocks.TheOdinProject]: 17, [SuperBlocks.ExampleCertification]: 18 }; @@ -93,11 +93,11 @@ describe('getSuperOrder', () => { process.env.SHOW_NEW_CURRICULUM !== 'true' && process.env.SHOW_UPCOMING_CHANGES !== 'true' ) { - expect.assertions(15); + expect.assertions(16); } else if (process.env.SHOW_NEW_CURRICULUM !== 'true') { - expect.assertions(15); + expect.assertions(16); } else if (process.env.SHOW_UPCOMING_CHANGES !== 'true') { - expect.assertions(15); + expect.assertions(16); } else { expect.assertions(19); } @@ -114,24 +114,23 @@ describe('getSuperOrder', () => { expect(getSuperOrder(SuperBlocks.InfoSec)).toBe(9); expect(getSuperOrder(SuperBlocks.MachineLearningPy)).toBe(10); expect(getSuperOrder(SuperBlocks.CollegeAlgebraPy)).toBe(11); - expect(getSuperOrder(SuperBlocks.CodingInterviewPrep)).toBe(12); - expect(getSuperOrder(SuperBlocks.ProjectEuler)).toBe(13); - expect(getSuperOrder(SuperBlocks.RespWebDesign)).toBe(14); + expect(getSuperOrder(SuperBlocks.FoundationalCSharp)).toBe(12); + expect(getSuperOrder(SuperBlocks.CodingInterviewPrep)).toBe(13); + expect(getSuperOrder(SuperBlocks.ProjectEuler)).toBe(14); + expect(getSuperOrder(SuperBlocks.RespWebDesign)).toBe(15); if ( process.env.SHOW_NEW_CURRICULUM === 'true' && process.env.SHOW_UPCOMING_CHANGES === 'true' ) { - expect(getSuperOrder(SuperBlocks.JsAlgoDataStructNew)).toBe(15); - expect(getSuperOrder(SuperBlocks.TheOdinProject)).toBe(16); - expect(getSuperOrder(SuperBlocks.FoundationalCSharp)).toBe(17); + expect(getSuperOrder(SuperBlocks.JsAlgoDataStructNew)).toBe(16); + expect(getSuperOrder(SuperBlocks.TheOdinProject)).toBe(17); expect(getSuperOrder(SuperBlocks.ExampleCertification)).toBe(18); } else if (process.env.SHOW_NEW_CURRICULUM === 'true') { return; } else if (process.env.SHOW_UPCOMING_CHANGES === 'true') { - expect(getSuperOrder(SuperBlocks.JsAlgoDataStructNew)).toBe(15); - expect(getSuperOrder(SuperBlocks.TheOdinProject)).toBe(16); - expect(getSuperOrder(SuperBlocks.FoundationalCSharp)).toBe(17); + expect(getSuperOrder(SuperBlocks.JsAlgoDataStructNew)).toBe(16); + expect(getSuperOrder(SuperBlocks.TheOdinProject)).toBe(17); expect(getSuperOrder(SuperBlocks.ExampleCertification)).toBe(18); } }); diff --git a/cypress/e2e/default/landing.ts b/cypress/e2e/default/landing.ts index 8c1d85afce3..57982fa3731 100644 --- a/cypress/e2e/default/landing.ts +++ b/cypress/e2e/default/landing.ts @@ -25,9 +25,9 @@ const superBlocks = [ 'Information Security', 'Machine Learning with Python', 'College Algebra with Python', + '(New) Foundational C# with Microsoft', 'Coding Interview Prep', - 'Project Euler', - 'Legacy Responsive Web Design' + 'Project Euler' ]; describe('Landing page', () => { diff --git a/cypress/e2e/default/learn/index.ts b/cypress/e2e/default/learn/index.ts index 46036deec47..3ce1ba4054f 100644 --- a/cypress/e2e/default/learn/index.ts +++ b/cypress/e2e/default/learn/index.ts @@ -19,9 +19,9 @@ const superBlockNames = [ 'Information Security Certification', 'Machine Learning with Python Certification', 'College Algebra with Python Certification', + '(New) Foundational C# with Microsoft Certification', 'Coding Interview Prep', - 'Project Euler', - 'Legacy Responsive Web Design Challenges' + 'Project Euler' ]; describe('Learn Landing page (not logged in)', () => { diff --git a/cypress/e2e/default/settings/certifications.ts b/cypress/e2e/default/settings/certifications.ts index 09baaf9388d..bad1eb0745d 100644 --- a/cypress/e2e/default/settings/certifications.ts +++ b/cypress/e2e/default/settings/certifications.ts @@ -10,7 +10,7 @@ describe('Settings certifications area', () => { it('Should render the default settings page', () => { cy.visit('/settings/'); cy.findAllByText('Claim Certification').should($btns => { - expect($btns).to.have.length(17); + expect($btns).to.have.length(18); }); cy.findByText('Show Certification').should('not.exist'); cy.contains(`I agree to freeCodeCamp's Academic Honesty Policy.`); diff --git a/cypress/e2e/default/user/certifications.ts b/cypress/e2e/default/user/certifications.ts index d6744b67636..740d1306864 100644 --- a/cypress/e2e/default/user/certifications.ts +++ b/cypress/e2e/default/user/certifications.ts @@ -14,7 +14,7 @@ describe('Public profile certifications', () => { // The following line is only required if you want to test it in development //cy.contains('Preview custom 404 page').click(); - cy.get('[data-cy=claimed-certification]').should('have.length', 17); + cy.get('[data-cy=claimed-certification]').should('have.length', 18); }); it('Should show claimed certifications if the username includes uppercase characters', () => { @@ -32,7 +32,7 @@ describe('Public profile certifications', () => { // The following line is only required if you want to test it in development //cy.contains('Preview custom 404 page').click(); - cy.get('[data-cy=claimed-certification]').should('have.length', 17); + cy.get('[data-cy=claimed-certification]').should('have.length', 18); }); }); diff --git a/docs/how-to-enable-new-languages.md b/docs/how-to-enable-new-languages.md index 0e52c0e7eac..09e83494c01 100644 --- a/docs/how-to-enable-new-languages.md +++ b/docs/how-to-enable-new-languages.md @@ -159,6 +159,7 @@ export const notAuditedSuperBlocks: NotAuditedSuperBlocks = { SuperBlocks.InfoSec, SuperBlocks.MachineLearningPy, SuperBlocks.CollegeAlgebraPy, + SuperBlocks.FoundationalCSharp, SuperBlocks.CodingInterviewPrep, SuperBlocks.ProjectEuler, SuperBlocks.JsAlgoDataStructNew, diff --git a/e2e/landing.spec.ts b/e2e/landing.spec.ts index 10b2b3cb3fa..91721fc9bf6 100644 --- a/e2e/landing.spec.ts +++ b/e2e/landing.spec.ts @@ -25,6 +25,7 @@ const superBlocks = [ 'Information Security', 'Machine Learning with Python', 'College Algebra with Python', + 'Foundational C# with Microsoft', 'Coding Interview Prep', 'Project Euler', 'Legacy Responsive Web Design' diff --git a/tools/challenge-editor/api/configs/super-block-list.ts b/tools/challenge-editor/api/configs/super-block-list.ts index 2c905820c73..63dbb595572 100644 --- a/tools/challenge-editor/api/configs/super-block-list.ts +++ b/tools/challenge-editor/api/configs/super-block-list.ts @@ -68,7 +68,7 @@ export const superBlockList = [ path: '18-project-euler' }, { - name: 'Foundational C# with Microsoft', + name: '(New) Foundational C# with Microsoft', path: '19-foundational-c-sharp-with-microsoft' }, { diff --git a/tools/scripts/build/build-external-curricula-data.test.ts b/tools/scripts/build/build-external-curricula-data.test.ts index 1d190c8cf9f..3b6d5f48cef 100644 --- a/tools/scripts/build/build-external-curricula-data.test.ts +++ b/tools/scripts/build/build-external-curricula-data.test.ts @@ -90,8 +90,8 @@ if (envData.clientLocale == 'english' && !envData.showUpcomingChanges) { const isUpcoming = [ '2022/javascript-algorithms-and-data-structures', 'college-algebra-with-python', - 'the-odin-project', 'foundational-c-sharp-with-microsoft', + 'the-odin-project', 'upcoming-python', 'example-certification' ];