|
import React, {Component, PropTypes} from 'react'; |
|
import {NavLink, matchPath, withRouter} from 'react-router-dom'; |
|
import {connect} from 'react-redux'; |
|
import {bindActionCreators} from 'redux'; |
|
import routes from 'routes'; |
|
import {store} from 'store'; |
|
import { waitAll } from 'containers/app/sagas'; |
|
|
|
// Actions |
|
import {viewActions as LoaderViewActions} from 'containers/loader/actions'; |
|
|
|
// Selectors |
|
import {selectLoaderIsShown} from 'containers/loader/selectors'; |
|
|
|
/* |
|
* NavigationLink |
|
*/ |
|
class NavigationLink extends Component { |
|
|
|
static propTypes = { |
|
match: PropTypes.object.isRequired, |
|
location: PropTypes.object.isRequired, |
|
history: PropTypes.object.isRequired, |
|
styles: PropTypes.object, |
|
data: PropTypes.object, |
|
// loaderIsShown: PropTypes.bool, |
|
// loaderIsLoading: PropTypes.bool, |
|
}; |
|
|
|
href = null; |
|
|
|
// Watching changes of loader.isShown |
|
// DOESN'T HAPPEN |
|
componentWillReceiveProps(nextProps) { |
|
console.log('this.props.loaderIsShown && this.href', this.props.loaderIsShown, this.href, nextProps.loaderIsShown); |
|
// if (!this.props.loaderIsShown && this.href) this._navigate(); |
|
} |
|
|
|
_navigate() { |
|
// hide current page here if needed |
|
console.log('_navigate', this.href); |
|
|
|
// route now! |
|
// this.props.history.push(this.href); |
|
this.href = null; |
|
} |
|
|
|
_handleClick(e) { |
|
let href = e.currentTarget.href; |
|
|
|
// if same page, do nothing |
|
if (href === window.location.href) return; |
|
|
|
// Test if we have a match |
|
href = href.replace(window.location.origin, ''); |
|
|
|
let route = []; |
|
routes.some(r => { |
|
// use `matchPath` here |
|
const match = matchPath(href, r); |
|
|
|
if (match) route = r; |
|
|
|
return match; |
|
}); |
|
|
|
// Test if not already loaded. If not, fetch data here! |
|
if (route.component.isLoaded && !route.component.isLoaded(store.getState(), href)) { |
|
e.preventDefault(); |
|
e.stopPropagation(); |
|
|
|
// show loader |
|
// change the store, loader.shown > true |
|
this.props.loaderActions.showLoader(); |
|
|
|
const preloaders = [route.fetchData()].reduce((result, saga) => result.concat(saga), []); |
|
|
|
store.runSaga(waitAll(preloaders)).done.then(() => { |
|
|
|
// store href |
|
this.href = href; |
|
|
|
// Hide loader and wait for this._navigate to be called |
|
// change the store at some point, loader.shown > false |
|
this.props.loaderActions.hideLoader(); |
|
|
|
}).catch((e) => { |
|
console.log('NavigationLink:error', href, e.stack); |
|
}); |
|
} |
|
} |
|
|
|
render() { |
|
const {data, styles} = this.props; |
|
|
|
return ( |
|
<NavLink className={styles} to={data.get('path')} onClick={::this._handleClick}>{data.get('label')}</NavLink> |
|
); |
|
} |
|
|
|
} |
|
|
|
const mapStateToProps = (state) => { |
|
return { |
|
loaderIsShown: selectLoaderIsShown(state), |
|
}; |
|
} |
|
|
|
const mapDispatchToProps = (dispatch) => { |
|
return { |
|
loaderActions: bindActionCreators(LoaderViewActions, dispatch) |
|
}; |
|
} |
|
|
|
// Order matters! |
|
NavigationLink = connect(mapStateToProps, mapDispatchToProps) (NavigationLink); |
|
NavigationLink = withRouter(NavigationLink); |
|
|
|
export default NavigationLink; |