mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
feat(client): display intro of FSD blocks in block header (#56808)
Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
This commit is contained in:
@@ -1,9 +1,12 @@
|
||||
import React from 'react';
|
||||
import { isEmpty } from 'lodash';
|
||||
|
||||
import { BlockTypes } from '../../../../../shared/config/blocks';
|
||||
import { ProgressBar } from '../../../components/Progress/progress-bar';
|
||||
import DropDown from '../../../assets/icons/dropdown';
|
||||
import CheckMark from './check-mark';
|
||||
import BlockLabel from './block-label';
|
||||
import BlockIntros from './block-intros';
|
||||
|
||||
interface BlockHeaderProps {
|
||||
blockDashed: string;
|
||||
@@ -15,6 +18,7 @@ interface BlockHeaderProps {
|
||||
isCompleted: boolean;
|
||||
isExpanded: boolean;
|
||||
percentageCompleted: number;
|
||||
blockIntroArr?: string[];
|
||||
}
|
||||
|
||||
function BlockHeader({
|
||||
@@ -26,7 +30,8 @@ function BlockHeader({
|
||||
handleClick,
|
||||
isCompleted,
|
||||
isExpanded,
|
||||
percentageCompleted
|
||||
percentageCompleted,
|
||||
blockIntroArr
|
||||
}: BlockHeaderProps): JSX.Element {
|
||||
return (
|
||||
<h3 className='block-grid-title'>
|
||||
@@ -45,6 +50,9 @@ function BlockHeader({
|
||||
</span>
|
||||
<DropDown />
|
||||
</span>
|
||||
{!isEmpty(blockIntroArr) && (
|
||||
<BlockIntros intros={blockIntroArr as string[]} />
|
||||
)}
|
||||
{!isExpanded && !isCompleted && completedCount > 0 && (
|
||||
<div aria-hidden='true' className='progress-wrapper'>
|
||||
<div>
|
||||
|
||||
@@ -226,11 +226,11 @@ class Block extends Component<BlockProps> {
|
||||
);
|
||||
|
||||
/**
|
||||
* ChallengeGridBlock displays challenges in a grid.
|
||||
* LegacyChallengeGridBlock displays challenges in a grid.
|
||||
* This layout is used for step-based blocks.
|
||||
* Example: https://www.freecodecamp.org/learn/2022/responsive-web-design/#learn-html-by-building-a-cat-photo-app
|
||||
* Example: https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures-v8/#learn-basic-javascript-by-building-a-role-playing-game
|
||||
*/
|
||||
const ChallengeGridBlock = (
|
||||
const LegacyChallengeGridBlock = (
|
||||
<ScrollableAnchor id={block}>
|
||||
<div className={`block block-grid ${isExpanded ? 'open' : ''}`}>
|
||||
<BlockHeader
|
||||
@@ -323,7 +323,9 @@ class Block extends Component<BlockProps> {
|
||||
*/
|
||||
const ChallengeListBlock = (
|
||||
<ScrollableAnchor id={block}>
|
||||
<div className={`block block-grid ${isExpanded ? 'open' : ''}`}>
|
||||
<div
|
||||
className={`block block-grid challenge-list-block ${isExpanded ? 'open' : ''}`}
|
||||
>
|
||||
<BlockHeader
|
||||
blockDashed={block}
|
||||
blockTitle={blockTitle}
|
||||
@@ -334,6 +336,7 @@ class Block extends Component<BlockProps> {
|
||||
isCompleted={isBlockCompleted}
|
||||
isExpanded={isExpanded}
|
||||
percentageCompleted={percentageCompleted}
|
||||
blockIntroArr={blockIntroArr}
|
||||
/>
|
||||
{!isAudited && (
|
||||
<div className='tags-wrapper'>
|
||||
@@ -347,7 +350,6 @@ class Block extends Component<BlockProps> {
|
||||
)}
|
||||
{isExpanded && (
|
||||
<div id={`${block}-panel`}>
|
||||
<BlockIntros intros={blockIntroArr} />
|
||||
<Challenges
|
||||
challengesWithCompleted={challengesWithCompleted}
|
||||
isProjectBlock={isProjectBlock}
|
||||
@@ -397,6 +399,51 @@ class Block extends Component<BlockProps> {
|
||||
</ScrollableAnchor>
|
||||
);
|
||||
|
||||
/**
|
||||
* ChallengeGridBlock displays challenges in a grid.
|
||||
* This layout is specifically used for the new Full Stack Developer Certification.
|
||||
*/
|
||||
const ChallengeGridBlock = (
|
||||
<ScrollableAnchor id={block}>
|
||||
<div
|
||||
className={`block block-grid challenge-grid-block ${isExpanded ? 'open' : ''}`}
|
||||
>
|
||||
<BlockHeader
|
||||
blockDashed={block}
|
||||
blockTitle={blockTitle}
|
||||
blockType={blockType}
|
||||
completedCount={completedCount}
|
||||
courseCompletionStatus={courseCompletionStatus()}
|
||||
handleClick={this.handleBlockClick}
|
||||
isCompleted={isBlockCompleted}
|
||||
isExpanded={isExpanded}
|
||||
percentageCompleted={percentageCompleted}
|
||||
blockIntroArr={blockIntroArr}
|
||||
/>
|
||||
{!isAudited && (
|
||||
<div className='tags-wrapper'>
|
||||
<Link
|
||||
className='cert-tag'
|
||||
to={t('links:help-translate-link-url')}
|
||||
>
|
||||
{t('misc.translation-pending')}
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
{isExpanded && (
|
||||
<div id={`${block}-panel`} className='challenge-grid-block-panel'>
|
||||
<Challenges
|
||||
challengesWithCompleted={challengesWithCompleted}
|
||||
isProjectBlock={isProjectBlock}
|
||||
isGridMap={true}
|
||||
blockTitle={blockTitle}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</ScrollableAnchor>
|
||||
);
|
||||
|
||||
const blockRenderer = () => {
|
||||
const blockLayout = challenges[0].blockLayout;
|
||||
|
||||
@@ -404,7 +451,9 @@ class Block extends Component<BlockProps> {
|
||||
if (!blockLayout) {
|
||||
if (isProjectBlock)
|
||||
return isGridBlock ? LegacyLinkBlock : ProjectListBlock;
|
||||
return isGridBlock ? ChallengeGridBlock : LegacyChallengeListBlock;
|
||||
return isGridBlock
|
||||
? LegacyChallengeGridBlock
|
||||
: LegacyChallengeListBlock;
|
||||
}
|
||||
|
||||
// blockLayout is only being used in new certs at the moment, so I made some new components for them for now to not interfere with the existing ones
|
||||
@@ -415,6 +464,8 @@ class Block extends Component<BlockProps> {
|
||||
if (blockLayout === BlockLayouts.LegacyLink) return LegacyLinkBlock;
|
||||
if (blockLayout === BlockLayouts.LegacyChallengeList)
|
||||
return LegacyChallengeListBlock;
|
||||
if (blockLayout === BlockLayouts.LegacyChallengeGrid)
|
||||
return LegacyChallengeGridBlock;
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -598,3 +598,22 @@ a.map-grid-item.challenge-completed {
|
||||
.grid-project-block:hover:has(.tags-wrapper a:hover) {
|
||||
background: var(--primary-background);
|
||||
}
|
||||
|
||||
/* Override the `.block-description` padding (25px)
|
||||
to align the description with the content in the panel. */
|
||||
.block-ui .challenge-list-block .block-header .block-description,
|
||||
.block-ui .challenge-grid-block .block-header .block-description {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.block-ui .challenge-grid-block .progress-wrapper {
|
||||
/* Make the progress bar align with the description above */
|
||||
padding-inline-start: 10px;
|
||||
}
|
||||
|
||||
.block-ui .challenge-grid-block .challenge-grid-block-panel {
|
||||
/* Add some space between panel content and the top edge of the container.
|
||||
The value (18px) is the same value `.map-challenges-grid` uses
|
||||
to create space between the grid and the bottom edge of the container. */
|
||||
margin-top: 18px;
|
||||
}
|
||||
|
||||
@@ -137,7 +137,8 @@ const schema = Joi.object()
|
||||
'link',
|
||||
'project-list',
|
||||
'legacy-challenge-list',
|
||||
'legacy-link'
|
||||
'legacy-link',
|
||||
'legacy-challenge-grid'
|
||||
).required()
|
||||
}),
|
||||
challengeOrder: Joi.number(),
|
||||
|
||||
@@ -12,7 +12,8 @@ const schema = Joi.object()
|
||||
'link',
|
||||
'project-list',
|
||||
'legacy-challenge-list',
|
||||
'legacy-link'
|
||||
'legacy-link',
|
||||
'legacy-challenge-grid'
|
||||
),
|
||||
blockType: Joi.valid(
|
||||
'workshop',
|
||||
|
||||
@@ -9,11 +9,12 @@ export enum BlockTypes {
|
||||
|
||||
export enum BlockLayouts {
|
||||
/**
|
||||
* These two are for the new Full Stack Developer Certification,
|
||||
* These three are for the new Full Stack Developer Certification,
|
||||
* so we can play with them without affecting the existing block layouts
|
||||
*/
|
||||
ChallengeList = 'challenge-list',
|
||||
Link = 'link',
|
||||
ChallengeGrid = 'challenge-grid',
|
||||
|
||||
/**
|
||||
* ChallengeList displays challenges in a list.
|
||||
@@ -23,11 +24,11 @@ export enum BlockLayouts {
|
||||
LegacyChallengeList = 'legacy-challenge-list',
|
||||
|
||||
/**
|
||||
* ChallengeGrid displays challenges in a grid.
|
||||
* LegacyChallengeGrid displays challenges in a grid.
|
||||
* This layout is used for step-based blocks.
|
||||
* Example: https://www.freecodecamp.org/learn/2022/responsive-web-design/#learn-html-by-building-a-cat-photo-app
|
||||
*/
|
||||
ChallengeGrid = 'challenge-grid',
|
||||
LegacyChallengeGrid = 'legacy-challenge-grid',
|
||||
|
||||
/**
|
||||
* Link displays the block as a single link.
|
||||
|
||||
Reference in New Issue
Block a user