Trigger accounts/contracts search on search input change (#2838)

* Styling Chips in search bar (#2766)

* Styling search chips // Add chip on space/comma/... (#2766)

* Update search on input (#2766)

* Fixing search triggers bugs (#2766)

* removed console logs

* Use props instead of weird CSS selectors for Search Bar

* Add tags on space and commas in EditMeta modal (#2766)

* Fixed empty input in EditMeta modal ; tokens input
This commit is contained in:
Nicolas Gotchac 2016-10-24 16:35:43 +02:00 committed by Gav Wood
parent 24fa2888ab
commit 487da9c9c6
6 changed files with 149 additions and 46 deletions

View File

@ -36,7 +36,7 @@ export default class EditMeta extends Component {
}
state = {
meta: this.props.account.meta,
meta: Object.assign({}, this.props.account.meta),
metaErrors: {},
name: this.props.account.name,
nameError: null
@ -102,20 +102,55 @@ export default class EditMeta extends Component {
renderTags () {
const { meta } = this.state;
const { tags } = meta || [];
const onChange = (chips) => this.onMetaChange('tags', chips);
return (
<ChipInput
defaultValue={ tags }
onChange={ onChange }
ref='tagsInput'
value={ tags }
onRequestAdd={ this.onAddTag }
onRequestDelete={ this.onDeleteTag }
floatingLabelText='(optional) tags'
hintText='press <Enter> to add a tag'
onUpdateInput={ this.onTagsInputChange }
floatingLabelFixed
fullWidth
/>
);
}
onAddTag = (tag) => {
const { meta } = this.state;
const { tags } = meta || [];
this.onMetaChange('tags', [].concat(tags, tag));
}
onDeleteTag = (tag) => {
const { meta } = this.state;
const { tags } = meta || [];
const newTags = tags
.filter(t => t !== tag);
this.onMetaChange('tags', newTags);
}
onTagsInputChange = (value) => {
const { meta } = this.state;
const { tags } = meta || [];
const tokens = value.split(/[\s,;]+/);
const newTokens = tokens
.slice(0, -1)
.filter(t => t.length > 0);
const inputValue = tokens.slice(-1)[0].trim();
this.onMetaChange('tags', [].concat(tags, newTokens));
this.refs.tagsInput.setState({ inputValue });
}
onNameChange = (name) => {
this.setState(validateName(name));
}

View File

@ -41,3 +41,11 @@
width: 0;
height: 0;
}
.chip > svg {
width: 1.2rem !important;
height: 1.2rem !important;
margin: initial !important;
margin-right: 4px !important;
padding: 4px 0 !important;
}

View File

@ -15,6 +15,8 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import React, { Component, PropTypes } from 'react';
import { Chip } from 'material-ui';
import { blue300 } from 'material-ui/styles/colors';
// import ChipInput from 'material-ui-chip-input';
import ChipInput from 'material-ui-chip-input/src/ChipInput';
import ActionSearch from 'material-ui/svg-icons/action/search';
@ -43,6 +45,10 @@ export default class ActionbarSearch extends Component {
if (tokens.length > 0 && this.props.tokens.length === 0) {
this.handleOpenSearch(true, true);
}
if (tokens.length !== this.props.tokens.length) {
this.handleSearchChange(tokens);
}
}
componentWillUnmount () {
@ -71,16 +77,26 @@ export default class ActionbarSearch extends Component {
<ChipInput
clearOnBlur={ false }
className={ styles.input }
chipRenderer={ this.chipRenderer }
hintText='Enter search input...'
hintStyle={ {
transition: 'none'
} }
ref='searchInput'
value={ tokens }
onBlur={ this.handleSearchBlur }
onRequestAdd={ this.handleTokenAdd }
onRequestDelete={ this.handleTokenDelete }
onUpdateInput={ this.handleInputChange } />
onUpdateInput={ this.handleInputChange }
hintStyle={ {
bottom: 16,
left: 2,
transition: 'none'
} }
inputStyle={ {
marginBottom: 18
} }
textFieldStyle={ {
height: 42
} }
/>
</div>
<Button
@ -92,42 +108,83 @@ export default class ActionbarSearch extends Component {
);
}
chipRenderer = (state, key) => {
const { value, isFocused, isDisabled, handleClick, handleRequestDelete } = state;
return (
<Chip
key={ key }
className={ styles.chip }
style={ {
margin: '8px 8px 0 0',
float: 'left',
pointerEvents: isDisabled ? 'none' : undefined,
alignItems: 'center'
} }
labelStyle={ {
paddingRight: 6,
fontSize: '0.9rem',
lineHeight: 'initial'
} }
backgroundColor={ isFocused ? blue300 : 'rgba(0, 0, 0, 0.73)' }
onTouchTap={ handleClick }
onRequestDelete={ handleRequestDelete }
>
{ value }
</Chip>
);
}
handleTokenAdd = (value) => {
const { tokens } = this.props;
const newSearchValues = uniq([].concat(tokens, value));
const newSearchTokens = uniq([].concat(tokens, value));
this.setState({
inputValue: ''
});
this.handleSearchChange(newSearchValues);
this.handleSearchChange(newSearchTokens);
}
handleTokenDelete = (value) => {
const { tokens } = this.props;
const newSearchValues = []
const newSearchTokens = []
.concat(tokens)
.filter(v => v !== value);
this.setState({
inputValue: ''
});
this.handleSearchChange(newSearchValues);
this.handleSearchChange(newSearchTokens);
this.refs.searchInput.focus();
}
handleInputChange = (value) => {
this.setState({ inputValue: value });
const splitTokens = value.split(/[\s,;]/);
const inputValue = (splitTokens.length <= 1)
? value
: splitTokens.slice(-1)[0].trim();
this.refs.searchInput.setState({ inputValue });
this.setState({ inputValue }, () => {
if (splitTokens.length > 1) {
const tokensToAdd = splitTokens.slice(0, -1);
tokensToAdd.forEach(token => this.handleTokenAdd(token));
} else {
this.handleSearchChange();
}
});
}
handleSearchChange = (searchValues) => {
const { onChange } = this.props;
const newSearchValues = searchValues.filter(v => v.length > 0);
handleSearchChange = (searchTokens) => {
const { onChange, tokens } = this.props;
const { inputValue } = this.state;
onChange(newSearchValues);
const newSearchTokens = []
.concat(searchTokens || tokens)
.filter(v => v.length > 0);
const newSearchValues = []
.concat(searchTokens || tokens, inputValue)
.filter(v => v.length > 0);
onChange(newSearchTokens, newSearchValues);
}
handleSearchClick = () => {

View File

@ -41,7 +41,8 @@ class Accounts extends Component {
addressBook: false,
newDialog: false,
sortOrder: '',
searchValues: []
searchValues: [],
searchTokens: []
}
render () {
@ -69,14 +70,14 @@ class Accounts extends Component {
}
renderSearchButton () {
const onChange = (searchValues) => {
this.setState({ searchValues });
const onChange = (searchTokens, searchValues) => {
this.setState({ searchTokens, searchValues });
};
return (
<ActionbarSearch
key='searchAccount'
tokens={ this.state.searchValues }
tokens={ this.state.searchTokens }
onChange={ onChange } />
);
}
@ -136,9 +137,9 @@ class Accounts extends Component {
}
onAddSearchToken = (token) => {
const { searchValues } = this.state;
const newSearchValues = uniq([].concat(searchValues, token));
this.setState({ searchValues: newSearchValues });
const { searchTokens } = this.state;
const newSearchTokens = uniq([].concat(searchTokens, token));
this.setState({ searchTokens: newSearchTokens });
}
onNewAccountClick = () => {

View File

@ -40,7 +40,8 @@ class Addresses extends Component {
state = {
showAdd: false,
sortOrder: '',
searchValues: []
searchValues: [],
searchTokens: []
}
render () {
@ -79,14 +80,14 @@ class Addresses extends Component {
}
renderSearchButton () {
const onChange = (searchValues) => {
this.setState({ searchValues });
const onChange = (searchTokens, searchValues) => {
this.setState({ searchTokens, searchValues });
};
return (
<ActionbarSearch
key='searchAddress'
tokens={ this.state.searchValues }
tokens={ this.state.searchTokens }
onChange={ onChange } />
);
}
@ -127,9 +128,9 @@ class Addresses extends Component {
}
onAddSearchToken = (token) => {
const { searchValues } = this.state;
const newSearchValues = uniq([].concat(searchValues, token));
this.setState({ searchValues: newSearchValues });
const { searchTokens } = this.state;
const newSearchTokens = uniq([].concat(searchTokens, token));
this.setState({ searchTokens: newSearchTokens });
}
onOpenAdd = () => {

View File

@ -43,7 +43,8 @@ class Contracts extends Component {
addContract: false,
deployContract: false,
sortOrder: '',
searchValues: []
searchValues: [],
searchTokens: []
}
render () {
@ -84,14 +85,14 @@ class Contracts extends Component {
}
renderSearchButton () {
const onChange = (searchValues) => {
this.setState({ searchValues });
const onChange = (searchTokens, searchValues) => {
this.setState({ searchTokens, searchValues });
};
return (
<ActionbarSearch
key='searchContract'
tokens={ this.state.searchValues }
tokens={ this.state.searchTokens }
onChange={ onChange } />
);
}
@ -152,9 +153,9 @@ class Contracts extends Component {
}
onAddSearchToken = (token) => {
const { searchValues } = this.state;
const newSearchValues = uniq([].concat(searchValues, token));
this.setState({ searchValues: newSearchValues });
const { searchTokens } = this.state;
const newSearchTokens = uniq([].concat(searchTokens, token));
this.setState({ searchTokens: newSearchTokens });
}
onDeployContractClose = () => {