diff --git a/client/src/templates/Challenges/classic/desktop-layout.tsx b/client/src/templates/Challenges/classic/desktop-layout.tsx
index 27e4d60b749..c76212c583f 100644
--- a/client/src/templates/Challenges/classic/desktop-layout.tsx
+++ b/client/src/templates/Challenges/classic/desktop-layout.tsx
@@ -240,17 +240,15 @@ const DesktopLayout = (props: DesktopLayoutProps): JSX.Element => {
const isMultifileProject =
challengeType === challengeTypes.multifileCertProject ||
challengeType === challengeTypes.multifilePythonCertProject ||
- challengeType == challengeTypes.lab;
+ challengeType === challengeTypes.lab ||
+ challengeType === challengeTypes.jsLab;
+ const isProjectStyle = projectBasedChallenge || isMultifileProject;
const displayPreviewPane = hasPreview && showPreviewPane;
const displayPreviewPortal = hasPreview && showPreviewPortal;
const displayNotes = projectBasedChallenge ? showNotes && !!notes : false;
- const displayEditorConsole = !(projectBasedChallenge || isMultifileProject)
- ? true
- : false;
- const displayPreviewConsole =
- (projectBasedChallenge || isMultifileProject) && showConsole;
- const hasVerticalResizableCodePane =
- !isMultifileProject && !projectBasedChallenge;
+ const displayEditorConsole = !isProjectStyle;
+ const displayPreviewConsole = !displayEditorConsole && showConsole;
+
const {
codePane,
editorPane,
@@ -265,7 +263,7 @@ const DesktopLayout = (props: DesktopLayoutProps): JSX.Element => {
return (
- {(projectBasedChallenge || isMultifileProject) && (
+ {isProjectStyle && (
{
>
diff --git a/client/src/templates/Challenges/classic/show.tsx b/client/src/templates/Challenges/classic/show.tsx
index 8d95496020b..73eef8f2ac2 100644
--- a/client/src/templates/Challenges/classic/show.tsx
+++ b/client/src/templates/Challenges/classic/show.tsx
@@ -63,7 +63,7 @@ import { preloadPage } from '../../../../utils/gatsby/page-loading';
import envData from '../../../../config/env.json';
import ToolPanel from '../components/tool-panel';
import { getChallengePaths } from '../utils/challenge-paths';
-import { isJavaScriptChallenge } from '../utils/build';
+import { challengeHasPreview, isJavaScriptChallenge } from '../utils/build';
import { XtermTerminal } from './xterm';
import MultifileEditor from './multifile-editor';
import DesktopLayout from './desktop-layout';
@@ -242,17 +242,7 @@ function ShowClassic({
)}: ${title}`;
const windowTitle = `${blockNameTitle} | freeCodeCamp.org`;
const openConsole = isJavaScriptChallenge({ challengeType });
- // TODO: show preview should NOT be computed like this. That determination is
- // made during the build (at least twice!). It should be either a prop or
- // computed from challengeType
- const showPreview = [
- challengeTypes.html,
- challengeTypes.modern,
- challengeTypes.multifileCertProject,
- challengeTypes.multifilePythonCertProject,
- challengeTypes.python,
- challengeTypes.lab
- ].includes(challengeType);
+ const hasPreview = challengeHasPreview({ challengeType });
const getLayoutState = () => {
const reflexLayout = store.get(REFLEX_LAYOUT) as ReflexLayout | null;
@@ -463,7 +453,7 @@ function ShowClassic({
isUsingKeyboardInTablist: usingKeyboardInTablist
})}
hasEditableBoundaries={hasEditableBoundaries}
- hasPreview={showPreview}
+ hasPreview={hasPreview}
instructions={renderInstructionsPanel({
toolPanel: null,
hasDemo: demoType === 'onClick'
@@ -498,7 +488,7 @@ function ShowClassic({
isUsingKeyboardInTablist: usingKeyboardInTablist
})}
hasEditableBoundaries={hasEditableBoundaries}
- hasPreview={showPreview}
+ hasPreview={hasPreview}
instructions={renderInstructionsPanel({
toolPanel: ,
hasDemo: demoType === 'onClick'
diff --git a/client/src/templates/Challenges/redux/selectors.js b/client/src/templates/Challenges/redux/selectors.js
index 296cdacd360..437630d1fcb 100644
--- a/client/src/templates/Challenges/redux/selectors.js
+++ b/client/src/templates/Challenges/redux/selectors.js
@@ -90,7 +90,8 @@ export const challengeDataSelector = state => {
challengeType === challengeTypes.python ||
challengeType === challengeTypes.lab ||
challengeType === challengeTypes.js ||
- challengeType === challengeTypes.jsProject
+ challengeType === challengeTypes.jsProject ||
+ challengeType === challengeTypes.jsLab
) {
const { required = [], template = '' } = challengeMetaSelector(state);
challengeData = {
diff --git a/client/src/templates/Challenges/utils/build.ts b/client/src/templates/Challenges/utils/build.ts
index 8bbf1b9952a..17d18ad40c5 100644
--- a/client/src/templates/Challenges/utils/build.ts
+++ b/client/src/templates/Challenges/utils/build.ts
@@ -3,7 +3,7 @@ import frameRunnerData from '../../../../../client/config/browser-scripts/frame-
import jsTestEvaluatorData from '../../../../../client/config/browser-scripts/test-evaluator.json';
import pyTestEvaluatorData from '../../../../../client/config/browser-scripts/python-test-evaluator.json';
-import { ChallengeFile, ChallengeMeta } from '../../../redux/prop-types';
+import type { ChallengeFile } from '../../../redux/prop-types';
import { concatHtml } from '../rechallenge/builders';
import {
getTransformers,
@@ -107,7 +107,8 @@ export const buildFunctions = {
[challengeTypes.colab]: buildBackendChallenge,
[challengeTypes.python]: buildPythonChallenge,
[challengeTypes.multifilePythonCertProject]: buildPythonChallenge,
- [challengeTypes.lab]: buildDOMChallenge
+ [challengeTypes.lab]: buildDOMChallenge,
+ [challengeTypes.jsLab]: buildJSChallenge
};
export function canBuildChallenge(challengeData: BuildChallengeData): boolean {
@@ -393,7 +394,11 @@ export function updateProjectPreview(
}
}
-export function challengeHasPreview({ challengeType }: ChallengeMeta): boolean {
+export function challengeHasPreview({
+ challengeType
+}: {
+ challengeType: number;
+}): boolean {
return (
challengeType === challengeTypes.html ||
challengeType === challengeTypes.modern ||
@@ -411,6 +416,7 @@ export function isJavaScriptChallenge({
}): boolean {
return (
challengeType === challengeTypes.js ||
- challengeType === challengeTypes.jsProject
+ challengeType === challengeTypes.jsProject ||
+ challengeType === challengeTypes.jsLab
);
}
diff --git a/client/src/utils/curriculum-layout.ts b/client/src/utils/curriculum-layout.ts
index 4f2cfb9066d..0459aed67ee 100644
--- a/client/src/utils/curriculum-layout.ts
+++ b/client/src/utils/curriculum-layout.ts
@@ -34,7 +34,8 @@ const projectBasedChallengeTypes = [
challengeTypes.exam,
challengeTypes.codeAllyPractice,
challengeTypes.multifilePythonCertProject,
- challengeTypes.lab
+ challengeTypes.lab,
+ challengeTypes.jsLab
];
export const isProjectBased = (
diff --git a/curriculum/challenges/english/25-front-end-development/lab-bank-account-manager/6718d2d59337c822ecb697ff.md b/curriculum/challenges/english/25-front-end-development/lab-bank-account-manager/6718d2d59337c822ecb697ff.md
index ce0428aca02..a1bf4b7b2ea 100644
--- a/curriculum/challenges/english/25-front-end-development/lab-bank-account-manager/6718d2d59337c822ecb697ff.md
+++ b/curriculum/challenges/english/25-front-end-development/lab-bank-account-manager/6718d2d59337c822ecb697ff.md
@@ -1,7 +1,7 @@
---
id: 6718d2d59337c822ecb697ff
title: Build a Bank Account Management Program
-challengeType: 25
+challengeType: 26
dashedName: build-a-bank-account-management-program
---
diff --git a/curriculum/challenges/english/25-front-end-development/lab-book-organizer/67172b43f84bcd2dec238a3d.md b/curriculum/challenges/english/25-front-end-development/lab-book-organizer/67172b43f84bcd2dec238a3d.md
index 4b3b9fc7a08..419f388391e 100644
--- a/curriculum/challenges/english/25-front-end-development/lab-book-organizer/67172b43f84bcd2dec238a3d.md
+++ b/curriculum/challenges/english/25-front-end-development/lab-book-organizer/67172b43f84bcd2dec238a3d.md
@@ -1,7 +1,7 @@
---
id: 67172b43f84bcd2dec238a3d
title: Build a Book Organizer
-challengeType: 25
+challengeType: 26
dashedName: build-a-book-organizer
---
diff --git a/curriculum/challenges/english/25-front-end-development/lab-date-conversion/66f686b8ebdb982fa8e14330.md b/curriculum/challenges/english/25-front-end-development/lab-date-conversion/66f686b8ebdb982fa8e14330.md
index a1acbe0bab4..95a76e95250 100644
--- a/curriculum/challenges/english/25-front-end-development/lab-date-conversion/66f686b8ebdb982fa8e14330.md
+++ b/curriculum/challenges/english/25-front-end-development/lab-date-conversion/66f686b8ebdb982fa8e14330.md
@@ -1,7 +1,7 @@
---
id: 66f686b8ebdb982fa8e14330
title: Build a Date Conversion Program
-challengeType: 25
+challengeType: 26
dashedName: lab-date-conversion
---
diff --git a/curriculum/challenges/english/25-front-end-development/lab-email-masker/66b205e6eacba4c4e54ea434.md b/curriculum/challenges/english/25-front-end-development/lab-email-masker/66b205e6eacba4c4e54ea434.md
index 3ed635dcef0..57a3d0cc78e 100644
--- a/curriculum/challenges/english/25-front-end-development/lab-email-masker/66b205e6eacba4c4e54ea434.md
+++ b/curriculum/challenges/english/25-front-end-development/lab-email-masker/66b205e6eacba4c4e54ea434.md
@@ -1,7 +1,7 @@
---
id: 66b205e6eacba4c4e54ea434
title: Build an Email Masker
-challengeType: 25
+challengeType: 26
dashedName: build-an-email-masker
---
diff --git a/curriculum/challenges/english/25-front-end-development/lab-factorial-calculator/66c07238b01053abaf812065.md b/curriculum/challenges/english/25-front-end-development/lab-factorial-calculator/66c07238b01053abaf812065.md
index b46f23aa404..e7c816ac494 100644
--- a/curriculum/challenges/english/25-front-end-development/lab-factorial-calculator/66c07238b01053abaf812065.md
+++ b/curriculum/challenges/english/25-front-end-development/lab-factorial-calculator/66c07238b01053abaf812065.md
@@ -1,7 +1,7 @@
---
id: 66c07238b01053abaf812065
title: Build a Factorial Calculator
-challengeType: 25
+challengeType: 26
dashedName: build-a-factorial-calculator
---
diff --git a/curriculum/challenges/english/25-front-end-development/lab-fortune-teller/66c06d618d075c7f7f1b890a.md b/curriculum/challenges/english/25-front-end-development/lab-fortune-teller/66c06d618d075c7f7f1b890a.md
index 3e2b9a0f1e4..35251457d52 100644
--- a/curriculum/challenges/english/25-front-end-development/lab-fortune-teller/66c06d618d075c7f7f1b890a.md
+++ b/curriculum/challenges/english/25-front-end-development/lab-fortune-teller/66c06d618d075c7f7f1b890a.md
@@ -1,7 +1,7 @@
---
id: 66c06d618d075c7f7f1b890a
title: Build a Fortune Teller
-challengeType: 25
+challengeType: 26
dashedName: build-a-fortune-teller
---
diff --git a/curriculum/challenges/english/25-front-end-development/lab-gradebook-app/66bb6a9c2dd58b73cd759034.md b/curriculum/challenges/english/25-front-end-development/lab-gradebook-app/66bb6a9c2dd58b73cd759034.md
index bb36233ef04..0191dd3a765 100644
--- a/curriculum/challenges/english/25-front-end-development/lab-gradebook-app/66bb6a9c2dd58b73cd759034.md
+++ b/curriculum/challenges/english/25-front-end-development/lab-gradebook-app/66bb6a9c2dd58b73cd759034.md
@@ -1,7 +1,7 @@
---
id: 66bb6a9c2dd58b73cd759034
title: Build a Gradebook App
-challengeType: 25
+challengeType: 26
dashedName: build-a-gradebook-app
---
diff --git a/curriculum/challenges/english/25-front-end-development/lab-inventory-management-program/66d75dd0aa65a71600dc669b.md b/curriculum/challenges/english/25-front-end-development/lab-inventory-management-program/66d75dd0aa65a71600dc669b.md
index 4d809d6a105..7909a852af1 100644
--- a/curriculum/challenges/english/25-front-end-development/lab-inventory-management-program/66d75dd0aa65a71600dc669b.md
+++ b/curriculum/challenges/english/25-front-end-development/lab-inventory-management-program/66d75dd0aa65a71600dc669b.md
@@ -1,7 +1,7 @@
---
id: 66d75dd0aa65a71600dc669b
title: Build an Inventory Management Program
-challengeType: 25
+challengeType: 26
dashedName: build-an-inventory-management-program
---
diff --git a/curriculum/challenges/english/25-front-end-development/lab-javascript-trivia-bot/66ed41f912d0bb1dc62da5dd.md b/curriculum/challenges/english/25-front-end-development/lab-javascript-trivia-bot/66ed41f912d0bb1dc62da5dd.md
index da19232a415..b6e841b64ba 100644
--- a/curriculum/challenges/english/25-front-end-development/lab-javascript-trivia-bot/66ed41f912d0bb1dc62da5dd.md
+++ b/curriculum/challenges/english/25-front-end-development/lab-javascript-trivia-bot/66ed41f912d0bb1dc62da5dd.md
@@ -1,7 +1,7 @@
---
id: 66ed41f912d0bb1dc62da5dd
title: Build a JavaScript Trivia Bot
-challengeType: 25
+challengeType: 26
dashedName: lab-javascript-trivia-bot
---
diff --git a/curriculum/challenges/english/25-front-end-development/lab-leap-year-calculator/66c06fad3475cd92421b9ac2.md b/curriculum/challenges/english/25-front-end-development/lab-leap-year-calculator/66c06fad3475cd92421b9ac2.md
index b14acff58a3..10d360d2016 100644
--- a/curriculum/challenges/english/25-front-end-development/lab-leap-year-calculator/66c06fad3475cd92421b9ac2.md
+++ b/curriculum/challenges/english/25-front-end-development/lab-leap-year-calculator/66c06fad3475cd92421b9ac2.md
@@ -1,7 +1,7 @@
---
id: 66c06fad3475cd92421b9ac2
title: Build a Leap Year Calculator
-challengeType: 25
+challengeType: 26
dashedName: build-a-leap-year-calculator
---
diff --git a/curriculum/challenges/english/25-front-end-development/lab-lunch-picker-program/66db529d37ad966480ebb633.md b/curriculum/challenges/english/25-front-end-development/lab-lunch-picker-program/66db529d37ad966480ebb633.md
index 93455410c46..f9003be5a93 100644
--- a/curriculum/challenges/english/25-front-end-development/lab-lunch-picker-program/66db529d37ad966480ebb633.md
+++ b/curriculum/challenges/english/25-front-end-development/lab-lunch-picker-program/66db529d37ad966480ebb633.md
@@ -1,7 +1,7 @@
---
id: 66db529d37ad966480ebb633
title: Build a Lunch Picker Program
-challengeType: 25
+challengeType: 26
dashedName: build-a-lunch-picker-program
---
diff --git a/curriculum/challenges/english/25-front-end-development/lab-password-generator/66f53dc2c5bd6a11d6c3282f.md b/curriculum/challenges/english/25-front-end-development/lab-password-generator/66f53dc2c5bd6a11d6c3282f.md
index 99d14778b06..229c3697892 100644
--- a/curriculum/challenges/english/25-front-end-development/lab-password-generator/66f53dc2c5bd6a11d6c3282f.md
+++ b/curriculum/challenges/english/25-front-end-development/lab-password-generator/66f53dc2c5bd6a11d6c3282f.md
@@ -1,7 +1,7 @@
---
id: 66f53dc2c5bd6a11d6c3282f
title: Build a Password Generator App
-challengeType: 25
+challengeType: 26
dashedName: lab-password-generator
---
diff --git a/curriculum/challenges/english/25-front-end-development/lab-permutation-generator/66fe4f33a2cc9b33f4d5cd9b.md b/curriculum/challenges/english/25-front-end-development/lab-permutation-generator/66fe4f33a2cc9b33f4d5cd9b.md
index 634ae874d81..d20d49d8f16 100644
--- a/curriculum/challenges/english/25-front-end-development/lab-permutation-generator/66fe4f33a2cc9b33f4d5cd9b.md
+++ b/curriculum/challenges/english/25-front-end-development/lab-permutation-generator/66fe4f33a2cc9b33f4d5cd9b.md
@@ -1,7 +1,7 @@
---
id: 66fe4f33a2cc9b33f4d5cd9b
title: Build a Permutation Generator
-challengeType: 25
+challengeType: 26
dashedName: build-a-permutation-generator
---
diff --git a/curriculum/challenges/english/25-front-end-development/lab-project-idea-board/67051431a73f1ca25d9a6f25.md b/curriculum/challenges/english/25-front-end-development/lab-project-idea-board/67051431a73f1ca25d9a6f25.md
index ccb8b77af50..7682b2cb74c 100644
--- a/curriculum/challenges/english/25-front-end-development/lab-project-idea-board/67051431a73f1ca25d9a6f25.md
+++ b/curriculum/challenges/english/25-front-end-development/lab-project-idea-board/67051431a73f1ca25d9a6f25.md
@@ -1,7 +1,7 @@
---
id: 67051431a73f1ca25d9a6f25
title: Build a Project Idea Board
-challengeType: 25
+challengeType: 26
dashedName: build-a-project-idea-board
---
diff --git a/curriculum/challenges/english/25-front-end-development/lab-pyramid-generator/66f2836c459cfb16ae76f24f.md b/curriculum/challenges/english/25-front-end-development/lab-pyramid-generator/66f2836c459cfb16ae76f24f.md
index 42c56dd82c1..00db35ff7f0 100644
--- a/curriculum/challenges/english/25-front-end-development/lab-pyramid-generator/66f2836c459cfb16ae76f24f.md
+++ b/curriculum/challenges/english/25-front-end-development/lab-pyramid-generator/66f2836c459cfb16ae76f24f.md
@@ -1,7 +1,7 @@
---
id: 66f2836c459cfb16ae76f24f
title: Build a Pyramid Generator
-challengeType: 25
+challengeType: 26
dashedName: lab-pyramid-generator
---
diff --git a/curriculum/challenges/english/25-front-end-development/lab-quiz-game/66f17db06803d11a1bd19a20.md b/curriculum/challenges/english/25-front-end-development/lab-quiz-game/66f17db06803d11a1bd19a20.md
index 0e91763e5c6..8786a1bba60 100644
--- a/curriculum/challenges/english/25-front-end-development/lab-quiz-game/66f17db06803d11a1bd19a20.md
+++ b/curriculum/challenges/english/25-front-end-development/lab-quiz-game/66f17db06803d11a1bd19a20.md
@@ -1,7 +1,7 @@
---
id: 66f17db06803d11a1bd19a20
title: Build a Quiz Game
-challengeType: 25
+challengeType: 26
dashedName: lab-quiz-game
---
diff --git a/curriculum/challenges/english/25-front-end-development/lab-sentence-maker/66c057041df6394ca796bf33.md b/curriculum/challenges/english/25-front-end-development/lab-sentence-maker/66c057041df6394ca796bf33.md
index 1f956cf2c72..546bcf8367c 100644
--- a/curriculum/challenges/english/25-front-end-development/lab-sentence-maker/66c057041df6394ca796bf33.md
+++ b/curriculum/challenges/english/25-front-end-development/lab-sentence-maker/66c057041df6394ca796bf33.md
@@ -1,7 +1,7 @@
---
id: 66c057041df6394ca796bf33
title: Build a Sentence Maker
-challengeType: 25
+challengeType: 26
dashedName: build-a-sentence-maker
---
diff --git a/curriculum/challenges/english/25-front-end-development/lab-voting-system/673b567e3ba535dda140d278.md b/curriculum/challenges/english/25-front-end-development/lab-voting-system/673b567e3ba535dda140d278.md
index e86fb0152f3..e96116bbaf1 100644
--- a/curriculum/challenges/english/25-front-end-development/lab-voting-system/673b567e3ba535dda140d278.md
+++ b/curriculum/challenges/english/25-front-end-development/lab-voting-system/673b567e3ba535dda140d278.md
@@ -1,7 +1,7 @@
---
id: 673b567e3ba535dda140d278
title: Build a Voting System
-challengeType: 25
+challengeType: 26
dashedName: build-a-voting-system
---
diff --git a/curriculum/schema/challenge-schema.js b/curriculum/schema/challenge-schema.js
index 1ece403fa54..a12afe0a896 100644
--- a/curriculum/schema/challenge-schema.js
+++ b/curriculum/schema/challenge-schema.js
@@ -155,7 +155,7 @@ const schema = Joi.object()
otherwise: Joi.optional()
}),
certification: Joi.string().regex(slugWithSlashRE),
- challengeType: Joi.number().min(0).max(25).required(),
+ challengeType: Joi.number().min(0).max(26).required(),
checksum: Joi.number(),
// TODO: require this only for normal challenges, not certs
dashedName: Joi.string().regex(slugRE),
diff --git a/shared/config/challenge-types.ts b/shared/config/challenge-types.ts
index 2968acb9bc2..e8c30cd34d1 100644
--- a/shared/config/challenge-types.ts
+++ b/shared/config/challenge-types.ts
@@ -25,6 +25,7 @@ const fillInTheBlank = 22;
const multifilePythonCertProject = 23;
const generic = 24;
const lab = 25;
+const jsLab = 26;
export const challengeTypes = {
html,
@@ -53,7 +54,8 @@ export const challengeTypes = {
fillInTheBlank,
multifilePythonCertProject,
generic,
- lab
+ lab,
+ jsLab
};
export const hasNoSolution = (challengeType: number): boolean => {
@@ -108,7 +110,8 @@ export const viewTypes = {
[fillInTheBlank]: 'fillInTheBlank',
[multifilePythonCertProject]: 'classic',
[generic]: 'generic',
- [lab]: 'classic'
+ [lab]: 'classic',
+ [jsLab]: 'classic'
};
// determine the type of submit function to use for the challenge on completion
@@ -141,7 +144,8 @@ export const submitTypes = {
[fillInTheBlank]: 'tests',
[multifilePythonCertProject]: 'tests',
[generic]: 'tests',
- [lab]: 'tests'
+ [lab]: 'tests',
+ [jsLab]: 'tests'
};
export const canSaveToDB = (challengeType: number): boolean =>