diff --git a/packages/learn/src/__mocks__/intro-nodes.js b/packages/learn/src/__mocks__/intro-nodes.js
new file mode 100644
index 0000000000..031dcb4a7d
--- /dev/null
+++ b/packages/learn/src/__mocks__/intro-nodes.js
@@ -0,0 +1,29 @@
+export default [
+ {
+ fields: {
+ slug: '/super-block-one/block-a'
+ },
+ frontmatter: {
+ block: 'Block A',
+ title: 'Introduction to Block A'
+ }
+ },
+ {
+ fields: {
+ slug: '/super-block-one/block-b'
+ },
+ frontmatter: {
+ block: 'Block B',
+ title: 'Introduction to Block B'
+ }
+ },
+ {
+ fields: {
+ slug: '/super-block-one/block-c'
+ },
+ frontmatter: {
+ block: 'Block C',
+ title: 'Introduction to Block C'
+ }
+ }
+];
diff --git a/packages/learn/src/components/Map/Map.js b/packages/learn/src/components/Map/Map.js
index 4a4d775b9d..f2a83691fc 100644
--- a/packages/learn/src/components/Map/Map.js
+++ b/packages/learn/src/components/Map/Map.js
@@ -9,14 +9,28 @@ import './map.css';
import { ChallengeNode } from '../../redux/propTypes';
const propTypes = {
+ introNodes: PropTypes.arrayOf(
+ PropTypes.shape({
+ fields: PropTypes.shape({ slug: PropTypes.string.isRequired }),
+ frontmatter: PropTypes.shape({
+ title: PropTypes.string.isRequired,
+ block: PropTypes.string.isRequired
+ })
+ })
+ ),
nodes: PropTypes.arrayOf(ChallengeNode)
};
class ShowMap extends PureComponent {
renderSuperBlocks(superBlocks) {
- const { nodes } = this.props;
+ const { nodes, introNodes } = this.props;
return superBlocks.map(superBlock => (
-
+
));
}
diff --git a/packages/learn/src/components/Map/Map.test.js b/packages/learn/src/components/Map/Map.test.js
index f13a748567..69714a9c80 100644
--- a/packages/learn/src/components/Map/Map.test.js
+++ b/packages/learn/src/components/Map/Map.test.js
@@ -7,11 +7,14 @@ import Adapter from 'enzyme-adapter-react-16';
import Map from './Map';
import mockNodes from '../../__mocks__/map-nodes';
+import mockIntroNodes from '../../__mocks__/intro-nodes';
Enzyme.configure({ adapter: new Adapter() });
const renderer = new ShallowRenderer();
test(' snapshot', () => {
- const component = renderer.render();
+ const component = renderer.render(
+
+ );
expect(component).toMatchSnapshot('Map');
});
diff --git a/packages/learn/src/components/Map/__snapshots__/Map.test.js.snap b/packages/learn/src/components/Map/__snapshots__/Map.test.js.snap
index b3de6f94bb..b6ae385dad 100644
--- a/packages/learn/src/components/Map/__snapshots__/Map.test.js.snap
+++ b/packages/learn/src/components/Map/__snapshots__/Map.test.js.snap
@@ -6,6 +6,37 @@ exports[` snapshot: Map 1`] = `
>
snapshot: Map 1`] = `
superBlock="Super Block One"
/>
const propTypes = {
blockDashedName: PropTypes.string,
challenges: PropTypes.array,
+ intro: PropTypes.shape({
+ fields: PropTypes.shape({ slug: PropTypes.string.isRequired }),
+ frontmatter: PropTypes.shape({
+ title: PropTypes.string.isRequired,
+ block: PropTypes.string.isRequired
+ })
+ }),
isExpanded: PropTypes.bool,
toggleBlock: PropTypes.func.isRequired,
toggleMapModal: PropTypes.func.isRequired
@@ -62,22 +69,25 @@ export class Block extends PureComponent {
};
}
- renderChallenges(challenges) {
+ renderChallenges(intro, challenges) {
// TODO: Split this into a Challenge Component and add tests
- return challenges.map(challenge => (
- -
+ return [intro].concat(challenges).map(challenge => (
+
-
- {challenge.title}
+ {challenge.title || challenge.frontmatter.title}
));
}
render() {
- const { challenges, isExpanded } = this.props;
+ const { challenges, isExpanded, intro } = this.props;
const { blockName } = challenges[0].fields;
return (
-
@@ -85,7 +95,7 @@ export class Block extends PureComponent {
{blockName}
- {isExpanded ? this.renderChallenges(challenges) : null}
+ {isExpanded ? this.renderChallenges(intro, challenges) : null}
);
}
diff --git a/packages/learn/src/components/Map/components/Block.test.js b/packages/learn/src/components/Map/components/Block.test.js
index 4ce6f1034c..ec7434e0d5 100644
--- a/packages/learn/src/components/Map/components/Block.test.js
+++ b/packages/learn/src/components/Map/components/Block.test.js
@@ -8,6 +8,7 @@ import sinon from 'sinon';
import { Block } from './Block';
import mockNodes from '../../../__mocks__/map-nodes';
+import mockIntroNodes from '../../../__mocks__/intro-nodes';
Enzyme.configure({ adapter: new Adapter() });
const renderer = new ShallowRenderer();
@@ -19,6 +20,7 @@ test(' not expanded snapshot', () => {
node.block === 'block-a')}
+ intro={mockIntroNodes[0]}
isExpanded={false}
toggleBlock={toggleSpy}
toggleMapModal={toggleMapSpy}
@@ -36,6 +38,7 @@ test(' {
node.block === 'block-a')}
+ intro={mockIntroNodes[0]}
isExpanded={true}
toggleBlock={toggleSpy}
toggleMapModal={toggleMapSpy}
@@ -53,6 +56,7 @@ test(' should handle toggle clicks correctly', () => {
const props = {
blockDashedName: 'block-a',
challenges: mockNodes.filter(node => node.block === 'block-a'),
+ intro: mockIntroNodes[0],
isExpanded: false,
toggleBlock: toggleSpy,
toggleMapModal: toggleMapSpy
diff --git a/packages/learn/src/components/Map/components/SuperBlock.js b/packages/learn/src/components/Map/components/SuperBlock.js
index 2b80825b41..114b3a1467 100644
--- a/packages/learn/src/components/Map/components/SuperBlock.js
+++ b/packages/learn/src/components/Map/components/SuperBlock.js
@@ -4,6 +4,7 @@ import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import uniq from 'lodash/uniq';
+import find from 'lodash/find';
import Block from './Block';
@@ -29,6 +30,15 @@ function mapDispatchToProps(dispatch) {
}
const propTypes = {
+ introNodes: PropTypes.arrayOf(
+ PropTypes.shape({
+ fields: PropTypes.shape({ slug: PropTypes.string.isRequired }),
+ frontmatter: PropTypes.shape({
+ title: PropTypes.string.isRequired,
+ block: PropTypes.string.isRequired
+ })
+ })
+ ),
isExpanded: PropTypes.bool,
nodes: PropTypes.arrayOf(ChallengeNode),
superBlock: PropTypes.string,
@@ -37,7 +47,7 @@ const propTypes = {
export class SuperBlock extends PureComponent {
renderBlock(superBlock) {
- const { nodes } = this.props;
+ const { nodes, introNodes } = this.props;
const blocksForSuperBlock = nodes.filter(
node => node.superBlock === superBlock
);
@@ -53,6 +63,14 @@ export class SuperBlock extends PureComponent {
challenges={blocksForSuperBlock.filter(
node => node.block === blockDashedName
)}
+ intro={find(
+ introNodes,
+ ({ frontmatter: { block } }) =>
+ block
+ .toLowerCase()
+ .split(' ')
+ .join('-') === blockDashedName
+ )}
key={blockDashedName}
/>
))}
diff --git a/packages/learn/src/components/Map/components/SuperBlock.test.js b/packages/learn/src/components/Map/components/SuperBlock.test.js
index e20a663a93..bb35533700 100644
--- a/packages/learn/src/components/Map/components/SuperBlock.test.js
+++ b/packages/learn/src/components/Map/components/SuperBlock.test.js
@@ -8,6 +8,7 @@ import sinon from 'sinon';
import { SuperBlock } from './SuperBlock';
import mockNodes from '../../../__mocks__/map-nodes';
+import mockIntroNodes from '../../../__mocks__/intro-nodes';
Enzyme.configure({ adapter: new Adapter() });
const renderer = new ShallowRenderer();
@@ -15,6 +16,7 @@ const renderer = new ShallowRenderer();
test(' not expanded snapshot', () => {
const toggleSpy = sinon.spy();
const props = {
+ introNodes: mockIntroNodes,
isExpanded: false,
nodes: mockNodes,
superBlock: 'Super Block One',
@@ -29,6 +31,7 @@ test(' not expanded snapshot', () => {
test(' expanded snapshot', () => {
const toggleSpy = sinon.spy();
const props = {
+ introNodes: mockIntroNodes,
isExpanded: true,
nodes: mockNodes,
superBlock: 'Super Block One',
@@ -43,6 +46,7 @@ test(' expanded snapshot', () => {
test(' {
const toggleSpy = sinon.spy();
const props = {
+ introNodes: mockIntroNodes,
isExpanded: false,
nodes: mockNodes,
superBlock: 'Super Block One',
diff --git a/packages/learn/src/components/Map/components/__snapshots__/Block.test.js.snap b/packages/learn/src/components/Map/components/__snapshots__/Block.test.js.snap
index 9fc90a0c03..23c612a05b 100644
--- a/packages/learn/src/components/Map/components/__snapshots__/Block.test.js.snap
+++ b/packages/learn/src/components/Map/components/__snapshots__/Block.test.js.snap
@@ -31,6 +31,16 @@ exports[`
+ -
+
+ Introduction to Block A
+
+
-
diff --git a/packages/learn/src/components/Map/components/__snapshots__/SuperBlock.test.js.snap b/packages/learn/src/components/Map/components/__snapshots__/SuperBlock.test.js.snap
index 269af39495..7e42d881f6 100644
--- a/packages/learn/src/components/Map/components/__snapshots__/SuperBlock.test.js.snap
+++ b/packages/learn/src/components/Map/components/__snapshots__/SuperBlock.test.js.snap
@@ -44,6 +44,17 @@ exports[` expanded snapshot: superBlock-expanded 1`] = `
},
]
}
+ intro={
+ Object {
+ "fields": Object {
+ "slug": "/super-block-one/block-a",
+ },
+ "frontmatter": Object {
+ "block": "Block A",
+ "title": "Introduction to Block A",
+ },
+ }
+ }
/>
expanded snapshot: superBlock-expanded 1`] = `
},
]
}
+ intro={
+ Object {
+ "fields": Object {
+ "slug": "/super-block-one/block-b",
+ },
+ "frontmatter": Object {
+ "block": "Block B",
+ "title": "Introduction to Block B",
+ },
+ }
+ }
/>
expanded snapshot: superBlock-expanded 1`] = `
},
]
}
+ intro={
+ Object {
+ "fields": Object {
+ "slug": "/super-block-one/block-c",
+ },
+ "frontmatter": Object {
+ "block": "Block C",
+ "title": "Introduction to Block C",
+ },
+ }
+ }
/>
diff --git a/packages/learn/src/components/MapModal/index.js b/packages/learn/src/components/MapModal/index.js
index 625b2d981d..2b030128d3 100644
--- a/packages/learn/src/components/MapModal/index.js
+++ b/packages/learn/src/components/MapModal/index.js
@@ -21,12 +21,21 @@ const mapDispatchToProps = dispatch =>
bindActionCreators({ toggleMapModal }, dispatch);
const propTypes = {
+ introNodes: PropTypes.arrayOf(
+ PropTypes.shape({
+ fields: PropTypes.shape({ slug: PropTypes.string.isRequired }),
+ frontmatter: PropTypes.shape({
+ title: PropTypes.string.isRequired,
+ block: PropTypes.string.isRequired
+ })
+ })
+ ),
nodes: PropTypes.arrayOf(ChallengeNode),
show: PropTypes.bool,
toggleMapModal: PropTypes.func.isRequired
};
-function MapModal({ nodes, show, toggleMapModal }) {
+function MapModal({ introNodes, nodes, show, toggleMapModal }) {
return (
-
+
diff --git a/packages/learn/src/layouts/index.js b/packages/learn/src/layouts/index.js
index a547083ee5..05a1d105db 100644
--- a/packages/learn/src/layouts/index.js
+++ b/packages/learn/src/layouts/index.js
@@ -64,7 +64,13 @@ class Layout extends PureComponent {
}
}
render() {
- const { children, data: { allChallengeNode: { edges } } } = this.props;
+ const {
+ children,
+ data: {
+ allChallengeNode: { edges },
+ allMarkdownRemark: { edges: mdEdges }
+ }
+ } = this.props;
return (
{children()}
node)}
nodes={edges
.map(({ node }) => node)
.filter(({ isPrivate }) => !isPrivate)}
@@ -120,5 +127,18 @@ export const query = graphql`
}
}
}
+ allMarkdownRemark(filter: { frontmatter: { block: { ne: null } } }) {
+ edges {
+ node {
+ frontmatter {
+ title
+ block
+ }
+ fields {
+ slug
+ }
+ }
+ }
+ }
}
`;
diff --git a/packages/learn/src/templates/Introduction/intro.css b/packages/learn/src/templates/Introduction/intro.css
index f7b2d16133..ebe740e651 100644
--- a/packages/learn/src/templates/Introduction/intro.css
+++ b/packages/learn/src/templates/Introduction/intro.css
@@ -1,3 +1,7 @@
+.intro-layout {
+ margin-top: 1.45rem;
+}
+
.intro-toc .list-group-item:hover {
background-color: #eee;
}