refactor: remove isPrivate (#61952)

This commit is contained in:
Oliver Eyton-Williams
2025-08-27 19:15:36 +02:00
committed by GitHub
parent 918e0abb9d
commit 12b5905c60
34 changed files with 208 additions and 258 deletions
-14
View File
@@ -7,7 +7,6 @@ interface MockChallengeNodes {
id: string; id: string;
block: string; block: string;
title: string; title: string;
isPrivate: boolean;
superBlock: string; superBlock: string;
dashedName: string; dashedName: string;
}; };
@@ -23,7 +22,6 @@ const mockChallengeNodes: MockChallengeNodes[] = [
id: 'a', id: 'a',
block: 'block-a', block: 'block-a',
title: 'Challenge One', title: 'Challenge One',
isPrivate: false,
superBlock: 'super-block-one', superBlock: 'super-block-one',
dashedName: 'challenge-one' dashedName: 'challenge-one'
} }
@@ -37,7 +35,6 @@ const mockChallengeNodes: MockChallengeNodes[] = [
id: 'b', id: 'b',
block: 'block-a', block: 'block-a',
title: 'Challenge Two', title: 'Challenge Two',
isPrivate: false,
superBlock: 'super-block-one', superBlock: 'super-block-one',
dashedName: 'challenge-two' dashedName: 'challenge-two'
} }
@@ -51,7 +48,6 @@ const mockChallengeNodes: MockChallengeNodes[] = [
id: 'c', id: 'c',
block: 'block-b', block: 'block-b',
title: 'Challenge One', title: 'Challenge One',
isPrivate: false,
superBlock: 'super-block-one', superBlock: 'super-block-one',
dashedName: 'challenge-one' dashedName: 'challenge-one'
} }
@@ -66,7 +62,6 @@ const mockChallengeNodes: MockChallengeNodes[] = [
id: 'd', id: 'd',
block: 'block-b', block: 'block-b',
title: 'Challenge Two', title: 'Challenge Two',
isPrivate: false,
superBlock: 'super-block-one', superBlock: 'super-block-one',
dashedName: 'challenge-two' dashedName: 'challenge-two'
} }
@@ -80,7 +75,6 @@ const mockChallengeNodes: MockChallengeNodes[] = [
id: 'e', id: 'e',
block: 'block-c', block: 'block-c',
title: 'Challenge One', title: 'Challenge One',
isPrivate: true,
superBlock: 'super-block-one', superBlock: 'super-block-one',
dashedName: 'challenge-one' dashedName: 'challenge-one'
} }
@@ -94,7 +88,6 @@ const mockChallengeNodes: MockChallengeNodes[] = [
id: 'f', id: 'f',
block: 'block-a', block: 'block-a',
title: 'Challenge One', title: 'Challenge One',
isPrivate: false,
superBlock: 'super-block-two', superBlock: 'super-block-two',
dashedName: 'challenge-one' dashedName: 'challenge-one'
} }
@@ -108,7 +101,6 @@ const mockChallengeNodes: MockChallengeNodes[] = [
id: 'g', id: 'g',
block: 'block-a', block: 'block-a',
title: 'Challenge Two', title: 'Challenge Two',
isPrivate: false,
superBlock: 'super-block-two', superBlock: 'super-block-two',
dashedName: 'challenge-two' dashedName: 'challenge-two'
} }
@@ -122,7 +114,6 @@ const mockChallengeNodes: MockChallengeNodes[] = [
id: 'h', id: 'h',
block: 'block-b', block: 'block-b',
title: 'Challenge One', title: 'Challenge One',
isPrivate: false,
superBlock: 'super-block-two', superBlock: 'super-block-two',
dashedName: 'challenge-one' dashedName: 'challenge-one'
} }
@@ -136,7 +127,6 @@ const mockChallengeNodes: MockChallengeNodes[] = [
id: 'i', id: 'i',
block: 'block-b', block: 'block-b',
title: 'Challenge Two', title: 'Challenge Two',
isPrivate: false,
superBlock: 'super-block-two', superBlock: 'super-block-two',
dashedName: 'challenge-two' dashedName: 'challenge-two'
} }
@@ -150,7 +140,6 @@ const mockChallengeNodes: MockChallengeNodes[] = [
id: 'j', id: 'j',
block: 'block-a', block: 'block-a',
title: 'Challenge One', title: 'Challenge One',
isPrivate: false,
superBlock: 'super-block-three', superBlock: 'super-block-three',
dashedName: 'challenge-one' dashedName: 'challenge-one'
} }
@@ -164,7 +153,6 @@ const mockChallengeNodes: MockChallengeNodes[] = [
id: 'k', id: 'k',
block: 'block-c', block: 'block-c',
title: 'Challenge Two', title: 'Challenge Two',
isPrivate: false,
superBlock: 'super-block-three', superBlock: 'super-block-three',
dashedName: 'challenge-two' dashedName: 'challenge-two'
} }
@@ -178,7 +166,6 @@ const mockChallengeNodes: MockChallengeNodes[] = [
id: 'l', id: 'l',
block: 'block-c', block: 'block-c',
title: 'Challenge Three', title: 'Challenge Three',
isPrivate: false,
superBlock: 'super-block-three', superBlock: 'super-block-three',
dashedName: 'challenge-three' dashedName: 'challenge-three'
} }
@@ -192,7 +179,6 @@ const mockChallengeNodes: MockChallengeNodes[] = [
id: 'm', id: 'm',
block: 'block-a', block: 'block-a',
title: 'Challenge One', title: 'Challenge One',
isPrivate: false,
superBlock: 'super-block-four', superBlock: 'super-block-four',
dashedName: 'challenge-one' dashedName: 'challenge-one'
} }
-1
View File
@@ -210,7 +210,6 @@ export type ChallengeNode = {
notes: string; notes: string;
prerequisites: PrerequisiteChallenge[]; prerequisites: PrerequisiteChallenge[];
isLocked: boolean; isLocked: boolean;
isPrivate: boolean;
order: number; order: number;
questions: Question[]; questions: Question[];
quizzes: Quiz[]; quizzes: Quiz[];
@@ -63,7 +63,6 @@ const defaultProps = {
notes: 'mockNotes', notes: 'mockNotes',
prerequisites: [] as PrerequisiteChallenge[], prerequisites: [] as PrerequisiteChallenge[],
isLocked: false, isLocked: false,
isPrivate: false,
order: 1, order: 1,
questions: [] as Question[], questions: [] as Question[],
assignments: ['mockAssignment'], assignments: ['mockAssignment'],
-1
View File
@@ -45,7 +45,6 @@ exports.buildChallenges = async function buildChallenges() {
}, []); }, []);
const builtChallenges = blocks const builtChallenges = blocks
.filter(block => !block.isPrivate)
.map(({ challenges }) => challenges) .map(({ challenges }) => challenges)
.reduce((accu, current) => accu.concat(current), []); .reduce((accu, current) => accu.concat(current), []);
return builtChallenges; return builtChallenges;
@@ -102,8 +102,6 @@ exports.createChallengePages = function (
id, id,
isLastChallengeInBlock isLastChallengeInBlock
} = node.challenge; } = node.challenge;
// TODO: challengeType === 7 and isPrivate are the same, right? If so, we
// should remove one of them.
createPage({ createPage({
path: slug, path: slug,
-1
View File
@@ -147,7 +147,6 @@ function addMetaToChallenge(challenge, meta) {
challenge.superOrder = meta.superOrder; challenge.superOrder = meta.superOrder;
challenge.challengeOrder = challengeOrderIndex; challenge.challengeOrder = challengeOrderIndex;
challenge.isLastChallengeInBlock = isLastChallengeInBlock; challenge.isLastChallengeInBlock = isLastChallengeInBlock;
challenge.isPrivate = challenge.isPrivate || meta.isPrivate;
challenge.required = (meta.required || []).concat(challenge.required || []); challenge.required = (meta.required || []).concat(challenge.required || []);
challenge.template = meta.template; challenge.template = meta.template;
challenge.helpCategory = challenge.helpCategory || meta.helpCategory; challenge.helpCategory = challenge.helpCategory || meta.helpCategory;
@@ -3,7 +3,6 @@ id: 688f1daf0133dbe2a36b140b
title: A1 Professional Chinese Certification title: A1 Professional Chinese Certification
certification: a1-professional-chinese-certification certification: a1-professional-chinese-certification
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: 688f1daf0133dbe2a36b140b - id: 688f1daf0133dbe2a36b140b
title: "Dialogue 1: PLACEHOLDER" title: "Dialogue 1: PLACEHOLDER"
@@ -3,7 +3,6 @@ id: 651dd7e01d697d0aab7833b7
title: A2 English for Developers Certification title: A2 English for Developers Certification
certification: a2-english-for-developers certification: a2-english-for-developers
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: 6721db5d9f0c116e6a0fe25a - id: 6721db5d9f0c116e6a0fe25a
title: A2 English for Developers Certification Exam title: A2 English for Developers Certification Exam
@@ -3,7 +3,6 @@ id: 682c3153086dd7cabe7f48bc
title: A2 Professional Chinese Certification title: A2 Professional Chinese Certification
certification: a2-professional-chinese-certification certification: a2-professional-chinese-certification
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: 682c2753317b88f1ecdad894 - id: 682c2753317b88f1ecdad894
title: "Dialogue 1: PLACEHOLDER" title: "Dialogue 1: PLACEHOLDER"
@@ -3,7 +3,6 @@ id: 681a6b22e5a782fe3459984a
title: A2 Professional Spanish Certification title: A2 Professional Spanish Certification
certification: a2-professional-spanish-certification certification: a2-professional-spanish-certification
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: 681a8796e5a782fe3459984b - id: 681a8796e5a782fe3459984b
title: "Dialogue 1: PLACEHOLDER" title: "Dialogue 1: PLACEHOLDER"
@@ -3,7 +3,6 @@ id: 66607e53317411dd5e8aae21
title: B1 English for Developers Certification title: B1 English for Developers Certification
certification: b1-english-for-developers certification: b1-english-for-developers
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: 66607e5b317411dd5e8aae22 - id: 66607e5b317411dd5e8aae22
title: "Dialogue 1: I'm Tom" title: "Dialogue 1: I'm Tom"
@@ -3,7 +3,6 @@ id: 561add10cb82ac38a17523bc
title: Back End Development and APIs Certification title: Back End Development and APIs Certification
certification: back-end-development-and-apis certification: back-end-development-and-apis
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: bd7158d8c443edefaeb5bdef - id: bd7158d8c443edefaeb5bdef
title: Timestamp Microservice title: Timestamp Microservice
@@ -3,7 +3,6 @@ id: 61531b20cc9dfa2741a5b800
title: College Algebra with Python Certification title: College Algebra with Python Certification
certification: college-algebra-with-python certification: college-algebra-with-python
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: 63d83ff239c73468b059cd3f - id: 63d83ff239c73468b059cd3f
title: Build a Multi-Function Calculator title: Build a Multi-Function Calculator
@@ -2,7 +2,6 @@ id: 5e46fc95ac417301a38fb934
title: Data Analysis with Python Certification title: Data Analysis with Python Certification
certification: data-analysis-with-python certification: data-analysis-with-python
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: 5e46f7e5ac417301a38fb928 - id: 5e46f7e5ac417301a38fb928
title: Mean-Variance-Standard Deviation Calculator title: Mean-Variance-Standard Deviation Calculator
@@ -2,7 +2,6 @@ id: 5a553ca864b52e1d8bceea14
title: Data Visualization Certification title: Data Visualization Certification
certification: data-visualization certification: data-visualization
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: bd7168d8c242eddfaeb5bd13 - id: bd7168d8c242eddfaeb5bd13
title: Visualize Data with a Bar Chart title: Visualize Data with a Bar Chart
@@ -3,7 +3,6 @@ id: 647f7da207d29547b3bee1ba
title: Foundational C# with Microsoft Certification title: Foundational C# with Microsoft Certification
certification: foundational-c-sharp-with-microsoft certification: foundational-c-sharp-with-microsoft
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: 647e22d18acb466c97ccbef8 - id: 647e22d18acb466c97ccbef8
title: Foundational C# with Microsoft Certification Exam title: Foundational C# with Microsoft Certification Exam
@@ -3,7 +3,6 @@ id: 561acd10cb82ac38a17513bc
title: Front End Development Libraries Certification title: Front End Development Libraries Certification
certification: front-end-development-libraries certification: front-end-development-libraries
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: bd7158d8c442eddfaeb5bd13 - id: bd7158d8c442eddfaeb5bd13
title: Build a Random Quote Machine title: Build a Random Quote Machine
@@ -3,7 +3,6 @@ id: 64514fda6c245de4d11eb7bb
title: Certified Full Stack Developer title: Certified Full Stack Developer
certification: full-stack-developer certification: full-stack-developer
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: 645147516c245de4d11eb7ba - id: 645147516c245de4d11eb7ba
title: Certified Full Stack Developer Exam title: Certified Full Stack Developer Exam
@@ -2,7 +2,6 @@ id: 5e6021435ac9d0ecd8b94b00
title: Information Security Certification title: Information Security Certification
certification: information-security certification: information-security
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: 587d824a367417b2b2512c44 - id: 587d824a367417b2b2512c44
title: Stock Price Checker title: Stock Price Checker
@@ -2,7 +2,6 @@ id: 658180220947283cdc0689ce
title: JavaScript Algorithms and Data Structures Certification title: JavaScript Algorithms and Data Structures Certification
certification: javascript-algorithms-and-data-structures-v8 certification: javascript-algorithms-and-data-structures-v8
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: 657bdc55a322aae1eac3838f - id: 657bdc55a322aae1eac3838f
title: Build a Palindrome Checker title: Build a Palindrome Checker
@@ -2,7 +2,6 @@ id: 561abd10cb81ac38a17513bc
title: Legacy JavaScript Algorithms and Data Structures Certification title: Legacy JavaScript Algorithms and Data Structures Certification
certification: javascript-algorithms-and-data-structures certification: javascript-algorithms-and-data-structures
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: aaa48de84e1ecc7c742e1124 - id: aaa48de84e1ecc7c742e1124
title: Palindrome Checker title: Palindrome Checker
@@ -2,7 +2,6 @@ id: 660add10cb82ac38a17513be
title: Legacy Back End Certification title: Legacy Back End Certification
certification: legacy-back-end certification: legacy-back-end
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: bd7158d8c443edefaeb5bdef - id: bd7158d8c443edefaeb5bdef
title: Timestamp Microservice title: Timestamp Microservice
@@ -2,7 +2,6 @@ id: 561add10cb82ac39a17513bc
title: Legacy Data Visualization Certification title: Legacy Data Visualization Certification
certification: legacy-data-visualization certification: legacy-data-visualization
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: bd7157d8c242eddfaeb5bd13 - id: bd7157d8c242eddfaeb5bd13
title: Build a Markdown Previewer title: Build a Markdown Previewer
@@ -2,7 +2,6 @@ id: 561add10cb82ac38a17513be
title: Legacy Front End Certification title: Legacy Front End Certification
certification: legacy-front-end certification: legacy-front-end
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: bd7158d8c242eddfaeb5bd13 - id: bd7158d8c242eddfaeb5bd13
title: Build a Personal Portfolio Webpage title: Build a Personal Portfolio Webpage
@@ -2,7 +2,6 @@ id: 561add10cb82ac38a17213bd
title: Legacy Full Stack Certification title: Legacy Full Stack Certification
certification: legacy-full-stack certification: legacy-full-stack
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: 561add10cb82ac38a17513bc - id: 561add10cb82ac38a17513bc
title: Responsive Web Design Certification title: Responsive Web Design Certification
@@ -2,7 +2,6 @@ id: 561add10cb82ac38a17213bc
title: Legacy Information Security and Quality Assurance Certification title: Legacy Information Security and Quality Assurance Certification
certification: legacy-information-security-and-quality-assurance certification: legacy-information-security-and-quality-assurance
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: 587d8249367417b2b2512c41 - id: 587d8249367417b2b2512c41
title: Metric-Imperial Converter title: Metric-Imperial Converter
@@ -2,7 +2,6 @@ id: 5e46fc95ac417301a38fb935
title: Machine Learning with Python Certification title: Machine Learning with Python Certification
certification: machine-learning-with-python certification: machine-learning-with-python
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: 5e46f8d6ac417301a38fb92d - id: 5e46f8d6ac417301a38fb92d
title: Rock Paper Scissors title: Rock Paper Scissors
@@ -2,7 +2,6 @@ id: 5e611829481575a52dc59c0e
title: Quality Assurance Certification title: Quality Assurance Certification
certification: quality-assurance certification: quality-assurance
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: 587d8249367417b2b2512c41 - id: 587d8249367417b2b2512c41
title: Metric-Imperial Converter title: Metric-Imperial Converter
@@ -2,7 +2,6 @@ id: 606243f50267e718b1e755f4
title: Relational Database Certification title: Relational Database Certification
certification: relational-database certification: relational-database
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: 5f1a4ef5d5d6b5ab580fc6ae - id: 5f1a4ef5d5d6b5ab580fc6ae
title: Celestial Bodies Database title: Celestial Bodies Database
@@ -2,7 +2,6 @@ id: 561add10cb82ac38a17513bc
title: Responsive Web Design Certification title: Responsive Web Design Certification
certification: responsive-web-design certification: responsive-web-design
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: bd7158d8c442eddfaeb5bd18 - id: bd7158d8c442eddfaeb5bd18
title: Build a Tribute Page title: Build a Tribute Page
@@ -2,7 +2,6 @@ id: 5e44431b903586ffb414c951
title: Scientific Computing with Python Certification title: Scientific Computing with Python Certification
certification: scientific-computing-with-python certification: scientific-computing-with-python
challengeType: 7 challengeType: 7
isPrivate: true
tests: tests:
- id: 5e44412c903586ffb414c94c - id: 5e44412c903586ffb414c94c
title: Arithmetic Formatter title: Arithmetic Formatter
+205 -208
View File
@@ -126,219 +126,216 @@ const quizJoi = Joi.object().keys({
.required() .required()
}); });
const schema = Joi.object() const schema = Joi.object().keys({
.keys({ block: Joi.string().regex(slugRE).required(),
block: Joi.string().regex(slugRE).required(), blockId: Joi.objectId(),
blockId: Joi.objectId(), blockType: Joi.when('superBlock', {
blockType: Joi.when('superBlock', { is: [...chapterBasedSuperBlocks, ...catalogSuperBlocks],
is: [...chapterBasedSuperBlocks, ...catalogSuperBlocks], then: Joi.valid(
then: Joi.valid( 'workshop',
'workshop', 'lab',
'lab', 'lecture',
'lecture', 'review',
'review', 'quiz',
'quiz', 'exam'
'exam'
).required(),
otherwise: Joi.valid(null)
}),
blockLayout: Joi.valid(
'challenge-list',
'challenge-grid',
'dialogue-grid',
'link',
'project-list',
'legacy-challenge-list',
'legacy-link',
'legacy-challenge-grid'
).required(), ).required(),
challengeOrder: Joi.number(), otherwise: Joi.valid(null)
chapter: Joi.string().when('superBlock', { }),
is: chapterBasedSuperBlocks, blockLayout: Joi.valid(
then: Joi.required(), 'challenge-list',
otherwise: Joi.optional() 'challenge-grid',
}), 'dialogue-grid',
certification: Joi.string().regex(slugWithSlashRE), 'link',
challengeType: Joi.number().min(0).max(30).required(), 'project-list',
checksum: Joi.number(), 'legacy-challenge-list',
// TODO: require this only for normal challenges, not certs 'legacy-link',
dashedName: Joi.string().regex(slugRE), 'legacy-challenge-grid'
demoType: Joi.string().valid('onClick', 'onLoad'), ).required(),
description: Joi.when('challengeType', { challengeOrder: Joi.number(),
is: [ chapter: Joi.string().when('superBlock', {
challengeTypes.step, is: chapterBasedSuperBlocks,
challengeTypes.video, then: Joi.required(),
challengeTypes.multipleChoice, otherwise: Joi.optional()
challengeTypes.fillInTheBlank }),
], certification: Joi.string().regex(slugWithSlashRE),
then: Joi.string().allow(''), challengeType: Joi.number().min(0).max(30).required(),
otherwise: Joi.string().required() checksum: Joi.number(),
}), // TODO: require this only for normal challenges, not certs
disableLoopProtectTests: Joi.boolean().required(), dashedName: Joi.string().regex(slugRE),
disableLoopProtectPreview: Joi.boolean().required(), demoType: Joi.string().valid('onClick', 'onLoad'),
explanation: Joi.when('challengeType', { description: Joi.when('challengeType', {
is: [challengeTypes.multipleChoice, challengeTypes.fillInTheBlank], is: [
then: Joi.string() challengeTypes.step,
}), challengeTypes.video,
challengeFiles: Joi.array().items(fileJoi), challengeTypes.multipleChoice,
guideUrl: Joi.string().uri({ scheme: 'https' }), challengeTypes.fillInTheBlank
hasEditableBoundaries: Joi.boolean(), ],
helpCategory: Joi.valid( then: Joi.string().allow(''),
'JavaScript', otherwise: Joi.string().required()
'HTML-CSS', }),
'Python', disableLoopProtectTests: Joi.boolean().required(),
'Backend Development', disableLoopProtectPreview: Joi.boolean().required(),
'C-Sharp', explanation: Joi.when('challengeType', {
'English', is: [challengeTypes.multipleChoice, challengeTypes.fillInTheBlank],
'Odin', then: Joi.string()
'Euler', }),
'Rosetta' challengeFiles: Joi.array().items(fileJoi),
), guideUrl: Joi.string().uri({ scheme: 'https' }),
isLastChallengeInBlock: Joi.boolean().required(), hasEditableBoundaries: Joi.boolean(),
videoUrl: Joi.string().allow(''), helpCategory: Joi.valid(
fillInTheBlank: Joi.object().keys({ 'JavaScript',
sentence: Joi.string().required(), 'HTML-CSS',
blanks: Joi.array() 'Python',
.items( 'Backend Development',
Joi.object().keys({ 'C-Sharp',
answer: Joi.string().required(), 'English',
feedback: Joi.string().allow(null) 'Odin',
}) 'Euler',
) 'Rosetta'
.required() ).required(),
}), isLastChallengeInBlock: Joi.boolean().required(),
forumTopicId: Joi.number(), videoUrl: Joi.string().allow(''),
id: Joi.objectId().required(), fillInTheBlank: Joi.object().keys({
instructions: Joi.string().when('challengeType', { sentence: Joi.string().required(),
is: [challengeTypes.pythonProject, challengeTypes.codeAllyCert], blanks: Joi.array()
then: Joi.string().min(1).required(),
otherwise: Joi.string().allow('')
}),
isComingSoon: Joi.bool(),
isLocked: Joi.bool(),
isPrivate: Joi.bool(),
module: Joi.string().when('superBlock', {
is: chapterBasedSuperBlocks,
then: Joi.required(),
otherwise: Joi.optional()
}),
msTrophyId: Joi.when('challengeType', {
is: [challengeTypes.msTrophy],
then: Joi.string().required()
}),
notes: Joi.string().allow(''),
order: Joi.number(),
prerequisites: Joi.when('challengeType', {
is: [challengeTypes.exam],
then: Joi.array().items(prerequisitesJoi)
}),
// video challenges only:
videoId: Joi.when('challengeType', {
is: [challengeTypes.video],
then: Joi.string().required()
}),
videoLocaleIds: Joi.when('challengeType', {
is: challengeTypes.video,
then: Joi.object().keys({
espanol: Joi.string(),
italian: Joi.string(),
portuguese: Joi.string()
})
}),
bilibiliIds: Joi.when('challengeType', {
is: challengeTypes.video,
then: Joi.object().keys({
aid: Joi.number().required(),
bvid: Joi.string().required(),
cid: Joi.number().required()
})
}),
questions: Joi.when('challengeType', {
is: [
challengeTypes.video,
challengeTypes.multipleChoice,
challengeTypes.theOdinProject
],
then: Joi.array().items(questionJoi).min(1).required(),
otherwise: Joi.array().length(0)
}),
quizzes: Joi.when('challengeType', {
is: challengeTypes.quiz,
then: Joi.array().items(quizJoi).min(1).required(),
otherwise: Joi.forbidden()
}),
required: Joi.array().items(
Joi.object().keys({
link: Joi.string(),
raw: Joi.bool(),
src: Joi.string(),
crossDomain: Joi.bool()
})
),
assignments: Joi.when('challengeType', {
is: challengeTypes.dialogue,
then: Joi.array().items(Joi.string()).required(),
otherwise: Joi.array().items(Joi.string())
}),
scene: Joi.object().keys({
setup: setupJoi.required(),
commands: Joi.array()
.items(commandJoi)
.unique(
(a, b) =>
a.dialogue &&
b.dialogue &&
!(
(a.startTime < b.startTime &&
a.finishTime < b.finishTime &&
a.finishTime <= b.startTime) ||
(b.startTime < a.startTime &&
b.finishTime < a.finishTime &&
b.finishTime <= a.startTime)
)
)
.messages({
'array.unique': 'Dialogues must not have overlapping times.'
})
}),
solutions: Joi.array().items(Joi.array().items(fileJoi).min(1)),
superBlock: Joi.string().regex(slugWithSlashRE),
superOrder: Joi.number(),
suborder: Joi.number(),
hooks: Joi.object().keys({
beforeAll: Joi.string().allow(''),
beforeEach: Joi.string().allow(''),
afterEach: Joi.string().allow('')
}),
tests: Joi.array()
.items( .items(
// public challenges
Joi.object().keys({ Joi.object().keys({
id: Joi.string().allow(''), answer: Joi.string().required(),
text: Joi.string().required(), feedback: Joi.string().allow(null)
testString: Joi.string().allow('').required()
}),
// our tests used in certification verification
Joi.object().keys({
id: Joi.string().required(),
title: Joi.string().required()
}) })
) )
.required(), .required()
template: Joi.string().allow(''), }),
title: Joi.string().required(), forumTopicId: Joi.number(),
transcript: Joi.when('challengeType', { id: Joi.objectId().required(),
is: [challengeTypes.generic, challengeTypes.video], instructions: Joi.string().when('challengeType', {
then: Joi.string() is: [challengeTypes.pythonProject, challengeTypes.codeAllyCert],
}), then: Joi.string().min(1).required(),
translationPending: Joi.bool().required(), otherwise: Joi.string().allow('')
url: Joi.when('challengeType', { }),
is: [challengeTypes.codeAllyPractice, challengeTypes.codeAllyCert], isComingSoon: Joi.bool(),
then: Joi.string().required() isLocked: Joi.bool(),
}), module: Joi.string().when('superBlock', {
usesMultifileEditor: Joi.boolean() is: chapterBasedSuperBlocks,
}) then: Joi.required(),
.xor('helpCategory', 'isPrivate'); otherwise: Joi.optional()
}),
msTrophyId: Joi.when('challengeType', {
is: [challengeTypes.msTrophy],
then: Joi.string().required()
}),
notes: Joi.string().allow(''),
order: Joi.number(),
prerequisites: Joi.when('challengeType', {
is: [challengeTypes.exam],
then: Joi.array().items(prerequisitesJoi)
}),
// video challenges only:
videoId: Joi.when('challengeType', {
is: [challengeTypes.video],
then: Joi.string().required()
}),
videoLocaleIds: Joi.when('challengeType', {
is: challengeTypes.video,
then: Joi.object().keys({
espanol: Joi.string(),
italian: Joi.string(),
portuguese: Joi.string()
})
}),
bilibiliIds: Joi.when('challengeType', {
is: challengeTypes.video,
then: Joi.object().keys({
aid: Joi.number().required(),
bvid: Joi.string().required(),
cid: Joi.number().required()
})
}),
questions: Joi.when('challengeType', {
is: [
challengeTypes.video,
challengeTypes.multipleChoice,
challengeTypes.theOdinProject
],
then: Joi.array().items(questionJoi).min(1).required(),
otherwise: Joi.array().length(0)
}),
quizzes: Joi.when('challengeType', {
is: challengeTypes.quiz,
then: Joi.array().items(quizJoi).min(1).required(),
otherwise: Joi.forbidden()
}),
required: Joi.array().items(
Joi.object().keys({
link: Joi.string(),
raw: Joi.bool(),
src: Joi.string(),
crossDomain: Joi.bool()
})
),
assignments: Joi.when('challengeType', {
is: challengeTypes.dialogue,
then: Joi.array().items(Joi.string()).required(),
otherwise: Joi.array().items(Joi.string())
}),
scene: Joi.object().keys({
setup: setupJoi.required(),
commands: Joi.array()
.items(commandJoi)
.unique(
(a, b) =>
a.dialogue &&
b.dialogue &&
!(
(a.startTime < b.startTime &&
a.finishTime < b.finishTime &&
a.finishTime <= b.startTime) ||
(b.startTime < a.startTime &&
b.finishTime < a.finishTime &&
b.finishTime <= a.startTime)
)
)
.messages({
'array.unique': 'Dialogues must not have overlapping times.'
})
}),
solutions: Joi.array().items(Joi.array().items(fileJoi).min(1)),
superBlock: Joi.string().regex(slugWithSlashRE),
superOrder: Joi.number(),
suborder: Joi.number(),
hooks: Joi.object().keys({
beforeAll: Joi.string().allow(''),
beforeEach: Joi.string().allow(''),
afterEach: Joi.string().allow('')
}),
tests: Joi.array()
.items(
// public challenges
Joi.object().keys({
id: Joi.string().allow(''),
text: Joi.string().required(),
testString: Joi.string().allow('').required()
}),
// our tests used in certification verification
Joi.object().keys({
id: Joi.string().required(),
title: Joi.string().required()
})
)
.required(),
template: Joi.string().allow(''),
title: Joi.string().required(),
transcript: Joi.when('challengeType', {
is: [challengeTypes.generic, challengeTypes.video],
then: Joi.string()
}),
translationPending: Joi.bool().required(),
url: Joi.when('challengeType', {
is: [challengeTypes.codeAllyPractice, challengeTypes.codeAllyCert],
then: Joi.string().required()
}),
usesMultifileEditor: Joi.boolean()
});
exports.challengeSchemaValidator = () => { exports.challengeSchemaValidator = () => {
return challenge => schema.validate(challenge); return challenge => schema.validate(challenge);
-1
View File
@@ -27,7 +27,6 @@ interface Challenge {
superBlock: string; superBlock: string;
dashedName: string; dashedName: string;
solutions: Solution[]; solutions: Solution[];
isPrivate?: boolean;
} }
interface block { interface block {
+1 -2
View File
@@ -61,8 +61,7 @@
{ {
"title": "Challenge Nine", "title": "Challenge Nine",
"block": "Block One", "block": "Block One",
"superBlock": "super-block-b", "superBlock": "super-block-b"
"isPrivate": true
}, },
{ {
"title": "Challenge Ten", "title": "Challenge Ten",