From 06b2a04a4259a0bc7dff4004328441d353c296de Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 5 Sep 2017 01:48:52 -0700 Subject: Implement tokens list UI --- ui/app/components/identicon.js | 4 +- ui/app/components/token-cell.js | 23 ++++-- ui/app/components/token-list.js | 101 +++++------------------- ui/app/components/tx-list.js | 37 +++++---- ui/app/components/wallet-view.js | 22 +++++- ui/app/css/itcss/components/index.scss | 2 + ui/app/css/itcss/components/newui-sections.scss | 13 ++- ui/app/css/itcss/components/token-list.scss | 21 +++++ ui/app/css/itcss/components/wallet-balance.scss | 4 +- ui/lib/icon-factory.js | 2 +- 10 files changed, 122 insertions(+), 107 deletions(-) create mode 100644 ui/app/css/itcss/components/token-list.scss diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index 98d5d40ef..71831fe71 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -18,9 +18,11 @@ function IdenticonComponent () { IdenticonComponent.prototype.render = function () { var props = this.props + const { className = '' } = props var diameter = props.diameter || this.defaultDiameter return ( - h('div.identicon', { + h('div', { + className: `${className} identicon`, key: 'identicon-' + this.props.address, style: { display: 'flex', diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index 19d7139bb..a24e4e1ac 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -13,23 +13,34 @@ function TokenCell () { TokenCell.prototype.render = function () { const props = this.props - const { address, symbol, string, network, userAddress } = props + const { + address, + symbol, + string, + network, + // userAddress, + } = props return ( - h('li.token-cell', { + h('div.token-list-item', { style: { cursor: network === '1' ? 'pointer' : 'default' }, - onClick: this.view.bind(this, address, userAddress, network), + // onClick: this.view.bind(this, address, userAddress, network), }, [ h(Identicon, { - diameter: 50, + className: 'token-list-item__identicon', + diameter: 45, address, network, }), - h('h3', `${string || 0} ${symbol}`), + h('h.token-list-item__balance-wrapper', null, [ + h('h3.token-list-item__token-balance', `${string || 0} ${symbol}`), - h('span', { style: { flex: '1 0 auto' } }), + h('div.token-list-item__fiat-amount', { + style: {}, + }, '210 FPO'), + ]), /* h('button', { diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js index 5ea31ae8d..7fe072fac 100644 --- a/ui/app/components/token-list.js +++ b/ui/app/components/token-list.js @@ -4,6 +4,17 @@ const inherits = require('util').inherits const TokenTracker = require('eth-token-tracker') const TokenCell = require('./token-cell.js') const normalizeAddress = require('eth-sig-util').normalize +const connect = require('react-redux').connect +const selectors = require('../selectors') + +function mapStateToProps (state) { + + return { + network: state.metamask.network, + tokens: state.metamask.tokens, + userAddress: selectors.getSelectedAddress(state), + } +} const defaultTokens = [] const contracts = require('eth-contract-metadata') @@ -15,7 +26,8 @@ for (const address in contracts) { } } -module.exports = TokenList +module.exports = connect(mapStateToProps)(TokenList) + inherits(TokenList, Component) function TokenList () { @@ -47,81 +59,7 @@ TokenList.prototype.render = function () { return h(TokenCell, tokenData) }) - return h('.full-flex-height', [ - this.renderTokenStatusBar(), - - h('ol.full-flex-height.flex-column', { - style: { - overflowY: 'auto', - display: 'flex', - flexDirection: 'column', - }, - }, [ - h('style', ` - - li.token-cell { - display: flex; - flex-direction: row; - align-items: center; - padding: 10px; - min-height: 50px; - } - - li.token-cell > h3 { - margin-left: 12px; - } - - li.token-cell:hover { - background: white; - cursor: pointer; - } - - `), - ...tokenViews, - h('.flex-grow'), - ]), - ]) -} - -TokenList.prototype.renderTokenStatusBar = function () { - const { tokens } = this.state - - let msg - if (tokens.length === 1) { - msg = `You own 1 token` - } else if (tokens.length === 1) { - msg = `You own ${tokens.length} tokens` - } else { - msg = `No tokens found` - } - - return h('div', { - style: { - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - minHeight: '70px', - padding: '10px', - }, - }, [ - h('span', msg), - h('button', { - key: 'reveal-account-bar', - onClick: (event) => { - event.preventDefault() - this.props.addToken() - }, - style: { - display: 'flex', - height: '40px', - padding: '10px', - justifyContent: 'center', - alignItems: 'center', - }, - }, [ - 'ADD TOKEN', - ]), - ]) + return h('div', tokenViews) } TokenList.prototype.message = function (body) { @@ -150,6 +88,7 @@ TokenList.prototype.createFreshTokenTracker = function () { if (!global.ethereumProvider) return const { userAddress } = this.props + this.tracker = new TokenTracker({ userAddress, provider: global.ethereumProvider, @@ -188,10 +127,10 @@ TokenList.prototype.componentWillUpdate = function (nextProps) { } TokenList.prototype.updateBalances = function (tokens) { - const heldTokens = tokens.filter(token => { - return token.balance !== '0' && token.string !== '0.000' - }) - this.setState({ tokens: heldTokens, isLoading: false }) + // const heldTokens = tokens.filter(token => { + // return token.balance !== '0' && token.string !== '0.000' + // }) + this.setState({ tokens: tokens, isLoading: false }) } TokenList.prototype.componentWillUnmount = function () { @@ -199,7 +138,7 @@ TokenList.prototype.componentWillUnmount = function () { this.tracker.stop() } -function uniqueMergeTokens (tokensA, tokensB) { +function uniqueMergeTokens (tokensA, tokensB = []) { const uniqueAddresses = [] const result = [] tokensA.concat(tokensB).forEach((token) => { diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index bd7d77c48..b8a18970f 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -40,7 +40,7 @@ TxList.prototype.render = function () { }, [ h('div', { - style: {} + style: {}, }, 'transactions'), ]), @@ -64,45 +64,52 @@ TxList.prototype.renderTransactionListItem = function (transaction) { transactionStatus: transaction.status, transactionAmount: formatBalance(transaction.txParams.value, 6), } - const { address, transactionStatus, transactionAmount, dateString } = props - - return h('div', {}, [ + const { + address = '', + transactionStatus, + transactionAmount, + dateString, + } = props + + return h('div', { + key: transaction.id, + }, [ h('div.flex-column.tx-list-item-wrapper', { - style: {} + style: {}, }, [ h('div.tx-list-date-wrapper', { - style: {} + style: {}, }, [ h('span.tx-list-date', {}, [ dateString, - ]) + ]), ]), h('div.flex-row.tx-list-content-wrapper', { - style: {} + style: {}, }, [ h('div.tx-list-identicon-wrapper', { - style: {} + style: {}, }, [ h(Identicon, { address, diameter: 28, - }) + }), ]), h('div.tx-list-account-and-status-wrapper', {}, [ h('div.tx-list-account-wrapper', { - style: {} + style: {}, }, [ h('span.tx-list-account', {}, [ - `${address.slice(0, 10)}...${address.slice(-4)}` + `${address.slice(0, 10)}...${address.slice(-4)}`, ]), ]), h('div.tx-list-status-wrapper', { - style: {} + style: {}, }, [ h('span.tx-list-status', {}, [ transactionStatus, @@ -111,7 +118,7 @@ TxList.prototype.renderTransactionListItem = function (transaction) { ]), h('div.flex-column.tx-list-details-wrapper', { - style: {} + style: {}, }, [ h('span.tx-list-value', {}, [ @@ -126,7 +133,7 @@ TxList.prototype.renderTransactionListItem = function (transaction) { ]), ]), - contentDivider + contentDivider, ]) } diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 48971a29e..304b5daba 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -6,6 +6,7 @@ const Identicon = require('./identicon') const AccountDropdowns = require('./dropdowns/index.js').AccountDropdowns const actions = require('../actions') const BalanceComponent = require('./balance-component') +const TokenList = require('./token-list') const selectors = require('../selectors') module.exports = connect(mapStateToProps, mapDispatchToProps)(WalletView) @@ -17,6 +18,7 @@ function mapStateToProps (state) { sidebarOpen: state.appState.sidebarOpen, identities: state.metamask.identities, accounts: state.metamask.accounts, + tokens: state.metamask.tokens, selectedAddress: selectors.getSelectedAddress(state), selectedIdentity: selectors.getSelectedIdentity(state), selectedAccount: selectors.getSelectedAccount(state), @@ -35,8 +37,23 @@ function WalletView () { Component.call(this) } +WalletView.prototype.renderTokenBalances = function () { + // const { tokens = [] } = this.props + // return tokens.map(({ address, decimals, symbol }) => ( + // h(BalanceComponent, { + // balanceValue: 0, + // style: {}, + // }) + // )) + return h(TokenList) +} + WalletView.prototype.render = function () { - const { network, responsiveDisplayClassname, identities, selectedAddress, selectedAccount, accounts, selectedIdentity } = this.props + const { + network, responsiveDisplayClassname, identities, + selectedAddress, selectedAccount, accounts, + selectedIdentity, + } = this.props // temporary logs + fake extra wallets console.log('walletview, selectedAccount:', selectedAccount) @@ -134,8 +151,11 @@ WalletView.prototype.render = function () { ]), + ]), + this.renderTokenBalances(), + ]) } diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index 19b8bbc95..952d11ce4 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -23,3 +23,5 @@ @import './transaction-list.scss'; @import './sections.scss'; + +@import './token-list.scss'; diff --git a/ui/app/css/itcss/components/newui-sections.scss b/ui/app/css/itcss/components/newui-sections.scss index f5accca8a..53c0023c3 100644 --- a/ui/app/css/itcss/components/newui-sections.scss +++ b/ui/app/css/itcss/components/newui-sections.scss @@ -6,6 +6,13 @@ $tx-view-bg: $white; $wallet-view-bg: $wild-sand; +html { + + @media screen and (max-width: 575px) { + height: 500px; + } +} + // Main container .main-container { position: absolute; @@ -17,7 +24,7 @@ $wallet-view-bg: $wild-sand; } .main-container::-webkit-scrollbar { - display: none; + display: none; } // tx view @@ -37,6 +44,7 @@ $wallet-view-bg: $wild-sand; @media screen and (min-width: 576px) { overflow-y: scroll; + overflow-x: hidden; } .wallet-view-account-details { @@ -142,7 +150,10 @@ $wallet-view-bg: $wild-sand; .main-container { margin-top: 35px; + height: calc(100% - 34px); width: 100%; + overflow-y: auto; + background-color: $white; } button.btn-clear { diff --git a/ui/app/css/itcss/components/token-list.scss b/ui/app/css/itcss/components/token-list.scss new file mode 100644 index 000000000..dd1d533c7 --- /dev/null +++ b/ui/app/css/itcss/components/token-list.scss @@ -0,0 +1,21 @@ +.token-list-item { + display: flex; + flex-flow: row nowrap; + align-items: center; + padding: 20px 24px; + cursor: pointer; + + &__identicon { + margin-right: 15px; + border: '1px solid #dedede'; + } + + &__token-balance { + font-size: 130%; + } + + &__fiat-amount { + margin-top: .25%; + font-size: 105%; + } +} diff --git a/ui/app/css/itcss/components/wallet-balance.scss b/ui/app/css/itcss/components/wallet-balance.scss index 36f0e1025..113380769 100644 --- a/ui/app/css/itcss/components/wallet-balance.scss +++ b/ui/app/css/itcss/components/wallet-balance.scss @@ -3,7 +3,7 @@ $wallet-balance-breakpoint: 890px; $wallet-balance-breakpoint-range: "screen and (min-width: #{$break-large}) and (max-width: #{$wallet-balance-breakpoint})"; .wallet-balance-wrapper { - flex: 0 0 80px; + flex: 0 0 auto; } .wallet-balance { @@ -12,6 +12,8 @@ $wallet-balance-breakpoint-range: "screen and (min-width: #{$break-large}) and ( flex-direction: row; justify-content: flex-start; align-items: center; + flex: 0 0 auto; + cursor: pointer; .balance-container { display: flex; diff --git a/ui/lib/icon-factory.js b/ui/lib/icon-factory.js index 27a74de66..31498a3a9 100644 --- a/ui/lib/icon-factory.js +++ b/ui/lib/icon-factory.js @@ -53,7 +53,7 @@ function imageElFor (address) { const path = `images/contract/${fileName}` const img = document.createElement('img') img.src = path - img.style.width = '75%' + img.style.width = '100%' return img } -- cgit v1.2.3