diff --git a/client/gatsby-node.js b/client/gatsby-node.js
index b7d96010ef..6fa003143a 100644
--- a/client/gatsby-node.js
+++ b/client/gatsby-node.js
@@ -20,13 +20,6 @@ const createByIdentityMap = {
exports.onCreateNode = function onCreateNode({ node, actions, getNode }) {
const { createNodeField } = actions;
- if (node.internal.type === 'ChallengeNode') {
- const { tests = [], block, dashedName, superBlock } = node;
- const slug = `/learn/${superBlock}/${block}/${dashedName}`;
- createNodeField({ node, name: 'slug', value: slug });
- createNodeField({ node, name: 'blockName', value: blockNameify(block) });
- createNodeField({ node, name: 'tests', value: tests });
- }
if (node.internal.type === 'MarkdownRemark') {
const slug = createFilePath({ node, getNode });
@@ -71,37 +64,45 @@ exports.createPages = function createPages({ graphql, actions, reporter }) {
graphql(`
{
allChallengeNode(
- sort: { fields: [superOrder, order, challengeOrder] }
+ sort: {
+ fields: [
+ challenge___superOrder
+ challenge___order
+ challenge___challengeOrder
+ ]
+ }
) {
edges {
node {
- block
- challengeType
- fields {
- slug
+ challenge {
+ block
+ challengeType
+ fields {
+ slug
+ }
+ id
+ order
+ required {
+ link
+ src
+ }
+ challengeOrder
+ challengeFiles {
+ name
+ ext
+ contents
+ head
+ tail
+ }
+ solutions {
+ contents
+ ext
+ }
+ superBlock
+ superOrder
+ template
+ usesMultifileEditor
}
- id
- order
- required {
- link
- src
- }
- challengeOrder
- challengeFiles {
- name
- ext
- contents
- head
- tail
- }
- solutions {
- contents
- ext
- }
- superBlock
- superOrder
- template
- usesMultifileEditor
}
}
}
@@ -137,12 +138,22 @@ exports.createPages = function createPages({ graphql, actions, reporter }) {
);
const blocks = uniq(
- result.data.allChallengeNode.edges.map(({ node: { block } }) => block)
+ result.data.allChallengeNode.edges.map(
+ ({
+ node: {
+ challenge: { block }
+ }
+ }) => block
+ )
).map(block => blockNameify(block));
const superBlocks = uniq(
result.data.allChallengeNode.edges.map(
- ({ node: { superBlock } }) => superBlock
+ ({
+ node: {
+ challenge: { superBlock }
+ }
+ }) => superBlock
)
);
@@ -256,6 +267,9 @@ exports.createSchemaCustomization = ({ actions }) => {
const { createTypes } = actions;
const typeDefs = `
type ChallengeNode implements Node {
+ challenge: Challenge
+ }
+ type Challenge {
challengeFiles: [FileContents]
notes: String
url: String
diff --git a/client/plugins/fcc-source-challenges/create-challenge-nodes.js b/client/plugins/fcc-source-challenges/create-challenge-nodes.js
index 394364f033..7e5e80b27b 100644
--- a/client/plugins/fcc-source-challenges/create-challenge-nodes.js
+++ b/client/plugins/fcc-source-challenges/create-challenge-nodes.js
@@ -1,4 +1,5 @@
const crypto = require('crypto');
+const { blockNameify } = require('../../../utils/block-nameify');
function createChallengeNode(challenge, reporter) {
// challengeType 11 is for video challenges (they only have instructions)
@@ -31,6 +32,17 @@ function createChallengeNode(challenge, reporter) {
type: challenge.challengeType === 7 ? 'CertificateNode' : 'ChallengeNode'
};
+ if (internal.type === 'ChallengeNode') {
+ const { tests = [], block, dashedName, superBlock } = challenge;
+ const slug = `/learn/${superBlock}/${block}/${dashedName}`;
+
+ challenge.fields = {
+ slug,
+ blockName: blockNameify(block),
+ tests
+ };
+ }
+
return JSON.parse(
JSON.stringify(
Object.assign(
@@ -41,7 +53,8 @@ function createChallengeNode(challenge, reporter) {
internal,
sourceInstanceName: 'challenge'
},
- challenge
+ { challenge },
+ { id: crypto.randomUUID() }
)
)
);
diff --git a/client/src/__mocks__/challenge-nodes.js b/client/src/__mocks__/challenge-nodes.js
index 87f4ef28ed..6a4ce63b0e 100644
--- a/client/src/__mocks__/challenge-nodes.js
+++ b/client/src/__mocks__/challenge-nodes.js
@@ -1,136 +1,158 @@
const mockChallengeNodes = [
{
- fields: {
- slug: '/super-block-one/block-a/challenge-one',
- blockName: 'Block A'
- },
- id: 'a',
- block: 'block-a',
- title: 'Challenge One',
- isPrivate: false,
- superBlock: 'super-block-one',
- dashedName: 'challenge-one'
+ challenge: {
+ fields: {
+ slug: '/super-block-one/block-a/challenge-one',
+ blockName: 'Block A'
+ },
+ id: 'a',
+ block: 'block-a',
+ title: 'Challenge One',
+ isPrivate: false,
+ superBlock: 'super-block-one',
+ dashedName: 'challenge-one'
+ }
},
{
- fields: {
- slug: '/super-block-one/block-a/challenge-two',
- blockName: 'Block A'
- },
- id: 'b',
- block: 'block-a',
- title: 'Challenge Two',
- isPrivate: false,
- superBlock: 'super-block-one',
- dashedName: 'challenge-two'
+ challenge: {
+ fields: {
+ slug: '/super-block-one/block-a/challenge-two',
+ blockName: 'Block A'
+ },
+ id: 'b',
+ block: 'block-a',
+ title: 'Challenge Two',
+ isPrivate: false,
+ superBlock: 'super-block-one',
+ dashedName: 'challenge-two'
+ }
},
{
- fields: {
- slug: '/super-block-one/block-b/challenge-one',
- blockName: 'Block B'
- },
- id: 'c',
- block: 'block-b',
- title: 'Challenge One',
- isPrivate: false,
- superBlock: 'super-block-one',
- dashedName: 'challenge-one'
+ challenge: {
+ fields: {
+ slug: '/super-block-one/block-b/challenge-one',
+ blockName: 'Block B'
+ },
+ id: 'c',
+ block: 'block-b',
+ title: 'Challenge One',
+ isPrivate: false,
+ superBlock: 'super-block-one',
+ dashedName: 'challenge-one'
+ }
},
{
- fields: {
- slug: '/super-block-one/block-b/challenge-two',
- blockName: 'Block B'
- },
+ challenge: {
+ fields: {
+ slug: '/super-block-one/block-b/challenge-two',
+ blockName: 'Block B'
+ },
- id: 'd',
- block: 'block-b',
- title: 'Challenge Two',
- isPrivate: false,
- superBlock: 'super-block-one',
- dashedName: 'challenge-two'
+ id: 'd',
+ block: 'block-b',
+ title: 'Challenge Two',
+ isPrivate: false,
+ superBlock: 'super-block-one',
+ dashedName: 'challenge-two'
+ }
},
{
- fields: {
- slug: '/super-block-one/block-c/challenge-one',
- blockName: 'Block C'
- },
- id: 'e',
- block: 'block-c',
- title: 'Challenge One',
- isPrivate: true,
- superBlock: 'super-block-one',
- dashedName: 'challenge-one'
+ challenge: {
+ fields: {
+ slug: '/super-block-one/block-c/challenge-one',
+ blockName: 'Block C'
+ },
+ id: 'e',
+ block: 'block-c',
+ title: 'Challenge One',
+ isPrivate: true,
+ superBlock: 'super-block-one',
+ dashedName: 'challenge-one'
+ }
},
{
- fields: {
- slug: '/super-block-two/block-a/challenge-one',
- blockName: 'Block A'
- },
- id: 'f',
- block: 'block-a',
- title: 'Challenge One',
- isPrivate: false,
- superBlock: 'super-block-two',
- dashedName: 'challenge-one'
+ challenge: {
+ fields: {
+ slug: '/super-block-two/block-a/challenge-one',
+ blockName: 'Block A'
+ },
+ id: 'f',
+ block: 'block-a',
+ title: 'Challenge One',
+ isPrivate: false,
+ superBlock: 'super-block-two',
+ dashedName: 'challenge-one'
+ }
},
{
- fields: {
- slug: '/super-block-two/block-a/challenge-two',
- blockName: 'Block A'
- },
- id: 'g',
- block: 'block-a',
- title: 'Challenge Two',
- isPrivate: false,
- superBlock: 'super-block-two',
- dashedName: 'challenge-two'
+ challenge: {
+ fields: {
+ slug: '/super-block-two/block-a/challenge-two',
+ blockName: 'Block A'
+ },
+ id: 'g',
+ block: 'block-a',
+ title: 'Challenge Two',
+ isPrivate: false,
+ superBlock: 'super-block-two',
+ dashedName: 'challenge-two'
+ }
},
{
- fields: {
- slug: '/super-block-two/block-b/challenge-one',
- blockName: 'Block B'
- },
- id: 'h',
- block: 'block-b',
- title: 'Challenge One',
- isPrivate: false,
- superBlock: 'super-block-two',
- dashedName: 'challenge-one'
+ challenge: {
+ fields: {
+ slug: '/super-block-two/block-b/challenge-one',
+ blockName: 'Block B'
+ },
+ id: 'h',
+ block: 'block-b',
+ title: 'Challenge One',
+ isPrivate: false,
+ superBlock: 'super-block-two',
+ dashedName: 'challenge-one'
+ }
},
{
- fields: {
- slug: '/super-block-two/block-b/challenge-two',
- blockName: 'Block B'
- },
- id: 'i',
- block: 'block-b',
- title: 'Challenge Two',
- isPrivate: false,
- superBlock: 'super-block-two',
- dashedName: 'challenge-two'
+ challenge: {
+ fields: {
+ slug: '/super-block-two/block-b/challenge-two',
+ blockName: 'Block B'
+ },
+ id: 'i',
+ block: 'block-b',
+ title: 'Challenge Two',
+ isPrivate: false,
+ superBlock: 'super-block-two',
+ dashedName: 'challenge-two'
+ }
},
{
- fields: {
- slug: '/super-block-three/block-a/challenge-one',
- blockName: 'Block A'
- },
- id: 'j',
- block: 'block-a',
- title: 'Challenge One',
- isPrivate: false,
- superBlock: 'super-block-three',
- dashedName: 'challenge-one'
+ challenge: {
+ fields: {
+ slug: '/super-block-three/block-a/challenge-one',
+ blockName: 'Block A'
+ },
+ id: 'j',
+ block: 'block-a',
+ title: 'Challenge One',
+ isPrivate: false,
+ superBlock: 'super-block-three',
+ dashedName: 'challenge-one'
+ }
},
{
- fields: {
- slug: '/super-block-three/block-c/challenge-two',
- blockName: 'Block C'
- },
- id: 'k',
- block: 'block-c',
- title: 'Challenge Two',
- isPrivate: false,
- superBlock: 'super-block-three',
- dashedName: 'challenge-two'
+ challenge: {
+ fields: {
+ slug: '/super-block-three/block-c/challenge-two',
+ blockName: 'Block C'
+ },
+ id: 'k',
+ block: 'block-c',
+ title: 'Challenge Two',
+ isPrivate: false,
+ superBlock: 'super-block-three',
+ dashedName: 'challenge-two'
+ }
}
];
diff --git a/client/src/components/Map/index.tsx b/client/src/components/Map/index.tsx
index 024a739156..6988f52487 100644
--- a/client/src/components/Map/index.tsx
+++ b/client/src/components/Map/index.tsx
@@ -42,19 +42,19 @@ const linkSpacingStyle = {
function renderLandingMap(nodes: ChallengeNode[]) {
nodes = nodes.filter(
- node => node.superBlock !== SuperBlocks.CodingInterviewPrep
+ ({ challenge }) => challenge.superBlock !== SuperBlocks.CodingInterviewPrep
);
return (
- {nodes.map((node, i) => (
+ {nodes.map(({ challenge }, i) => (
-
- {generateIconComponent(node.superBlock, 'map-icon')}
- {i18next.t(`intro:${node.superBlock}.title`)}
+ {generateIconComponent(challenge.superBlock, 'map-icon')}
+ {i18next.t(`intro:${challenge.superBlock}.title`)}
@@ -68,18 +68,20 @@ function renderLearnMap(
nodes: ChallengeNode[],
currentSuperBlock: MapProps['currentSuperBlock']
) {
- nodes = nodes.filter(node => node.superBlock !== currentSuperBlock);
+ nodes = nodes.filter(
+ ({ challenge }) => challenge.superBlock !== currentSuperBlock
+ );
return curriculumLocale === 'english' ? (
- {nodes.map((node, i) => (
+ {nodes.map(({ challenge }, i) => (
-
- {generateIconComponent(node.superBlock, 'map-icon')}
- {createSuperBlockTitle(node.superBlock)}
+ {generateIconComponent(challenge.superBlock, 'map-icon')}
+ {createSuperBlockTitle(challenge.superBlock)}
@@ -88,16 +90,18 @@ function renderLearnMap(
) : (
{nodes
- .filter(node => isAuditedCert(curriculumLocale, node.superBlock))
- .map((node, i) => (
+ .filter(({ challenge }) =>
+ isAuditedCert(curriculumLocale, challenge.superBlock)
+ )
+ .map(({ challenge }, i) => (
-
- {generateIconComponent(node.superBlock, 'map-icon')}
- {createSuperBlockTitle(node.superBlock)}
+ {generateIconComponent(challenge.superBlock, 'map-icon')}
+ {createSuperBlockTitle(challenge.superBlock)}
@@ -115,16 +119,19 @@ function renderLearnMap(
{nodes
- .filter(node => !isAuditedCert(curriculumLocale, node.superBlock))
- .map((node, i) => (
+ .filter(
+ ({ challenge }) =>
+ !isAuditedCert(curriculumLocale, challenge.superBlock)
+ )
+ .map(({ challenge }, i) => (
-
- {generateIconComponent(node.superBlock, 'map-icon')}
- {createSuperBlockTitle(node.superBlock)}
+ {generateIconComponent(challenge.superBlock, 'map-icon')}
+ {createSuperBlockTitle(challenge.superBlock)}
@@ -145,12 +152,14 @@ export function Map({
const data: MapData = useStaticQuery(graphql`
query SuperBlockNodes {
allChallengeNode(
- sort: { fields: [superOrder] }
- filter: { order: { eq: 0 }, challengeOrder: { eq: 0 } }
+ sort: { fields: [challenge___superOrder] }
+ filter: { challenge: { order: { eq: 0 }, challengeOrder: { eq: 0 } } }
) {
nodes {
- superBlock
- dashedName
+ challenge {
+ superBlock
+ dashedName
+ }
}
}
}
diff --git a/client/src/components/profile/components/TimeLine.tsx b/client/src/components/profile/components/TimeLine.tsx
index 0505e63b5a..0558289d16 100644
--- a/client/src/components/profile/components/TimeLine.tsx
+++ b/client/src/components/profile/components/TimeLine.tsx
@@ -269,11 +269,13 @@ function useIdToNameMap(): Map {
allChallengeNode {
edges {
node {
- fields {
- slug
+ challenge {
+ fields {
+ slug
+ }
+ id
+ title
}
- id
- title
}
}
}
@@ -289,12 +291,14 @@ function useIdToNameMap(): Map {
edges.forEach(
({
node: {
- // @ts-expect-error Graphql needs typing
- id,
- // @ts-expect-error Graphql needs typing
- title,
- // @ts-expect-error Graphql needs typing
- fields: { slug }
+ challenge: {
+ // @ts-expect-error Graphql needs typing
+ id,
+ // @ts-expect-error Graphql needs typing
+ title,
+ // @ts-expect-error Graphql needs typing
+ fields: { slug }
+ }
}
}) => {
idToNameMap.set(id, { challengeTitle: title, challengePath: slug });
diff --git a/client/src/components/profile/components/time-line.test.tsx b/client/src/components/profile/components/time-line.test.tsx
index 833f5bc735..b5044188eb 100644
--- a/client/src/components/profile/components/time-line.test.tsx
+++ b/client/src/components/profile/components/time-line.test.tsx
@@ -12,29 +12,35 @@ beforeEach(() => {
edges: [
{
node: {
- fields: {
- slug: ''
- },
- id: '5e46f802ac417301a38fb92b',
- title: 'Page View Time Series Visualizer'
+ challenge: {
+ fields: {
+ slug: ''
+ },
+ id: '5e46f802ac417301a38fb92b',
+ title: 'Page View Time Series Visualizer'
+ }
}
},
{
node: {
- fields: {
- slug: ''
- },
- id: '5e4f5c4b570f7e3a4949899f',
- title: 'Sea Level Predictor'
+ challenge: {
+ fields: {
+ slug: ''
+ },
+ id: '5e4f5c4b570f7e3a4949899f',
+ title: 'Sea Level Predictor'
+ }
}
},
{
node: {
- fields: {
- slug: ''
- },
- id: '5e46f7f8ac417301a38fb92a',
- title: 'Medical Data Visualizer'
+ challenge: {
+ fields: {
+ slug: ''
+ },
+ id: '5e46f7f8ac417301a38fb92a',
+ title: 'Medical Data Visualizer'
+ }
}
}
]
diff --git a/client/src/pages/learn.tsx b/client/src/pages/learn.tsx
index 13022530a7..1e3e39d58a 100644
--- a/client/src/pages/learn.tsx
+++ b/client/src/pages/learn.tsx
@@ -53,7 +53,9 @@ interface LearnPageProps {
user: User;
data: {
challengeNode: {
- fields: Slug;
+ challenge: {
+ fields: Slug;
+ };
};
};
executeGA: (payload: Record) => void;
@@ -70,7 +72,9 @@ function LearnPage({
executeGA,
data: {
challengeNode: {
- fields: { slug }
+ challenge: {
+ fields: { slug }
+ }
}
}
}: LearnPageProps) {
@@ -117,9 +121,11 @@ export default connect(mapStateToProps, mapDispatchToProps)(LearnPage);
export const query = graphql`
query FirstChallenge {
- challengeNode(order: { eq: 0 }, challengeOrder: { eq: 0 }) {
- fields {
- slug
+ challengeNode(challenge: { order: { eq: 0 }, challengeOrder: { eq: 0 } }) {
+ challenge {
+ fields {
+ slug
+ }
}
}
}
diff --git a/client/src/redux/prop-types.ts b/client/src/redux/prop-types.ts
index 65af9e912c..30a7c41260 100644
--- a/client/src/redux/prop-types.ts
+++ b/client/src/redux/prop-types.ts
@@ -128,55 +128,57 @@ export interface VideoLocaleIds {
}
export type ChallengeNode = {
- block: string;
- challengeOrder: number;
- challengeType: number;
- dashedName: string;
- description: string;
- challengeFiles: ChallengeFiles;
- fields: Fields;
- forumTopicId: number;
- guideUrl: string;
- head: string[];
- helpCategory: string;
- id: string;
- instructions: string;
- isComingSoon: boolean;
- internal?: {
- content: string;
- contentDigest: string;
+ challenge: {
+ block: string;
+ challengeOrder: number;
+ challengeType: number;
+ dashedName: string;
description: string;
- fieldOwners: string[];
- ignoreType: boolean | null;
- mediaType: string;
- owner: string;
- type: string;
+ challengeFiles: ChallengeFiles;
+ fields: Fields;
+ forumTopicId: number;
+ guideUrl: string;
+ head: string[];
+ helpCategory: string;
+ id: string;
+ instructions: string;
+ isComingSoon: boolean;
+ internal?: {
+ content: string;
+ contentDigest: string;
+ description: string;
+ fieldOwners: string[];
+ ignoreType: boolean | null;
+ mediaType: string;
+ owner: string;
+ type: string;
+ };
+ notes: string;
+ removeComments: boolean;
+ isLocked: boolean;
+ isPrivate: boolean;
+ order: number;
+ question: Question;
+ required: Required[];
+ solutions: {
+ [T in FileKey]: FileKeyChallenge;
+ };
+ sourceInstanceName: string;
+ superOrder: number;
+ superBlock: SuperBlocks;
+ tail: string[];
+ template: string;
+ tests: Test[];
+ time: string;
+ title: string;
+ translationPending: boolean;
+ url: string;
+ usesMultifileEditor: boolean;
+ videoId: string;
+ videoLocaleIds?: VideoLocaleIds;
+ bilibiliIds?: BilibiliIds;
+ videoUrl: string;
};
- notes: string;
- removeComments: boolean;
- isLocked: boolean;
- isPrivate: boolean;
- order: number;
- question: Question;
- required: Required[];
- solutions: {
- [T in FileKey]: FileKeyChallenge;
- };
- sourceInstanceName: string;
- superOrder: number;
- superBlock: SuperBlocks;
- tail: string[];
- template: string;
- tests: Test[];
- time: string;
- title: string;
- translationPending: boolean;
- url: string;
- usesMultifileEditor: boolean;
- videoId: string;
- videoLocaleIds?: VideoLocaleIds;
- bilibiliIds?: BilibiliIds;
- videoUrl: string;
};
export type AllChallengeNode = {
diff --git a/client/src/templates/Challenges/classic/show.tsx b/client/src/templates/Challenges/classic/show.tsx
index 1173f93848..8e3ec4b5d8 100644
--- a/client/src/templates/Challenges/classic/show.tsx
+++ b/client/src/templates/Challenges/classic/show.tsx
@@ -212,7 +212,9 @@ class ShowClassic extends Component {
componentDidMount() {
const {
data: {
- challengeNode: { title }
+ challengeNode: {
+ challenge: { title }
+ }
}
} = this.props;
this.initializeComponent(title);
@@ -222,16 +224,20 @@ class ShowClassic extends Component {
const {
data: {
challengeNode: {
- title: prevTitle,
- fields: { tests: prevTests }
+ challenge: {
+ title: prevTitle,
+ fields: { tests: prevTests }
+ }
}
}
} = prevProps;
const {
data: {
challengeNode: {
- title: currentTitle,
- fields: { tests: currTests }
+ challenge: {
+ title: currentTitle,
+ fields: { tests: currTests }
+ }
}
}
} = this.props;
@@ -250,11 +256,13 @@ class ShowClassic extends Component {
openModal,
data: {
challengeNode: {
- challengeFiles,
- fields: { tests },
- challengeType,
- removeComments,
- helpCategory
+ challenge: {
+ challengeFiles,
+ fields: { tests },
+ challengeType,
+ removeComments,
+ helpCategory
+ }
}
},
pageContext: {
@@ -282,7 +290,7 @@ class ShowClassic extends Component {
cancelTests();
}
- getChallenge = () => this.props.data.challengeNode;
+ getChallenge = () => this.props.data.challengeNode.challenge;
getBlockNameTitle(t: TFunction) {
const { block, superBlock, title } = this.getChallenge();
@@ -337,8 +345,10 @@ class ShowClassic extends Component {
challengeFiles,
data: {
challengeNode: {
- fields: { tests },
- usesMultifileEditor
+ challenge: {
+ fields: { tests },
+ usesMultifileEditor
+ }
}
}
} = this.props;
@@ -489,40 +499,42 @@ export default connect(
export const query = graphql`
query ClassicChallenge($slug: String!) {
- challengeNode(fields: { slug: { eq: $slug } }) {
- block
- title
- description
- instructions
- notes
- removeComments
- challengeType
- helpCategory
- videoUrl
- superBlock
- translationPending
- forumTopicId
- fields {
- blockName
- slug
- tests {
- text
- testString
+ challengeNode(challenge: { fields: { slug: { eq: $slug } } }) {
+ challenge {
+ block
+ title
+ description
+ instructions
+ notes
+ removeComments
+ challengeType
+ helpCategory
+ videoUrl
+ superBlock
+ translationPending
+ forumTopicId
+ fields {
+ blockName
+ slug
+ tests {
+ text
+ testString
+ }
+ }
+ required {
+ link
+ src
+ }
+ usesMultifileEditor
+ challengeFiles {
+ fileKey
+ ext
+ name
+ contents
+ head
+ tail
+ editableRegionBoundaries
}
- }
- required {
- link
- src
- }
- usesMultifileEditor
- challengeFiles {
- fileKey
- ext
- name
- contents
- head
- tail
- editableRegionBoundaries
}
}
}
diff --git a/client/src/templates/Challenges/codeally/show.tsx b/client/src/templates/Challenges/codeally/show.tsx
index d990c3f7ec..72defa8383 100644
--- a/client/src/templates/Challenges/codeally/show.tsx
+++ b/client/src/templates/Challenges/codeally/show.tsx
@@ -49,7 +49,9 @@ class ShowCodeAlly extends Component {
const {
updateChallengeMeta,
data: {
- challengeNode: { challengeType, title }
+ challengeNode: {
+ challenge: { challengeType, title }
+ }
},
pageContext: { challengeMeta }
} = this.props;
@@ -60,9 +62,11 @@ class ShowCodeAlly extends Component {
const {
data: {
challengeNode: {
- title,
- fields: { blockName },
- url
+ challenge: {
+ title,
+ fields: { blockName },
+ url
+ }
}
},
webhookToken = null
@@ -94,12 +98,14 @@ export default connect(mapStateToProps, mapDispatchToProps)(ShowCodeAlly);
// GraphQL
export const query = graphql`
query CodeAllyChallenge($slug: String!) {
- challengeNode(fields: { slug: { eq: $slug } }) {
- title
- challengeType
- url
- fields {
- blockName
+ challengeNode(challenge: { fields: { slug: { eq: $slug } } }) {
+ challenge {
+ title
+ challengeType
+ url
+ fields {
+ blockName
+ }
}
}
}
diff --git a/client/src/templates/Challenges/components/completion-modal.tsx b/client/src/templates/Challenges/components/completion-modal.tsx
index f26613904e..1ccc4ba33e 100644
--- a/client/src/templates/Challenges/components/completion-modal.tsx
+++ b/client/src/templates/Challenges/components/completion-modal.tsx
@@ -280,13 +280,23 @@ const useCurrentBlockIds = (blockName: string) => {
allChallengeNode: { edges }
}: { allChallengeNode: AllChallengeNode } = useStaticQuery(graphql`
query getCurrentBlockNodes {
- allChallengeNode(sort: { fields: [superOrder, order, challengeOrder] }) {
+ allChallengeNode(
+ sort: {
+ fields: [
+ challenge___superOrder
+ challenge___order
+ challenge___challengeOrder
+ ]
+ }
+ ) {
edges {
node {
- fields {
- blockName
+ challenge {
+ fields {
+ blockName
+ }
+ id
}
- id
}
}
}
@@ -294,9 +304,9 @@ const useCurrentBlockIds = (blockName: string) => {
`);
const currentBlockIds = edges
- .filter(edge => edge.node.fields.blockName === blockName)
+ .filter(edge => edge.node.challenge.fields.blockName === blockName)
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
- .map(edge => edge.node.id);
+ .map(edge => edge.node.challenge.id);
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return currentBlockIds;
};
diff --git a/client/src/templates/Challenges/projects/backend/Show.tsx b/client/src/templates/Challenges/projects/backend/Show.tsx
index 4e4fb9cc95..7d62c424d7 100644
--- a/client/src/templates/Challenges/projects/backend/Show.tsx
+++ b/client/src/templates/Challenges/projects/backend/Show.tsx
@@ -123,16 +123,20 @@ class BackEnd extends Component {
const {
data: {
challengeNode: {
- title: prevTitle,
- fields: { tests: prevTests }
+ challenge: {
+ title: prevTitle,
+ fields: { tests: prevTests }
+ }
}
}
} = prevProps;
const {
data: {
challengeNode: {
- title: currentTitle,
- fields: { tests: currTests }
+ challenge: {
+ title: currentTitle,
+ fields: { tests: currTests }
+ }
}
}
} = this.props;
@@ -149,10 +153,12 @@ class BackEnd extends Component {
updateChallengeMeta,
data: {
challengeNode: {
- fields: { tests },
- title,
- challengeType,
- helpCategory
+ challenge: {
+ fields: { tests },
+ title,
+ challengeType,
+ helpCategory
+ }
}
},
pageContext: { challengeMeta }
@@ -182,15 +188,17 @@ class BackEnd extends Component {
const {
data: {
challengeNode: {
- fields: { blockName },
- challengeType,
- forumTopicId,
- title,
- description,
- instructions,
- translationPending,
- superBlock,
- block
+ challenge: {
+ fields: { blockName },
+ challengeType,
+ forumTopicId,
+ title,
+ description,
+ instructions,
+ translationPending,
+ superBlock,
+ block
+ }
}
},
isChallengeCompleted,
@@ -278,22 +286,24 @@ export default connect(
export const query = graphql`
query BackendChallenge($slug: String!) {
- challengeNode(fields: { slug: { eq: $slug } }) {
- forumTopicId
- title
- description
- instructions
- challengeType
- helpCategory
- superBlock
- block
- translationPending
- fields {
- blockName
- slug
- tests {
- text
- testString
+ challengeNode(challenge: { fields: { slug: { eq: $slug } } }) {
+ challenge {
+ forumTopicId
+ title
+ description
+ instructions
+ challengeType
+ helpCategory
+ superBlock
+ block
+ translationPending
+ fields {
+ blockName
+ slug
+ tests {
+ text
+ testString
+ }
}
}
}
diff --git a/client/src/templates/Challenges/projects/frontend/Show.tsx b/client/src/templates/Challenges/projects/frontend/Show.tsx
index 2b3905a39b..7c5c6ba789 100644
--- a/client/src/templates/Challenges/projects/frontend/Show.tsx
+++ b/client/src/templates/Challenges/projects/frontend/Show.tsx
@@ -76,7 +76,9 @@ class Project extends Component {
const {
challengeMounted,
data: {
- challengeNode: { title, challengeType, helpCategory }
+ challengeNode: {
+ challenge: { title, challengeType, helpCategory }
+ }
},
pageContext: { challengeMeta },
updateChallengeMeta
@@ -94,13 +96,17 @@ class Project extends Component {
componentDidUpdate(prevProps: ProjectProps): void {
const {
data: {
- challengeNode: { title: prevTitle }
+ challengeNode: {
+ challenge: { title: prevTitle }
+ }
}
} = prevProps;
const {
challengeMounted,
data: {
- challengeNode: { title: currentTitle, challengeType, helpCategory }
+ challengeNode: {
+ challenge: { title: currentTitle, challengeType, helpCategory }
+ }
},
pageContext: { challengeMeta },
updateChallengeMeta
@@ -130,15 +136,17 @@ class Project extends Component {
const {
data: {
challengeNode: {
- challengeType,
- fields: { blockName },
- forumTopicId,
- title,
- description,
- instructions,
- superBlock,
- block,
- translationPending
+ challenge: {
+ challengeType,
+ fields: { blockName },
+ forumTopicId,
+ title,
+ description,
+ instructions,
+ superBlock,
+ block,
+ translationPending
+ }
}
},
isChallengeCompleted,
@@ -215,19 +223,21 @@ export default connect(
export const query = graphql`
query ProjectChallenge($slug: String!) {
- challengeNode(fields: { slug: { eq: $slug } }) {
- forumTopicId
- title
- description
- instructions
- challengeType
- helpCategory
- superBlock
- block
- translationPending
- fields {
- blockName
- slug
+ challengeNode(challenge: { fields: { slug: { eq: $slug } } }) {
+ challenge {
+ forumTopicId
+ title
+ description
+ instructions
+ challengeType
+ helpCategory
+ superBlock
+ block
+ translationPending
+ fields {
+ blockName
+ slug
+ }
}
}
}
diff --git a/client/src/templates/Challenges/video/Show.tsx b/client/src/templates/Challenges/video/Show.tsx
index 677da5c5a0..c078ebc8bd 100644
--- a/client/src/templates/Challenges/video/Show.tsx
+++ b/client/src/templates/Challenges/video/Show.tsx
@@ -97,7 +97,9 @@ class ShowVideo extends Component {
const {
challengeMounted,
data: {
- challengeNode: { title, challengeType, helpCategory }
+ challengeNode: {
+ challenge: { title, challengeType, helpCategory }
+ }
},
pageContext: { challengeMeta },
updateChallengeMeta
@@ -115,13 +117,17 @@ class ShowVideo extends Component {
componentDidUpdate(prevProps: ShowVideoProps): void {
const {
data: {
- challengeNode: { title: prevTitle }
+ challengeNode: {
+ challenge: { title: prevTitle }
+ }
}
} = prevProps;
const {
challengeMounted,
data: {
- challengeNode: { title: currentTitle, challengeType, helpCategory }
+ challengeNode: {
+ challenge: { title: currentTitle, challengeType, helpCategory }
+ }
},
pageContext: { challengeMeta },
updateChallengeMeta
@@ -169,16 +175,18 @@ class ShowVideo extends Component {
const {
data: {
challengeNode: {
- fields: { blockName },
- title,
- description,
- superBlock,
- block,
- translationPending,
- videoId,
- videoLocaleIds,
- bilibiliIds,
- question: { text, answers, solution }
+ challenge: {
+ fields: { blockName },
+ title,
+ description,
+ superBlock,
+ block,
+ translationPending,
+ videoId,
+ videoLocaleIds,
+ bilibiliIds,
+ question: { text, answers, solution }
+ }
}
},
openCompletionModal,
@@ -313,34 +321,36 @@ export default connect(
export const query = graphql`
query VideoChallenge($slug: String!) {
- challengeNode(fields: { slug: { eq: $slug } }) {
- videoId
- videoLocaleIds {
- espanol
- italian
- portuguese
+ challengeNode(challenge: { fields: { slug: { eq: $slug } } }) {
+ challenge {
+ videoId
+ videoLocaleIds {
+ espanol
+ italian
+ portuguese
+ }
+ bilibiliIds {
+ aid
+ bvid
+ cid
+ }
+ title
+ description
+ challengeType
+ helpCategory
+ superBlock
+ block
+ fields {
+ blockName
+ slug
+ }
+ question {
+ text
+ answers
+ solution
+ }
+ translationPending
}
- bilibiliIds {
- aid
- bvid
- cid
- }
- title
- description
- challengeType
- helpCategory
- superBlock
- block
- fields {
- blockName
- slug
- }
- question {
- text
- answers
- solution
- }
- translationPending
}
}
`;
diff --git a/client/src/templates/Introduction/components/block.tsx b/client/src/templates/Introduction/components/block.tsx
index 6d0db6050f..62392e1692 100644
--- a/client/src/templates/Introduction/components/block.tsx
+++ b/client/src/templates/Introduction/components/block.tsx
@@ -101,7 +101,7 @@ export class Block extends Component {
} = this.props;
let completedCount = 0;
- const challengesWithCompleted = challenges.map(challenge => {
+ const challengesWithCompleted = challenges.map(({ challenge }) => {
const { id } = challenge;
const isCompleted = completedChallengeIds.some(
(completedChallengeId: string) => completedChallengeId === id
@@ -112,7 +112,7 @@ export class Block extends Component {
return { ...challenge, isCompleted };
});
- const isProjectBlock = challenges.some(challenge => {
+ const isProjectBlock = challenges.some(({ challenge }) => {
const isJsProject =
challenge.order === 10 && challenge.challengeType === 5;
diff --git a/client/src/templates/Introduction/intro.tsx b/client/src/templates/Introduction/intro.tsx
index 5dfd6a78ab..aadb8d8854 100644
--- a/client/src/templates/Introduction/intro.tsx
+++ b/client/src/templates/Introduction/intro.tsx
@@ -21,7 +21,7 @@ function renderMenuItems({
edges?: Array<{ node: ChallengeNode }>;
}) {
return edges
- .map(({ node }) => node)
+ .map(({ node: { challenge } }) => challenge)
.map(({ title, fields: { slug } }) => (
{title}
@@ -42,7 +42,8 @@ function IntroductionPage({
html,
frontmatter: { block }
} = markdownRemark;
- const firstLesson = allChallengeNode && allChallengeNode.edges[0].node;
+ const firstLesson =
+ allChallengeNode && allChallengeNode.edges[0].node.challenge;
const firstLessonPath = firstLesson
? firstLesson.fields.slug
: '/strange-place';
@@ -97,15 +98,23 @@ export const query = graphql`
html
}
allChallengeNode(
- filter: { block: { eq: $block } }
- sort: { fields: [superOrder, order, challengeOrder] }
+ filter: { challenge: { block: { eq: $block } } }
+ sort: {
+ fields: [
+ challenge___superOrder
+ challenge___order
+ challenge___challengeOrder
+ ]
+ }
) {
edges {
node {
- fields {
- slug
+ challenge {
+ fields {
+ slug
+ }
+ title
}
- title
}
}
}
diff --git a/client/src/templates/Introduction/super-block-intro.tsx b/client/src/templates/Introduction/super-block-intro.tsx
index cf9a9702c8..cb224fcc0e 100644
--- a/client/src/templates/Introduction/super-block-intro.tsx
+++ b/client/src/templates/Introduction/super-block-intro.tsx
@@ -141,15 +141,15 @@ const SuperBlockIntroductionPage = (props: SuperBlockProp) => {
if (isSignedIn) {
// see if currentChallenge is in this superBlock
const currentChallengeEdge = edges.find(
- edge => edge.node.id === currentChallengeId
+ edge => edge.node.challenge.id === currentChallengeId
);
return currentChallengeEdge
- ? currentChallengeEdge.node.block
- : edge.node.block;
+ ? currentChallengeEdge.node.challenge.block
+ : edge.node.challenge.block;
}
- return edge.node.block;
+ return edge.node.challenge.block;
};
const initializeExpandedState = () => {
@@ -173,7 +173,9 @@ const SuperBlockIntroductionPage = (props: SuperBlockProp) => {
} = props;
const nodesForSuperBlock = edges.map(({ node }) => node);
- const blockDashedNames = uniq(nodesForSuperBlock.map(({ block }) => block));
+ const blockDashedNames = uniq(
+ nodesForSuperBlock.map(({ challenge: { block } }) => block)
+ );
const i18nSuperBlock = t(`intro:${superBlock}.title`);
const i18nTitle =
superBlock === SuperBlocks.CodingInterviewPrep
@@ -206,7 +208,7 @@ const SuperBlockIntroductionPage = (props: SuperBlockProp) => {
node.block === blockDashedName
+ node => node.challenge.block === blockDashedName
)}
superBlock={superBlock}
/>
@@ -263,22 +265,30 @@ export const query = graphql`
}
}
allChallengeNode(
- sort: { fields: [superOrder, order, challengeOrder] }
- filter: { superBlock: { eq: $superBlock } }
+ sort: {
+ fields: [
+ challenge___superOrder
+ challenge___order
+ challenge___challengeOrder
+ ]
+ }
+ filter: { challenge: { superBlock: { eq: $superBlock } } }
) {
edges {
node {
- fields {
- slug
- blockName
+ challenge {
+ fields {
+ slug
+ blockName
+ }
+ id
+ block
+ challengeType
+ title
+ order
+ superBlock
+ dashedName
}
- id
- block
- challengeType
- title
- order
- superBlock
- dashedName
}
}
}
diff --git a/client/utils/gatsby/challenge-page-creator.js b/client/utils/gatsby/challenge-page-creator.js
index e48509f591..e0649fda2c 100644
--- a/client/utils/gatsby/challenge-page-creator.js
+++ b/client/utils/gatsby/challenge-page-creator.js
@@ -45,12 +45,12 @@ const views = {
function getNextChallengePath(_node, index, nodeArray) {
const next = nodeArray[index + 1];
- return next ? next.node.fields.slug : '/learn';
+ return next ? next.node.challenge.fields.slug : '/learn';
}
function getPrevChallengePath(_node, index, nodeArray) {
const prev = nodeArray[index - 1];
- return prev ? prev.node.fields.slug : '/learn';
+ return prev ? prev.node.challenge.fields.slug : '/learn';
}
function getTemplateComponent(challengeType) {
@@ -58,7 +58,7 @@ function getTemplateComponent(challengeType) {
}
exports.createChallengePages = function (createPage) {
- return function ({ node: challenge }, index, allChallengeEdges) {
+ return function ({ node: { challenge } }, index, allChallengeEdges) {
const {
superBlock,
block,
@@ -103,8 +103,8 @@ function getProjectPreviewConfig(challenge, allChallengeEdges) {
const { block, challengeOrder, usesMultifileEditor } = challenge;
const challengesInBlock = allChallengeEdges
- .filter(({ node }) => node.block === block)
- .map(({ node }) => node);
+ .filter(({ node: { challenge } }) => challenge.block === block)
+ .map(({ node: { challenge } }) => challenge);
const lastChallenge = challengesInBlock[challengesInBlock.length - 1];
const solutionToLastChallenge = sortChallengeFiles(
lastChallenge.solutions[0] ?? []