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
This commit is contained in:
committed by
Mrugesh Mohapatra
parent
6aff2bbe42
commit
910dd0584c
@@ -5,4 +5,5 @@ node_js:
|
|||||||
- "lts/*"
|
- "lts/*"
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
- "node_modules"
|
- "node_modules"
|
||||||
|
script: "yarn test:ci"
|
@@ -68,7 +68,6 @@ module.exports = {
|
|||||||
fonts: ['Lato:400,400i,500']
|
fonts: ['Lato:400,400i,500']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'gatsby-plugin-sitemap',
|
'gatsby-plugin-sitemap'
|
||||||
'gatsby-plugin-offline'
|
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
@@ -104,6 +104,7 @@ exports.createPages = ({ graphql, boundActionCreators }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const webpack = require('webpack');
|
const webpack = require('webpack');
|
||||||
|
const RmServiceWorkerPlugin = require('webpack-remove-serviceworker-plugin');
|
||||||
const generateBabelConfig = require('gatsby/dist/utils/babel-config');
|
const generateBabelConfig = require('gatsby/dist/utils/babel-config');
|
||||||
|
|
||||||
exports.modifyWebpackConfig = ({ config, stage }) => {
|
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 */
|
/* eslint-disable prefer-object-spread/prefer-object-spread */
|
||||||
|
@@ -23,7 +23,6 @@
|
|||||||
"gatsby": "^1.9.243",
|
"gatsby": "^1.9.243",
|
||||||
"gatsby-link": "^1.6.39",
|
"gatsby-link": "^1.6.39",
|
||||||
"gatsby-plugin-google-fonts": "^0.0.4",
|
"gatsby-plugin-google-fonts": "^0.0.4",
|
||||||
"gatsby-plugin-offline": "^1.0.15",
|
|
||||||
"gatsby-plugin-react-helmet": "^2.0.8",
|
"gatsby-plugin-react-helmet": "^2.0.8",
|
||||||
"gatsby-plugin-react-next": "^1.0.11",
|
"gatsby-plugin-react-next": "^1.0.11",
|
||||||
"gatsby-plugin-sitemap": "^1.2.21",
|
"gatsby-plugin-sitemap": "^1.2.21",
|
||||||
@@ -48,6 +47,7 @@
|
|||||||
"react-redux": "^5.0.7",
|
"react-redux": "^5.0.7",
|
||||||
"react-reflex": "^2.2.1",
|
"react-reflex": "^2.2.1",
|
||||||
"react-router-redux": "^5.0.0-alpha.9",
|
"react-router-redux": "^5.0.0-alpha.9",
|
||||||
|
"react-spinkit": "^3.0.0",
|
||||||
"react-test-renderer": "^16.3.1",
|
"react-test-renderer": "^16.3.1",
|
||||||
"redux": "^3.7.2",
|
"redux": "^3.7.2",
|
||||||
"redux-actions": "^2.3.0",
|
"redux-actions": "^2.3.0",
|
||||||
@@ -57,7 +57,8 @@
|
|||||||
"rxjs": "^5.5.7",
|
"rxjs": "^5.5.7",
|
||||||
"store": "^2.0.12",
|
"store": "^2.0.12",
|
||||||
"uglifyjs-webpack-plugin": "^1.2.4",
|
"uglifyjs-webpack-plugin": "^1.2.4",
|
||||||
"validator": "^9.4.1"
|
"validator": "^9.4.1",
|
||||||
|
"webpack-remove-serviceworker-plugin": "^1.0.0"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"gatsby"
|
"gatsby"
|
||||||
@@ -77,7 +78,8 @@
|
|||||||
"lint:src": "eslint ./src . --fix",
|
"lint:src": "eslint ./src . --fix",
|
||||||
"lint:utils": "eslint ./utils . --fix",
|
"lint:utils": "eslint ./utils . --fix",
|
||||||
"pretty": "yarn format && yarn lint",
|
"pretty": "yarn format && yarn lint",
|
||||||
"test": "yarn format && jest src",
|
"test": "jest src",
|
||||||
|
"test:ci": "yarn format && jest src",
|
||||||
"test:watch": "jest --watch src"
|
"test:watch": "jest --watch src"
|
||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
|
@@ -2,24 +2,45 @@ import React, { PureComponent } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
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 Login from './Login';
|
||||||
import SignedIn from './SignedIn';
|
import SignedIn from './SignedIn';
|
||||||
|
|
||||||
const mapStateToProps = createSelector(isSignedInSelector, isSignedIn => ({
|
const mapStateToProps = createSelector(
|
||||||
isSignedIn
|
userStateLoadingSelector,
|
||||||
}));
|
isSignedInSelector,
|
||||||
|
(showLoading, isSignedIn) => ({
|
||||||
|
isSignedIn,
|
||||||
|
showLoading
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
email: PropTypes.string,
|
email: PropTypes.string,
|
||||||
isSignedIn: PropTypes.bool,
|
isSignedIn: PropTypes.bool,
|
||||||
name: PropTypes.string
|
name: PropTypes.string,
|
||||||
|
showLoading: PropTypes.bool
|
||||||
};
|
};
|
||||||
|
|
||||||
class UserState extends PureComponent {
|
class UserState extends PureComponent {
|
||||||
render() {
|
render() {
|
||||||
const { isSignedIn } = this.props;
|
const { isSignedIn, showLoading } = this.props;
|
||||||
|
if (showLoading) {
|
||||||
|
return (
|
||||||
|
<Spinner
|
||||||
|
className='user-state-spinner'
|
||||||
|
color='white'
|
||||||
|
fadeIn='none'
|
||||||
|
height='40px'
|
||||||
|
name='line-scale'
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
return isSignedIn ? <SignedIn /> : <Login />;
|
return isSignedIn ? <SignedIn /> : <Login />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -70,6 +70,13 @@ header {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.user-state-spinner {
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-state-spinner > div {
|
||||||
|
animation-duration: 1.5s !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Search bar */
|
/* Search bar */
|
||||||
.fcc_searchBar {
|
.fcc_searchBar {
|
||||||
|
@@ -17,7 +17,7 @@ function Header() {
|
|||||||
<FCCSearch />
|
<FCCSearch />
|
||||||
<ul id='top-right-nav'>
|
<ul id='top-right-nav'>
|
||||||
<li>
|
<li>
|
||||||
<a href='https://learn.freecodecamp.org'>Learn</a>
|
<Link to='/'>Curriculum</Link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href='https://forum.freecodecamp.org'>Forum</a>
|
<a href='https://forum.freecodecamp.org'>Forum</a>
|
||||||
|
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
|||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import Link, { navigateTo } from 'gatsby-link';
|
import Link from 'gatsby-link';
|
||||||
|
|
||||||
import ga from '../../../analytics';
|
import ga from '../../../analytics';
|
||||||
import { makeExpandedBlockSelector, toggleBlock } from '../redux';
|
import { makeExpandedBlockSelector, toggleBlock } from '../redux';
|
||||||
@@ -57,17 +57,12 @@ export class Block extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleBlockClick() {
|
handleBlockClick() {
|
||||||
const { blockDashedName, challenges, toggleBlock } = this.props;
|
const { blockDashedName, toggleBlock } = this.props;
|
||||||
const blockPath = challenges[0].fields.slug
|
|
||||||
.split('/')
|
|
||||||
.slice(0, -1)
|
|
||||||
.join('/');
|
|
||||||
toggleBlock(blockDashedName);
|
|
||||||
ga.event({
|
ga.event({
|
||||||
category: 'Map Block Click',
|
category: 'Map Block Click',
|
||||||
action: blockDashedName
|
action: blockDashedName
|
||||||
});
|
});
|
||||||
return navigateTo(blockPath);
|
return toggleBlock(blockDashedName);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChallengeClick(slug) {
|
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: Split this into a Challenge Component and add tests
|
||||||
// TODO: The styles badge and map-badge on the completion span do not exist
|
// TODO: The styles badge and map-badge on the completion span do not exist
|
||||||
return [intro].concat(challenges).map(challenge => {
|
return [intro].concat(challenges).map(challenge => {
|
||||||
|
@@ -45,6 +45,14 @@ const propTypes = {
|
|||||||
toggleSuperBlock: PropTypes.func.isRequired
|
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 {
|
export class SuperBlock extends PureComponent {
|
||||||
renderBlock(superBlock) {
|
renderBlock(superBlock) {
|
||||||
const { nodes, introNodes } = this.props;
|
const { nodes, introNodes } = this.props;
|
||||||
@@ -54,7 +62,6 @@ export class SuperBlock extends PureComponent {
|
|||||||
const blockDashedNames = uniq(
|
const blockDashedNames = uniq(
|
||||||
blocksForSuperBlock.map(({ block }) => block)
|
blocksForSuperBlock.map(({ block }) => block)
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ul>
|
<ul>
|
||||||
{blockDashedNames.map(blockDashedName => (
|
{blockDashedNames.map(blockDashedName => (
|
||||||
@@ -84,7 +91,7 @@ export class SuperBlock extends PureComponent {
|
|||||||
<li className={`superblock ${isExpanded ? 'open' : ''}`}>
|
<li className={`superblock ${isExpanded ? 'open' : ''}`}>
|
||||||
<div className='map-title' onClick={() => toggleSuperBlock(superBlock)}>
|
<div className='map-title' onClick={() => toggleSuperBlock(superBlock)}>
|
||||||
<Caret />
|
<Caret />
|
||||||
<h4>{superBlock}</h4>
|
<h4>{createSuperBlockTitle(superBlock)}</h4>
|
||||||
</div>
|
</div>
|
||||||
{isExpanded ? this.renderBlock(superBlock) : null}
|
{isExpanded ? this.renderBlock(superBlock) : null}
|
||||||
</li>
|
</li>
|
||||||
|
@@ -61,7 +61,7 @@ test('<SuperBlock should handle toggle clicks correctly', () => {
|
|||||||
.find('.map-title')
|
.find('.map-title')
|
||||||
.find('h4')
|
.find('h4')
|
||||||
.text()
|
.text()
|
||||||
).toBe('Super Block One');
|
).toBe('Super Block One Certification (300 hours)');
|
||||||
expect(enzymeWrapper.find('ul').length).toBe(0);
|
expect(enzymeWrapper.find('ul').length).toBe(0);
|
||||||
|
|
||||||
enzymeWrapper.find('.map-title').simulate('click');
|
enzymeWrapper.find('.map-title').simulate('click');
|
||||||
@@ -76,6 +76,6 @@ test('<SuperBlock should handle toggle clicks correctly', () => {
|
|||||||
.find('.map-title')
|
.find('.map-title')
|
||||||
.find('h4')
|
.find('h4')
|
||||||
.text()
|
.text()
|
||||||
).toBe('Super Block One');
|
).toBe('Super Block One Certification (300 hours)');
|
||||||
expect(enzymeWrapper.find('ul').length).toBe(1);
|
expect(enzymeWrapper.find('ul').length).toBe(1);
|
||||||
});
|
});
|
||||||
|
@@ -10,7 +10,7 @@ exports[`<SuperBlock /> expanded snapshot: superBlock-expanded 1`] = `
|
|||||||
>
|
>
|
||||||
<Caret />
|
<Caret />
|
||||||
<h4>
|
<h4>
|
||||||
Super Block One
|
Super Block One Certification (300 hours)
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
@@ -147,7 +147,7 @@ exports[`<SuperBlock /> not expanded snapshot: superBlock-not-expanded 1`] = `
|
|||||||
>
|
>
|
||||||
<Caret />
|
<Caret />
|
||||||
<h4>
|
<h4>
|
||||||
Super Block One
|
Super Block One Certification (300 hours)
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
.map-ui {
|
.map-ui {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
max-height: calc(100vh - (45px + 1.45rem));
|
max-height: calc(100vh - (45px + 1.45rem));
|
||||||
|
margin-left: 35px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.map-ui ul {
|
.map-ui ul {
|
||||||
|
@@ -8,8 +8,12 @@ export const getNS = () => ns;
|
|||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
expandedState: {
|
expandedState: {
|
||||||
superBlock: {},
|
superBlock: {
|
||||||
block: {}
|
'Responsive Web Design': true
|
||||||
|
},
|
||||||
|
block: {
|
||||||
|
'basic-html-and-html5': true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
.util-spacer {
|
.util-spacer {
|
||||||
margin: 5px 0px;
|
margin: 5px 0px;
|
||||||
|
height: 1px;
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: Introduction to the Quality Assurance with Chai Challenges
|
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
|
superBlock: Information Security and Quality Assurance
|
||||||
---
|
---
|
||||||
## Introduction to Quality Assurance with Chai Challenges
|
## Introduction to Quality Assurance with Chai Challenges
|
||||||
|
@@ -656,4 +656,4 @@ h1, h2, h3, h4, h5, h6 {
|
|||||||
|
|
||||||
.btn-primary-link > a {
|
.btn-primary-link > a {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
/* global graphql */
|
|
||||||
import React, { Fragment, PureComponent } from 'react';
|
import React, { Fragment, PureComponent } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
@@ -7,9 +6,7 @@ import Helmet from 'react-helmet';
|
|||||||
|
|
||||||
import ga from '../analytics';
|
import ga from '../analytics';
|
||||||
|
|
||||||
import { AllChallengeNode } from '../redux/propTypes';
|
|
||||||
import Header from '../components/Header';
|
import Header from '../components/Header';
|
||||||
import MapModal from '../components/MapModal';
|
|
||||||
import { fetchUser } from '../redux/app';
|
import { fetchUser } from '../redux/app';
|
||||||
|
|
||||||
import 'prismjs/themes/prism.css';
|
import 'prismjs/themes/prism.css';
|
||||||
@@ -47,7 +44,6 @@ const mapDispatchToProps = dispatch =>
|
|||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
children: PropTypes.func,
|
children: PropTypes.func,
|
||||||
data: AllChallengeNode,
|
|
||||||
fetchUser: PropTypes.func.isRequired
|
fetchUser: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -79,13 +75,7 @@ class Layout extends PureComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
const {
|
const { children } = this.props;
|
||||||
children,
|
|
||||||
data: {
|
|
||||||
allChallengeNode: { edges },
|
|
||||||
allMarkdownRemark: { edges: mdEdges }
|
|
||||||
}
|
|
||||||
} = this.props;
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Helmet
|
<Helmet
|
||||||
@@ -103,12 +93,6 @@ class Layout extends PureComponent {
|
|||||||
<div className='app-wrapper'>
|
<div className='app-wrapper'>
|
||||||
<main>{children()}</main>
|
<main>{children()}</main>
|
||||||
</div>
|
</div>
|
||||||
<MapModal
|
|
||||||
introNodes={mdEdges.map(({ node }) => node)}
|
|
||||||
nodes={edges
|
|
||||||
.map(({ node }) => node)
|
|
||||||
.filter(({ isPrivate }) => !isPrivate)}
|
|
||||||
/>
|
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -117,41 +101,3 @@ class Layout extends PureComponent {
|
|||||||
Layout.propTypes = propTypes;
|
Layout.propTypes = propTypes;
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(Layout);
|
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
@@ -23,5 +23,5 @@ main {
|
|||||||
|
|
||||||
.app-wrapper {
|
.app-wrapper {
|
||||||
margin-top: 38px;
|
margin-top: 38px;
|
||||||
height: calc(100vh - 80px);
|
height: calc(100vh - 38px);
|
||||||
}
|
}
|
@@ -5,4 +5,8 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
max-width: 960px;
|
max-width: 960px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.index-page-wrapper p {
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
}
|
}
|
@@ -1,15 +1,20 @@
|
|||||||
/* global graphql */
|
/* global graphql */
|
||||||
|
/* eslint-disable max-len */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import Link from 'gatsby-link';
|
import Link from 'gatsby-link';
|
||||||
import Helmet from 'react-helmet';
|
import Helmet from 'react-helmet';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-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 { toggleMapModal } from '../redux/app';
|
||||||
import Spacer from '../components/util/Spacer';
|
import Spacer from '../components/util/Spacer';
|
||||||
|
import Map from '../components/Map';
|
||||||
|
|
||||||
import './index.css';
|
import './index.css';
|
||||||
|
|
||||||
@@ -20,14 +25,19 @@ const mapDispatchToProps = dispatch =>
|
|||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
data: PropTypes.shape({
|
data: PropTypes.shape({
|
||||||
challengeNode: ChallengeNode
|
challengeNode: ChallengeNode,
|
||||||
|
allChallengeNode: AllChallengeNode,
|
||||||
|
allMarkdownRemark: AllMarkdownRemark
|
||||||
}),
|
}),
|
||||||
toggleMapModal: PropTypes.func.isRequired
|
toggleMapModal: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
const IndexPage = ({
|
const IndexPage = ({
|
||||||
data: { challengeNode: { title, fields: { slug, blockName } } },
|
data: {
|
||||||
toggleMapModal
|
challengeNode: { fields: { slug } },
|
||||||
|
allChallengeNode: { edges },
|
||||||
|
allMarkdownRemark: { edges: mdEdges }
|
||||||
|
}
|
||||||
}) => (
|
}) => (
|
||||||
<div className='index-page-wrapper'>
|
<div className='index-page-wrapper'>
|
||||||
<Helmet title='Welcome to learn.freeCodeCamp!' />
|
<Helmet title='Welcome to learn.freeCodeCamp!' />
|
||||||
@@ -35,27 +45,25 @@ const IndexPage = ({
|
|||||||
<Spacer />
|
<Spacer />
|
||||||
<h2>Welcome to the freeCodeCamp curriculum</h2>
|
<h2>Welcome to the freeCodeCamp curriculum</h2>
|
||||||
<p>We have thousands of coding lessons to help you improve your skills.</p>
|
<p>We have thousands of coding lessons to help you improve your skills.</p>
|
||||||
|
<p>You can earn each certification by completing its 5 final projects.</p>
|
||||||
<p>
|
<p>
|
||||||
You can earn verified certifications by completing each sections 6
|
And yes - all of this is 100% free, thanks to the thousands of campers who{' '}
|
||||||
required projects.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
{'And yes - all of this is 100% free, thanks to the thousands of ' +
|
|
||||||
'campers who '}
|
|
||||||
<a href='https://donate.freecodecamp.org' target='_blank'>
|
<a href='https://donate.freecodecamp.org' target='_blank'>
|
||||||
donate
|
donate
|
||||||
</a>{' '}
|
</a>{' '}
|
||||||
to our nonprofit.
|
to our nonprofit.
|
||||||
</p>
|
</p>
|
||||||
<h3>Not sure where to start?</h3>
|
|
||||||
<p>
|
<p>
|
||||||
We recommend you start at the beginning{' '}
|
If you are new to coding, we recommend you{' '}
|
||||||
<Link to={slug}>{`${blockName} -> ${title}`}</Link>
|
<Link to={slug}>start at the beginning</Link>.
|
||||||
</p>
|
</p>
|
||||||
<h3>Want to dive into our curriculum?</h3>
|
<Spacer />
|
||||||
<Button block={true} bsSize='lg' bsStyle='primary' onClick={toggleMapModal}>
|
<Map
|
||||||
Explore the curriculum
|
introNodes={mdEdges.map(({ node }) => node)}
|
||||||
</Button>
|
nodes={edges
|
||||||
|
.map(({ node }) => node)
|
||||||
|
.filter(({ isPrivate }) => !isPrivate)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -67,10 +75,41 @@ export default connect(mapStateToProps, mapDispatchToProps)(IndexPage);
|
|||||||
export const query = graphql`
|
export const query = graphql`
|
||||||
query FirstChallenge {
|
query FirstChallenge {
|
||||||
challengeNode(order: { eq: 0 }, suborder: { eq: 1 }) {
|
challengeNode(order: { eq: 0 }, suborder: { eq: 1 }) {
|
||||||
title
|
|
||||||
fields {
|
fields {
|
||||||
slug
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,18 +1,26 @@
|
|||||||
/* global HOME_PATH */
|
/* global HOME_PATH */
|
||||||
import { of } from 'rxjs/observable/of';
|
import { of } from 'rxjs/observable/of';
|
||||||
|
import { merge } from 'rxjs/observable/merge';
|
||||||
import { ofType } from 'redux-observable';
|
import { ofType } from 'redux-observable';
|
||||||
import { types, fetchUserComplete, hardGoTo } from './';
|
import {
|
||||||
|
types,
|
||||||
|
fetchUserComplete,
|
||||||
|
fetchUserError,
|
||||||
|
noUserFound,
|
||||||
|
hardGoTo
|
||||||
|
} from './';
|
||||||
import {
|
import {
|
||||||
switchMap,
|
switchMap,
|
||||||
filter,
|
filter,
|
||||||
map,
|
map,
|
||||||
catchError,
|
catchError,
|
||||||
defaultIfEmpty
|
defaultIfEmpty,
|
||||||
|
mapTo
|
||||||
} from 'rxjs/operators';
|
} from 'rxjs/operators';
|
||||||
import { jwt } from '../cookieVaules';
|
import { jwt } from '../cookieVaules';
|
||||||
|
|
||||||
function fetchUserEpic(action$, _, { services }) {
|
function fetchUserEpic(action$, _, { services }) {
|
||||||
return action$.pipe(
|
const fetchUser = action$.pipe(
|
||||||
ofType(types.fetchUser),
|
ofType(types.fetchUser),
|
||||||
filter(() => !!jwt),
|
filter(() => !!jwt),
|
||||||
switchMap(() => {
|
switchMap(() => {
|
||||||
@@ -25,14 +33,20 @@ function fetchUserEpic(action$, _, { services }) {
|
|||||||
}
|
}
|
||||||
return fetchUserComplete(response);
|
return fetchUserComplete(response);
|
||||||
}),
|
}),
|
||||||
defaultIfEmpty({ type: 'no-user' }),
|
defaultIfEmpty(noUserFound()),
|
||||||
catchError(err => {
|
catchError(() => {
|
||||||
console.log(err);
|
return of(fetchUserError());
|
||||||
return of({ type: 'fetch-user-error' });
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
const isLoadingRequired = action$.pipe(
|
||||||
|
ofType(types.fetchUser),
|
||||||
|
filter(() => !jwt),
|
||||||
|
mapTo(noUserFound())
|
||||||
|
);
|
||||||
|
|
||||||
|
return merge(fetchUser, isLoadingRequired);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default fetchUserEpic;
|
export default fetchUserEpic;
|
||||||
|
@@ -14,6 +14,7 @@ export const types = createTypes(
|
|||||||
'fetchUser',
|
'fetchUser',
|
||||||
'fetchUserComplete',
|
'fetchUserComplete',
|
||||||
'fetchUserError',
|
'fetchUserError',
|
||||||
|
'noUserFound',
|
||||||
'hardGoTo',
|
'hardGoTo',
|
||||||
'updateUserSignedIn',
|
'updateUserSignedIn',
|
||||||
'toggleMapModal'
|
'toggleMapModal'
|
||||||
@@ -23,6 +24,7 @@ export const types = createTypes(
|
|||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
appUsername: '',
|
appUsername: '',
|
||||||
|
showLoading: true,
|
||||||
isSignedIn: false,
|
isSignedIn: false,
|
||||||
user: {},
|
user: {},
|
||||||
showMapModal: false
|
showMapModal: false
|
||||||
@@ -30,7 +32,8 @@ const initialState = {
|
|||||||
|
|
||||||
export const fetchUser = createAction(types.fetchUser);
|
export const fetchUser = createAction(types.fetchUser);
|
||||||
export const fetchUserComplete = createAction(types.fetchUserComplete);
|
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);
|
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 isMapModalOpenSelector = state => state[ns].showMapModal;
|
||||||
export const isSignedInSelector = state => state[ns].isSignedIn;
|
export const isSignedInSelector = state => state[ns].isSignedIn;
|
||||||
export const userSelector = state => state[ns].user || {};
|
export const userSelector = state => state[ns].user || {};
|
||||||
|
export const userStateLoadingSelector = state => state[ns].showLoading;
|
||||||
export const completedChallengesSelector = state =>
|
export const completedChallengesSelector = state =>
|
||||||
state[ns].user.completedChallenges || [];
|
state[ns].user.completedChallenges || [];
|
||||||
export const currentChallengeIdSelector = state =>
|
export const currentChallengeIdSelector = state =>
|
||||||
@@ -55,8 +59,11 @@ export const reducer = handleActions(
|
|||||||
...state,
|
...state,
|
||||||
appUsername: result,
|
appUsername: result,
|
||||||
user: user[result],
|
user: user[result],
|
||||||
|
showLoading: false,
|
||||||
isSignedIn: !!Object.keys(user).length
|
isSignedIn: !!Object.keys(user).length
|
||||||
}),
|
}),
|
||||||
|
[types.fetchUserError]: state => ({ ...state, showLoading: false }),
|
||||||
|
[types.noUserFound]: state => ({ ...state, showLoading: false }),
|
||||||
[types.toggleMapModal]: state => ({
|
[types.toggleMapModal]: state => ({
|
||||||
...state,
|
...state,
|
||||||
showMapModal: !state.showMapModal
|
showMapModal: !state.showMapModal
|
||||||
|
@@ -63,3 +63,11 @@ export const AllChallengeNode = PropTypes.shape({
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const AllMarkdownRemark = PropTypes.shape({
|
||||||
|
edges: PropTypes.arrayOf(
|
||||||
|
PropTypes.shape({
|
||||||
|
node: MarkdownRemark
|
||||||
|
})
|
||||||
|
)
|
||||||
|
});
|
||||||
|
@@ -119,7 +119,6 @@ export class BackEnd extends PureComponent {
|
|||||||
const blockNameTitle = `${blockName} - ${title}`;
|
const blockNameTitle = `${blockName} - ${title}`;
|
||||||
return (
|
return (
|
||||||
<Row>
|
<Row>
|
||||||
<ProjectToolPanel />
|
|
||||||
<Col xs={6} xsOffset={3}>
|
<Col xs={6} xsOffset={3}>
|
||||||
<Spacer />
|
<Spacer />
|
||||||
<div>
|
<div>
|
||||||
@@ -134,6 +133,7 @@ export class BackEnd extends PureComponent {
|
|||||||
options={options}
|
options={options}
|
||||||
submit={executeChallenge}
|
submit={executeChallenge}
|
||||||
/>
|
/>
|
||||||
|
<ProjectToolPanel />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<br />
|
<br />
|
||||||
|
@@ -10,7 +10,6 @@ import { ReflexContainer, ReflexSplitter, ReflexElement } from 'react-reflex';
|
|||||||
import Editor from './Editor';
|
import Editor from './Editor';
|
||||||
import Preview from '../components/Preview';
|
import Preview from '../components/Preview';
|
||||||
import SidePanel from '../components/Side-Panel';
|
import SidePanel from '../components/Side-Panel';
|
||||||
import TestSuite from '../components/Test-Suite';
|
|
||||||
import Output from '../components/Output';
|
import Output from '../components/Output';
|
||||||
import CompletionModal from '../components/CompletionModal';
|
import CompletionModal from '../components/CompletionModal';
|
||||||
import HelpModal from '../components/HelpModal';
|
import HelpModal from '../components/HelpModal';
|
||||||
@@ -32,8 +31,6 @@ import {
|
|||||||
} from '../redux';
|
} from '../redux';
|
||||||
|
|
||||||
import './classic.css';
|
import './classic.css';
|
||||||
import ToolPanel from '../components/Tool-Panel';
|
|
||||||
import Spacer from '../../../components/util/Spacer';
|
|
||||||
|
|
||||||
const mapStateToProps = createSelector(
|
const mapStateToProps = createSelector(
|
||||||
challengeFilesSelector,
|
challengeFilesSelector,
|
||||||
@@ -157,7 +154,6 @@ class ShowClassic extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
// console.log(this.state)
|
|
||||||
const {
|
const {
|
||||||
data: {
|
data: {
|
||||||
challengeNode: {
|
challengeNode: {
|
||||||
@@ -169,7 +165,6 @@ class ShowClassic extends PureComponent {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
files,
|
files,
|
||||||
tests,
|
|
||||||
output
|
output
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const editors = Object.keys(files)
|
const editors = Object.keys(files)
|
||||||
@@ -202,9 +197,7 @@ class ShowClassic extends PureComponent {
|
|||||||
<Output
|
<Output
|
||||||
defaultOutput={`
|
defaultOutput={`
|
||||||
/**
|
/**
|
||||||
* Your output will go here.
|
* Your test output will go here.
|
||||||
* Any console.log() statements
|
|
||||||
* will appear in here as well.
|
|
||||||
*/
|
*/
|
||||||
`}
|
`}
|
||||||
output={output}
|
output={output}
|
||||||
@@ -220,12 +213,12 @@ class ShowClassic extends PureComponent {
|
|||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Helmet title={`${blockNameTitle} | Learn freeCodeCamp`} />
|
<Helmet title={`${blockNameTitle} | Learn freeCodeCamp`} />
|
||||||
<ToolPanel guideUrl={guideUrl} />
|
|
||||||
<ReflexContainer orientation='vertical'>
|
<ReflexContainer orientation='vertical'>
|
||||||
<ReflexElement flex={1} {...this.resizeProps}>
|
<ReflexElement flex={1} {...this.resizeProps}>
|
||||||
<SidePanel
|
<SidePanel
|
||||||
className='full-height'
|
className='full-height'
|
||||||
description={description}
|
description={description}
|
||||||
|
guideUrl={guideUrl}
|
||||||
title={blockNameTitle}
|
title={blockNameTitle}
|
||||||
/>
|
/>
|
||||||
</ReflexElement>
|
</ReflexElement>
|
||||||
@@ -234,16 +227,14 @@ class ShowClassic extends PureComponent {
|
|||||||
{editors}
|
{editors}
|
||||||
</ReflexElement>
|
</ReflexElement>
|
||||||
<ReflexSplitter propagate={true} {...this.resizeProps} />
|
<ReflexSplitter propagate={true} {...this.resizeProps} />
|
||||||
<ReflexElement flex={0.5} {...this.resizeProps}>
|
{showPreview ? (
|
||||||
{showPreview ? (
|
<ReflexElement flex={0.7} {...this.resizeProps}>
|
||||||
<Preview
|
<Preview
|
||||||
className='full-height'
|
className='full-height'
|
||||||
disableIframe={this.state.resizing}
|
disableIframe={this.state.resizing}
|
||||||
/>
|
/>
|
||||||
) : null}
|
</ReflexElement>
|
||||||
<Spacer />
|
) : null}
|
||||||
<TestSuite tests={tests} />
|
|
||||||
</ReflexElement>
|
|
||||||
</ReflexContainer>
|
</ReflexContainer>
|
||||||
|
|
||||||
<CompletionModal />
|
<CompletionModal />
|
||||||
|
@@ -6,11 +6,16 @@ import { bindActionCreators } from 'redux';
|
|||||||
|
|
||||||
import ChallengeTitle from './Challenge-Title';
|
import ChallengeTitle from './Challenge-Title';
|
||||||
import ChallengeDescription from './Challenge-Description';
|
import ChallengeDescription from './Challenge-Description';
|
||||||
|
import ToolPanel from './Tool-Panel';
|
||||||
|
import TestSuite from './Test-Suite';
|
||||||
import Spacer from '../../../components/util/Spacer';
|
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 =>
|
const mapDispatchToProps = dispatch =>
|
||||||
bindActionCreators(
|
bindActionCreators(
|
||||||
@@ -22,7 +27,9 @@ const mapDispatchToProps = dispatch =>
|
|||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
description: PropTypes.arrayOf(PropTypes.string),
|
description: PropTypes.arrayOf(PropTypes.string),
|
||||||
|
guideUrl: PropTypes.string,
|
||||||
initConsole: PropTypes.func.isRequired,
|
initConsole: PropTypes.func.isRequired,
|
||||||
|
tests: PropTypes.arrayOf(PropTypes.object),
|
||||||
title: PropTypes.string
|
title: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -52,7 +59,7 @@ export class SidePanel extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { title, description } = this.props;
|
const { title, description, guideUrl, tests } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className='instructions-panel' role='complementary'>
|
<div className='instructions-panel' role='complementary'>
|
||||||
<div ref={this.bindTopDiv} />
|
<div ref={this.bindTopDiv} />
|
||||||
@@ -61,7 +68,9 @@ export class SidePanel extends PureComponent {
|
|||||||
<ChallengeTitle>{title}</ChallengeTitle>
|
<ChallengeTitle>{title}</ChallengeTitle>
|
||||||
<ChallengeDescription description={description} />
|
<ChallengeDescription description={description} />
|
||||||
</div>
|
</div>
|
||||||
<Spacer />
|
<hr />
|
||||||
|
<ToolPanel guideUrl={guideUrl} />
|
||||||
|
<TestSuite tests={tests} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,8 @@ import React from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import GreenPass from './icons/GreenPass';
|
import GreenPass from './icons/GreenPass';
|
||||||
import RedFail from './icons/RedFail';
|
import Fail from './icons/Fail';
|
||||||
|
import Initial from './icons/Initial';
|
||||||
|
|
||||||
import './test-suite.css';
|
import './test-suite.css';
|
||||||
|
|
||||||
@@ -28,6 +29,8 @@ function TestSuite({ tests }) {
|
|||||||
return (
|
return (
|
||||||
<div className='challenge-test-suite'>
|
<div className='challenge-test-suite'>
|
||||||
{tests.map(({ err, pass = false, text = '' }, index) => {
|
{tests.map(({ err, pass = false, text = '' }, index) => {
|
||||||
|
const isInitial = !pass && !err;
|
||||||
|
const statusIcon = pass && !err ? <GreenPass /> : <Fail />;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
aria-label={getAccessibleText(err, pass, text)}
|
aria-label={getAccessibleText(err, pass, text)}
|
||||||
@@ -36,7 +39,7 @@ function TestSuite({ tests }) {
|
|||||||
tabIndex='0'
|
tabIndex='0'
|
||||||
>
|
>
|
||||||
<div className='test-status-icon'>
|
<div className='test-status-icon'>
|
||||||
{pass ? <GreenPass /> : <RedFail />}
|
{isInitial ? <Initial /> : statusIcon}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
aria-hidden='true'
|
aria-hidden='true'
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import React from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
@@ -7,7 +7,6 @@ import { Button } from 'react-bootstrap';
|
|||||||
|
|
||||||
import './tool-panel.css';
|
import './tool-panel.css';
|
||||||
import { openModal, executeChallenge } from '../redux';
|
import { openModal, executeChallenge } from '../redux';
|
||||||
import { toggleMapModal } from '../../../redux/app';
|
|
||||||
|
|
||||||
const mapStateToProps = () => ({});
|
const mapStateToProps = () => ({});
|
||||||
const mapDispatchToProps = dispatch =>
|
const mapDispatchToProps = dispatch =>
|
||||||
@@ -15,8 +14,7 @@ const mapDispatchToProps = dispatch =>
|
|||||||
{
|
{
|
||||||
executeChallenge,
|
executeChallenge,
|
||||||
openHelpModal: () => openModal('help'),
|
openHelpModal: () => openModal('help'),
|
||||||
openResetModal: () => openModal('reset'),
|
openResetModal: () => openModal('reset')
|
||||||
toggleMapModal
|
|
||||||
},
|
},
|
||||||
dispatch
|
dispatch
|
||||||
);
|
);
|
||||||
@@ -25,37 +23,29 @@ const propTypes = {
|
|||||||
executeChallenge: PropTypes.func.isRequired,
|
executeChallenge: PropTypes.func.isRequired,
|
||||||
guideUrl: PropTypes.string,
|
guideUrl: PropTypes.string,
|
||||||
openHelpModal: PropTypes.func.isRequired,
|
openHelpModal: PropTypes.func.isRequired,
|
||||||
openResetModal: PropTypes.func.isRequired,
|
openResetModal: PropTypes.func.isRequired
|
||||||
toggleMapModal: PropTypes.func.isRequired
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function ToolPanel({
|
function ToolPanel({
|
||||||
executeChallenge,
|
executeChallenge,
|
||||||
openHelpModal,
|
openHelpModal,
|
||||||
openResetModal,
|
openResetModal,
|
||||||
toggleMapModal,
|
|
||||||
guideUrl
|
guideUrl
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className='tool-panel'>
|
<Fragment>
|
||||||
<div id='left-tool-panel'>
|
<div className='tool-panel-group'>
|
||||||
<Button
|
<Button block={true} bsStyle='primary' onClick={executeChallenge}>
|
||||||
bsStyle='primary'
|
|
||||||
className='btn-primary-invert'
|
|
||||||
onClick={toggleMapModal}
|
|
||||||
>
|
|
||||||
View the Curriculum
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div id='centre-tool-panel'>
|
|
||||||
<Button bsStyle='primary' onClick={executeChallenge}>
|
|
||||||
Run the Tests
|
Run the Tests
|
||||||
</Button>
|
</Button>
|
||||||
<Button bsStyle='default' onClick={openResetModal}>
|
<Button
|
||||||
|
block={true}
|
||||||
|
bsStyle='primary'
|
||||||
|
className='btn-primary-invert'
|
||||||
|
onClick={openResetModal}
|
||||||
|
>
|
||||||
Reset All Code
|
Reset All Code
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
|
||||||
<div id='right-tool-panel'>
|
|
||||||
{guideUrl ? (
|
{guideUrl ? (
|
||||||
<Button
|
<Button
|
||||||
block={true}
|
block={true}
|
||||||
@@ -76,7 +66,7 @@ function ToolPanel({
|
|||||||
Ask for help
|
Ask for help
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,7 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
const propTypes = {};
|
|
||||||
|
|
||||||
function RedFail() {
|
function RedFail() {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
@@ -15,9 +13,9 @@ function RedFail() {
|
|||||||
<circle
|
<circle
|
||||||
cx='100'
|
cx='100'
|
||||||
cy='99'
|
cy='99'
|
||||||
fill='#ff0000'
|
fill='#555'
|
||||||
r='95'
|
r='95'
|
||||||
stroke='#ff0000'
|
stroke='#555'
|
||||||
strokeDasharray='null'
|
strokeDasharray='null'
|
||||||
strokeLinecap='null'
|
strokeLinecap='null'
|
||||||
strokeLinejoin='null'
|
strokeLinejoin='null'
|
||||||
@@ -52,6 +50,5 @@ function RedFail() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RedFail.displayName = 'RedFail';
|
RedFail.displayName = 'RedFail';
|
||||||
RedFail.propTypes = propTypes;
|
|
||||||
|
|
||||||
export default RedFail;
|
export default RedFail;
|
@@ -1,7 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
const propTypes = {};
|
|
||||||
|
|
||||||
function GreenPass(props) {
|
function GreenPass(props) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
@@ -53,6 +51,5 @@ function GreenPass(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GreenPass.displayName = 'GreenPass';
|
GreenPass.displayName = 'GreenPass';
|
||||||
GreenPass.propTypes = propTypes;
|
|
||||||
|
|
||||||
export default GreenPass;
|
export default GreenPass;
|
||||||
|
@@ -0,0 +1,55 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
function Initial(props) {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
height='50'
|
||||||
|
viewBox='0 0 200 200'
|
||||||
|
width='50'
|
||||||
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<title>Initial</title>
|
||||||
|
<circle
|
||||||
|
cx='100'
|
||||||
|
cy='99'
|
||||||
|
fill='#555'
|
||||||
|
r='95'
|
||||||
|
stroke='#555'
|
||||||
|
strokeDasharray='null'
|
||||||
|
strokeLinecap='null'
|
||||||
|
strokeLinejoin='null'
|
||||||
|
/>
|
||||||
|
<svg
|
||||||
|
height='200'
|
||||||
|
viewBox='-13 -12 50 50'
|
||||||
|
width='200'
|
||||||
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d={
|
||||||
|
'M8 1c0-.552.448-1 1-1h6c.553 0 1 .448 1 1s-.447 1-1 1h-6c-' +
|
||||||
|
'.552 0-1-.448-1-1zm13 20.554c0 1.284-1.023 2.446-2.424 ' +
|
||||||
|
'2.446h-13.153c-1.4 0-2.423-1.162-2.423-2.445 0-.35.076-.709.' +
|
||||||
|
'242-1.057l3.743-7.856c1.04-2.186 2.015-4.581 2.015-7.007v-1.' +
|
||||||
|
'635h2l-.006 2c-.087 2.623-1.09 5.092-1.973 7h3.682l4.377 9h1.' +
|
||||||
|
'496c.309 0 .52-.342.377-.644l-3.743-7.854c-1.046-2.197-2.12-4' +
|
||||||
|
'.791-2.21-7.502v-2h2v1.635c0 2.426.975 4.82 2.016 7.006l3.743' +
|
||||||
|
' 7.856c.165.348.241.707.241 1.057zm-12-1.054c0-.829-.671-1.5-' +
|
||||||
|
'1.5-1.5s-1.5.671-1.5 1.5.671 1.5 1.5 1.5 1.5-.671 1.5-1.5zm2-' +
|
||||||
|
'3.5c0-.553-.448-1-1-1-.553 0-1 .447-1 1s.447 1 1 1c.552 0 1-.' +
|
||||||
|
'447 1-1zm3 3c0-.552-.448-1-1-1s-1 .448-1 1 .448 1 1 1 1-.448 ' +
|
||||||
|
'1-1z'
|
||||||
|
}
|
||||||
|
fill='#fff'
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Initial.displayName = 'Initial';
|
||||||
|
|
||||||
|
export default Initial;
|
@@ -6,7 +6,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.challenge-preview, .challenge-preview-frame {
|
.challenge-preview, .challenge-preview-frame {
|
||||||
height: calc(60vh);
|
height: calc(100vh - 40px);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
margin-top: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.test-result {
|
.test-result {
|
||||||
|
@@ -1,22 +1,8 @@
|
|||||||
.tool-panel {
|
.tool-panel-group button, .tool-panel-group a {
|
||||||
height: 40px;
|
font-size: 1.1rem;
|
||||||
display: flex;
|
|
||||||
justify-content: space-around;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
background-color: #99C199;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#centre-tool-panel {
|
.project-tool-panel {
|
||||||
width: 300px;
|
width: 100%;
|
||||||
}
|
padding: 0 15px;
|
||||||
|
|
||||||
#right-tool-panel {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#right-tool-panel a, #right-tool-panel .btn-block {
|
|
||||||
margin: 0;
|
|
||||||
}
|
}
|
||||||
|
@@ -24,6 +24,7 @@ import {
|
|||||||
import { frontEndProject } from '../../../../utils/challengeTypes';
|
import { frontEndProject } from '../../../../utils/challengeTypes';
|
||||||
|
|
||||||
import './project.css';
|
import './project.css';
|
||||||
|
import Spacer from '../../../components/util/Spacer';
|
||||||
|
|
||||||
const mapStateToProps = () => ({});
|
const mapStateToProps = () => ({});
|
||||||
const mapDispatchToProps = dispatch =>
|
const mapDispatchToProps = dispatch =>
|
||||||
@@ -106,7 +107,6 @@ export class Project extends PureComponent {
|
|||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Helmet title={`${blockNameTitle} | Learn freeCodeCamp}`} />
|
<Helmet title={`${blockNameTitle} | Learn freeCodeCamp}`} />
|
||||||
<ToolPanel />
|
|
||||||
<div className='project-show-wrapper'>
|
<div className='project-show-wrapper'>
|
||||||
<SidePanel
|
<SidePanel
|
||||||
className='full-height'
|
className='full-height'
|
||||||
@@ -119,6 +119,8 @@ export class Project extends PureComponent {
|
|||||||
openModal={openCompletionModal}
|
openModal={openCompletionModal}
|
||||||
updateProjectForm={updateProjectFormValues}
|
updateProjectForm={updateProjectFormValues}
|
||||||
/>
|
/>
|
||||||
|
<ToolPanel />
|
||||||
|
<Spacer />
|
||||||
</div>
|
</div>
|
||||||
<CompletionModal />
|
<CompletionModal />
|
||||||
<HelpModal />
|
<HelpModal />
|
||||||
|
@@ -27,40 +27,28 @@ const propTypes = {
|
|||||||
|
|
||||||
export class ToolPanel extends PureComponent {
|
export class ToolPanel extends PureComponent {
|
||||||
render() {
|
render() {
|
||||||
const { guideUrl, openHelpModal, toggleMapModal } = this.props;
|
const { guideUrl, openHelpModal } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className='tool-panel'>
|
<div className='tool-panel-group project-tool-panel'>
|
||||||
<div id='left-tool-panel sub-panel'>
|
{guideUrl && (
|
||||||
<Button
|
|
||||||
bsStyle='primary'
|
|
||||||
className='btn-primary-invert'
|
|
||||||
onClick={toggleMapModal}
|
|
||||||
>
|
|
||||||
View the Curriculum
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div id='centre-tool-panel sub-panel' />
|
|
||||||
<div id='right-tool-panel sub-panel'>
|
|
||||||
{guideUrl && (
|
|
||||||
<Button
|
|
||||||
block={true}
|
|
||||||
bsStyle='primary'
|
|
||||||
className='btn-primary-invert'
|
|
||||||
href={guideUrl}
|
|
||||||
target='_blank'
|
|
||||||
>
|
|
||||||
Get a hint
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
<Button
|
<Button
|
||||||
block={true}
|
block={true}
|
||||||
bsStyle='primary'
|
bsStyle='primary'
|
||||||
className='btn-primary-invert'
|
className='btn-primary-invert'
|
||||||
onClick={openHelpModal}
|
href={guideUrl}
|
||||||
|
target='_blank'
|
||||||
>
|
>
|
||||||
Ask for help
|
Get a hint
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
)}
|
||||||
|
<Button
|
||||||
|
block={true}
|
||||||
|
bsStyle='primary'
|
||||||
|
className='btn-primary-invert'
|
||||||
|
onClick={openHelpModal}
|
||||||
|
>
|
||||||
|
Ask for help
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -1,29 +1,21 @@
|
|||||||
/* global graphql */
|
/* global graphql */
|
||||||
import React, { Fragment } from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { bindActionCreators } from 'redux';
|
import Link, { navigateTo } from 'gatsby-link';
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import Link from 'gatsby-link';
|
|
||||||
import Helmet from 'react-helmet';
|
import Helmet from 'react-helmet';
|
||||||
import { Button, ListGroup, ListGroupItem } from 'react-bootstrap';
|
import { Button, ListGroup, ListGroupItem } from 'react-bootstrap';
|
||||||
|
|
||||||
import FullWidthRow from '../../components/util/FullWidthRow';
|
import FullWidthRow from '../../components/util/FullWidthRow';
|
||||||
import ButtonSpacer from '../../components/util/ButtonSpacer';
|
import ButtonSpacer from '../../components/util/ButtonSpacer';
|
||||||
import { toggleMapModal } from '../../redux/app';
|
|
||||||
import { MarkdownRemark, AllChallengeNode } from '../../redux/propTypes';
|
import { MarkdownRemark, AllChallengeNode } from '../../redux/propTypes';
|
||||||
|
|
||||||
import './intro.css';
|
import './intro.css';
|
||||||
|
|
||||||
const mapStateToProps = () => ({});
|
|
||||||
const mapDispatchToProps = dispatch =>
|
|
||||||
bindActionCreators({ toggleMapModal }, dispatch);
|
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
data: PropTypes.shape({
|
data: PropTypes.shape({
|
||||||
markdownRemark: MarkdownRemark,
|
markdownRemark: MarkdownRemark,
|
||||||
allChallengeNode: AllChallengeNode
|
allChallengeNode: AllChallengeNode
|
||||||
}),
|
})
|
||||||
toggleMapModal: PropTypes.func.isRequired
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function renderMenuItems({ edges = [] }) {
|
function renderMenuItems({ edges = [] }) {
|
||||||
@@ -34,10 +26,11 @@ function renderMenuItems({ edges = [] }) {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
function IntroductionPage({
|
function handleCurriculumClick() {
|
||||||
data: { markdownRemark, allChallengeNode },
|
return navigateTo('/');
|
||||||
toggleMapModal
|
}
|
||||||
}) {
|
|
||||||
|
function IntroductionPage({ data: { markdownRemark, allChallengeNode } }) {
|
||||||
const { html, frontmatter: { block } } = markdownRemark;
|
const { html, frontmatter: { block } } = markdownRemark;
|
||||||
const firstLesson = allChallengeNode && allChallengeNode.edges[0].node;
|
const firstLesson = allChallengeNode && allChallengeNode.edges[0].node;
|
||||||
const firstLessonPath = firstLesson
|
const firstLessonPath = firstLesson
|
||||||
@@ -63,7 +56,7 @@ function IntroductionPage({
|
|||||||
block={true}
|
block={true}
|
||||||
bsSize='lg'
|
bsSize='lg'
|
||||||
className='btn-primary-invert'
|
className='btn-primary-invert'
|
||||||
onClick={toggleMapModal}
|
onClick={handleCurriculumClick}
|
||||||
>
|
>
|
||||||
View the curriculum
|
View the curriculum
|
||||||
</Button>
|
</Button>
|
||||||
@@ -83,7 +76,7 @@ function IntroductionPage({
|
|||||||
IntroductionPage.displayName = 'IntroductionPage';
|
IntroductionPage.displayName = 'IntroductionPage';
|
||||||
IntroductionPage.propTypes = propTypes;
|
IntroductionPage.propTypes = propTypes;
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(IntroductionPage);
|
export default IntroductionPage;
|
||||||
|
|
||||||
export const query = graphql`
|
export const query = graphql`
|
||||||
query IntroPageBySlug($slug: String!, $block: String!) {
|
query IntroPageBySlug($slug: String!, $block: String!) {
|
||||||
|
@@ -1914,13 +1914,6 @@ callsites@^2.0.0:
|
|||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50"
|
resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50"
|
||||||
|
|
||||||
camelcase-keys@^2.0.0:
|
|
||||||
version "2.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7"
|
|
||||||
dependencies:
|
|
||||||
camelcase "^2.0.0"
|
|
||||||
map-obj "^1.0.0"
|
|
||||||
|
|
||||||
camelcase@4.1.0, camelcase@^4.0.0, camelcase@^4.1.0:
|
camelcase@4.1.0, camelcase@^4.0.0, camelcase@^4.1.0:
|
||||||
version "4.1.0"
|
version "4.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
|
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
|
||||||
@@ -1929,10 +1922,6 @@ camelcase@^1.0.2:
|
|||||||
version "1.2.1"
|
version "1.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"
|
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"
|
||||||
|
|
||||||
camelcase@^2.0.0:
|
|
||||||
version "2.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
|
|
||||||
|
|
||||||
camelcase@^3.0.0:
|
camelcase@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
|
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
|
||||||
@@ -2137,7 +2126,7 @@ class-utils@^0.3.5:
|
|||||||
isobject "^3.0.0"
|
isobject "^3.0.0"
|
||||||
static-extend "^0.1.1"
|
static-extend "^0.1.1"
|
||||||
|
|
||||||
classnames@^2.2.5:
|
classnames@^2.2.3, classnames@^2.2.5:
|
||||||
version "2.2.5"
|
version "2.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d"
|
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d"
|
||||||
|
|
||||||
@@ -3011,12 +3000,6 @@ dom-serializer@0, dom-serializer@~0.1.0:
|
|||||||
domelementtype "~1.1.1"
|
domelementtype "~1.1.1"
|
||||||
entities "~1.1.1"
|
entities "~1.1.1"
|
||||||
|
|
||||||
dom-urls@^1.1.0:
|
|
||||||
version "1.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/dom-urls/-/dom-urls-1.1.0.tgz#001ddf81628cd1e706125c7176f53ccec55d918e"
|
|
||||||
dependencies:
|
|
||||||
urijs "^1.16.1"
|
|
||||||
|
|
||||||
dom-walk@^0.1.0:
|
dom-walk@^0.1.0:
|
||||||
version "0.1.1"
|
version "0.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018"
|
resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018"
|
||||||
@@ -3335,7 +3318,7 @@ es6-promise@3.2.1:
|
|||||||
version "3.2.1"
|
version "3.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.2.1.tgz#ec56233868032909207170c39448e24449dd1fc4"
|
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.2.1.tgz#ec56233868032909207170c39448e24449dd1fc4"
|
||||||
|
|
||||||
es6-promise@^4.0.2, es6-promise@^4.0.5, es6-promise@^4.1.0:
|
es6-promise@^4.0.2, es6-promise@^4.1.0:
|
||||||
version "4.2.4"
|
version "4.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.4.tgz#dc4221c2b16518760bd8c39a52d8f356fc00ed29"
|
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.4.tgz#dc4221c2b16518760bd8c39a52d8f356fc00ed29"
|
||||||
|
|
||||||
@@ -4208,13 +4191,6 @@ gatsby-plugin-google-fonts@^0.0.4:
|
|||||||
version "0.0.4"
|
version "0.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-google-fonts/-/gatsby-plugin-google-fonts-0.0.4.tgz#dc1402a71f27c3ae6caee10777d10adadf74bd7c"
|
resolved "https://registry.yarnpkg.com/gatsby-plugin-google-fonts/-/gatsby-plugin-google-fonts-0.0.4.tgz#dc1402a71f27c3ae6caee10777d10adadf74bd7c"
|
||||||
|
|
||||||
gatsby-plugin-offline@^1.0.15:
|
|
||||||
version "1.0.15"
|
|
||||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-offline/-/gatsby-plugin-offline-1.0.15.tgz#26af0e1d1c8ed0c31f92bc6a75484b583550ef5b"
|
|
||||||
dependencies:
|
|
||||||
babel-runtime "^6.26.0"
|
|
||||||
sw-precache "^5.0.0"
|
|
||||||
|
|
||||||
gatsby-plugin-react-helmet@^2.0.8:
|
gatsby-plugin-react-helmet@^2.0.8:
|
||||||
version "2.0.8"
|
version "2.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-react-helmet/-/gatsby-plugin-react-helmet-2.0.8.tgz#26928bfd38f6828f479d76393839523ddf85b005"
|
resolved "https://registry.yarnpkg.com/gatsby-plugin-react-helmet/-/gatsby-plugin-react-helmet-2.0.8.tgz#26928bfd38f6828f479d76393839523ddf85b005"
|
||||||
@@ -4467,10 +4443,6 @@ get-port@^3.0.0:
|
|||||||
version "3.2.0"
|
version "3.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc"
|
resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc"
|
||||||
|
|
||||||
get-stdin@^4.0.1:
|
|
||||||
version "4.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
|
|
||||||
|
|
||||||
get-stream@^3.0.0:
|
get-stream@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
|
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
|
||||||
@@ -5151,12 +5123,6 @@ imurmurhash@^0.1.4:
|
|||||||
version "0.1.4"
|
version "0.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
||||||
|
|
||||||
indent-string@^2.1.0:
|
|
||||||
version "2.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
|
|
||||||
dependencies:
|
|
||||||
repeating "^2.0.0"
|
|
||||||
|
|
||||||
indexes-of@^1.0.1:
|
indexes-of@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
|
resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
|
||||||
@@ -6362,6 +6328,10 @@ loader-utils@^1.0.2, loader-utils@^1.1.0:
|
|||||||
emojis-list "^2.0.0"
|
emojis-list "^2.0.0"
|
||||||
json5 "^0.5.0"
|
json5 "^0.5.0"
|
||||||
|
|
||||||
|
loaders.css@^0.1.2:
|
||||||
|
version "0.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/loaders.css/-/loaders.css-0.1.2.tgz#3a9fb43726c73334a38142af9d0629019b658743"
|
||||||
|
|
||||||
locate-path@^2.0.0:
|
locate-path@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
|
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
|
||||||
@@ -6401,7 +6371,7 @@ lodash.clonedeep@^4.5.0:
|
|||||||
version "4.5.0"
|
version "4.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
|
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
|
||||||
|
|
||||||
lodash.defaults@^4.0.1, lodash.defaults@^4.2.0:
|
lodash.defaults@^4.0.1:
|
||||||
version "4.2.0"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
|
resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
|
||||||
|
|
||||||
@@ -6497,7 +6467,7 @@ lodash.sortby@^4.7.0:
|
|||||||
version "4.7.0"
|
version "4.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
|
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
|
||||||
|
|
||||||
lodash.template@^4.2.4, lodash.template@^4.4.0:
|
lodash.template@^4.2.4:
|
||||||
version "4.4.0"
|
version "4.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.4.0.tgz#e73a0385c8355591746e020b99679c690e68fba0"
|
resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.4.0.tgz#e73a0385c8355591746e020b99679c690e68fba0"
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -6566,7 +6536,7 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3
|
|||||||
dependencies:
|
dependencies:
|
||||||
js-tokens "^3.0.0"
|
js-tokens "^3.0.0"
|
||||||
|
|
||||||
loud-rejection@^1.0.0, loud-rejection@^1.2.0:
|
loud-rejection@^1.2.0:
|
||||||
version "1.6.0"
|
version "1.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
|
resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -6623,10 +6593,6 @@ map-cache@^0.2.0, map-cache@^0.2.2:
|
|||||||
version "0.2.2"
|
version "0.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
|
resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
|
||||||
|
|
||||||
map-obj@^1.0.0, map-obj@^1.0.1:
|
|
||||||
version "1.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
|
|
||||||
|
|
||||||
map-visit@^1.0.0:
|
map-visit@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f"
|
resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f"
|
||||||
@@ -6754,21 +6720,6 @@ memory-fs@~0.4.1:
|
|||||||
errno "^0.1.3"
|
errno "^0.1.3"
|
||||||
readable-stream "^2.0.1"
|
readable-stream "^2.0.1"
|
||||||
|
|
||||||
meow@^3.7.0:
|
|
||||||
version "3.7.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
|
|
||||||
dependencies:
|
|
||||||
camelcase-keys "^2.0.0"
|
|
||||||
decamelize "^1.1.2"
|
|
||||||
loud-rejection "^1.0.0"
|
|
||||||
map-obj "^1.0.1"
|
|
||||||
minimist "^1.1.3"
|
|
||||||
normalize-package-data "^2.3.4"
|
|
||||||
object-assign "^4.0.1"
|
|
||||||
read-pkg-up "^1.0.1"
|
|
||||||
redent "^1.0.0"
|
|
||||||
trim-newlines "^1.0.0"
|
|
||||||
|
|
||||||
merge-descriptors@1.0.1:
|
merge-descriptors@1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
|
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
|
||||||
@@ -6905,7 +6856,7 @@ minimist@0.0.8:
|
|||||||
version "0.0.8"
|
version "0.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
|
||||||
|
|
||||||
minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0:
|
minimist@^1.1.1, minimist@^1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
|
||||||
|
|
||||||
@@ -7199,7 +7150,7 @@ nopt@^4.0.1:
|
|||||||
abbrev "1"
|
abbrev "1"
|
||||||
osenv "^0.1.4"
|
osenv "^0.1.4"
|
||||||
|
|
||||||
normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
|
normalize-package-data@^2.3.2:
|
||||||
version "2.4.0"
|
version "2.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f"
|
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f"
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -7711,7 +7662,7 @@ path-to-regexp@0.1.7:
|
|||||||
version "0.1.7"
|
version "0.1.7"
|
||||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
|
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
|
||||||
|
|
||||||
path-to-regexp@^1.0.1, path-to-regexp@^1.7.0:
|
path-to-regexp@^1.7.0:
|
||||||
version "1.7.0"
|
version "1.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d"
|
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d"
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -8860,6 +8811,15 @@ react-side-effect@^1.1.0:
|
|||||||
exenv "^1.2.1"
|
exenv "^1.2.1"
|
||||||
shallowequal "^1.0.1"
|
shallowequal "^1.0.1"
|
||||||
|
|
||||||
|
react-spinkit@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-spinkit/-/react-spinkit-3.0.0.tgz#31fdaf4e18177766c57d1b1f3330290f8492a85a"
|
||||||
|
dependencies:
|
||||||
|
classnames "^2.2.3"
|
||||||
|
loaders.css "^0.1.2"
|
||||||
|
object-assign "^4.1.0"
|
||||||
|
prop-types "^15.5.8"
|
||||||
|
|
||||||
react-test-renderer@^16.0.0-0, react-test-renderer@^16.3.1:
|
react-test-renderer@^16.0.0-0, react-test-renderer@^16.3.1:
|
||||||
version "16.3.1"
|
version "16.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.3.1.tgz#d9257936d8535bd40f57f3d5a84e7b0452fb17f2"
|
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.3.1.tgz#d9257936d8535bd40f57f3d5a84e7b0452fb17f2"
|
||||||
@@ -9036,13 +8996,6 @@ redbox-react@^1.3.6:
|
|||||||
prop-types "^15.5.4"
|
prop-types "^15.5.4"
|
||||||
sourcemapped-stacktrace "^1.1.6"
|
sourcemapped-stacktrace "^1.1.6"
|
||||||
|
|
||||||
redent@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
|
|
||||||
dependencies:
|
|
||||||
indent-string "^2.1.0"
|
|
||||||
strip-indent "^1.0.1"
|
|
||||||
|
|
||||||
reduce-css-calc@^1.2.6, reduce-css-calc@^1.2.7:
|
reduce-css-calc@^1.2.6, reduce-css-calc@^1.2.7:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716"
|
resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716"
|
||||||
@@ -9817,10 +9770,6 @@ serve@^6.4.0:
|
|||||||
path-type "3.0.0"
|
path-type "3.0.0"
|
||||||
send "0.16.2"
|
send "0.16.2"
|
||||||
|
|
||||||
serviceworker-cache-polyfill@^4.0.0:
|
|
||||||
version "4.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/serviceworker-cache-polyfill/-/serviceworker-cache-polyfill-4.0.0.tgz#de19ee73bef21ab3c0740a37b33db62464babdeb"
|
|
||||||
|
|
||||||
set-blocking@^1.0.0:
|
set-blocking@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-1.0.0.tgz#cd5e5d938048df1ac92dfe92e1f16add656f5ec5"
|
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-1.0.0.tgz#cd5e5d938048df1ac92dfe92e1f16add656f5ec5"
|
||||||
@@ -10421,12 +10370,6 @@ strip-eof@^1.0.0:
|
|||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
|
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
|
||||||
|
|
||||||
strip-indent@^1.0.1:
|
|
||||||
version "1.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2"
|
|
||||||
dependencies:
|
|
||||||
get-stdin "^4.0.1"
|
|
||||||
|
|
||||||
strip-json-comments@~2.0.1:
|
strip-json-comments@~2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
|
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
|
||||||
@@ -10486,28 +10429,6 @@ svgo@^0.7.0:
|
|||||||
sax "~1.2.1"
|
sax "~1.2.1"
|
||||||
whet.extend "~0.9.9"
|
whet.extend "~0.9.9"
|
||||||
|
|
||||||
sw-precache@^5.0.0:
|
|
||||||
version "5.2.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/sw-precache/-/sw-precache-5.2.1.tgz#06134f319eec68f3b9583ce9a7036b1c119f7179"
|
|
||||||
dependencies:
|
|
||||||
dom-urls "^1.1.0"
|
|
||||||
es6-promise "^4.0.5"
|
|
||||||
glob "^7.1.1"
|
|
||||||
lodash.defaults "^4.2.0"
|
|
||||||
lodash.template "^4.4.0"
|
|
||||||
meow "^3.7.0"
|
|
||||||
mkdirp "^0.5.1"
|
|
||||||
pretty-bytes "^4.0.2"
|
|
||||||
sw-toolbox "^3.4.0"
|
|
||||||
update-notifier "^2.3.0"
|
|
||||||
|
|
||||||
sw-toolbox@^3.4.0:
|
|
||||||
version "3.6.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/sw-toolbox/-/sw-toolbox-3.6.0.tgz#26df1d1c70348658e4dea2884319149b7b3183b5"
|
|
||||||
dependencies:
|
|
||||||
path-to-regexp "^1.0.1"
|
|
||||||
serviceworker-cache-polyfill "^4.0.0"
|
|
||||||
|
|
||||||
symbol-observable@1.0.1:
|
symbol-observable@1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4"
|
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4"
|
||||||
@@ -10753,10 +10674,6 @@ trim-lines@^1.0.0:
|
|||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-1.1.0.tgz#9926d03ede13ba18f7d42222631fb04c79ff26fe"
|
resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-1.1.0.tgz#9926d03ede13ba18f7d42222631fb04c79ff26fe"
|
||||||
|
|
||||||
trim-newlines@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
|
|
||||||
|
|
||||||
trim-right@^1.0.1:
|
trim-right@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
|
resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
|
||||||
@@ -11074,10 +10991,6 @@ uri-js@^3.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
punycode "^2.1.0"
|
punycode "^2.1.0"
|
||||||
|
|
||||||
urijs@^1.16.1:
|
|
||||||
version "1.19.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.1.tgz#5b0ff530c0cbde8386f6342235ba5ca6e995d25a"
|
|
||||||
|
|
||||||
urix@^0.1.0:
|
urix@^0.1.0:
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
|
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
|
||||||
@@ -11352,6 +11265,10 @@ webpack-md5-hash@0.0.5:
|
|||||||
dependencies:
|
dependencies:
|
||||||
md5 "^2.0.0"
|
md5 "^2.0.0"
|
||||||
|
|
||||||
|
webpack-remove-serviceworker-plugin@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/webpack-remove-serviceworker-plugin/-/webpack-remove-serviceworker-plugin-1.0.0.tgz#63a7604da9a7fd9bae8f9eef87d274a2470dcaa7"
|
||||||
|
|
||||||
webpack-sources@^0.1.0:
|
webpack-sources@^0.1.0:
|
||||||
version "0.1.5"
|
version "0.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-0.1.5.tgz#aa1f3abf0f0d74db7111c40e500b84f966640750"
|
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-0.1.5.tgz#aa1f3abf0f0d74db7111c40e500b84f966640750"
|
||||||
|
Reference in New Issue
Block a user