diff --git a/common/app/Nav/Nav.jsx b/common/app/Nav/Nav.jsx
index 463519a77e..2fb225beca 100644
--- a/common/app/Nav/Nav.jsx
+++ b/common/app/Nav/Nav.jsx
@@ -2,53 +2,22 @@ import React from 'react';
import PropTypes from 'prop-types';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
-import capitalize from 'lodash/capitalize';
import { createSelector } from 'reselect';
import FCCSearchBar from 'react-freecodecamp-search';
import {
- MenuItem,
- Nav,
- NavDropdown,
- NavItem,
- Navbar,
- NavbarBrand
+ Navbar
} from 'react-bootstrap';
-import NoPropsPassThrough from '../utils/No-Props-Passthrough.jsx';
-import { Link } from '../Router';
-import navLinks from './links.json';
-import SignUp from './Sign-Up.jsx';
-import BinButton from './Bin-Button.jsx';
+import { BinButtons, NavLogo, NavLinks } from './components';
import {
clickOnLogo,
- clickOnMap,
- openDropdown,
- closeDropdown,
- createNavLinkActionCreator,
-
- dropdownSelector
+ clickOnMap
} from './redux';
-import { isSignedInSelector, signInLoadingSelector } from '../redux';
import { panesSelector } from '../Panes/redux';
-import { onRouteCurrentChallenge } from '../routes/Challenges/redux';
-
-
-const fCClogo = 'https://s3.amazonaws.com/freecodecamp/freecodecamp_logo.svg';
-// TODO @freecodecamp-team: place this glyph in S3 like above, PR in /assets
-const fCCglyph = 'https://raw.githubusercontent.com/freeCodeCamp/assets/' +
- '3b9cafc312802199ebba8b31fb1ed9b466a3efbb/assets/logos/FFCFire.png';
const mapStateToProps = createSelector(
- isSignedInSelector,
- dropdownSelector,
- signInLoadingSelector,
panesSelector,
- (
- isSignedIn,
- isDropdownOpen,
- showLoading,
- panes,
- ) => {
+ panes => {
return {
panes: panes.map(({ name, type }) => {
return {
@@ -56,20 +25,13 @@ const mapStateToProps = createSelector(
action: type
};
}, {}),
- isDropdownOpen,
- isSignedIn,
- showLoading
+ shouldShowMapButton: panes.length === 0
};
}
);
function mapDispatchToProps(dispatch) {
- const dispatchers = bindActionCreators(navLinks.reduce(
- (mdtp, { content }) => {
- const handler = `handle${capitalize(content)}Click`;
- mdtp[handler] = createNavLinkActionCreator(content);
- return mdtp;
- },
+ const dispatchers = bindActionCreators(
{
clickOnMap: e => {
e.preventDefault();
@@ -78,11 +40,10 @@ function mapDispatchToProps(dispatch) {
clickOnLogo: e => {
e.preventDefault();
return clickOnLogo();
- },
- closeDropdown: () => closeDropdown(),
- openDropdown: () => openDropdown()
- }
- ), dispatch);
+ }
+ },
+ dispatch
+ );
dispatchers.dispatch = dispatch;
return () => dispatchers;
}
@@ -105,153 +66,42 @@ function mergeProps(stateProps, dispatchProps, ownProps) {
const propTypes = {
clickOnLogo: PropTypes.func.isRequired,
clickOnMap: PropTypes.func.isRequired,
- closeDropdown: PropTypes.func.isRequired,
- isDropdownOpen: PropTypes.bool,
- isSignedIn: PropTypes.bool,
- openDropdown: PropTypes.func.isRequired,
panes: PropTypes.array,
- showLoading: PropTypes.bool,
- signedIn: PropTypes.bool
+ shouldShowMapButton: PropTypes.bool
};
-export class FCCNav extends React.Component {
- renderLink(isNavItem, { isReact, isDropdown, content, link, links, target }) {
- const Component = isNavItem ? NavItem : MenuItem;
- const {
- isDropdownOpen,
- openDropdown,
- closeDropdown
- } = this.props;
-
- if (isDropdown) {
- // adding a noop to NavDropdown to disable false warning
- // about controlled component
- return (
-
- { links.map(this.renderLink.bind(this, false)) }
-
- );
- }
- if (isReact) {
- return (
-
-
- { content }
-
-
- );
- }
- return (
-
- { content }
-
- );
- }
-
- render() {
- const {
- panes,
- isSignedIn,
- clickOnLogo,
- clickOnMap,
- showLoading
- } = this.props;
-
- const shouldShowMapButton = panes.length === 0;
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
- }
+function FCCNav(props) {
+ const {
+ panes,
+ clickOnLogo,
+ clickOnMap,
+ shouldShowMapButton
+ } = props;
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
}
FCCNav.displayName = 'FCCNav';
diff --git a/common/app/Nav/Bin-Button.jsx b/common/app/Nav/components/Bin-Button.jsx
similarity index 100%
rename from common/app/Nav/Bin-Button.jsx
rename to common/app/Nav/components/Bin-Button.jsx
diff --git a/common/app/Nav/components/BinButtons.jsx b/common/app/Nav/components/BinButtons.jsx
new file mode 100644
index 0000000000..67ae2072d6
--- /dev/null
+++ b/common/app/Nav/components/BinButtons.jsx
@@ -0,0 +1,36 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Nav } from 'react-bootstrap';
+import BinButton from './Bin-Button.jsx';
+
+const propTypes = {
+ panes: PropTypes.arrayOf(
+ PropTypes.shape({
+ actionCreator: PropTypes.func.isRequired,
+ content: PropTypes.string.isRequired
+ })
+ )
+};
+
+function BinButtons({ panes }) {
+ return (
+
+
+
+ );
+}
+
+BinButtons.displayName = 'BinButtons';
+BinButtons.propTypes = propTypes;
+
+export default BinButtons;
diff --git a/common/app/Nav/components/NavLinks.jsx b/common/app/Nav/components/NavLinks.jsx
new file mode 100644
index 0000000000..2a8cec2024
--- /dev/null
+++ b/common/app/Nav/components/NavLinks.jsx
@@ -0,0 +1,167 @@
+import React, { PureComponent } from 'react';
+import PropTypes from 'prop-types';
+import { capitalize } from 'lodash';
+import { bindActionCreators } from 'redux';
+import { connect } from 'react-redux';
+import { createSelector } from 'reselect';
+import { MenuItem, NavDropdown, NavItem, Nav } from 'react-bootstrap';
+
+import navLinks from '../links.json';
+import SignUp from './Sign-Up.jsx';
+import NoPropsPassThrough from '../../utils/No-Props-Passthrough.jsx';
+import { Link } from '../../Router';
+
+import { onRouteCurrentChallenge } from '../../routes/Challenges/redux';
+import {
+ openDropdown,
+ closeDropdown,
+ dropdownSelector,
+ createNavLinkActionCreator
+} from '../redux';
+import { isSignedInSelector, signInLoadingSelector } from '../../redux';
+
+const mapStateToProps = createSelector(
+ isSignedInSelector,
+ dropdownSelector,
+ signInLoadingSelector,
+ (isSignedIn, isDropdownOpen, showLoading) => ({
+ isDropdownOpen,
+ isSignedIn,
+ navLinks,
+ showLoading
+ })
+);
+
+function mapDispatchToProps(dispatch) {
+ return bindActionCreators(
+ {
+ ...navLinks.reduce(
+ (mdtp, { content }) => {
+ const handler = `handle${capitalize(content)}Click`;
+ mdtp[handler] = createNavLinkActionCreator(content);
+ return mdtp;
+ }),
+ closeDropdown,
+ openDropdown
+ },
+ dispatch
+ );
+}
+
+const navLinkPropType = PropTypes.shape({
+ content: PropTypes.string,
+ link: PropTypes.string,
+ isDropdown: PropTypes.bool,
+ target: PropTypes.string,
+ links: PropTypes.array
+});
+
+const propTypes = {
+ clickOnMap: PropTypes.func.isRequired,
+ closeDropdown: PropTypes.func.isRequired,
+ isDropdownOpen: PropTypes.bool,
+ isSignedIn: PropTypes.bool,
+ navLinks: PropTypes.arrayOf(navLinkPropType),
+ openDropdown: PropTypes.func.isRequired,
+ shouldShowMapButton: PropTypes.bool,
+ showLoading: PropTypes.bool
+};
+
+class NavLinks extends PureComponent {
+
+ renderLink(isNavItem, { isReact, isDropdown, content, link, links, target }) {
+ const Component = isNavItem ? NavItem : MenuItem;
+ const {
+ isDropdownOpen,
+ openDropdown,
+ closeDropdown
+ } = this.props;
+
+ if (isDropdown) {
+ // adding a noop to NavDropdown to disable false warning
+ // about controlled component
+ return (
+
+ { links.map(this.renderLink.bind(this, false)) }
+
+ );
+ }
+ if (isReact) {
+ return (
+
+
+ { content }
+
+
+ );
+ }
+ return (
+
+ { content }
+
+ );
+ }
+
+ render() {
+ const {
+ shouldShowMapButton,
+ clickOnMap,
+ showLoading,
+ isSignedIn,
+ navLinks
+ } = this.props;
+ return (
+
+ );
+ }
+}
+
+NavLinks.displayName = 'NavLinks';
+NavLinks.propTypes = propTypes;
+
+export default connect(mapStateToProps, mapDispatchToProps)(NavLinks);
diff --git a/common/app/Nav/components/NavLogo.jsx b/common/app/Nav/components/NavLogo.jsx
new file mode 100644
index 0000000000..9f06918d61
--- /dev/null
+++ b/common/app/Nav/components/NavLogo.jsx
@@ -0,0 +1,39 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { NavbarBrand } from 'react-bootstrap';
+
+const fCClogo = 'https://s3.amazonaws.com/freecodecamp/freecodecamp_logo.svg';
+// TODO @freecodecamp-team: place this glyph in S3 like above, PR in /assets
+const fCCglyph = 'https://raw.githubusercontent.com/freeCodeCamp/assets/' +
+ '3b9cafc312802199ebba8b31fb1ed9b466a3efbb/assets/logos/FFCFire.png';
+
+const propTypes = {
+ clickOnLogo: PropTypes.func.isRequired
+};
+
+function NavLogo({ clickOnLogo }) {
+ return (
+
+
+
+
+
+
+ );
+}
+
+NavLogo.displayName = 'NavLogo';
+NavLogo.propTypes = propTypes;
+
+export default NavLogo;
diff --git a/common/app/Nav/Sign-Up.jsx b/common/app/Nav/components/Sign-Up.jsx
similarity index 87%
rename from common/app/Nav/Sign-Up.jsx
rename to common/app/Nav/components/Sign-Up.jsx
index b91c9e895a..922ba52eca 100644
--- a/common/app/Nav/Sign-Up.jsx
+++ b/common/app/Nav/components/Sign-Up.jsx
@@ -2,8 +2,8 @@ import React from 'react';
import PropTypes from 'prop-types';
import { NavItem } from 'react-bootstrap';
-import { Link } from '../Router';
-import { onRouteSettings } from '../routes/Settings/redux';
+import { Link } from '../../Router';
+import { onRouteSettings } from '../../routes/Settings/redux';
const propTypes = {
showLoading: PropTypes.bool,
diff --git a/common/app/Nav/components/index.js b/common/app/Nav/components/index.js
new file mode 100644
index 0000000000..a406b1ec16
--- /dev/null
+++ b/common/app/Nav/components/index.js
@@ -0,0 +1,3 @@
+export { default as BinButtons } from './BinButtons.jsx';
+export { default as NavLogo } from './NavLogo.jsx';
+export { default as NavLinks } from './NavLinks.jsx';