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