mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2025-12-19 18:18:27 -05:00
refactor(config): superblocks and map (#50435)
This commit is contained in:
@@ -7,6 +7,6 @@ config/i18n.js
|
||||
config/misc.js
|
||||
config/certification-settings.js
|
||||
config/donation-settings.js
|
||||
config/superblock-order.js
|
||||
config/superblocks.js
|
||||
web/**
|
||||
docs/**/*.md
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -166,8 +166,8 @@ config/i18n.js
|
||||
config/misc.js
|
||||
config/certification-settings.js
|
||||
config/donation-settings.js
|
||||
config/superblock-order.js
|
||||
config/superblock-order.test.js
|
||||
config/superblocks.js
|
||||
config/superblocks.test.js
|
||||
|
||||
### Generated utils files ###
|
||||
utils/block-nameify.js
|
||||
|
||||
@@ -10,8 +10,8 @@ config/i18n.js
|
||||
config/misc.js
|
||||
config/certification-settings.js
|
||||
config/donation-settings.js
|
||||
config/superblock-order.js
|
||||
config/superblock-order.test.js
|
||||
config/superblocks.js
|
||||
config/superblocks.test.js
|
||||
utils/block-nameify.js
|
||||
utils/block-nameify.test.js
|
||||
utils/slugs.js
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs from 'fs';
|
||||
import { setup } from 'jest-json-schema-extended';
|
||||
import { availableLangs, LangNames, LangCodes } from '../../config/i18n';
|
||||
import { SuperBlocks } from '../../config/certification-settings';
|
||||
import { SuperBlocks } from '../../config/superblocks';
|
||||
import intro from './locales/english/intro.json';
|
||||
|
||||
setup();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { SuperBlocks } from '../../../../config/certification-settings';
|
||||
import { SuperBlocks } from '../../../../config/superblocks';
|
||||
import APIIcon from './api';
|
||||
import D3Icon from './d3';
|
||||
import DatabaseIcon from './database';
|
||||
|
||||
@@ -1,26 +1,24 @@
|
||||
import i18next from 'i18next';
|
||||
import React from 'react';
|
||||
|
||||
import { SuperBlocks } from '../../../../config/certification-settings';
|
||||
import {
|
||||
CurriculumMaps,
|
||||
getAuditedSuperBlocks,
|
||||
getNotAuditedSuperBlocks,
|
||||
superBlockOrder
|
||||
} from '../../../../config/superblock-order';
|
||||
import { Languages } from '../../../../config/i18n';
|
||||
import envData from '../../../../config/env.json';
|
||||
SuperBlocks,
|
||||
createFlatSuperBlockMap,
|
||||
getFirstNotAuditedSuperBlock
|
||||
} from '../../../../config/superblocks';
|
||||
import { generateIconComponent } from '../../assets/icons';
|
||||
import LinkButton from '../../assets/icons/link-button';
|
||||
import { Link, Spacer } from '../helpers';
|
||||
import { getSuperBlockTitleForMap } from '../../utils/superblock-map-titles';
|
||||
import {
|
||||
curriculumLocale,
|
||||
showUpcomingChanges,
|
||||
showNewCurriculum
|
||||
} from '../../../../config/env.json';
|
||||
|
||||
import './map.css';
|
||||
|
||||
const { curriculumLocale, showNewCurriculum, showUpcomingChanges } = envData;
|
||||
|
||||
interface MapProps {
|
||||
currentSuperBlock?: SuperBlocks | null;
|
||||
forLanding?: boolean;
|
||||
}
|
||||
|
||||
@@ -31,6 +29,16 @@ const linkSpacingStyle = {
|
||||
gap: '15px'
|
||||
};
|
||||
|
||||
const flatSuperBlockMap = createFlatSuperBlockMap({
|
||||
showNewCurriculum: showNewCurriculum.toString(),
|
||||
showUpcomingChanges: showUpcomingChanges.toString()
|
||||
});
|
||||
const firstNotAuditedSuperBlock = getFirstNotAuditedSuperBlock({
|
||||
language: curriculumLocale,
|
||||
showNewCurriculum: showNewCurriculum.toString(),
|
||||
showUpcomingChanges: showUpcomingChanges.toString()
|
||||
});
|
||||
|
||||
function MapLi({
|
||||
superBlock,
|
||||
landing = false
|
||||
@@ -39,62 +47,9 @@ function MapLi({
|
||||
landing: boolean;
|
||||
}) {
|
||||
return (
|
||||
<li>
|
||||
<Link className='btn link-btn btn-lg' to={`/learn/${superBlock}/`}>
|
||||
<div style={linkSpacingStyle}>
|
||||
{generateIconComponent(superBlock, 'map-icon')}
|
||||
{getSuperBlockTitleForMap(superBlock)}
|
||||
</div>
|
||||
{landing && <LinkButton />}
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
function renderLandingMap() {
|
||||
const landingSuperOrder =
|
||||
superBlockOrder[curriculumLocale as Languages][CurriculumMaps.Landing];
|
||||
|
||||
return (
|
||||
<ul data-test-label='certifications'>
|
||||
{landingSuperOrder.map((superBlock, i) => (
|
||||
<MapLi superBlock={superBlock} key={i} landing={true} />
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
function renderLearnMap(currentSuperBlock: MapProps['currentSuperBlock']) {
|
||||
const tempAuditedSuperBlocks = getAuditedSuperBlocks({
|
||||
language: curriculumLocale,
|
||||
showNewCurriculum: showNewCurriculum.toString(),
|
||||
showUpcomingChanges: showUpcomingChanges.toString()
|
||||
});
|
||||
const tempNotAuditedSuperBlocks = getNotAuditedSuperBlocks({
|
||||
language: curriculumLocale,
|
||||
showNewCurriculum: showNewCurriculum.toString(),
|
||||
showUpcomingChanges: showUpcomingChanges.toString()
|
||||
});
|
||||
|
||||
const auditedSuperBlocks = tempAuditedSuperBlocks.filter(
|
||||
superBlock => superBlock !== currentSuperBlock
|
||||
);
|
||||
|
||||
const notAuditedSuperBlocks = tempNotAuditedSuperBlocks.filter(
|
||||
superBlock => superBlock !== currentSuperBlock
|
||||
);
|
||||
|
||||
return (
|
||||
<ul data-test-label='learn-curriculum-map'>
|
||||
{/* audited superblocks */}
|
||||
{auditedSuperBlocks.map((superBlock, i) => (
|
||||
<MapLi key={i} superBlock={superBlock} landing={false} />
|
||||
))}
|
||||
|
||||
{/* has not audited superblocks */}
|
||||
{notAuditedSuperBlocks.length > 0 && (
|
||||
<>
|
||||
{firstNotAuditedSuperBlock === superBlock && (
|
||||
<>
|
||||
{' '}
|
||||
<hr />
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<p style={{ marginBottom: 0 }}>
|
||||
@@ -112,21 +67,27 @@ function renderLearnMap(currentSuperBlock: MapProps['currentSuperBlock']) {
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* not audited superblocks */}
|
||||
{notAuditedSuperBlocks.map((superBlock, i) => (
|
||||
<MapLi key={i} superBlock={superBlock} landing={false} />
|
||||
))}
|
||||
</ul>
|
||||
<li data-test-label='curriculum-map-button'>
|
||||
<Link className='btn link-btn btn-lg' to={`/learn/${superBlock}/`}>
|
||||
<div style={linkSpacingStyle}>
|
||||
{generateIconComponent(superBlock, 'map-icon')}
|
||||
{getSuperBlockTitleForMap(superBlock)}
|
||||
</div>
|
||||
{landing && <LinkButton />}
|
||||
</Link>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function Map({
|
||||
forLanding = false,
|
||||
currentSuperBlock = null
|
||||
}: MapProps): React.ReactElement {
|
||||
function Map({ forLanding = false }: MapProps): React.ReactElement {
|
||||
return (
|
||||
<div className='map-ui' data-test-label='learn-curriculum-map'>
|
||||
{forLanding ? renderLandingMap() : renderLearnMap(currentSuperBlock)}
|
||||
<div className='map-ui' data-test-label='curriculum-map'>
|
||||
<ul>
|
||||
{flatSuperBlockMap.map((superBlock, i) => (
|
||||
<MapLi key={i} superBlock={superBlock} landing={forLanding} />
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useStaticQuery, graphql } from 'gatsby';
|
||||
import React from 'react';
|
||||
import Helmet from 'react-helmet';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { SuperBlocks } from '../../../../config/certification-settings';
|
||||
import { SuperBlocks } from '../../../../config/superblocks';
|
||||
|
||||
interface SEOProps {
|
||||
title?: string;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { HandlerProps } from 'react-reflex';
|
||||
import { SuperBlocks } from '../../../config/certification-settings';
|
||||
import { SuperBlocks } from '../../../config/superblocks';
|
||||
import { Themes } from '../components/settings/theme';
|
||||
import { fullCertMap } from '../resources/cert-and-project-map';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { SuperBlocks } from '../../../config/certification-settings';
|
||||
import { SuperBlocks } from '../../../config/superblocks';
|
||||
import { ns as MainApp } from './action-types';
|
||||
|
||||
export const savedChallengesSelector = state =>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { SuperBlocks } from '../../../config/certification-settings';
|
||||
import { SuperBlocks } from '../../../config/superblocks';
|
||||
import config from '../../../config/env.json';
|
||||
|
||||
const { showUpcomingChanges } = config;
|
||||
|
||||
@@ -44,7 +44,7 @@ import {
|
||||
import ProjectToolPanel from '../projects/tool-panel';
|
||||
import SolutionForm from '../projects/solution-form';
|
||||
import { FlashMessages } from '../../../components/Flash/redux/flash-messages';
|
||||
import { SuperBlocks } from '../../../../../config/certification-settings';
|
||||
import { SuperBlocks } from '../../../../../config/superblocks';
|
||||
import { CodeAllyDown } from '../../../components/growth-book/codeally-down';
|
||||
|
||||
import './codeally.css';
|
||||
|
||||
@@ -6,7 +6,7 @@ import { connect } from 'react-redux';
|
||||
import ScrollableAnchor from 'react-scrollable-anchor';
|
||||
import { bindActionCreators, Dispatch } from 'redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { SuperBlocks } from '../../../../../config/certification-settings';
|
||||
import { SuperBlocks } from '../../../../../config/superblocks';
|
||||
import envData from '../../../../../config/env.json';
|
||||
import { isAuditedCert } from '../../../../../utils/is-audited';
|
||||
import Caret from '../../../assets/icons/caret';
|
||||
|
||||
@@ -6,9 +6,10 @@ import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import {
|
||||
certSlugTypeMap,
|
||||
superBlockCertTypeMap,
|
||||
SuperBlocks
|
||||
superBlockCertTypeMap
|
||||
} from '../../../../../config/certification-settings';
|
||||
import { SuperBlocks } from '../../../../../config/superblocks';
|
||||
|
||||
import { createFlashMessage } from '../../../components/Flash/redux';
|
||||
import { FlashMessages } from '../../../components/Flash/redux/flash-messages';
|
||||
import {
|
||||
|
||||
@@ -8,7 +8,7 @@ import type { Dispatch } from 'redux';
|
||||
import GreenNotCompleted from '../../../assets/icons/green-not-completed';
|
||||
import GreenPass from '../../../assets/icons/green-pass';
|
||||
import { executeGA } from '../../../redux/actions';
|
||||
import { SuperBlocks } from '../../../../../config/certification-settings';
|
||||
import { SuperBlocks } from '../../../../../config/superblocks';
|
||||
import { ChallengeWithCompletedNode } from '../../../redux/prop-types';
|
||||
import { isNewJsCert, isNewRespCert } from '../../../utils/is-a-cert';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Alert } from '@freecodecamp/react-bootstrap';
|
||||
import { SuperBlocks } from '../../../../../config/certification-settings';
|
||||
import { SuperBlocks } from '../../../../../config/superblocks';
|
||||
import { isOldRespCert, isRelationalDbCert } from '../../../utils/is-a-cert';
|
||||
import { Link } from '../../../components/helpers';
|
||||
import { CodeAllyDown } from '../../../components/growth-book/codeally-down';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { SuperBlocks } from '../../../../../config/certification-settings';
|
||||
import { SuperBlocks } from '../../../../../config/superblocks';
|
||||
import { generateIconComponent } from '../../../assets/icons';
|
||||
import { Spacer } from '../../../components/helpers';
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import { configureAnchors } from 'react-scrollable-anchor';
|
||||
import { bindActionCreators, Dispatch } from 'redux';
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
import { SuperBlocks } from '../../../../config/certification-settings';
|
||||
import { SuperBlocks } from '../../../../config/superblocks';
|
||||
import { getSuperBlockTitleForMap } from '../../utils/superblock-map-titles';
|
||||
import DonateModal from '../../components/Donation/donation-modal';
|
||||
import Login from '../../components/Header/components/login';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { SuperBlocks } from '../../../config/certification-settings';
|
||||
import { SuperBlocks } from '../../../config/superblocks';
|
||||
|
||||
export function isNewRespCert(superBlock: string): boolean {
|
||||
return superBlock === SuperBlocks.RespWebDesignNew;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import i18next from 'i18next';
|
||||
import { SuperBlocks } from '../../../config/certification-settings';
|
||||
import { SuperBlocks } from '../../../config/superblocks';
|
||||
|
||||
// these are keys from i18n translations.json files
|
||||
enum SuperBlockI18nKeys {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { SuperBlocks } from './superblocks';
|
||||
|
||||
export const certTypes = {
|
||||
frontEnd: 'isFrontEndCert',
|
||||
backEnd: 'isBackEndCert',
|
||||
@@ -18,27 +20,6 @@ export const certTypes = {
|
||||
collegeAlgebraPyV8: 'isCollegeAlgebraPyCertV8'
|
||||
} as const;
|
||||
|
||||
export enum SuperBlocks {
|
||||
RespWebDesignNew = '2022/responsive-web-design',
|
||||
RespWebDesign = 'responsive-web-design',
|
||||
JsAlgoDataStruct = 'javascript-algorithms-and-data-structures',
|
||||
JsAlgoDataStructNew = '2022/javascript-algorithms-and-data-structures',
|
||||
FrontEndDevLibs = 'front-end-development-libraries',
|
||||
DataVis = 'data-visualization',
|
||||
RelationalDb = 'relational-database',
|
||||
BackEndDevApis = 'back-end-development-and-apis',
|
||||
QualityAssurance = 'quality-assurance',
|
||||
SciCompPy = 'scientific-computing-with-python',
|
||||
DataAnalysisPy = 'data-analysis-with-python',
|
||||
InfoSec = 'information-security',
|
||||
MachineLearningPy = 'machine-learning-with-python',
|
||||
CodingInterviewPrep = 'coding-interview-prep',
|
||||
TheOdinProject = 'the-odin-project',
|
||||
ProjectEuler = 'project-euler',
|
||||
CollegeAlgebraPy = 'college-algebra-with-python',
|
||||
ExampleCertification = 'example-certification'
|
||||
}
|
||||
|
||||
export const certIds = {
|
||||
legacyFrontEndChallengeId: '561add10cb82ac38a17513be',
|
||||
legacyBackEndChallengeId: '660add10cb82ac38a17513be',
|
||||
|
||||
@@ -101,12 +101,13 @@ export const LangCodes = {
|
||||
/**
|
||||
* This array contains languages that should NOT appear in the language selector.
|
||||
*/
|
||||
export const hiddenLangs = ['arabic'];
|
||||
// German is temporarily disabled until the new RWD is fully translated
|
||||
export const hiddenLangs = [Languages.Arabic, Languages.German];
|
||||
|
||||
/**
|
||||
* This array contains languages that use the RTL layouts.
|
||||
*/
|
||||
export const rtlLangs = ['arabic'];
|
||||
export const rtlLangs = [Languages.Arabic];
|
||||
|
||||
// locale is sourced from a JSON file, so we use getLangCode to
|
||||
// find the associated enum values
|
||||
|
||||
@@ -1,205 +0,0 @@
|
||||
import { Languages } from './i18n';
|
||||
import { SuperBlocks } from './certification-settings';
|
||||
import {
|
||||
CurriculumMaps,
|
||||
defaultSuperBlockOrder,
|
||||
getAuditedSuperBlocks,
|
||||
getNotAuditedSuperBlocks,
|
||||
getLearnSuperBlocks,
|
||||
numberOfSuperBlocksOnLanding,
|
||||
superBlockOrder,
|
||||
SuperBlockStates,
|
||||
TranslationStates
|
||||
} from './superblock-order';
|
||||
|
||||
const superBlocks = Object.values(SuperBlocks);
|
||||
const translationStates = Object.values(TranslationStates);
|
||||
const superBlockStates = Object.values(SuperBlockStates);
|
||||
const superBlockOrderLanguages = Object.keys(superBlockOrder);
|
||||
|
||||
describe("'defaultSuperBlockOrder'", () => {
|
||||
it("should have a matching item for each value in the 'SuperBlocks' object", () => {
|
||||
expect(defaultSuperBlockOrder).toEqual(expect.arrayContaining(superBlocks));
|
||||
});
|
||||
|
||||
it('should not have any extra keys', () => {
|
||||
expect(defaultSuperBlockOrder.length).toEqual(superBlocks.length);
|
||||
});
|
||||
});
|
||||
|
||||
describe("'superBlockOrder'", () => {
|
||||
superBlockOrderLanguages.forEach(language => {
|
||||
describe(`'${language}'`, () => {
|
||||
describe("'landing'", () => {
|
||||
const landingSuperBlocks =
|
||||
superBlockOrder[language as Languages][CurriculumMaps.Landing];
|
||||
|
||||
it(`should have ${numberOfSuperBlocksOnLanding} items (superBlocks)`, () => {
|
||||
expect(landingSuperBlocks.length).toEqual(
|
||||
numberOfSuperBlocksOnLanding
|
||||
);
|
||||
});
|
||||
|
||||
it('should not have a superBlock out of order', () => {
|
||||
landingSuperBlocks.forEach((superBlock, index) => {
|
||||
const defaultIndex = defaultSuperBlockOrder.indexOf(superBlock);
|
||||
const defaultSbsAfterCurrentSb = defaultSuperBlockOrder.slice(
|
||||
defaultIndex + 1
|
||||
);
|
||||
|
||||
for (let j = index + 1; j < landingSuperBlocks.length; j++) {
|
||||
expect(defaultSbsAfterCurrentSb).toContain(landingSuperBlocks[j]);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("'learn'", () => {
|
||||
const learn =
|
||||
superBlockOrder[language as Languages][CurriculumMaps.Learn];
|
||||
const audited = learn[TranslationStates.Audited];
|
||||
const notAudited = learn[TranslationStates.NotAudited];
|
||||
|
||||
describe("'audited'", () => {
|
||||
superBlockStates.forEach(superBlockState => {
|
||||
const stateSuperBlocks = audited[superBlockState];
|
||||
|
||||
describe(`'${superBlockState}'`, () => {
|
||||
it('should not have a superBlock out of order', () => {
|
||||
stateSuperBlocks.forEach((superBlock, index) => {
|
||||
const defaultIndex =
|
||||
defaultSuperBlockOrder.indexOf(superBlock);
|
||||
const defaultSbsAfterCurrentSb = defaultSuperBlockOrder.slice(
|
||||
defaultIndex + 1
|
||||
);
|
||||
|
||||
for (let j = index + 1; j < stateSuperBlocks.length; j++) {
|
||||
expect(defaultSbsAfterCurrentSb).toContain(
|
||||
stateSuperBlocks[j]
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('not audited', () => {
|
||||
superBlockStates.forEach(superBlockState => {
|
||||
const stateSuperBlocks = notAudited[superBlockState];
|
||||
|
||||
describe(`'${superBlockState}'`, () => {
|
||||
it('should not have a superBlock out of order', () => {
|
||||
stateSuperBlocks.forEach((superBlock, index) => {
|
||||
const defaultIndex =
|
||||
defaultSuperBlockOrder.indexOf(superBlock);
|
||||
const defaultSbsAfterCurrentSb = defaultSuperBlockOrder.slice(
|
||||
defaultIndex + 1
|
||||
);
|
||||
|
||||
for (let j = index + 1; j < stateSuperBlocks.length; j++) {
|
||||
expect(defaultSbsAfterCurrentSb).toContain(
|
||||
stateSuperBlocks[j]
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should have exactly one of each 'SuperBlocks' among it's children", () => {
|
||||
// flatten all ${language}.learn superblocks into one array
|
||||
const learnSuperBlocks: SuperBlocks[] = [];
|
||||
|
||||
translationStates.forEach(translationState => {
|
||||
superBlockStates.forEach(superBlockState => {
|
||||
learnSuperBlocks.push(
|
||||
...learn[translationState][superBlockState]
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
superBlocks.forEach(superBlock => {
|
||||
expect(learnSuperBlocks).toContain(superBlock);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("'superBlockOrder' helper functions", () => {
|
||||
it("'getLearnSuperBlocks('english')' should return the correct array", () => {
|
||||
const learnSuperBlocks = getLearnSuperBlocks({
|
||||
language: 'english',
|
||||
showNewCurriculum: 'true',
|
||||
showUpcomingChanges: 'true'
|
||||
});
|
||||
const test = [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy,
|
||||
SuperBlocks.CodingInterviewPrep,
|
||||
SuperBlocks.ProjectEuler,
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.TheOdinProject,
|
||||
SuperBlocks.ExampleCertification,
|
||||
SuperBlocks.RespWebDesign
|
||||
];
|
||||
expect(learnSuperBlocks).toStrictEqual(test);
|
||||
expect(learnSuperBlocks.length).toEqual(test.length);
|
||||
});
|
||||
|
||||
it("'getAuditedSuperBlocks('german')' should return the correct array", () => {
|
||||
const auditedSuperBlocks = getAuditedSuperBlocks({
|
||||
language: 'german',
|
||||
showNewCurriculum: 'true',
|
||||
showUpcomingChanges: 'true'
|
||||
});
|
||||
const test = [
|
||||
SuperBlocks.RespWebDesign,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs
|
||||
];
|
||||
expect(auditedSuperBlocks).toStrictEqual(test);
|
||||
expect(auditedSuperBlocks.length).toEqual(test.length);
|
||||
});
|
||||
|
||||
it("'getNotAuditedSuperBlocks('german')' should return the correct array", () => {
|
||||
const notAuditedSuperBlocks = getNotAuditedSuperBlocks({
|
||||
language: 'german',
|
||||
showNewCurriculum: 'true',
|
||||
showUpcomingChanges: 'true'
|
||||
});
|
||||
console.log(notAuditedSuperBlocks);
|
||||
const test = [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy,
|
||||
SuperBlocks.CodingInterviewPrep,
|
||||
SuperBlocks.ProjectEuler,
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.TheOdinProject,
|
||||
SuperBlocks.ExampleCertification
|
||||
];
|
||||
expect(notAuditedSuperBlocks).toStrictEqual(test);
|
||||
expect(notAuditedSuperBlocks.length).toEqual(test.length);
|
||||
});
|
||||
});
|
||||
@@ -1,707 +0,0 @@
|
||||
import { Languages } from './i18n';
|
||||
import { SuperBlocks } from './certification-settings';
|
||||
|
||||
/*
|
||||
* .env SHOW_NEW_CURRICULUM = SuperBlockStates.New
|
||||
* 'New' -> shown only on english staging at the moment
|
||||
*
|
||||
* .env SHOW_UPCOMING_CHANGES = SuperBlockStates.Upcoming
|
||||
* 'Upcoming' is for development -> not shown on stag or prod anywhere
|
||||
*
|
||||
*/
|
||||
|
||||
export enum CurriculumMaps {
|
||||
Landing = 'landing',
|
||||
Learn = 'learn'
|
||||
}
|
||||
|
||||
export enum TranslationStates {
|
||||
Audited = 'audited',
|
||||
NotAudited = 'notAudited'
|
||||
}
|
||||
|
||||
export enum SuperBlockStates {
|
||||
Current = 'current',
|
||||
New = 'new',
|
||||
Upcoming = 'upcoming',
|
||||
Legacy = 'legacy'
|
||||
}
|
||||
|
||||
export const orderedSuperBlockStates = [
|
||||
SuperBlockStates.Current,
|
||||
SuperBlockStates.New,
|
||||
SuperBlockStates.Upcoming,
|
||||
SuperBlockStates.Legacy
|
||||
];
|
||||
|
||||
type SuperBlockOrder = {
|
||||
[key in Languages]: {
|
||||
[CurriculumMaps.Landing]: SuperBlocks[];
|
||||
[CurriculumMaps.Learn]: {
|
||||
[TranslationStates.Audited]: {
|
||||
[SuperBlockStates.Current]: SuperBlocks[];
|
||||
[SuperBlockStates.New]: SuperBlocks[];
|
||||
[SuperBlockStates.Upcoming]: SuperBlocks[];
|
||||
[SuperBlockStates.Legacy]: SuperBlocks[];
|
||||
};
|
||||
[TranslationStates.NotAudited]: {
|
||||
[SuperBlockStates.Current]: SuperBlocks[];
|
||||
[SuperBlockStates.New]: SuperBlocks[];
|
||||
[SuperBlockStates.Upcoming]: SuperBlocks[];
|
||||
[SuperBlockStates.Legacy]: SuperBlocks[];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// all languages should have this many, one for each current cert
|
||||
export const numberOfSuperBlocksOnLanding = 12;
|
||||
|
||||
/*
|
||||
* This is the used for tests to make sure a superBlock isn't out of order
|
||||
* e.g. so that a RWD button isn't below a JS button.
|
||||
* It compares each array in `superBlockOrder` to this - those arrays do not
|
||||
* have to include all these superBlocks, but the ones it does include, have
|
||||
* to be in this order
|
||||
*/
|
||||
export const defaultSuperBlockOrder: SuperBlocks[] = [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.RespWebDesign,
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy,
|
||||
SuperBlocks.CodingInterviewPrep,
|
||||
SuperBlocks.ProjectEuler,
|
||||
SuperBlocks.TheOdinProject,
|
||||
SuperBlocks.ExampleCertification
|
||||
];
|
||||
|
||||
/*
|
||||
* The order of superblocks in the arrays below are how they appear on the maps
|
||||
*
|
||||
* The 'Landing' map array should contain exactly one superblock for each
|
||||
* current, non-legacy certification, and only one superblock of each type -
|
||||
* e.g. only one RWD superblock (button)
|
||||
*
|
||||
* The 'Learn' map arrays should contain ALL available SuperBlocks, sorted into
|
||||
* their various states. These will be used to create the 'superOrder' property.
|
||||
*
|
||||
*/
|
||||
export const superBlockOrder: SuperBlockOrder = {
|
||||
[Languages.English]: {
|
||||
[CurriculumMaps.Landing]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy
|
||||
],
|
||||
[CurriculumMaps.Learn]: {
|
||||
[TranslationStates.Audited]: {
|
||||
[SuperBlockStates.Current]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy,
|
||||
SuperBlocks.CodingInterviewPrep,
|
||||
SuperBlocks.ProjectEuler
|
||||
],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.TheOdinProject,
|
||||
SuperBlocks.ExampleCertification
|
||||
],
|
||||
[SuperBlockStates.Legacy]: [SuperBlocks.RespWebDesign]
|
||||
},
|
||||
[TranslationStates.NotAudited]: {
|
||||
[SuperBlockStates.Current]: [],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [],
|
||||
[SuperBlockStates.Legacy]: []
|
||||
}
|
||||
}
|
||||
},
|
||||
[Languages.Espanol]: {
|
||||
[CurriculumMaps.Landing]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy
|
||||
],
|
||||
[CurriculumMaps.Learn]: {
|
||||
[TranslationStates.Audited]: {
|
||||
[SuperBlockStates.Current]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy
|
||||
],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [],
|
||||
[SuperBlockStates.Legacy]: [SuperBlocks.RespWebDesign]
|
||||
},
|
||||
[TranslationStates.NotAudited]: {
|
||||
[SuperBlockStates.Current]: [
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy,
|
||||
SuperBlocks.CodingInterviewPrep,
|
||||
SuperBlocks.ProjectEuler
|
||||
],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.TheOdinProject,
|
||||
SuperBlocks.ExampleCertification
|
||||
],
|
||||
[SuperBlockStates.Legacy]: []
|
||||
}
|
||||
}
|
||||
},
|
||||
[Languages.Chinese]: {
|
||||
[CurriculumMaps.Landing]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy
|
||||
],
|
||||
[CurriculumMaps.Learn]: {
|
||||
[TranslationStates.Audited]: {
|
||||
[SuperBlockStates.Current]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy
|
||||
],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [],
|
||||
[SuperBlockStates.Legacy]: [SuperBlocks.RespWebDesign]
|
||||
},
|
||||
[TranslationStates.NotAudited]: {
|
||||
[SuperBlockStates.Current]: [
|
||||
SuperBlocks.CollegeAlgebraPy,
|
||||
SuperBlocks.CodingInterviewPrep,
|
||||
SuperBlocks.ProjectEuler
|
||||
],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.TheOdinProject,
|
||||
SuperBlocks.ExampleCertification
|
||||
],
|
||||
[SuperBlockStates.Legacy]: []
|
||||
}
|
||||
}
|
||||
},
|
||||
[Languages.ChineseTraditional]: {
|
||||
[CurriculumMaps.Landing]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy
|
||||
],
|
||||
[CurriculumMaps.Learn]: {
|
||||
[TranslationStates.Audited]: {
|
||||
[SuperBlockStates.Current]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy
|
||||
],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [],
|
||||
[SuperBlockStates.Legacy]: [SuperBlocks.RespWebDesign]
|
||||
},
|
||||
[TranslationStates.NotAudited]: {
|
||||
[SuperBlockStates.Current]: [
|
||||
SuperBlocks.CollegeAlgebraPy,
|
||||
SuperBlocks.CodingInterviewPrep,
|
||||
SuperBlocks.ProjectEuler
|
||||
],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.TheOdinProject,
|
||||
SuperBlocks.ExampleCertification
|
||||
],
|
||||
[SuperBlockStates.Legacy]: []
|
||||
}
|
||||
}
|
||||
},
|
||||
[Languages.Italian]: {
|
||||
[CurriculumMaps.Landing]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy
|
||||
],
|
||||
[CurriculumMaps.Learn]: {
|
||||
[TranslationStates.Audited]: {
|
||||
[SuperBlockStates.Current]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy,
|
||||
SuperBlocks.CodingInterviewPrep,
|
||||
SuperBlocks.ProjectEuler
|
||||
],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [],
|
||||
[SuperBlockStates.Legacy]: [SuperBlocks.RespWebDesign]
|
||||
},
|
||||
[TranslationStates.NotAudited]: {
|
||||
[SuperBlockStates.Current]: [],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.TheOdinProject,
|
||||
SuperBlocks.ExampleCertification
|
||||
],
|
||||
[SuperBlockStates.Legacy]: []
|
||||
}
|
||||
}
|
||||
},
|
||||
[Languages.Portuguese]: {
|
||||
[CurriculumMaps.Landing]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy
|
||||
],
|
||||
[CurriculumMaps.Learn]: {
|
||||
[TranslationStates.Audited]: {
|
||||
[SuperBlockStates.Current]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy,
|
||||
SuperBlocks.CodingInterviewPrep,
|
||||
SuperBlocks.ProjectEuler
|
||||
],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [SuperBlocks.TheOdinProject],
|
||||
[SuperBlockStates.Legacy]: [SuperBlocks.RespWebDesign]
|
||||
},
|
||||
[TranslationStates.NotAudited]: {
|
||||
[SuperBlockStates.Current]: [],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.ExampleCertification
|
||||
],
|
||||
[SuperBlockStates.Legacy]: []
|
||||
}
|
||||
}
|
||||
},
|
||||
[Languages.Ukrainian]: {
|
||||
[CurriculumMaps.Landing]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy
|
||||
],
|
||||
[CurriculumMaps.Learn]: {
|
||||
[TranslationStates.Audited]: {
|
||||
[SuperBlockStates.Current]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy
|
||||
],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [SuperBlocks.TheOdinProject],
|
||||
[SuperBlockStates.Legacy]: [SuperBlocks.RespWebDesign]
|
||||
},
|
||||
[TranslationStates.NotAudited]: {
|
||||
[SuperBlockStates.Current]: [
|
||||
SuperBlocks.CodingInterviewPrep,
|
||||
SuperBlocks.ProjectEuler
|
||||
],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.ExampleCertification
|
||||
],
|
||||
[SuperBlockStates.Legacy]: []
|
||||
}
|
||||
}
|
||||
},
|
||||
[Languages.Japanese]: {
|
||||
[CurriculumMaps.Landing]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy
|
||||
],
|
||||
[CurriculumMaps.Learn]: {
|
||||
[TranslationStates.Audited]: {
|
||||
[SuperBlockStates.Current]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.RespWebDesign,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CodingInterviewPrep
|
||||
],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [],
|
||||
[SuperBlockStates.Legacy]: []
|
||||
},
|
||||
[TranslationStates.NotAudited]: {
|
||||
[SuperBlockStates.Current]: [
|
||||
SuperBlocks.CollegeAlgebraPy,
|
||||
SuperBlocks.ProjectEuler
|
||||
],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.TheOdinProject,
|
||||
SuperBlocks.ExampleCertification
|
||||
],
|
||||
[SuperBlockStates.Legacy]: []
|
||||
}
|
||||
}
|
||||
},
|
||||
[Languages.German]: {
|
||||
[CurriculumMaps.Landing]: [
|
||||
SuperBlocks.RespWebDesign,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy
|
||||
],
|
||||
[CurriculumMaps.Learn]: {
|
||||
[TranslationStates.Audited]: {
|
||||
[SuperBlockStates.Current]: [
|
||||
SuperBlocks.RespWebDesign,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs
|
||||
],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [],
|
||||
[SuperBlockStates.Legacy]: []
|
||||
},
|
||||
[TranslationStates.NotAudited]: {
|
||||
[SuperBlockStates.Current]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy,
|
||||
SuperBlocks.CodingInterviewPrep,
|
||||
SuperBlocks.ProjectEuler
|
||||
],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.TheOdinProject,
|
||||
SuperBlocks.ExampleCertification
|
||||
],
|
||||
[SuperBlockStates.Legacy]: []
|
||||
}
|
||||
}
|
||||
},
|
||||
[Languages.Arabic]: {
|
||||
[CurriculumMaps.Landing]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy
|
||||
],
|
||||
[CurriculumMaps.Learn]: {
|
||||
[TranslationStates.Audited]: {
|
||||
[SuperBlockStates.Current]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs
|
||||
],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [],
|
||||
[SuperBlockStates.Legacy]: []
|
||||
},
|
||||
[TranslationStates.NotAudited]: {
|
||||
[SuperBlockStates.Current]: [
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy,
|
||||
SuperBlocks.CodingInterviewPrep,
|
||||
SuperBlocks.ProjectEuler
|
||||
],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.TheOdinProject,
|
||||
SuperBlocks.ExampleCertification
|
||||
],
|
||||
[SuperBlockStates.Legacy]: [SuperBlocks.RespWebDesign]
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// The client uses the object above to create the map
|
||||
// Keep this so it can't change
|
||||
Object.freeze(superBlockOrder);
|
||||
|
||||
function shouldShowSuperblocks({
|
||||
superBlockState,
|
||||
showNewCurriculum = 'false',
|
||||
showUpcomingChanges = 'false'
|
||||
}: {
|
||||
superBlockState: string;
|
||||
showNewCurriculum: string;
|
||||
showUpcomingChanges: string;
|
||||
}) {
|
||||
if (
|
||||
(superBlockState === SuperBlockStates.New &&
|
||||
showNewCurriculum !== 'true') ||
|
||||
(superBlockState === SuperBlockStates.Upcoming &&
|
||||
showUpcomingChanges !== 'true')
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
type Config = {
|
||||
language: string;
|
||||
showNewCurriculum?: string;
|
||||
showUpcomingChanges?: string;
|
||||
};
|
||||
|
||||
export function getLearnSuperBlocks({
|
||||
language = 'english',
|
||||
showNewCurriculum = 'false',
|
||||
showUpcomingChanges = 'false'
|
||||
}: Config): SuperBlocks[] {
|
||||
const learnSuperBlocks: SuperBlocks[] = [];
|
||||
|
||||
Object.values(TranslationStates).forEach(translationState => {
|
||||
Object.values(SuperBlockStates).forEach(superBlockState => {
|
||||
if (
|
||||
shouldShowSuperblocks({
|
||||
superBlockState,
|
||||
showNewCurriculum,
|
||||
showUpcomingChanges
|
||||
})
|
||||
) {
|
||||
learnSuperBlocks.push(
|
||||
...superBlockOrder[language as Languages][CurriculumMaps.Learn][
|
||||
translationState as TranslationStates
|
||||
][superBlockState as SuperBlockStates]
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return learnSuperBlocks;
|
||||
}
|
||||
|
||||
export function getAuditedSuperBlocks({
|
||||
language = 'english',
|
||||
showNewCurriculum = 'false',
|
||||
showUpcomingChanges = 'false'
|
||||
}: Config): SuperBlocks[] {
|
||||
const auditedSuperBlocks: SuperBlocks[] = [];
|
||||
|
||||
Object.values(SuperBlockStates).forEach(superBlockState => {
|
||||
if (
|
||||
shouldShowSuperblocks({
|
||||
superBlockState,
|
||||
showNewCurriculum,
|
||||
showUpcomingChanges
|
||||
})
|
||||
) {
|
||||
auditedSuperBlocks.push(
|
||||
...superBlockOrder[language as Languages][CurriculumMaps.Learn][
|
||||
TranslationStates.Audited
|
||||
][superBlockState as SuperBlockStates]
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return auditedSuperBlocks;
|
||||
}
|
||||
|
||||
export function getNotAuditedSuperBlocks({
|
||||
language = 'english',
|
||||
showNewCurriculum = 'false',
|
||||
showUpcomingChanges = 'false'
|
||||
}: Config): SuperBlocks[] {
|
||||
const notAuditedSuperBlocks: SuperBlocks[] = [];
|
||||
|
||||
Object.values(SuperBlockStates).forEach(superBlockState => {
|
||||
if (
|
||||
shouldShowSuperblocks({
|
||||
superBlockState,
|
||||
showNewCurriculum,
|
||||
showUpcomingChanges
|
||||
})
|
||||
) {
|
||||
notAuditedSuperBlocks.push(
|
||||
...superBlockOrder[language as Languages][CurriculumMaps.Learn][
|
||||
TranslationStates.NotAudited
|
||||
][superBlockState as SuperBlockStates]
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return notAuditedSuperBlocks;
|
||||
}
|
||||
125
config/superblocks.test.ts
Normal file
125
config/superblocks.test.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
import { Languages } from './i18n';
|
||||
import {
|
||||
SuperBlocks,
|
||||
SuperBlockStages,
|
||||
superBlockOrder,
|
||||
notAuditedSuperBlocks,
|
||||
createSuperBlockMap,
|
||||
createFlatSuperBlockMap,
|
||||
getAuditedSuperBlocks,
|
||||
getFirstNotAuditedSuperBlock
|
||||
} from './superblocks';
|
||||
|
||||
describe('superBlockOrder', () => {
|
||||
it('should contain all SuperBlocks', () => {
|
||||
const allSuperBlocks = Object.values(SuperBlocks);
|
||||
const superBlockOrderValues = Object.values(superBlockOrder).flat();
|
||||
expect(superBlockOrderValues).toHaveLength(allSuperBlocks.length);
|
||||
expect(superBlockOrderValues).toEqual(
|
||||
expect.arrayContaining(allSuperBlocks)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('createSuperBlockMap', () => {
|
||||
it('should return an object with New and Upcoming when { showNewCurriculum: true, showUpcomingChanges: true }', () => {
|
||||
const result = createSuperBlockMap({
|
||||
showNewCurriculum: 'true',
|
||||
showUpcomingChanges: 'true'
|
||||
});
|
||||
expect(result[SuperBlockStages.New]).toHaveLength(
|
||||
superBlockOrder[SuperBlockStages.New].length
|
||||
);
|
||||
expect(result[SuperBlockStages.Upcoming]).toHaveLength(
|
||||
superBlockOrder[SuperBlockStages.Upcoming].length
|
||||
);
|
||||
});
|
||||
|
||||
it('should return an object without New and Upcoming when { showNewCurriculum: false, showUpcomingChanges: false }', () => {
|
||||
const result = createSuperBlockMap({
|
||||
showNewCurriculum: 'false',
|
||||
showUpcomingChanges: 'false'
|
||||
});
|
||||
expect(result[SuperBlockStages.New]).toHaveLength(0);
|
||||
expect(result[SuperBlockStages.Upcoming]).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('createFlatSuperBlockMap', () => {
|
||||
it('should return an array of SuperBlocks object with New and Upcoming when { showNewCurriculum: true, showUpcomingChanges: true }', () => {
|
||||
const result = createFlatSuperBlockMap({
|
||||
showNewCurriculum: 'true',
|
||||
showUpcomingChanges: 'true'
|
||||
});
|
||||
expect(result).toHaveLength(Object.values(superBlockOrder).flat().length);
|
||||
});
|
||||
|
||||
it('should return an array of SuperBlocks without New and Upcoming when { showNewCurriculum: false, showUpcomingChanges: false }', () => {
|
||||
const result = createFlatSuperBlockMap({
|
||||
showNewCurriculum: 'false',
|
||||
showUpcomingChanges: 'false'
|
||||
});
|
||||
const tempSuperBlockMap = { ...superBlockOrder };
|
||||
tempSuperBlockMap[SuperBlockStages.New] = [];
|
||||
tempSuperBlockMap[SuperBlockStages.Upcoming] = [];
|
||||
expect(result).toHaveLength(Object.values(tempSuperBlockMap).flat().length);
|
||||
});
|
||||
});
|
||||
|
||||
describe('firstNotAuditedSuperBlock', () => {
|
||||
it("should return 'null' when language is 'english'", () => {
|
||||
const result = getFirstNotAuditedSuperBlock({
|
||||
language: Languages.English,
|
||||
showNewCurriculum: 'false',
|
||||
showUpcomingChanges: 'false'
|
||||
});
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it("should return a SuperBlock when language is 'chinese'", () => {
|
||||
const result = getFirstNotAuditedSuperBlock({
|
||||
language: Languages.Chinese,
|
||||
showNewCurriculum: 'false',
|
||||
showUpcomingChanges: 'false'
|
||||
});
|
||||
expect(result).toEqual(SuperBlocks.CollegeAlgebraPy);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Immutability of superBlockOrder, notAuditedSuperBlocks, and flatSuperBlockMap', () => {
|
||||
it('should not allow modification of superBlockOrder', () => {
|
||||
expect(() => {
|
||||
superBlockOrder[SuperBlockStages.FrontEnd] = [];
|
||||
}).toThrowError(TypeError);
|
||||
});
|
||||
|
||||
it('should not allow modification of notAuditedSuperBlocks', () => {
|
||||
expect(() => {
|
||||
notAuditedSuperBlocks[Languages.English] = [];
|
||||
}).toThrowError(TypeError);
|
||||
});
|
||||
|
||||
it('should not allow modification of flatSuperBlockMap', () => {
|
||||
expect(() => {
|
||||
notAuditedSuperBlocks[Languages.English] = [];
|
||||
}).toThrowError(TypeError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAuditedSuperBlocks', () => {
|
||||
Object.keys(notAuditedSuperBlocks).forEach(language => {
|
||||
it(`should return only audited SuperBlocks for ${language}`, () => {
|
||||
const auditedSuperBlocks = getAuditedSuperBlocks({
|
||||
showNewCurriculum: 'true',
|
||||
showUpcomingChanges: 'true',
|
||||
language
|
||||
});
|
||||
|
||||
auditedSuperBlocks.forEach(superblock => {
|
||||
expect(notAuditedSuperBlocks[language as Languages]).not.toContain(
|
||||
superblock
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
243
config/superblocks.ts
Normal file
243
config/superblocks.ts
Normal file
@@ -0,0 +1,243 @@
|
||||
import { Languages } from './i18n';
|
||||
|
||||
// all superblocks
|
||||
export enum SuperBlocks {
|
||||
RespWebDesignNew = '2022/responsive-web-design',
|
||||
RespWebDesign = 'responsive-web-design',
|
||||
JsAlgoDataStruct = 'javascript-algorithms-and-data-structures',
|
||||
JsAlgoDataStructNew = '2022/javascript-algorithms-and-data-structures',
|
||||
FrontEndDevLibs = 'front-end-development-libraries',
|
||||
DataVis = 'data-visualization',
|
||||
RelationalDb = 'relational-database',
|
||||
BackEndDevApis = 'back-end-development-and-apis',
|
||||
QualityAssurance = 'quality-assurance',
|
||||
SciCompPy = 'scientific-computing-with-python',
|
||||
DataAnalysisPy = 'data-analysis-with-python',
|
||||
InfoSec = 'information-security',
|
||||
MachineLearningPy = 'machine-learning-with-python',
|
||||
CodingInterviewPrep = 'coding-interview-prep',
|
||||
TheOdinProject = 'the-odin-project',
|
||||
ProjectEuler = 'project-euler',
|
||||
CollegeAlgebraPy = 'college-algebra-with-python',
|
||||
ExampleCertification = 'example-certification'
|
||||
}
|
||||
|
||||
/*
|
||||
* SuperBlockStages.New = SHOW_NEW_CURRICULUM === 'true'
|
||||
* 'New' -> shown only on english staging at the moment
|
||||
*
|
||||
* SuperBlockStages.Upcoming = SHOW_UPCOMING_CHANGES === 'true'
|
||||
* 'Upcoming' is for development -> not shown on stag or prod anywhere
|
||||
*/
|
||||
export enum SuperBlockStages {
|
||||
FrontEnd = 'frontend',
|
||||
Backend = 'backend',
|
||||
Python = 'python',
|
||||
Extra = 'extra',
|
||||
Legacy = 'legacy',
|
||||
New = 'new',
|
||||
Upcoming = 'upcoming'
|
||||
}
|
||||
|
||||
export type SuperBlockOrder = {
|
||||
[key in SuperBlockStages]: SuperBlocks[];
|
||||
};
|
||||
|
||||
// order of buttons on map, this should include all superblocks
|
||||
// new and upcoming superblocks are removed below
|
||||
export const superBlockOrder: SuperBlockOrder = {
|
||||
[SuperBlockStages.FrontEnd]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis
|
||||
],
|
||||
[SuperBlockStages.Backend]: [
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance
|
||||
],
|
||||
[SuperBlockStages.Python]: [
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy
|
||||
],
|
||||
[SuperBlockStages.Extra]: [
|
||||
SuperBlocks.CodingInterviewPrep,
|
||||
SuperBlocks.ProjectEuler
|
||||
],
|
||||
[SuperBlockStages.Legacy]: [SuperBlocks.RespWebDesign],
|
||||
[SuperBlockStages.New]: [],
|
||||
[SuperBlockStages.Upcoming]: [
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.TheOdinProject,
|
||||
SuperBlocks.ExampleCertification
|
||||
]
|
||||
};
|
||||
|
||||
Object.freeze(superBlockOrder);
|
||||
|
||||
type NotAuditedSuperBlocks = {
|
||||
[key in Languages]: SuperBlocks[];
|
||||
};
|
||||
|
||||
// when a superBlock is audited, remove it from its language below
|
||||
// when adding a new language, add all (not audited) superblocks to the object
|
||||
export const notAuditedSuperBlocks: NotAuditedSuperBlocks = {
|
||||
[Languages.English]: [],
|
||||
[Languages.Espanol]: [
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy,
|
||||
SuperBlocks.CodingInterviewPrep,
|
||||
SuperBlocks.ProjectEuler,
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.TheOdinProject
|
||||
],
|
||||
[Languages.Chinese]: [
|
||||
SuperBlocks.CollegeAlgebraPy,
|
||||
SuperBlocks.CodingInterviewPrep,
|
||||
SuperBlocks.ProjectEuler,
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.TheOdinProject
|
||||
],
|
||||
[Languages.ChineseTraditional]: [
|
||||
SuperBlocks.CollegeAlgebraPy,
|
||||
SuperBlocks.CodingInterviewPrep,
|
||||
SuperBlocks.ProjectEuler,
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.TheOdinProject
|
||||
],
|
||||
[Languages.Italian]: [
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.TheOdinProject
|
||||
],
|
||||
[Languages.Portuguese]: [
|
||||
SuperBlocks.CollegeAlgebraPy,
|
||||
SuperBlocks.ProjectEuler,
|
||||
SuperBlocks.JsAlgoDataStructNew
|
||||
],
|
||||
[Languages.Ukrainian]: [
|
||||
SuperBlocks.CodingInterviewPrep,
|
||||
SuperBlocks.ProjectEuler,
|
||||
SuperBlocks.JsAlgoDataStructNew
|
||||
],
|
||||
[Languages.Japanese]: [
|
||||
SuperBlocks.CollegeAlgebraPy,
|
||||
SuperBlocks.ProjectEuler,
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.TheOdinProject
|
||||
],
|
||||
[Languages.German]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy,
|
||||
SuperBlocks.CodingInterviewPrep,
|
||||
SuperBlocks.ProjectEuler,
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.TheOdinProject
|
||||
],
|
||||
[Languages.Arabic]: [
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy,
|
||||
SuperBlocks.CodingInterviewPrep,
|
||||
SuperBlocks.ProjectEuler,
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.TheOdinProject
|
||||
]
|
||||
};
|
||||
|
||||
Object.freeze(notAuditedSuperBlocks);
|
||||
|
||||
type Config = {
|
||||
showNewCurriculum: string | undefined;
|
||||
showUpcomingChanges: string | undefined;
|
||||
};
|
||||
|
||||
type LanguagesConfig = Config & {
|
||||
language: string;
|
||||
};
|
||||
|
||||
// removes new and upcoming from superBlockOrder
|
||||
// not used yet, will be used when adding progress indicators to map
|
||||
export function createSuperBlockMap({
|
||||
showNewCurriculum,
|
||||
showUpcomingChanges
|
||||
}: Config): SuperBlockOrder {
|
||||
const superBlockMap = { ...superBlockOrder };
|
||||
if (showNewCurriculum !== 'true') {
|
||||
superBlockMap[SuperBlockStages.New] = [];
|
||||
}
|
||||
if (showUpcomingChanges !== 'true') {
|
||||
superBlockMap[SuperBlockStages.Upcoming] = [];
|
||||
}
|
||||
return superBlockMap;
|
||||
}
|
||||
|
||||
export function createFlatSuperBlockMap({
|
||||
showNewCurriculum,
|
||||
showUpcomingChanges
|
||||
}: Config): SuperBlocks[] {
|
||||
const superBlockMap = { ...superBlockOrder };
|
||||
if (showNewCurriculum !== 'true') {
|
||||
superBlockMap[SuperBlockStages.New] = [];
|
||||
}
|
||||
if (showUpcomingChanges !== 'true') {
|
||||
superBlockMap[SuperBlockStages.Upcoming] = [];
|
||||
}
|
||||
return Object.values(superBlockMap).flat();
|
||||
}
|
||||
|
||||
// this is so we know where to display the "help us translate" section
|
||||
export function getFirstNotAuditedSuperBlock({
|
||||
language,
|
||||
showNewCurriculum,
|
||||
showUpcomingChanges
|
||||
}: LanguagesConfig): SuperBlocks | null {
|
||||
const flatSuperBlockMap = createFlatSuperBlockMap({
|
||||
showNewCurriculum,
|
||||
showUpcomingChanges
|
||||
});
|
||||
for (const superBlock of flatSuperBlockMap) {
|
||||
if (notAuditedSuperBlocks[language as Languages].includes(superBlock)) {
|
||||
return superBlock;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getAuditedSuperBlocks({
|
||||
language = 'english',
|
||||
showNewCurriculum = 'false',
|
||||
showUpcomingChanges = 'false'
|
||||
}: LanguagesConfig): SuperBlocks[] {
|
||||
if (!Object.prototype.hasOwnProperty.call(notAuditedSuperBlocks, language)) {
|
||||
throw Error(`'${language}' key not found in 'notAuditedSuperBlocks'`);
|
||||
}
|
||||
|
||||
const flatSuperBlockMap = createFlatSuperBlockMap({
|
||||
showNewCurriculum,
|
||||
showUpcomingChanges
|
||||
});
|
||||
const auditedSuperBlocks = flatSuperBlockMap.filter(
|
||||
superBlock =>
|
||||
!notAuditedSuperBlocks[language as Languages].includes(superBlock)
|
||||
);
|
||||
return auditedSuperBlocks;
|
||||
}
|
||||
@@ -1,11 +1,8 @@
|
||||
const path = require('path');
|
||||
const {
|
||||
CurriculumMaps,
|
||||
superBlockOrder,
|
||||
SuperBlockStates,
|
||||
TranslationStates,
|
||||
orderedSuperBlockStates
|
||||
} = require('../config/superblock-order');
|
||||
createFlatSuperBlockMap,
|
||||
SuperBlocks
|
||||
} = require('../config/superblocks');
|
||||
|
||||
require('dotenv').config({ path: path.resolve(__dirname, '../.env') });
|
||||
|
||||
@@ -26,72 +23,30 @@ exports.testedLang = function testedLang() {
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* creates an object with all the superblocks in
|
||||
* 'superBlockOrder[lang][learn]' as keys and gives them
|
||||
* a number (superOrder), starting with 0, as the value
|
||||
*/
|
||||
function createSuperOrder({
|
||||
language = 'english',
|
||||
showNewCurriculum = 'false',
|
||||
showUpcomingChanges = 'false'
|
||||
}) {
|
||||
if (!Object.prototype.hasOwnProperty.call(superBlockOrder, language)) {
|
||||
throw Error(`${language} not found in superblock-order.ts`);
|
||||
function createSuperOrder(superBlocks) {
|
||||
if (!Array.isArray(superBlocks)) {
|
||||
throw Error(`superBlocks must be an Array`);
|
||||
}
|
||||
|
||||
if (
|
||||
!Object.prototype.hasOwnProperty.call(superBlockOrder[language], [
|
||||
CurriculumMaps.Learn
|
||||
])
|
||||
) {
|
||||
throw Error(
|
||||
`${language} does not have a 'learn' key in superblock-order.ts`
|
||||
);
|
||||
}
|
||||
|
||||
const audited =
|
||||
superBlockOrder[language][CurriculumMaps.Learn][TranslationStates.Audited];
|
||||
const notAudited =
|
||||
superBlockOrder[language][CurriculumMaps.Learn][
|
||||
TranslationStates.NotAudited
|
||||
];
|
||||
superBlocks.forEach(superBlock => {
|
||||
if (!Object.values(SuperBlocks).includes(superBlock)) {
|
||||
throw Error(`Invalid superBlock: ${superBlock}`);
|
||||
}
|
||||
});
|
||||
|
||||
const superOrder = {};
|
||||
let i = 0;
|
||||
|
||||
function addToSuperOrder(superBlocks) {
|
||||
superBlocks.forEach(key => {
|
||||
superOrder[key] = i;
|
||||
i++;
|
||||
});
|
||||
}
|
||||
|
||||
function canAddToSuperOrder(superBlockState) {
|
||||
if (superBlockState === SuperBlockStates.New)
|
||||
return showNewCurriculum === 'true';
|
||||
if (superBlockState === SuperBlockStates.Upcoming)
|
||||
return showUpcomingChanges === 'true';
|
||||
return true;
|
||||
}
|
||||
|
||||
function addSuperBlockStates(translationState) {
|
||||
orderedSuperBlockStates.forEach(state => {
|
||||
if (canAddToSuperOrder(state)) addToSuperOrder(translationState[state]);
|
||||
});
|
||||
}
|
||||
|
||||
addSuperBlockStates(audited);
|
||||
addSuperBlockStates(notAudited);
|
||||
superBlocks.forEach((superBlock, i) => {
|
||||
superOrder[superBlock] = i;
|
||||
});
|
||||
|
||||
return superOrder;
|
||||
}
|
||||
|
||||
const superOrder = createSuperOrder({
|
||||
language: process.env.CURRICULUM_LOCALE,
|
||||
const flatSuperBlockMap = createFlatSuperBlockMap({
|
||||
showNewCurriculum: process.env.SHOW_NEW_CURRICULUM,
|
||||
showUpcomingChanges: process.env.SHOW_UPCOMING_CHANGES
|
||||
});
|
||||
const superOrder = createSuperOrder(flatSuperBlockMap);
|
||||
|
||||
// gets the superOrder of a superBlock from the object created above
|
||||
function getSuperOrder(superblock) {
|
||||
|
||||
@@ -4,12 +4,33 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { config } from 'dotenv';
|
||||
import { SuperBlocks } from '../config/certification-settings';
|
||||
import { SuperBlocks } from '../config/superblocks';
|
||||
import { createSuperOrder, getSuperOrder, getSuperBlockFromDir } from './utils';
|
||||
|
||||
config({ path: path.resolve(__dirname, '../.env') });
|
||||
|
||||
const englishTest = {
|
||||
const mockSuperBlocks = [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy,
|
||||
SuperBlocks.CodingInterviewPrep,
|
||||
SuperBlocks.ProjectEuler,
|
||||
SuperBlocks.RespWebDesign,
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.TheOdinProject,
|
||||
SuperBlocks.ExampleCertification
|
||||
];
|
||||
|
||||
const fullSuperOrder = {
|
||||
[SuperBlocks.RespWebDesignNew]: 0,
|
||||
[SuperBlocks.JsAlgoDataStruct]: 1,
|
||||
[SuperBlocks.FrontEndDevLibs]: 2,
|
||||
@@ -24,105 +45,25 @@ const englishTest = {
|
||||
[SuperBlocks.CollegeAlgebraPy]: 11,
|
||||
[SuperBlocks.CodingInterviewPrep]: 12,
|
||||
[SuperBlocks.ProjectEuler]: 13,
|
||||
[SuperBlocks.RespWebDesign]: 14
|
||||
};
|
||||
|
||||
const upcomingTest = {
|
||||
[SuperBlocks.RespWebDesignNew]: 0,
|
||||
[SuperBlocks.JsAlgoDataStruct]: 1,
|
||||
[SuperBlocks.FrontEndDevLibs]: 2,
|
||||
[SuperBlocks.DataVis]: 3,
|
||||
[SuperBlocks.RelationalDb]: 4,
|
||||
[SuperBlocks.BackEndDevApis]: 5,
|
||||
[SuperBlocks.QualityAssurance]: 6,
|
||||
[SuperBlocks.SciCompPy]: 7,
|
||||
[SuperBlocks.DataAnalysisPy]: 8,
|
||||
[SuperBlocks.InfoSec]: 9,
|
||||
[SuperBlocks.MachineLearningPy]: 10,
|
||||
[SuperBlocks.CollegeAlgebraPy]: 11,
|
||||
[SuperBlocks.CodingInterviewPrep]: 12,
|
||||
[SuperBlocks.ProjectEuler]: 13,
|
||||
[SuperBlocks.JsAlgoDataStructNew]: 14,
|
||||
[SuperBlocks.TheOdinProject]: 15,
|
||||
[SuperBlocks.ExampleCertification]: 16,
|
||||
[SuperBlocks.RespWebDesign]: 17
|
||||
};
|
||||
|
||||
const espanolTest = {
|
||||
[SuperBlocks.RespWebDesignNew]: 0,
|
||||
[SuperBlocks.JsAlgoDataStruct]: 1,
|
||||
[SuperBlocks.FrontEndDevLibs]: 2,
|
||||
[SuperBlocks.DataVis]: 3,
|
||||
[SuperBlocks.RelationalDb]: 4,
|
||||
[SuperBlocks.BackEndDevApis]: 5,
|
||||
[SuperBlocks.QualityAssurance]: 6,
|
||||
[SuperBlocks.SciCompPy]: 7,
|
||||
[SuperBlocks.DataAnalysisPy]: 8,
|
||||
[SuperBlocks.RespWebDesign]: 9,
|
||||
[SuperBlocks.InfoSec]: 10,
|
||||
[SuperBlocks.MachineLearningPy]: 11,
|
||||
[SuperBlocks.CollegeAlgebraPy]: 12,
|
||||
[SuperBlocks.CodingInterviewPrep]: 13,
|
||||
[SuperBlocks.ProjectEuler]: 14
|
||||
};
|
||||
|
||||
const chineseTest = {
|
||||
[SuperBlocks.RespWebDesignNew]: 0,
|
||||
[SuperBlocks.JsAlgoDataStruct]: 1,
|
||||
[SuperBlocks.FrontEndDevLibs]: 2,
|
||||
[SuperBlocks.DataVis]: 3,
|
||||
[SuperBlocks.RelationalDb]: 4,
|
||||
[SuperBlocks.BackEndDevApis]: 5,
|
||||
[SuperBlocks.QualityAssurance]: 6,
|
||||
[SuperBlocks.SciCompPy]: 7,
|
||||
[SuperBlocks.DataAnalysisPy]: 8,
|
||||
[SuperBlocks.InfoSec]: 9,
|
||||
[SuperBlocks.MachineLearningPy]: 10,
|
||||
[SuperBlocks.RespWebDesign]: 11,
|
||||
[SuperBlocks.CollegeAlgebraPy]: 12,
|
||||
[SuperBlocks.CodingInterviewPrep]: 13,
|
||||
[SuperBlocks.ProjectEuler]: 14
|
||||
[SuperBlocks.RespWebDesign]: 14,
|
||||
[SuperBlocks.JsAlgoDataStructNew]: 15,
|
||||
[SuperBlocks.TheOdinProject]: 16,
|
||||
[SuperBlocks.ExampleCertification]: 17
|
||||
};
|
||||
|
||||
describe('createSuperOrder', () => {
|
||||
const englishSuperOrder = createSuperOrder({
|
||||
language: 'english',
|
||||
showNewCurriculum: 'false',
|
||||
showUpcomingChanges: 'false'
|
||||
const superOrder = createSuperOrder(mockSuperBlocks);
|
||||
|
||||
it('should create the correct object given an array of SuperBlocks', () => {
|
||||
expect(superOrder).toStrictEqual(fullSuperOrder);
|
||||
});
|
||||
|
||||
const upcomingSuperOrder = createSuperOrder({
|
||||
language: 'english',
|
||||
showNewCurriculum: 'false',
|
||||
showUpcomingChanges: 'true'
|
||||
});
|
||||
|
||||
const espanolSuperOrder = createSuperOrder({
|
||||
language: 'espanol',
|
||||
showNewCurriculum: 'false',
|
||||
showUpcomingChanges: 'false'
|
||||
});
|
||||
|
||||
const chineseSuperOrder = createSuperOrder({
|
||||
language: 'chinese',
|
||||
showNewCurriculum: 'false',
|
||||
showUpcomingChanges: 'false'
|
||||
});
|
||||
|
||||
it("should create the correct object for 'english'", () => {
|
||||
expect(englishSuperOrder).toStrictEqual(englishTest);
|
||||
});
|
||||
|
||||
it('should create the correct object with upcoming changes shown', () => {
|
||||
expect(upcomingSuperOrder).toStrictEqual(upcomingTest);
|
||||
});
|
||||
|
||||
it("should create the correct object for 'espanol'", () => {
|
||||
expect(espanolSuperOrder).toStrictEqual(espanolTest);
|
||||
});
|
||||
|
||||
it("should create the correct object for 'chinese'", () => {
|
||||
expect(chineseSuperOrder).toStrictEqual(chineseTest);
|
||||
it('throws when not given an array of SuperBlocks', () => {
|
||||
expect.assertions(4);
|
||||
expect(() => getSuperOrder()).toThrow();
|
||||
expect(() => getSuperOrder(null)).toThrow();
|
||||
expect(() => getSuperOrder('')).toThrow();
|
||||
expect(() => getSuperOrder(['respansive-wib-desoin'])).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -146,12 +87,14 @@ describe('getSuperOrder', () => {
|
||||
});
|
||||
|
||||
it('returns unique numbers for all current superblocks', () => {
|
||||
// Skip non-english tests
|
||||
if (process.env.CURRICULUM_LOCALE !== 'english') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (process.env.SHOW_UPCOMING_CHANGES !== 'true') {
|
||||
if (
|
||||
process.env.SHOW_NEW_CURRICULUM !== 'true' &&
|
||||
process.env.SHOW_UPCOMING_CHANGES !== 'true'
|
||||
) {
|
||||
expect.assertions(15);
|
||||
} else if (process.env.SHOW_NEW_CURRICULUM !== 'true') {
|
||||
expect.assertions(15);
|
||||
} else if (process.env.SHOW_UPCOMING_CHANGES !== 'true') {
|
||||
expect.assertions(15);
|
||||
} else {
|
||||
expect.assertions(18);
|
||||
@@ -171,14 +114,21 @@ describe('getSuperOrder', () => {
|
||||
expect(getSuperOrder(SuperBlocks.CollegeAlgebraPy)).toBe(11);
|
||||
expect(getSuperOrder(SuperBlocks.CodingInterviewPrep)).toBe(12);
|
||||
expect(getSuperOrder(SuperBlocks.ProjectEuler)).toBe(13);
|
||||
expect(getSuperOrder(SuperBlocks.RespWebDesign)).toBe(14);
|
||||
|
||||
if (process.env.SHOW_UPCOMING_CHANGES === 'true') {
|
||||
expect(getSuperOrder(SuperBlocks.JsAlgoDataStructNew)).toBe(14);
|
||||
expect(getSuperOrder(SuperBlocks.TheOdinProject)).toBe(15);
|
||||
expect(getSuperOrder(SuperBlocks.ExampleCertification)).toBe(16);
|
||||
expect(getSuperOrder(SuperBlocks.RespWebDesign)).toBe(17);
|
||||
} else {
|
||||
expect(getSuperOrder(SuperBlocks.RespWebDesign)).toBe(14);
|
||||
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.ExampleCertification)).toBe(17);
|
||||
} 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.ExampleCertification)).toBe(17);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@ const landingPageElements = {
|
||||
heading: "[data-test-label='landing-header']",
|
||||
callToAction: "[data-test-label='landing-big-cta']",
|
||||
certifications: "[data-test-label='certifications']",
|
||||
curriculumBtns: "[data-test-label='curriculum-map-button']",
|
||||
testimonials: "[data-test-label='testimonial-cards']",
|
||||
landingPageImage: "[data-test-label='landing-page-figure']",
|
||||
faq: "[data-test-label='landing-page-faq']"
|
||||
@@ -11,7 +12,7 @@ type LandingPageTypes<T> = T[keyof T];
|
||||
|
||||
type LandingPageLogs = LandingPageTypes<typeof landingPageElements>;
|
||||
|
||||
const certifications = [
|
||||
const superBlocks = [
|
||||
'Responsive Web Design',
|
||||
'JavaScript Algorithms and Data Structures',
|
||||
'Front End Development Libraries',
|
||||
@@ -23,7 +24,10 @@ const certifications = [
|
||||
'Data Analysis with Python',
|
||||
'Information Security',
|
||||
'Machine Learning with Python',
|
||||
'College Algebra with Python'
|
||||
'College Algebra with Python',
|
||||
'Coding Interview Prep',
|
||||
'Project Euler',
|
||||
'Legacy Responsive Web Design'
|
||||
];
|
||||
|
||||
describe('Landing page', () => {
|
||||
@@ -67,13 +71,10 @@ describe('Landing page', () => {
|
||||
.should('not.exist');
|
||||
});
|
||||
|
||||
it('Has links to all the certifications', function () {
|
||||
cy.get(landingPageElements.certifications)
|
||||
.children()
|
||||
.its('length')
|
||||
.should('eq', 12);
|
||||
cy.wrap(certifications).each((cert: LandingPageLogs) => {
|
||||
cy.get(landingPageElements.certifications).contains(cert);
|
||||
it('Has links to all superblocks', function () {
|
||||
cy.get(landingPageElements.curriculumBtns).its('length').should('eq', 15);
|
||||
cy.wrap(superBlocks).each((cert: LandingPageLogs) => {
|
||||
cy.get(landingPageElements.curriculumBtns).contains(cert);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { SuperBlocks } from '../../../../../config/certification-settings';
|
||||
import { SuperBlocks } from '../../../../../config/superblocks';
|
||||
|
||||
interface Meta {
|
||||
challengeOrder: string[][];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const challengerSelector = {
|
||||
challengeMap: "[data-test-label='learn-curriculum-map']"
|
||||
curriculumMap: "[data-test-label='curriculum-map']"
|
||||
} as const;
|
||||
|
||||
const learnUrl = {
|
||||
@@ -43,7 +43,7 @@ describe('Learn Landing page (not logged in)', () => {
|
||||
it('Should render a curriculum map', () => {
|
||||
cy.document().then(document => {
|
||||
const superBlocks = document.querySelectorAll<HTMLAnchorElement>(
|
||||
`${challengerSelector.challengeMap} > li > a`
|
||||
`${challengerSelector.curriculumMap} > ul > li > a`
|
||||
);
|
||||
expect(superBlocks).to.have.length(15);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { SuperBlocks } from '../../../../../config/certification-settings';
|
||||
import { SuperBlocks } from '../../../../../config/superblocks';
|
||||
|
||||
const projects = {
|
||||
superBlock: SuperBlocks.FrontEndDevLibs,
|
||||
|
||||
@@ -120,69 +120,32 @@ export const rtlLangs = [''];
|
||||
> [!NOTE]
|
||||
> When a language has been set up in the deployment pipeline AND has a public `/news` instance live, it can be removed from the `hiddenLangs` array and be made available to the public.
|
||||
|
||||
### Configure the Language Superblock Order
|
||||
### Set Translated SuperBlocks
|
||||
|
||||
In the [config/superblock-order.ts](https://github.com/freeCodeCamp/freeCodeCamp/blob/main/config/superblock-order.ts) file, you need to set the order and state of all the superblocks for the new language in the `superBlockOrder` object. Copy one of the language keys and all its values, paste it to the bottom of the object (or wherever), and change the key to your new language from the `Languages` enum.
|
||||
In the [config/superblocks.ts](https://github.com/freeCodeCamp/freeCodeCamp/blob/main/config/superblocks.ts) file, add the new language to the `notAuditedSuperBlocks` object. This lists all the superblocks which are not fully translated. Add an array of superblocks which have not been fully translated to it:
|
||||
|
||||
```js
|
||||
export const superBlockOrder: SuperBlockOrder = {
|
||||
export const notAuditedSuperBlocks: NotAuditedSuperBlocks = {
|
||||
...
|
||||
[Languages.Dothraki]: {
|
||||
[CurriculumMaps.Landing]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy
|
||||
],
|
||||
[CurriculumMaps.Learn]: {
|
||||
[TranslationStates.Audited]: {
|
||||
[SuperBlockStates.Current]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CodingInterviewPrep
|
||||
],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [SuperBlocks.JsAlgoDataStructNew],
|
||||
[SuperBlockStates.Legacy]: [SuperBlocks.RespWebDesign]
|
||||
},
|
||||
[TranslationStates.NotAudited]: {
|
||||
[SuperBlockStates.Current]: [],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [],
|
||||
[SuperBlockStates.Legacy]: []
|
||||
}
|
||||
}
|
||||
}
|
||||
[Languages.Dothraki]: [
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CollegeAlgebraPy,
|
||||
SuperBlocks.CodingInterviewPrep,
|
||||
SuperBlocks.ProjectEuler,
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.TheOdinProject
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The order of the superblocks in this object is how they appear on the "Landing" page and "Learn" maps. Follow the comments in that file so you know how you are allowed to order the superblocks, then move them to their proper places for the new language.
|
||||
|
||||
> [!ATTENTION]
|
||||
> Do not change the order of any of the keys in the object, just move the superblocks to the different arrays
|
||||
|
||||
The `CurriculumMaps.Landing` array should contain exactly one superblock for all our current certifications, and the `CurriculumMaps.Learn` object should have all existing superblocks in it. Translated superblocks go in `TranslationStates.Audited` and non-translated superblocks go in `TranslationStates.NotAudited`. Each of those two objects has four different states a superblock can be in.
|
||||
|
||||
- `SuperBlockStates.Current`: Means that the superblock is current, `Responsive Web Design` for example.
|
||||
- `SuperBlockStates.New`: These only show up when `SHOW_NEW_CURRICULUM` is set to `true` in your `.env` file. It is for displaying new superblocks on a specific build. For example, when we released the new RWD, we only showed it on English to start.
|
||||
- `SuperBlockStates.Upcoming`: These only show up when `SHOW_UPCOMING_CHANGES` is set to `true` in your `.env` file. It is to show superblocks locally while they are in development. Or, if you just need to hide a superblock from the map for some other reason.
|
||||
- `SuperBlockStates.Legacy`: A superblock is moved here when a newer version of that superblock has been fully translated and replaced it.
|
||||
Be sure to only add the superblocks which are **not** fully translated and approved. The translated superblocks will be calculated from this object. When a new superblock is finished being fully translated, remove it from the array for that language.
|
||||
|
||||
### Configure Search
|
||||
|
||||
|
||||
@@ -389,4 +389,4 @@ The user is now a proofreader.
|
||||
|
||||
## How to Add or Update a Language
|
||||
|
||||
Check out the [how to enable new language](how-to-enable-new-languages.md) docs. If you are updating a language the section on [configuring the language superblock order](how-to-enable-new-languages.md#configure-the-language-superblock-order) should be helpful.
|
||||
Check out the [how to enable new language](how-to-enable-new-languages.md) docs. If you are updating a language the section on [set translated superblocks](how-to-enable-new-languages.md#set-translated-superblocks) should be helpful.
|
||||
|
||||
@@ -9,8 +9,7 @@ config({ path: envPath });
|
||||
|
||||
import { availableLangs } from '../../config/i18n';
|
||||
import { getChallengesForLang } from '../../curriculum/get-challenges';
|
||||
import { SuperBlocks } from '../../config/certification-settings';
|
||||
import { getAuditedSuperBlocks } from '../../config/superblock-order';
|
||||
import { SuperBlocks, getAuditedSuperBlocks } from '../../config/superblocks';
|
||||
|
||||
// TODO: re-organise the types to a common 'types' folder that can be shared
|
||||
// between the workspaces so we don't have to declare ChallengeNode here and in
|
||||
|
||||
@@ -5,7 +5,7 @@ import { prompt } from 'inquirer';
|
||||
import { format } from 'prettier';
|
||||
|
||||
import ObjectID from 'bson-objectid';
|
||||
import { SuperBlocks } from '../../config/certification-settings';
|
||||
import { SuperBlocks } from '../../config/superblocks';
|
||||
import { createStepFile } from './utils';
|
||||
import { getSuperBlockSubPath } from './fs-utils';
|
||||
import { Meta } from './helpers/project-metadata';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
import { SuperBlocks } from '../../config/certification-settings';
|
||||
import { SuperBlocks } from '../../config/superblocks';
|
||||
import { getSuperBlockSubPath } from './fs-utils';
|
||||
|
||||
describe('getSuperBlockSubPath', () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { SuperBlocks } from '../../config/certification-settings';
|
||||
import { SuperBlocks } from '../../config/superblocks';
|
||||
|
||||
export function getSuperBlockSubPath(superBlock: SuperBlocks): string {
|
||||
const pathMap = {
|
||||
|
||||
@@ -5,7 +5,7 @@ import readdirp from 'readdirp';
|
||||
// TODO: remove chai and use jest's assertion errors
|
||||
import { AssertionError } from 'chai';
|
||||
import envData from '../../../config/env.json';
|
||||
import { SuperBlocks } from '../../../config/certification-settings';
|
||||
import { SuperBlocks } from '../../../config/superblocks';
|
||||
import {
|
||||
superblockSchemaValidator,
|
||||
availableSuperBlocksValidator
|
||||
|
||||
@@ -2,7 +2,7 @@ import { mkdirSync, writeFileSync, readFileSync } from 'fs';
|
||||
import { resolve, dirname } from 'path';
|
||||
import { submitTypes } from '../../../client/utils/challenge-types';
|
||||
import { type ChallengeNode } from '../../../client/src/redux/prop-types';
|
||||
import { SuperBlocks } from '../../../config/certification-settings';
|
||||
import { SuperBlocks } from '../../../config/superblocks';
|
||||
|
||||
type Intro = { [keyValue in SuperBlocks]: IntroProps };
|
||||
export type Curriculum<T> = {
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
const { getAuditedSuperBlocks } = require('../config/superblock-order');
|
||||
const { Languages } = require('../config/i18n');
|
||||
const { getAuditedSuperBlocks } = require('../config/superblocks');
|
||||
const {
|
||||
showNewCurriculum,
|
||||
showUpcomingChanges
|
||||
} = require('../config/env.json');
|
||||
|
||||
function isAuditedCert(language, superblock) {
|
||||
if (!language || !superblock)
|
||||
throw Error('Both arguments must be provided for auditing');
|
||||
|
||||
if (language === Languages.English) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const auditedSuperBlocks = getAuditedSuperBlocks({ language });
|
||||
const auditedSuperBlocks = getAuditedSuperBlocks({
|
||||
showNewCurriculum: showNewCurriculum.toString(),
|
||||
showUpcomingChanges: showUpcomingChanges.toString(),
|
||||
language
|
||||
});
|
||||
return auditedSuperBlocks.includes(superblock);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user