From 04da22db0863a9a361a0f414d9cc37bf3bb3a392 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Wed, 20 Sep 2017 22:57:36 -0700 Subject: [PATCH] Add Token UI - hover/select state; fetch token address --- ui/app/add-token.js | 85 +++++++++++++++++----- ui/app/css/itcss/components/add-token.scss | 15 +++- ui/app/css/itcss/settings/variables.scss | 1 + 3 files changed, 82 insertions(+), 19 deletions(-) diff --git a/ui/app/add-token.js b/ui/app/add-token.js index dbba8e4f1..622cf2bc2 100644 --- a/ui/app/add-token.js +++ b/ui/app/add-token.js @@ -1,5 +1,6 @@ const inherits = require('util').inherits const Component = require('react').Component +const classnames = require('classnames') const h = require('react-hyperscript') const connect = require('react-redux').connect const Fuse = require('fuse.js') @@ -7,14 +8,14 @@ const contractMap = require('eth-contract-metadata') const contractList = Object.entries(contractMap).map(([ _, tokenData]) => tokenData) const fuse = new Fuse(contractList, { shouldSort: true, - threshold: 0.3, + threshold: 0.45, location: 0, distance: 100, maxPatternLength: 32, minMatchCharLength: 1, keys: ['address', 'name', 'symbol'], }) -// const actions = require('./actions') +const actions = require('./actions') // const Tooltip = require('./components/tooltip.js') @@ -25,7 +26,7 @@ const EthContract = require('ethjs-contract') const emptyAddr = '0x0000000000000000000000000000000000000000' -module.exports = connect(mapStateToProps)(AddTokenScreen) +module.exports = connect(mapStateToProps, mapDispatchToProps)(AddTokenScreen) function mapStateToProps (state) { return { @@ -33,6 +34,12 @@ function mapStateToProps (state) { } } +function mapDispatchToProps (dispatch) { + return { + goHome: () => dispatch(actions.goHome()), + } +} + inherits(AddTokenScreen, Component) function AddTokenScreen () { this.state = { @@ -40,33 +47,63 @@ function AddTokenScreen () { // address: null, // symbol: 'TOKEN', // decimals: 18, + customAddress: '', + customSymbol: '', + customDecimals: 0, searchQuery: '', isCollapsed: true, + selectedToken: {}, } + this.tokenAddressDidChange = this.tokenAddressDidChange.bind(this) Component.call(this) } +AddTokenScreen.prototype.toggleToken = function (symbol) { + const { selectedToken } = this.state + const { [symbol]: isSelected } = selectedToken + this.setState({ + selectedToken: { + ...selectedToken, + [symbol]: !isSelected, + }, + }) +} + AddTokenScreen.prototype.renderCustomForm = function () { + const { customAddress, customSymbol, customDecimals } = this.state + return !this.state.isCollapsed && ( h('div.add-token__add-custom-form', [ h('div.add-token__add-custom-field', [ h('div.add-token__add-custom-label', 'Token Address'), - h('input.add-token__add-custom-input', { type: 'text' }), + h('input.add-token__add-custom-input', { + type: 'text', + onChange: this.tokenAddressDidChange, + value: customAddress, + }), ]), h('div.add-token__add-custom-field', [ h('div.add-token__add-custom-label', 'Token Symbol'), - h('input.add-token__add-custom-input', { type: 'text', disabled: true }), + h('input.add-token__add-custom-input', { + type: 'text', + value: customSymbol, + disabled: true, + }), ]), h('div.add-token__add-custom-field', [ h('div.add-token__add-custom-label', 'Decimals of Precision'), - h('input.add-token__add-custom-input', { type: 'text', disabled: true }), + h('input.add-token__add-custom-input', { + type: 'number', + value: customDecimals, + disabled: true, + }), ]), ]) ) } AddTokenScreen.prototype.renderTokenList = function () { - const { searchQuery = '' } = this.state + const { searchQuery = '', selectedToken } = this.state const results = searchQuery ? fuse.search(searchQuery) || [] : contractList @@ -74,9 +111,13 @@ AddTokenScreen.prototype.renderTokenList = function () { return Array(6).fill(undefined) .map((_, i) => { const { logo, symbol, name } = results[i] || {} - console.log({ i, logo, symbol, name }) return Boolean(logo || symbol || name) && ( - h('div.add-token__token-wrapper', [ + h('div.add-token__token-wrapper', { + className: classnames('add-token__token-wrapper', { + 'add-token__token-wrapper--selected': selectedToken[symbol], + }), + onClick: () => this.toggleToken(symbol), + }, [ h('div.add-token__token-icon', { style: { backgroundImage: `url(images/contract/${logo})`, @@ -93,6 +134,7 @@ AddTokenScreen.prototype.renderTokenList = function () { AddTokenScreen.prototype.render = function () { const { isCollapsed } = this.state + const { goHome } = this.props return ( h('div.add-token', [ @@ -124,7 +166,9 @@ AddTokenScreen.prototype.render = function () { ]), h('div.add-token__buttons', [ h('button.btn-secondary', 'Next'), - h('button.btn-tertiary', 'Cancel'), + h('button.btn-tertiary', { + onClick: goHome, + }, 'Cancel'), ]), ]) ) @@ -270,12 +314,16 @@ AddTokenScreen.prototype.componentWillMount = function () { this.TokenContract = this.contract(abi) } -AddTokenScreen.prototype.tokenAddressDidChange = function (event) { - const el = event.target - const address = el.value.trim() - if (ethUtil.isValidAddress(address) && address !== emptyAddr) { - this.setState({ address }) - this.attemptToAutoFillTokenParams(address) +AddTokenScreen.prototype.tokenAddressDidChange = function (e) { + const customAddress = e.target.value.trim() + this.setState({ customAddress }) + if (ethUtil.isValidAddress(customAddress) && customAddress !== emptyAddr) { + this.attemptToAutoFillTokenParams(customAddress) + } else { + this.setState({ + customSymbol: '', + customDecimals: 0, + }) } } @@ -330,6 +378,9 @@ AddTokenScreen.prototype.attemptToAutoFillTokenParams = async function (address) const [ symbol, decimals ] = results if (symbol && decimals) { - this.setState({ symbol: symbol[0], decimals: decimals[0].toString() }) + this.setState({ + customSymbol: symbol[0], + customDecimals: decimals[0].toString(), + }) } } diff --git a/ui/app/css/itcss/components/add-token.scss b/ui/app/css/itcss/components/add-token.scss index db1d0dc18..ebfdf7b11 100644 --- a/ui/app/css/itcss/components/add-token.scss +++ b/ui/app/css/itcss/components/add-token.scss @@ -140,11 +140,22 @@ } &__token-wrapper { + transition: 200ms ease-in-out; display: flex; flex-flow: row nowrap; - flex: 0 0 50%; + flex: 0 0 45%; align-items: center; - padding: 24px 0 24px 24px; + padding: 12px; + margin: 2.5%; + box-sizing: border-box; + border-radius: 10px; + cursor: pointer; + border: 2px solid transparent; + + &:hover, + &--selected { + border: 2px solid $malibu-blue; + } } &__token-name { diff --git a/ui/app/css/itcss/settings/variables.scss b/ui/app/css/itcss/settings/variables.scss index 624b301d1..103a7ffe0 100644 --- a/ui/app/css/itcss/settings/variables.scss +++ b/ui/app/css/itcss/settings/variables.scss @@ -38,6 +38,7 @@ $crimson: #e91550; $blue-lagoon: #038789; $purple: #690496; $tulip-tree: #ebb33f; +$malibu-blue: #7ac9fd; /* Z-Indicies