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