fix(client): handle builds without all challenges (#61040)

Co-authored-by: Shaun Hamilton <shauhami020@gmail.com>
This commit is contained in:
Oliver Eyton-Williams
2025-10-02 16:44:27 +02:00
committed by GitHub
parent 568840b8d8
commit 517b9f0576
5 changed files with 95 additions and 32 deletions
+88 -12
View File
@@ -295,22 +295,56 @@ exports.createSchemaCustomization = ({ actions }) => {
challenge: Challenge
}
type Challenge {
blockType: String
blockLayout: String
challengeFiles: [FileContents]
chapter: String
explanation: String
hooks: Hooks
notes: String
url: String
assignments: [String]
prerequisites: [PrerequisiteChallenge]
bilibiliIds: BilibiliIds
block: String
blockId: String
blockLayout: String
blockType: String
certification: String
challengeFiles: [FileContents]
challengeOrder: Int
challengeType: Int
chapter: String
dashedName: String
demoType: String
description: String
disableLoopProtectPreview: Boolean
disableLoopProtectTests: Boolean
explanation: String
fillInTheBlank: FillInTheBlank
forumTopicId: Int
hasEditableBoundaries: Boolean
helpCategory: String
hooks: Hooks
id: String
instructions: String
isComingSoon: Boolean
isLastChallengeInBlock: Boolean
isPrivate: Boolean
module: String
msTrophyId: String
fillInTheBlank: FillInTheBlank
scene: Scene
transcript: String
notes: String
order: Int
prerequisites: [PrerequisiteChallenge]
questions: [Question]
quizzes: [Quiz]
required: [RequiredResource]
scene: Scene
solutions: [[FileContents]]
suborder: Int
superBlock: String
superOrder: Int
template: String
tests: [Test]
title: String
transcript: String
translationPending: Boolean
url: String
usesMultifileEditor: Boolean
videoId: String
videoLocaleIds: VideoLocaleIds
videoUrl: String
}
type FileContents {
fileKey: String
@@ -320,11 +354,53 @@ exports.createSchemaCustomization = ({ actions }) => {
head: String
tail: String
editableRegionBoundaries: [Int]
path: String
error: String
seed: String
id: String
history: [String]
}
type PrerequisiteChallenge {
id: String
title: String
}
type VideoLocaleIds {
espanol: String
italian: String
portuguese: String
}
type BilibiliIds {
aid: Int
bvid: String
cid: Int
}
type Question {
text: String
answers: [Answer]
solution: Int
}
type Answer {
answer: String
feedback: String
}
type RequiredResource {
link: String
raw: Boolean
src: String
crossDomain: Boolean
}
type Hooks {
beforeAll: String
beforeEach: String
afterAll: String
afterEach: String
}
type Test {
id: String
text: String
testString: String
title: String
}
type FillInTheBlank {
sentence: String
blanks: [Blank]
+4 -8
View File
@@ -57,7 +57,7 @@ interface LearnPageProps {
challenge: {
fields: Slug;
};
};
} | null;
};
}
@@ -67,18 +67,14 @@ function LearnPage({
isSignedIn,
fetchState: { pending, complete },
user,
data: {
challengeNode: {
challenge: {
fields: { slug }
}
}
}
data: { challengeNode }
}: LearnPageProps) {
const { name, completedChallengeCount, isDonating } = user ?? EMPTY_USER;
const { t } = useTranslation();
const slug = challengeNode?.challenge?.fields?.slug || '';
const onLearnDonationAlertClick = () => {
callGA({
event: 'donation_related',
-1
View File
@@ -188,7 +188,6 @@ export type ChallengeNode = {
fields: Fields;
fillInTheBlank: FillInTheBlank;
forumTopicId: number;
guideUrl: string;
head: string[];
hasEditableBoundaries: boolean;
helpCategory: string;
@@ -20,7 +20,7 @@ interface SuperBlockIntroQueryData {
slug: string;
};
};
};
} | null;
}
type ReduxProps = ConnectedProps<typeof connector>;
@@ -115,13 +115,7 @@ function SuperBlockIntro({
note: string;
};
const {
challengeNode: {
challenge: {
fields: { slug: firstChallengeSlug }
}
}
} = useStaticQuery<SuperBlockIntroQueryData>(graphql`
const { challengeNode } = useStaticQuery<SuperBlockIntroQueryData>(graphql`
query SuperBlockIntroQuery {
challengeNode(
challenge: {
@@ -139,6 +133,7 @@ function SuperBlockIntro({
}
`);
const firstChallengeSlug = challengeNode?.challenge?.fields?.slug || '';
const {
title: i18nSuperBlock,
intro: superBlockIntroText,
-3
View File
@@ -162,7 +162,6 @@ const schema = Joi.object().keys({
}),
certification: Joi.string().regex(slugWithSlashRE),
challengeType: Joi.number().min(0).max(31).required(),
checksum: Joi.number(),
// TODO: require this only for normal challenges, not certs
dashedName: Joi.string().regex(slugRE),
demoType: Joi.string().valid('onClick', 'onLoad'),
@@ -183,7 +182,6 @@ const schema = Joi.object().keys({
then: Joi.string()
}),
challengeFiles: Joi.array().items(fileJoi),
guideUrl: Joi.string().uri({ scheme: 'https' }),
hasEditableBoundaries: Joi.boolean(),
helpCategory: Joi.valid(
'JavaScript',
@@ -217,7 +215,6 @@ const schema = Joi.object().keys({
otherwise: Joi.string().allow('')
}),
isComingSoon: Joi.bool(),
isLocked: Joi.bool(),
module: Joi.string().when('superBlock', {
is: chapterBasedSuperBlocks,
then: Joi.required(),