chore: use constants for superblocks (#43886)
* chore: use constants for superblocks * add prettier ts dec to challenge-helper-scripts * config/ to ts. broken * typescripterise tools/ and config/ * create global tsconfig, remove alternate configs * delete temp ts->js, add to gitignore * fix gitignore * re-import SuperBlocks in super-block-intro.tsx * remove renamed files added again * fix config * remove accidental files * remove snap * delete built files * adjust eslintrc for enums * add node types to root * ignore build files in lint and prettier * fix tools/ in tsconfig * ignore annoying ts warnings * prettierise Map/index.tsx * fix enum to match lint rule * rejig Map to render RWD superblock * 'pretty minor' - implicitly tsc within root Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com> * fix client/package.json for Gitpod * broken: migrate @types to root * fix: use typeRoots to prevent duplication * fix show.tsx, try typeroots in root * silly fix for duplicate node_modules types * remove typeRoots from root * fix: tsconfig or not tsconfig, that is the... * fix: ...question: Whether 'tis nobler in the mind to suffer the slings and arrows of outrageous configs... * fix: Or to take Arms against a Sea of lint errors And by opposing end them Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
This commit is contained in:
@ -4,3 +4,6 @@ client/public/**
|
||||
api-server/src/public/**
|
||||
api-server/lib/**
|
||||
tools/contributor/**
|
||||
tools/scripts/build/ensure-env.js
|
||||
config/i18n/all-langs.js
|
||||
config/certification-settings.js
|
||||
|
@ -45,9 +45,9 @@
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": [
|
||||
"./client/tsconfig.json",
|
||||
"./tools/challenge-helper-scripts/tsconfig.json",
|
||||
"./tools/ui-components/tsconfig.json"
|
||||
"./tsconfig.json",
|
||||
"./tools/ui-components/tsconfig.json",
|
||||
"./tools/scripts/build/tsconfig.json"
|
||||
]
|
||||
},
|
||||
"extends": [
|
||||
@ -91,6 +91,10 @@
|
||||
{
|
||||
"selector": "function",
|
||||
"format": ["camelCase", "PascalCase"]
|
||||
},
|
||||
{
|
||||
"selector": "enumMember",
|
||||
"format": ["PascalCase"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -163,6 +163,10 @@ config/client/sass-compile.json
|
||||
config/client/frame-runner.json
|
||||
config/client/test-evaluator.json
|
||||
config/curriculum.json
|
||||
config/i18n/all-langs.js
|
||||
config/certification-settings.js
|
||||
|
||||
tools/scripts/build/ensure-env.js
|
||||
|
||||
### vim ###
|
||||
# Swap
|
||||
|
@ -5,6 +5,9 @@ client/static
|
||||
curriculum/challenges/_meta/*/*
|
||||
curriculum/challenges/**/*
|
||||
config/**/*.json
|
||||
config/i18n/all-langs.js
|
||||
config/certification-settings.js
|
||||
client/i18n/**/*.json
|
||||
docs/i18n
|
||||
**/package-lock.json
|
||||
tools/scripts/build/ensure-env.js
|
@ -19,11 +19,11 @@
|
||||
"author": "freeCodeCamp <team@freecodecamp.org>",
|
||||
"main": "none",
|
||||
"scripts": {
|
||||
"prebuild": "node ../tools/scripts/build/ensure-env.js && npm run build:workers -- --env production",
|
||||
"prebuild": "tsc -p ../tools/scripts/build/ && node ../tools/scripts/build/ensure-env.js && npm run build:workers -- --env production",
|
||||
"build": "node --max_old_space_size=7168 node_modules/gatsby-cli build --prefix-paths",
|
||||
"build:workers": "node --max_old_space_size=7168 node_modules/webpack-cli/bin/cli --config ./webpack-workers.js",
|
||||
"clean": "gatsby clean",
|
||||
"predevelop": "node ../tools/scripts/build/ensure-env.js && npm run build:workers -- --env development",
|
||||
"predevelop": "tsc -p ../tools/scripts/build/ && node ../tools/scripts/build/ensure-env.js && npm run build:workers -- --env development",
|
||||
"develop": "node --max_old_space_size=4000 node_modules/gatsby-cli develop --inspect=9230",
|
||||
"lint": "node ./i18n/schema-validation.js",
|
||||
"serve": "gatsby serve -p 8000",
|
||||
@ -132,27 +132,6 @@
|
||||
"@codesee/tracker": "0.143.0",
|
||||
"@testing-library/jest-dom": "5.15.0",
|
||||
"@testing-library/react": "12.1.2",
|
||||
"@types/chai": "4.2.22",
|
||||
"@types/jest": "26.0.24",
|
||||
"@types/loadable__component": "5.13.4",
|
||||
"@types/lodash-es": "4.17.5",
|
||||
"@types/node": "16.11.7",
|
||||
"@types/prismjs": "1.16.6",
|
||||
"@types/psl": "1.1.0",
|
||||
"@types/reach__router": "1.3.9",
|
||||
"@types/react-dom": "17.0.11",
|
||||
"@types/react-helmet": "6.1.4",
|
||||
"@types/react-instantsearch-dom": "6.12.0",
|
||||
"@types/react-monaco-editor": "0.16.0",
|
||||
"@types/react-redux": "7.1.16",
|
||||
"@types/react-responsive": "8.0.2",
|
||||
"@types/react-spinkit": "3.0.7",
|
||||
"@types/react-test-renderer": "17.0.1",
|
||||
"@types/react-transition-group": "4.4.4",
|
||||
"@types/redux-actions": "2.6.2",
|
||||
"@types/sanitize-html": "2.5.0",
|
||||
"@types/store": "2.0.2",
|
||||
"@types/validator": "13.7.0",
|
||||
"autoprefixer": "10.4.0",
|
||||
"babel-plugin-transform-imports": "2.0.0",
|
||||
"chokidar": "3.5.2",
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import { SuperBlocks } from '../../../../config/certification-settings';
|
||||
import APIIcon from './API-icon';
|
||||
import D3Icon from './D3-icon';
|
||||
import DatabaseIcon from './Database-icon';
|
||||
@ -13,24 +14,22 @@ import ResponsiveDesign from './responsive-design';
|
||||
import Shield from './shield';
|
||||
|
||||
const iconMap = {
|
||||
'responsive-web-design': ResponsiveDesign,
|
||||
'javascript-algorithms-and-data-structures': JavaScriptIcon,
|
||||
'front-end-development-libraries': ReactIcon,
|
||||
'data-visualization': D3Icon,
|
||||
'back-end-development-and-apis': APIIcon,
|
||||
'relational-databases': DatabaseIcon,
|
||||
'quality-assurance': Clipboard,
|
||||
'scientific-computing-with-python': PythonIcon,
|
||||
'data-analysis-with-python': Analytics,
|
||||
'information-security': Shield,
|
||||
'machine-learning-with-python': TensorflowIcon,
|
||||
'coding-interview-prep': Algorithm
|
||||
[SuperBlocks.RespWebDesign]: ResponsiveDesign,
|
||||
[SuperBlocks.JsAlgoDataStruct]: JavaScriptIcon,
|
||||
[SuperBlocks.FrontEndDevLibs]: ReactIcon,
|
||||
[SuperBlocks.DataVis]: D3Icon,
|
||||
[SuperBlocks.BackEndDevApis]: APIIcon,
|
||||
[SuperBlocks.RelationalDb]: DatabaseIcon,
|
||||
[SuperBlocks.QualityAssurance]: Clipboard,
|
||||
[SuperBlocks.SciCompPy]: PythonIcon,
|
||||
[SuperBlocks.DataAnalysisPy]: Analytics,
|
||||
[SuperBlocks.InfoSec]: Shield,
|
||||
[SuperBlocks.MachineLearningPy]: TensorflowIcon,
|
||||
[SuperBlocks.CodingInterviewPrep]: Algorithm
|
||||
};
|
||||
|
||||
type SuperBlock = keyof typeof iconMap;
|
||||
|
||||
const generateIconComponent = (
|
||||
superBlock: SuperBlock,
|
||||
superBlock: SuperBlocks,
|
||||
className: string
|
||||
): JSX.Element => {
|
||||
// fallback in case super block doesn't exist and for tests
|
||||
@ -39,4 +38,4 @@ const generateIconComponent = (
|
||||
return <Icon className={className} />;
|
||||
};
|
||||
|
||||
export { generateIconComponent, SuperBlock };
|
||||
export { generateIconComponent };
|
||||
|
@ -20,8 +20,8 @@ export const flashMessageSelector = (state: State): FlashState['message'] =>
|
||||
// ACTION DEFINITIONS
|
||||
|
||||
enum FlashActionTypes {
|
||||
createFlashMessage = 'createFlashMessage',
|
||||
removeFlashMessage = 'removeFlashMessage'
|
||||
CreateFlashMessage = 'createFlashMessage',
|
||||
RemoveFlashMessage = 'removeFlashMessage'
|
||||
}
|
||||
|
||||
export type FlashMessageArg = {
|
||||
@ -32,7 +32,7 @@ export type FlashMessageArg = {
|
||||
|
||||
export const createFlashMessage = (
|
||||
flash: FlashMessageArg
|
||||
): ReducerPayload<FlashActionTypes.createFlashMessage> => {
|
||||
): ReducerPayload<FlashActionTypes.CreateFlashMessage> => {
|
||||
const playSound = store.get('fcc-sound') as boolean | undefined;
|
||||
if (playSound) {
|
||||
void import('tone').then(tone => {
|
||||
@ -54,20 +54,20 @@ export const createFlashMessage = (
|
||||
});
|
||||
}
|
||||
return {
|
||||
type: FlashActionTypes.createFlashMessage,
|
||||
type: FlashActionTypes.CreateFlashMessage,
|
||||
payload: { ...flash, id: nanoid() }
|
||||
};
|
||||
};
|
||||
|
||||
export const removeFlashMessage =
|
||||
(): ReducerPayload<FlashActionTypes.removeFlashMessage> => ({
|
||||
type: FlashActionTypes.removeFlashMessage
|
||||
(): ReducerPayload<FlashActionTypes.RemoveFlashMessage> => ({
|
||||
type: FlashActionTypes.RemoveFlashMessage
|
||||
});
|
||||
|
||||
// REDUCER
|
||||
type ReducerBase<T> = { type: T };
|
||||
type ReducerPayload<T extends FlashActionTypes> =
|
||||
T extends FlashActionTypes.createFlashMessage
|
||||
T extends FlashActionTypes.CreateFlashMessage
|
||||
? ReducerBase<T> & {
|
||||
payload: FlashState['message'];
|
||||
}
|
||||
@ -79,9 +79,9 @@ export const reducer = (
|
||||
action: ReducerPayload<FlashActionTypes>
|
||||
): FlashState => {
|
||||
switch (action.type) {
|
||||
case FlashActionTypes.createFlashMessage:
|
||||
case FlashActionTypes.CreateFlashMessage:
|
||||
return { ...state, message: action.payload };
|
||||
case FlashActionTypes.removeFlashMessage:
|
||||
case FlashActionTypes.RemoveFlashMessage:
|
||||
return { ...state, message: initialState.message };
|
||||
default:
|
||||
return state;
|
||||
|
@ -2,9 +2,10 @@ import { graphql, useStaticQuery } from 'gatsby';
|
||||
import i18next from 'i18next';
|
||||
import React from 'react';
|
||||
|
||||
import { SuperBlocks } from '../../../../config/certification-settings';
|
||||
import envData from '../../../../config/env.json';
|
||||
import { isAuditedCert } from '../../../../utils/is-audited';
|
||||
import { generateIconComponent, SuperBlock } from '../../assets/icons';
|
||||
import { generateIconComponent } from '../../assets/icons';
|
||||
import LinkButton from '../../assets/icons/link-button';
|
||||
import { ChallengeNode } from '../../redux/prop-types';
|
||||
import { Link, Spacer } from '../helpers';
|
||||
@ -14,7 +15,7 @@ import './map.css';
|
||||
const { curriculumLocale } = envData;
|
||||
|
||||
interface MapProps {
|
||||
currentSuperBlock?: string;
|
||||
currentSuperBlock?: SuperBlocks | null;
|
||||
forLanding?: boolean;
|
||||
}
|
||||
|
||||
@ -24,7 +25,7 @@ interface MapData {
|
||||
};
|
||||
}
|
||||
|
||||
function createSuperBlockTitle(superBlock: string) {
|
||||
function createSuperBlockTitle(superBlock: SuperBlocks) {
|
||||
const superBlockTitle = i18next.t(`intro:${superBlock}.title`);
|
||||
return superBlock === 'coding-interview-prep'
|
||||
? i18next.t('learn.cert-map-estimates.coding-prep', {
|
||||
@ -40,7 +41,9 @@ const linkSpacingStyle = {
|
||||
};
|
||||
|
||||
function renderLandingMap(nodes: ChallengeNode[]) {
|
||||
nodes = nodes.filter(node => node.superBlock !== 'coding-interview-prep');
|
||||
nodes = nodes.filter(
|
||||
node => node.superBlock !== SuperBlocks.CodingInterviewPrep
|
||||
);
|
||||
return (
|
||||
<ul data-test-label='certifications'>
|
||||
{nodes.map((node, i) => (
|
||||
@ -50,7 +53,7 @@ function renderLandingMap(nodes: ChallengeNode[]) {
|
||||
to={`/learn/${node.superBlock}/`}
|
||||
>
|
||||
<div style={linkSpacingStyle}>
|
||||
{generateIconComponent(node.superBlock as SuperBlock, 'map-icon')}
|
||||
{generateIconComponent(node.superBlock, 'map-icon')}
|
||||
{i18next.t(`intro:${node.superBlock}.title`)}
|
||||
</div>
|
||||
<LinkButton />
|
||||
@ -61,7 +64,10 @@ function renderLandingMap(nodes: ChallengeNode[]) {
|
||||
);
|
||||
}
|
||||
|
||||
function renderLearnMap(nodes: ChallengeNode[], currentSuperBlock = '') {
|
||||
function renderLearnMap(
|
||||
nodes: ChallengeNode[],
|
||||
currentSuperBlock: MapProps['currentSuperBlock']
|
||||
) {
|
||||
nodes = nodes.filter(node => node.superBlock !== currentSuperBlock);
|
||||
return curriculumLocale === 'english' ? (
|
||||
<ul data-test-label='learn-curriculum-map'>
|
||||
@ -72,7 +78,7 @@ function renderLearnMap(nodes: ChallengeNode[], currentSuperBlock = '') {
|
||||
to={`/learn/${node.superBlock}/`}
|
||||
>
|
||||
<div style={linkSpacingStyle}>
|
||||
{generateIconComponent(node.superBlock as SuperBlock, 'map-icon')}
|
||||
{generateIconComponent(node.superBlock, 'map-icon')}
|
||||
{createSuperBlockTitle(node.superBlock)}
|
||||
</div>
|
||||
</Link>
|
||||
@ -90,10 +96,7 @@ function renderLearnMap(nodes: ChallengeNode[], currentSuperBlock = '') {
|
||||
to={`/learn/${node.superBlock}/`}
|
||||
>
|
||||
<div style={linkSpacingStyle}>
|
||||
{generateIconComponent(
|
||||
node.superBlock as SuperBlock,
|
||||
'map-icon'
|
||||
)}
|
||||
{generateIconComponent(node.superBlock, 'map-icon')}
|
||||
{createSuperBlockTitle(node.superBlock)}
|
||||
</div>
|
||||
</Link>
|
||||
@ -120,10 +123,7 @@ function renderLearnMap(nodes: ChallengeNode[], currentSuperBlock = '') {
|
||||
to={`/learn/${node.superBlock}/`}
|
||||
>
|
||||
<div style={linkSpacingStyle}>
|
||||
{generateIconComponent(
|
||||
node.superBlock as SuperBlock,
|
||||
'map-icon'
|
||||
)}
|
||||
{generateIconComponent(node.superBlock, 'map-icon')}
|
||||
{createSuperBlockTitle(node.superBlock)}
|
||||
</div>
|
||||
</Link>
|
||||
@ -135,7 +135,7 @@ function renderLearnMap(nodes: ChallengeNode[], currentSuperBlock = '') {
|
||||
|
||||
export function Map({
|
||||
forLanding = false,
|
||||
currentSuperBlock = ''
|
||||
currentSuperBlock = null
|
||||
}: MapProps): React.ReactElement {
|
||||
/*
|
||||
* this query gets the first challenge from each block and the second block
|
||||
|
@ -2,6 +2,7 @@ import { uniqBy } from 'lodash-es';
|
||||
import { createAction, handleActions } from 'redux-actions';
|
||||
import store from 'store';
|
||||
|
||||
import { SuperBlocks } from '../../../config/certification-settings';
|
||||
import { actionTypes as challengeTypes } from '../templates/Challenges/redux/action-types';
|
||||
import { CURRENT_CHALLENGE_KEY } from '../templates/Challenges/redux/current-challenge-saga';
|
||||
import { createAcceptTermsSaga } from './accept-terms-saga';
|
||||
@ -292,27 +293,27 @@ export const certificatesByNameSelector = username => state => {
|
||||
{
|
||||
show: isRespWebDesignCert,
|
||||
title: 'Responsive Web Design Certification',
|
||||
certSlug: 'responsive-web-design'
|
||||
certSlug: SuperBlocks.RespWebDesign
|
||||
},
|
||||
{
|
||||
show: isJsAlgoDataStructCert,
|
||||
title: 'JavaScript Algorithms and Data Structures Certification',
|
||||
certSlug: 'javascript-algorithms-and-data-structures'
|
||||
certSlug: SuperBlocks.JsAlgoDataStruct
|
||||
},
|
||||
{
|
||||
show: isFrontEndLibsCert,
|
||||
title: 'Front End Development Libraries Certification',
|
||||
certSlug: 'front-end-development-libraries'
|
||||
certSlug: SuperBlocks.FrontEndDevLibs
|
||||
},
|
||||
{
|
||||
show: is2018DataVisCert,
|
||||
title: 'Data Visualization Certification',
|
||||
certSlug: 'data-visualization'
|
||||
certSlug: SuperBlocks.DataVis
|
||||
},
|
||||
{
|
||||
show: isApisMicroservicesCert,
|
||||
title: 'Back End Development and APIs Certification',
|
||||
certSlug: 'back-end-development-and-apis'
|
||||
certSlug: SuperBlocks.BackEndDevApis
|
||||
},
|
||||
{
|
||||
show: isQaCertV7,
|
||||
|
@ -1,5 +1,6 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import { HandlerProps } from 'react-reflex';
|
||||
import { SuperBlocks } from '../../../config/certification-settings';
|
||||
|
||||
export const UserPropType = PropTypes.shape({
|
||||
about: PropTypes.string,
|
||||
@ -81,7 +82,7 @@ export type MarkdownRemark = {
|
||||
frontmatter: {
|
||||
block: string;
|
||||
isBeta: boolean;
|
||||
superBlock: string;
|
||||
superBlock: SuperBlocks;
|
||||
title: string;
|
||||
};
|
||||
headings: [
|
||||
@ -159,7 +160,7 @@ export type ChallengeNode = {
|
||||
};
|
||||
sourceInstanceName: string;
|
||||
superOrder: number;
|
||||
superBlock: string;
|
||||
superBlock: SuperBlocks;
|
||||
tail: string[];
|
||||
template: string;
|
||||
tests: Test[];
|
||||
@ -302,7 +303,7 @@ export type ChallengeMeta = {
|
||||
nextChallengePath: string;
|
||||
prevChallengePath: string;
|
||||
removeComments: boolean;
|
||||
superBlock: string;
|
||||
superBlock: SuperBlocks;
|
||||
title?: string;
|
||||
challengeType?: number;
|
||||
helpCategory: string;
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { SuperBlocks } from '../../../config/certification-settings';
|
||||
|
||||
const responsiveWebBase =
|
||||
'/learn/responsive-web-design/responsive-web-design-projects';
|
||||
const jsAlgoBase =
|
||||
@ -289,228 +291,228 @@ const certMap = [
|
||||
{
|
||||
id: '561add10cb82ac38a17513bc',
|
||||
title: 'Responsive Web Design',
|
||||
certSlug: 'responsive-web-design',
|
||||
certSlug: SuperBlocks.RespWebDesign,
|
||||
flag: 'isRespWebDesignCert',
|
||||
projects: [
|
||||
{
|
||||
id: 'bd7158d8c442eddfaeb5bd18',
|
||||
title: 'Build a Tribute Page',
|
||||
link: `${responsiveWebBase}/build-a-tribute-page`,
|
||||
certSlug: 'responsive-web-design'
|
||||
certSlug: SuperBlocks.RespWebDesign
|
||||
},
|
||||
{
|
||||
id: '587d78af367417b2b2512b03',
|
||||
title: 'Build a Survey Form',
|
||||
link: `${responsiveWebBase}/build-a-survey-form`,
|
||||
certSlug: 'responsive-web-design'
|
||||
certSlug: SuperBlocks.RespWebDesign
|
||||
},
|
||||
{
|
||||
id: '587d78af367417b2b2512b04',
|
||||
title: 'Build a Product Landing Page',
|
||||
link: `${responsiveWebBase}/build-a-product-landing-page`,
|
||||
certSlug: 'responsive-web-design'
|
||||
certSlug: SuperBlocks.RespWebDesign
|
||||
},
|
||||
{
|
||||
id: '587d78b0367417b2b2512b05',
|
||||
title: 'Build a Technical Documentation Page',
|
||||
link: `${responsiveWebBase}/build-a-technical-documentation-page`,
|
||||
certSlug: 'responsive-web-design'
|
||||
certSlug: SuperBlocks.RespWebDesign
|
||||
},
|
||||
{
|
||||
id: 'bd7158d8c242eddfaeb5bd13',
|
||||
title: 'Build a Personal Portfolio Webpage',
|
||||
link: `${responsiveWebBase}/build-a-personal-portfolio-webpage`,
|
||||
certSlug: 'responsive-web-design'
|
||||
certSlug: SuperBlocks.RespWebDesign
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: '561abd10cb81ac38a17513bc',
|
||||
title: 'JavaScript Algorithms and Data Structures',
|
||||
certSlug: 'javascript-algorithms-and-data-structures',
|
||||
certSlug: SuperBlocks.JsAlgoDataStruct,
|
||||
flag: 'isJsAlgoDataStructCert',
|
||||
projects: [
|
||||
{
|
||||
id: 'aaa48de84e1ecc7c742e1124',
|
||||
title: 'Palindrome Checker',
|
||||
link: `${jsAlgoBase}/palindrome-checker`,
|
||||
certSlug: 'javascript-algorithms-and-data-structures'
|
||||
certSlug: SuperBlocks.JsAlgoDataStruct
|
||||
},
|
||||
{
|
||||
id: 'a7f4d8f2483413a6ce226cac',
|
||||
title: 'Roman Numeral Converter',
|
||||
link: `${jsAlgoBase}/roman-numeral-converter`,
|
||||
certSlug: 'javascript-algorithms-and-data-structures'
|
||||
certSlug: SuperBlocks.JsAlgoDataStruct
|
||||
},
|
||||
{
|
||||
id: '56533eb9ac21ba0edf2244e2',
|
||||
title: 'Caesars Cipher',
|
||||
link: `${jsAlgoBase}/caesars-cipher`,
|
||||
certSlug: 'javascript-algorithms-and-data-structures'
|
||||
certSlug: SuperBlocks.JsAlgoDataStruct
|
||||
},
|
||||
{
|
||||
id: 'aff0395860f5d3034dc0bfc9',
|
||||
title: 'Telephone Number Validator',
|
||||
link: `${jsAlgoBase}/telephone-number-validator`,
|
||||
certSlug: 'javascript-algorithms-and-data-structures'
|
||||
certSlug: SuperBlocks.JsAlgoDataStruct
|
||||
},
|
||||
{
|
||||
id: 'aa2e6f85cab2ab736c9a9b24',
|
||||
title: 'Cash Register',
|
||||
link: `${jsAlgoBase}/cash-register`,
|
||||
certSlug: 'javascript-algorithms-and-data-structures'
|
||||
certSlug: SuperBlocks.JsAlgoDataStruct
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: '561acd10cb82ac38a17513bc',
|
||||
title: 'Front End Development Libraries',
|
||||
certSlug: 'front-end-development-libraries',
|
||||
certSlug: SuperBlocks.FrontEndDevLibs,
|
||||
flag: 'isFrontEndLibsCert',
|
||||
projects: [
|
||||
{
|
||||
id: 'bd7158d8c442eddfaeb5bd13',
|
||||
title: 'Build a Random Quote Machine',
|
||||
link: `${feLibsBase}/build-a-random-quote-machine`,
|
||||
certSlug: 'front-end-development-libraries'
|
||||
certSlug: SuperBlocks.FrontEndDevLibs
|
||||
},
|
||||
{
|
||||
id: 'bd7157d8c242eddfaeb5bd13',
|
||||
title: 'Build a Markdown Previewer',
|
||||
link: `${feLibsBase}/build-a-markdown-previewer`,
|
||||
certSlug: 'front-end-development-libraries'
|
||||
certSlug: SuperBlocks.FrontEndDevLibs
|
||||
},
|
||||
{
|
||||
id: '587d7dbc367417b2b2512bae',
|
||||
title: 'Build a Drum Machine',
|
||||
link: `${feLibsBase}/build-a-drum-machine`,
|
||||
certSlug: 'front-end-development-libraries'
|
||||
certSlug: SuperBlocks.FrontEndDevLibs
|
||||
},
|
||||
{
|
||||
id: 'bd7158d8c442eddfaeb5bd17',
|
||||
title: 'Build a JavaScript Calculator',
|
||||
link: `${feLibsBase}/build-a-javascript-calculator`,
|
||||
certSlug: 'front-end-development-libraries'
|
||||
certSlug: SuperBlocks.FrontEndDevLibs
|
||||
},
|
||||
{
|
||||
id: 'bd7158d8c442eddfaeb5bd0f',
|
||||
title: 'Build a 25 + 5 Clock',
|
||||
link: `${feLibsBase}/build-a-25--5-clock`,
|
||||
certSlug: 'front-end-development-libraries'
|
||||
certSlug: SuperBlocks.FrontEndDevLibs
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: '5a553ca864b52e1d8bceea14',
|
||||
title: 'Data Visualization',
|
||||
certSlug: 'data-visualization',
|
||||
certSlug: SuperBlocks.DataVis,
|
||||
flag: 'is2018DataVisCert',
|
||||
projects: [
|
||||
{
|
||||
id: 'bd7168d8c242eddfaeb5bd13',
|
||||
title: 'Visualize Data with a Bar Chart',
|
||||
link: `${dataVisBase}/visualize-data-with-a-bar-chart`,
|
||||
certSlug: 'data-visualization'
|
||||
certSlug: SuperBlocks.DataVis
|
||||
},
|
||||
{
|
||||
id: 'bd7178d8c242eddfaeb5bd13',
|
||||
title: 'Visualize Data with a Scatterplot Graph',
|
||||
link: `${dataVisBase}/visualize-data-with-a-scatterplot-graph`,
|
||||
certSlug: 'data-visualization'
|
||||
certSlug: SuperBlocks.DataVis
|
||||
},
|
||||
{
|
||||
id: 'bd7188d8c242eddfaeb5bd13',
|
||||
title: 'Visualize Data with a Heat Map',
|
||||
link: `${dataVisBase}/visualize-data-with-a-heat-map`,
|
||||
certSlug: 'data-visualization'
|
||||
certSlug: SuperBlocks.DataVis
|
||||
},
|
||||
{
|
||||
id: '587d7fa6367417b2b2512bbf',
|
||||
title: 'Visualize Data with a Choropleth Map',
|
||||
link: `${dataVisBase}/visualize-data-with-a-choropleth-map`,
|
||||
certSlug: 'data-visualization'
|
||||
certSlug: SuperBlocks.DataVis
|
||||
},
|
||||
{
|
||||
id: '587d7fa6367417b2b2512bc0',
|
||||
title: 'Visualize Data with a Treemap Diagram',
|
||||
link: `${dataVisBase}/visualize-data-with-a-treemap-diagram`,
|
||||
certSlug: 'data-visualization'
|
||||
certSlug: SuperBlocks.DataVis
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: '606243f50267e718b1e755f4',
|
||||
title: 'Relational Databases',
|
||||
certSlug: 'relational-databases',
|
||||
certSlug: SuperBlocks.RelationalDb,
|
||||
flag: 'isRelationalDatabasesCert',
|
||||
projects: [
|
||||
{
|
||||
id: '5f1a4ef5d5d6b5ab580fc6ae',
|
||||
title: 'Celestial Bodies Database',
|
||||
link: `${relationalDatabasesBase}/celestial-bodies-database`,
|
||||
superBlock: 'relational-databases'
|
||||
superBlock: SuperBlocks.RelationalDb
|
||||
},
|
||||
{
|
||||
id: '5f87ac112ae598023a42df1a',
|
||||
title: 'Salon Appointment Scheduler',
|
||||
link: `${relationalDatabasesBase}/salon-appointment-scheduler`,
|
||||
superBlock: 'relational-databases'
|
||||
superBlock: SuperBlocks.RelationalDb
|
||||
},
|
||||
{
|
||||
id: '5f9771307d4d22b9d2b75a94',
|
||||
title: 'World Cup Database',
|
||||
link: `${relationalDatabasesBase}/world-cup-database`,
|
||||
superBlock: 'relational-databases'
|
||||
superBlock: SuperBlocks.RelationalDb
|
||||
},
|
||||
{
|
||||
id: '602d9ff222201c65d2a019f2',
|
||||
title: 'Periodic Table Database',
|
||||
link: `${relationalDatabasesBase}/periodic-table-database`,
|
||||
superBlock: 'relational-databases'
|
||||
superBlock: SuperBlocks.RelationalDb
|
||||
},
|
||||
{
|
||||
id: '602da04c22201c65d2a019f4',
|
||||
title: 'Number Guessing Game',
|
||||
link: `${relationalDatabasesBase}/number-guessing-game`,
|
||||
superBlock: 'relational-databases'
|
||||
superBlock: SuperBlocks.RelationalDb
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: '561add10cb82ac38a17523bc',
|
||||
title: 'Back End Development and APIs',
|
||||
certSlug: 'back-end-development-and-apis',
|
||||
certSlug: SuperBlocks.BackEndDevApis,
|
||||
flag: 'isApisMicroservicesCert',
|
||||
projects: [
|
||||
{
|
||||
id: 'bd7158d8c443edefaeb5bdef',
|
||||
title: 'Timestamp Microservice',
|
||||
link: `${apiMicroBase}/timestamp-microservice`,
|
||||
certSlug: 'back-end-development-and-apis'
|
||||
certSlug: SuperBlocks.BackEndDevApis
|
||||
},
|
||||
{
|
||||
id: 'bd7158d8c443edefaeb5bdff',
|
||||
title: 'Request Header Parser Microservice',
|
||||
link: `${apiMicroBase}/request-header-parser-microservice`,
|
||||
certSlug: 'back-end-development-and-apis'
|
||||
certSlug: SuperBlocks.BackEndDevApis
|
||||
},
|
||||
{
|
||||
id: 'bd7158d8c443edefaeb5bd0e',
|
||||
title: 'URL Shortener Microservice',
|
||||
link: `${apiMicroBase}/url-shortener-microservice`,
|
||||
certSlug: 'back-end-development-and-apis'
|
||||
certSlug: SuperBlocks.BackEndDevApis
|
||||
},
|
||||
{
|
||||
id: '5a8b073d06fa14fcfde687aa',
|
||||
title: 'Exercise Tracker',
|
||||
link: `${apiMicroBase}/exercise-tracker`,
|
||||
certSlug: 'back-end-development-and-apis'
|
||||
certSlug: SuperBlocks.BackEndDevApis
|
||||
},
|
||||
{
|
||||
id: 'bd7158d8c443edefaeb5bd0f',
|
||||
title: 'File Metadata Microservice',
|
||||
link: `${apiMicroBase}/file-metadata-microservice`,
|
||||
certSlug: 'back-end-development-and-apis'
|
||||
certSlug: SuperBlocks.BackEndDevApis
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -333,7 +333,6 @@ class ShowClassic extends Component<ShowClassicProps, ShowClassicState> {
|
||||
containerRef={this.containerRef}
|
||||
description={description}
|
||||
editorRef={this.editorRef}
|
||||
hasEditableBoundaries={this.hasEditableBoundaries()}
|
||||
initialTests={tests}
|
||||
resizeProps={this.resizeProps}
|
||||
title={title}
|
||||
|
@ -1,12 +1,14 @@
|
||||
import { render, fireEvent, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
|
||||
import { SuperBlocks } from '../../../../../config/certification-settings';
|
||||
|
||||
import CompletionModalBody from './completion-modal-body';
|
||||
|
||||
const props = {
|
||||
block: 'basic-html-and-html5',
|
||||
completedPercent: Math.floor(Math.random() * 101),
|
||||
superBlock: 'responsive-web-design'
|
||||
superBlock: SuperBlocks.RespWebDesign
|
||||
};
|
||||
|
||||
describe('<CompletionModalBody />', () => {
|
||||
|
@ -10,6 +10,7 @@ import { configureAnchors } from 'react-scrollable-anchor';
|
||||
import { bindActionCreators, Dispatch } from 'redux';
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
import { SuperBlocks } from '../../../../config/certification-settings';
|
||||
import DonateModal from '../../components/Donation/DonationModal';
|
||||
import Login from '../../components/Header/components/Login';
|
||||
import Map from '../../components/Map';
|
||||
@ -172,7 +173,7 @@ const SuperBlockIntroductionPage = (props: SuperBlockProp) => {
|
||||
const blockDashedNames = uniq(nodesForSuperBlock.map(({ block }) => block));
|
||||
const i18nSuperBlock = t(`intro:${superBlock}.title`);
|
||||
const i18nTitle =
|
||||
superBlock === 'coding-interview-prep'
|
||||
superBlock === SuperBlocks.CodingInterviewPrep
|
||||
? i18nSuperBlock
|
||||
: t(`intro:misc-text.certification`, {
|
||||
cert: i18nSuperBlock
|
||||
@ -209,7 +210,7 @@ const SuperBlockIntroductionPage = (props: SuperBlockProp) => {
|
||||
{blockDashedName !== 'project-euler' ? <Spacer /> : null}
|
||||
</Fragment>
|
||||
))}
|
||||
{superBlock !== 'coding-interview-prep' && (
|
||||
{superBlock !== SuperBlocks.CodingInterviewPrep && (
|
||||
<div>
|
||||
<CertChallenge
|
||||
superBlock={superBlock}
|
||||
|
@ -1,4 +1,4 @@
|
||||
const certTypes = {
|
||||
export const certTypes = {
|
||||
frontEnd: 'isFrontEndCert',
|
||||
backEnd: 'isBackEndCert',
|
||||
dataVis: 'isDataVisCert',
|
||||
@ -17,7 +17,22 @@ const certTypes = {
|
||||
relationalDatabasesV8: 'isRelationalDatabasesCertV8'
|
||||
};
|
||||
|
||||
const certIds = {
|
||||
export enum SuperBlocks {
|
||||
RespWebDesign = 'responsive-web-design',
|
||||
JsAlgoDataStruct = 'javascript-algorithms-and-data-structures',
|
||||
FrontEndDevLibs = 'front-end-development-libraries',
|
||||
DataVis = 'data-visualization',
|
||||
RelationalDb = 'relational-databases',
|
||||
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'
|
||||
}
|
||||
|
||||
export const certIds = {
|
||||
legacyFrontEndChallengeId: '561add10cb82ac38a17513be',
|
||||
legacyBackEndChallengeId: '660add10cb82ac38a17513be',
|
||||
legacyDataVisId: '561add10cb82ac39a17513bc',
|
||||
@ -36,7 +51,7 @@ const certIds = {
|
||||
relationalDatabasesV8Id: '606243f50267e718b1e755f4'
|
||||
};
|
||||
|
||||
const completionHours = {
|
||||
export const completionHours = {
|
||||
[certTypes.frontEnd]: 400,
|
||||
[certTypes.backEnd]: 400,
|
||||
[certTypes.dataVis]: 400,
|
||||
@ -55,7 +70,7 @@ const completionHours = {
|
||||
[certTypes.relationalDatabasesV8]: 300
|
||||
};
|
||||
|
||||
const certSlugTypeMap = {
|
||||
export const certSlugTypeMap = {
|
||||
// legacy
|
||||
'legacy-front-end': certTypes.frontEnd,
|
||||
'legacy-back-end': certTypes.backEnd,
|
||||
@ -66,11 +81,11 @@ const certSlugTypeMap = {
|
||||
'full-stack': certTypes.fullStack,
|
||||
|
||||
// modern
|
||||
'responsive-web-design': certTypes.respWebDesign,
|
||||
'javascript-algorithms-and-data-structures': certTypes.jsAlgoDataStruct,
|
||||
'front-end-development-libraries': certTypes.frontEndDevLibs,
|
||||
'data-visualization': certTypes.dataVis2018,
|
||||
'back-end-development-and-apis': certTypes.apisMicroservices,
|
||||
[SuperBlocks.RespWebDesign]: certTypes.respWebDesign,
|
||||
[SuperBlocks.JsAlgoDataStruct]: certTypes.jsAlgoDataStruct,
|
||||
[SuperBlocks.FrontEndDevLibs]: certTypes.frontEndDevLibs,
|
||||
[SuperBlocks.DataVis]: certTypes.dataVis2018,
|
||||
[SuperBlocks.BackEndDevApis]: certTypes.apisMicroservices,
|
||||
'quality-assurance-v7': certTypes.qaV7,
|
||||
'information-security-v7': certTypes.infosecV7,
|
||||
'scientific-computing-with-python-v7': certTypes.sciCompPyV7,
|
||||
@ -79,7 +94,7 @@ const certSlugTypeMap = {
|
||||
'relational-databases-v8': certTypes.relationalDatabasesV8
|
||||
};
|
||||
|
||||
const superBlockCertTypeMap = {
|
||||
export const superBlockCertTypeMap = {
|
||||
// legacy
|
||||
'legacy-front-end': certTypes.frontEnd,
|
||||
'legacy-back-end': certTypes.backEnd,
|
||||
@ -88,20 +103,20 @@ const superBlockCertTypeMap = {
|
||||
'full-stack': certTypes.fullStack,
|
||||
|
||||
// modern
|
||||
'responsive-web-design': certTypes.respWebDesign,
|
||||
'javascript-algorithms-and-data-structures': certTypes.jsAlgoDataStruct,
|
||||
'front-end-development-libraries': certTypes.frontEndDevLibs,
|
||||
'data-visualization': certTypes.dataVis2018,
|
||||
'back-end-development-and-apis': certTypes.apisMicroservices,
|
||||
'quality-assurance': certTypes.qaV7,
|
||||
'information-security': certTypes.infosecV7,
|
||||
'scientific-computing-with-python': certTypes.sciCompPyV7,
|
||||
'data-analysis-with-python': certTypes.dataAnalysisPyV7,
|
||||
'machine-learning-with-python': certTypes.machineLearningPyV7,
|
||||
'relational-databases': certTypes.relationalDatabasesV8
|
||||
[SuperBlocks.RespWebDesign]: certTypes.respWebDesign,
|
||||
[SuperBlocks.JsAlgoDataStruct]: certTypes.jsAlgoDataStruct,
|
||||
[SuperBlocks.FrontEndDevLibs]: certTypes.frontEndDevLibs,
|
||||
[SuperBlocks.DataVis]: certTypes.dataVis2018,
|
||||
[SuperBlocks.BackEndDevApis]: certTypes.apisMicroservices,
|
||||
[SuperBlocks.QualityAssurance]: certTypes.qaV7,
|
||||
[SuperBlocks.InfoSec]: certTypes.infosecV7,
|
||||
[SuperBlocks.SciCompPy]: certTypes.sciCompPyV7,
|
||||
[SuperBlocks.DataAnalysisPy]: certTypes.dataAnalysisPyV7,
|
||||
[SuperBlocks.MachineLearningPy]: certTypes.machineLearningPyV7,
|
||||
[SuperBlocks.RelationalDb]: certTypes.relationalDatabasesV8
|
||||
};
|
||||
|
||||
const certTypeIdMap = {
|
||||
export const certTypeIdMap = {
|
||||
[certTypes.frontEnd]: certIds.legacyFrontEndChallengeId,
|
||||
[certTypes.backEnd]: certIds.legacyBackEndChallengeId,
|
||||
[certTypes.dataVis]: certIds.legacyDataVisId,
|
||||
@ -120,7 +135,7 @@ const certTypeIdMap = {
|
||||
[certTypes.relationalDatabasesV8]: certIds.relationalDatabasesV8Id
|
||||
};
|
||||
|
||||
const certTypeTitleMap = {
|
||||
export const certTypeTitleMap = {
|
||||
[certTypes.frontEnd]: 'Legacy Front End',
|
||||
[certTypes.backEnd]: 'Legacy Back End',
|
||||
[certTypes.dataVis]: 'Legacy Data Visualization',
|
||||
@ -139,11 +154,4 @@ const certTypeTitleMap = {
|
||||
[certTypes.relationalDatabasesV8]: 'Relational Databases'
|
||||
};
|
||||
|
||||
exports.oldDataVizId = '561add10cb82ac38a17513b3';
|
||||
exports.completionHours = completionHours;
|
||||
exports.certTypes = certTypes;
|
||||
exports.superBlockCertTypeMap = superBlockCertTypeMap;
|
||||
exports.certSlugTypeMap = certSlugTypeMap;
|
||||
exports.certIds = certIds;
|
||||
exports.certTypeIdMap = certTypeIdMap;
|
||||
exports.certTypeTitleMap = certTypeTitleMap;
|
||||
export const oldDataVizId = '561add10cb82ac38a17513b3';
|
@ -1,5 +1,5 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
import { SuperBlocks } from '../certification-settings';
|
||||
/*
|
||||
* List of languages with localizations enabled for builds.
|
||||
*
|
||||
@ -8,7 +8,7 @@
|
||||
* An error will be thrown if the CLIENT_LOCALE and CURRICULUM_LOCALE variables
|
||||
* from the .env file aren't found in their respective arrays below
|
||||
*/
|
||||
const availableLangs = {
|
||||
export const availableLangs = {
|
||||
client: [
|
||||
'english',
|
||||
'espanol',
|
||||
@ -35,61 +35,61 @@ const availableLangs = {
|
||||
* certifications which have not been audited & approved will fallback to
|
||||
* English equivalent.
|
||||
*/
|
||||
const auditedCerts = {
|
||||
export const auditedCerts = {
|
||||
espanol: [
|
||||
'responsive-web-design',
|
||||
'javascript-algorithms-and-data-structures',
|
||||
'front-end-development-libraries',
|
||||
'data-visualization',
|
||||
'back-end-development-and-apis'
|
||||
SuperBlocks.RespWebDesign,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.BackEndDevApis
|
||||
],
|
||||
chinese: [
|
||||
'responsive-web-design',
|
||||
'javascript-algorithms-and-data-structures',
|
||||
'front-end-development-libraries',
|
||||
'data-visualization',
|
||||
'back-end-development-and-apis',
|
||||
'quality-assurance',
|
||||
'scientific-computing-with-python',
|
||||
'data-analysis-with-python',
|
||||
'information-security',
|
||||
'machine-learning-with-python'
|
||||
SuperBlocks.RespWebDesign,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy
|
||||
],
|
||||
'chinese-traditional': [
|
||||
'responsive-web-design',
|
||||
'javascript-algorithms-and-data-structures',
|
||||
'front-end-development-libraries',
|
||||
'data-visualization',
|
||||
'back-end-development-and-apis',
|
||||
'quality-assurance',
|
||||
'scientific-computing-with-python',
|
||||
'data-analysis-with-python',
|
||||
'information-security',
|
||||
'machine-learning-with-python'
|
||||
SuperBlocks.RespWebDesign,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy
|
||||
],
|
||||
italian: [
|
||||
'responsive-web-design',
|
||||
'javascript-algorithms-and-data-structures',
|
||||
'front-end-development-libraries',
|
||||
'data-visualization',
|
||||
'back-end-development-and-apis',
|
||||
'quality-assurance',
|
||||
'scientific-computing-with-python',
|
||||
'data-analysis-with-python',
|
||||
'information-security',
|
||||
'machine-learning-with-python'
|
||||
SuperBlocks.RespWebDesign,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy
|
||||
],
|
||||
portuguese: [
|
||||
'responsive-web-design',
|
||||
'javascript-algorithms-and-data-structures',
|
||||
'front-end-development-libraries',
|
||||
'data-visualization',
|
||||
'back-end-development-and-apis',
|
||||
'quality-assurance',
|
||||
'scientific-computing-with-python',
|
||||
'data-analysis-with-python',
|
||||
'information-security',
|
||||
'machine-learning-with-python'
|
||||
SuperBlocks.RespWebDesign,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy
|
||||
]
|
||||
};
|
||||
|
||||
@ -101,7 +101,7 @@ const auditedCerts = {
|
||||
* string for the language to take advantage of available functionality.
|
||||
* Use a 639-1 code here https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
|
||||
*/
|
||||
const i18nextCodes = {
|
||||
export const i18nextCodes = {
|
||||
english: 'en',
|
||||
espanol: 'es',
|
||||
chinese: 'zh',
|
||||
@ -111,7 +111,7 @@ const i18nextCodes = {
|
||||
};
|
||||
|
||||
// These are for the language selector dropdown menu in the footer
|
||||
const langDisplayNames = {
|
||||
export const langDisplayNames = {
|
||||
english: 'English',
|
||||
espanol: 'Español',
|
||||
chinese: '中文(简体字)',
|
||||
@ -124,7 +124,7 @@ const langDisplayNames = {
|
||||
* There's an example in profile/components/Camper.js
|
||||
* List: https://github.com/unicode-cldr/cldr-dates-modern/tree/master/main
|
||||
*/
|
||||
const langCodes = {
|
||||
export const langCodes = {
|
||||
english: 'en-US',
|
||||
espanol: 'es-419',
|
||||
chinese: 'zh',
|
||||
@ -132,9 +132,3 @@ const langCodes = {
|
||||
italian: 'it',
|
||||
portuguese: 'pt-BR'
|
||||
};
|
||||
|
||||
exports.availableLangs = availableLangs;
|
||||
exports.i18nextCodes = i18nextCodes;
|
||||
exports.langDisplayNames = langDisplayNames;
|
||||
exports.langCodes = langCodes;
|
||||
exports.auditedCerts = auditedCerts;
|
@ -1,6 +1,8 @@
|
||||
import { SuperBlocks } from '../../config/certification-settings';
|
||||
|
||||
const certificationUrl = '/certification/developmentuser/responsive-web-design';
|
||||
const projects = {
|
||||
superBlock: 'responsive-web-design',
|
||||
superBlock: SuperBlocks.RespWebDesign,
|
||||
block: 'responsive-web-design-projects',
|
||||
challenges: [
|
||||
{
|
||||
|
@ -1,11 +1,12 @@
|
||||
/* global cy */
|
||||
import { SuperBlocks } from '../../../../config/certification-settings';
|
||||
|
||||
const selectors = {
|
||||
editor: '.react-monaco-editor-container'
|
||||
};
|
||||
|
||||
const pythonProjects = {
|
||||
superBlock: 'machine-learning-with-python',
|
||||
superBlock: SuperBlocks.MachineLearningPy,
|
||||
block: 'machine-learning-with-python-projects',
|
||||
challenges: [
|
||||
{
|
||||
@ -64,7 +65,7 @@ describe('project submission', () => {
|
||||
cy.login();
|
||||
cy.fixture('../../config/curriculum.json').then(curriculum => {
|
||||
const { challenges, meta } =
|
||||
curriculum['javascript-algorithms-and-data-structures'].blocks[
|
||||
curriculum[SuperBlocks.JsAlgoDataStruct].blocks[
|
||||
'javascript-algorithms-and-data-structures-projects'
|
||||
];
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { SuperBlocks } from '../../../../config/certification-settings';
|
||||
|
||||
const projects = {
|
||||
superBlock: 'responsive-web-design',
|
||||
superBlock: SuperBlocks.RespWebDesign,
|
||||
block: 'responsive-web-design-projects',
|
||||
challenges: [
|
||||
{
|
||||
|
1103
package-lock.json
generated
1103
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
27
package.json
27
package.json
@ -55,7 +55,7 @@
|
||||
"e2e:dev:watch": "start-test develop ':3000/status/ping|8000' cypress:dev:watch",
|
||||
"e2e:prd:run": "npm run build && start-test ':3000/status/ping|8000' cypress:dev:run",
|
||||
"e2e:prd:watch": "npm run build && start-test ':3000/status/ping|8000' cypress:dev:watch",
|
||||
"ensure-env": "cross-env DEBUG=fcc:* node ./tools/scripts/build/ensure-env.js",
|
||||
"ensure-env": "cross-env DEBUG=fcc:* tsc ./tools/scripts/build/ensure-env.ts && node ./tools/scripts/build/ensure-env.js",
|
||||
"format": "run-s format:eslint format:prettier",
|
||||
"format:eslint": "eslint . --fix",
|
||||
"format:prettier": "prettier --write .",
|
||||
@ -64,7 +64,7 @@
|
||||
"lint": "npm-run-all ensure-env -p lint:*",
|
||||
"lint:challenges": "cd ./curriculum && npm run lint",
|
||||
"lint:js": "eslint --max-warnings 0 .",
|
||||
"lint:ts": "tsc -p client && tsc -p tools/ui-components",
|
||||
"lint:ts": "tsc && tsc -p tools/ui-components && tsc -p tools/scripts/build",
|
||||
"lint:prettier": "prettier --list-different .",
|
||||
"postinstall": "npm run bootstrap",
|
||||
"seed": "cross-env DEBUG=fcc:* node ./tools/scripts/seed/seedAuthUser",
|
||||
@ -101,6 +101,29 @@
|
||||
"@testing-library/dom": "8.11.1",
|
||||
"@testing-library/jest-dom": "5.15.0",
|
||||
"@testing-library/user-event": "13.5.0",
|
||||
"@types/chai": "^4.2.22",
|
||||
"@types/inquirer": "^8.1.3",
|
||||
"@types/jest": "^27.0.2",
|
||||
"@types/loadable__component": "^5.13.4",
|
||||
"@types/lodash-es": "^4.17.5",
|
||||
"@types/node": "^16.11.7",
|
||||
"@types/prismjs": "^1.16.6",
|
||||
"@types/psl": "^1.1.0",
|
||||
"@types/reach__router": "^1.3.9",
|
||||
"@types/react": "^17.0.35",
|
||||
"@types/react-dom": "^17.0.11",
|
||||
"@types/react-helmet": "^6.1.4",
|
||||
"@types/react-instantsearch-dom": "^6.12.0",
|
||||
"@types/react-monaco-editor": "^0.16.0",
|
||||
"@types/react-redux": "^7.1.20",
|
||||
"@types/react-responsive": "^8.0.4",
|
||||
"@types/react-spinkit": "^3.0.7",
|
||||
"@types/react-test-renderer": "^17.0.1",
|
||||
"@types/react-transition-group": "^4.4.4",
|
||||
"@types/redux-actions": "^2.6.2",
|
||||
"@types/sanitize-html": "^2.5.0",
|
||||
"@types/store": "^2.0.2",
|
||||
"@types/validator": "^13.7.0",
|
||||
"@typescript-eslint/eslint-plugin": "4.33.0",
|
||||
"@typescript-eslint/parser": "4.33.0",
|
||||
"babel-eslint": "10.1.0",
|
||||
|
@ -4,25 +4,10 @@ import path from 'path';
|
||||
import { prompt } from 'inquirer';
|
||||
import { format } from 'prettier';
|
||||
|
||||
import { SuperBlocks } from '../../config/certification-settings';
|
||||
import { blockNameify } from '../../utils/block-nameify';
|
||||
import { createStepFile } from './utils.js';
|
||||
|
||||
const superBlocks = [
|
||||
'responsive-web-design',
|
||||
'javascript-algorithms-and-data-structures',
|
||||
'front-end-development-libraries',
|
||||
'data-visualization',
|
||||
'back-end-development-and-apis',
|
||||
'quality-assurance',
|
||||
'scientific-computing-with-python',
|
||||
'data-analysis-with-python',
|
||||
'information-security',
|
||||
'machine-learning-with-python',
|
||||
'coding-interview-prep'
|
||||
] as const;
|
||||
|
||||
type SuperBlock = typeof superBlocks[number];
|
||||
|
||||
const helpCategories = ['HTML-CSS', 'JavaScript', 'Python'] as const;
|
||||
|
||||
type BlockInfo = {
|
||||
@ -34,7 +19,7 @@ type SuperBlockInfo = {
|
||||
blocks: Record<string, BlockInfo>;
|
||||
};
|
||||
|
||||
type IntroJson = Record<SuperBlock, SuperBlockInfo>;
|
||||
type IntroJson = Record<SuperBlocks, SuperBlockInfo>;
|
||||
|
||||
type Meta = {
|
||||
name: string;
|
||||
@ -51,7 +36,7 @@ type Meta = {
|
||||
};
|
||||
|
||||
async function createProject(
|
||||
superBlock: SuperBlock,
|
||||
superBlock: SuperBlocks,
|
||||
block: string,
|
||||
helpCategory: string,
|
||||
order: number,
|
||||
@ -86,7 +71,7 @@ async function createProject(
|
||||
}
|
||||
|
||||
async function updateIntroJson(
|
||||
superBlock: SuperBlock,
|
||||
superBlock: SuperBlocks,
|
||||
block: string,
|
||||
title: string
|
||||
) {
|
||||
@ -138,7 +123,7 @@ async function updateBlockNames(block: string, title: string) {
|
||||
}
|
||||
|
||||
async function createMetaJson(
|
||||
superBlock: SuperBlock,
|
||||
superBlock: SuperBlocks,
|
||||
block: string,
|
||||
title: string,
|
||||
order: number,
|
||||
@ -149,7 +134,7 @@ async function createMetaJson(
|
||||
newMeta.name = title;
|
||||
newMeta.dashedName = block;
|
||||
newMeta.order = order;
|
||||
newMeta.superOrder = superBlocks.indexOf(superBlock) + 1;
|
||||
newMeta.superOrder = Object.values(SuperBlocks).indexOf(superBlock) + 1;
|
||||
newMeta.superBlock = superBlock;
|
||||
newMeta.challengeOrder = [[challengeId, 'Step 1']];
|
||||
const newMetaDir = path.resolve(metaDir, block);
|
||||
@ -190,10 +175,10 @@ This is a test for the new project-based curriculum.
|
||||
}
|
||||
|
||||
async function createFirstChallenge(
|
||||
superBlock: SuperBlock,
|
||||
superBlock: SuperBlocks,
|
||||
block: string
|
||||
): Promise<string> {
|
||||
const superBlockId = (superBlocks.indexOf(superBlock) + 1)
|
||||
const superBlockId = (Object.values(SuperBlocks).indexOf(superBlock) + 1)
|
||||
.toString()
|
||||
.padStart(2, '0');
|
||||
const newChallengeDir = path.resolve(
|
||||
@ -234,9 +219,9 @@ prompt([
|
||||
{
|
||||
name: 'superBlock',
|
||||
message: 'Which certification does this belong to?',
|
||||
default: 'responsive-web-design',
|
||||
default: SuperBlocks.RespWebDesign,
|
||||
type: 'list',
|
||||
choices: superBlocks
|
||||
choices: SuperBlocks
|
||||
},
|
||||
{
|
||||
name: 'block',
|
||||
|
@ -23,8 +23,6 @@
|
||||
"create-project": "ts-node create-project"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/inquirer": "7.3.3",
|
||||
"@types/node": "16.11.7",
|
||||
"bson-objectid": "2.0.1",
|
||||
"cross-env": "7.0.3",
|
||||
"gray-matter": "4.0.3",
|
||||
|
@ -1,12 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"noEmit": true,
|
||||
"strict": true,
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
}
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
const { spawn } = require('child_process');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
import { spawn } from 'child_process';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
const { availableLangs } = require('../../../config/i18n/all-langs');
|
||||
const env = require('../../../config/read-env');
|
||||
import { availableLangs } from '../../../config/i18n/all-langs';
|
||||
|
||||
// eslint-disable-next-line
|
||||
const env = require('../../../config/read-env.js');
|
||||
|
||||
const globalConfigPath = path.resolve(__dirname, '../../../config');
|
||||
|
||||
@ -11,21 +13,25 @@ const { FREECODECAMP_NODE_ENV } = process.env;
|
||||
|
||||
function checkClientLocale() {
|
||||
if (!availableLangs.client.includes(process.env.CLIENT_LOCALE)) {
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
throw Error(`
|
||||
|
||||
CLIENT_LOCALE, ${process.env.CLIENT_LOCALE}, is not an available language in config/i18n/all-langs.js
|
||||
|
||||
`);
|
||||
/* eslint-enable @typescript-eslint/restrict-template-expressions */
|
||||
}
|
||||
}
|
||||
|
||||
function checkCurriculumLocale() {
|
||||
if (!availableLangs.curriculum.includes(process.env.CURRICULUM_LOCALE)) {
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
throw Error(`
|
||||
|
||||
CURRICULUM_LOCALE, ${process.env.CURRICULUM_LOCALE}, is not an available language in config/i18n/all-langs.js
|
||||
|
||||
`);
|
||||
/* eslint-enable @typescript-eslint/restrict-template-expressions */
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,6 +63,7 @@ if (FREECODECAMP_NODE_ENV !== 'development') {
|
||||
expectedVariables.sort();
|
||||
receivedvariables.sort();
|
||||
if (expectedVariables.length !== receivedvariables.length) {
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
throw Error(`
|
||||
|
||||
Env. variable validation failed. Make sure these keys are used and configured.
|
||||
@ -71,9 +78,11 @@ if (FREECODECAMP_NODE_ENV !== 'development') {
|
||||
)}
|
||||
|
||||
`);
|
||||
/* eslint-enable @typescript-eslint/restrict-template-expressions */
|
||||
}
|
||||
|
||||
for (const key of expectedVariables) {
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
if (typeof env[key] === 'undefined' || env[key] === null) {
|
||||
throw Error(`
|
||||
|
||||
@ -86,16 +95,16 @@ if (FREECODECAMP_NODE_ENV !== 'development') {
|
||||
if (env['environment'] !== 'production')
|
||||
throw Error(`
|
||||
|
||||
Production environment should be 'production'
|
||||
Production environment should be 'production'
|
||||
|
||||
`);
|
||||
`);
|
||||
|
||||
if (env['showUpcomingChanges'])
|
||||
throw Error(`
|
||||
|
||||
SHOW_UPCOMING_CHANGES should never be 'true' in production
|
||||
SHOW_UPCOMING_CHANGES should never be 'true' in production
|
||||
|
||||
`);
|
||||
`);
|
||||
|
||||
checkClientLocale();
|
||||
checkCurriculumLocale();
|
||||
@ -103,8 +112,10 @@ if (FREECODECAMP_NODE_ENV !== 'development') {
|
||||
checkClientLocale();
|
||||
checkCurriculumLocale();
|
||||
if (fs.existsSync(`${globalConfigPath}/env.json`)) {
|
||||
// eslint-disable-next-line
|
||||
const { showUpcomingChanges } = require(`${globalConfigPath}/env.json`);
|
||||
if (env['showUpcomingChanges'] !== showUpcomingChanges) {
|
||||
/* eslint-enable @typescript-eslint/no-unsafe-member-access */
|
||||
console.log(
|
||||
'SHOW_UPCOMING_CHANGES value has changed, cleaning client cache.'
|
||||
);
|
6
tools/scripts/build/tsconfig.json
Normal file
6
tools/scripts/build/tsconfig.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"typeRoots": ["../../node_modules/@types"],
|
||||
"types": ["node"]
|
||||
}
|
||||
}
|
@ -20,7 +20,6 @@
|
||||
"homepage": "https://github.com/freeCodeCamp/freeCodeCamp#readme",
|
||||
"dependencies": {
|
||||
"@babel/preset-typescript": "7.16.0",
|
||||
"@types/jest": "27.0.2",
|
||||
"@types/node": "16.11.7",
|
||||
"@types/react": "17.0.33",
|
||||
"@types/react-dom": "17.0.11",
|
||||
@ -39,18 +38,20 @@
|
||||
"@storybook/addon-links": "6.3.12",
|
||||
"@storybook/addon-postcss": "2.0.0",
|
||||
"@storybook/react": "6.3.12",
|
||||
"@testing-library/jest-dom": "^5.15.0",
|
||||
"@testing-library/react": "12.1.2",
|
||||
"@types/jest": "^27.0.2",
|
||||
"autoprefixer": "10.4.0",
|
||||
"babel-loader": "8.2.3",
|
||||
"babel-plugin-transform-react-remove-prop-types": "0.4.24",
|
||||
"cross-env": "7.0.3",
|
||||
"postcss": "8.3.11",
|
||||
"postcss-import": "14.0.2",
|
||||
"tailwindcss": "2.2.19",
|
||||
"rimraf": "3.0.2",
|
||||
"rollup": "2.60.0",
|
||||
"rollup-plugin-postcss": "4.0.1",
|
||||
"rollup-plugin-terser": "7.0.2"
|
||||
"rollup-plugin-terser": "7.0.2",
|
||||
"tailwindcss": "2.2.19"
|
||||
},
|
||||
"scripts": {
|
||||
"storybook": "start-storybook -p 6006",
|
||||
|
@ -8,6 +8,7 @@
|
||||
"esModuleInterop": true,
|
||||
"moduleResolution": "node",
|
||||
"strict": true,
|
||||
"noEmit": true
|
||||
"noEmit": true,
|
||||
"typeRoots": ["./node_modules/@types"]
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,13 @@
|
||||
{
|
||||
"include": ["./i18n/**/*", "./plugins/**/*", "./src/**/*", "./utils/**/*"],
|
||||
"include": [
|
||||
"client/i18n/**/*",
|
||||
"client/plugins/**/*",
|
||||
"client/src/**/*",
|
||||
"client/utils/**/*",
|
||||
"tools/challenge-helper-scripts/**/*",
|
||||
"config/certification-settings.ts",
|
||||
"config/i18n/**/*"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"lib": ["WebWorker", "DOM", "DOM.Iterable"],
|
||||
"target": "es2020",
|
Reference in New Issue
Block a user