diff options
| author | Noah Loomans <noahloomans@gmail.com> | 2018-06-28 16:08:57 +0200 | 
|---|---|---|
| committer | Noah Loomans <noahloomans@gmail.com> | 2018-06-28 16:08:57 +0200 | 
| commit | 823aa5ad43126747cb071a0c347b200cc84df714 (patch) | |
| tree | 5705a3dfc8cc3a884d17cd177dc2515cf9e37fd6 | |
| parent | 41620ceb096a4c3d94bb83cf9a56077939d89a2c (diff) | |
Split search
| -rw-r--r-- | src/client/react/components/container/Search.js | 141 | ||||
| -rw-r--r-- | src/client/react/components/presentational/Search.js | 158 | ||||
| -rw-r--r-- | src/client/react/components/presentational/Search.scss (renamed from src/client/react/components/container/Search.scss) | 0 | 
3 files changed, 161 insertions, 138 deletions
| diff --git a/src/client/react/components/container/Search.js b/src/client/react/components/container/Search.js index 3e599e7..8308d67 100644 --- a/src/client/react/components/container/Search.js +++ b/src/client/react/components/container/Search.js @@ -18,145 +18,10 @@   *   */ -import React from 'react'; -import PropTypes from 'prop-types';  import { connect } from 'react-redux'; -import classnames from 'classnames';  import { withRouter } from 'react-router-dom'; - -import SearchIcon from 'react-icons/lib/md/search'; - -import { userFromMatch } from '../../lib/url'; -import { setUser as setUserAction } from '../../store/actions'; - -import users from '../../users'; -import Menu from './Menu'; -import Results from './Results'; -import IconFromUserType from '../presentational/IconFromUserType'; - -import './Search.scss'; - -class Search extends React.Component { -  static propTypes = { -    selectedResult: PropTypes.string, -    searchText: PropTypes.string.isRequired, -    match: PropTypes.object.isRequired, -    setUser: PropTypes.func.isRequired, -    onInputChange: PropTypes.func.isRequired, -    changeSelectedResult: PropTypes.func.isRequired, -  }; - -  static defaultProps = { -    selectedResult: null, -  }; - -  constructor(props) { -    super(props); - -    this.state = { -      hasFocus: false, -    }; - -    this.onFocus = this.onFocus.bind(this); -    this.onBlur = this.onBlur.bind(this); -    this.onKeyDown = this.onKeyDown.bind(this); -  } - -  onFocus() { -    this.setState({ -      hasFocus: true, -    }); -  } - -  onBlur() { -    this.setState({ -      hasFocus: false, -    }); -  } - -  onKeyDown(event) { -    const { -      selectedResult, -      match, -      setUser, -      changeSelectedResult, -    } = this.props; - -    const urlUser = userFromMatch(match); - -    switch (event.key) { -      case 'ArrowUp': -        event.preventDefault(); -        changeSelectedResult(-1); -        break; - -      case 'ArrowDown': -        event.preventDefault(); -        changeSelectedResult(+1); -        break; - -      case 'Escape': -        event.preventDefault(); -        setUser(urlUser); -        break; - -      case 'Enter': -        event.preventDefault(); -        if (selectedResult) { -          setUser(selectedResult); -        } -        break; - -      default: -        // Do nothing -    } -  } - -  render() { -    const { -      searchText, -      match, -      onInputChange, -    } = this.props; - -    const { -      hasFocus, -    } = this.state; - -    const urlUser = userFromMatch(match); - -    const isExactMatch = ( -      urlUser != null && searchText === users.byId[urlUser].value -    ); - -    return ( -      <div className="Search"> -        <div className={classnames('overflow', { hasFocus })}> -          <div className="inputWrapper"> -            <div className="iconWrapper"> -              <IconFromUserType -                userType={isExactMatch ? users.byId[urlUser].type : null} -                defaultIcon={<SearchIcon />} -              /> -            </div> -            <input -              id="searchInput" -              onChange={event => onInputChange(event.target.value)} -              onKeyDown={this.onKeyDown} -              value={searchText} -              placeholder="Zoeken" -              onFocus={this.onFocus} -              onBlur={this.onBlur} -              autoComplete="off" -            /> -            <Menu /> -          </div> -          <Results /> -        </div> -      </div> -    ); -  } -} +import Search from '../presentational/Search'; +import { setUser } from '../../store/actions';  const mapStateToProps = state => ({    results: state.search.results, @@ -165,7 +30,7 @@ const mapStateToProps = state => ({  });  const mapDispatchToProps = dispatch => ({ -  setUser: user => dispatch(setUserAction(user)), +  setUser: user => dispatch(setUser(user)),    onInputChange: searchText => dispatch({      type: 'SEARCH/INPUT_CHANGE',      searchText, diff --git a/src/client/react/components/presentational/Search.js b/src/client/react/components/presentational/Search.js new file mode 100644 index 0000000..8c90efb --- /dev/null +++ b/src/client/react/components/presentational/Search.js @@ -0,0 +1,158 @@ +/** + * Copyright (C) 2018 Noah Loomans + * + * This file is part of rooster.hetmml.nl. + * + * rooster.hetmml.nl is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * rooster.hetmml.nl is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with rooster.hetmml.nl.  If not, see <http://www.gnu.org/licenses/>. + * + */ + +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; + +import SearchIcon from 'react-icons/lib/md/search'; + +import { userFromMatch } from '../../lib/url'; + +import users from '../../users'; +import Menu from '../container/Menu'; +import Results from '../container/Results'; +import IconFromUserType from './IconFromUserType'; + +import './Search.scss'; + +class Search extends React.Component { +  static propTypes = { +    selectedResult: PropTypes.string, +    searchText: PropTypes.string.isRequired, +    match: PropTypes.object.isRequired, +    setUser: PropTypes.func.isRequired, +    onInputChange: PropTypes.func.isRequired, +    changeSelectedResult: PropTypes.func.isRequired, +  }; + +  static defaultProps = { +    selectedResult: null, +  }; + +  constructor(props) { +    super(props); + +    this.state = { +      hasFocus: false, +    }; + +    this.onFocus = this.onFocus.bind(this); +    this.onBlur = this.onBlur.bind(this); +    this.onKeyDown = this.onKeyDown.bind(this); +  } + +  onFocus() { +    this.setState({ +      hasFocus: true, +    }); +  } + +  onBlur() { +    this.setState({ +      hasFocus: false, +    }); +  } + +  onKeyDown(event) { +    const { +      selectedResult, +      match, +      setUser, +      changeSelectedResult, +    } = this.props; + +    const urlUser = userFromMatch(match); + +    switch (event.key) { +      case 'ArrowUp': +        event.preventDefault(); +        changeSelectedResult(-1); +        break; + +      case 'ArrowDown': +        event.preventDefault(); +        changeSelectedResult(+1); +        break; + +      case 'Escape': +        event.preventDefault(); +        setUser(urlUser); +        break; + +      case 'Enter': +        event.preventDefault(); +        if (selectedResult) { +          setUser(selectedResult); +        } +        break; + +      default: +        // Do nothing +    } +  } + +  render() { +    const { +      searchText, +      match, +      onInputChange, +    } = this.props; + +    const { +      hasFocus, +    } = this.state; + +    const urlUser = userFromMatch(match); + +    const isExactMatch = ( +      urlUser != null && searchText === users.byId[urlUser].value +    ); + +    return ( +      <div className="Search"> +        <div className={classnames('overflow', { hasFocus })}> +          <div className="inputWrapper"> +            <div className="iconWrapper"> +              <IconFromUserType +                userType={isExactMatch ? users.byId[urlUser].type : null} +                defaultIcon={<SearchIcon />} +              /> +            </div> +            <input +              id="searchInput" +              onChange={event => onInputChange(event.target.value)} +              onKeyDown={this.onKeyDown} +              value={searchText} +              placeholder="Zoeken" +              onFocus={this.onFocus} +              onBlur={this.onBlur} +              autoComplete="off" +            /> +            <Menu /> +          </div> +          <Results /> +        </div> +      </div> +    ); +  } +} + +export default Search; diff --git a/src/client/react/components/container/Search.scss b/src/client/react/components/presentational/Search.scss index ef629c2..ef629c2 100644 --- a/src/client/react/components/container/Search.scss +++ b/src/client/react/components/presentational/Search.scss | 
