diff --git a/client/index.js b/client/index.js index 969dab1366..514fb1a6f0 100644 --- a/client/index.js +++ b/client/index.js @@ -4,20 +4,13 @@ import Rx from 'rx'; import debug from 'debug'; import { render } from 'redux-epic'; import createHistory from 'history/createBrowserHistory'; -import useLangRoutes from './utils/use-lang-routes'; import sendPageAnalytics from './utils/send-page-analytics'; import { App, createApp, provideStore } from '../common/app'; -import { getLangFromPath } from '../common/app/utils/lang'; // client specific epics import epics from './epics'; -import { - isColdStored, - getColdStorage, - saveToColdStorage -} from './cold-reload'; const { __OPBEAT__ORG_ID, @@ -47,7 +40,7 @@ const { document, ga, __fcc__: { - data: ssrState = {}, + data: defaultState = {}, csrf: { token: csrfToken } = {} @@ -63,10 +56,6 @@ const epicOptions = { const DOMContainer = document.getElementById('fcc'); -const defaultState = isColdStored() ? - getColdStorage() : - ssrState; -const primaryLang = getLangFromPath(location.pathname); defaultState.app.csrfToken = csrfToken; @@ -76,7 +65,7 @@ const serviceOptions = { xhrTimeout: 15000 }; -const history = useLangRoutes(createHistory, primaryLang)(); +const history = createHistory(); sendPageAnalytics(history, ga); createApp({ @@ -88,14 +77,13 @@ createApp({ enhancers: isDev && devToolsExtension && [ devToolsExtension() ], middlewares: enableOpbeat && [ createOpbeatMiddleware() ] }) - .doOnNext(({ store }) => { + .doOnNext(() => { if (module.hot && typeof module.hot.accept === 'function') { module.hot.accept(() => { // note(berks): not sure this ever runs anymore after adding // RHR? log('saving state and refreshing.'); log('ignore react ssr warning.'); - saveToColdStorage(store.getState()); setTimeout(() => location.reload(), hotReloadTimeout); }); } diff --git a/client/less/main.less b/client/less/main.less index f1653e0759..db9a804e05 100644 --- a/client/less/main.less +++ b/client/less/main.less @@ -152,6 +152,24 @@ h1, h2, h3, h4, h5, h6, p, li { width: 100px; } +p.stats { + font-size: 2rem; +} + +.green-text { + color: #006400; +} + +.more-button-container { + display: flex; + justify-content: center; + align-items: center; + + div { + flex-grow: 1; + } +} + .completion-icon { font-size: 150px; } diff --git a/client/utils/use-lang-routes.js b/client/utils/use-lang-routes.js deleted file mode 100644 index d254e1ac09..0000000000 --- a/client/utils/use-lang-routes.js +++ /dev/null @@ -1,44 +0,0 @@ -import { addLang, getLangFromPath } from '../../common/app/utils/lang.js'; - -function addLangToLocation(location, lang) { - if (!location) { - return location; - } - if (typeof location === 'string') { - return addLang(location, lang); - } - return { - ...location, - pathname: addLang(location.pathname, lang) - }; -} - -function getLangFromLocation(location) { - if (!location) { - return location; - } - if (typeof location === 'string') { - return getLangFromPath(location); - } - return getLangFromPath(location.pathname); -} - -export default function useLangRoutes(createHistory, primaryLang) { - return (options = {}) => { - let lang = primaryLang || 'en'; - const history = createHistory(options); - const unsubscribeFromHistory = history.listen(nextLocation => { - lang = getLangFromLocation(nextLocation); - }); - const push = location => history.push(addLangToLocation(location, lang)); - const replace = location => history.replace( - addLangToLocation(location, lang) - ); - return { - ...history, - push, - replace, - unsubscribe() { unsubscribeFromHistory(); } - }; - }; -} diff --git a/common/app/App.jsx b/common/app/App.jsx index f4e17b61f6..7d32cdc6e6 100644 --- a/common/app/App.jsx +++ b/common/app/App.jsx @@ -10,17 +10,19 @@ import { isSignedInSelector } from './redux'; +import { fetchMapUi } from './Map/redux'; + import Flash from './Flash'; import Nav from './Nav'; import Toasts from './Toasts'; import NotFound from './NotFound'; import { mainRouteSelector } from './routes/redux'; -import Challenges from './routes/Challenges'; import Profile from './routes/Profile'; import Settings from './routes/Settings'; const mapDispatchToProps = { appMounted, + fetchMapUi, fetchUser }; @@ -37,6 +39,7 @@ const mapStateToProps = state => { const propTypes = { appMounted: PropTypes.func.isRequired, children: PropTypes.node, + fetchMapUi: PropTypes.func.isRequired, fetchUser: PropTypes.func, isSignedIn: PropTypes.bool, route: PropTypes.string, @@ -44,7 +47,6 @@ const propTypes = { }; const routes = { - challenges: Challenges, profile: Profile, settings: Settings }; @@ -53,6 +55,7 @@ const routes = { export class FreeCodeCamp extends React.Component { componentDidMount() { this.props.appMounted(); + this.props.fetchMapUi(); if (!this.props.isSignedIn) { this.props.fetchUser(); } diff --git a/common/app/Map/Block.jsx b/common/app/Map/Block.jsx deleted file mode 100644 index 1387faa0bd..0000000000 --- a/common/app/Map/Block.jsx +++ /dev/null @@ -1,105 +0,0 @@ -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import FA from 'react-fontawesome'; -import { Panel } from 'react-bootstrap'; - -import ns from './ns.json'; -import Challenges from './Challenges.jsx'; -import { - toggleThisPanel, - makePanelOpenSelector -} from './redux'; -import { fetchNewBlock } from '../redux'; - -import { makeBlockSelector } from '../entities'; - -const mapDispatchToProps = { - fetchNewBlock, - toggleThisPanel -}; -function makeMapStateToProps(_, { dashedName }) { - return createSelector( - makeBlockSelector(dashedName), - makePanelOpenSelector(dashedName), - (block, isOpen) => { - return { - isOpen, - dashedName, - title: block.title, - time: block.time, - challenges: block.challenges || [] - }; - } - ); -} -const propTypes = { - challenges: PropTypes.array, - dashedName: PropTypes.string, - fetchNewBlock: PropTypes.func.isRequired, - isOpen: PropTypes.bool, - time: PropTypes.string, - title: PropTypes.string, - toggleThisPanel: PropTypes.func -}; - -export class Block extends PureComponent { - constructor(...props) { - super(...props); - this.handleSelect = this.handleSelect.bind(this); - } - handleSelect(eventKey, e) { - e.preventDefault(); - this.props.toggleThisPanel(eventKey); - } - - renderHeader(isOpen, title, time, isCompleted) { - return ( -
- - - { title } - - { - time && ({ time }) - } -
- ); - } - - render() { - const { - title, - time, - dashedName, - isOpen, - challenges, - fetchNewBlock - } = this.props; - return ( - fetchNewBlock(dashedName) } - onSelect={ this.handleSelect } - > - { isOpen && } - - ); - } -} - -Block.displayName = 'Block'; -Block.propTypes = propTypes; - -export default connect(makeMapStateToProps, mapDispatchToProps)(Block); diff --git a/common/app/Map/Blocks.jsx b/common/app/Map/Blocks.jsx deleted file mode 100644 index 879a928334..0000000000 --- a/common/app/Map/Blocks.jsx +++ /dev/null @@ -1,39 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; - -import ns from './ns.json'; -import Block from './Block.jsx'; - -const propTypes = { - blocks: PropTypes.array.isRequired -}; - -export default class Blocks extends Component { - shouldComponentUpdate(nextProps) { - return this.props.blocks !== nextProps.blocks; - } - - render() { - const { - blocks - } = this.props; - if (blocks.length <= 0) { - return null; - } - return ( -
- { - blocks.map(dashedName => ( - - )) - } -
- ); - } -} - -Blocks.displayName = 'Blocks'; -Blocks.propTypes = propTypes; diff --git a/common/app/Map/Challenge.jsx b/common/app/Map/Challenge.jsx deleted file mode 100644 index ccc4d18401..0000000000 --- a/common/app/Map/Challenge.jsx +++ /dev/null @@ -1,155 +0,0 @@ -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import classnames from 'classnames'; -import debug from 'debug'; - -import { clickOnChallenge } from './redux'; -import { userSelector } from '../redux'; -import { paramsSelector } from '../Router/redux'; -import { challengeMapSelector } from '../entities'; -import { Link } from '../Router'; -import { onRouteChallenges } from '../routes/Challenges/redux'; - -const propTypes = { - block: PropTypes.string, - challenge: PropTypes.object, - clickOnChallenge: PropTypes.func.isRequired, - dashedName: PropTypes.string, - isComingSoon: PropTypes.bool, - isCompleted: PropTypes.bool, - isDev: PropTypes.bool, - isLocked: PropTypes.bool, - selected: PropTypes.bool, - title: PropTypes.string -}; -const mapDispatchToProps = { clickOnChallenge }; - -function makeMapStateToProps(_, { dashedName }) { - return createSelector( - userSelector, - challengeMapSelector, - paramsSelector, - ( - { challengeMap: userChallengeMap }, - challengeMap, - params - ) => { - const { - id, - title, - block, - isLocked, - isComingSoon - } = challengeMap[dashedName] || {}; - const isCompleted = userChallengeMap ? !!userChallengeMap[id] : false; - const selected = dashedName === params.dashedName; - return { - dashedName, - isCompleted, - title, - block, - isLocked, - isComingSoon, - isDev: debug.enabled('fcc:*'), - selected - }; - } - ); -} - -export class Challenge extends PureComponent { - renderCompleted(isCompleted, isLocked) { - if (isLocked || !isCompleted) { - return null; - } - return completed; - } - - renderComingSoon(isComingSoon) { - if (!isComingSoon) { - return null; - } - return ( - -     - - Coming Soon - - - ); - } - - renderLocked(title, isComingSoon, className) { - return ( -

- { title } - { this.renderComingSoon(isComingSoon) } -

- ); - } - - - render() { - const { - block, - clickOnChallenge, - dashedName, - isComingSoon, - isCompleted, - isDev, - isLocked, - title, - selected - } = this.props; - if (!title) { - return null; - } - const challengeClassName = classnames({ - 'text-primary': true, - 'padded-ionic-icon': true, - 'map-challenge-title': true, - 'ion-checkmark-circled faded': !(isLocked || isComingSoon) && isCompleted, - 'ion-ios-circle-outline': !(isLocked || isComingSoon) && !isCompleted, - 'ion-locked': isLocked || isComingSoon, - disabled: isLocked || (!isDev && isComingSoon), - selectedChallenge: selected - }); - if (isLocked || (!isDev && isComingSoon)) { - return this.renderLocked( - title, - isComingSoon, - challengeClassName - ); - } - return ( -
- - - { title } - { this.renderCompleted(isCompleted, isLocked) } - - -
- ); - } -} - -Challenge.propTypes = propTypes; -Challenge.dispalyName = 'Challenge'; - -export default connect( - makeMapStateToProps, - mapDispatchToProps -)(Challenge); diff --git a/common/app/Map/Challenges.jsx b/common/app/Map/Challenges.jsx deleted file mode 100644 index 975553a48a..0000000000 --- a/common/app/Map/Challenges.jsx +++ /dev/null @@ -1,35 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; - -import Challenge from './Challenge.jsx'; - -const propTypes = { - challenges: PropTypes.array.isRequired -}; - -export default class Challenges extends Component { - shouldComponentUpdate(nextProps) { - return this.props.challenges !== nextProps.challenges; - } - render() { - const { challenges } = this.props; - if (!challenges.length) { - return
No Challenges Found
; - } - return ( -
- { - challenges.map(dashedName => ( - - )) - } -
- ); - } -} - -Challenges.displayName = 'Challenges'; -Challenges.propTypes = propTypes; diff --git a/common/app/Map/Map.jsx b/common/app/Map/Map.jsx deleted file mode 100644 index 6d9ec9e3c8..0000000000 --- a/common/app/Map/Map.jsx +++ /dev/null @@ -1,127 +0,0 @@ -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { Col, Row } from 'react-bootstrap'; - -import ns from './ns.json'; -import { Loader } from '../helperComponents'; -import SuperBlock from './Super-Block.jsx'; -import { currentChallengeSelector, superBlocksSelector } from '../redux'; -import { fetchMapUi } from './redux'; - -const mapStateToProps = state => ({ - currentChallenge: currentChallengeSelector(state), - superBlocks: superBlocksSelector(state) -}); - -const mapDispatchToProps = { fetchMapUi }; -const propTypes = { - currentChallenge: PropTypes.string, - fetchMapUi: PropTypes.func.isRequired, - params: PropTypes.object, - superBlocks: PropTypes.array -}; - -export class ShowMap extends PureComponent { - componentDidMount() { - this.setupMapScroll(); - } - - componentDidUpdate() { - this.setupMapScroll(); - } - - setupMapScroll() { - this.updateMapScrollAttempts = 0; - this.updateMapScroll(); - } - - updateMapScroll() { - const { currentChallenge } = this.props; - const rowNode = this._row; - const challengeNode = rowNode.querySelector( - `[data-challenge="${currentChallenge}"]` - ); - - if ( !challengeNode ) { - this.retryUpdateMapScroll(); - return; - } - - const containerScrollHeight = rowNode.scrollHeight; - const containerHeight = rowNode.clientHeight; - - const offset = 100; - const itemTop = challengeNode.offsetTop; - const itemBottom = itemTop + challengeNode.clientHeight; - - const currentViewBottom = rowNode.scrollTop + containerHeight; - - if ( itemBottom + offset < currentViewBottom ) { - // item is visible with enough offset from bottom => no need to scroll - return; - } - - if ( containerHeight === containerScrollHeight ) { - /* - * During a first run containerNode scrollHeight may be not updated yet. - * In this case containerNode ignores changes of scrollTop property. - * So we have to wait some time before scrollTop can be updated - * */ - this.retryUpdateMapScroll(); - return; - } - - const scrollTop = itemBottom + offset - containerHeight; - rowNode.scrollTop = scrollTop; - } - - retryUpdateMapScroll() { - const maxAttempts = 5; - this.updateMapScrollAttempts++; - - if (this.updateMapScrollAttempts < maxAttempts) { - setTimeout(() => this.updateMapScroll(), 300); - } - } - - renderSuperBlocks() { - const { superBlocks } = this.props; - if (!Array.isArray(superBlocks) || !superBlocks.length) { - return ( -
- -
- ); - } - return superBlocks.map(dashedName => ( - - )); - } - - render() { - return ( -
{ this._row = ref; }}> - - -
- { this.renderSuperBlocks() } -
-
- - -
- ); - } -} - -ShowMap.displayName = 'Map'; -ShowMap.propTypes = propTypes; - -export default connect( - mapStateToProps, - mapDispatchToProps -)(ShowMap); diff --git a/common/app/Map/Super-Block.jsx b/common/app/Map/Super-Block.jsx deleted file mode 100644 index c5ce006263..0000000000 --- a/common/app/Map/Super-Block.jsx +++ /dev/null @@ -1,96 +0,0 @@ -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import FA from 'react-fontawesome'; -import { Panel } from 'react-bootstrap'; - -import ns from './ns.json'; -import Blocks from './Blocks.jsx'; -import { - toggleThisPanel, - - makePanelOpenSelector -} from './redux'; -import { makeSuperBlockSelector } from '../entities'; - -const mapDispatchToProps = { toggleThisPanel }; -// make selectors unique to each component -// see -// reactjs/reselect -// sharing-selectors-with-props-across-multiple-components -function mapStateToProps(_, { dashedName }) { - return createSelector( - makeSuperBlockSelector(dashedName), - makePanelOpenSelector(dashedName), - (superBlock, isOpen) => ({ - isOpen, - dashedName, - title: superBlock.title || dashedName, - blocks: superBlock.blocks || [] - }) - ); -} - -const propTypes = { - blocks: PropTypes.array, - dashedName: PropTypes.string, - isOpen: PropTypes.bool, - title: PropTypes.string, - toggleThisPanel: PropTypes.func -}; - -export class SuperBlock extends PureComponent { - constructor(...props) { - super(...props); - this.handleSelect = this.handleSelect.bind(this); - } - handleSelect(eventKey, e) { - e.preventDefault(); - this.props.toggleThisPanel(eventKey); - } - - renderHeader(isOpen, title, isCompleted) { - return ( -
- - { title } -
- ); - } - - render() { - const { - title, - dashedName, - blocks, - isOpen - } = this.props; - return ( - - - - ); - } -} - -SuperBlock.displayName = 'SuperBlock'; -SuperBlock.propTypes = propTypes; - -export default connect( - mapStateToProps, - mapDispatchToProps -)(SuperBlock); diff --git a/common/app/Map/index.js b/common/app/Map/index.js deleted file mode 100644 index a046dd5d2d..0000000000 --- a/common/app/Map/index.js +++ /dev/null @@ -1 +0,0 @@ -export default from './Map.jsx'; diff --git a/common/app/Map/map.less b/common/app/Map/map.less deleted file mode 100644 index c95767bf79..0000000000 --- a/common/app/Map/map.less +++ /dev/null @@ -1,144 +0,0 @@ -// should be the same as the filename and ./ns.json -@ns: map; - -.@{ns}-container { - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - overflow-x: hidden; - overflow-y: auto; -} - -.@{ns}-accordion { - max-width: 700px; - overflow-y: auto; - width: 100%; - - a:focus { - text-decoration: none; - color:darkgreen; - } - - a:focus:hover { - text-decoration: underline; - color:#001800; - } - - @media (max-width: 720px) { - left: 0; - right: 0; - width: 100%; - top: 195px; - bottom: 0; - // position:absolute; - overflow-x: hidden; - overflow-y: auto; - -webkit-overflow-scrolling: touch; - h2 { - margin:15px 0; - padding:0; - &:first-of-type { - margin-top:0; - } - > a { - padding: 10px 0; - padding-left: 50px; - padding-right: 20px; - font-size: 20px; - } - } - a { - margin: 10px 0; - padding: 0; - > h3 { - clear:both; - font-size:20px; - } - } - } - - .@{ns}-caret { - color: @gray-dark; - text-decoration: none; - // make sure all carats are fixed width - width: 10px; - } -} - - -.@{ns}-accordion-block .@{ns}-accordion-panel-heading { - padding-left: 26px; -} - -.@{ns}-challenge-title, .@{ns}-accordion-panel-heading { - background: @body-bg; - line-height: 26px; - padding: 2px 12px 2px 10px; - width:100%; -} - -.@{ns}-challenge-title { - &::before { - padding-right: 6px; - } - padding-left: 40px; - a { - cursor: pointer; - } - @media (min-width: 721px) { - clear: both; - } -} - -.@{ns}-accordion-panel-heading a { - cursor: pointer; - display: block; -} - -.@{ns}-accordion-panel-collapse { - transition: height 0.001s; -} - -.@{ns}-accordion-panel-title { - @media (min-width: 721px) { - clear: both; - } -} - -.@{ns}-block-time { - color: #555555; - @media (min-width: 721px) { - float: right; - } -} - -.@{ns}-block-description { - margin:0; - margin-top:-10px; - padding:0 15px 23px 30px; -} - - -.night { - .@{ns}-accordion .no-link-underline { - color: @brand-primary; - } - .@{ns}-accordion h2 > a { - background: #666; - } - .@{ns}-accordion a:focus, #noneFound { - color: #ABABAB; - } - .@{ns}-challenge-title, .@{ns}-accordion-panel-heading { - background: @night-body-bg; - color: @night-text-color; - a { - color: @night-text-color; - } - } - .@{ns}-caret { - color: @night-text-color; - } -} diff --git a/common/app/Map/ns.json b/common/app/Map/ns.json deleted file mode 100644 index 6bc66fc09e..0000000000 --- a/common/app/Map/ns.json +++ /dev/null @@ -1 +0,0 @@ -"map" diff --git a/common/app/Map/redux/fetch-map-ui-epic.js b/common/app/Map/redux/fetch-map-ui-epic.js index 37e7cfa09b..9933f1121e 100644 --- a/common/app/Map/redux/fetch-map-ui-epic.js +++ b/common/app/Map/redux/fetch-map-ui-epic.js @@ -3,38 +3,34 @@ import debug from 'debug'; import { types as appTypes, - createErrorObservable, - currentChallengeSelector + createErrorObservable } from '../../redux'; import { types, fetchMapUiComplete } from './'; -import { langSelector } from '../../Router/redux'; import { shapeChallenges } from '../../redux/utils'; const isDev = debug.enabled('fcc:*'); export default function fetchMapUiEpic( actions, - { getState }, + _, { services } ) { - return actions::ofType( + return actions.do(console.log)::ofType( appTypes.appMounted, types.fetchMapUi.start ) .flatMapLatest(() => { - const lang = langSelector(getState()); const options = { - params: { lang }, service: 'map-ui' }; return services.readService$(options) .retry(3) + .do(console.info) .map(({ entities, ...res }) => ({ entities: shapeChallenges( entities, isDev ), - initialNode: currentChallengeSelector(getState()), ...res })) .map(fetchMapUiComplete) diff --git a/common/app/Map/redux/index.js b/common/app/Map/redux/index.js index f68e67c32e..8fdc57c0a7 100644 --- a/common/app/Map/redux/index.js +++ b/common/app/Map/redux/index.js @@ -8,13 +8,14 @@ import { createSelector } from 'reselect'; import { capitalize, noop } from 'lodash'; import * as utils from './utils.js'; -import ns from '../ns.json'; import { createEventMetaCreator } from '../../redux'; import fetchMapUiEpic from './fetch-map-ui-epic'; +const ns = 'map'; + export const epics = [ fetchMapUiEpic ]; export const types = createTypes([ diff --git a/common/app/Nav/LargeNav.jsx b/common/app/Nav/LargeNav.jsx index d0925bc37d..a1127e3bf4 100644 --- a/common/app/Nav/LargeNav.jsx +++ b/common/app/Nav/LargeNav.jsx @@ -2,11 +2,11 @@ import React from 'react'; import Media from 'react-media'; import { Col, Navbar, Row } from 'react-bootstrap'; import FCCSearchBar from 'react-freecodecamp-search'; -import { NavLogo, BinButtons, NavLinks } from './components'; +import { NavLogo, NavLinks } from './components'; import propTypes from './navPropTypes'; -function LargeNav({ clickOnLogo, clickOnMap, shouldShowMapButton, panes }) { +function LargeNav({ clickOnLogo }) { return ( - - - + - +
diff --git a/common/app/Nav/MediumNav.jsx b/common/app/Nav/MediumNav.jsx index 559bf623f1..76c84095b5 100644 --- a/common/app/Nav/MediumNav.jsx +++ b/common/app/Nav/MediumNav.jsx @@ -2,11 +2,11 @@ import React from 'react'; import Media from 'react-media'; import { Navbar, Row } from 'react-bootstrap'; import FCCSearchBar from 'react-freecodecamp-search'; -import { NavLogo, BinButtons, NavLinks } from './components'; +import { NavLogo, NavLinks } from './components'; import propTypes from './navPropTypes'; -function MediumNav({ clickOnLogo, clickOnMap, shouldShowMapButton, panes }) { +function MediumNav({ clickOnLogo }) { return ( matches && typeof window !== 'undefined' && (
- -
- - - -
-
- -
-
+ +
+ + + +
+
+ - +
diff --git a/common/app/Nav/Nav.jsx b/common/app/Nav/Nav.jsx index aaddb015fa..23714fcb0f 100644 --- a/common/app/Nav/Nav.jsx +++ b/common/app/Nav/Nav.jsx @@ -1,67 +1,25 @@ import React from 'react'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; import { Navbar } from 'react-bootstrap'; import LargeNav from './LargeNav.jsx'; import MediumNav from './MediumNav.jsx'; import SmallNav from './SmallNav.jsx'; import { - clickOnLogo, - clickOnMap + clickOnLogo } from './redux'; -import { panesSelector, panesByNameSelector } from '../Panes/redux'; import propTypes from './navPropTypes'; -const mapStateToProps = createSelector( - panesSelector, - panesByNameSelector, - (panes, panesByName) => { - return { - panes: panes.map(({ name, type }) => { - return { - content: name, - action: type, - isHidden: panesByName[name].isHidden - }; - }, {}), - shouldShowMapButton: panes.length === 0 - }; - } -); +const mapStateToProps = () => ({}); function mapDispatchToProps(dispatch) { - const dispatchers = bindActionCreators( + return bindActionCreators( { - clickOnMap: e => { - e.preventDefault(); - return clickOnMap(); - }, - clickOnLogo: e => { - e.preventDefault(); - return clickOnLogo(); - } + clickOnLogo }, dispatch ); - dispatchers.dispatch = dispatch; - return () => dispatchers; -} - -function mergeProps(stateProps, dispatchProps, ownProps) { - const panes = stateProps.panes.map(pane => { - return { - ...pane, - actionCreator: () => dispatchProps.dispatch({ type: pane.action }) - }; - }); - return { - ...ownProps, - ...stateProps, - ...dispatchProps, - panes - }; } const allNavs = [ @@ -72,18 +30,12 @@ const allNavs = [ function FCCNav(props) { const { - panes, - clickOnLogo, - clickOnMap, - shouldShowMapButton + clickOnLogo } = props; const withNavProps = Component => ( ); return ( @@ -104,6 +56,5 @@ FCCNav.propTypes = propTypes; export default connect( mapStateToProps, - mapDispatchToProps, - mergeProps + mapDispatchToProps )(FCCNav); diff --git a/common/app/Nav/SmallNav.jsx b/common/app/Nav/SmallNav.jsx index 50b456e1c3..dfa251437e 100644 --- a/common/app/Nav/SmallNav.jsx +++ b/common/app/Nav/SmallNav.jsx @@ -2,11 +2,11 @@ import React from 'react'; import Media from 'react-media'; import { Navbar, Row } from 'react-bootstrap'; import FCCSearchBar from 'react-freecodecamp-search'; -import { NavLogo, BinButtons, NavLinks } from './components'; +import { NavLogo, NavLinks } from './components'; import propTypes from './navPropTypes'; -function SmallNav({ clickOnLogo, clickOnMap, shouldShowMapButton, panes }) { +function SmallNav({ clickOnLogo }) { return ( matches && typeof window !== 'undefined' && (
- -
- - -
-
- -
-
+ +
+ + +
+
+ - + diff --git a/common/app/Nav/components/NavLinks.jsx b/common/app/Nav/components/NavLinks.jsx index 950d7ed8e8..ac12ba778b 100644 --- a/common/app/Nav/components/NavLinks.jsx +++ b/common/app/Nav/components/NavLinks.jsx @@ -8,10 +8,8 @@ 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, @@ -58,14 +56,12 @@ const navLinkPropType = PropTypes.shape({ const propTypes = { children: PropTypes.any, - clickOnMap: PropTypes.func.isRequired, closeDropdown: PropTypes.func.isRequired, isDropdownOpen: PropTypes.bool, isInNav: PropTypes.bool, isSignedIn: PropTypes.bool, navLinks: PropTypes.arrayOf(navLinkPropType), openDropdown: PropTypes.func.isRequired, - shouldShowMapButton: PropTypes.bool, showLoading: PropTypes.bool }; @@ -125,8 +121,6 @@ class NavLinks extends PureComponent { render() { const { - shouldShowMapButton, - clickOnMap, showLoading, isSignedIn, navLinks, @@ -136,20 +130,6 @@ class NavLinks extends PureComponent { return (