From 30376908301dae90d40532210d382c8edc088ac6 Mon Sep 17 00:00:00 2001 From: Noah Loomans Date: Fri, 2 Feb 2018 15:52:33 +0100 Subject: Get user and week from context --- src/client/react/components/container/Results.js | 76 ++++++++++++---------- src/client/react/components/container/Search.js | 26 +++++--- src/client/react/components/container/View.js | 18 +++-- .../react/components/container/WeekSelector.js | 17 +++-- src/client/react/components/page/User.js | 22 ++----- src/client/react/lib/url.js | 24 +++++++ 6 files changed, 115 insertions(+), 68 deletions(-) create mode 100644 src/client/react/lib/url.js diff --git a/src/client/react/components/container/Results.js b/src/client/react/components/container/Results.js index c329c3c..0f70aa6 100644 --- a/src/client/react/components/container/Results.js +++ b/src/client/react/components/container/Results.js @@ -1,52 +1,63 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; import classnames from 'classnames'; +import { connect } from 'react-redux'; import { withRouter } from 'react-router-dom'; -import Result from '../presentational/Result'; + import { setUser } from '../../actions/search'; +import { userFromMatch } from '../../lib/url'; +import Result from '../presentational/Result'; const Results = ({ results, isExactMatch, - urlUser, selectedResult, + match, history, dispatch, -}) => ( -
0, - })} - style={{ - minHeight: isExactMatch ? 0 : results.length * 54, - }} - > - {!isExactMatch && results.map(userId => ( - { - if (userId === urlUser) { - // EDGE CASE: The user is set if the user changes, but it doesn't - // change if the result is already the one we are viewing. - // Therefor, we need to dispatch the SET_USER command manually. - dispatch(setUser(urlUser)); - } else { - history.push(`/${userId}`); - } - }} - /> - ))} -
-); +}) => { + const user = userFromMatch(match); + + return ( +
0, + })} + style={{ + minHeight: isExactMatch ? 0 : results.length * 54, + }} + > + {!isExactMatch && results.map(userId => ( + { + if (userId === user) { + // EDGE CASE: The user is set if the user changes, but it doesn't + // change if the result is already the one we are viewing. + // Therefor, we need to dispatch the SET_USER command manually. + dispatch(setUser(user)); + } else { + history.push(`/${userId}`); + } + }} + /> + ))} +
+ ); +}; Results.propTypes = { results: PropTypes.arrayOf(PropTypes.string).isRequired, isExactMatch: PropTypes.bool.isRequired, - urlUser: PropTypes.string, selectedResult: PropTypes.string, + match: PropTypes.shape({ + params: PropTypes.shape({ + type: PropTypes.string, + value: PropTypes.string, + }).isRequired, + }).isRequired, history: PropTypes.shape({ push: PropTypes.func.isRequired, }).isRequired, @@ -54,7 +65,6 @@ Results.propTypes = { }; Results.defaultProps = { - urlUser: null, selectedResult: null, }; diff --git a/src/client/react/components/container/Search.js b/src/client/react/components/container/Search.js index ad6f7f1..4f3c6ee 100644 --- a/src/client/react/components/container/Search.js +++ b/src/client/react/components/container/Search.js @@ -6,6 +6,7 @@ import { withRouter } from 'react-router-dom'; import SearchIcon from 'react-icons/lib/md/search'; +import { userFromMatch } from '../../lib/url'; import { setUser, inputChange, changeSelectedResult } from '../../actions/search'; import users from '../../users'; @@ -26,12 +27,14 @@ class Search extends React.Component { } componentDidMount() { - this.props.dispatch(setUser(this.props.urlUser)); + const urlUser = userFromMatch(this.props.match); + this.props.dispatch(setUser(urlUser)); } componentWillReceiveProps(nextProps) { - if (nextProps.urlUser !== this.props.urlUser) { - this.props.dispatch(setUser(nextProps.urlUser)); + if (nextProps.match !== this.props.match) { + const urlUser = userFromMatch(nextProps.match); + this.props.dispatch(setUser(urlUser)); } } @@ -59,12 +62,13 @@ class Search extends React.Component { break; case 'Enter': { const result = this.props.selectedResult || this.props.results[0]; + const urlUser = userFromMatch(this.props.match); - if (result === this.props.urlUser) { + if (result === urlUser) { // EDGE CASE: The user is set if the user changes, but it doesn't // change if the result is already the one we are viewing. // Therefor, we need to dispatch the SET_USER command manually. - this.props.dispatch(setUser(this.props.urlUser)); + this.props.dispatch(setUser(urlUser)); } else if (result) { this.props.history.push(`/${result}`); } @@ -109,7 +113,7 @@ class Search extends React.Component { autoComplete="off" /> - + ); @@ -119,18 +123,22 @@ class Search extends React.Component { Search.propTypes = { results: PropTypes.arrayOf(PropTypes.string).isRequired, selectedResult: PropTypes.string, - urlUser: PropTypes.string, isExactMatch: PropTypes.bool.isRequired, searchText: PropTypes.string.isRequired, - dispatch: PropTypes.func.isRequired, + match: PropTypes.shape({ + params: PropTypes.shape({ + type: PropTypes.string, + value: PropTypes.string, + }).isRequired, + }).isRequired, history: PropTypes.shape({ push: PropTypes.func.isRequired, }).isRequired, + dispatch: PropTypes.func.isRequired, }; Search.defaultProps = { selectedResult: null, - urlUser: null, }; const mapStateToProps = state => ({ diff --git a/src/client/react/components/container/View.js b/src/client/react/components/container/View.js index 4f16100..052173f 100644 --- a/src/client/react/components/container/View.js +++ b/src/client/react/components/container/View.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { withRouter } from 'react-router-dom'; +import { userFromMatch, weekFromLocation } from '../../lib/url'; import { fetchSchedule } from '../../actions/view'; import extractSchedule from '../../lib/extractSchedule'; @@ -11,10 +12,12 @@ import Loading from '../presentational/Loading'; const View = ({ schedules, - user, - week, + match, + location, dispatch, }) => { + const user = userFromMatch(match); + const week = weekFromLocation(location); const schedule = extractSchedule(schedules, user, week); switch (schedule.state) { @@ -35,8 +38,15 @@ View.propTypes = { state: PropTypes.string.isRequired, htmlStr: PropTypes.string, }))).isRequired, - user: PropTypes.string.isRequired, - week: PropTypes.number.isRequired, + match: PropTypes.shape({ + params: PropTypes.shape({ + type: PropTypes.string.isRequired, + value: PropTypes.string.isRequired, + }).isRequired, + }).isRequired, + location: PropTypes.shape({ + search: PropTypes.string.isRequired, + }).isRequired, dispatch: PropTypes.func.isRequired, }; diff --git a/src/client/react/components/container/WeekSelector.js b/src/client/react/components/container/WeekSelector.js index d5ba752..a7ffa3a 100644 --- a/src/client/react/components/container/WeekSelector.js +++ b/src/client/react/components/container/WeekSelector.js @@ -8,10 +8,13 @@ import ArrowBackIcon from 'react-icons/lib/md/arrow-back'; import ArrowForwardIcon from 'react-icons/lib/md/arrow-forward'; import purifyWeek from '../../lib/purifyWeek'; +import { weekFromLocation } from '../../lib/url'; + +const WeekSelector = ({ location, history }) => { + const week = weekFromLocation(location); -const WeekSelector = ({ urlWeek, location, history }) => { const updateWeek = (change) => { - const newWeek = purifyWeek(urlWeek + change); + const newWeek = purifyWeek(week + change); const isCurrentWeek = moment().week() === newWeek; const query = queryString.stringify({ @@ -23,19 +26,19 @@ const WeekSelector = ({ urlWeek, location, history }) => { return (
-
Week {urlWeek}
+
Week {week}
); }; WeekSelector.propTypes = { - urlWeek: PropTypes.number.isRequired, - history: PropTypes.shape({ - push: PropTypes.func.isRequired, - }).isRequired, location: PropTypes.shape({ pathname: PropTypes.string.isRequired, + search: PropTypes.string.isRequired, + }).isRequired, + history: PropTypes.shape({ + push: PropTypes.func.isRequired, }).isRequired, }; diff --git a/src/client/react/components/page/User.js b/src/client/react/components/page/User.js index 0c79a8b..1b7e1ce 100644 --- a/src/client/react/components/page/User.js +++ b/src/client/react/components/page/User.js @@ -1,20 +1,15 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Redirect } from 'react-router-dom'; -import queryString from 'query-string'; -import moment from 'moment'; -import purifyWeek from '../../lib/purifyWeek'; import Search from '../container/Search'; import View from '../container/View'; -import users from '../../users'; +import { userFromMatch } from '../../lib/url'; import WeekSelector from '../container/WeekSelector'; -const UserPage = ({ match, location }) => { - const user = `${match.params.type}/${match.params.value}`; - const weekStr = queryString.parse(location.search).week; - const week = purifyWeek(weekStr ? parseInt(weekStr, 10) : moment().week()); +const UserPage = ({ match }) => { + const user = userFromMatch(match); - if (!users.allIds.includes(user)) { + if (!user) { // Invalid user, redirect to index. return ; } @@ -23,15 +18,15 @@ const UserPage = ({ match, location }) => {
- +
- +
- +
); }; @@ -43,9 +38,6 @@ UserPage.propTypes = { value: PropTypes.string.isRequired, }).isRequired, }).isRequired, - location: PropTypes.shape({ - search: PropTypes.string.isRequired, - }).isRequired, }; export default UserPage; diff --git a/src/client/react/lib/url.js b/src/client/react/lib/url.js new file mode 100644 index 0000000..3b7f6b4 --- /dev/null +++ b/src/client/react/lib/url.js @@ -0,0 +1,24 @@ +import moment from 'moment'; +import queryString from 'query-string'; +import users from '../users'; +import purifyWeek from './purifyWeek'; + +export function userFromMatch(match) { + const user = `${match.params.type}/${match.params.value}`; + + if (!users.allIds.includes(user)) { + return null; + } + + return user; +} + +export function weekFromLocation(location) { + const weekStr = queryString.parse(location.search).week; + + if (!weekStr) { + return moment().week(); + } + + return purifyWeek(parseInt(weekStr, 10)); +} -- cgit v1.1