mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
feat(tools): add chapter and module names to external curricula data (#60483)
This commit is contained in:
@@ -19,6 +19,7 @@ import {
|
|||||||
type GeneratedCurriculumProps,
|
type GeneratedCurriculumProps,
|
||||||
type GeneratedBlockBasedCurriculumProps,
|
type GeneratedBlockBasedCurriculumProps,
|
||||||
type GeneratedChapterBasedCurriculumProps,
|
type GeneratedChapterBasedCurriculumProps,
|
||||||
|
type ChapterBasedCurriculumIntros,
|
||||||
orderedSuperBlockInfo
|
orderedSuperBlockInfo
|
||||||
} from './build-external-curricula-data-v2';
|
} from './build-external-curricula-data-v2';
|
||||||
|
|
||||||
@@ -176,6 +177,10 @@ ${result.error.message}`);
|
|||||||
superBlock
|
superBlock
|
||||||
] as GeneratedChapterBasedCurriculumProps;
|
] as GeneratedChapterBasedCurriculumProps;
|
||||||
|
|
||||||
|
const superBlockIntros = intros[
|
||||||
|
superBlock
|
||||||
|
] as ChapterBasedCurriculumIntros[SuperBlocks];
|
||||||
|
|
||||||
// Randomly pick a chapter.
|
// Randomly pick a chapter.
|
||||||
const chapters = superBlockData.chapters;
|
const chapters = superBlockData.chapters;
|
||||||
const randomChapterIndex = Math.floor(Math.random() * chapters.length);
|
const randomChapterIndex = Math.floor(Math.random() * chapters.length);
|
||||||
@@ -190,15 +195,29 @@ ${result.error.message}`);
|
|||||||
const blocks = randomModule.blocks;
|
const blocks = randomModule.blocks;
|
||||||
const randomBlockIndex = Math.floor(Math.random() * blocks.length);
|
const randomBlockIndex = Math.floor(Math.random() * blocks.length);
|
||||||
|
|
||||||
expect(superBlockData.intro).toEqual(intros[superBlock].intro);
|
// Check super block data
|
||||||
|
expect(superBlockData.intro).toEqual(superBlockIntros.intro);
|
||||||
|
|
||||||
|
// Check chapter data
|
||||||
|
expect(superBlockData.chapters[randomChapterIndex].name).toEqual(
|
||||||
|
superBlockIntros.chapters[randomChapterIndex]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check module data
|
||||||
|
expect(
|
||||||
|
superBlockData.chapters[randomChapterIndex].modules[randomModuleIndex]
|
||||||
|
.name
|
||||||
|
).toEqual(superBlockIntros.modules[randomModuleIndex]);
|
||||||
|
|
||||||
|
// Check block data
|
||||||
expect(
|
expect(
|
||||||
superBlockData.chapters[randomChapterIndex].modules[randomModuleIndex]
|
superBlockData.chapters[randomChapterIndex].modules[randomModuleIndex]
|
||||||
.blocks[randomBlockIndex].intro
|
.blocks[randomBlockIndex].intro
|
||||||
).toEqual(intros[superBlock].blocks[randomBlockIndex].intro);
|
).toEqual(superBlockIntros.blocks[randomBlockIndex].intro);
|
||||||
expect(
|
expect(
|
||||||
superBlockData.chapters[randomChapterIndex].modules[randomModuleIndex]
|
superBlockData.chapters[randomChapterIndex].modules[randomModuleIndex]
|
||||||
.blocks[randomBlockIndex].meta.name
|
.blocks[randomBlockIndex].meta.name
|
||||||
).toEqual(intros[superBlock].blocks[randomBlockIndex].title);
|
).toEqual(superBlockIntros.blocks[randomBlockIndex].title);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,11 @@ import {
|
|||||||
import fullStackSuperBlockStructure from '../../../curriculum/superblock-structure/full-stack.json';
|
import fullStackSuperBlockStructure from '../../../curriculum/superblock-structure/full-stack.json';
|
||||||
import type { Chapter } from '../../../shared/config/chapters';
|
import type { Chapter } from '../../../shared/config/chapters';
|
||||||
|
|
||||||
export type CurriculumIntros = {
|
export type CurriculumIntros =
|
||||||
|
| BlockBasedCurriculumIntros
|
||||||
|
| ChapterBasedCurriculumIntros;
|
||||||
|
|
||||||
|
type BlockBasedCurriculumIntros = {
|
||||||
[keyValue in SuperBlocks]: {
|
[keyValue in SuperBlocks]: {
|
||||||
title: string;
|
title: string;
|
||||||
intro: string[];
|
intro: string[];
|
||||||
@@ -17,6 +21,16 @@ export type CurriculumIntros = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ChapterBasedCurriculumIntros = {
|
||||||
|
[keyValue in SuperBlocks]: {
|
||||||
|
title: string;
|
||||||
|
intro: string[];
|
||||||
|
chapters: Record<string, string>;
|
||||||
|
modules: Record<string, string>;
|
||||||
|
blocks: Record<string, { title: string; intro: string[] }>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export type Curriculum<T> = {
|
export type Curriculum<T> = {
|
||||||
[keyValue in SuperBlocks]: T extends CurriculumProps
|
[keyValue in SuperBlocks]: T extends CurriculumProps
|
||||||
? CurriculumProps
|
? CurriculumProps
|
||||||
@@ -51,6 +65,7 @@ export interface GeneratedChapterBasedCurriculumProps {
|
|||||||
|
|
||||||
interface GeneratedChapter {
|
interface GeneratedChapter {
|
||||||
dashedName: string;
|
dashedName: string;
|
||||||
|
name: string;
|
||||||
comingSoon?: boolean;
|
comingSoon?: boolean;
|
||||||
modules: GeneratedModule[];
|
modules: GeneratedModule[];
|
||||||
chapterType?: string;
|
chapterType?: string;
|
||||||
@@ -58,6 +73,7 @@ interface GeneratedChapter {
|
|||||||
|
|
||||||
interface GeneratedModule {
|
interface GeneratedModule {
|
||||||
dashedName: string;
|
dashedName: string;
|
||||||
|
name: string;
|
||||||
comingSoon?: boolean;
|
comingSoon?: boolean;
|
||||||
blocks: GeneratedBlock[];
|
blocks: GeneratedBlock[];
|
||||||
moduleType?: string;
|
moduleType?: string;
|
||||||
@@ -260,25 +276,30 @@ export function buildExtCurriculumDataV2(
|
|||||||
const chapters: Chapter[] = fullStackSuperBlockStructure.chapters;
|
const chapters: Chapter[] = fullStackSuperBlockStructure.chapters;
|
||||||
const blocksWithData = curriculum[superBlockKey].blocks;
|
const blocksWithData = curriculum[superBlockKey].blocks;
|
||||||
|
|
||||||
|
const superBlockIntros = intros[
|
||||||
|
superBlockKey
|
||||||
|
] as ChapterBasedCurriculumIntros[SuperBlocks];
|
||||||
|
|
||||||
// Skip upcoming chapter/module as the metadata of their blocks
|
// Skip upcoming chapter/module as the metadata of their blocks
|
||||||
// is not included in the `curriculum` object.
|
// is not included in the `curriculum` object.
|
||||||
const allChapters = chapters.map(chapter => ({
|
const allChapters = chapters.map(chapter => ({
|
||||||
dashedName: chapter.dashedName,
|
dashedName: chapter.dashedName,
|
||||||
|
name: superBlockIntros.chapters[chapter.dashedName],
|
||||||
comingSoon: chapter.comingSoon,
|
comingSoon: chapter.comingSoon,
|
||||||
chapterType: chapter.chapterType,
|
chapterType: chapter.chapterType,
|
||||||
modules: chapter.comingSoon
|
modules: chapter.comingSoon
|
||||||
? []
|
? []
|
||||||
: chapter.modules.map(module => ({
|
: chapter.modules.map(module => ({
|
||||||
dashedName: module.dashedName,
|
dashedName: module.dashedName,
|
||||||
|
name: superBlockIntros.modules[module.dashedName],
|
||||||
comingSoon: module.comingSoon,
|
comingSoon: module.comingSoon,
|
||||||
moduleType: module.moduleType,
|
moduleType: module.moduleType,
|
||||||
blocks: module.comingSoon
|
blocks: module.comingSoon
|
||||||
? []
|
? []
|
||||||
: module.blocks.map(block => {
|
: module.blocks.map(block => {
|
||||||
const blockData = blocksWithData[block.dashedName];
|
const blockData = blocksWithData[block.dashedName];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
intro: intros[superBlockKey].blocks[block.dashedName].intro,
|
intro: superBlockIntros.blocks[block.dashedName].intro,
|
||||||
meta: blockData.meta
|
meta: blockData.meta
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -81,12 +81,14 @@ const chapterBasedCurriculumSchema = Joi.object().pattern(
|
|||||||
chapters: Joi.array().items(
|
chapters: Joi.array().items(
|
||||||
Joi.object().keys({
|
Joi.object().keys({
|
||||||
dashedName: Joi.string().regex(slugRE).required(),
|
dashedName: Joi.string().regex(slugRE).required(),
|
||||||
|
name: Joi.string().required(),
|
||||||
comingSoon: Joi.boolean().optional(),
|
comingSoon: Joi.boolean().optional(),
|
||||||
chapterType: Joi.valid('exam').optional(),
|
chapterType: Joi.valid('exam').optional(),
|
||||||
modules: Joi.array()
|
modules: Joi.array()
|
||||||
.items(
|
.items(
|
||||||
Joi.object().keys({
|
Joi.object().keys({
|
||||||
moduleType: Joi.valid('review', 'exam').optional(),
|
moduleType: Joi.valid('review', 'exam').optional(),
|
||||||
|
name: Joi.string().required(),
|
||||||
comingSoon: Joi.boolean().optional(),
|
comingSoon: Joi.boolean().optional(),
|
||||||
dashedName: Joi.string().regex(slugRE).required(),
|
dashedName: Joi.string().regex(slugRE).required(),
|
||||||
blocks: Joi.array().items(blockSchema)
|
blocks: Joi.array().items(blockSchema)
|
||||||
|
|||||||
Reference in New Issue
Block a user