mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
feat(challenge-parser): add transcript to challenge parser (#57967)
This commit is contained in:
@@ -305,6 +305,7 @@ exports.createSchemaCustomization = ({ actions }) => {
|
|||||||
msTrophyId: String
|
msTrophyId: String
|
||||||
fillInTheBlank: FillInTheBlank
|
fillInTheBlank: FillInTheBlank
|
||||||
scene: Scene
|
scene: Scene
|
||||||
|
transcript: String
|
||||||
quizzes: [Quiz]
|
quizzes: [Quiz]
|
||||||
}
|
}
|
||||||
type FileContents {
|
type FileContents {
|
||||||
|
|||||||
@@ -428,6 +428,7 @@
|
|||||||
"questions": "Questions",
|
"questions": "Questions",
|
||||||
"answered-mcq": "You have unanswered questions and/or incorrect answers.",
|
"answered-mcq": "You have unanswered questions and/or incorrect answers.",
|
||||||
"explanation": "Explanation",
|
"explanation": "Explanation",
|
||||||
|
"transcript": "Read a transcript of this video",
|
||||||
"solution-link": "Solution Link",
|
"solution-link": "Solution Link",
|
||||||
"source-code-link": "Source Code Link",
|
"source-code-link": "Source Code Link",
|
||||||
"ms-link": "Microsoft Link",
|
"ms-link": "Microsoft Link",
|
||||||
|
|||||||
@@ -221,6 +221,7 @@ export type ChallengeNode = {
|
|||||||
template: string;
|
template: string;
|
||||||
tests: Test[];
|
tests: Test[];
|
||||||
title: string;
|
title: string;
|
||||||
|
transcript: string;
|
||||||
translationPending: boolean;
|
translationPending: boolean;
|
||||||
url: string;
|
url: string;
|
||||||
usesMultifileEditor: boolean;
|
usesMultifileEditor: boolean;
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
.challenge-transcript {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { Spacer } from '@freecodecamp/ui';
|
||||||
|
import PrismFormatted from './prism-formatted';
|
||||||
|
|
||||||
|
import './challenge-transcript.css';
|
||||||
|
|
||||||
|
interface ChallengeTranscriptProps {
|
||||||
|
transcript: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ChallengeTranscript({
|
||||||
|
transcript
|
||||||
|
}: ChallengeTranscriptProps): JSX.Element {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<details className='challenge-transcript'>
|
||||||
|
<summary>{t('learn.transcript')}</summary>
|
||||||
|
<Spacer size='m' />
|
||||||
|
<PrismFormatted className={'line-numbers'} text={transcript} />
|
||||||
|
</details>
|
||||||
|
<Spacer size='m' />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChallengeTranscript.displayName = 'ChallengeTranscript';
|
||||||
|
|
||||||
|
export default ChallengeTranscript;
|
||||||
@@ -28,6 +28,7 @@ import { getChallengePaths } from '../utils/challenge-paths';
|
|||||||
import Scene from '../components/scene/scene';
|
import Scene from '../components/scene/scene';
|
||||||
import MultipleChoiceQuestions from '../components/multiple-choice-questions';
|
import MultipleChoiceQuestions from '../components/multiple-choice-questions';
|
||||||
import ChallengeExplanation from '../components/challenge-explanation';
|
import ChallengeExplanation from '../components/challenge-explanation';
|
||||||
|
import ChallengeTranscript from '../components/challenge-transcript';
|
||||||
import HelpModal from '../components/help-modal';
|
import HelpModal from '../components/help-modal';
|
||||||
import { SceneSubject } from '../components/scene/scene-subject';
|
import { SceneSubject } from '../components/scene/scene-subject';
|
||||||
|
|
||||||
@@ -82,6 +83,7 @@ const ShowGeneric = ({
|
|||||||
instructions,
|
instructions,
|
||||||
questions,
|
questions,
|
||||||
title,
|
title,
|
||||||
|
transcript,
|
||||||
translationPending,
|
translationPending,
|
||||||
scene,
|
scene,
|
||||||
superBlock,
|
superBlock,
|
||||||
@@ -204,6 +206,8 @@ const ShowGeneric = ({
|
|||||||
{title}
|
{title}
|
||||||
</ChallengeTitle>
|
</ChallengeTitle>
|
||||||
|
|
||||||
|
<Spacer size='m' />
|
||||||
|
|
||||||
{description && (
|
{description && (
|
||||||
<Col md={8} mdOffset={2} sm={10} smOffset={1} xs={12}>
|
<Col md={8} mdOffset={2} sm={10} smOffset={1} xs={12}>
|
||||||
<ChallengeDescription
|
<ChallengeDescription
|
||||||
@@ -216,28 +220,34 @@ const ShowGeneric = ({
|
|||||||
|
|
||||||
<Col lg={10} lgOffset={1} md={10} mdOffset={1}>
|
<Col lg={10} lgOffset={1} md={10} mdOffset={1}>
|
||||||
{videoId && (
|
{videoId && (
|
||||||
<VideoPlayer
|
<>
|
||||||
bilibiliIds={bilibiliIds}
|
<VideoPlayer
|
||||||
onVideoLoad={handleVideoIsLoaded}
|
bilibiliIds={bilibiliIds}
|
||||||
title={title}
|
onVideoLoad={handleVideoIsLoaded}
|
||||||
videoId={videoId}
|
title={title}
|
||||||
videoIsLoaded={videoIsLoaded}
|
videoId={videoId}
|
||||||
videoLocaleIds={videoLocaleIds}
|
videoIsLoaded={videoIsLoaded}
|
||||||
/>
|
videoLocaleIds={videoLocaleIds}
|
||||||
|
/>
|
||||||
|
<Spacer size='m' />
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
{scene && <Scene scene={scene} sceneSubject={sceneSubject} />}
|
{scene && <Scene scene={scene} sceneSubject={sceneSubject} />}
|
||||||
|
|
||||||
<Col md={8} mdOffset={2} sm={10} smOffset={1} xs={12}>
|
<Col md={8} mdOffset={2} sm={10} smOffset={1} xs={12}>
|
||||||
{instructions && (
|
{transcript && <ChallengeTranscript transcript={transcript} />}
|
||||||
<ChallengeDescription
|
|
||||||
instructions={instructions}
|
|
||||||
superBlock={superBlock}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Spacer size='m' />
|
{instructions && (
|
||||||
|
<>
|
||||||
|
<ChallengeDescription
|
||||||
|
instructions={instructions}
|
||||||
|
superBlock={superBlock}
|
||||||
|
/>
|
||||||
|
<Spacer size='m' />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
{assignments.length > 0 && (
|
{assignments.length > 0 && (
|
||||||
<Assignments
|
<Assignments
|
||||||
@@ -362,6 +372,7 @@ export const query = graphql`
|
|||||||
}
|
}
|
||||||
superBlock
|
superBlock
|
||||||
title
|
title
|
||||||
|
transcript
|
||||||
translationPending
|
translationPending
|
||||||
videoId
|
videoId
|
||||||
videoId
|
videoId
|
||||||
|
|||||||
@@ -287,6 +287,10 @@ const schema = Joi.object()
|
|||||||
.required(),
|
.required(),
|
||||||
template: Joi.string().allow(''),
|
template: Joi.string().allow(''),
|
||||||
title: Joi.string().required(),
|
title: Joi.string().required(),
|
||||||
|
transcript: Joi.when('challengeType', {
|
||||||
|
is: [challengeTypes.generic, challengeTypes.video],
|
||||||
|
then: Joi.string()
|
||||||
|
}),
|
||||||
translationPending: Joi.bool().required(),
|
translationPending: Joi.bool().required(),
|
||||||
url: Joi.when('challengeType', {
|
url: Joi.when('challengeType', {
|
||||||
is: [challengeTypes.codeAllyPractice, challengeTypes.codeAllyCert],
|
is: [challengeTypes.codeAllyPractice, challengeTypes.codeAllyCert],
|
||||||
|
|||||||
@@ -53,7 +53,13 @@ const processor = unified()
|
|||||||
.use(addScene)
|
.use(addScene)
|
||||||
.use(addQuizzes)
|
.use(addQuizzes)
|
||||||
.use(addTests)
|
.use(addTests)
|
||||||
.use(addText, ['description', 'instructions', 'notes', 'explanation']);
|
.use(addText, [
|
||||||
|
'description',
|
||||||
|
'instructions',
|
||||||
|
'notes',
|
||||||
|
'explanation',
|
||||||
|
'transcript'
|
||||||
|
]);
|
||||||
|
|
||||||
exports.parseMD = function parseMD(filename) {
|
exports.parseMD = function parseMD(filename) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user