// Copyright 2015, 2016 Ethcore (UK) Ltd. // This file is part of Parity. // Parity 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. // Parity 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 Parity. If not, see . import React, { Component, PropTypes } from 'react'; import { MenuItem } from 'material-ui'; import AutoComplete from '../AutoComplete'; import IdentityIcon from '../../IdentityIcon'; import IdentityName from '../../IdentityName'; import styles from './addressSelect.css'; export default class AddressSelect extends Component { static contextTypes = { api: PropTypes.object.isRequired } static propTypes = { disabled: PropTypes.bool, accounts: PropTypes.object, contacts: PropTypes.object, contracts: PropTypes.object, wallets: PropTypes.object, label: PropTypes.string, hint: PropTypes.string, error: PropTypes.string, value: PropTypes.string, tokens: PropTypes.object, onChange: PropTypes.func.isRequired, allowInput: PropTypes.bool } state = { entries: {}, addresses: [], value: '' } entriesFromProps (props = this.props) { const { accounts, contacts, contracts, wallets } = props; const entries = Object.assign({}, accounts || {}, wallets || {}, contacts || {}, contracts || {}); return entries; } componentWillMount () { const { value } = this.props; const entries = this.entriesFromProps(); const addresses = Object.keys(entries).sort(); this.setState({ entries, addresses, value }); } componentWillReceiveProps (newProps) { if (newProps.value !== this.props.value) { this.setState({ value: newProps.value }); } } render () { const { allowInput, disabled, error, hint, label } = this.props; const { entries, value } = this.state; const searchText = this.getSearchText(); const icon = this.renderIdentityIcon(value); return (
{ icon }
); } renderIdentityIcon (inputValue) { const { error, value, label } = this.props; if (error || !inputValue || value.length !== 42) { return null; } const classes = [ styles.icon ]; if (!label) { classes.push(styles.noLabel); } return ( ); } renderItem = (entry) => { const { address, name } = entry; return { text: name && name.toUpperCase() || address, value: this.renderMenuItem(address), address }; } renderMenuItem (address) { const item = (
); return ( { item } ); } getSearchText () { const entry = this.getEntry(); const { value } = this.state; return entry && entry.name ? entry.name.toUpperCase() : value; } getEntry () { const { entries, value } = this.state; return value ? entries[value] : null; } handleFilter = (searchText, name, item) => { const { address } = item; const entry = this.state.entries[address]; const lowCaseSearch = searchText.toLowerCase(); return [entry.name, entry.address] .some(text => text.toLowerCase().indexOf(lowCaseSearch) !== -1); } onChange = (entry, empty) => { const { allowInput } = this.props; const { value } = this.state; const address = entry && entry.address ? entry.address : ((empty && !allowInput) ? '' : value); this.props.onChange(null, address); } onUpdateInput = (query, choices) => { const { api } = this.context; const address = query.trim(); if (!/^0x/.test(address) && api.util.isAddressValid(`0x${address}`)) { const checksumed = api.util.toChecksumAddress(`0x${address}`); return this.props.onChange(null, checksumed); } this.props.onChange(null, address); }; }