From 331005f4c7205d3cc5668092f59b4d2ad720d63f Mon Sep 17 00:00:00 2001 From: Huyen Nguyen <25715018+huyenltnguyen@users.noreply.github.com> Date: Thu, 22 May 2025 22:52:30 +0700 Subject: [PATCH] feat(tools): add chapter and module names to external curricula data (#60483) --- .../build-external-curricula-data-v2.test.ts | 25 ++++++++++++++--- .../build/build-external-curricula-data-v2.ts | 27 ++++++++++++++++--- .../scripts/build/external-data-schema-v2.js | 2 ++ 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/tools/scripts/build/build-external-curricula-data-v2.test.ts b/tools/scripts/build/build-external-curricula-data-v2.test.ts index 8db526d39eb..6c989039ae5 100644 --- a/tools/scripts/build/build-external-curricula-data-v2.test.ts +++ b/tools/scripts/build/build-external-curricula-data-v2.test.ts @@ -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); }); }); diff --git a/tools/scripts/build/build-external-curricula-data-v2.ts b/tools/scripts/build/build-external-curricula-data-v2.ts index cc676f8b872..82b9b47cf83 100644 --- a/tools/scripts/build/build-external-curricula-data-v2.ts +++ b/tools/scripts/build/build-external-curricula-data-v2.ts @@ -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; + modules: Record; + blocks: Record; + }; +}; + export type Curriculum = { [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 }; }) diff --git a/tools/scripts/build/external-data-schema-v2.js b/tools/scripts/build/external-data-schema-v2.js index 365997a7408..0a024b08018 100644 --- a/tools/scripts/build/external-data-schema-v2.js +++ b/tools/scripts/build/external-data-schema-v2.js @@ -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)