Skip to content
This repository has been archived by the owner on Feb 14, 2022. It is now read-only.

Commit

Permalink
Implement auto-complete for hero select (#94)
Browse files Browse the repository at this point in the history
* Added naive impl of mui-downshift for hero select

* Implemented styling for search to match in toolbar

* Fixed bug when clearing hero autocomplete

* Fixed default selected hero displaying correctly

* Moved generic downshift code to standard AutoComplete component

* Removed a lost console log

* Added noop scrollIntoView to fix AutoComplete scrolling bug

* Filter items if there is a default

* Fixed broken noop test o.O

* Temporary downgrade of nodejs to fix bug in 11.11

See jestjs/jest#8069
  • Loading branch information
stocky37 committed Mar 13, 2019
1 parent 64b991c commit 988ca30
Show file tree
Hide file tree
Showing 10 changed files with 144 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
@@ -1,6 +1,6 @@
language: node_js
node_js:
- "node"
- "11.10.1"
cache:
yarn: true
directories:
Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -9,6 +9,7 @@
"classnames": "^2.2.6",
"lodash.isempty": "^4.4.0",
"lodash.merge": "^4.6.1",
"mui-downshift": "^1.4.1",
"normalizr": "^3.3.0",
"prop-types": "^15.6.2",
"react": "^16.7.0",
Expand Down
4 changes: 0 additions & 4 deletions src/core/components/App/App.test.js
@@ -1,5 +1 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

it('renders without crashing', () => {});
50 changes: 50 additions & 0 deletions src/core/components/AutoComplete/AutoComplete.js
@@ -0,0 +1,50 @@
import React from 'react';
import {Component} from 'react';
import MuiDownshift from 'mui-downshift';

class AutoComplete extends Component {
static defaultProps = {
items: [],
};

constructor(props) {
super(props);
const {defaultSelectedItem} = props;
this.state = {
filteredItems: defaultSelectedItem
? this.filterItems(defaultSelectedItem.label)
: this.props.items,
};
}

filterItems = filter =>
this.props.items.filter(item => item.label.toLowerCase().includes(filter.toLowerCase()));

handleStateChange = changes => {
if (typeof changes.inputValue === 'string') {
this.setState({filteredItems: this.filterItems(changes.inputValue)});
}
if (this.input && this.props.blurOnSelect) {
this.input.blur();
}
};

render() {
const {items, ...props} = this.props;
const {filteredItems} = this.state;
return (
<MuiDownshift
scrollIntoView={() => {}} // workaround for bug causing entire page to scroll
items={filteredItems}
onStateChange={this.handleStateChange}
getListItemKey={index => filteredItems[index].value}
{...props}
inputRef={node => {
this.input = node;
}}
/>
);
}
}

export default AutoComplete;
3 changes: 3 additions & 0 deletions src/core/components/AutoComplete/index.js
@@ -0,0 +1,3 @@
import AutoComplete from './AutoComplete';

export default AutoComplete;
12 changes: 12 additions & 0 deletions src/gear-preview/components/NewHeroSelect/index.js
@@ -0,0 +1,12 @@
import {connect} from 'react-redux';
import AutoComplete from '../../../core/components/AutoComplete';
import getHeroes from '../../../core/selectors/getHeroes';

const mapState = state => ({
items: getHeroes(state).map(hero => ({
label: hero.name,
value: hero._id,
})),
});

export default connect(mapState)(AutoComplete);
34 changes: 26 additions & 8 deletions src/gear-preview/components/Toolbar/Toolbar.js
Expand Up @@ -4,23 +4,32 @@ import withStyles from '@material-ui/core/styles/withStyles';
import MuiToolbar from '@material-ui/core/Toolbar';
import classNames from 'classnames';
import React from 'react';
import HeroSelect from '../../../core/components/HeroSelect';
import AwakeningSelect from '../AwakeningSelect';
import ClearSnapshotButton from '../ClearSnapshotButton';
import LevelSelect from '../LevelSelect';
import NewHeroSelect from '../NewHeroSelect';
import SnapshotButton from '../SnapshotButton';

const style = theme => ({
root: {
background: theme.palette.primary,
zIndex: theme.zIndex.appBar - 1,
},
toolbar: {
display: 'flex',
padding: 0,
},
heroSelect: {
flexGrow: 1,
fontSize: '1.25em',
fontSize: theme.typography.pxToRem(16),
marginRight: theme.spacing.unit * 2,
minHeight: 64,
},
input: {
minHeight: 64,
padding: 0,
fontSize: 'inherit',
paddingLeft: theme.spacing.unit * 2,
},
divider: {
width: 1,
Expand All @@ -36,20 +45,29 @@ const style = theme => ({
},
});

const handleHeroChange = onHeroChange => event => {
const handleHeroChange = onHeroChange => change => {
if (onHeroChange) {
onHeroChange(event.target.value);
onHeroChange(change ? change.value : null);
}
};

const Toolbar = ({className, classes, onHeroChange, hero, totalStats, ...props}) => (
<AppBar className={classNames(classes.root, className)} position="static" {...props}>
<MuiToolbar className={classes.toolbar}>
<HeroSelect
className={classes.heroSelect}
<NewHeroSelect
defaultSelectedItem={hero}
onChange={handleHeroChange(onHeroChange)}
variant="standard"
value={hero}
getInputProps={() => ({
placeholder: 'Select a hero',
disableUnderline: true,
fullWidth: true,
classes: {
input: classes.input,
},
})}
getRootProps={() => ({
className: classes.heroSelect,
})}
/>
<AwakeningSelect align="center" />
<Divider className={classes.divider} />
Expand Down
17 changes: 13 additions & 4 deletions src/gear-preview/components/Toolbar/index.js
Expand Up @@ -2,13 +2,22 @@ import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import selectHero from '../../actions/selectHero';
import getHeroTotalStats from '../../selectors/getHeroTotalStats';
import getSelectedHeroId from '../../selectors/getSelectedHeroId';
import getSelectedHero from '../../selectors/getSelectedHero';
import Toolbar from './Toolbar';

const mapState = state => {
const hero = getSelectedHeroId(state);
const totalStats = hero ? getHeroTotalStats(state) : {};
return {hero, totalStats};
const hero = getSelectedHero(state);
if (!hero) {
return {hero: null, totalStats: {}};
}

return {
hero: {
value: hero.id,
label: hero.name,
},
totalStats: getHeroTotalStats(state),
};
};

const mapDispatch = dispatch => bindActionCreators({onHeroChange: selectHero}, dispatch);
Expand Down
1 change: 0 additions & 1 deletion src/gear-preview/selectors/getCompleteGearSets.js
Expand Up @@ -27,7 +27,6 @@ export default createSelector(
}
});

console.log(completedSets);
return completedSets;
}
);
41 changes: 38 additions & 3 deletions yarn.lock
Expand Up @@ -2287,7 +2287,7 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"

classnames@^2.2.5, classnames@^2.2.6:
classnames@^2.2.3, classnames@^2.2.5, classnames@^2.2.6:
version "2.2.6"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
Expand Down Expand Up @@ -2465,6 +2465,11 @@ compression@^1.5.2:
safe-buffer "5.1.2"
vary "~1.1.2"

compute-scroll-into-view@^1.0.2:
version "1.0.11"
resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.11.tgz#7ff0a57f9aeda6314132d8994cce7aeca794fecf"
integrity sha512-uUnglJowSe0IPmWOdDtrlHXof5CTIJitfJEyITHBW6zDVOGu9Pjk5puaLM73SLcwak0L4hEjO7Td88/a6P5i7A==

concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
Expand Down Expand Up @@ -3169,7 +3174,7 @@ dom-converter@~0.2:
dependencies:
utila "~0.4"

dom-helpers@^3.2.1, dom-helpers@^3.3.1:
"dom-helpers@^2.4.0 || ^3.0.0", dom-helpers@^3.2.1, dom-helpers@^3.3.1:
version "3.4.0"
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8"
integrity sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==
Expand Down Expand Up @@ -3248,6 +3253,14 @@ dotenv@6.0.0:
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.0.0.tgz#24e37c041741c5f4b25324958ebbc34bca965935"
integrity sha512-FlWbnhgjtwD+uNLUGHbMykMOYQaTivdHEmYwAKFjn6GKe/CqY0fNae93ZHTd20snh9ZLr8mTzIL9m0APQ1pjQg==

downshift@^2.2.0:
version "2.2.3"
resolved "https://registry.yarnpkg.com/downshift/-/downshift-2.2.3.tgz#85187568455134e72025fbddd40bb9cf96c55eed"
integrity sha512-SXFgGq5QYT9mxbaSsYdp4Ng0tP87F5z33PD+tZ2kyK0qIBYd1rcPe90+ykCOYqsWHsb/gcrjaAav2Jpa6qNbQg==
dependencies:
compute-scroll-into-view "^1.0.2"
prop-types "^15.6.0"

duplexer@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
Expand Down Expand Up @@ -6118,7 +6131,7 @@ loglevel@^1.4.1:
resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa"
integrity sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=

loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.0, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
Expand Down Expand Up @@ -6452,6 +6465,16 @@ ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==

mui-downshift@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/mui-downshift/-/mui-downshift-1.4.1.tgz#281cf75f8c11c5d201407580fefe39a6c43df5c3"
integrity sha512-8t0ZHbz1BvEiz2j2HPQD1DLHsSWdwAX0z36y+8nDSNXfWbzgKl1oIGNg8lywlARD8B2hXOYWHuv8rKAw4Xp37w==
dependencies:
classnames "^2.2.6"
downshift "^2.2.0"
prop-types "^15.7.2"
react-virtualized "^9.20.1"

multicast-dns-service-types@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901"
Expand Down Expand Up @@ -8272,6 +8295,18 @@ react-transition-group@^2.2.1:
prop-types "^15.6.2"
react-lifecycles-compat "^3.0.4"

react-virtualized@^9.20.1:
version "9.21.0"
resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.21.0.tgz#8267c40ffb48db35b242a36dea85edcf280a6506"
integrity sha512-duKD2HvO33mqld4EtQKm9H9H0p+xce1c++2D5xn59Ma7P8VT7CprfAe5hwjd1OGkyhqzOZiTMlTal7LxjH5yBQ==
dependencies:
babel-runtime "^6.26.0"
classnames "^2.2.3"
dom-helpers "^2.4.0 || ^3.0.0"
loose-envify "^1.3.0"
prop-types "^15.6.0"
react-lifecycles-compat "^3.0.4"

react@^16.7.0:
version "16.8.2"
resolved "https://registry.yarnpkg.com/react/-/react-16.8.2.tgz#83064596feaa98d9c2857c4deae1848b542c9c0c"
Expand Down

0 comments on commit 988ca30

Please sign in to comment.