+ {!isAudited && (
+
+
+ {t('misc.translation-pending')}
+
+
+ )}
+
+ {isGridBlock ? (
+
) : (
@@ -469,10 +527,31 @@ export class Block extends Component
{
>
);
+ const LinkBlock = (
+ <>
+
+
+
+
+ >
+ );
+
const layoutToComponent = {
[BlockLayouts.ChallengeGrid]: AccordionBlock,
[BlockLayouts.ChallengeList]: AccordionBlock,
- [BlockLayouts.Link]: AccordionBlock,
+ [BlockLayouts.Link]: accordion ? LinkBlock : AccordionBlock,
[BlockLayouts.ProjectList]: ProjectListBlock,
[BlockLayouts.LegacyLink]: LegacyLinkBlock,
[BlockLayouts.LegacyChallengeList]: LegacyChallengeListBlock,
diff --git a/client/src/templates/Introduction/components/challenges.tsx b/client/src/templates/Introduction/components/challenges.tsx
index d686c43d7fa..376fd97f40b 100644
--- a/client/src/templates/Introduction/components/challenges.tsx
+++ b/client/src/templates/Introduction/components/challenges.tsx
@@ -22,6 +22,10 @@ interface ChallengesProps {
challenges: ChallengeInfo[];
}
+interface JumpLinkProps {
+ jumpLink?: boolean;
+}
+
interface BlockTitleProps {
blockTitle: string;
}
@@ -122,16 +126,18 @@ const LinkToFirstIncompleteChallenge = ({
export const GridMapChallenges = ({
challenges,
blockTitle,
- isProjectBlock
-}: ChallengesProps & BlockTitleProps & IsProjectBlockProps) => {
+ isProjectBlock,
+ jumpLink
+}: ChallengesProps & BlockTitleProps & IsProjectBlockProps & JumpLinkProps) => {
const { t } = useTranslation();
-
return (
<>
-
+ {jumpLink && (
+
+ )}
-
-
- {t('learn.steps-completed', {
- totalSteps,
- completedSteps
- })}
-
+ {t(`intro:${superBlock}.modules.${dashedName}`)}
- {children}
+ {comingSoon && (
+
+ {note && (
+
+ {note}
+
+ )}
+ {intro?.length && intro.map(ntro =>
{ntro}
)}
+
+ )}
+ {showModuleContent && children}
);
};
-const LinkBlock = ({
+const LinkModule = ({
superBlock,
- challenges
+ challenges,
+ accordion
}: {
superBlock: SuperBlocks;
challenges?: Challenge[];
-}) =>
- challenges?.length ? (
+ accordion: boolean;
+}) => {
+ if (!challenges?.length) return null;
+
+ return (
- ) : null;
+ );
+};
export const SuperBlockAccordion = ({
challenges,
@@ -185,7 +243,11 @@ export const SuperBlockAccordion = ({
const isLinkModule = (name: string) => {
const module = modules.find(module => module.dashedName === name);
- return module?.moduleType === 'review' || module?.moduleType === 'exam';
+ return (
+ module?.moduleType === 'review' ||
+ module?.moduleType === 'exam' ||
+ module?.moduleType === 'quiz'
+ );
};
const getBlockToChapterMap = () => {
@@ -214,11 +276,8 @@ export const SuperBlockAccordion = ({
const blockToChapterMap = getBlockToChapterMap();
const blockToModuleMap = getBlockToModuleMap();
-
- const { t } = useTranslation();
- const { allChapters } = useMemo(() => {
- const chapters = superBlockStructure.chapters;
- const populateBlocks = (blocks: string[]) =>
+ const allChapters = useMemo
(() => {
+ const populateBlocks = (blocks: string[]): PopulatedBlock[] =>
blocks.map(block => {
const blockChallenges = challenges.filter(
({ block: blockName }) => blockName === block
@@ -231,7 +290,7 @@ export const SuperBlockAccordion = ({
};
});
- const allChapters = chapters.map(chapter => ({
+ return superBlockStructure.chapters.map((chapter: Chapter) => ({
name: chapter.dashedName,
comingSoon: chapter.comingSoon,
modules: chapter.modules.map((module: Module) => ({
@@ -241,13 +300,12 @@ export const SuperBlockAccordion = ({
blocks: populateBlocks(module.blocks)
}))
}));
-
- return { allChapters };
}, [challenges, superBlockStructure.chapters]);
// Expand the outer layers in order to reveal the chosen block.
const expandedChapter = blockToChapterMap.get(chosenBlock);
const expandedModule = blockToModuleMap.get(chosenBlock);
+ const accordion = true;
return (
@@ -261,10 +319,25 @@ export const SuperBlockAccordion = ({
});
const chapterStepIdsSet = new Set(chapterStepIds);
+
const completedStepsInChapter = new Set(
completedChallengeIds.filter(id => chapterStepIdsSet.has(id))
).size;
+ const [firstChapterModule] = chapter.modules;
+
+ const [firstModuleBlock] = firstChapterModule?.blocks ?? [];
+
+ const isLinkChapter =
+ chapter.modules.length === 1 &&
+ firstChapterModule?.blocks.length === 1 &&
+ firstModuleBlock?.blockLabel === BlockLabel.exam &&
+ firstModuleBlock.challenges.length === 1;
+
+ const examSlug = isLinkChapter
+ ? firstModuleBlock?.challenges[0]?.fields.slug
+ : undefined;
+
return (
{chapter.modules.map(module => {
if (module.comingSoon && !showUpcomingChanges) {
if (module.moduleType === 'review') {
return null;
}
-
- const { note, intro } = t(
- `intro:${superBlock}.module-intros.${module.name}`,
- { returnObjects: true }
- ) as {
- note: string;
- intro: string[];
- };
-
- return (
-
-
-
-
-
-
- {t(`intro:${superBlock}.modules.${module.name}`)}
-
-
-
-
- {note && (
-
- {note}
-
- )}
- {intro &&
- intro.length > 0 &&
- intro.map(ntro =>
{ntro}
)}
-
-
-
- );
}
if (isLinkModule(module.name)) {
return (
-
);
}
@@ -349,6 +388,7 @@ export const SuperBlockAccordion = ({
totalSteps={moduleStepIds.length}
completedSteps={completedStepsInModule}
superBlock={superBlock}
+ comingSoon={!!module.comingSoon}
>
{module.blocks.map(block => (
// maybe TODO: allow blocks to be "coming soon"
@@ -358,6 +398,7 @@ export const SuperBlockAccordion = ({
blockLabel={block.blockLabel}
challenges={block.challenges}
superBlock={superBlock}
+ accordion={accordion}
/>
))}
diff --git a/curriculum/structure/superblocks/full-stack-developer.json b/curriculum/structure/superblocks/full-stack-developer.json
index cd1f9255f63..29109fc6ffa 100644
--- a/curriculum/structure/superblocks/full-stack-developer.json
+++ b/curriculum/structure/superblocks/full-stack-developer.json
@@ -937,6 +937,7 @@
{ "dashedName": "capstone-project", "comingSoon": true, "blocks": [] },
{
"dashedName": "certified-full-stack-developer-exam",
+ "moduleType": "exam",
"comingSoon": true,
"blocks": ["exam-certified-full-stack-developer"]
}
diff --git a/e2e/super-block-page.spec.ts b/e2e/super-block-page.spec.ts
index 0d313dd3e6c..aaf6d08c41d 100644
--- a/e2e/super-block-page.spec.ts
+++ b/e2e/super-block-page.spec.ts
@@ -43,7 +43,7 @@ test.describe('Super Block Page - Authenticated User', () => {
await page.addInitScript(() => {
window.localStorage.setItem(
'currentChallengeId',
- '660ee6e3a242da6bd579de69' // JS Pyramid Generator step 2
+ '62a3b3eab50e193608c19fc6' // Learn Basic JavaScript by Building a Role Playing Game step 9
);
});
@@ -51,7 +51,7 @@ test.describe('Super Block Page - Authenticated User', () => {
await expect(
page.getByRole('button', {
- name: 'Learn Introductory JavaScript by Building a Pyramid Generator'
+ name: 'Learn Basic JavaScript by Building a Role Playing Game'
})
).toHaveAttribute('aria-expanded', 'true');
});
@@ -124,14 +124,14 @@ test.describe('Super Block Page - Authenticated User', () => {
// Module
await expect(
page.getByRole('button', {
- name: /Basic CSS \d+ of \d+ steps complete/
+ name: 'Basic CSS'
})
).toHaveAttribute('aria-expanded', 'true');
// Block
await expect(
page.getByRole('button', {
- name: /Workshop Design a Cafe Menu/
+ name: 'Design a Cafe Menu'
})
).toHaveAttribute('aria-expanded', 'true');
});
@@ -156,14 +156,14 @@ test.describe('Super Block Page - Authenticated User', () => {
// Basic HTML module
await expect(
page.getByRole('button', {
- name: /Basic HTML \d+ of \d+ steps complete/
+ name: 'Basic HTML'
})
).toHaveAttribute('aria-expanded', 'true');
// Understanding HTML Attributes block
await expect(
page.getByRole('button', {
- name: /Theory Understanding HTML Attributes/
+ name: 'Understanding HTML Attributes'
})
).toHaveAttribute('aria-expanded', 'true');
});
@@ -183,14 +183,14 @@ test.describe('Super Block Page - Authenticated User', () => {
// First module
await expect(
page.getByRole('button', {
- name: /Basic HTML \d+ of \d+ steps complete/
+ name: 'Basic HTML'
})
).toHaveAttribute('aria-expanded', 'true');
// First block
await expect(
page.getByRole('button', {
- name: /Build a Curriculum Outline/
+ name: 'Build a Curriculum Outline'
})
).toHaveAttribute('aria-expanded', 'true');
@@ -212,7 +212,7 @@ test.describe('Super Block Page - Authenticated User', () => {
// Cat Blog Page block
await expect(
page.getByRole('button', {
- name: 'Workshop Build a Cat Blog Page'
+ name: 'Build a Cat Blog Page'
})
).toHaveAttribute('aria-expanded', 'true');
});
@@ -258,7 +258,7 @@ test.describe('Super Block Page - Unauthenticated User', () => {
// First module
await expect(
page.getByRole('button', {
- name: /Basic HTML \d+ of \d+ steps complete/
+ name: 'Basic HTML'
})
).toHaveAttribute('aria-expanded', 'true');