From 910dd0584cb8658b95a7bf289f1a2ace4a0e8a27 Mon Sep 17 00:00:00 2001 From: mrugesh mohapatra Date: Fri, 1 Jun 2018 03:36:42 +0530 Subject: [PATCH] fix: all things (#124) * fix 'Testing with Chai' 404 error * Remove service worker and unregister old workers from clients * Fix block name in QA and Chai intro * Move the map to the index page * Split test commands, have travis run format on test * Only expand the first block * Remove some margin from p tags on the index page * Learn -> Curriculum link in header * UI Fixes * Use webpack plugin to destroy sercive worker * Add spinner for unknown user state * Fix map placement * Fix vcurriculum button clicks --- packages/learn/.travis.yml | 3 +- packages/learn/gatsby-config.js | 3 +- packages/learn/gatsby-node.js | 4 + packages/learn/package.json | 8 +- .../components/Header/components/UserState.js | 33 ++++- .../learn/src/components/Header/header.css | 7 + packages/learn/src/components/Header/index.js | 2 +- .../src/components/Map/components/Block.js | 13 +- .../components/Map/components/SuperBlock.js | 11 +- .../Map/components/SuperBlock.test.js | 4 +- .../__snapshots__/SuperBlock.test.js.snap | 4 +- packages/learn/src/components/Map/map.css | 1 + .../learn/src/components/Map/redux/index.js | 8 +- packages/learn/src/components/util/spacer.css | 1 + .../index.md | 2 +- packages/learn/src/layouts/global.css | 2 +- packages/learn/src/layouts/index.js | 56 +------- packages/learn/src/layouts/layout.css | 2 +- packages/learn/src/pages/index.css | 4 + packages/learn/src/pages/index.js | 79 ++++++++--- .../learn/src/redux/app/fetch-user-epic.js | 28 +++- packages/learn/src/redux/app/index.js | 9 +- packages/learn/src/redux/propTypes.js | 8 ++ .../src/templates/Challenges/backend/Show.js | 2 +- .../src/templates/Challenges/classic/Show.js | 21 +-- .../Challenges/components/Side-Panel.js | 17 ++- .../Challenges/components/Test-Suite.js | 7 +- .../Challenges/components/Tool-Panel.js | 36 ++--- .../components/icons/{RedFail.js => Fail.js} | 7 +- .../Challenges/components/icons/GreenPass.js | 3 - .../Challenges/components/icons/Initial.js | 55 ++++++++ .../Challenges/components/preview.css | 2 +- .../Challenges/components/test-suite.css | 1 + .../Challenges/components/tool-panel.css | 24 +--- .../src/templates/Challenges/project/Show.js | 4 +- .../Challenges/project/Tool-Panel.js | 42 ++---- .../learn/src/templates/Introduction/Intro.js | 25 ++-- packages/learn/yarn.lock | 133 ++++-------------- 38 files changed, 330 insertions(+), 341 deletions(-) rename packages/learn/src/templates/Challenges/components/icons/{RedFail.js => Fail.js} (91%) create mode 100644 packages/learn/src/templates/Challenges/components/icons/Initial.js diff --git a/packages/learn/.travis.yml b/packages/learn/.travis.yml index 19e06c3e69b..852cdc44542 100644 --- a/packages/learn/.travis.yml +++ b/packages/learn/.travis.yml @@ -5,4 +5,5 @@ node_js: - "lts/*" cache: directories: - - "node_modules" \ No newline at end of file + - "node_modules" +script: "yarn test:ci" \ No newline at end of file diff --git a/packages/learn/gatsby-config.js b/packages/learn/gatsby-config.js index 8488e014da1..52dd531a8d3 100644 --- a/packages/learn/gatsby-config.js +++ b/packages/learn/gatsby-config.js @@ -68,7 +68,6 @@ module.exports = { fonts: ['Lato:400,400i,500'] } }, - 'gatsby-plugin-sitemap', - 'gatsby-plugin-offline' + 'gatsby-plugin-sitemap' ] }; diff --git a/packages/learn/gatsby-node.js b/packages/learn/gatsby-node.js index e0e8b2c5b6b..89a3d557027 100644 --- a/packages/learn/gatsby-node.js +++ b/packages/learn/gatsby-node.js @@ -104,6 +104,7 @@ exports.createPages = ({ graphql, boundActionCreators }) => { }; const webpack = require('webpack'); +const RmServiceWorkerPlugin = require('webpack-remove-serviceworker-plugin'); const generateBabelConfig = require('gatsby/dist/utils/babel-config'); exports.modifyWebpackConfig = ({ config, stage }) => { @@ -143,6 +144,9 @@ exports.modifyWebpackConfig = ({ config, stage }) => { ) } ]); + config.plugin('RemoveServiceWorkerPlugin', RmServiceWorkerPlugin, [ + { filename: 'sw.js' } + ]); }); }; /* eslint-disable prefer-object-spread/prefer-object-spread */ diff --git a/packages/learn/package.json b/packages/learn/package.json index 28935e90569..5b48827557c 100644 --- a/packages/learn/package.json +++ b/packages/learn/package.json @@ -23,7 +23,6 @@ "gatsby": "^1.9.243", "gatsby-link": "^1.6.39", "gatsby-plugin-google-fonts": "^0.0.4", - "gatsby-plugin-offline": "^1.0.15", "gatsby-plugin-react-helmet": "^2.0.8", "gatsby-plugin-react-next": "^1.0.11", "gatsby-plugin-sitemap": "^1.2.21", @@ -48,6 +47,7 @@ "react-redux": "^5.0.7", "react-reflex": "^2.2.1", "react-router-redux": "^5.0.0-alpha.9", + "react-spinkit": "^3.0.0", "react-test-renderer": "^16.3.1", "redux": "^3.7.2", "redux-actions": "^2.3.0", @@ -57,7 +57,8 @@ "rxjs": "^5.5.7", "store": "^2.0.12", "uglifyjs-webpack-plugin": "^1.2.4", - "validator": "^9.4.1" + "validator": "^9.4.1", + "webpack-remove-serviceworker-plugin": "^1.0.0" }, "keywords": [ "gatsby" @@ -77,7 +78,8 @@ "lint:src": "eslint ./src . --fix", "lint:utils": "eslint ./utils . --fix", "pretty": "yarn format && yarn lint", - "test": "yarn format && jest src", + "test": "jest src", + "test:ci": "yarn format && jest src", "test:watch": "jest --watch src" }, "jest": { diff --git a/packages/learn/src/components/Header/components/UserState.js b/packages/learn/src/components/Header/components/UserState.js index 92ad460a9e6..4facf59b45f 100644 --- a/packages/learn/src/components/Header/components/UserState.js +++ b/packages/learn/src/components/Header/components/UserState.js @@ -2,24 +2,45 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { createSelector } from 'reselect'; +import Spinner from 'react-spinkit'; -import { isSignedInSelector } from '../../../redux/app'; +import { + isSignedInSelector, + userStateLoadingSelector +} from '../../../redux/app'; import Login from './Login'; import SignedIn from './SignedIn'; -const mapStateToProps = createSelector(isSignedInSelector, isSignedIn => ({ - isSignedIn -})); +const mapStateToProps = createSelector( + userStateLoadingSelector, + isSignedInSelector, + (showLoading, isSignedIn) => ({ + isSignedIn, + showLoading + }) +); const propTypes = { email: PropTypes.string, isSignedIn: PropTypes.bool, - name: PropTypes.string + name: PropTypes.string, + showLoading: PropTypes.bool }; class UserState extends PureComponent { render() { - const { isSignedIn } = this.props; + const { isSignedIn, showLoading } = this.props; + if (showLoading) { + return ( + + ); + } return isSignedIn ? : ; } } diff --git a/packages/learn/src/components/Header/header.css b/packages/learn/src/components/Header/header.css index ab7b1fddb8b..05dc6cfe4ff 100644 --- a/packages/learn/src/components/Header/header.css +++ b/packages/learn/src/components/Header/header.css @@ -70,6 +70,13 @@ header { font-weight: 500; } +.user-state-spinner { + height: 40px; +} + +.user-state-spinner > div { + animation-duration: 1.5s !important; +} /* Search bar */ .fcc_searchBar { diff --git a/packages/learn/src/components/Header/index.js b/packages/learn/src/components/Header/index.js index 624dc1530dd..ec812bc56d1 100644 --- a/packages/learn/src/components/Header/index.js +++ b/packages/learn/src/components/Header/index.js @@ -17,7 +17,7 @@ function Header() {
  • - Learn + Curriculum
  • Forum diff --git a/packages/learn/src/components/Map/components/Block.js b/packages/learn/src/components/Map/components/Block.js index 24144425b10..1e720236bed 100644 --- a/packages/learn/src/components/Map/components/Block.js +++ b/packages/learn/src/components/Map/components/Block.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; import { createSelector } from 'reselect'; -import Link, { navigateTo } from 'gatsby-link'; +import Link from 'gatsby-link'; import ga from '../../../analytics'; import { makeExpandedBlockSelector, toggleBlock } from '../redux'; @@ -57,17 +57,12 @@ export class Block extends PureComponent { } handleBlockClick() { - const { blockDashedName, challenges, toggleBlock } = this.props; - const blockPath = challenges[0].fields.slug - .split('/') - .slice(0, -1) - .join('/'); - toggleBlock(blockDashedName); + const { blockDashedName, toggleBlock } = this.props; ga.event({ category: 'Map Block Click', action: blockDashedName }); - return navigateTo(blockPath); + return toggleBlock(blockDashedName); } handleChallengeClick(slug) { @@ -80,7 +75,7 @@ export class Block extends PureComponent { }; } - renderChallenges(intro, challenges) { + renderChallenges(intro = {}, challenges = []) { // TODO: Split this into a Challenge Component and add tests // TODO: The styles badge and map-badge on the completion span do not exist return [intro].concat(challenges).map(challenge => { diff --git a/packages/learn/src/components/Map/components/SuperBlock.js b/packages/learn/src/components/Map/components/SuperBlock.js index 114b3a14673..1317512a499 100644 --- a/packages/learn/src/components/Map/components/SuperBlock.js +++ b/packages/learn/src/components/Map/components/SuperBlock.js @@ -45,6 +45,14 @@ const propTypes = { toggleSuperBlock: PropTypes.func.isRequired }; +const codingPrepRE = new RegExp('Interview Prep'); + +function createSuperBlockTitle(str) { + return codingPrepRE.test(str) + ? `${str} (Thousands of hours of challenges)` + : `${str} Certification (300 hours)`; +} + export class SuperBlock extends PureComponent { renderBlock(superBlock) { const { nodes, introNodes } = this.props; @@ -54,7 +62,6 @@ export class SuperBlock extends PureComponent { const blockDashedNames = uniq( blocksForSuperBlock.map(({ block }) => block) ); - return (
      {blockDashedNames.map(blockDashedName => ( @@ -84,7 +91,7 @@ export class SuperBlock extends PureComponent {
    • toggleSuperBlock(superBlock)}> -

      {superBlock}

      +

      {createSuperBlockTitle(superBlock)}

      {isExpanded ? this.renderBlock(superBlock) : null}
    • diff --git a/packages/learn/src/components/Map/components/SuperBlock.test.js b/packages/learn/src/components/Map/components/SuperBlock.test.js index bb355337000..68814c4cb7f 100644 --- a/packages/learn/src/components/Map/components/SuperBlock.test.js +++ b/packages/learn/src/components/Map/components/SuperBlock.test.js @@ -61,7 +61,7 @@ test(' { .find('.map-title') .find('h4') .text() - ).toBe('Super Block One'); + ).toBe('Super Block One Certification (300 hours)'); expect(enzymeWrapper.find('ul').length).toBe(0); enzymeWrapper.find('.map-title').simulate('click'); @@ -76,6 +76,6 @@ test(' { .find('.map-title') .find('h4') .text() - ).toBe('Super Block One'); + ).toBe('Super Block One Certification (300 hours)'); expect(enzymeWrapper.find('ul').length).toBe(1); }); 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 0c499a57f21..f0f4e937dc4 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 @@ -10,7 +10,7 @@ exports[` expanded snapshot: superBlock-expanded 1`] = ` >

      - Super Block One + Super Block One Certification (300 hours)

        @@ -147,7 +147,7 @@ exports[` not expanded snapshot: superBlock-not-expanded 1`] = ` >

        - Super Block One + Super Block One Certification (300 hours)

        diff --git a/packages/learn/src/components/Map/map.css b/packages/learn/src/components/Map/map.css index 4f12baba542..4773093f2e2 100644 --- a/packages/learn/src/components/Map/map.css +++ b/packages/learn/src/components/Map/map.css @@ -1,6 +1,7 @@ .map-ui { height: 100%; max-height: calc(100vh - (45px + 1.45rem)); + margin-left: 35px; } .map-ui ul { diff --git a/packages/learn/src/components/Map/redux/index.js b/packages/learn/src/components/Map/redux/index.js index 5872cf8a9bd..4c27ba66522 100644 --- a/packages/learn/src/components/Map/redux/index.js +++ b/packages/learn/src/components/Map/redux/index.js @@ -8,8 +8,12 @@ export const getNS = () => ns; const initialState = { expandedState: { - superBlock: {}, - block: {} + superBlock: { + 'Responsive Web Design': true + }, + block: { + 'basic-html-and-html5': true + } } }; diff --git a/packages/learn/src/components/util/spacer.css b/packages/learn/src/components/util/spacer.css index 111b408a2eb..1297e9da028 100644 --- a/packages/learn/src/components/util/spacer.css +++ b/packages/learn/src/components/util/spacer.css @@ -1,3 +1,4 @@ .util-spacer { margin: 5px 0px; + height: 1px; } diff --git a/packages/learn/src/introductions/information-security-and-quality-assurance/quality-assurance-and-testing-with-chai/index.md b/packages/learn/src/introductions/information-security-and-quality-assurance/quality-assurance-and-testing-with-chai/index.md index 7f5263a9d89..3de8c65babc 100644 --- a/packages/learn/src/introductions/information-security-and-quality-assurance/quality-assurance-and-testing-with-chai/index.md +++ b/packages/learn/src/introductions/information-security-and-quality-assurance/quality-assurance-and-testing-with-chai/index.md @@ -1,6 +1,6 @@ --- title: Introduction to the Quality Assurance with Chai Challenges -block: Quality Assurance with Chai +block: Quality Assurance and Testing with Chai superBlock: Information Security and Quality Assurance --- ## Introduction to Quality Assurance with Chai Challenges diff --git a/packages/learn/src/layouts/global.css b/packages/learn/src/layouts/global.css index 21ab100f58d..1473c7bc4bb 100644 --- a/packages/learn/src/layouts/global.css +++ b/packages/learn/src/layouts/global.css @@ -656,4 +656,4 @@ h1, h2, h3, h4, h5, h6 { .btn-primary-link > a { color: #fff; -} \ No newline at end of file +} diff --git a/packages/learn/src/layouts/index.js b/packages/learn/src/layouts/index.js index 9acc6a88797..c14ff90b9c9 100644 --- a/packages/learn/src/layouts/index.js +++ b/packages/learn/src/layouts/index.js @@ -1,4 +1,3 @@ -/* global graphql */ import React, { Fragment, PureComponent } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; @@ -7,9 +6,7 @@ import Helmet from 'react-helmet'; import ga from '../analytics'; -import { AllChallengeNode } from '../redux/propTypes'; import Header from '../components/Header'; -import MapModal from '../components/MapModal'; import { fetchUser } from '../redux/app'; import 'prismjs/themes/prism.css'; @@ -47,7 +44,6 @@ const mapDispatchToProps = dispatch => const propTypes = { children: PropTypes.func, - data: AllChallengeNode, fetchUser: PropTypes.func.isRequired }; @@ -79,13 +75,7 @@ class Layout extends PureComponent { } } render() { - const { - children, - data: { - allChallengeNode: { edges }, - allMarkdownRemark: { edges: mdEdges } - } - } = this.props; + const { children } = this.props; return (
        {children()}
        - node)} - nodes={edges - .map(({ node }) => node) - .filter(({ isPrivate }) => !isPrivate)} - />
        ); } @@ -117,41 +101,3 @@ class Layout extends PureComponent { Layout.propTypes = propTypes; export default connect(mapStateToProps, mapDispatchToProps)(Layout); - -export const query = graphql` - query LayoutQuery { - allChallengeNode( - filter: { isPrivate: { eq: false } } - sort: { fields: [superOrder, order, suborder] } - ) { - edges { - node { - fields { - slug - blockName - } - id - block - title - isRequired - isPrivate - superBlock - dashedName - } - } - } - allMarkdownRemark(filter: { frontmatter: { block: { ne: null } } }) { - edges { - node { - frontmatter { - title - block - } - fields { - slug - } - } - } - } - } -`; diff --git a/packages/learn/src/layouts/layout.css b/packages/learn/src/layouts/layout.css index 1104b29c367..e1a51f76bcb 100644 --- a/packages/learn/src/layouts/layout.css +++ b/packages/learn/src/layouts/layout.css @@ -23,5 +23,5 @@ main { .app-wrapper { margin-top: 38px; - height: calc(100vh - 80px); + height: calc(100vh - 38px); } \ No newline at end of file diff --git a/packages/learn/src/pages/index.css b/packages/learn/src/pages/index.css index 56ad3642541..d81456c729c 100644 --- a/packages/learn/src/pages/index.css +++ b/packages/learn/src/pages/index.css @@ -5,4 +5,8 @@ align-items: center; max-width: 960px; margin: 0 auto; +} + +.index-page-wrapper p { + margin-bottom: 0.75rem; } \ No newline at end of file diff --git a/packages/learn/src/pages/index.js b/packages/learn/src/pages/index.js index 5cbfebe0511..2f9e00cde4b 100644 --- a/packages/learn/src/pages/index.js +++ b/packages/learn/src/pages/index.js @@ -1,15 +1,20 @@ /* global graphql */ +/* eslint-disable max-len */ import React from 'react'; import PropTypes from 'prop-types'; import Link from 'gatsby-link'; import Helmet from 'react-helmet'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; -import { Button } from 'react-bootstrap'; -import { ChallengeNode } from '../redux/propTypes'; +import { + ChallengeNode, + AllChallengeNode, + AllMarkdownRemark +} from '../redux/propTypes'; import { toggleMapModal } from '../redux/app'; import Spacer from '../components/util/Spacer'; +import Map from '../components/Map'; import './index.css'; @@ -20,14 +25,19 @@ const mapDispatchToProps = dispatch => const propTypes = { data: PropTypes.shape({ - challengeNode: ChallengeNode + challengeNode: ChallengeNode, + allChallengeNode: AllChallengeNode, + allMarkdownRemark: AllMarkdownRemark }), toggleMapModal: PropTypes.func.isRequired }; const IndexPage = ({ - data: { challengeNode: { title, fields: { slug, blockName } } }, - toggleMapModal + data: { + challengeNode: { fields: { slug } }, + allChallengeNode: { edges }, + allMarkdownRemark: { edges: mdEdges } + } }) => (
        @@ -35,27 +45,25 @@ const IndexPage = ({

        Welcome to the freeCodeCamp curriculum

        We have thousands of coding lessons to help you improve your skills.

        +

        You can earn each certification by completing its 5 final projects.

        - You can earn verified certifications by completing each sections 6 - required projects. -

        -

        - {'And yes - all of this is 100% free, thanks to the thousands of ' + - 'campers who '} + And yes - all of this is 100% free, thanks to the thousands of campers who{' '} donate {' '} to our nonprofit.

        -

        Not sure where to start?

        - We recommend you start at the beginning{' '} - {`${blockName} -> ${title}`} + If you are new to coding, we recommend you{' '} + start at the beginning.

        -

        Want to dive into our curriculum?

        - + + node)} + nodes={edges + .map(({ node }) => node) + .filter(({ isPrivate }) => !isPrivate)} + />
        ); @@ -67,10 +75,41 @@ export default connect(mapStateToProps, mapDispatchToProps)(IndexPage); export const query = graphql` query FirstChallenge { challengeNode(order: { eq: 0 }, suborder: { eq: 1 }) { - title fields { slug - blockName + } + } + allChallengeNode( + filter: { isPrivate: { eq: false } } + sort: { fields: [superOrder, order, suborder] } + ) { + edges { + node { + fields { + slug + blockName + } + id + block + title + isRequired + isPrivate + superBlock + dashedName + } + } + } + allMarkdownRemark(filter: { frontmatter: { block: { ne: null } } }) { + edges { + node { + frontmatter { + title + block + } + fields { + slug + } + } } } } diff --git a/packages/learn/src/redux/app/fetch-user-epic.js b/packages/learn/src/redux/app/fetch-user-epic.js index 92174fdd385..f4a08511bf3 100644 --- a/packages/learn/src/redux/app/fetch-user-epic.js +++ b/packages/learn/src/redux/app/fetch-user-epic.js @@ -1,18 +1,26 @@ /* global HOME_PATH */ import { of } from 'rxjs/observable/of'; +import { merge } from 'rxjs/observable/merge'; import { ofType } from 'redux-observable'; -import { types, fetchUserComplete, hardGoTo } from './'; +import { + types, + fetchUserComplete, + fetchUserError, + noUserFound, + hardGoTo +} from './'; import { switchMap, filter, map, catchError, - defaultIfEmpty + defaultIfEmpty, + mapTo } from 'rxjs/operators'; import { jwt } from '../cookieVaules'; function fetchUserEpic(action$, _, { services }) { - return action$.pipe( + const fetchUser = action$.pipe( ofType(types.fetchUser), filter(() => !!jwt), switchMap(() => { @@ -25,14 +33,20 @@ function fetchUserEpic(action$, _, { services }) { } return fetchUserComplete(response); }), - defaultIfEmpty({ type: 'no-user' }), - catchError(err => { - console.log(err); - return of({ type: 'fetch-user-error' }); + defaultIfEmpty(noUserFound()), + catchError(() => { + return of(fetchUserError()); }) ); }) ); + const isLoadingRequired = action$.pipe( + ofType(types.fetchUser), + filter(() => !jwt), + mapTo(noUserFound()) + ); + + return merge(fetchUser, isLoadingRequired); } export default fetchUserEpic; diff --git a/packages/learn/src/redux/app/index.js b/packages/learn/src/redux/app/index.js index d99b3eee7bf..2cabf091b8e 100644 --- a/packages/learn/src/redux/app/index.js +++ b/packages/learn/src/redux/app/index.js @@ -14,6 +14,7 @@ export const types = createTypes( 'fetchUser', 'fetchUserComplete', 'fetchUserError', + 'noUserFound', 'hardGoTo', 'updateUserSignedIn', 'toggleMapModal' @@ -23,6 +24,7 @@ export const types = createTypes( const initialState = { appUsername: '', + showLoading: true, isSignedIn: false, user: {}, showMapModal: false @@ -30,7 +32,8 @@ const initialState = { export const fetchUser = createAction(types.fetchUser); export const fetchUserComplete = createAction(types.fetchUserComplete); -export const fecthUserError = createAction(types.fetchUserError); +export const fetchUserError = createAction(types.fetchUserError); +export const noUserFound = createAction(types.noUserFound); export const hardGoTo = createAction(types.hardGoTo); @@ -41,6 +44,7 @@ export const updateUserSignedIn = createAction(types.updateUserSignedIn); export const isMapModalOpenSelector = state => state[ns].showMapModal; export const isSignedInSelector = state => state[ns].isSignedIn; export const userSelector = state => state[ns].user || {}; +export const userStateLoadingSelector = state => state[ns].showLoading; export const completedChallengesSelector = state => state[ns].user.completedChallenges || []; export const currentChallengeIdSelector = state => @@ -55,8 +59,11 @@ export const reducer = handleActions( ...state, appUsername: result, user: user[result], + showLoading: false, isSignedIn: !!Object.keys(user).length }), + [types.fetchUserError]: state => ({ ...state, showLoading: false }), + [types.noUserFound]: state => ({ ...state, showLoading: false }), [types.toggleMapModal]: state => ({ ...state, showMapModal: !state.showMapModal diff --git a/packages/learn/src/redux/propTypes.js b/packages/learn/src/redux/propTypes.js index 667df7e3a84..c6c5d3ff021 100644 --- a/packages/learn/src/redux/propTypes.js +++ b/packages/learn/src/redux/propTypes.js @@ -63,3 +63,11 @@ export const AllChallengeNode = PropTypes.shape({ }) ) }); + +export const AllMarkdownRemark = PropTypes.shape({ + edges: PropTypes.arrayOf( + PropTypes.shape({ + node: MarkdownRemark + }) + ) +}); diff --git a/packages/learn/src/templates/Challenges/backend/Show.js b/packages/learn/src/templates/Challenges/backend/Show.js index 70fadacf386..1ce416936d1 100644 --- a/packages/learn/src/templates/Challenges/backend/Show.js +++ b/packages/learn/src/templates/Challenges/backend/Show.js @@ -119,7 +119,6 @@ export class BackEnd extends PureComponent { const blockNameTitle = `${blockName} - ${title}`; return ( -
        @@ -134,6 +133,7 @@ export class BackEnd extends PureComponent { options={options} submit={executeChallenge} /> +

        diff --git a/packages/learn/src/templates/Challenges/classic/Show.js b/packages/learn/src/templates/Challenges/classic/Show.js index 4e7908b618d..e48e7b6ea64 100644 --- a/packages/learn/src/templates/Challenges/classic/Show.js +++ b/packages/learn/src/templates/Challenges/classic/Show.js @@ -10,7 +10,6 @@ import { ReflexContainer, ReflexSplitter, ReflexElement } from 'react-reflex'; import Editor from './Editor'; import Preview from '../components/Preview'; import SidePanel from '../components/Side-Panel'; -import TestSuite from '../components/Test-Suite'; import Output from '../components/Output'; import CompletionModal from '../components/CompletionModal'; import HelpModal from '../components/HelpModal'; @@ -32,8 +31,6 @@ import { } from '../redux'; import './classic.css'; -import ToolPanel from '../components/Tool-Panel'; -import Spacer from '../../../components/util/Spacer'; const mapStateToProps = createSelector( challengeFilesSelector, @@ -157,7 +154,6 @@ class ShowClassic extends PureComponent { } render() { - // console.log(this.state) const { data: { challengeNode: { @@ -169,7 +165,6 @@ class ShowClassic extends PureComponent { } }, files, - tests, output } = this.props; const editors = Object.keys(files) @@ -202,9 +197,7 @@ class ShowClassic extends PureComponent { - @@ -234,16 +227,14 @@ class ShowClassic extends PureComponent { {editors} - - {showPreview ? ( + {showPreview ? ( + - ) : null} - - - + + ) : null} diff --git a/packages/learn/src/templates/Challenges/components/Side-Panel.js b/packages/learn/src/templates/Challenges/components/Side-Panel.js index 28c8569790e..55f68333fb0 100644 --- a/packages/learn/src/templates/Challenges/components/Side-Panel.js +++ b/packages/learn/src/templates/Challenges/components/Side-Panel.js @@ -6,11 +6,16 @@ import { bindActionCreators } from 'redux'; import ChallengeTitle from './Challenge-Title'; import ChallengeDescription from './Challenge-Description'; +import ToolPanel from './Tool-Panel'; +import TestSuite from './Test-Suite'; import Spacer from '../../../components/util/Spacer'; -import { initConsole } from '../redux'; +import { initConsole, challengeTestsSelector } from '../redux'; +import { createSelector } from 'reselect'; -const mapStateToProps = () => ({}); +const mapStateToProps = createSelector(challengeTestsSelector, tests => ({ + tests +})); const mapDispatchToProps = dispatch => bindActionCreators( @@ -22,7 +27,9 @@ const mapDispatchToProps = dispatch => const propTypes = { description: PropTypes.arrayOf(PropTypes.string), + guideUrl: PropTypes.string, initConsole: PropTypes.func.isRequired, + tests: PropTypes.arrayOf(PropTypes.object), title: PropTypes.string }; @@ -52,7 +59,7 @@ export class SidePanel extends PureComponent { } render() { - const { title, description } = this.props; + const { title, description, guideUrl, tests } = this.props; return (
        @@ -61,7 +68,9 @@ export class SidePanel extends PureComponent { {title}
        - +
        + +
        ); } diff --git a/packages/learn/src/templates/Challenges/components/Test-Suite.js b/packages/learn/src/templates/Challenges/components/Test-Suite.js index 3a0fc7e034e..10c360ce77e 100644 --- a/packages/learn/src/templates/Challenges/components/Test-Suite.js +++ b/packages/learn/src/templates/Challenges/components/Test-Suite.js @@ -2,7 +2,8 @@ import React from 'react'; import PropTypes from 'prop-types'; import GreenPass from './icons/GreenPass'; -import RedFail from './icons/RedFail'; +import Fail from './icons/Fail'; +import Initial from './icons/Initial'; import './test-suite.css'; @@ -28,6 +29,8 @@ function TestSuite({ tests }) { return (
        {tests.map(({ err, pass = false, text = '' }, index) => { + const isInitial = !pass && !err; + const statusIcon = pass && !err ? : ; return (
        - {pass ? : } + {isInitial ? : statusIcon}