From 2a5f2c7f4041006daf5bda4d51117b4fe9544e98 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sat, 29 Jul 2017 17:38:29 -0700 Subject: Add responsive container; add send token copy --- ui/app/components/ens-input.js | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'ui/app/components') diff --git a/ui/app/components/ens-input.js b/ui/app/components/ens-input.js index 3a33ebf74..93c07599d 100644 --- a/ui/app/components/ens-input.js +++ b/ui/app/components/ens-input.js @@ -44,6 +44,13 @@ EnsInput.prototype.render = function () { return h('div', { style: { width: '100%' }, }, [ + h('span', { + style: { + textAlign: 'left', + } + }, [ + 'To:' + ]), h('input.large-input', opts), // The address book functionality. h('datalist#addresses', -- cgit v1.2.3 From 35ff4c195c4ff91a90b7572f07060b0213898f22 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sat, 29 Jul 2017 20:55:55 -0700 Subject: [WIP] Isolate form logic from rest of confirmation UI --- ui/app/components/pending-tx.js | 49 +++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 22 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index 5324ccd64..2414a9759 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -75,11 +75,8 @@ PendingTx.prototype.render = function () { key: txMeta.id, }, [ - h('form#pending-tx-form', { - onSubmit: this.onSubmit.bind(this), - + h('div', { }, [ - // tx info h('div', [ @@ -305,24 +302,32 @@ PendingTx.prototype.render = function () { }, 'Buy Ether') : null, - h('button', { - onClick: (event) => { - this.resetGasFields() - event.preventDefault() - }, - }, 'Reset'), - - // Accept Button - h('input.confirm.btn-green', { - type: 'submit', - value: 'SUBMIT', - style: { marginLeft: '10px' }, - disabled: insufficientBalance || !this.state.valid || !isValidAddress || this.state.submitting, - }), - - h('button.cancel.btn-red', { - onClick: props.cancelTransaction, - }, 'Reject'), + + h('form#pending-tx-form', { + onSubmit: this.onSubmit.bind(this), + }, [ + // Reset Button + h('button', { + onClick: (event) => { + this.resetGasFields() + event.preventDefault() + }, + }, 'Reset'), + + // Accept Button + h('input.confirm.btn-green', { + type: 'submit', + value: 'SUBMIT', + style: { marginLeft: '10px' }, + disabled: insufficientBalance || !this.state.valid || !isValidAddress || this.state.submitting, + }), + + // Cancel Button + h('button.cancel.btn-red', { + onClick: props.cancelTransaction, + }, 'Reject'), + ]), + ]), ]), ]) -- cgit v1.2.3 From abc78a1bf9b83d35bf1ac4453d8886f11675d41d Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sat, 29 Jul 2017 22:18:26 -0700 Subject: Add content boxes to pendingTx, prep for reusability --- ui/app/components/pending-tx.js | 509 ++++++++++++++-------------------------- 1 file changed, 179 insertions(+), 330 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index 2414a9759..8031547d4 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -20,6 +20,11 @@ const GWEI_FACTOR = new BN(1e9) const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR) const MIN_GAS_LIMIT_BN = new BN(21000) + +// Faked, for Icon +const Identicon = require('./identicon') +const ARAGON = '960b236A07cf122663c4303350609A66A7B288C0' + module.exports = PendingTx inherits(PendingTx, Component) function PendingTx () { @@ -31,6 +36,24 @@ function PendingTx () { } } +const sectionDivider = h('div', { + style: { + height:'1px', + background:'#E7E7E7', + }, +}), + +// Next: create separate react components +const contentDivider = h('div', { + style: { + marginLeft: '16px', + marginRight: '16px', + height:'1px', + background:'#E7E7E7', + }, +}) + + PendingTx.prototype.render = function () { const props = this.props const { currentCurrency, blockGasLimit } = props @@ -70,349 +93,187 @@ PendingTx.prototype.render = function () { this.inputs = [] return ( - - h('div', { - key: txMeta.id, + h('div.flex-column.flex-grow', { + style: { + // overflow: 'scroll', + minWidth: '355px', // TODO: maxWidth TBD, use home.html + }, }, [ - h('div', { + // Main Send token Card + h('div.send-screen.flex-column.flex-grow', { + style: { + marginLeft: '3.5%', + marginRight: '3.5%', + background: '#FFFFFF', // $background-white + boxShadow: '0 2px 4px 0 rgba(0,0,0,0.08)', + } }, [ - // tx info - h('div', [ - - h('.flex-row.flex-center', { - style: { - maxWidth: '100%', - }, - }, [ - - h(MiniAccountPanel, { - imageSeed: address, - picOrder: 'right', - }, [ - h('span.font-small', { - style: { - fontFamily: 'Montserrat Bold, Montserrat, sans-serif', - }, - }, identity.name), - - h(Copyable, { - value: ethUtil.toChecksumAddress(address), - }, [ - h('span.font-small', { - style: { - fontFamily: 'Montserrat Light, Montserrat, sans-serif', - }, - }, addressSummary(address, 6, 4, false)), - ]), - - h('span.font-small', { - style: { - fontFamily: 'Montserrat Light, Montserrat, sans-serif', - }, - }, [ - h(EthBalance, { - value: balance, - conversionRate, - currentCurrency, - inline: true, - labelColor: '#F7861C', - }), - ]), - ]), - - forwardCarrat(), - - this.miniAccountPanelForRecipient(), - ]), - - h('style', ` - .table-box { - margin: 7px 0px 0px 0px; - width: 100%; - } - .table-box .row { - margin: 0px; - background: rgb(236,236,236); - display: flex; - justify-content: space-between; - font-family: Montserrat Light, sans-serif; - font-size: 13px; - padding: 5px 25px; - } - .table-box .row .value { - font-family: Montserrat Regular; - } - `), - - h('.table-box', [ - - // Ether Value - // Currently not customizable, but easily modified - // in the way that gas and gasLimit currently are. - h('.row', [ - h('.cell.label', 'Amount'), - h(EthBalance, { value: txParams.value, currentCurrency, conversionRate }), - ]), - - // Gas Limit (customizable) - h('.cell.row', [ - h('.cell.label', 'Gas Limit'), - h('.cell.value', { - }, [ - h(BNInput, { - name: 'Gas Limit', - value: gasBn, - precision: 0, - scale: 0, - // The hard lower limit for gas. - min: MIN_GAS_LIMIT_BN.toString(10), - max: safeGasLimit, - suffix: 'UNITS', - style: { - position: 'relative', - top: '5px', - }, - onChange: this.gasLimitChanged.bind(this), - - ref: (hexInput) => { this.inputs.push(hexInput) }, - }), - ]), - ]), - - // Gas Price (customizable) - h('.cell.row', [ - h('.cell.label', 'Gas Price'), - h('.cell.value', { - }, [ - h(BNInput, { - name: 'Gas Price', - value: gasPriceBn, - precision: 9, - scale: 9, - suffix: 'GWEI', - min: MIN_GAS_PRICE_GWEI_BN.toString(10), - style: { - position: 'relative', - top: '5px', - }, - onChange: this.gasPriceChanged.bind(this), - ref: (hexInput) => { this.inputs.push(hexInput) }, - }), - ]), - ]), - - // Max Transaction Fee (calculated) - h('.cell.row', [ - h('.cell.label', 'Max Transaction Fee'), - h(EthBalance, { value: txFeeBn.toString(16), currentCurrency, conversionRate }), - ]), - - h('.cell.row', { - style: { - fontFamily: 'Montserrat Regular', - background: 'white', - padding: '10px 25px', - }, - }, [ - h('.cell.label', 'Max Total'), - h('.cell.value', { - style: { - display: 'flex', - alignItems: 'center', - }, - }, [ - h(EthBalance, { - value: maxCost.toString(16), - currentCurrency, - conversionRate, - inline: true, - labelColor: 'black', - fontSize: '16px', - }), - ]), - ]), - - // Data size row: - h('.cell.row', { - style: { - background: '#f7f7f7', - paddingBottom: '0px', - }, - }, [ - h('.cell.label'), - h('.cell.value', { - style: { - fontFamily: 'Montserrat Light', - fontSize: '11px', - }, - }, `Data included: ${dataLength} bytes`), - ]), - ]), // End of Table - + h('section.flex-center.flex-row', { + style: { + zIndex: 15, // $token-icon-z-index + marginTop: '-35px', + } + }, [ + h(Identicon, { + address: ARAGON, + diameter: 76, + }), ]), - h('style', ` - .conf-buttons button { - margin-left: 10px; - text-transform: uppercase; - } - `), + // + // Required Fields + // - txMeta.simulationFails ? - h('.error', { - style: { - marginLeft: 50, - fontSize: '0.9em', - }, - }, 'Transaction Error. Exception thrown in contract code.') - : null, + h('h3.flex-center', { + style: { + marginTop: '-18px', + fontSize: '16px', + }, + }, [ + 'Confirm Transaction', + ]), - !isValidAddress ? - h('.error', { - style: { - marginLeft: 50, - fontSize: '0.9em', - }, - }, 'Recipient address is invalid. Sending this transaction will result in a loss of ETH.') - : null, + h('h3.flex-center', { + style: { + textAlign: 'center', + fontSize: '12px', + }, + }, [ + 'You\'re sending to Recipient ...5924', + ]), - insufficientBalance ? - h('span.error', { - style: { - marginLeft: 50, - fontSize: '0.9em', - }, - }, 'Insufficient balance for transaction') - : null, + h('h3.flex-center', { + style: { + textAlign: 'center', + fontSize: '36px', + marginTop: '8px', + }, + }, [ + '0.24', + ]), - // send + cancel - h('.flex-row.flex-space-around.conf-buttons', { + h('h3.flex-center', { style: { - display: 'flex', - justifyContent: 'flex-end', - margin: '14px 25px', + textAlign: 'center', + fontSize: '12px', + marginTop: '4px', }, }, [ + 'ANT', + ]), + // error message + props.error && h('span.error.flex-center', props.error), - insufficientBalance ? - h('button.btn-green', { - onClick: props.buyEth, - }, 'Buy Ether') - : null, + sectionDivider, + h('section.flex-row.flex-center', { - h('form#pending-tx-form', { - onSubmit: this.onSubmit.bind(this), + }, [ + h('div', { + style: { + width: '50%', + } }, [ - // Reset Button - h('button', { - onClick: (event) => { - this.resetGasFields() - event.preventDefault() - }, - }, 'Reset'), - - // Accept Button - h('input.confirm.btn-green', { - type: 'submit', - value: 'SUBMIT', - style: { marginLeft: '10px' }, - disabled: insufficientBalance || !this.state.valid || !isValidAddress || this.state.submitting, - }), - - // Cancel Button - h('button.cancel.btn-red', { - onClick: props.cancelTransaction, - }, 'Reject'), + h('span', { + style: { + textAlign: 'left', + fontSize: '12px', + } + }, [ + 'From' + ]) ]), - ]), - ]), - ]) - ) -} - -PendingTx.prototype.miniAccountPanelForRecipient = function () { - const props = this.props - const txData = props.txData - const txParams = txData.txParams || {} - const isContractDeploy = !('to' in txParams) - - // If it's not a contract deploy, send to the account - if (!isContractDeploy) { - return h(MiniAccountPanel, { - imageSeed: txParams.to, - picOrder: 'left', - }, [ - - h('span.font-small', { - style: { - fontFamily: 'Montserrat Bold, Montserrat, sans-serif', - }, - }, nameForAddress(txParams.to, props.identities)), - - h(Copyable, { - value: ethUtil.toChecksumAddress(txParams.to), - }, [ - h('span.font-small', { - style: { - fontFamily: 'Montserrat Light, Montserrat, sans-serif', - }, - }, addressSummary(txParams.to, 6, 4, false)), - ]), - - ]) - } else { - return h(MiniAccountPanel, { - picOrder: 'left', - }, [ + h('div', { + style: { + width: '50%', + } + },[ + h('div', { + style: { + textAlign: 'left', + fontSize: '10px', + marginBottom: '-10px', + }, + }, 'Aragon Token'), - h('span.font-small', { - style: { - fontFamily: 'Montserrat Bold, Montserrat, sans-serif', - }, - }, 'New Contract'), + h('div', { + style: { + textAlign: 'left', + fontSize: '8px', + }, + }, 'Your Balance 2.34 ANT') + ]) + ]), - ]) - } -} + contentDivider, -PendingTx.prototype.gasPriceChanged = function (newBN, valid) { - log.info(`Gas price changed to: ${newBN.toString(10)}`) - const txMeta = this.gatherTxMeta() - txMeta.txParams.gasPrice = '0x' + newBN.toString('hex') - this.setState({ - txData: clone(txMeta), - valid, - }) -} + h('form#pending-tx-form', { + onSubmit: this.onSubmit.bind(this), + }, [ + // Reset Button + h('button', { + onClick: (event) => { + this.resetGasFields() + event.preventDefault() + }, + }, 'Reset'), + + // Accept Button + h('input.confirm.btn-green', { + type: 'submit', + value: 'SUBMIT', + style: { marginLeft: '10px' }, + disabled: insufficientBalance || !this.state.valid || !isValidAddress || this.state.submitting, + }), + + // Cancel Button + h('button.cancel.btn-red', { + onClick: props.cancelTransaction, + }, 'Reject'), + ]), -PendingTx.prototype.gasLimitChanged = function (newBN, valid) { - log.info(`Gas limit changed to ${newBN.toString(10)}`) - const txMeta = this.gatherTxMeta() - txMeta.txParams.gas = '0x' + newBN.toString('hex') - this.setState({ - txData: clone(txMeta), - valid, - }) + ]) // end of main container + ]) // end of minwidth wrapper + ) } -PendingTx.prototype.resetGasFields = function () { - log.debug(`pending-tx resetGasFields`) - - this.inputs.forEach((hexInput) => { - if (hexInput) { - hexInput.setValid() - } - }) - - this.setState({ - txData: null, - valid: true, - }) -} +// PendingTx.prototype.gasPriceChanged = function (newBN, valid) { +// log.info(`Gas price changed to: ${newBN.toString(10)}`) +// const txMeta = this.gatherTxMeta() +// txMeta.txParams.gasPrice = '0x' + newBN.toString('hex') +// this.setState({ +// txData: clone(txMeta), +// valid, +// }) +// } + +// PendingTx.prototype.gasLimitChanged = function (newBN, valid) { +// log.info(`Gas limit changed to ${newBN.toString(10)}`) +// const txMeta = this.gatherTxMeta() +// txMeta.txParams.gas = '0x' + newBN.toString('hex') +// this.setState({ +// txData: clone(txMeta), +// valid, +// }) +// } + +// PendingTx.prototype.resetGasFields = function () { +// log.debug(`pending-tx resetGasFields`) + +// this.inputs.forEach((hexInput) => { +// if (hexInput) { +// hexInput.setValid() +// } +// }) + +// this.setState({ +// txData: null, +// valid: true, +// }) +// } PendingTx.prototype.onSubmit = function (event) { event.preventDefault() @@ -471,15 +332,3 @@ PendingTx.prototype.bnMultiplyByFraction = function (targetBN, numerator, denomi const denomBN = new BN(denominator) return targetBN.mul(numBN).div(denomBN) } - -function forwardCarrat () { - return ( - h('img', { - src: 'images/forward-carrat.svg', - style: { - padding: '5px 6px 0px 10px', - height: '37px', - }, - }) - ) -} -- cgit v1.2.3 From 4880ee26d589ea7bbb1f0d532646fa818d4eaae4 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sat, 29 Jul 2017 22:20:29 -0700 Subject: Add note to self, for future code cleanup --- ui/app/components/pending-tx.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index 8031547d4..f77374ef8 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -36,6 +36,13 @@ function PendingTx () { } } +// Next: create separate react components +// roughly 5 components: +// heroIcon +// numericDisplay (contains symbol + currency) +// divider +// contentBox +// actionButtons const sectionDivider = h('div', { style: { height:'1px', @@ -43,7 +50,6 @@ const sectionDivider = h('div', { }, }), -// Next: create separate react components const contentDivider = h('div', { style: { marginLeft: '16px', -- cgit v1.2.3 From 689f60d1ce811f542e70da523bcb89b12242440d Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sat, 29 Jul 2017 22:44:39 -0700 Subject: Add rounded background to total token, with minor styling tweaks --- ui/app/components/pending-tx.js | 192 +++++++++++++++++++++++++++++++++++----- 1 file changed, 171 insertions(+), 21 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index f77374ef8..4b06f71b0 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -25,17 +25,6 @@ const MIN_GAS_LIMIT_BN = new BN(21000) const Identicon = require('./identicon') const ARAGON = '960b236A07cf122663c4303350609A66A7B288C0' -module.exports = PendingTx -inherits(PendingTx, Component) -function PendingTx () { - Component.call(this) - this.state = { - valid: true, - txData: null, - submitting: false, - } -} - // Next: create separate react components // roughly 5 components: // heroIcon @@ -48,7 +37,7 @@ const sectionDivider = h('div', { height:'1px', background:'#E7E7E7', }, -}), +}) const contentDivider = h('div', { style: { @@ -59,6 +48,16 @@ const contentDivider = h('div', { }, }) +module.exports = PendingTx +inherits(PendingTx, Component) +function PendingTx () { + Component.call(this) + this.state = { + valid: true, + txData: null, + submitting: false, + } +} PendingTx.prototype.render = function () { const props = this.props @@ -175,7 +174,6 @@ PendingTx.prototype.render = function () { sectionDivider, h('section.flex-row.flex-center', { - }, [ h('div', { style: { @@ -216,27 +214,179 @@ PendingTx.prototype.render = function () { contentDivider, + h('section.flex-row.flex-center', { + }, [ + h('div', { + style: { + width: '50%', + } + }, [ + h('span', { + style: { + textAlign: 'left', + fontSize: '12px', + } + }, [ + 'To' + ]) + ]), + + h('div', { + style: { + width: '50%', + } + },[ + h('div', { + style: { + textAlign: 'left', + fontSize: '10px', + marginBottom: '-10px', + }, + }, 'Ethereum Address'), + + h('div', { + style: { + textAlign: 'left', + fontSize: '8px', + }, + }, '...5924') + ]) + ]), + + contentDivider, + + h('section.flex-row.flex-center', { + }, [ + h('div', { + style: { + width: '50%', + } + }, [ + h('span', { + style: { + textAlign: 'left', + fontSize: '12px', + } + }, [ + 'Gas Fee' + ]) + ]), + + h('div', { + style: { + width: '50%', + } + },[ + h('div', { + style: { + textAlign: 'left', + fontSize: '10px', + marginBottom: '-10px', + }, + }, '$0.04 USD'), + + h('div', { + style: { + textAlign: 'left', + fontSize: '8px', + }, + }, '0.001575 ETH') + ]) + ]), + + contentDivider, + + h('section.flex-row.flex-center', { + style: { + backgroundColor: '#F6F6F6', // $wild-sand + borderRadius: '8px', + marginLeft: '10px', + marginRight: '10px', + paddingLeft: '6px', + paddingRight: '6px', + } + }, [ + h('div', { + style: { + width: '50%', + } + }, [ + h('div', { + style: { + textAlign: 'left', + fontSize: '12px', + } + }, [ + 'Total Tokens' + ]), + + h('div', { + style: { + textAlign: 'left', + fontSize: '8px', + } + }, [ + 'Total Gas' + ]) + + ]), + + h('div', { + style: { + width: '50%', + } + },[ + h('div', { + style: { + textAlign: 'left', + fontSize: '10px', + marginBottom: '-10px', + }, + }, '0.24 ANT (127.00 USD)'), + + h('div', { + style: { + textAlign: 'left', + fontSize: '8px', + }, + }, '0.249 ETH') + ]) + ]), + + sectionDivider, + h('form#pending-tx-form', { onSubmit: this.onSubmit.bind(this), }, [ // Reset Button - h('button', { - onClick: (event) => { - this.resetGasFields() - event.preventDefault() - }, - }, 'Reset'), + // h('button', { + // onClick: (event) => { + // this.resetGasFields() + // event.preventDefault() + // }, + // }, 'Reset'), // Accept Button h('input.confirm.btn-green', { type: 'submit', value: 'SUBMIT', - style: { marginLeft: '10px' }, + style: { + color: '#FFFFFF', + fontSize: '12px', + lineHeight: '20px', + textAlign: 'center', + }, disabled: insufficientBalance || !this.state.valid || !isValidAddress || this.state.submitting, }), // Cancel Button - h('button.cancel.btn-red', { + h('button.cancel.btn-light', { + style: { + background: '#F7F7F7', // $alabaster + border: 'none', + opacity: 1, + width: '8em', + }, onClick: props.cancelTransaction, }, 'Reject'), ]), -- cgit v1.2.3 From f368f371c29699f277b8c91ad8a6284a3b451223 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sat, 29 Jul 2017 23:02:04 -0700 Subject: Simplify btn-green colors --- ui/app/components/pending-tx.js | 1 + 1 file changed, 1 insertion(+) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index 4b06f71b0..eae9046a8 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -372,6 +372,7 @@ PendingTx.prototype.render = function () { value: 'SUBMIT', style: { color: '#FFFFFF', + borderRadius: '2px'; fontSize: '12px', lineHeight: '20px', textAlign: 'center', -- cgit v1.2.3 From 9373ba9f381f390be7e8d88057c0c6f1a97a27f8 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sat, 29 Jul 2017 23:09:49 -0700 Subject: Move action buttons out of send token container, tweak styles --- ui/app/components/pending-tx.js | 78 +++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 38 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index eae9046a8..ede561bd2 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -304,6 +304,7 @@ PendingTx.prototype.render = function () { marginRight: '10px', paddingLeft: '6px', paddingRight: '6px', + marginBottom: '10px', } }, [ h('div', { @@ -315,6 +316,7 @@ PendingTx.prototype.render = function () { style: { textAlign: 'left', fontSize: '12px', + marginBottom: '-10px', } }, [ 'Total Tokens' @@ -353,46 +355,46 @@ PendingTx.prototype.render = function () { ]) ]), - sectionDivider, - - h('form#pending-tx-form', { - onSubmit: this.onSubmit.bind(this), - }, [ - // Reset Button - // h('button', { - // onClick: (event) => { - // this.resetGasFields() - // event.preventDefault() - // }, - // }, 'Reset'), - - // Accept Button - h('input.confirm.btn-green', { - type: 'submit', - value: 'SUBMIT', - style: { - color: '#FFFFFF', - borderRadius: '2px'; - fontSize: '12px', - lineHeight: '20px', - textAlign: 'center', - }, - disabled: insufficientBalance || !this.state.valid || !isValidAddress || this.state.submitting, - }), + ]), // end of container - // Cancel Button - h('button.cancel.btn-light', { - style: { - background: '#F7F7F7', // $alabaster - border: 'none', - opacity: 1, - width: '8em', - }, - onClick: props.cancelTransaction, - }, 'Reject'), - ]), + h('form#pending-tx-form.flex-column.flex-center', { + onSubmit: this.onSubmit.bind(this), + }, [ + // Reset Button + // h('button', { + // onClick: (event) => { + // this.resetGasFields() + // event.preventDefault() + // }, + // }, 'Reset'), + + // Accept Button + h('input.confirm.btn-green', { + type: 'submit', + value: 'SUBMIT', + style: { + marginTop: '8px', + width: '8em', + color: '#FFFFFF', + borderRadius: '2px', + fontSize: '12px', + lineHeight: '20px', + textAlign: 'center', + }, + disabled: insufficientBalance || !this.state.valid || !isValidAddress || this.state.submitting, + }), - ]) // end of main container + // Cancel Button + h('button.cancel.btn-light', { + style: { + background: '#F7F7F7', // $alabaster + border: 'none', + opacity: 1, + width: '8em', + }, + onClick: props.cancelTransaction, + }, 'Reject'), + ]), ]) // end of minwidth wrapper ) } -- cgit v1.2.3 From 97cb25c9f17b5cbf66f4e9a769bcdbdd39b4c9b5 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sat, 29 Jul 2017 23:11:11 -0700 Subject: Adjust copy in send token confirmation screen --- ui/app/components/pending-tx.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index ede561bd2..1fa9db4ef 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -371,7 +371,7 @@ PendingTx.prototype.render = function () { // Accept Button h('input.confirm.btn-green', { type: 'submit', - value: 'SUBMIT', + value: 'CONFIRM', style: { marginTop: '8px', width: '8em', @@ -393,7 +393,7 @@ PendingTx.prototype.render = function () { width: '8em', }, onClick: props.cancelTransaction, - }, 'Reject'), + }, 'CANCEL'), ]), ]) // end of minwidth wrapper ) -- cgit v1.2.3 From a7ab69b940e91aea4362c3c0bf9e9f3efb7c76c9 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 30 Jul 2017 16:47:47 -0700 Subject: Adjust button styles for Send Token screen --- ui/app/components/pending-tx.js | 1 + 1 file changed, 1 insertion(+) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index 1fa9db4ef..1c47440f2 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -380,6 +380,7 @@ PendingTx.prototype.render = function () { fontSize: '12px', lineHeight: '20px', textAlign: 'center', + borderStyle: 'none', }, disabled: insufficientBalance || !this.state.valid || !isValidAddress || this.state.submitting, }), -- cgit v1.2.3 From cbd53d4601f1af5aa4337e86ea8875606406e803 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 30 Jul 2017 21:25:32 -0700 Subject: Add containers for wallet view and dropdown UI --- ui/app/components/wallet-view.js | 81 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 ui/app/components/wallet-view.js (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js new file mode 100644 index 000000000..fed227d6b --- /dev/null +++ b/ui/app/components/wallet-view.js @@ -0,0 +1,81 @@ +const Component = require('react').Component +const connect = require('react-redux').connect +const h = require('react-hyperscript') +const inherits = require('util').inherits +const Identicon = require('./identicon') +const AccountDropdowns = require('./account-dropdowns').AccountDropdowns + +module.exports = connect(mapStateToProps)(WalletView) + +function mapStateToProps (state) { + return { + network: state.metamask.network, + } +} + + +inherits(WalletView, Component) +function WalletView () { + Component.call(this) +} + +const noop = () => {} + +WalletView.prototype.render = function () { + const selected = '0x82df11beb942BEeeD58d466fCb0F0791365C7684' + const { network } = this.props + + return h('div.wallet-view.flex-column', { + style: { + flexGrow: 1, + height: '82vh', + background: '#FAFAFA', + } + }, [ + + h('div.flex-row.flex-center', { + style: { + // marginLeft: '5px', + // marginRight: '5px', + // marginTop: '10px', + // alignItems: 'center', + } + }, [ + + h('.identicon-wrapper.select-none', [ + h(Identicon, { + diameter: 24, + address: selected, + }), + ]), + + h('span', { + style: { + fontSize: '1.5em', + marginLeft: '5px', + } + }, [ + 'Account 1' + ]), + + h( + AccountDropdowns, + { + style: { + marginRight: '8px', + marginLeft: 'auto', + cursor: 'pointer', + }, + selected, + network, + identities: {}, + }, + ), + + ]) + + // wallet display 1 + // token display 1 + + ]) +} -- cgit v1.2.3 From ddbf5613b3b7cf7b7b637f33cac87f5bbe69e7a7 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 30 Jul 2017 21:35:41 -0700 Subject: Add note for later on isolating components --- ui/app/components/wallet-view.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index fed227d6b..3a08705be 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -67,7 +67,7 @@ WalletView.prototype.render = function () { cursor: 'pointer', }, selected, - network, + network, // TODO: this prop could be in the account dropdown container identities: {}, }, ), -- cgit v1.2.3 From 0ca50dfb1b990dadc702b178fad7e6434b71167a Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 30 Jul 2017 21:53:13 -0700 Subject: Center account name and dropdowns --- ui/app/components/wallet-view.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 3a08705be..f425ec3d1 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -35,10 +35,9 @@ WalletView.prototype.render = function () { h('div.flex-row.flex-center', { style: { - // marginLeft: '5px', - // marginRight: '5px', - // marginTop: '10px', - // alignItems: 'center', + marginLeft: '35px', + marginRight: '35px', + marginTop: '35px', } }, [ @@ -52,7 +51,7 @@ WalletView.prototype.render = function () { h('span', { style: { fontSize: '1.5em', - marginLeft: '5px', + marginLeft: '10px', // TODO: switch all units for this component to em } }, [ 'Account 1' -- cgit v1.2.3 From 610d6da8aee2c32bb142b1ff93f6a0a685adf46c Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 30 Jul 2017 22:10:59 -0700 Subject: Add hyperscript for wallet display component --- ui/app/components/wallet-view.js | 52 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index f425ec3d1..c06c4133b 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -29,10 +29,11 @@ WalletView.prototype.render = function () { style: { flexGrow: 1, height: '82vh', - background: '#FAFAFA', + background: '#FAFAFA', // TODO: add to reusable colors } }, [ + // TODO: Separate component: wallet account details h('div.flex-row.flex-center', { style: { marginLeft: '35px', @@ -71,10 +72,53 @@ WalletView.prototype.render = function () { }, ), - ]) + ]), - // wallet display 1 - // token display 1 + // TODO: Separate component: wallet contents + h('div.flex-column', { + style: { + marginLeft: '35px', + marginTop: '15px', + alignItems: 'flex-start', + } + }, [ + + h('span', { + style: { + fontSize: '1.1em', + }, + }, 'Wallet'), + + h('span', { + style: { + fontSize: '1.8em', + margin: '10px 0px', + }, + }, '1001.124 ETH'), + + h('span', { + style: { + fontSize: '1.3em', + }, + }, '$300,000.00 USD'), + + h('div', { + style: { + position: 'absolute', + marginLeft: '-35px', + height: '6em', + width: '4px', + background: '#D8D8D8', // TODO: add to resuable colors + } + }, [ + ]) + ]), + + // Buy Buttons + + + + // Wallet contents ]) } -- cgit v1.2.3 From 7d4927c975554b091d72f6c24e7dd9e824f32548 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 30 Jul 2017 22:25:20 -0700 Subject: Add layout for Buy and Send buttons --- ui/app/components/wallet-view.js | 45 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index c06c4133b..b61b53447 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -115,7 +115,50 @@ WalletView.prototype.render = function () { ]), // Buy Buttons - + // for index.css + // + // TODO: move into a class + // div.wallet-btn { + // border: 1px solid rgb(91, 93, 103); + // border-radius: 2px; + // height: 30px; + // width: 75px; + // font-size: 0.8em; + // text-align: center; + // line-height: 25px; + // } + + h('div.flex-row', { + style: { + marginLeft: '35px', + marginTop: '10px', + } + }, [ + h('div', { + style: { + border: '1px solid rgb(91, 93, 103)', + borderRadius: '2px', + height: '30px', + width: '75px', + fontSize: '0.8em', + textAlign: 'center', + lineHeight: '25px', + } + }, 'BUY'), + h('div.wallet-btn', { + style: { + border: '1px solid rgb(91, 93, 103)', + borderRadius: '2px', + height: '30px', + width: '75px', + fontSize: '0.8em', + textAlign: 'center', + lineHeight: '25px', + // spacing... + marginLeft: '15px', + } + }, 'SEND'), + ]), // Wallet contents -- cgit v1.2.3 From 0c1aea97c74e6ac0c263a654510faca73a2dc949 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 30 Jul 2017 22:30:55 -0700 Subject: Isolate wallet-content-display component --- ui/app/components/wallet-content-display.js | 54 +++++++++++++++++++++++++++++ ui/app/components/wallet-view.js | 10 ++++-- 2 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 ui/app/components/wallet-content-display.js (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-content-display.js b/ui/app/components/wallet-content-display.js new file mode 100644 index 000000000..f1db09ec8 --- /dev/null +++ b/ui/app/components/wallet-content-display.js @@ -0,0 +1,54 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits + +module.exports = WalletContentDisplay + +inherits(WalletContentDisplay, Component) +function WalletContentDisplay () { + Component.call(this) +} + +WalletContentDisplay.prototype.render = function () { + const { title, amount, fiatValue, active } = this.props + + return h('div.flex-column', { + style: { + marginLeft: '35px', + marginTop: '15px', + alignItems: 'flex-start', + } + }, [ + + h('span', { + style: { + fontSize: '1.1em', + }, + }, title), + + h('span', { + style: { + fontSize: '1.8em', + margin: '10px 0px', + }, + }, amount), + + h('span', { + style: { + fontSize: '1.3em', + }, + }, fiatValue), + + active && h('div', { + style: { + position: 'absolute', + marginLeft: '-35px', + height: '6em', + width: '4px', + background: '#D8D8D8', // TODO: add to resuable colors + } + }, [ + ]) + ]) +} + diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index b61b53447..1c3f3b7f9 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -4,6 +4,7 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const Identicon = require('./identicon') const AccountDropdowns = require('./account-dropdowns').AccountDropdowns +const Content = require('./wallet-content-display') module.exports = connect(mapStateToProps)(WalletView) @@ -74,7 +75,7 @@ WalletView.prototype.render = function () { ]), - // TODO: Separate component: wallet contents + // TODO: Separate component: wallet-content-account h('div.flex-column', { style: { marginLeft: '35px', @@ -160,8 +161,13 @@ WalletView.prototype.render = function () { }, 'SEND'), ]), - // Wallet contents + h(Content, { + title: "Total Token Balance", + amount: "45.439 ETH", + fiatValue: "$13,000.00 USD", + active: false, + }) ]) } -- cgit v1.2.3 From 3797b9921fc227c1bcf9681cffa73588cc7afb44 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 31 Jul 2017 20:22:15 -0700 Subject: Adjust popup size to 545x450; refactor wallet view to fit --- ui/app/components/wallet-content-display.js | 14 +++--- ui/app/components/wallet-view.js | 74 ++++++++--------------------- 2 files changed, 28 insertions(+), 60 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-content-display.js b/ui/app/components/wallet-content-display.js index f1db09ec8..3baffad69 100644 --- a/ui/app/components/wallet-content-display.js +++ b/ui/app/components/wallet-content-display.js @@ -10,13 +10,14 @@ function WalletContentDisplay () { } WalletContentDisplay.prototype.render = function () { - const { title, amount, fiatValue, active } = this.props + const { title, amount, fiatValue, active, style } = this.props + // TODO: Separate component: wallet-content-account return h('div.flex-column', { style: { - marginLeft: '35px', - marginTop: '15px', + marginLeft: '1.3em', alignItems: 'flex-start', + ...style, } }, [ @@ -29,7 +30,7 @@ WalletContentDisplay.prototype.render = function () { h('span', { style: { fontSize: '1.8em', - margin: '10px 0px', + margin: '0.4em 0em', }, }, amount), @@ -42,13 +43,14 @@ WalletContentDisplay.prototype.render = function () { active && h('div', { style: { position: 'absolute', - marginLeft: '-35px', + marginLeft: '-1.3em', height: '6em', - width: '4px', + width: '0.3em', background: '#D8D8D8', // TODO: add to resuable colors } }, [ ]) ]) + } diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 1c3f3b7f9..0c5bd5c4f 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -37,9 +37,7 @@ WalletView.prototype.render = function () { // TODO: Separate component: wallet account details h('div.flex-row.flex-center', { style: { - marginLeft: '35px', - marginRight: '35px', - marginTop: '35px', + margin: '1.8em 1.3em', } }, [ @@ -52,8 +50,8 @@ WalletView.prototype.render = function () { h('span', { style: { - fontSize: '1.5em', - marginLeft: '10px', // TODO: switch all units for this component to em + fontSize: '1.2em', + marginLeft: '0.6em', // TODO: switch all units for this component to em } }, [ 'Account 1' @@ -63,7 +61,6 @@ WalletView.prototype.render = function () { AccountDropdowns, { style: { - marginRight: '8px', marginLeft: 'auto', cursor: 'pointer', }, @@ -75,49 +72,15 @@ WalletView.prototype.render = function () { ]), - // TODO: Separate component: wallet-content-account - h('div.flex-column', { - style: { - marginLeft: '35px', - marginTop: '15px', - alignItems: 'flex-start', - } - }, [ - - h('span', { - style: { - fontSize: '1.1em', - }, - }, 'Wallet'), - - h('span', { - style: { - fontSize: '1.8em', - margin: '10px 0px', - }, - }, '1001.124 ETH'), - - h('span', { - style: { - fontSize: '1.3em', - }, - }, '$300,000.00 USD'), - - h('div', { - style: { - position: 'absolute', - marginLeft: '-35px', - height: '6em', - width: '4px', - background: '#D8D8D8', // TODO: add to resuable colors - } - }, [ - ]) - ]), + h(Content, { + title: 'Wallet', + amount: '1001.124 ETH', + fiatValue: '$300,000.00 USD', + active: true, + }), // Buy Buttons // for index.css - // // TODO: move into a class // div.wallet-btn { // border: 1px solid rgb(91, 93, 103); @@ -131,32 +94,32 @@ WalletView.prototype.render = function () { h('div.flex-row', { style: { - marginLeft: '35px', - marginTop: '10px', + marginLeft: '1.3em', + marginTop: '0.8em', } }, [ h('div', { style: { border: '1px solid rgb(91, 93, 103)', borderRadius: '2px', - height: '30px', - width: '75px', + height: '28px', + width: '70px', fontSize: '0.8em', textAlign: 'center', lineHeight: '25px', + marginLeft: '.6em', } }, 'BUY'), h('div.wallet-btn', { style: { border: '1px solid rgb(91, 93, 103)', borderRadius: '2px', - height: '30px', - width: '75px', + height: '28px', + width: '70px', fontSize: '0.8em', textAlign: 'center', lineHeight: '25px', - // spacing... - marginLeft: '15px', + marginLeft: '.6em', } }, 'SEND'), ]), @@ -167,6 +130,9 @@ WalletView.prototype.render = function () { amount: "45.439 ETH", fiatValue: "$13,000.00 USD", active: false, + style: { + marginTop: '1.3em', + } }) ]) -- cgit v1.2.3 From 92bd783e0c61e05772cc494a386bb5f21e9dbbb3 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 31 Jul 2017 20:54:04 -0700 Subject: Adjust button styles to left align with wallet text --- ui/app/components/wallet-view.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 0c5bd5c4f..e61346290 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -102,23 +102,20 @@ WalletView.prototype.render = function () { style: { border: '1px solid rgb(91, 93, 103)', borderRadius: '2px', - height: '28px', - width: '70px', + height: '20px', + width: '50px', fontSize: '0.8em', textAlign: 'center', - lineHeight: '25px', - marginLeft: '.6em', } }, 'BUY'), h('div.wallet-btn', { style: { border: '1px solid rgb(91, 93, 103)', borderRadius: '2px', - height: '28px', - width: '70px', + height: '20px', + width: '50px', fontSize: '0.8em', textAlign: 'center', - lineHeight: '25px', marginLeft: '.6em', } }, 'SEND'), -- cgit v1.2.3 From c876428044c8e6eec300ceeb0d7ab0c44e68f8d3 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 31 Jul 2017 21:16:07 -0700 Subject: Add TxView, use width percentages instead of flex-grow for layout --- ui/app/components/tx-view.js | 53 ++++++++++++++++++++++++++++++++++++++++ ui/app/components/wallet-view.js | 2 +- 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 ui/app/components/tx-view.js (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js new file mode 100644 index 000000000..b10589035 --- /dev/null +++ b/ui/app/components/tx-view.js @@ -0,0 +1,53 @@ +const Component = require('react').Component +const connect = require('react-redux').connect +const h = require('react-hyperscript') +const inherits = require('util').inherits +// const Identicon = require('./identicon') +// const AccountDropdowns = require('./account-dropdowns').AccountDropdowns +// const Content = require('./wallet-content-display') + +module.exports = connect()(TxView) + +// function mapStateToProps (state) { +// return { +// network: state.metamask.network, +// } +// } + +inherits(TxView, Component) +function TxView () { + Component.call(this) +} + +TxView.prototype.render = function () { + return h('div.tx-view.flex-column', { + style: { + width: '66.666%', + height: '82vh', + background: '#FFFFFF', + } + }, [ + h('div.flex-row', { + }, [ + // tab + h('div.flex-column', { + + }, [ + h('div', {}, 'Transactions'), + h('div', { + style: { + height: '0.5em', + color: 'black', + width: '100%', + } + }) + ]), + + // tab2 + ]) + ]) + // column + // tab row + // divider + // item +} diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index e61346290..b8ea633db 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -28,7 +28,7 @@ WalletView.prototype.render = function () { return h('div.wallet-view.flex-column', { style: { - flexGrow: 1, + width: '33.333%', height: '82vh', background: '#FAFAFA', // TODO: add to reusable colors } -- cgit v1.2.3 From c7ace5b23d911512495edbd4f0ecb8e0190bc537 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 31 Jul 2017 21:27:37 -0700 Subject: Add hyperscript for tx-view tabs --- ui/app/components/tx-view.js | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index b10589035..06ee3bfc6 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -13,6 +13,15 @@ module.exports = connect()(TxView) // network: state.metamask.network, // } // } +// +const contentDivider = h('div', { + style: { + marginLeft: '1.3em', + marginRight: '1.3em', + height:'1px', + background:'#E7E7E7', // TODO: make custom color + }, +}) inherits(TxView, Component) function TxView () { @@ -28,23 +37,32 @@ TxView.prototype.render = function () { } }, [ h('div.flex-row', { + style: { + margin: '1.8em 1.3em', + } }, [ - // tab - h('div.flex-column', { + // tx-view-tab.js + h('div.flex-row', { }, [ - h('div', {}, 'Transactions'), + h('div', { style: { - height: '0.5em', - color: 'black', - width: '100%', + borderBottom: '0.07em solid black', + paddingBottom: '0.015em', } - }) - ]), + }, 'TRANSACTIONS'), + + h('div', { + style: { + marginLeft: '2em', + } + }, 'TOKENS'), - // tab2 + ]), ]) + + h('') ]) // column // tab row -- cgit v1.2.3 From ce06fbd36debac144b4f4bf1d3948b35332e9c41 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 31 Jul 2017 21:34:37 -0700 Subject: Add tx-view content divider component --- ui/app/components/tx-view.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 06ee3bfc6..1bc828c20 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -13,7 +13,7 @@ module.exports = connect()(TxView) // network: state.metamask.network, // } // } -// + const contentDivider = h('div', { style: { marginLeft: '1.3em', @@ -38,7 +38,7 @@ TxView.prototype.render = function () { }, [ h('div.flex-row', { style: { - margin: '1.8em 1.3em', + margin: '1.8em 1.3em 0.8em 1.3em', } }, [ @@ -55,14 +55,15 @@ TxView.prototype.render = function () { h('div', { style: { - marginLeft: '2em', + marginLeft: '1.25em', } }, 'TOKENS'), ]), - ]) + ]), + + contentDivider, - h('') ]) // column // tab row -- cgit v1.2.3 From caab0b61ccb20a19fd97d4177698e9675d0b5451 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 31 Jul 2017 22:00:18 -0700 Subject: Add rough layout for tx list items --- ui/app/components/tx-view.js | 60 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 1bc828c20..c32e9edcb 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -64,9 +64,69 @@ TxView.prototype.render = function () { contentDivider, + this.renderTransactionListItem(), + + contentDivider, + + this.renderTransactionListItem(), + + contentDivider, + ]) // column // tab row // divider // item } + +TxView.prototype.renderTransactionListItem = function () { + return h('div.flex-column', { + style: { + alignItems: 'stretch', + margin: '0.6em 1.3em 0.6em 1.3em', + } + }, [ + + h('div', { + style: { + flexGrow: 1, + marginTop: '0.3em', + } + }, 'Jul 01, 2017'), + + h('div.flex-row', { + style: { + alignItems: 'stretch', + } + }, [ + + h('div', { + style: { + flexGrow: 1, + } + }, 'icon'), + + h('div', { + style: { + flexGrow: 3, + } + }, 'Hash'), + + h('div', { + style: { + flexGrow: 5, + } + }, 'Status'), + + h('div', { + style: { + flexGrow: 2, + } + }, 'Details'), + + ]) + + ]) +} + + -- cgit v1.2.3 From a7fc5126502a9c69aaa727178997ea4ed703c2d6 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 31 Jul 2017 23:07:58 -0700 Subject: Implement mobile-friendly responsive layout with flex wrap --- ui/app/components/tx-view.js | 6 +++++- ui/app/components/wallet-view.js | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index c32e9edcb..bcd30e6d8 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -31,7 +31,11 @@ function TxView () { TxView.prototype.render = function () { return h('div.tx-view.flex-column', { style: { - width: '66.666%', + // width: '66.666%', + flexGrow: 2, + flexShrink: 0, + flexBasis: '230px', // .666*345 + // flexBasis: '400px', height: '82vh', background: '#FFFFFF', } diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index b8ea633db..60c2cb5c6 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -28,7 +28,10 @@ WalletView.prototype.render = function () { return h('div.wallet-view.flex-column', { style: { - width: '33.333%', + // width: '33.333%', + flexGrow: 1, + flexShrink: 0, + flexBasis: '230px', // .333*345 height: '82vh', background: '#FAFAFA', // TODO: add to reusable colors } -- cgit v1.2.3 From 6f4bee45997862b3ca52785b9d62489969f070f5 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 31 Jul 2017 23:21:11 -0700 Subject: Hook up send button to Send Token screen --- ui/app/components/wallet-view.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 60c2cb5c6..091a5cd7c 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -5,8 +5,9 @@ const inherits = require('util').inherits const Identicon = require('./identicon') const AccountDropdowns = require('./account-dropdowns').AccountDropdowns const Content = require('./wallet-content-display') +const actions = require('../actions') -module.exports = connect(mapStateToProps)(WalletView) +module.exports = connect(mapStateToProps, mapDispatchToProps)(WalletView) function mapStateToProps (state) { return { @@ -14,6 +15,12 @@ function mapStateToProps (state) { } } +function mapDispatchToProps (dispatch) { + return { + showSendPage: () => {dispatch(actions.showSendPage())}, + } +} + inherits(WalletView, Component) function WalletView () { @@ -112,6 +119,10 @@ WalletView.prototype.render = function () { } }, 'BUY'), h('div.wallet-btn', { + onClick: () => { + console.log("SHOW"); + this.props.showSendPage(); + }, style: { border: '1px solid rgb(91, 93, 103)', borderRadius: '2px', -- cgit v1.2.3 From 41c585c796a9049c2413036e7b23bf07330daa82 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Wed, 2 Aug 2017 12:18:29 -0700 Subject: Make wallet view visible iff vw above 575px --- ui/app/components/wallet-view.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 091a5cd7c..97c881483 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -33,7 +33,7 @@ WalletView.prototype.render = function () { const selected = '0x82df11beb942BEeeD58d466fCb0F0791365C7684' const { network } = this.props - return h('div.wallet-view.flex-column', { + return h('div.wallet-view.flex-column.lap-visible', { style: { // width: '33.333%', flexGrow: 1, -- cgit v1.2.3 From 22b03c62e650182951dce25a5ce9de982782a7fa Mon Sep 17 00:00:00 2001 From: sdtsui Date: Wed, 2 Aug 2017 12:29:07 -0700 Subject: Add burger icon and phone-visible media queries --- ui/app/components/tx-view.js | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index bcd30e6d8..c5c6484cc 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -40,6 +40,11 @@ TxView.prototype.render = function () { background: '#FFFFFF', } }, [ + + h('div.phone-visible.fa.fa-bars', { + + }, []), + h('div.flex-row', { style: { margin: '1.8em 1.3em 0.8em 1.3em', -- cgit v1.2.3 From 7767f9f7ad7321d88a0b738d2c272961cc1ce286 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Wed, 2 Aug 2017 13:03:36 -0700 Subject: Hook up responsive sidebar --- ui/app/components/wallet-view.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 97c881483..63335dd93 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -31,9 +31,9 @@ const noop = () => {} WalletView.prototype.render = function () { const selected = '0x82df11beb942BEeeD58d466fCb0F0791365C7684' - const { network } = this.props + const { network, responsiveDisplayClassname } = this.props - return h('div.wallet-view.flex-column.lap-visible', { + return h('div.wallet-view.flex-column' + (responsiveDisplayClassname || ''), { style: { // width: '33.333%', flexGrow: 1, -- cgit v1.2.3 From dfa10763e36f745d82fb62adc4ac42773d266da4 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Wed, 2 Aug 2017 13:32:02 -0700 Subject: Integrate slideout menu with tx view --- ui/app/components/tx-view.js | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index c5c6484cc..b72abb084 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -2,17 +2,29 @@ const Component = require('react').Component const connect = require('react-redux').connect const h = require('react-hyperscript') const inherits = require('util').inherits +const actions = require('../actions') +// slideout menu +const SlideoutMenu = require('react-burger-menu').slide +const WalletView = require('./wallet-view') + // const Identicon = require('./identicon') // const AccountDropdowns = require('./account-dropdowns').AccountDropdowns // const Content = require('./wallet-content-display') -module.exports = connect()(TxView) +module.exports = connect(mapStateToProps, mapDispatchToProps)(TxView) + +function mapStateToProps (state) { + return { + sidebarOpen: state.appState.sidebarOpen, + } +} -// function mapStateToProps (state) { -// return { -// network: state.metamask.network, -// } -// } +function mapDispatchToProps (dispatch) { + return { + showSidebar: () => {dispatch(actions.showSidebar())}, + hideSidebar: () => {dispatch(actions.hideSidebar())}, + } +} const contentDivider = h('div', { style: { @@ -40,9 +52,19 @@ TxView.prototype.render = function () { background: '#FFFFFF', } }, [ + // slideout - move to separate render func + h(SlideoutMenu, { + isOpen: this.props.sidebarOpen, + }, [ + h(WalletView, { + responsiveDisplayClassname: '.phone-visible' + }), + ]), h('div.phone-visible.fa.fa-bars', { - + onClick: () => { + this.props.sidebarOpen ? this.props.hideSidebar() : this.props.showSidebar() + } }, []), h('div.flex-row', { -- cgit v1.2.3 From 9ebdc343aa32c36bdff9debcecc3c75485939e2a Mon Sep 17 00:00:00 2001 From: sdtsui Date: Wed, 2 Aug 2017 14:17:58 -0700 Subject: Implement custom sidebar, with close button --- ui/app/components/tx-view.js | 13 +++---------- ui/app/components/wallet-view.js | 14 ++++++++++++-- 2 files changed, 15 insertions(+), 12 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index b72abb084..2aaa32395 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -52,20 +52,13 @@ TxView.prototype.render = function () { background: '#FFFFFF', } }, [ - // slideout - move to separate render func - h(SlideoutMenu, { - isOpen: this.props.sidebarOpen, - }, [ - h(WalletView, { - responsiveDisplayClassname: '.phone-visible' - }), - ]), - h('div.phone-visible.fa.fa-bars', { onClick: () => { + console.log("click received") this.props.sidebarOpen ? this.props.hideSidebar() : this.props.showSidebar() } - }, []), + }, [ + ]), h('div.flex-row', { style: { diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 63335dd93..2a626a930 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -12,16 +12,17 @@ module.exports = connect(mapStateToProps, mapDispatchToProps)(WalletView) function mapStateToProps (state) { return { network: state.metamask.network, + sidebarOpen: state.appState.sidebarOpen, } } function mapDispatchToProps (dispatch) { return { showSendPage: () => {dispatch(actions.showSendPage())}, + hideSidebar: () => {dispatch(actions.hideSidebar())}, } } - inherits(WalletView, Component) function WalletView () { Component.call(this) @@ -31,7 +32,7 @@ const noop = () => {} WalletView.prototype.render = function () { const selected = '0x82df11beb942BEeeD58d466fCb0F0791365C7684' - const { network, responsiveDisplayClassname } = this.props + const { network, responsiveDisplayClassname, style } = this.props return h('div.wallet-view.flex-column' + (responsiveDisplayClassname || ''), { style: { @@ -41,9 +42,18 @@ WalletView.prototype.render = function () { flexBasis: '230px', // .333*345 height: '82vh', background: '#FAFAFA', // TODO: add to reusable colors + ...style, } }, [ + h('div.phone-visible.fa.fa-bars', { + onClick: () => { + console.log("click received-inwalletview") + this.props.hideSidebar() + } + }, [ + ]), + // TODO: Separate component: wallet account details h('div.flex-row.flex-center', { style: { -- cgit v1.2.3 From 01788376d5b7a0437b9073c8e8e0284a2cead6e4 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Wed, 2 Aug 2017 23:07:35 -0700 Subject: Finalize height for main screens, excluding sidebar --- ui/app/components/tx-view.js | 5 +---- ui/app/components/wallet-view.js | 2 -- 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 2aaa32395..dc86e7ea8 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -43,12 +43,9 @@ function TxView () { TxView.prototype.render = function () { return h('div.tx-view.flex-column', { style: { - // width: '66.666%', flexGrow: 2, flexShrink: 0, - flexBasis: '230px', // .666*345 - // flexBasis: '400px', - height: '82vh', + flexBasis: '230px', background: '#FFFFFF', } }, [ diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 2a626a930..8fd555ccb 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -36,11 +36,9 @@ WalletView.prototype.render = function () { return h('div.wallet-view.flex-column' + (responsiveDisplayClassname || ''), { style: { - // width: '33.333%', flexGrow: 1, flexShrink: 0, flexBasis: '230px', // .333*345 - height: '82vh', background: '#FAFAFA', // TODO: add to reusable colors ...style, } -- cgit v1.2.3 From 3ed81847d1b6f00e208dbcb973cafcc633c268ad Mon Sep 17 00:00:00 2001 From: sdtsui Date: Wed, 2 Aug 2017 23:54:21 -0700 Subject: Isolate routing logic for isUnlocked, remove stray logs --- ui/app/components/tx-view.js | 1 - ui/app/components/wallet-view.js | 2 -- 2 files changed, 3 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index dc86e7ea8..c0e40e9b4 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -51,7 +51,6 @@ TxView.prototype.render = function () { }, [ h('div.phone-visible.fa.fa-bars', { onClick: () => { - console.log("click received") this.props.sidebarOpen ? this.props.hideSidebar() : this.props.showSidebar() } }, [ diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 8fd555ccb..4d1ac1a49 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -46,7 +46,6 @@ WalletView.prototype.render = function () { h('div.phone-visible.fa.fa-bars', { onClick: () => { - console.log("click received-inwalletview") this.props.hideSidebar() } }, [ @@ -128,7 +127,6 @@ WalletView.prototype.render = function () { }, 'BUY'), h('div.wallet-btn', { onClick: () => { - console.log("SHOW"); this.props.showSendPage(); }, style: { -- cgit v1.2.3 From 267d12646c93931c76a1c0fa1ccabd61f8e0dcd6 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Thu, 3 Aug 2017 00:43:24 -0700 Subject: Implement 'clear buttons' for tx view --- ui/app/components/tx-view.js | 38 +++++++++++++++++++++++++++++++++ ui/app/components/wallet-view.js | 45 ---------------------------------------- 2 files changed, 38 insertions(+), 45 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index c0e40e9b4..b2799a65f 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -56,6 +56,44 @@ TxView.prototype.render = function () { }, [ ]), + h('div.flex-row.flex-wrap', { + style: { + margin: '1.8em 1.3em 0.8em 1.3em', + flex: '1 0 auto', + } + }, [ + + h('div.flex-column.flex-center', { + style: { + width: '100%', + } + }, [ + + h('div', {}, 'ETH LOGO'), + + h('div', {}, '1001.124 ETH'), + + h('div', {}, '$300,000 USD'), + + ]), + + h('div.flex-row.flex-center', { + style: { + width: '100%', + } + }, [ + h('button.btn-clear', { + textAlign: 'center' + }, 'BUY'), + + h('button.btn-clear', { + textAlign: 'center' + }, 'SEND'), + + ]), + + ]), + h('div.flex-row', { style: { margin: '1.8em 1.3em 0.8em 1.3em', diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 4d1ac1a49..d57ab39d9 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -96,51 +96,6 @@ WalletView.prototype.render = function () { active: true, }), - // Buy Buttons - // for index.css - // TODO: move into a class - // div.wallet-btn { - // border: 1px solid rgb(91, 93, 103); - // border-radius: 2px; - // height: 30px; - // width: 75px; - // font-size: 0.8em; - // text-align: center; - // line-height: 25px; - // } - - h('div.flex-row', { - style: { - marginLeft: '1.3em', - marginTop: '0.8em', - } - }, [ - h('div', { - style: { - border: '1px solid rgb(91, 93, 103)', - borderRadius: '2px', - height: '20px', - width: '50px', - fontSize: '0.8em', - textAlign: 'center', - } - }, 'BUY'), - h('div.wallet-btn', { - onClick: () => { - this.props.showSendPage(); - }, - style: { - border: '1px solid rgb(91, 93, 103)', - borderRadius: '2px', - height: '20px', - width: '50px', - fontSize: '0.8em', - textAlign: 'center', - marginLeft: '.6em', - } - }, 'SEND'), - ]), - // Wallet contents h(Content, { title: "Total Token Balance", -- cgit v1.2.3 From 0171918407a1c04b8c04bb05f678b04acb4f53b0 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Thu, 3 Aug 2017 01:17:27 -0700 Subject: Add rough layout for flat layout tx details, add notes for breakpoints --- ui/app/components/tx-view.js | 59 +++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 20 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index b2799a65f..dc9a7985f 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -56,42 +56,61 @@ TxView.prototype.render = function () { }, [ ]), - h('div.flex-row.flex-wrap', { + h('div.flex-row', { style: { margin: '1.8em 1.3em 0.8em 1.3em', - flex: '1 0 auto', + // flex: '1 0 520px', } }, [ - h('div.flex-column.flex-center', { + // laptop: flex-row + // mobile: flex-column + h('div.flex-row.flex-center', { style: { - width: '100%', } }, [ - h('div', {}, 'ETH LOGO'), - - h('div', {}, '1001.124 ETH'), + // laptop: 50px 50px + // mobile: 100px 100px + h('img', { + src: '../images/eth_logo.svg', + width: '50px', + height: '50px', + style: { + borderRadius: '25px', + border: '1px solid', + } + }), - h('div', {}, '$300,000 USD'), + // laptop: 5vw? + // phone: 50vw? + h('div.flex-column.flex-center', { + style: {} + }, [ + h('div', {}, '1001.124 ETH'), - ]), + h('div', {}, '$300,000 USD'), + ]), - h('div.flex-row.flex-center', { - style: { - width: '100%', - } - }, [ - h('button.btn-clear', { - textAlign: 'center' - }, 'BUY'), + // laptop: 10vw? + // phone: 75vw? + h('div.flex-row.flex-center', { + style: { + width: '100%', + } + }, [ + h('button.btn-clear', { + textAlign: 'center' + }, 'BUY'), - h('button.btn-clear', { - textAlign: 'center' - }, 'SEND'), + h('button.btn-clear', { + textAlign: 'center' + }, 'SEND'), + ]), ]), + ]), h('div.flex-row', { -- cgit v1.2.3 From 966b25573b04cc9562ba7eb5d345cf48789ddfd9 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 6 Aug 2017 14:03:44 -0700 Subject: Move remaining debug, fonts, reset, and transitions into inverted triangle --- ui/app/components/tx-view.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index dc9a7985f..36c22897e 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -100,11 +100,15 @@ TxView.prototype.render = function () { } }, [ h('button.btn-clear', { - textAlign: 'center' + style: { + textAlign: 'center', + }, }, 'BUY'), h('button.btn-clear', { - textAlign: 'center' + style: { + textAlign: 'center', + }, }, 'SEND'), ]), -- cgit v1.2.3 From 17de77f24a11bfcd26f8472628d6ead28ce8dced Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 6 Aug 2017 14:55:28 -0700 Subject: Position account display and burger in mobile tx view --- ui/app/components/tx-view.js | 47 +++++++++++++++++++++++++++++++++++----- ui/app/components/wallet-view.js | 2 +- 2 files changed, 42 insertions(+), 7 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 36c22897e..75c8a2c11 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -7,7 +7,7 @@ const actions = require('../actions') const SlideoutMenu = require('react-burger-menu').slide const WalletView = require('./wallet-view') -// const Identicon = require('./identicon') +const Identicon = require('./identicon') // const AccountDropdowns = require('./account-dropdowns').AccountDropdowns // const Content = require('./wallet-content-display') @@ -41,6 +41,8 @@ function TxView () { } TxView.prototype.render = function () { + const selected = '0x82df11beb942BEeeD58d466fCb0F0791365C7684' // TODO: remove fake address + return h('div.tx-view.flex-column', { style: { flexGrow: 2, @@ -49,16 +51,49 @@ TxView.prototype.render = function () { background: '#FFFFFF', } }, [ - h('div.phone-visible.fa.fa-bars', { - onClick: () => { - this.props.sidebarOpen ? this.props.hideSidebar() : this.props.showSidebar() + + h('div.flex-row.phone-visible', { + style: { + margin: '1em 0.9em', + alignItems: 'center' } }, [ + // burger + h('div.fa.fa-bars', { + style: { + fontSize: '1.3em', + }, + onClick: () => { + this.props.sidebarOpen ? this.props.hideSidebar() : this.props.showSidebar() + } + }, []), + + //account display + h('.identicon-wrapper.select-none', { + style: { + marginLeft: '0.9em', + }, + }, [ + h(Identicon, { + diameter: 24, + address: selected, + }), + ]), + + h('span', { + style: { + fontSize: '1.2em', + marginLeft: '0.5em', // TODO: switch all units for this component to em + } + }, [ + 'Account 1' + ]), + ]), h('div.flex-row', { style: { - margin: '1.8em 1.3em 0.8em 1.3em', + margin: '1.8em 0.9em 0.8em 0.9em', // flex: '1 0 520px', } }, [ @@ -119,7 +154,7 @@ TxView.prototype.render = function () { h('div.flex-row', { style: { - margin: '1.8em 1.3em 0.8em 1.3em', + margin: '1.8em 0.9em 0.8em 0.9em', } }, [ diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index d57ab39d9..2518a1213 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -31,7 +31,7 @@ function WalletView () { const noop = () => {} WalletView.prototype.render = function () { - const selected = '0x82df11beb942BEeeD58d466fCb0F0791365C7684' + const selected = '0x82df11beb942BEeeD58d466fCb0F0791365C7684' // TODO: remove fake address const { network, responsiveDisplayClassname, style } = this.props return h('div.wallet-view.flex-column' + (responsiveDisplayClassname || ''), { -- cgit v1.2.3 From 802c29c98642043cf679eb2658934e0420f8ecc7 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 6 Aug 2017 15:46:55 -0700 Subject: Implement hero balance UI, mobile --- ui/app/components/tx-view.js | 89 +++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 51 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 75c8a2c11..77ca87834 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -91,65 +91,52 @@ TxView.prototype.render = function () { ]), - h('div.flex-row', { - style: { - margin: '1.8em 0.9em 0.8em 0.9em', - // flex: '1 0 520px', - } + // laptop: flex-row, flex-center + // mobile: flex-column + h('div.hero-balance', { + style: {}, }, [ - // laptop: flex-row - // mobile: flex-column - h('div.flex-row.flex-center', { - style: { - } - }, [ - - // laptop: 50px 50px - // mobile: 100px 100px - h('img', { - src: '../images/eth_logo.svg', - width: '50px', - height: '50px', - style: { - borderRadius: '25px', - border: '1px solid', - } - }), - - // laptop: 5vw? - // phone: 50vw? - h('div.flex-column.flex-center', { + // laptop: 50px 50px + // mobile: 100px 100px + h('img.hero-balance-icon', { + src: '../images/eth_logo.svg', + width: '60px', + height: '60px', + style: {} + }), + + // laptop: 5vw? + // phone: 50vw? + h('div.hero-balance-display', {}, [ + h('div.token-amount', { style: {} - }, [ - h('div', {}, '1001.124 ETH'), + }, '1001.124 ETH'), - h('div', {}, '$300,000 USD'), - ]), + h('div.fiat-amount', { + style: {} + }, '$300,000 USD'), + ]), - // laptop: 10vw? - // phone: 75vw? - h('div.flex-row.flex-center', { + // laptop: 10vw? + // phone: 75vw? + h('div.flex-row.flex-center.hero-balance-buttons', { + style: {} + }, [ + h('button.btn-clear', { style: { - width: '100%', - } - }, [ - h('button.btn-clear', { - style: { - textAlign: 'center', - }, - }, 'BUY'), - - h('button.btn-clear', { - style: { - textAlign: 'center', - }, - }, 'SEND'), - - ]), - ]), + textAlign: 'center', + }, + }, 'BUY'), + h('button.btn-clear', { + style: { + textAlign: 'center', + marginLeft: '1.4em', + }, + }, 'SEND'), + ]), ]), h('div.flex-row', { -- cgit v1.2.3 From c1b85179590e824e9af93da5c1c67ef3a5eb1d06 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 6 Aug 2017 16:37:41 -0700 Subject: Normalize sidebar dimensions and adjust hero button responsiveness --- ui/app/components/tx-view.js | 4 +--- ui/app/components/wallet-view.js | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 77ca87834..3652a43a6 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -45,9 +45,7 @@ TxView.prototype.render = function () { return h('div.tx-view.flex-column', { style: { - flexGrow: 2, - flexShrink: 0, - flexBasis: '230px', + flex: '62 0 62%', background: '#FFFFFF', } }, [ diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 2518a1213..e0bc34b49 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -36,9 +36,7 @@ WalletView.prototype.render = function () { return h('div.wallet-view.flex-column' + (responsiveDisplayClassname || ''), { style: { - flexGrow: 1, - flexShrink: 0, - flexBasis: '230px', // .333*345 + flex: '28 0 28%', background: '#FAFAFA', // TODO: add to reusable colors ...style, } -- cgit v1.2.3 From dc0f78c1b986a57313d465fd352235eb36bbe828 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 6 Aug 2017 16:58:45 -0700 Subject: Fix font size of eth display for 576-780px vw --- ui/app/components/tx-view.js | 2 -- 1 file changed, 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 3652a43a6..193abe8dc 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -99,8 +99,6 @@ TxView.prototype.render = function () { // mobile: 100px 100px h('img.hero-balance-icon', { src: '../images/eth_logo.svg', - width: '60px', - height: '60px', style: {} }), -- cgit v1.2.3 From 403d9c52b506e31fa31b385b61fd167f81b5ff88 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 6 Aug 2017 18:06:23 -0700 Subject: Add fine css tweaks to hero balance - laptop --- ui/app/components/tx-view.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 193abe8dc..164684821 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -104,7 +104,7 @@ TxView.prototype.render = function () { // laptop: 5vw? // phone: 50vw? - h('div.hero-balance-display', {}, [ + h('div.flex-column.hero-balance-display', {}, [ h('div.token-amount', { style: {} }, '1001.124 ETH'), -- cgit v1.2.3 From a7017b824d108bbf81b8dbc994d451829c2413db Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 6 Aug 2017 18:50:23 -0700 Subject: Refactor app-header css, including box shadow and z-index --- ui/app/components/network.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/network.js b/ui/app/components/network.js index 698a0bbb9..ba1d0ea11 100644 --- a/ui/app/components/network.js +++ b/ui/app/components/network.js @@ -60,7 +60,7 @@ Network.prototype.render = function () { } return ( - h('#network_component.pointer', { + h('.network-component.pointer', { title: hoverText, onClick: (event) => this.props.onClick(event), }, [ -- cgit v1.2.3 From 850d2124c81ee81b98f23be1f49db13ca5e8aa27 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 6 Aug 2017 19:26:52 -0700 Subject: Refactor account name css - mobile views --- ui/app/components/tx-view.js | 7 ++----- ui/app/components/wallet-view.js | 7 ++----- 2 files changed, 4 insertions(+), 10 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 164684821..ed8f05e95 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -78,11 +78,8 @@ TxView.prototype.render = function () { }), ]), - h('span', { - style: { - fontSize: '1.2em', - marginLeft: '0.5em', // TODO: switch all units for this component to em - } + h('span.account-name', { + style: {} }, [ 'Account 1' ]), diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index e0bc34b49..9b27f1cca 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -63,11 +63,8 @@ WalletView.prototype.render = function () { }), ]), - h('span', { - style: { - fontSize: '1.2em', - marginLeft: '0.6em', // TODO: switch all units for this component to em - } + h('span.account-name', { + style: {} }, [ 'Account 1' ]), -- cgit v1.2.3 From b3d7abd5d4c0900ce7646519174891b6a51a6ac7 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 6 Aug 2017 19:29:51 -0700 Subject: Allow clicks on account view to enable sidebar, not just burger --- ui/app/components/tx-view.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index ed8f05e95..2bc6daae5 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -54,16 +54,16 @@ TxView.prototype.render = function () { style: { margin: '1em 0.9em', alignItems: 'center' - } + }, + onClick: () => { + this.props.sidebarOpen ? this.props.hideSidebar() : this.props.showSidebar() + }, }, [ // burger h('div.fa.fa-bars', { style: { fontSize: '1.3em', }, - onClick: () => { - this.props.sidebarOpen ? this.props.hideSidebar() : this.props.showSidebar() - } }, []), //account display -- cgit v1.2.3 From fd36d95c506db55afa33a251c6c187c194a55854 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 6 Aug 2017 19:50:14 -0700 Subject: Cleanup before rebase on NewUI - need new version of AccountDropdowns --- ui/app/components/wallet-view.js | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 9b27f1cca..cb1448598 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -42,18 +42,9 @@ WalletView.prototype.render = function () { } }, [ - h('div.phone-visible.fa.fa-bars', { - onClick: () => { - this.props.hideSidebar() - } - }, [ - ]), - // TODO: Separate component: wallet account details - h('div.flex-row.flex-center', { - style: { - margin: '1.8em 1.3em', - } + h('div.flex-column', { + style: {} }, [ h('.identicon-wrapper.select-none', [ -- cgit v1.2.3 From 29662ff7b48c9cc8fc68cae6ba1e5a1f81ddf1c0 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 6 Aug 2017 20:47:59 -0700 Subject: Move tx and wallet view styles to component classes --- ui/app/components/tx-view.js | 5 +---- ui/app/components/wallet-view.js | 6 +----- 2 files changed, 2 insertions(+), 9 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 6b8e9e4dd..97b9a89f4 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -43,10 +43,7 @@ TxView.prototype.render = function () { const selected = '0x82df11beb942BEeeD58d466fCb0F0791365C7684' // TODO: remove fake address return h('div.tx-view.flex-column', { - style: { - flex: '62 0 62%', - background: '#FFFFFF', - } + style: {}, }, [ h('div.flex-row.phone-visible', { diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index cb1448598..1c7330193 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -35,11 +35,7 @@ WalletView.prototype.render = function () { const { network, responsiveDisplayClassname, style } = this.props return h('div.wallet-view.flex-column' + (responsiveDisplayClassname || ''), { - style: { - flex: '28 0 28%', - background: '#FAFAFA', // TODO: add to reusable colors - ...style, - } + style: {}, }, [ // TODO: Separate component: wallet account details -- cgit v1.2.3 From ba50411bb2247d783667142cc5e7efff1bf839de Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 6 Aug 2017 21:54:42 -0700 Subject: Position account icon, name, and caret --- ui/app/components/account-dropdowns.js | 19 +++++----- ui/app/components/wallet-view.js | 64 +++++++++++++++++++++++++++++----- 2 files changed, 64 insertions(+), 19 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/account-dropdowns.js b/ui/app/components/account-dropdowns.js index b23600e9b..3129e0226 100644 --- a/ui/app/components/account-dropdowns.js +++ b/ui/app/components/account-dropdowns.js @@ -218,16 +218,16 @@ class AccountDropdowns extends Component { }, [ enableAccountsSelector && h( - // 'i.fa.fa-angle-down', - 'div.cursor-pointer.color-orange.accounts-selector', + 'i.fa.fa-angle-down', + // 'div.cursor-pointer.color-orange.accounts-selector', { style: { - // fontSize: '1.8em', - background: 'url(images/switch_acc.svg) white center center no-repeat', - height: '25px', - width: '25px', - transform: 'scale(0.75)', - marginRight: '3px', + // fontSize: '135%', + // background: 'url(images/switch_acc.svg) white center center no-repeat', + // height: '25px', + // width: '25px', + // transform: 'scale(0.75)', + // marginRight: '3px', }, onClick: (event) => { event.stopPropagation() @@ -243,8 +243,7 @@ class AccountDropdowns extends Component { 'i.fa.fa-ellipsis-h', { style: { - marginRight: '0.5em', - fontSize: '1.8em', + fontSize: '135%', }, onClick: (event) => { event.stopPropagation() diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 1c7330193..c96819ab9 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -13,6 +13,7 @@ function mapStateToProps (state) { return { network: state.metamask.network, sidebarOpen: state.appState.sidebarOpen, + identities: state.metamask.identities, } } @@ -32,7 +33,7 @@ const noop = () => {} WalletView.prototype.render = function () { const selected = '0x82df11beb942BEeeD58d466fCb0F0791365C7684' // TODO: remove fake address - const { network, responsiveDisplayClassname, style } = this.props + const { network, responsiveDisplayClassname, style, identities } = this.props return h('div.wallet-view.flex-column' + (responsiveDisplayClassname || ''), { style: {}, @@ -43,19 +44,64 @@ WalletView.prototype.render = function () { style: {} }, [ - h('.identicon-wrapper.select-none', [ - h(Identicon, { - diameter: 24, - address: selected, - }), + h('div.flex-row.account-options-menu', { + }, [ + + h(AccountDropdowns, { + // selected, + // network, + // identities: props.identities, + enableAccountOptions: true, + }, []), + ]), - h('span.account-name', { - style: {} + h('div.flex-column.flex-center', { + }, [ - 'Account 1' + + h('.identicon-wrapper.select-none', { + style: { + marginBottom: '1%', + }, + }, [ + h(Identicon, { + diameter: 54, + address: selected, + }), + ]), + + h('span.account-name', { + style: {} + }, [ + 'Account 1' + ]), + + // h(AccountDropdowns, { + // style: { + // // position: 'absolute', + // // left: '58.5%', + // // top: '10.25%', + // }, + // selected, + // network, + // identities, + // enableAccountsSelector: true, + // }, []), + h('div.flex-column.flex-center,', { + style: { + position: 'absolute', + marginLeft: '42px', + marginTop: '-10px', + }, + }, h('i.fa.fa-angle-down', {}, [])), + ]), + // position: absolute; + // left: 58.5%; + // top: 10.25%; + h( AccountDropdowns, { -- cgit v1.2.3 From 0f140c5db59e72836ec437063314b39f33bae100 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 6 Aug 2017 22:30:27 -0700 Subject: Improve positioning of caret and add reusable color for wallet view --- ui/app/components/wallet-view.js | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index c96819ab9..ad84ee6a8 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -57,7 +57,10 @@ WalletView.prototype.render = function () { ]), h('div.flex-column.flex-center', { - + style: { + // constrains size of absolutely positioned wrappers + position: 'relative', + }, }, [ h('.identicon-wrapper.select-none', { @@ -77,31 +80,19 @@ WalletView.prototype.render = function () { 'Account 1' ]), - // h(AccountDropdowns, { - // style: { - // // position: 'absolute', - // // left: '58.5%', - // // top: '10.25%', - // }, - // selected, - // network, - // identities, - // enableAccountsSelector: true, - // }, []), - h('div.flex-column.flex-center,', { + h(AccountDropdowns, { style: { position: 'absolute', - marginLeft: '42px', - marginTop: '-10px', + left: '66.5%', + top: '19.5%', }, - }, h('i.fa.fa-angle-down', {}, [])), - + selected, + network, + identities, + enableAccountsSelector: true, + }, []), ]), - // position: absolute; - // left: 58.5%; - // top: 10.25%; - h( AccountDropdowns, { -- cgit v1.2.3 From d8fff0fc8c25d1bd0a287502ca633a44a7844911 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 6 Aug 2017 23:12:40 -0700 Subject: Opt for calculated values in absolutely positioned caret --- ui/app/components/wallet-view.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index ad84ee6a8..3c331a100 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -58,7 +58,7 @@ WalletView.prototype.render = function () { h('div.flex-column.flex-center', { style: { - // constrains size of absolutely positioned wrappers + // constrains size of absolutely positioned wrappers position: 'relative', }, }, [ @@ -83,7 +83,10 @@ WalletView.prototype.render = function () { h(AccountDropdowns, { style: { position: 'absolute', - left: '66.5%', + left: 'calc(50% + 28px + 5.5px)', + // left: '42px', + // top: '-10px' + // left: '66.5%', top: '19.5%', }, selected, -- cgit v1.2.3 From e8ade42f2aa3af6e0091e939beef3fdf769a2606 Mon Sep 17 00:00:00 2001 From: Simon Liang Date: Tue, 8 Aug 2017 16:49:45 +0800 Subject: extracted balance component and renders to the format, also wired in the account name --- ui/app/components/balance-component.js | 89 ++++++++++++++++++++++++++++++++++ ui/app/components/tx-view.js | 49 ++++++++++--------- 2 files changed, 115 insertions(+), 23 deletions(-) create mode 100644 ui/app/components/balance-component.js (limited to 'ui/app/components') diff --git a/ui/app/components/balance-component.js b/ui/app/components/balance-component.js new file mode 100644 index 000000000..62024895b --- /dev/null +++ b/ui/app/components/balance-component.js @@ -0,0 +1,89 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits + +const { formatBalance, generateBalanceObject } = require('../util') + +module.exports = BalanceComponent + +inherits(BalanceComponent, Component) +function BalanceComponent () { + Component.call(this) +} + +BalanceComponent.prototype.render = function () { + const props = this.props + const { balanceValue } = props + const needsParse = 'needsParse' in props ? props.needsParse : true + const formattedBalance = balanceValue ? formatBalance(balanceValue, 6, needsParse) : '...' + + return h('div.balance-container', {}, [ + // laptop: 50px 50px + // mobile: 100px 100px + + // TODO: balance icon needs to be passed in + h('img.balance-icon', { + src: '../images/eth_logo.svg', + style: {}, + }), + + this.renderBalance(formattedBalance), + ]) +} + +BalanceComponent.prototype.renderBalance = function (formattedBalance) { + const props = this.props + const { shorten } = props + const showFiat = 'showFiat' in props ? props.showFiat : true + + if (formattedBalance === 'None' || formattedBalance === '...') { + return h('div.flex-column.balance-display', {}, [ + h('div.token-amount', { + style: {}, + }, formattedBalance), + ]) + } + + var balanceObj = generateBalanceObject(formattedBalance, shorten ? 1 : 3) + var balanceValue = shorten ? balanceObj.shortBalance : balanceObj.balance + + var label = balanceObj.label + + // laptop: 5vw? + // phone: 50vw? + return h('div.flex-column.balance-display', {}, [ + h('div.token-amount', { + style: {}, + }, `${balanceValue} ${label}`), + + showFiat ? this.renderFiatValue(formattedBalance) : null, + ]) +} + +BalanceComponent.prototype.renderFiatValue = function (formattedBalance) { + + const props = this.props + const { conversionRate, currentCurrency } = props + + if (formattedBalance === 'None') return formattedBalance + var fiatDisplayNumber + var splitBalance = formattedBalance.split(' ') + + if (conversionRate !== 0) { + fiatDisplayNumber = (Number(splitBalance[0]) * conversionRate).toFixed(2) + } else { + fiatDisplayNumber = 'N/A' + } + + return fiatDisplay(fiatDisplayNumber, currentCurrency) +} + +function fiatDisplay (fiatDisplayNumber, fiatSuffix) { + if (fiatDisplayNumber !== 'N/A') { + return h('div.fiat-amount', { + style: {}, + }, `${fiatDisplayNumber} ${fiatSuffix}`) + } else { + return h('div') + } +} diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 97b9a89f4..d0337fcb1 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -1,11 +1,15 @@ const Component = require('react').Component const connect = require('react-redux').connect const h = require('react-hyperscript') +const ethUtil = require('ethereumjs-util') const inherits = require('util').inherits const actions = require('../actions') // slideout menu const WalletView = require('./wallet-view') +// balance component +const BalanceComponent = require('./balance-component') + const Identicon = require('./identicon') // const AccountDropdowns = require('./account-dropdowns').AccountDropdowns // const Content = require('./wallet-content-display') @@ -15,13 +19,18 @@ module.exports = connect(mapStateToProps, mapDispatchToProps)(TxView) function mapStateToProps (state) { return { sidebarOpen: state.appState.sidebarOpen, + identities: state.metamask.identities, + accounts: state.metamask.accounts, + address: state.metamask.selectedAddress, + conversionRate: state.metamask.conversionRate, + currentCurrency: state.metamask.currentCurrency, } } function mapDispatchToProps (dispatch) { return { - showSidebar: () => {dispatch(actions.showSidebar())}, - hideSidebar: () => {dispatch(actions.hideSidebar())}, + showSidebar: () => { dispatch(actions.showSidebar()) }, + hideSidebar: () => { dispatch(actions.hideSidebar()) }, } } @@ -40,7 +49,13 @@ function TxView () { } TxView.prototype.render = function () { - const selected = '0x82df11beb942BEeeD58d466fCb0F0791365C7684' // TODO: remove fake address + + var props = this.props + var selected = props.address || Object.keys(props.accounts)[0] + var checksumAddress = selected && ethUtil.toChecksumAddress(selected) + var identity = props.identities[selected] + var account = props.accounts[selected] + const { conversionRate, currentCurrency } = props return h('div.tx-view.flex-column', { style: {}, @@ -62,7 +77,7 @@ TxView.prototype.render = function () { }, }, []), - //account display + // account display h('.identicon-wrapper.select-none', { style: { marginLeft: '0.9em', @@ -75,9 +90,9 @@ TxView.prototype.render = function () { ]), h('span.account-name', { - style: {} + style: {}, }, [ - 'Account 1' + identity.name, ]), ]), @@ -88,25 +103,13 @@ TxView.prototype.render = function () { style: {}, }, [ - // laptop: 50px 50px - // mobile: 100px 100px - h('img.hero-balance-icon', { - src: '../images/eth_logo.svg', - style: {} + h(BalanceComponent, { + balanceValue: account && account.balance, + conversionRate, + currentCurrency, + style: {}, }), - // laptop: 5vw? - // phone: 50vw? - h('div.flex-column.hero-balance-display', {}, [ - h('div.token-amount', { - style: {} - }, '1001.124 ETH'), - - h('div.fiat-amount', { - style: {} - }, '$300,000 USD'), - ]), - // laptop: 10vw? // phone: 75vw? h('div.flex-row.flex-center.hero-balance-buttons', { -- cgit v1.2.3 From 0db627d9793d91e2e3000a0650f6659a5d5dd67a Mon Sep 17 00:00:00 2001 From: Simon Liang Date: Tue, 8 Aug 2017 20:15:30 +0800 Subject: refactored and added unit test --- ui/app/components/balance-component.js | 49 ++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 23 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/balance-component.js b/ui/app/components/balance-component.js index 62024895b..47da24c74 100644 --- a/ui/app/components/balance-component.js +++ b/ui/app/components/balance-component.js @@ -44,17 +44,12 @@ BalanceComponent.prototype.renderBalance = function (formattedBalance) { ]) } - var balanceObj = generateBalanceObject(formattedBalance, shorten ? 1 : 3) - var balanceValue = shorten ? balanceObj.shortBalance : balanceObj.balance - - var label = balanceObj.label - // laptop: 5vw? // phone: 50vw? return h('div.flex-column.balance-display', {}, [ h('div.token-amount', { style: {}, - }, `${balanceValue} ${label}`), + }, this.getTokenBalance(formattedBalance, shorten)), showFiat ? this.renderFiatValue(formattedBalance) : null, ]) @@ -65,25 +60,33 @@ BalanceComponent.prototype.renderFiatValue = function (formattedBalance) { const props = this.props const { conversionRate, currentCurrency } = props - if (formattedBalance === 'None') return formattedBalance - var fiatDisplayNumber - var splitBalance = formattedBalance.split(' ') + const fiatDisplayNumber = this.getFiatDisplayNumber(formattedBalance, conversionRate) - if (conversionRate !== 0) { - fiatDisplayNumber = (Number(splitBalance[0]) * conversionRate).toFixed(2) - } else { - fiatDisplayNumber = 'N/A' - } + return this.renderFiatAmount(fiatDisplayNumber, currentCurrency) +} + +BalanceComponent.prototype.renderFiatAmount = function (fiatDisplayNumber, fiatSuffix) { + if (fiatDisplayNumber === 'N/A') return null - return fiatDisplay(fiatDisplayNumber, currentCurrency) + return h('div.fiat-amount', { + style: {}, + }, `${fiatDisplayNumber} ${fiatSuffix}`) } -function fiatDisplay (fiatDisplayNumber, fiatSuffix) { - if (fiatDisplayNumber !== 'N/A') { - return h('div.fiat-amount', { - style: {}, - }, `${fiatDisplayNumber} ${fiatSuffix}`) - } else { - return h('div') - } +BalanceComponent.prototype.getTokenBalance = function (formattedBalance, shorten) { + const balanceObj = generateBalanceObject(formattedBalance, shorten ? 1 : 3) + + const balanceValue = shorten ? balanceObj.shortBalance : balanceObj.balance + const label = balanceObj.label + + return `${balanceValue} ${label}` +} + +BalanceComponent.prototype.getFiatDisplayNumber = function (formattedBalance, conversionRate) { + if (formattedBalance === 'None') return formattedBalance + if (conversionRate === 0) return 'N/A' + + const splitBalance = formattedBalance.split(' ') + + return (Number(splitBalance[0]) * conversionRate).toFixed(2) } -- cgit v1.2.3 From f72f57dc6c75f6c0abfd90765073e41487f6f584 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Tue, 8 Aug 2017 13:37:41 -0700 Subject: Implement global modal --- ui/app/components/modal.js | 75 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 ui/app/components/modal.js (limited to 'ui/app/components') diff --git a/ui/app/components/modal.js b/ui/app/components/modal.js new file mode 100644 index 000000000..5bbc86ff5 --- /dev/null +++ b/ui/app/components/modal.js @@ -0,0 +1,75 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const connect = require('react-redux').connect +// const elementType = require('react-prop-types/lib/elementType') +// const PropTypes from 'prop-types' +const FadeModal = require('boron').FadeModal +const actions = require('../actions') + +function mapStateToProps (state) { + return { + active: state.appState.modalOpen + } +} + +function mapDispatchToProps (dispatch) { + return { + hideModal: () => { + dispatch(actions.hideModal()) + }, + } +} + +inherits(Modal, Component) +function Modal () { + Component.call(this) +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)(Modal) + +Modal.prototype.render = function () { + + return h(FadeModal, + { + keyboard: false, + onHide: () => {this.onHide()}, + ref: (ref) => { + this.modalRef = ref + }, + }, + this.props.children, + ) +} + +Modal.prototype.componentWillReceiveProps = function(nextProps) { + if (nextProps.active) { + this.show() + } else if (this.props.active) { + this.hide() + } +} + +Modal.prototype.onHide = function() { + if (this.props.onHideCallback) { + this.props.onHideCallback() + } + this.props.hideModal() +} + +Modal.prototype.hide = function() { + this.modalRef.hide() +} + +Modal.prototype.show = function() { + this.modalRef.show() +} + +// Modal.defaultProps = {} + +// Modal.propTypes = { +// active: PropTypes.bool, +// hideModal: PropTypes.func.isRequired, +// component: elementType, +// onHideCallback: PropTypes.func, +// } -- cgit v1.2.3 From 29c8f448ca683f0dbdd2ef046463500121e5e24e Mon Sep 17 00:00:00 2001 From: sdtsui Date: Tue, 8 Aug 2017 13:37:52 -0700 Subject: Hook up global modal to Tx view, Buy button --- ui/app/components/tx-view.js | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index d0337fcb1..9d7bc9138 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -31,6 +31,7 @@ function mapDispatchToProps (dispatch) { return { showSidebar: () => { dispatch(actions.showSidebar()) }, hideSidebar: () => { dispatch(actions.hideSidebar()) }, + showModal: () => { dispatch(actions.showModal()) }, } } @@ -119,6 +120,9 @@ TxView.prototype.render = function () { style: { textAlign: 'center', }, + onClick: () => { + this.props.showModal() + }, }, 'BUY'), h('button.btn-clear', { -- cgit v1.2.3 From 922a272e811ad104c2d7b7d4c0912a4d629ec2e7 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Tue, 8 Aug 2017 14:05:19 -0700 Subject: Add note for responsive modal styles --- ui/app/components/modal.js | 1 + 1 file changed, 1 insertion(+) (limited to 'ui/app/components') diff --git a/ui/app/components/modal.js b/ui/app/components/modal.js index 5bbc86ff5..b008a56d2 100644 --- a/ui/app/components/modal.js +++ b/ui/app/components/modal.js @@ -32,6 +32,7 @@ Modal.prototype.render = function () { return h(FadeModal, { + className: 'modal', keyboard: false, onHide: () => {this.onHide()}, ref: (ref) => { -- cgit v1.2.3 From 928adae1042addb8cf123879dd8ec50928ac456f Mon Sep 17 00:00:00 2001 From: sdtsui Date: Tue, 8 Aug 2017 17:11:25 -0700 Subject: Implement modal content for buy flow - mobile view --- ui/app/components/modal.js | 3 +++ 1 file changed, 3 insertions(+) (limited to 'ui/app/components') diff --git a/ui/app/components/modal.js b/ui/app/components/modal.js index b008a56d2..bcc2ead44 100644 --- a/ui/app/components/modal.js +++ b/ui/app/components/modal.js @@ -38,6 +38,9 @@ Modal.prototype.render = function () { ref: (ref) => { this.modalRef = ref }, + modalStyle: { + width: '95%', + }, }, this.props.children, ) -- cgit v1.2.3 From b97dcf09ac56a2dba30c62c01244100de453a1e2 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Tue, 8 Aug 2017 17:51:06 -0700 Subject: Move inline styles out into explicitly named BEM classes --- ui/app/components/modal.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modal.js b/ui/app/components/modal.js index bcc2ead44..2339ee497 100644 --- a/ui/app/components/modal.js +++ b/ui/app/components/modal.js @@ -1,4 +1,5 @@ const Component = require('react').Component + const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect @@ -6,6 +7,7 @@ const connect = require('react-redux').connect // const PropTypes from 'prop-types' const FadeModal = require('boron').FadeModal const actions = require('../actions') +const isMobileView = require('../../lib/is-mobile-view') function mapStateToProps (state) { return { @@ -30,6 +32,15 @@ module.exports = connect(mapStateToProps, mapDispatchToProps)(Modal) Modal.prototype.render = function () { + const mobileModalStyles = { + width: '95%', + } + + const laptopModalStyles = { + width: '66%', + top: '30%', + } + return h(FadeModal, { className: 'modal', @@ -38,9 +49,7 @@ Modal.prototype.render = function () { ref: (ref) => { this.modalRef = ref }, - modalStyle: { - width: '95%', - }, + modalStyle: isMobileView() ? mobileModalStyles : laptopModalStyles, }, this.props.children, ) -- cgit v1.2.3 From dc702705bff055ecdc67897680a5d345b03a5faa Mon Sep 17 00:00:00 2001 From: sdtsui Date: Tue, 8 Aug 2017 18:34:04 -0700 Subject: Move buy view into its own component - BuyOptions --- ui/app/components/buy-options.js | 70 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 ui/app/components/buy-options.js (limited to 'ui/app/components') diff --git a/ui/app/components/buy-options.js b/ui/app/components/buy-options.js new file mode 100644 index 000000000..c58e508bf --- /dev/null +++ b/ui/app/components/buy-options.js @@ -0,0 +1,70 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const connect = require('react-redux').connect +const actions = require('../actions') + +function mapStateToProps (state) { + return { + network: state.metamask.network, + } +} + +function mapDispatchToProps (dispatch) { + return { + toCoinbase: () => { + dispatch(actions.buyEth({ network: '1', address, amount: 0 })) + }, + } +} + +inherits(BuyOptions, Component) +function BuyOptions () { + Component.call(this) +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)(BuyOptions) + +BuyOptions.prototype.render = function () { + return h('div', {}, [ + h('div.modal-content.transfers-subview', { + + }, [ + h('div.modal-content-title-wrapper.flex-column.flex-center', { + style: {}, + }, [ + h('div.modal-content-title', { + style: {}, + }, 'Transfers'), + h('div', {}, 'How would you like to buy Ether?'), + ]), + + h('div.modal-content-options.flex-column.flex-center', {}, [ + + h('div.modal-content-option', {}, [ + h('div.modal-content-option-title', {}, 'Coinbase'), + h('div.modal-content-option-subtitle', { + onClick: () => { + this.props.toCoinbase() + }, + }, 'Buy with Fiat'), + ]), + + h('div.modal-content-option', {}, [ + h('div.modal-content-option-title', {}, 'Shapeshift'), + h('div.modal-content-option-subtitle', {}, 'Trade any digital asset for any other'), + ]), + + h('div.modal-content-option', {}, [ + h('div.modal-content-option-title', {}, 'Direct Deposit'), + h('div.modal-content-option-subtitle', {}, 'Deposit from another account'), + ]), + + ]), + + h('div.modal-content-footer', { + style: {}, + }, 'Cancel'), + ]) + ]) +} -- cgit v1.2.3 From c8893fb9cac245c7ec22c8a01a12458c56a8e56a Mon Sep 17 00:00:00 2001 From: sdtsui Date: Tue, 8 Aug 2017 18:37:20 -0700 Subject: Hook up 'Buy with Fiat', redirect to Coinbase --- ui/app/components/buy-options.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/buy-options.js b/ui/app/components/buy-options.js index c58e508bf..f0864d087 100644 --- a/ui/app/components/buy-options.js +++ b/ui/app/components/buy-options.js @@ -7,12 +7,13 @@ const actions = require('../actions') function mapStateToProps (state) { return { network: state.metamask.network, + address: state.metamask.selectedAddress, } } function mapDispatchToProps (dispatch) { return { - toCoinbase: () => { + toCoinbase: (address) => { dispatch(actions.buyEth({ network: '1', address, amount: 0 })) }, } @@ -41,13 +42,15 @@ BuyOptions.prototype.render = function () { h('div.modal-content-options.flex-column.flex-center', {}, [ - h('div.modal-content-option', {}, [ + h('div.modal-content-option', { + onClick: () => { + console.log("buy clicked") + const { toCoinbase, address } = this.props + toCoinbase(address) + }, + }, [ h('div.modal-content-option-title', {}, 'Coinbase'), - h('div.modal-content-option-subtitle', { - onClick: () => { - this.props.toCoinbase() - }, - }, 'Buy with Fiat'), + h('div.modal-content-option-subtitle', {}, 'Buy with Fiat'), ]), h('div.modal-content-option', {}, [ -- cgit v1.2.3 From bdf5436c2d26304b226734e4295ee319ed67b954 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Tue, 8 Aug 2017 18:44:20 -0700 Subject: Add minor comments and cleanup for new components --- ui/app/components/buy-options.js | 5 +++-- ui/app/components/modal.js | 23 ++++++++++++----------- 2 files changed, 15 insertions(+), 13 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/buy-options.js b/ui/app/components/buy-options.js index f0864d087..d36328efd 100644 --- a/ui/app/components/buy-options.js +++ b/ui/app/components/buy-options.js @@ -26,10 +26,12 @@ function BuyOptions () { module.exports = connect(mapStateToProps, mapDispatchToProps)(BuyOptions) +// BuyOptions is currently meant to be rendered inside +// It is the only component in this codebase that does so +// It utilizes modal styles BuyOptions.prototype.render = function () { return h('div', {}, [ h('div.modal-content.transfers-subview', { - }, [ h('div.modal-content-title-wrapper.flex-column.flex-center', { style: {}, @@ -44,7 +46,6 @@ BuyOptions.prototype.render = function () { h('div.modal-content-option', { onClick: () => { - console.log("buy clicked") const { toCoinbase, address } = this.props toCoinbase(address) }, diff --git a/ui/app/components/modal.js b/ui/app/components/modal.js index 2339ee497..8bac866a8 100644 --- a/ui/app/components/modal.js +++ b/ui/app/components/modal.js @@ -1,10 +1,7 @@ const Component = require('react').Component - const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect -// const elementType = require('react-prop-types/lib/elementType') -// const PropTypes from 'prop-types' const FadeModal = require('boron').FadeModal const actions = require('../actions') const isMobileView = require('../../lib/is-mobile-view') @@ -30,16 +27,16 @@ function Modal () { module.exports = connect(mapStateToProps, mapDispatchToProps)(Modal) -Modal.prototype.render = function () { +const mobileModalStyles = { + width: '95%', +} - const mobileModalStyles = { - width: '95%', - } +const laptopModalStyles = { + width: '66%', + top: '30%', +} - const laptopModalStyles = { - width: '66%', - top: '30%', - } +Modal.prototype.render = function () { return h(FadeModal, { @@ -78,8 +75,12 @@ Modal.prototype.show = function() { this.modalRef.show() } +// TODO: specify default props and proptypes // Modal.defaultProps = {} +// const elementType = require('react-prop-types/lib/elementType') +// const PropTypes from 'prop-types' + // Modal.propTypes = { // active: PropTypes.bool, // hideModal: PropTypes.func.isRequired, -- cgit v1.2.3 From 67213e75830bf36bd9f4d83ca75eec992786a2c9 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Tue, 8 Aug 2017 18:48:32 -0700 Subject: Add backdrop styles and box shadow to new global modal defaults --- ui/app/components/modal.js | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'ui/app/components') diff --git a/ui/app/components/modal.js b/ui/app/components/modal.js index 8bac866a8..89de1cedb 100644 --- a/ui/app/components/modal.js +++ b/ui/app/components/modal.js @@ -29,11 +29,17 @@ module.exports = connect(mapStateToProps, mapDispatchToProps)(Modal) const mobileModalStyles = { width: '95%', + boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', } const laptopModalStyles = { width: '66%', top: '30%', + boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', +} + +const backdropStyles = { + backgroundColor: 'rgba(245, 245, 245, 0.85)', } Modal.prototype.render = function () { @@ -47,6 +53,7 @@ Modal.prototype.render = function () { this.modalRef = ref }, modalStyle: isMobileView() ? mobileModalStyles : laptopModalStyles, + backdropStyle: backdropStyles, }, this.props.children, ) -- cgit v1.2.3 From 5e9926b0d035a5ba946080e94777ac0bd887d396 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Tue, 8 Aug 2017 19:02:58 -0700 Subject: Fix dropdown z-index value --- ui/app/components/dropdown.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdown.js b/ui/app/components/dropdown.js index 34c7149ee..d9593efe2 100644 --- a/ui/app/components/dropdown.js +++ b/ui/app/components/dropdown.js @@ -22,7 +22,7 @@ class Dropdown extends Component { { useCssTransition, isOpen, - zIndex: 11, + zIndex: 30, onClickOutside, style, innerStyle: innerStyleDefaults, -- cgit v1.2.3 From 231b8a75427e2b14a3ef29fef0bc71c35acd97ee Mon Sep 17 00:00:00 2001 From: sdtsui Date: Wed, 9 Aug 2017 16:03:14 -0700 Subject: Vertically center modal in mobile view - @cjeria --- ui/app/components/modal.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modal.js b/ui/app/components/modal.js index 89de1cedb..bc365c0e9 100644 --- a/ui/app/components/modal.js +++ b/ui/app/components/modal.js @@ -5,6 +5,7 @@ const connect = require('react-redux').connect const FadeModal = require('boron').FadeModal const actions = require('../actions') const isMobileView = require('../../lib/is-mobile-view') +const isPopupOrNotification = require('../../../app/scripts/lib/is-popup-or-notification') function mapStateToProps (state) { return { @@ -29,12 +30,14 @@ module.exports = connect(mapStateToProps, mapDispatchToProps)(Modal) const mobileModalStyles = { width: '95%', + // Used to create matching t/l/r/b space in mobile view. + top: isPopupOrNotification() === 'popup' ? '47vh' : '36.5vh', boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', } const laptopModalStyles = { width: '66%', - top: '30%', + top: 'calc(30% + 10px)', boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', } -- cgit v1.2.3 From 50f8535f7b732879103665ea28fdd79dc7ee01a2 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Wed, 9 Aug 2017 16:27:55 -0700 Subject: Switch buy modal 'cancel' from text to button for accessibility --- ui/app/components/buy-options.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/buy-options.js b/ui/app/components/buy-options.js index d36328efd..7d640c007 100644 --- a/ui/app/components/buy-options.js +++ b/ui/app/components/buy-options.js @@ -16,6 +16,9 @@ function mapDispatchToProps (dispatch) { toCoinbase: (address) => { dispatch(actions.buyEth({ network: '1', address, amount: 0 })) }, + hideModal: () => { + dispatch(actions.hideModal()) + } } } @@ -66,9 +69,12 @@ BuyOptions.prototype.render = function () { ]), - h('div.modal-content-footer', { - style: {}, - }, 'Cancel'), + h('button', { + style: { + background: 'white', + }, + onClick: () => { this.props.hideModal() }, + }, h('div.modal-content-footer#modal-content-footer-text',{}, 'Cancel')), ]) ]) } -- cgit v1.2.3 From 5f74564debd0f7e498d632f6a8120d46994c7c57 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Wed, 9 Aug 2017 16:32:46 -0700 Subject: Adjust modal styles to match new modal size, from cancel button tweak --- ui/app/components/modal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modal.js b/ui/app/components/modal.js index bc365c0e9..010122d42 100644 --- a/ui/app/components/modal.js +++ b/ui/app/components/modal.js @@ -31,7 +31,7 @@ module.exports = connect(mapStateToProps, mapDispatchToProps)(Modal) const mobileModalStyles = { width: '95%', // Used to create matching t/l/r/b space in mobile view. - top: isPopupOrNotification() === 'popup' ? '47vh' : '36.5vh', + top: isPopupOrNotification() === 'popup' ? '48vh' : '36.5vh', boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', } -- cgit v1.2.3 From 779be75370e10ea9b248686790127200badc3f65 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Wed, 9 Aug 2017 21:40:21 -0700 Subject: [WIP] Position account potions dropdown correctly and hook up to action creators --- ui/app/components/account-dropdowns.js | 61 +++++++++++++++++++++++++--------- ui/app/components/dropdown.js | 3 +- ui/app/components/wallet-view.js | 51 ++++++++++++++-------------- 3 files changed, 73 insertions(+), 42 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/account-dropdowns.js b/ui/app/components/account-dropdowns.js index 3129e0226..3f1b0ee53 100644 --- a/ui/app/components/account-dropdowns.js +++ b/ui/app/components/account-dropdowns.js @@ -22,7 +22,7 @@ class AccountDropdowns extends Component { } renderAccounts () { - const { identities, selected } = this.props + const { identities, selected, menuItemStyles, dropdownWrapperStyle } = this.props return Object.keys(identities).map((key, index) => { const identity = identities[key] @@ -35,10 +35,13 @@ class AccountDropdowns extends Component { onClick: () => { this.props.actions.showAccountDetail(identity.address) }, - style: { - marginTop: index === 0 ? '5px' : '', - fontSize: '24px', - }, + style: Object.assign( + { + marginTop: index === 0 ? '5px' : '', + fontSize: '24px', + }, + menuItemStyles, + ), }, [ h( @@ -59,8 +62,8 @@ class AccountDropdowns extends Component { } renderAccountSelector () { - const { actions } = this.props - const { accountSelectorActive } = this.state + const { actions, dropdownWrapperStyle } = this.props + const { accountSelectorActive, menuItemStyles } = this.state return h( Dropdown, @@ -93,6 +96,10 @@ class AccountDropdowns extends Component { { closeMenu: () => {}, onClick: () => actions.addNewAccount(), + style: Object.assign( + {}, + menuItemStyles, + ), }, [ h( @@ -112,6 +119,10 @@ class AccountDropdowns extends Component { { closeMenu: () => {}, onClick: () => actions.showImportPage(), + style: Object.assign( + {}, + menuItemStyles, + ), }, [ h( @@ -137,16 +148,20 @@ class AccountDropdowns extends Component { } renderAccountOptions () { - const { actions } = this.props - const { optionsMenuActive } = this.state + const { actions, dropdownWrapperStyle } = this.props + const { optionsMenuActive, menuItemStyles } = this.state return h( Dropdown, { - style: { - marginLeft: '-215px', - minWidth: '180px', - }, + style: Object.assign( + { + marginLeft: '-10px', + position: 'absolute', + width: '29vh', // affects both mobile and laptop views + }, + dropdownWrapperStyle, + ), isOpen: optionsMenuActive, onClickOutside: () => { const { classList } = event.target @@ -166,6 +181,10 @@ class AccountDropdowns extends Component { const url = genAccountLink(selected, network) global.platform.openWindow({ url }) }, + style: Object.assign( + {}, + menuItemStyles, + ), }, 'View account on Etherscan', ), @@ -178,6 +197,10 @@ class AccountDropdowns extends Component { var identity = identities[selected] actions.showQrView(selected, identity ? identity.name : '') }, + style: Object.assign( + {}, + menuItemStyles, + ), }, 'Show QR Code', ), @@ -190,6 +213,10 @@ class AccountDropdowns extends Component { const checkSumAddress = selected && ethUtil.toChecksumAddress(selected) copyToClipboard(checkSumAddress) }, + style: Object.assign( + {}, + menuItemStyles, + ), }, 'Copy Address to clipboard', ), @@ -200,6 +227,10 @@ class AccountDropdowns extends Component { onClick: () => { actions.requestAccountExport() }, + style: Object.assign( + {}, + menuItemStyles, + ), }, 'Export Private Key', ), @@ -208,7 +239,7 @@ class AccountDropdowns extends Component { } render () { - const { style, enableAccountsSelector, enableAccountOptions } = this.props + const { style, enableAccountsSelector, enableAccountOptions, dropdownWrapperStyle } = this.props const { optionsMenuActive, accountSelectorActive } = this.state return h( @@ -267,7 +298,7 @@ AccountDropdowns.defaultProps = { AccountDropdowns.propTypes = { identities: PropTypes.objectOf(PropTypes.object), - selected: PropTypes.string, + selected: PropTypes.string, // TODO: refactor to be more explicit: selectedAddress } const mapDispatchToProps = (dispatch) => { diff --git a/ui/app/components/dropdown.js b/ui/app/components/dropdown.js index d9593efe2..07ef75f12 100644 --- a/ui/app/components/dropdown.js +++ b/ui/app/components/dropdown.js @@ -67,7 +67,7 @@ class DropdownMenuItem extends Component { }, style: Object.assign({ listStyle: 'none', - padding: '8px 0px 8px 0px', + padding: '8px 0px', fontSize: '18px', fontStyle: 'normal', fontFamily: 'Montserrat Regular', @@ -75,6 +75,7 @@ class DropdownMenuItem extends Component { display: 'flex', justifyContent: 'flex-start', alignItems: 'center', + color: 'white', }, style), }, children diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 3c331a100..56aac1f13 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -6,14 +6,20 @@ const Identicon = require('./identicon') const AccountDropdowns = require('./account-dropdowns').AccountDropdowns const Content = require('./wallet-content-display') const actions = require('../actions') +const selectors = require('../selectors') module.exports = connect(mapStateToProps, mapDispatchToProps)(WalletView) function mapStateToProps (state) { + return { network: state.metamask.network, sidebarOpen: state.appState.sidebarOpen, identities: state.metamask.identities, + accounts: state.metamask.accounts, + selectedAddress: selectors.getSelectedAddress(state), + selectedIdentity: selectors.getSelectedIdentity(state), + selectedAccount: selectors.getSelectedAccount(state), } } @@ -32,8 +38,7 @@ function WalletView () { const noop = () => {} WalletView.prototype.render = function () { - const selected = '0x82df11beb942BEeeD58d466fCb0F0791365C7684' // TODO: remove fake address - const { network, responsiveDisplayClassname, style, identities } = this.props + const { network, responsiveDisplayClassname, style, identities, selectedAddress } = this.props return h('div.wallet-view.flex-column' + (responsiveDisplayClassname || ''), { style: {}, @@ -45,20 +50,32 @@ WalletView.prototype.render = function () { }, [ h('div.flex-row.account-options-menu', { + style: { + position: 'relative', + }, }, [ h(AccountDropdowns, { - // selected, - // network, - // identities: props.identities, + selected: selectedAddress, + network, + identities, enableAccountOptions: true, + dropdownWrapperStyle: { + padding: '1px 15px', + marginLeft: '-25px', + position: 'absolute', + width: '122%', //TODO, refactor all of this component out into media queries + }, + menuItemStyles: { + padding: '0px 0px', + margin: '22px 0px', + } }, []), ]), h('div.flex-column.flex-center', { style: { - // constrains size of absolutely positioned wrappers position: 'relative', }, }, [ @@ -70,7 +87,7 @@ WalletView.prototype.render = function () { }, [ h(Identicon, { diameter: 54, - address: selected, + address: selectedAddress, }), ]), @@ -84,31 +101,14 @@ WalletView.prototype.render = function () { style: { position: 'absolute', left: 'calc(50% + 28px + 5.5px)', - // left: '42px', - // top: '-10px' - // left: '66.5%', top: '19.5%', }, - selected, + selected: selectedAddress, network, identities, enableAccountsSelector: true, }, []), ]), - - h( - AccountDropdowns, - { - style: { - marginLeft: 'auto', - cursor: 'pointer', - }, - selected, - network, // TODO: this prop could be in the account dropdown container - identities: {}, - }, - ), - ]), h(Content, { @@ -128,6 +128,5 @@ WalletView.prototype.render = function () { marginTop: '1.3em', } }) - ]) } -- cgit v1.2.3 From 72df9746faa2d3797c5155162ededa7cb7a5fcb9 Mon Sep 17 00:00:00 2001 From: Simon Liang Date: Wed, 9 Aug 2017 05:36:58 +0800 Subject: removing styling comments --- ui/app/components/balance-component.js | 4 ---- 1 file changed, 4 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/balance-component.js b/ui/app/components/balance-component.js index 47da24c74..250bb6479 100644 --- a/ui/app/components/balance-component.js +++ b/ui/app/components/balance-component.js @@ -18,8 +18,6 @@ BalanceComponent.prototype.render = function () { const formattedBalance = balanceValue ? formatBalance(balanceValue, 6, needsParse) : '...' return h('div.balance-container', {}, [ - // laptop: 50px 50px - // mobile: 100px 100px // TODO: balance icon needs to be passed in h('img.balance-icon', { @@ -44,8 +42,6 @@ BalanceComponent.prototype.renderBalance = function (formattedBalance) { ]) } - // laptop: 5vw? - // phone: 50vw? return h('div.flex-column.balance-display', {}, [ h('div.token-amount', { style: {}, -- cgit v1.2.3 From 9d36b25c5f11fccd0f3517901ff9cfc583cc3816 Mon Sep 17 00:00:00 2001 From: Simon Liang Date: Wed, 9 Aug 2017 18:10:51 +0800 Subject: extracted transaction list --- ui/app/components/tx-list.js | 141 +++++++++++++++++++++++++++++++++++++++++++ ui/app/components/tx-view.js | 112 +++------------------------------- 2 files changed, 151 insertions(+), 102 deletions(-) create mode 100644 ui/app/components/tx-list.js (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js new file mode 100644 index 000000000..8f6f09348 --- /dev/null +++ b/ui/app/components/tx-list.js @@ -0,0 +1,141 @@ +const Component = require('react').Component +const connect = require('react-redux').connect +const h = require('react-hyperscript') +const inherits = require('util').inherits + +const valuesFor = require('../util').valuesFor + +module.exports = connect(mapStateToProps)(TxList) + +function mapStateToProps(state) { + return { + network: state.metamask.network, + unapprovedMsgs: valuesFor(state.metamask.unapprovedMsgs), + shapeShiftTxList: state.metamask.shapeShiftTxList, + transactions: state.metamask.selectedAddressTxList || [], + conversionRate: state.metamask.conversionRate, + } +} + +inherits(TxList, Component) +function TxList () { + Component.call(this) +} + +const contentDivider = h('div', { + style: { + marginLeft: '1.3em', + marginRight: '1.3em', + height:'1px', + background:'#E7E7E7', // TODO: make custom color + }, +}) + +TxList.prototype.render = function () { + + const { transactions, network, unapprovedMsgs, conversionRate } = this.props + + var shapeShiftTxList + if (network === '1') { + shapeShiftTxList = this.props.shapeShiftTxList + } + const txsToRender = !shapeShiftTxList ? transactions.concat(unapprovedMsgs) : transactions.concat(unapprovedMsgs, shapeShiftTxList) + .sort((a, b) => b.time - a.time) + + console.log("transactions to render", txsToRender) + + return h('div.flex-column.tx-list-container', {}, [ + + h('div.flex-row.tx-list', { + style: { + margin: '1.8em 0.9em 0.8em 0.9em', + }, + }, [ + + // tx-view-tab.js + h('div.flex-row', { + }, [ + + h('div', { + style: { + borderBottom: '0.07em solid black', + paddingBottom: '0.015em', + } + }, 'TRANSACTIONS'), + + h('div', { + style: { + marginLeft: '1.25em', + } + }, 'TOKENS'), + + ]), + ]), + + contentDivider, + + this.renderTransactionListItem(), + + contentDivider, + + this.renderTransactionListItem(), + + contentDivider, + + // column + // tab row + // divider + // item + ]) +} + +TxList.prototype.renderTransactionListItem = function () { + return h('div.flex-column', { + style: { + alignItems: 'stretch', + margin: '0.6em 1.3em 0.6em 1.3em', + } + }, [ + + h('div', { + style: { + flexGrow: 1, + marginTop: '0.3em', + } + }, 'Jul 01, 2017'), + + h('div.flex-row', { + style: { + alignItems: 'stretch', + } + }, [ + + h('div', { + style: { + flexGrow: 1, + } + }, 'icon'), + + h('div', { + style: { + flexGrow: 3, + } + }, 'Hash'), + + h('div', { + style: { + flexGrow: 5, + } + }, 'Status'), + + h('div', { + style: { + flexGrow: 2, + } + }, 'Details'), + + ]) + + ]) +} + diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 9d7bc9138..f0a93a2ab 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -10,6 +10,9 @@ const WalletView = require('./wallet-view') // balance component const BalanceComponent = require('./balance-component') +// tx list +const TxList = require('./tx-list') + const Identicon = require('./identicon') // const AccountDropdowns = require('./account-dropdowns').AccountDropdowns // const Content = require('./wallet-content-display') @@ -22,6 +25,8 @@ function mapStateToProps (state) { identities: state.metamask.identities, accounts: state.metamask.accounts, address: state.metamask.selectedAddress, + transactions: state.metamask.selectedAddressTxList || [], + shapeShiftTxList: state.metamask.shapeShiftTxList, conversionRate: state.metamask.conversionRate, currentCurrency: state.metamask.currentCurrency, } @@ -35,15 +40,6 @@ function mapDispatchToProps (dispatch) { } } -const contentDivider = h('div', { - style: { - marginLeft: '1.3em', - marginRight: '1.3em', - height:'1px', - background:'#E7E7E7', // TODO: make custom color - }, -}) - inherits(TxView, Component) function TxView () { Component.call(this) @@ -56,7 +52,9 @@ TxView.prototype.render = function () { var checksumAddress = selected && ethUtil.toChecksumAddress(selected) var identity = props.identities[selected] var account = props.accounts[selected] - const { conversionRate, currentCurrency } = props + const { conversionRate, currentCurrency, transactions } = props + + console.log(transactions) return h('div.tx-view.flex-column', { style: {}, @@ -114,7 +112,7 @@ TxView.prototype.render = function () { // laptop: 10vw? // phone: 75vw? h('div.flex-row.flex-center.hero-balance-buttons', { - style: {} + style: {}, }, [ h('button.btn-clear', { style: { @@ -135,97 +133,7 @@ TxView.prototype.render = function () { ]), ]), - h('div.flex-row', { - style: { - margin: '1.8em 0.9em 0.8em 0.9em', - } - }, [ - - // tx-view-tab.js - h('div.flex-row', { - }, [ - - h('div', { - style: { - borderBottom: '0.07em solid black', - paddingBottom: '0.015em', - } - }, 'TRANSACTIONS'), - - h('div', { - style: { - marginLeft: '1.25em', - } - }, 'TOKENS'), - - ]), - ]), - - contentDivider, - - this.renderTransactionListItem(), - - contentDivider, - - this.renderTransactionListItem(), - - contentDivider, + h(TxList, {}), ]) - // column - // tab row - // divider - // item } - -TxView.prototype.renderTransactionListItem = function () { - return h('div.flex-column', { - style: { - alignItems: 'stretch', - margin: '0.6em 1.3em 0.6em 1.3em', - } - }, [ - - h('div', { - style: { - flexGrow: 1, - marginTop: '0.3em', - } - }, 'Jul 01, 2017'), - - h('div.flex-row', { - style: { - alignItems: 'stretch', - } - }, [ - - h('div', { - style: { - flexGrow: 1, - } - }, 'icon'), - - h('div', { - style: { - flexGrow: 3, - } - }, 'Hash'), - - h('div', { - style: { - flexGrow: 5, - } - }, 'Status'), - - h('div', { - style: { - flexGrow: 2, - } - }, 'Details'), - - ]) - - ]) -} - - -- cgit v1.2.3 From 87cb930130cb43130bf584552451aad4795dd210 Mon Sep 17 00:00:00 2001 From: Simon Liang Date: Thu, 10 Aug 2017 11:06:37 +0800 Subject: moved the props initialization steps into mapStateToProps --- ui/app/components/tx-list.js | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 8f6f09348..8fa712b4a 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -7,12 +7,18 @@ const valuesFor = require('../util').valuesFor module.exports = connect(mapStateToProps)(TxList) -function mapStateToProps(state) { +function mapStateToProps (state) { + const network = state.metamask.network + const unapprovedMsgs = valuesFor(state.metamask.unapprovedMsgs) + + const shapeShiftTxList = (network === '1') ? state.metamask.shapeShiftTxList : undefined + const transactions = state.metamask.selectedAddressTxList || [] + + const txsToRender = !shapeShiftTxList ? transactions.concat(unapprovedMsgs) : transactions.concat(unapprovedMsgs, shapeShiftTxList) + .sort((a, b) => b.time - a.time) + return { - network: state.metamask.network, - unapprovedMsgs: valuesFor(state.metamask.unapprovedMsgs), - shapeShiftTxList: state.metamask.shapeShiftTxList, - transactions: state.metamask.selectedAddressTxList || [], + txsToRender, conversionRate: state.metamask.conversionRate, } } @@ -33,16 +39,9 @@ const contentDivider = h('div', { TxList.prototype.render = function () { - const { transactions, network, unapprovedMsgs, conversionRate } = this.props - - var shapeShiftTxList - if (network === '1') { - shapeShiftTxList = this.props.shapeShiftTxList - } - const txsToRender = !shapeShiftTxList ? transactions.concat(unapprovedMsgs) : transactions.concat(unapprovedMsgs, shapeShiftTxList) - .sort((a, b) => b.time - a.time) + const { txsToRender, conversionRate } = this.props - console.log("transactions to render", txsToRender) + console.log('transactions to render', txsToRender) return h('div.flex-column.tx-list-container', {}, [ -- cgit v1.2.3 From 53c91591b34eea68e0f8b834e33c451ca48d3a7c Mon Sep 17 00:00:00 2001 From: Simon Liang Date: Thu, 10 Aug 2017 11:17:39 +0800 Subject: redid tx-view and balance-component mapStateToProps logic --- ui/app/components/balance-component.js | 13 +++++++++--- ui/app/components/tx-view.js | 37 ++++++++++++++++------------------ 2 files changed, 27 insertions(+), 23 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/balance-component.js b/ui/app/components/balance-component.js index 250bb6479..48efc7b6a 100644 --- a/ui/app/components/balance-component.js +++ b/ui/app/components/balance-component.js @@ -1,10 +1,18 @@ const Component = require('react').Component +const connect = require('react-redux').connect const h = require('react-hyperscript') const inherits = require('util').inherits const { formatBalance, generateBalanceObject } = require('../util') -module.exports = BalanceComponent +module.exports = connect(mapStateToProps)(BalanceComponent) + +function mapStateToProps (state) { + return { + conversionRate: state.metamask.conversionRate, + currentCurrency: state.metamask.currentCurrency, + } +} inherits(BalanceComponent, Component) function BalanceComponent () { @@ -53,8 +61,7 @@ BalanceComponent.prototype.renderBalance = function (formattedBalance) { BalanceComponent.prototype.renderFiatValue = function (formattedBalance) { - const props = this.props - const { conversionRate, currentCurrency } = props + const { conversionRate, currentCurrency } = this.props const fiatDisplayNumber = this.getFiatDisplayNumber(formattedBalance, conversionRate) diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index f0a93a2ab..ba93aae8b 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -20,15 +20,21 @@ const Identicon = require('./identicon') module.exports = connect(mapStateToProps, mapDispatchToProps)(TxView) function mapStateToProps (state) { + const sidebarOpen = state.appState.sidebarOpen + + const identities = state.metamask.identities + const accounts = state.metamask.accounts + const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] + const checksumAddress = selectedAddress && ethUtil.toChecksumAddress(selectedAddress) + const identity = identities[selectedAddress] + const account = accounts[selectedAddress] + return { - sidebarOpen: state.appState.sidebarOpen, - identities: state.metamask.identities, - accounts: state.metamask.accounts, - address: state.metamask.selectedAddress, - transactions: state.metamask.selectedAddressTxList || [], - shapeShiftTxList: state.metamask.shapeShiftTxList, - conversionRate: state.metamask.conversionRate, - currentCurrency: state.metamask.currentCurrency, + sidebarOpen, + selectedAddress, + checksumAddress, + identity, + account, } } @@ -47,14 +53,7 @@ function TxView () { TxView.prototype.render = function () { - var props = this.props - var selected = props.address || Object.keys(props.accounts)[0] - var checksumAddress = selected && ethUtil.toChecksumAddress(selected) - var identity = props.identities[selected] - var account = props.accounts[selected] - const { conversionRate, currentCurrency, transactions } = props - - console.log(transactions) + const { selectedAddress, identity, account } = this.props return h('div.tx-view.flex-column', { style: {}, @@ -63,7 +62,7 @@ TxView.prototype.render = function () { h('div.flex-row.phone-visible', { style: { margin: '1em 0.9em', - alignItems: 'center' + alignItems: 'center', }, onClick: () => { this.props.sidebarOpen ? this.props.hideSidebar() : this.props.showSidebar() @@ -84,7 +83,7 @@ TxView.prototype.render = function () { }, [ h(Identicon, { diameter: 24, - address: selected, + address: selectedAddress, }), ]), @@ -104,8 +103,6 @@ TxView.prototype.render = function () { h(BalanceComponent, { balanceValue: account && account.balance, - conversionRate, - currentCurrency, style: {}, }), -- cgit v1.2.3 From a3f96951c2d6f2c8607e4fa270b5484e838b2e42 Mon Sep 17 00:00:00 2001 From: Simon Liang Date: Thu, 10 Aug 2017 11:34:26 +0800 Subject: connected wallet view dropdown button with real data --- ui/app/components/wallet-view.js | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 56aac1f13..7d4b8cd51 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -11,7 +11,6 @@ const selectors = require('../selectors') module.exports = connect(mapStateToProps, mapDispatchToProps)(WalletView) function mapStateToProps (state) { - return { network: state.metamask.network, sidebarOpen: state.appState.sidebarOpen, @@ -25,8 +24,8 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { - showSendPage: () => {dispatch(actions.showSendPage())}, - hideSidebar: () => {dispatch(actions.hideSidebar())}, + showSendPage: () => { dispatch(actions.showSendPage()) }, + hideSidebar: () => { dispatch(actions.hideSidebar()) }, } } @@ -38,7 +37,7 @@ function WalletView () { const noop = () => {} WalletView.prototype.render = function () { - const { network, responsiveDisplayClassname, style, identities, selectedAddress } = this.props + const { network, responsiveDisplayClassname, style, identities, selectedAddress, selectedIdentity } = this.props return h('div.wallet-view.flex-column' + (responsiveDisplayClassname || ''), { style: {}, @@ -46,7 +45,7 @@ WalletView.prototype.render = function () { // TODO: Separate component: wallet account details h('div.flex-column', { - style: {} + style: {}, }, [ h('div.flex-row.account-options-menu', { @@ -92,9 +91,9 @@ WalletView.prototype.render = function () { ]), h('span.account-name', { - style: {} + style: {}, }, [ - 'Account 1' + selectedIdentity.name, ]), h(AccountDropdowns, { @@ -103,30 +102,31 @@ WalletView.prototype.render = function () { left: 'calc(50% + 28px + 5.5px)', top: '19.5%', }, - selected: selectedAddress, + selectedAddress, network, identities, enableAccountsSelector: true, }, []), ]), + ]), h(Content, { - title: 'Wallet', - amount: '1001.124 ETH', - fiatValue: '$300,000.00 USD', - active: true, + title: 'Wallet', + amount: '1001.124 ETH', + fiatValue: '$300,000.00 USD', + active: true, }), // Wallet contents h(Content, { - title: "Total Token Balance", - amount: "45.439 ETH", - fiatValue: "$13,000.00 USD", + title: 'Total Token Balance', + amount: '45.439 ETH', + fiatValue: '$13,000.00 USD', active: false, style: { marginTop: '1.3em', - } - }) + }, + }), ]) } -- cgit v1.2.3 From 708d8398f41f6bafe1e4678baebd18fb40999fc5 Mon Sep 17 00:00:00 2001 From: Simon Liang Date: Thu, 10 Aug 2017 14:48:05 +0800 Subject: reverted my changes --- ui/app/components/wallet-view.js | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 7d4b8cd51..56aac1f13 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -11,6 +11,7 @@ const selectors = require('../selectors') module.exports = connect(mapStateToProps, mapDispatchToProps)(WalletView) function mapStateToProps (state) { + return { network: state.metamask.network, sidebarOpen: state.appState.sidebarOpen, @@ -24,8 +25,8 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { - showSendPage: () => { dispatch(actions.showSendPage()) }, - hideSidebar: () => { dispatch(actions.hideSidebar()) }, + showSendPage: () => {dispatch(actions.showSendPage())}, + hideSidebar: () => {dispatch(actions.hideSidebar())}, } } @@ -37,7 +38,7 @@ function WalletView () { const noop = () => {} WalletView.prototype.render = function () { - const { network, responsiveDisplayClassname, style, identities, selectedAddress, selectedIdentity } = this.props + const { network, responsiveDisplayClassname, style, identities, selectedAddress } = this.props return h('div.wallet-view.flex-column' + (responsiveDisplayClassname || ''), { style: {}, @@ -45,7 +46,7 @@ WalletView.prototype.render = function () { // TODO: Separate component: wallet account details h('div.flex-column', { - style: {}, + style: {} }, [ h('div.flex-row.account-options-menu', { @@ -91,9 +92,9 @@ WalletView.prototype.render = function () { ]), h('span.account-name', { - style: {}, + style: {} }, [ - selectedIdentity.name, + 'Account 1' ]), h(AccountDropdowns, { @@ -102,31 +103,30 @@ WalletView.prototype.render = function () { left: 'calc(50% + 28px + 5.5px)', top: '19.5%', }, - selectedAddress, + selected: selectedAddress, network, identities, enableAccountsSelector: true, }, []), ]), - ]), h(Content, { - title: 'Wallet', - amount: '1001.124 ETH', - fiatValue: '$300,000.00 USD', - active: true, + title: 'Wallet', + amount: '1001.124 ETH', + fiatValue: '$300,000.00 USD', + active: true, }), // Wallet contents h(Content, { - title: 'Total Token Balance', - amount: '45.439 ETH', - fiatValue: '$13,000.00 USD', + title: "Total Token Balance", + amount: "45.439 ETH", + fiatValue: "$13,000.00 USD", active: false, style: { marginTop: '1.3em', - }, - }), + } + }) ]) } -- cgit v1.2.3 From 95eda70efedd47ac5be8e790d6cf89cb219f4161 Mon Sep 17 00:00:00 2001 From: Simon Liang Date: Thu, 10 Aug 2017 16:52:26 +0800 Subject: added logging for account balance --- ui/app/components/wallet-view.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 56aac1f13..5622505c8 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -38,7 +38,9 @@ function WalletView () { const noop = () => {} WalletView.prototype.render = function () { - const { network, responsiveDisplayClassname, style, identities, selectedAddress } = this.props + const { network, responsiveDisplayClassname, style, identities, selectedAddress, selectedAccount } = this.props + + console.log(selectedAccount) return h('div.wallet-view.flex-column' + (responsiveDisplayClassname || ''), { style: {}, -- cgit v1.2.3 From 96b186dfb2a96561d6a0ba50846cd610c484b688 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Thu, 10 Aug 2017 19:35:10 -0700 Subject: Cleanup txList and txView components --- ui/app/components/tx-list.js | 119 ++++++++++++++++++++++++++++++------------- ui/app/components/tx-view.js | 16 +----- 2 files changed, 87 insertions(+), 48 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 8fa712b4a..368854786 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -2,24 +2,17 @@ const Component = require('react').Component const connect = require('react-redux').connect const h = require('react-hyperscript') const inherits = require('util').inherits +const selectors = require('../selectors') +const Identicon = require('./identicon') const valuesFor = require('../util').valuesFor module.exports = connect(mapStateToProps)(TxList) function mapStateToProps (state) { - const network = state.metamask.network - const unapprovedMsgs = valuesFor(state.metamask.unapprovedMsgs) - - const shapeShiftTxList = (network === '1') ? state.metamask.shapeShiftTxList : undefined - const transactions = state.metamask.selectedAddressTxList || [] - - const txsToRender = !shapeShiftTxList ? transactions.concat(unapprovedMsgs) : transactions.concat(unapprovedMsgs, shapeShiftTxList) - .sort((a, b) => b.time - a.time) - return { - txsToRender, - conversionRate: state.metamask.conversionRate, + txsToRender: selectors.transactionsSelector(state), + conversionRate: selectors.conversionRateSelector(state), } } @@ -56,18 +49,9 @@ TxList.prototype.render = function () { }, [ h('div', { - style: { - borderBottom: '0.07em solid black', - paddingBottom: '0.015em', - } + style: {} }, 'TRANSACTIONS'), - h('div', { - style: { - marginLeft: '1.25em', - } - }, 'TOKENS'), - ]), ]), @@ -77,31 +61,77 @@ TxList.prototype.render = function () { contentDivider, - this.renderTransactionListItem(), + // this.renderTransactionListItem(), - contentDivider, + // contentDivider, + + // this.renderTransactionListItem(), + + // contentDivider, + + // this.renderTransactionListItem(), + + // contentDivider, + + // this.renderTransactionListItem(), + + // contentDivider, + + // this.renderTransactionListItem(), + + // contentDivider, + + // this.renderTransactionListItem(), + + // contentDivider, + + // this.renderTransactionListItem(), + + // contentDivider, + + // this.renderTransactionListItem(), + + // contentDivider, + + // this.renderTransactionListItem(), + + // contentDivider, - // column - // tab row - // divider - // item ]) } TxList.prototype.renderTransactionListItem = function () { + // fake data + const props = { + dateString: 'Jul 01, 2017', + address: '0x82df11beb942beeed58d466fcb0f0791365c7684', + transactionStatus: 'Confirmed', + transactionAmount: '3' + } + + const { address, transactionStatus, transactionAmount, dateString } = props + return h('div.flex-column', { style: { alignItems: 'stretch', + justifyContent: 'flex-start', margin: '0.6em 1.3em 0.6em 1.3em', + overflow: 'none' } }, [ h('div', { style: { flexGrow: 1, + flexShrink: 1, + flexBasis: 'auto', marginTop: '0.3em', } - }, 'Jul 01, 2017'), + }, [ + h('span', {}, [ + dateString, + ]) + ]), h('div.flex-row', { style: { @@ -113,28 +143,49 @@ TxList.prototype.renderTransactionListItem = function () { style: { flexGrow: 1, } - }, 'icon'), + }, [ + h(Identicon, { + address, + diameter: 24, + }) + ]), h('div', { style: { flexGrow: 3, } - }, 'Hash'), + }, [ + h('span', {}, [ + '0x82df11be...7684', //address + ]), + ]), h('div', { style: { flexGrow: 5, } - }, 'Status'), + }, [ + h('span', {}, [ + transactionStatus, + ]), + ]), - h('div', { + h('div.flex-column', { style: { flexGrow: 2, } - }, 'Details'), + }, [ - ]) + h('span', {}, [ + transactionAmount, + ]), + + h('span', {}, [ + '300 USD', + ]), + ]), + ]) ]) } diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index ba93aae8b..0d1f3fc31 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -4,18 +4,11 @@ const h = require('react-hyperscript') const ethUtil = require('ethereumjs-util') const inherits = require('util').inherits const actions = require('../actions') -// slideout menu -const WalletView = require('./wallet-view') -// balance component +const WalletView = require('./wallet-view') const BalanceComponent = require('./balance-component') - -// tx list const TxList = require('./tx-list') - const Identicon = require('./identicon') -// const AccountDropdowns = require('./account-dropdowns').AccountDropdowns -// const Content = require('./wallet-content-display') module.exports = connect(mapStateToProps, mapDispatchToProps)(TxView) @@ -68,14 +61,13 @@ TxView.prototype.render = function () { this.props.sidebarOpen ? this.props.hideSidebar() : this.props.showSidebar() }, }, [ - // burger + h('div.fa.fa-bars', { style: { fontSize: '1.3em', }, }, []), - // account display h('.identicon-wrapper.select-none', { style: { marginLeft: '0.9em', @@ -95,8 +87,6 @@ TxView.prototype.render = function () { ]), - // laptop: flex-row, flex-center - // mobile: flex-column h('div.hero-balance', { style: {}, }, [ @@ -106,8 +96,6 @@ TxView.prototype.render = function () { style: {}, }), - // laptop: 10vw? - // phone: 75vw? h('div.flex-row.flex-center.hero-balance-buttons', { style: {}, }, [ -- cgit v1.2.3 From f9432c59826d95dbdaf70a3da4a8a453137efb11 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Thu, 10 Aug 2017 19:55:01 -0700 Subject: Move Txs list item styles into classes --- ui/app/components/tx-list.js | 54 ++++++++++++++------------------------------ 1 file changed, 17 insertions(+), 37 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 368854786..57d7af4f1 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -111,69 +111,49 @@ TxList.prototype.renderTransactionListItem = function () { const { address, transactionStatus, transactionAmount, dateString } = props - return h('div.flex-column', { - style: { - alignItems: 'stretch', - justifyContent: 'flex-start', - margin: '0.6em 1.3em 0.6em 1.3em', - overflow: 'none' - } + return h('div.flex-column.tx-list-item-wrapper', { + style: {} }, [ - h('div', { - style: { - flexGrow: 1, - flexShrink: 1, - flexBasis: 'auto', - marginTop: '0.3em', - } + h('div.tx-list-date-wrapper', { + style: {} }, [ - h('span', {}, [ + h('span.tx-list-date', {}, [ dateString, ]) ]), - h('div.flex-row', { - style: { - alignItems: 'stretch', - } + h('div.flex-row.tx-list-content-wrapper', { + style: {} }, [ - h('div', { - style: { - flexGrow: 1, - } + h('div.tx-list-identicon-wrapper', { + style: {} }, [ h(Identicon, { address, - diameter: 24, + diameter: 18, }) ]), - h('div', { - style: { - flexGrow: 3, - } + h('div.tx-list-account-wrapper', { + style: {} }, [ h('span', {}, [ '0x82df11be...7684', //address ]), ]), - h('div', { - style: { - flexGrow: 5, - } + h('div.tx-list-status-wrapper', { + style: {} }, [ - h('span', {}, [ + h('span.tx-list-status', {}, [ transactionStatus, ]), ]), - h('div.flex-column', { - style: { - flexGrow: 2, - } + h('div.flex-column.tx-list-details-wrapper', { + style: {} }, [ h('span', {}, [ -- cgit v1.2.3 From e31c2982888fcfef5383124db4ca606644a29044 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Thu, 10 Aug 2017 20:52:22 -0700 Subject: Implement widescreen layout for tx list --- ui/app/components/tx-list.js | 58 +++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 30 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 57d7af4f1..e9f0c1cef 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -21,7 +21,7 @@ function TxList () { Component.call(this) } -const contentDivider = h('div', { +const contentDivider = h('div.tx-list-content-divider', { style: { marginLeft: '1.3em', marginRight: '1.3em', @@ -38,13 +38,10 @@ TxList.prototype.render = function () { return h('div.flex-column.tx-list-container', {}, [ - h('div.flex-row.tx-list', { - style: { - margin: '1.8em 0.9em 0.8em 0.9em', - }, + h('div.flex-row.tx-list-header', { + style: {}, }, [ - // tx-view-tab.js h('div.flex-row', { }, [ @@ -53,6 +50,7 @@ TxList.prototype.render = function () { }, 'TRANSACTIONS'), ]), + ]), contentDivider, @@ -61,41 +59,41 @@ TxList.prototype.render = function () { contentDivider, - // this.renderTransactionListItem(), + this.renderTransactionListItem(), - // contentDivider, + contentDivider, - // this.renderTransactionListItem(), + this.renderTransactionListItem(), - // contentDivider, + contentDivider, - // this.renderTransactionListItem(), + this.renderTransactionListItem(), - // contentDivider, + contentDivider, - // this.renderTransactionListItem(), + this.renderTransactionListItem(), - // contentDivider, + contentDivider, - // this.renderTransactionListItem(), + this.renderTransactionListItem(), - // contentDivider, + contentDivider, - // this.renderTransactionListItem(), + this.renderTransactionListItem(), - // contentDivider, + contentDivider, - // this.renderTransactionListItem(), + this.renderTransactionListItem(), - // contentDivider, + contentDivider, - // this.renderTransactionListItem(), + this.renderTransactionListItem(), - // contentDivider, + contentDivider, - // this.renderTransactionListItem(), + this.renderTransactionListItem(), - // contentDivider, + contentDivider, ]) } @@ -106,7 +104,7 @@ TxList.prototype.renderTransactionListItem = function () { dateString: 'Jul 01, 2017', address: '0x82df11beb942beeed58d466fcb0f0791365c7684', transactionStatus: 'Confirmed', - transactionAmount: '3' + transactionAmount: '+ 3 ETH' } const { address, transactionStatus, transactionAmount, dateString } = props @@ -132,14 +130,14 @@ TxList.prototype.renderTransactionListItem = function () { }, [ h(Identicon, { address, - diameter: 18, + diameter: 24, }) ]), h('div.tx-list-account-wrapper', { style: {} }, [ - h('span', {}, [ + h('span.tx-list-account', {}, [ '0x82df11be...7684', //address ]), ]), @@ -156,12 +154,12 @@ TxList.prototype.renderTransactionListItem = function () { style: {} }, [ - h('span', {}, [ + h('span.tx-list-value', {}, [ transactionAmount, ]), - h('span', {}, [ - '300 USD', + h('span.tx-list-fiat-value', {}, [ + '+ $300 USD', ]), ]), -- cgit v1.2.3 From 7a664a7f720f43679dad6f8857790af84b8b7da6 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Thu, 10 Aug 2017 22:16:42 -0700 Subject: Improve text positioning on mobile view --- ui/app/components/tx-list.js | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index e9f0c1cef..39cf7de79 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -134,19 +134,21 @@ TxList.prototype.renderTransactionListItem = function () { }) ]), - h('div.tx-list-account-wrapper', { - style: {} - }, [ - h('span.tx-list-account', {}, [ - '0x82df11be...7684', //address + h('div.tx-list-account-and-status-wrapper', {}, [ + h('div.tx-list-account-wrapper', { + style: {} + }, [ + h('span.tx-list-account', {}, [ + '0x82df11be...7684', //address + ]), ]), - ]), - h('div.tx-list-status-wrapper', { - style: {} - }, [ - h('span.tx-list-status', {}, [ - transactionStatus, + h('div.tx-list-status-wrapper', { + style: {} + }, [ + h('span.tx-list-status', {}, [ + transactionStatus, + ]), ]), ]), -- cgit v1.2.3 From 58b61eb1fc2d4add59f6225ddf4df09fdfa5b92b Mon Sep 17 00:00:00 2001 From: sdtsui Date: Thu, 10 Aug 2017 22:47:56 -0700 Subject: Add UI tweaks, including separation of overflow logic for mobile (full-height) vs laptop (tx-view-only) --- ui/app/components/tx-list.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 39cf7de79..74d46728c 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -22,12 +22,7 @@ function TxList () { } const contentDivider = h('div.tx-list-content-divider', { - style: { - marginLeft: '1.3em', - marginRight: '1.3em', - height:'1px', - background:'#E7E7E7', // TODO: make custom color - }, + style: {}, }) TxList.prototype.render = function () { @@ -38,11 +33,11 @@ TxList.prototype.render = function () { return h('div.flex-column.tx-list-container', {}, [ - h('div.flex-row.tx-list-header', { + h('div.flex-row.tx-list-header-wrapper', { style: {}, }, [ - h('div.flex-row', { + h('div.flex-row.tx-list-header', { }, [ h('div', { -- cgit v1.2.3 From 0fab1b54820aec01d3b4e7c2c351da57769647ee Mon Sep 17 00:00:00 2001 From: sdtsui Date: Fri, 11 Aug 2017 00:31:06 -0700 Subject: Implement responsive wallet balances --- ui/app/components/wallet-view.js | 146 ++++++++++++++++++++++++++++++++++----- 1 file changed, 129 insertions(+), 17 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 5622505c8..4f6a67994 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('./account-dropdowns').AccountDropdowns const Content = require('./wallet-content-display') const actions = require('../actions') +const BalanceComponent = require('./balance-component') const selectors = require('../selectors') module.exports = connect(mapStateToProps, mapDispatchToProps)(WalletView) @@ -113,22 +114,133 @@ WalletView.prototype.render = function () { ]), ]), - h(Content, { - title: 'Wallet', - amount: '1001.124 ETH', - fiatValue: '$300,000.00 USD', - active: true, - }), - - // Wallet contents - h(Content, { - title: "Total Token Balance", - amount: "45.439 ETH", - fiatValue: "$13,000.00 USD", - active: false, - style: { - marginTop: '1.3em', - } - }) + //'Wallet' - Title + // Not visible on mobile + h('div.flex-column.wallet-view-title-wrapper', {}, [ + h('span.wallet-view-title', {}, [ + 'Wallet', + ]) + ]), + + //Wallet Balances + h('div.flex-column.wallet-balance-wrapper-active', {}, [ + + h('div', {}, [ + + h('div.wallet-balance', {}, [ + + h(BalanceComponent, { + balanceValue: selectedAccount.balance, + style: {}, + }), + + ]), + + ]) + + ]), + + h('div.flex-column', {}, [ + + h('div', {}, [ + + h('div.wallet-balance', {}, [ + + h(BalanceComponent, { + balanceValue: selectedAccount.balance, + style: {}, + }), + + ]), + + ]) + + ]), + + h('div.flex-column', {}, [ + + h('div', {}, [ + + h('div.wallet-balance', {}, [ + + h(BalanceComponent, { + balanceValue: selectedAccount.balance, + style: {}, + }), + + ]), + + ]) + + ]), + + h('div.flex-column', {}, [ + + h('div', {}, [ + + h('div.wallet-balance', {}, [ + + h(BalanceComponent, { + balanceValue: selectedAccount.balance, + style: {}, + }), + + ]), + + ]) + + ]), + + h('div.flex-column', {}, [ + + h('div', {}, [ + + h('div.wallet-balance', {}, [ + + h(BalanceComponent, { + balanceValue: selectedAccount.balance, + style: {}, + }), + + ]), + + ]) + + ]), + + h('div.flex-column', {}, [ + + h('div', {}, [ + + h('div.wallet-balance', {}, [ + + h(BalanceComponent, { + balanceValue: selectedAccount.balance, + style: {}, + }), + + ]), + + ]) + + ]), + + h('div.flex-column', {}, [ + + h('div', {}, [ + + h('div.wallet-balance', {}, [ + + h(BalanceComponent, { + balanceValue: selectedAccount.balance, + style: {}, + }), + + ]), + + ]) + + ]), + ]) } -- cgit v1.2.3 From 9954c95b4a582d13c3b184b4e18f240865bc45f9 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Fri, 11 Aug 2017 00:42:44 -0700 Subject: [WIP] Begin fixing responsive layout with many wallets --- ui/app/components/wallet-view.js | 51 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 4f6a67994..db69b5faa 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -242,5 +242,56 @@ WalletView.prototype.render = function () { ]), + h('div.flex-column', {}, [ + + h('div', {}, [ + + h('div.wallet-balance', {}, [ + + h(BalanceComponent, { + balanceValue: selectedAccount.balance, + style: {}, + }), + + ]), + + ]) + + ]), + + h('div.flex-column', {}, [ + + h('div', {}, [ + + h('div.wallet-balance', {}, [ + + h(BalanceComponent, { + balanceValue: selectedAccount.balance, + style: {}, + }), + + ]), + + ]) + + ]), + + h('div.flex-column', {}, [ + + h('div', {}, [ + + h('div.wallet-balance', {}, [ + + h(BalanceComponent, { + balanceValue: selectedAccount.balance, + style: {}, + }), + + ]), + + ]) + + ]), + ]) } -- cgit v1.2.3 From 9b48e0aa53ff73fe526c4788c929b0ffe5a2d499 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Fri, 11 Aug 2017 09:17:14 -0700 Subject: Implement infinite scrolls (no lazy loading) for wallet view --- ui/app/components/wallet-view.js | 170 ++++++--------------------------------- 1 file changed, 23 insertions(+), 147 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index db69b5faa..cf7f74e49 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -41,14 +41,24 @@ const noop = () => {} WalletView.prototype.render = function () { const { network, responsiveDisplayClassname, style, identities, selectedAddress, selectedAccount } = this.props + // temporary logs + fake extra wallets console.log(selectedAccount) + const extraWallet = h('div.flex-column.wallet-balance-wrapper', {}, [ + h('div.wallet-balance', {}, [ + h(BalanceComponent, { + balanceValue: selectedAccount.balance, + style: {}, + }), + ]), + ]) + return h('div.wallet-view.flex-column' + (responsiveDisplayClassname || ''), { style: {}, }, [ // TODO: Separate component: wallet account details - h('div.flex-column', { + h('div.flex-column.wallet-view-account-details', { style: {} }, [ @@ -123,9 +133,7 @@ WalletView.prototype.render = function () { ]), //Wallet Balances - h('div.flex-column.wallet-balance-wrapper-active', {}, [ - - h('div', {}, [ + h('div.flex-column.wallet-balance-wrapper.wallet-balance-wrapper-active', {}, [ h('div.wallet-balance', {}, [ @@ -136,13 +144,9 @@ WalletView.prototype.render = function () { ]), - ]) - ]), - h('div.flex-column', {}, [ - - h('div', {}, [ + h('div.flex-column.wallet-balance-wrapper', {}, [ h('div.wallet-balance', {}, [ @@ -153,145 +157,17 @@ WalletView.prototype.render = function () { ]), - ]) - - ]), - - h('div.flex-column', {}, [ - - h('div', {}, [ - - h('div.wallet-balance', {}, [ - - h(BalanceComponent, { - balanceValue: selectedAccount.balance, - style: {}, - }), - - ]), - - ]) - - ]), - - h('div.flex-column', {}, [ - - h('div', {}, [ - - h('div.wallet-balance', {}, [ - - h(BalanceComponent, { - balanceValue: selectedAccount.balance, - style: {}, - }), - - ]), - - ]) - - ]), - - h('div.flex-column', {}, [ - - h('div', {}, [ - - h('div.wallet-balance', {}, [ - - h(BalanceComponent, { - balanceValue: selectedAccount.balance, - style: {}, - }), - - ]), - - ]) - - ]), - - h('div.flex-column', {}, [ - - h('div', {}, [ - - h('div.wallet-balance', {}, [ - - h(BalanceComponent, { - balanceValue: selectedAccount.balance, - style: {}, - }), - - ]), - - ]) - - ]), - - h('div.flex-column', {}, [ - - h('div', {}, [ - - h('div.wallet-balance', {}, [ - - h(BalanceComponent, { - balanceValue: selectedAccount.balance, - style: {}, - }), - - ]), - - ]) - - ]), - - h('div.flex-column', {}, [ - - h('div', {}, [ - - h('div.wallet-balance', {}, [ - - h(BalanceComponent, { - balanceValue: selectedAccount.balance, - style: {}, - }), - - ]), - - ]) - - ]), - - h('div.flex-column', {}, [ - - h('div', {}, [ - - h('div.wallet-balance', {}, [ - - h(BalanceComponent, { - balanceValue: selectedAccount.balance, - style: {}, - }), - - ]), - - ]) - - ]), - - h('div.flex-column', {}, [ - - h('div', {}, [ - - h('div.wallet-balance', {}, [ - - h(BalanceComponent, { - balanceValue: selectedAccount.balance, - style: {}, - }), - - ]), - - ]) - ]), + extraWallet, + extraWallet, + extraWallet, + extraWallet, + extraWallet, + extraWallet, + extraWallet, + extraWallet, + extraWallet, + extraWallet, ]) } -- cgit v1.2.3 From 25184a3901f96e3c4fea94ed0bd135fbe7597148 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 13 Aug 2017 10:24:51 -0700 Subject: Move global modals into own pod, inside components/modals --- ui/app/components/modal.js | 99 --------------------------------- ui/app/components/modals/buy-modal.js | 27 +++++++++ ui/app/components/modals/index.js | 9 +++ ui/app/components/modals/modal.js | 100 ++++++++++++++++++++++++++++++++++ 4 files changed, 136 insertions(+), 99 deletions(-) delete mode 100644 ui/app/components/modal.js create mode 100644 ui/app/components/modals/buy-modal.js create mode 100644 ui/app/components/modals/index.js create mode 100644 ui/app/components/modals/modal.js (limited to 'ui/app/components') diff --git a/ui/app/components/modal.js b/ui/app/components/modal.js deleted file mode 100644 index 010122d42..000000000 --- a/ui/app/components/modal.js +++ /dev/null @@ -1,99 +0,0 @@ -const Component = require('react').Component -const h = require('react-hyperscript') -const inherits = require('util').inherits -const connect = require('react-redux').connect -const FadeModal = require('boron').FadeModal -const actions = require('../actions') -const isMobileView = require('../../lib/is-mobile-view') -const isPopupOrNotification = require('../../../app/scripts/lib/is-popup-or-notification') - -function mapStateToProps (state) { - return { - active: state.appState.modalOpen - } -} - -function mapDispatchToProps (dispatch) { - return { - hideModal: () => { - dispatch(actions.hideModal()) - }, - } -} - -inherits(Modal, Component) -function Modal () { - Component.call(this) -} - -module.exports = connect(mapStateToProps, mapDispatchToProps)(Modal) - -const mobileModalStyles = { - width: '95%', - // Used to create matching t/l/r/b space in mobile view. - top: isPopupOrNotification() === 'popup' ? '48vh' : '36.5vh', - boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', -} - -const laptopModalStyles = { - width: '66%', - top: 'calc(30% + 10px)', - boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', -} - -const backdropStyles = { - backgroundColor: 'rgba(245, 245, 245, 0.85)', -} - -Modal.prototype.render = function () { - - return h(FadeModal, - { - className: 'modal', - keyboard: false, - onHide: () => {this.onHide()}, - ref: (ref) => { - this.modalRef = ref - }, - modalStyle: isMobileView() ? mobileModalStyles : laptopModalStyles, - backdropStyle: backdropStyles, - }, - this.props.children, - ) -} - -Modal.prototype.componentWillReceiveProps = function(nextProps) { - if (nextProps.active) { - this.show() - } else if (this.props.active) { - this.hide() - } -} - -Modal.prototype.onHide = function() { - if (this.props.onHideCallback) { - this.props.onHideCallback() - } - this.props.hideModal() -} - -Modal.prototype.hide = function() { - this.modalRef.hide() -} - -Modal.prototype.show = function() { - this.modalRef.show() -} - -// TODO: specify default props and proptypes -// Modal.defaultProps = {} - -// const elementType = require('react-prop-types/lib/elementType') -// const PropTypes from 'prop-types' - -// Modal.propTypes = { -// active: PropTypes.bool, -// hideModal: PropTypes.func.isRequired, -// component: elementType, -// onHideCallback: PropTypes.func, -// } diff --git a/ui/app/components/modals/buy-modal.js b/ui/app/components/modals/buy-modal.js new file mode 100644 index 000000000..c1bf1d0df --- /dev/null +++ b/ui/app/components/modals/buy-modal.js @@ -0,0 +1,27 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const connect = require('react-redux').connect +const FadeModal = require('boron').FadeModal +const actions = require('../../actions') +const isMobileView = require('../../../lib/is-mobile-view') +const isPopupOrNotification = require('../../../../app/scripts/lib/is-popup-or-notification') +const BuyOptions = require('../buy-options') + +inherits(BuyModal, Component) +function BuyModal () { + Component.call(this) +} + +module.exports = BuyModal + +BuyModal.prototype.render = function () { + return h(BuyModal, { + ref: "modalRef", + }, [ + h(BuyOptions, {}, []), + ]) + +} + +// TODO: specify default props and proptypes diff --git a/ui/app/components/modals/index.js b/ui/app/components/modals/index.js new file mode 100644 index 000000000..23b432b7c --- /dev/null +++ b/ui/app/components/modals/index.js @@ -0,0 +1,9 @@ +const Modal = require('./modal') +const BuyModal = require('./buy-modal') +// const h = require('account-options') +// const h = require('account-details') + +module.exports = { + Modal, + BuyModal, +} \ No newline at end of file diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js new file mode 100644 index 000000000..006e009b3 --- /dev/null +++ b/ui/app/components/modals/modal.js @@ -0,0 +1,100 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const connect = require('react-redux').connect +const FadeModal = require('boron').FadeModal +const actions = require('../../actions') +const isMobileView = require('../../../lib/is-mobile-view') +const isPopupOrNotification = require('../../../../app/scripts/lib/is-popup-or-notification') + +function mapStateToProps (state) { + return { + active: state.appState.modalOpen + } +} + +function mapDispatchToProps (dispatch) { + return { + hideModal: () => { + dispatch(actions.hideModal()) + }, + } +} + +// Global Modal Component +inherits(Modal, Component) +function Modal () { + Component.call(this) +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)(Modal) + +const mobileModalStyles = { + width: '95%', + // Used to create matching t/l/r/b space in mobile view. + top: isPopupOrNotification() === 'popup' ? '48vh' : '36.5vh', + boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', +} + +const laptopModalStyles = { + width: '66%', + top: 'calc(30% + 10px)', + boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', +} + +const backdropStyles = { + backgroundColor: 'rgba(245, 245, 245, 0.85)', +} + +Modal.prototype.render = function () { + + return h(FadeModal, + { + className: 'modal', + keyboard: false, + onHide: () => {this.onHide()}, + ref: (ref) => { + this.modalRef = ref + }, + modalStyle: isMobileView() ? mobileModalStyles : laptopModalStyles, + backdropStyle: backdropStyles, + }, + this.props.children, + ) +} + +Modal.prototype.componentWillReceiveProps = function(nextProps) { + if (nextProps.active) { + this.show() + } else if (this.props.active) { + this.hide() + } +} + +Modal.prototype.onHide = function() { + if (this.props.onHideCallback) { + this.props.onHideCallback() + } + this.props.hideModal() +} + +Modal.prototype.hide = function() { + this.modalRef.hide() +} + +Modal.prototype.show = function() { + this.modalRef.show() +} + +// TODO: specify default props and proptypes +// Modal.defaultProps = {} + +// const elementType = require('react-prop-types/lib/elementType') +// const PropTypes from 'prop-types' + +// Modal.propTypes = { +// active: PropTypes.bool, +// hideModal: PropTypes.func.isRequired, +// component: elementType, +// onHideCallback: PropTypes.func, +// } -- cgit v1.2.3 From e39c600a45a4cf28b5429231dd6c57442d467075 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 13 Aug 2017 10:49:41 -0700 Subject: [WIP] Extract network dropdown out of main app render function --- ui/app/components/dropdowns/index.js | 16 ++ ui/app/components/dropdowns/network.js | 259 +++++++++++++++++++++++++++++++++ ui/app/components/modals/buy-modal.js | 8 +- 3 files changed, 277 insertions(+), 6 deletions(-) create mode 100644 ui/app/components/dropdowns/index.js create mode 100644 ui/app/components/dropdowns/network.js (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/index.js b/ui/app/components/dropdowns/index.js new file mode 100644 index 000000000..b52dd8802 --- /dev/null +++ b/ui/app/components/dropdowns/index.js @@ -0,0 +1,16 @@ +// Reusable Dropdown Components +// const Dropdown = require('./dropdown') //TODO: Refactor into separate components +// const AccountDropdowns = require('./account-dropdowns') + +// App-Specific Instances +// const AccountSelectionDropdown = require('./account-selection-dropdown') +// const AccountOptionsDropdown = require('./account-options-dropdown') +const NetworkDropdown = require('./network-dropdown') + +module.exports = { + // AccountSelectionDropdown, + // AccountOptionsDropdown, + NetworkDropdown, + // Dropdown, + // AccountDropdowns, +} \ No newline at end of file diff --git a/ui/app/components/dropdowns/network.js b/ui/app/components/dropdowns/network.js new file mode 100644 index 000000000..2b693803b --- /dev/null +++ b/ui/app/components/dropdowns/network.js @@ -0,0 +1,259 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const connect = require('react-redux').connect +const actions = require('../../actions') + +// connect, dispatch actions... + // onClick: () => props.dispatch(actions.setProviderType('mainnet')), + // onClick: () => props.dispatch(actions.setDefaultRpcTarget()), + // onClick: () => props.dispatch(actions.setRpcTarget(rpcTarget)), + // onClick: () => this.props.dispatch(actions.showConfigPage()), + +function mapStateToProps (state) { + return { + active: state.appState.modalOpen + } +} + +function mapDispatchToProps (dispatch) { + return { + hideModal: () => { + dispatch(actions.hideModal()) + }, + } +} + + +inherits(NetworkDropdown, Component) +function NetworkDropdown () { + Component.call(this) +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)(NetworkDropdown) + +// renderNetworkDropdown +// renderCustomOption +// renderCommonRpc +// TODO: specify default props and proptypes +NetworkDropdown.prototype.render = function () { + const props = this.props + const { provider: { type: providerType, rpcTarget: activeNetwork } } = props + const rpcList = props.frequentRpcList + const state = this.state || {} + const isOpen = state.isNetworkMenuOpen + + return h(Dropdown, { + useCssTransition: true, + isOpen, + onClickOutside: (event) => { + const { classList } = event.target + const isNotToggleElement = [ + classList.contains('menu-icon'), + classList.contains('network-name'), + classList.contains('network-indicator'), + ].filter(bool => bool).length === 0 + // classes from three constituent nodes of the toggle element + + if (isNotToggleElement) { + this.setState({ isNetworkMenuOpen: false }) + } + }, + zIndex: 11, + style: { + position: 'absolute', + right: '2px', + top: '38px', + }, + innerStyle: { + padding: '2px 16px 2px 0px', + }, + }, [ + + h( + DropdownMenuItem, + { + key: 'main', + closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), + onClick: () => props.dispatch(actions.setProviderType('mainnet')), + style: { + fontSize: '18px', + }, + }, + [ + h('.menu-icon.diamond'), + 'Main Ethereum Network', + providerType === 'mainnet' ? h('.check', '✓') : null, + ] + ), + + h( + DropdownMenuItem, + { + key: 'ropsten', + closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), + onClick: () => props.dispatch(actions.setProviderType('ropsten')), + style: { + fontSize: '18px', + }, + }, + [ + h('.menu-icon.red-dot'), + 'Ropsten Test Network', + providerType === 'ropsten' ? h('.check', '✓') : null, + ] + ), + + h( + DropdownMenuItem, + { + key: 'kovan', + closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), + onClick: () => props.dispatch(actions.setProviderType('kovan')), + style: { + fontSize: '18px', + }, + }, + [ + h('.menu-icon.hollow-diamond'), + 'Kovan Test Network', + providerType === 'kovan' ? h('.check', '✓') : null, + ] + ), + + h( + DropdownMenuItem, + { + key: 'rinkeby', + closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), + onClick: () => props.dispatch(actions.setProviderType('rinkeby')), + style: { + fontSize: '18px', + }, + }, + [ + h('.menu-icon.golden-square'), + 'Rinkeby Test Network', + providerType === 'rinkeby' ? h('.check', '✓') : null, + ] + ), + + h( + DropdownMenuItem, + { + key: 'default', + closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), + onClick: () => props.dispatch(actions.setDefaultRpcTarget()), + style: { + fontSize: '18px', + }, + }, + [ + h('i.fa.fa-question-circle.fa-lg.menu-icon'), + 'Localhost 8545', + activeNetwork === 'http://localhost:8545' ? h('.check', '✓') : null, + ] + ), + + this.renderCustomOption(props.provider), + this.renderCommonRpc(rpcList, props.provider), + + h( + DropdownMenuItem, + { + closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), + onClick: () => this.props.dispatch(actions.showConfigPage()), + style: { + fontSize: '18px', + }, + }, + [ + h('i.fa.fa-question-circle.fa-lg.menu-icon'), + 'Custom RPC', + activeNetwork === 'custom' ? h('.check', '✓') : null, + ] + ), + + ]) +} + + +NetworkDropdown.prototype.getNetworkName = function () { + const { provider } = this.props + const providerName = provider.type + + let name + + if (providerName === 'mainnet') { + name = 'Main Ethereum Network' + } else if (providerName === 'ropsten') { + name = 'Ropsten Test Network' + } else if (providerName === 'kovan') { + name = 'Kovan Test Network' + } else if (providerName === 'rinkeby') { + name = 'Rinkeby Test Network' + } else { + name = 'Unknown Private Network' + } + + return name +} + +NetworkDropdown.prototype.renderCommonRpc = function (rpcList, provider) { + const props = this.props + const rpcTarget = provider.rpcTarget + + return rpcList.map((rpc) => { + if ((rpc === 'http://localhost:8545') || (rpc === rpcTarget)) { + return null + } else { + return h( + DropdownMenuItem, + { + key: `common${rpc}`, + closeMenu: () => this.setState({ isNetworkMenuOpen: false }), + onClick: () => props.dispatch(actions.setRpcTarget(rpc)), + }, + [ + h('i.fa.fa-question-circle.fa-lg.menu-icon'), + rpc, + rpcTarget === rpc ? h('.check', '✓') : null, + ] + ) + } + }) +} + +NetworkDropdown.prototype.renderCustomOption = function (provider) { + const { rpcTarget, type } = provider + const props = this.props + + if (type !== 'rpc') return null + + // Concatenate long URLs + let label = rpcTarget + if (rpcTarget.length > 31) { + label = label.substr(0, 34) + '...' + } + + switch (rpcTarget) { + + case 'http://localhost:8545': + return null + + default: + return h( + DropdownMenuItem, + { + key: rpcTarget, + onClick: () => props.dispatch(actions.setRpcTarget(rpcTarget)), + closeMenu: () => this.setState({ isNetworkMenuOpen: false }), + }, + [ + h('i.fa.fa-question-circle.fa-lg.menu-icon'), + label, + h('.check', '✓'), + ] + ) + } +} diff --git a/ui/app/components/modals/buy-modal.js b/ui/app/components/modals/buy-modal.js index c1bf1d0df..9a3e4dff9 100644 --- a/ui/app/components/modals/buy-modal.js +++ b/ui/app/components/modals/buy-modal.js @@ -1,12 +1,8 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits -const connect = require('react-redux').connect -const FadeModal = require('boron').FadeModal -const actions = require('../../actions') -const isMobileView = require('../../../lib/is-mobile-view') -const isPopupOrNotification = require('../../../../app/scripts/lib/is-popup-or-notification') const BuyOptions = require('../buy-options') +const Modal = require('./modal.js') inherits(BuyModal, Component) function BuyModal () { @@ -16,7 +12,7 @@ function BuyModal () { module.exports = BuyModal BuyModal.prototype.render = function () { - return h(BuyModal, { + return h(Modal, { ref: "modalRef", }, [ h(BuyOptions, {}, []), -- cgit v1.2.3 From 4cd33453dc14ae9e6a797c16cccb52598904941a Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 13 Aug 2017 22:15:21 +0200 Subject: [WIP] Extract network dropdown into own component --- ui/app/components/dropdowns/index.js | 2 +- ui/app/components/dropdowns/network-dropdown.js | 276 ++++++++++++++++++++++++ ui/app/components/dropdowns/network.js | 259 ---------------------- 3 files changed, 277 insertions(+), 260 deletions(-) create mode 100644 ui/app/components/dropdowns/network-dropdown.js delete mode 100644 ui/app/components/dropdowns/network.js (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/index.js b/ui/app/components/dropdowns/index.js index b52dd8802..6723a2048 100644 --- a/ui/app/components/dropdowns/index.js +++ b/ui/app/components/dropdowns/index.js @@ -5,7 +5,7 @@ // App-Specific Instances // const AccountSelectionDropdown = require('./account-selection-dropdown') // const AccountOptionsDropdown = require('./account-options-dropdown') -const NetworkDropdown = require('./network-dropdown') +const NetworkDropdown = require('./network-dropdown').default module.exports = { // AccountSelectionDropdown, diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js new file mode 100644 index 000000000..42ab53c60 --- /dev/null +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -0,0 +1,276 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const connect = require('react-redux').connect +const actions = require('../../actions') +const Dropdown = require('../dropdown').Dropdown +const DropdownMenuItem = require('../dropdown').DropdownMenuItem + +function mapStateToProps (state) { + return { + provider: state.metamask.provider, + frequentRpcList: state.metamask.frequentRpcList || [], + networkDropdownOpen: state.appState.networkDropdownOpen, + } +} + +function mapDispatchToProps (dispatch) { + return { + hideModal: () => { + dispatch(actions.hideModal()) + }, + setProviderType: (type) => { + dispatch(actions.setProviderType(type)) + }, + setDefaultRpcTarget: () => { + dispatch(actions.setDefaultRpcTarget(type)) + }, + setRpcTarget: (target) => { + dispatch(actions.setRpcTarget(target)) + }, + showConfigPage: () => { + dispatch(actions.showConfigPage()) + }, + showNetworkDropdown: () => {dispatch(actions.showNetworkDropdown())}, + hideNetworkDropdown: () => {dispatch(actions.hideNetworkDropdown())}, + } +} + + +inherits(NetworkDropdown, Component) +function NetworkDropdown () { + Component.call(this) +} + +// renderNetworkDropdown +// renderCustomOption +// renderCommonRpc +// TODO: specify default props and proptypes +NetworkDropdown.prototype.render = function () { + console.log("RENDER") + const props = this.props + const { provider: { type: providerType, rpcTarget: activeNetwork } } = props + const rpcList = props.frequentRpcList + const state = this.state || {} + console.log("this.state", state) + const isOpen = this.props.networkDropdownOpen + + console.log("isOpen", isOpen) + + return h(Dropdown, { + useCssTransition: true, + isOpen, + onClickOutside: (event) => { + const { classList } = event.target + const isNotToggleElement = [ + classList.contains('menu-icon'), + classList.contains('network-name'), + classList.contains('network-indicator'), + ].filter(bool => bool).length === 0 + // classes from three constituent nodes of the toggle element + + if (isNotToggleElement) { + this.props.hideNetworkDropdown() + } + }, + zIndex: 11, + style: { + position: 'absolute', + right: '2px', + top: '38px', + }, + innerStyle: { + padding: '2px 16px 2px 0px', + }, + }, [ + + h( + DropdownMenuItem, + { + key: 'main', + closeMenu: () => this.props.hideNetworkDropdown(), + onClick: () => props.setProviderType('mainnet'), + style: { + fontSize: '18px', + }, + }, + [ + h('.menu-icon.diamond'), + 'Main Ethereum Network', + providerType === 'mainnet' ? h('.check', '✓') : null, + ] + ), + + h( + DropdownMenuItem, + { + key: 'ropsten', + closeMenu: () => this.props.hideNetworkDropdown(), + onClick: () => props.setProviderType('ropsten'), + style: { + fontSize: '18px', + }, + }, + [ + h('.menu-icon.red-dot'), + 'Ropsten Test Network', + providerType === 'ropsten' ? h('.check', '✓') : null, + ] + ), + + h( + DropdownMenuItem, + { + key: 'kovan', + closeMenu: () => this.props.hideNetworkDropdown(), + onClick: () => props.setProviderType('kovan'), + style: { + fontSize: '18px', + }, + }, + [ + h('.menu-icon.hollow-diamond'), + 'Kovan Test Network', + providerType === 'kovan' ? h('.check', '✓') : null, + ] + ), + + h( + DropdownMenuItem, + { + key: 'rinkeby', + closeMenu: () => this.props.hideNetworkDropdown(), + onClick: () => propssetProviderType('rinkeby'), + style: { + fontSize: '18px', + }, + }, + [ + h('.menu-icon.golden-square'), + 'Rinkeby Test Network', + providerType === 'rinkeby' ? h('.check', '✓') : null, + ] + ), + + h( + DropdownMenuItem, + { + key: 'default', + closeMenu: () => this.props.hideNetworkDropdown(), + onClick: () => props.setDefaultRpcTarget(), + style: { + fontSize: '18px', + }, + }, + [ + h('i.fa.fa-question-circle.fa-lg.menu-icon'), + 'Localhost 8545', + activeNetwork === 'http://localhost:8545' ? h('.check', '✓') : null, + ] + ), + + this.renderCustomOption(props.provider), + this.renderCommonRpc(rpcList, props.provider), + + h( + DropdownMenuItem, + { + closeMenu: () => this.props.hideNetworkDropdown(), + onClick: () => this.props.showConfigPage(), + style: { + fontSize: '18px', + }, + }, + [ + h('i.fa.fa-question-circle.fa-lg.menu-icon'), + 'Custom RPC', + activeNetwork === 'custom' ? h('.check', '✓') : null, + ] + ), + + ]) +} + + +NetworkDropdown.prototype.getNetworkName = function () { + const { provider } = this.props + const providerName = provider.type + + let name + + if (providerName === 'mainnet') { + name = 'Main Ethereum Network' + } else if (providerName === 'ropsten') { + name = 'Ropsten Test Network' + } else if (providerName === 'kovan') { + name = 'Kovan Test Network' + } else if (providerName === 'rinkeby') { + name = 'Rinkeby Test Network' + } else { + name = 'Unknown Private Network' + } + + return name +} + +NetworkDropdown.prototype.renderCommonRpc = function (rpcList, provider) { + const props = this.props + const rpcTarget = provider.rpcTarget + + return rpcList.map((rpc) => { + if ((rpc === 'http://localhost:8545') || (rpc === rpcTarget)) { + return null + } else { + return h( + DropdownMenuItem, + { + key: `common${rpc}`, + closeMenu: () => this.props.hideNetworkDropdown(), + onClick: () => props.setRpcTarget(rpc), + }, + [ + h('i.fa.fa-question-circle.fa-lg.menu-icon'), + rpc, + rpcTarget === rpc ? h('.check', '✓') : null, + ] + ) + } + }) +} + +NetworkDropdown.prototype.renderCustomOption = function (provider) { + const { rpcTarget, type } = provider + const props = this.props + + if (type !== 'rpc') return null + + // Concatenate long URLs + let label = rpcTarget + if (rpcTarget.length > 31) { + label = label.substr(0, 34) + '...' + } + + switch (rpcTarget) { + + case 'http://localhost:8545': + return null + + default: + return h( + DropdownMenuItem, + { + key: rpcTarget, + onClick: () => props.setRpcTarget(rpcTarget), + closeMenu: () => this.props.hideNetworkDropdown(), + }, + [ + h('i.fa.fa-question-circle.fa-lg.menu-icon'), + label, + h('.check', '✓'), + ] + ) + } +} + +const comp = connect(mapStateToProps, mapDispatchToProps)(NetworkDropdown) +module.exports = comp diff --git a/ui/app/components/dropdowns/network.js b/ui/app/components/dropdowns/network.js deleted file mode 100644 index 2b693803b..000000000 --- a/ui/app/components/dropdowns/network.js +++ /dev/null @@ -1,259 +0,0 @@ -const Component = require('react').Component -const h = require('react-hyperscript') -const inherits = require('util').inherits -const connect = require('react-redux').connect -const actions = require('../../actions') - -// connect, dispatch actions... - // onClick: () => props.dispatch(actions.setProviderType('mainnet')), - // onClick: () => props.dispatch(actions.setDefaultRpcTarget()), - // onClick: () => props.dispatch(actions.setRpcTarget(rpcTarget)), - // onClick: () => this.props.dispatch(actions.showConfigPage()), - -function mapStateToProps (state) { - return { - active: state.appState.modalOpen - } -} - -function mapDispatchToProps (dispatch) { - return { - hideModal: () => { - dispatch(actions.hideModal()) - }, - } -} - - -inherits(NetworkDropdown, Component) -function NetworkDropdown () { - Component.call(this) -} - -module.exports = connect(mapStateToProps, mapDispatchToProps)(NetworkDropdown) - -// renderNetworkDropdown -// renderCustomOption -// renderCommonRpc -// TODO: specify default props and proptypes -NetworkDropdown.prototype.render = function () { - const props = this.props - const { provider: { type: providerType, rpcTarget: activeNetwork } } = props - const rpcList = props.frequentRpcList - const state = this.state || {} - const isOpen = state.isNetworkMenuOpen - - return h(Dropdown, { - useCssTransition: true, - isOpen, - onClickOutside: (event) => { - const { classList } = event.target - const isNotToggleElement = [ - classList.contains('menu-icon'), - classList.contains('network-name'), - classList.contains('network-indicator'), - ].filter(bool => bool).length === 0 - // classes from three constituent nodes of the toggle element - - if (isNotToggleElement) { - this.setState({ isNetworkMenuOpen: false }) - } - }, - zIndex: 11, - style: { - position: 'absolute', - right: '2px', - top: '38px', - }, - innerStyle: { - padding: '2px 16px 2px 0px', - }, - }, [ - - h( - DropdownMenuItem, - { - key: 'main', - closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), - onClick: () => props.dispatch(actions.setProviderType('mainnet')), - style: { - fontSize: '18px', - }, - }, - [ - h('.menu-icon.diamond'), - 'Main Ethereum Network', - providerType === 'mainnet' ? h('.check', '✓') : null, - ] - ), - - h( - DropdownMenuItem, - { - key: 'ropsten', - closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), - onClick: () => props.dispatch(actions.setProviderType('ropsten')), - style: { - fontSize: '18px', - }, - }, - [ - h('.menu-icon.red-dot'), - 'Ropsten Test Network', - providerType === 'ropsten' ? h('.check', '✓') : null, - ] - ), - - h( - DropdownMenuItem, - { - key: 'kovan', - closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), - onClick: () => props.dispatch(actions.setProviderType('kovan')), - style: { - fontSize: '18px', - }, - }, - [ - h('.menu-icon.hollow-diamond'), - 'Kovan Test Network', - providerType === 'kovan' ? h('.check', '✓') : null, - ] - ), - - h( - DropdownMenuItem, - { - key: 'rinkeby', - closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), - onClick: () => props.dispatch(actions.setProviderType('rinkeby')), - style: { - fontSize: '18px', - }, - }, - [ - h('.menu-icon.golden-square'), - 'Rinkeby Test Network', - providerType === 'rinkeby' ? h('.check', '✓') : null, - ] - ), - - h( - DropdownMenuItem, - { - key: 'default', - closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), - onClick: () => props.dispatch(actions.setDefaultRpcTarget()), - style: { - fontSize: '18px', - }, - }, - [ - h('i.fa.fa-question-circle.fa-lg.menu-icon'), - 'Localhost 8545', - activeNetwork === 'http://localhost:8545' ? h('.check', '✓') : null, - ] - ), - - this.renderCustomOption(props.provider), - this.renderCommonRpc(rpcList, props.provider), - - h( - DropdownMenuItem, - { - closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), - onClick: () => this.props.dispatch(actions.showConfigPage()), - style: { - fontSize: '18px', - }, - }, - [ - h('i.fa.fa-question-circle.fa-lg.menu-icon'), - 'Custom RPC', - activeNetwork === 'custom' ? h('.check', '✓') : null, - ] - ), - - ]) -} - - -NetworkDropdown.prototype.getNetworkName = function () { - const { provider } = this.props - const providerName = provider.type - - let name - - if (providerName === 'mainnet') { - name = 'Main Ethereum Network' - } else if (providerName === 'ropsten') { - name = 'Ropsten Test Network' - } else if (providerName === 'kovan') { - name = 'Kovan Test Network' - } else if (providerName === 'rinkeby') { - name = 'Rinkeby Test Network' - } else { - name = 'Unknown Private Network' - } - - return name -} - -NetworkDropdown.prototype.renderCommonRpc = function (rpcList, provider) { - const props = this.props - const rpcTarget = provider.rpcTarget - - return rpcList.map((rpc) => { - if ((rpc === 'http://localhost:8545') || (rpc === rpcTarget)) { - return null - } else { - return h( - DropdownMenuItem, - { - key: `common${rpc}`, - closeMenu: () => this.setState({ isNetworkMenuOpen: false }), - onClick: () => props.dispatch(actions.setRpcTarget(rpc)), - }, - [ - h('i.fa.fa-question-circle.fa-lg.menu-icon'), - rpc, - rpcTarget === rpc ? h('.check', '✓') : null, - ] - ) - } - }) -} - -NetworkDropdown.prototype.renderCustomOption = function (provider) { - const { rpcTarget, type } = provider - const props = this.props - - if (type !== 'rpc') return null - - // Concatenate long URLs - let label = rpcTarget - if (rpcTarget.length > 31) { - label = label.substr(0, 34) + '...' - } - - switch (rpcTarget) { - - case 'http://localhost:8545': - return null - - default: - return h( - DropdownMenuItem, - { - key: rpcTarget, - onClick: () => props.dispatch(actions.setRpcTarget(rpcTarget)), - closeMenu: () => this.setState({ isNetworkMenuOpen: false }), - }, - [ - h('i.fa.fa-question-circle.fa-lg.menu-icon'), - label, - h('.check', '✓'), - ] - ) - } -} -- cgit v1.2.3 From d01a6633423e9b20f3ca8e73cd39655362190f64 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 13 Aug 2017 22:18:08 +0200 Subject: Remove unused code - network dropdown components in app --- ui/app/components/dropdowns/network-dropdown.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js index 42ab53c60..eb41f6f9b 100644 --- a/ui/app/components/dropdowns/network-dropdown.js +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -42,21 +42,16 @@ function NetworkDropdown () { Component.call(this) } -// renderNetworkDropdown -// renderCustomOption -// renderCommonRpc +module.exports = connect(mapStateToProps, mapDispatchToProps)(NetworkDropdown) + // TODO: specify default props and proptypes NetworkDropdown.prototype.render = function () { - console.log("RENDER") const props = this.props const { provider: { type: providerType, rpcTarget: activeNetwork } } = props const rpcList = props.frequentRpcList const state = this.state || {} - console.log("this.state", state) const isOpen = this.props.networkDropdownOpen - console.log("isOpen", isOpen) - return h(Dropdown, { useCssTransition: true, isOpen, @@ -271,6 +266,3 @@ NetworkDropdown.prototype.renderCustomOption = function (provider) { ) } } - -const comp = connect(mapStateToProps, mapDispatchToProps)(NetworkDropdown) -module.exports = comp -- cgit v1.2.3 From b900da885ebb5b5581a670d9ca85761cecaa648f Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 14 Aug 2017 07:33:43 +0200 Subject: Fix odd relative position conflict so main icon is rounded - See flyswatter/jazzicon/issues/1 --- ui/app/components/wallet-view.js | 41 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 22 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index cf7f74e49..38b2787d5 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -88,39 +88,36 @@ WalletView.prototype.render = function () { ]), h('div.flex-column.flex-center', { - style: { - position: 'relative', - }, }, [ - - h('.identicon-wrapper.select-none', { + h('div', { style: { - marginBottom: '1%', - }, + position: 'relative', + } }, [ - h(Identicon, { - diameter: 54, - address: selectedAddress, - }), + h(AccountDropdowns, { + style: { + position: 'absolute', + left: 'calc(50% + 28px + 5.5px)', + top: '14px', + }, + selected: selectedAddress, + network, + identities, + enableAccountsSelector: true, + }, []), ]), + h(Identicon, { + diameter: 54, + address: selectedAddress, + }), + h('span.account-name', { style: {} }, [ 'Account 1' ]), - h(AccountDropdowns, { - style: { - position: 'absolute', - left: 'calc(50% + 28px + 5.5px)', - top: '19.5%', - }, - selected: selectedAddress, - network, - identities, - enableAccountsSelector: true, - }, []), ]), ]), -- cgit v1.2.3 From 88665ba150c74955ef11a1b3fbc0f158a1c321de Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 14 Aug 2017 08:31:49 +0200 Subject: Extract dropdown component into components/dropdowns, hook up to app --- ui/app/components/account-dropdowns.js | 319 --------------------- ui/app/components/dropdown.js | 95 ------ .../dropdowns/account-options-dropdown.js | 28 ++ .../dropdowns/account-selection-dropdown.js | 28 ++ .../dropdowns/components/account-dropdowns.js | 318 ++++++++++++++++++++ ui/app/components/dropdowns/components/dropdown.js | 95 ++++++ ui/app/components/dropdowns/index.js | 18 +- ui/app/components/wallet-view.js | 2 +- 8 files changed, 480 insertions(+), 423 deletions(-) delete mode 100644 ui/app/components/account-dropdowns.js delete mode 100644 ui/app/components/dropdown.js create mode 100644 ui/app/components/dropdowns/account-options-dropdown.js create mode 100644 ui/app/components/dropdowns/account-selection-dropdown.js create mode 100644 ui/app/components/dropdowns/components/account-dropdowns.js create mode 100644 ui/app/components/dropdowns/components/dropdown.js (limited to 'ui/app/components') diff --git a/ui/app/components/account-dropdowns.js b/ui/app/components/account-dropdowns.js deleted file mode 100644 index 3f1b0ee53..000000000 --- a/ui/app/components/account-dropdowns.js +++ /dev/null @@ -1,319 +0,0 @@ -const Component = require('react').Component -const PropTypes = require('react').PropTypes -const h = require('react-hyperscript') -const actions = require('../actions') -const genAccountLink = require('../../lib/account-link.js') -const connect = require('react-redux').connect -const Dropdown = require('./dropdown').Dropdown -const DropdownMenuItem = require('./dropdown').DropdownMenuItem -const Identicon = require('./identicon') -const ethUtil = require('ethereumjs-util') -const copyToClipboard = require('copy-to-clipboard') - -class AccountDropdowns extends Component { - constructor (props) { - super(props) - this.state = { - accountSelectorActive: false, - optionsMenuActive: false, - } - this.accountSelectorToggleClassName = 'accounts-selector' - this.optionsMenuToggleClassName = 'fa-ellipsis-h' - } - - renderAccounts () { - const { identities, selected, menuItemStyles, dropdownWrapperStyle } = this.props - - return Object.keys(identities).map((key, index) => { - const identity = identities[key] - const isSelected = identity.address === selected - - return h( - DropdownMenuItem, - { - closeMenu: () => {}, - onClick: () => { - this.props.actions.showAccountDetail(identity.address) - }, - style: Object.assign( - { - marginTop: index === 0 ? '5px' : '', - fontSize: '24px', - }, - menuItemStyles, - ), - }, - [ - h( - Identicon, - { - address: identity.address, - diameter: 32, - style: { - marginLeft: '10px', - }, - }, - ), - h('span', { style: { marginLeft: '20px', fontSize: '24px' } }, identity.name || ''), - h('span', { style: { marginLeft: '20px', fontSize: '24px' } }, isSelected ? h('.check', '✓') : null), - ] - ) - }) - } - - renderAccountSelector () { - const { actions, dropdownWrapperStyle } = this.props - const { accountSelectorActive, menuItemStyles } = this.state - - return h( - Dropdown, - { - useCssTransition: true, // Hardcoded because account selector is temporarily in app-header - style: { - marginLeft: '-238px', - marginTop: '38px', - minWidth: '180px', - overflowY: 'auto', - maxHeight: '300px', - width: '300px', - }, - innerStyle: { - padding: '8px 25px', - }, - isOpen: accountSelectorActive, - onClickOutside: (event) => { - const { classList } = event.target - const isNotToggleElement = !classList.contains(this.accountSelectorToggleClassName) - if (accountSelectorActive && isNotToggleElement) { - this.setState({ accountSelectorActive: false }) - } - }, - }, - [ - ...this.renderAccounts(), - h( - DropdownMenuItem, - { - closeMenu: () => {}, - onClick: () => actions.addNewAccount(), - style: Object.assign( - {}, - menuItemStyles, - ), - }, - [ - h( - Identicon, - { - style: { - marginLeft: '10px', - }, - diameter: 32, - }, - ), - h('span', { style: { marginLeft: '20px', fontSize: '24px' } }, 'Create Account'), - ], - ), - h( - DropdownMenuItem, - { - closeMenu: () => {}, - onClick: () => actions.showImportPage(), - style: Object.assign( - {}, - menuItemStyles, - ), - }, - [ - h( - Identicon, - { - style: { - marginLeft: '10px', - }, - diameter: 32, - }, - ), - h('span', { - style: { - marginLeft: '20px', - fontSize: '24px', - marginBottom: '5px', - }, - }, 'Import Account'), - ] - ), - ] - ) - } - - renderAccountOptions () { - const { actions, dropdownWrapperStyle } = this.props - const { optionsMenuActive, menuItemStyles } = this.state - - return h( - Dropdown, - { - style: Object.assign( - { - marginLeft: '-10px', - position: 'absolute', - width: '29vh', // affects both mobile and laptop views - }, - dropdownWrapperStyle, - ), - isOpen: optionsMenuActive, - onClickOutside: () => { - const { classList } = event.target - const isNotToggleElement = !classList.contains(this.optionsMenuToggleClassName) - if (optionsMenuActive && isNotToggleElement) { - this.setState({ optionsMenuActive: false }) - } - }, - }, - [ - h( - DropdownMenuItem, - { - closeMenu: () => {}, - onClick: () => { - const { selected, network } = this.props - const url = genAccountLink(selected, network) - global.platform.openWindow({ url }) - }, - style: Object.assign( - {}, - menuItemStyles, - ), - }, - 'View account on Etherscan', - ), - h( - DropdownMenuItem, - { - closeMenu: () => {}, - onClick: () => { - const { selected, identities } = this.props - var identity = identities[selected] - actions.showQrView(selected, identity ? identity.name : '') - }, - style: Object.assign( - {}, - menuItemStyles, - ), - }, - 'Show QR Code', - ), - h( - DropdownMenuItem, - { - closeMenu: () => {}, - onClick: () => { - const { selected } = this.props - const checkSumAddress = selected && ethUtil.toChecksumAddress(selected) - copyToClipboard(checkSumAddress) - }, - style: Object.assign( - {}, - menuItemStyles, - ), - }, - 'Copy Address to clipboard', - ), - h( - DropdownMenuItem, - { - closeMenu: () => {}, - onClick: () => { - actions.requestAccountExport() - }, - style: Object.assign( - {}, - menuItemStyles, - ), - }, - 'Export Private Key', - ), - ] - ) - } - - render () { - const { style, enableAccountsSelector, enableAccountOptions, dropdownWrapperStyle } = this.props - const { optionsMenuActive, accountSelectorActive } = this.state - - return h( - 'span', - { - style: style, - }, - [ - enableAccountsSelector && h( - 'i.fa.fa-angle-down', - // 'div.cursor-pointer.color-orange.accounts-selector', - { - style: { - // fontSize: '135%', - // background: 'url(images/switch_acc.svg) white center center no-repeat', - // height: '25px', - // width: '25px', - // transform: 'scale(0.75)', - // marginRight: '3px', - }, - onClick: (event) => { - event.stopPropagation() - this.setState({ - accountSelectorActive: !accountSelectorActive, - optionsMenuActive: false, - }) - }, - }, - this.renderAccountSelector(), - ), - enableAccountOptions && h( - 'i.fa.fa-ellipsis-h', - { - style: { - fontSize: '135%', - }, - onClick: (event) => { - event.stopPropagation() - this.setState({ - accountSelectorActive: false, - optionsMenuActive: !optionsMenuActive, - }) - }, - }, - this.renderAccountOptions() - ), - ] - ) - } -} - -AccountDropdowns.defaultProps = { - enableAccountsSelector: false, - enableAccountOptions: false, -} - -AccountDropdowns.propTypes = { - identities: PropTypes.objectOf(PropTypes.object), - selected: PropTypes.string, // TODO: refactor to be more explicit: selectedAddress -} - -const mapDispatchToProps = (dispatch) => { - return { - actions: { - showConfigPage: () => dispatch(actions.showConfigPage()), - requestAccountExport: () => dispatch(actions.requestExportAccount()), - showAccountDetail: (address) => dispatch(actions.showAccountDetail(address)), - addNewAccount: () => dispatch(actions.addNewAccount()), - showImportPage: () => dispatch(actions.showImportPage()), - showQrView: (selected, identity) => dispatch(actions.showQrView(selected, identity)), - }, - } -} - -module.exports = { - AccountDropdowns: connect(null, mapDispatchToProps)(AccountDropdowns), -} diff --git a/ui/app/components/dropdown.js b/ui/app/components/dropdown.js deleted file mode 100644 index 07ef75f12..000000000 --- a/ui/app/components/dropdown.js +++ /dev/null @@ -1,95 +0,0 @@ -const Component = require('react').Component -const PropTypes = require('react').PropTypes -const h = require('react-hyperscript') -const MenuDroppo = require('./menu-droppo') -const extend = require('xtend') - -const noop = () => {} - -class Dropdown extends Component { - render () { - const { isOpen, onClickOutside, style, innerStyle, children, useCssTransition } = this.props - - const innerStyleDefaults = extend({ - borderRadius: '4px', - padding: '8px 16px', - background: 'rgba(0, 0, 0, 0.8)', - boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', - }, innerStyle) - - return h( - MenuDroppo, - { - useCssTransition, - isOpen, - zIndex: 30, - onClickOutside, - style, - innerStyle: innerStyleDefaults, - }, - [ - h( - 'style', - ` - li.dropdown-menu-item:hover { color:rgb(225, 225, 225); } - li.dropdown-menu-item { color: rgb(185, 185, 185); } - ` - ), - ...children, - ] - ) - } -} - -Dropdown.defaultProps = { - isOpen: false, - onClick: noop, - useCssTransition: false, -} - -Dropdown.propTypes = { - isOpen: PropTypes.bool.isRequired, - onClick: PropTypes.func.isRequired, - children: PropTypes.node, - style: PropTypes.object.isRequired, -} - -class DropdownMenuItem extends Component { - render () { - const { onClick, closeMenu, children, style } = this.props - - return h( - 'li.dropdown-menu-item', - { - onClick: () => { - onClick() - closeMenu() - }, - style: Object.assign({ - listStyle: 'none', - padding: '8px 0px', - fontSize: '18px', - fontStyle: 'normal', - fontFamily: 'Montserrat Regular', - cursor: 'pointer', - display: 'flex', - justifyContent: 'flex-start', - alignItems: 'center', - color: 'white', - }, style), - }, - children - ) - } -} - -DropdownMenuItem.propTypes = { - closeMenu: PropTypes.func.isRequired, - onClick: PropTypes.func.isRequired, - children: PropTypes.node, -} - -module.exports = { - Dropdown, - DropdownMenuItem, -} diff --git a/ui/app/components/dropdowns/account-options-dropdown.js b/ui/app/components/dropdowns/account-options-dropdown.js new file mode 100644 index 000000000..7d7188ec4 --- /dev/null +++ b/ui/app/components/dropdowns/account-options-dropdown.js @@ -0,0 +1,28 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const AccountDropdowns = require('./components/account-dropdowns') + +inherits(AccountOptionsDropdown, Component) +function AccountOptionsDropdown () { + Component.call(this) +} + +module.exports = AccountOptionsDropdown + +// TODO: specify default props and proptypes +// TODO: hook up to state, connect to redux to clean up API +AccountOptionsDropdown.prototype.render = function () { + const { selected, network, identities, style, dropdownWrapperStyle, menuItemStyles } = this.props + + return h(AccountDropdowns, { + enableAccountOptions: true, + enableAccountsSelector: false, + selected: selectedAddress, + network, + identities, + style: !!style ? style : {}, + dropdownWrapperStyle: !!dropdownWrapperStyle ? dropdownWrapperStyle : {}, + menuItemStyles: !!menuItemStyles ? menuItemStyles : {}, + }, []) +} diff --git a/ui/app/components/dropdowns/account-selection-dropdown.js b/ui/app/components/dropdowns/account-selection-dropdown.js new file mode 100644 index 000000000..ccb73bde7 --- /dev/null +++ b/ui/app/components/dropdowns/account-selection-dropdown.js @@ -0,0 +1,28 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const AccountDropdowns = require('./components/account-dropdowns') + +inherits(AccountSelectionDropdown, Component) +function AccountSelectionDropdown () { + Component.call(this) +} + +module.exports = AccountSelectionDropdown + +// TODO: specify default props and proptypes +// TODO: hook up to state, connect to redux to clean up API +AccountSelectionDropdown.prototype.render = function () { + const { selected, network, identities, style, dropdownWrapperStyle, menuItemStyles } = this.props + + return h(AccountDropdowns, { + enableAccountOptions: false, + enableAccountsSelector: true, + selected: selectedAddress, + network, + identities, + style: !!style ? style : {}, + dropdownWrapperStyle: !!dropdownWrapperStyle ? dropdownWrapperStyle : {}, + menuItemStyles: !!menuItemStyles ? menuItemStyles : {}, + }, []) +} diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js new file mode 100644 index 000000000..ee41829c9 --- /dev/null +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -0,0 +1,318 @@ +const Component = require('react').Component +const PropTypes = require('react').PropTypes +const h = require('react-hyperscript') +const actions = require('../../../actions') +const genAccountLink = require('../../../../lib/account-link.js') +const connect = require('react-redux').connect +const Dropdown = require('./dropdown').Dropdown +const DropdownMenuItem = require('./dropdown').DropdownMenuItem +const Identicon = require('../../identicon') +const ethUtil = require('ethereumjs-util') +const copyToClipboard = require('copy-to-clipboard') + +class AccountDropdowns extends Component { + constructor (props) { + super(props) + this.state = { + accountSelectorActive: false, + optionsMenuActive: false, + } + this.accountSelectorToggleClassName = 'accounts-selector' + this.optionsMenuToggleClassName = 'fa-ellipsis-h' + } + + renderAccounts () { + const { identities, selected, menuItemStyles, dropdownWrapperStyle } = this.props + + return Object.keys(identities).map((key, index) => { + const identity = identities[key] + const isSelected = identity.address === selected + + return h( + DropdownMenuItem, + { + closeMenu: () => {}, + onClick: () => { + this.props.actions.showAccountDetail(identity.address) + }, + style: Object.assign( + { + marginTop: index === 0 ? '5px' : '', + fontSize: '24px', + }, + menuItemStyles, + ), + }, + [ + h( + Identicon, + { + address: identity.address, + diameter: 32, + style: { + marginLeft: '10px', + }, + }, + ), + h('span', { style: { marginLeft: '20px', fontSize: '24px' } }, identity.name || ''), + h('span', { style: { marginLeft: '20px', fontSize: '24px' } }, isSelected ? h('.check', '✓') : null), + ] + ) + }) + } + + renderAccountSelector () { + const { actions, dropdownWrapperStyle } = this.props + const { accountSelectorActive, menuItemStyles } = this.state + + return h( + Dropdown, + { + useCssTransition: true, // Hardcoded because account selector is temporarily in app-header + style: { + marginLeft: '-238px', + marginTop: '38px', + minWidth: '180px', + overflowY: 'auto', + maxHeight: '300px', + width: '300px', + }, + innerStyle: { + padding: '8px 25px', + }, + isOpen: accountSelectorActive, + onClickOutside: (event) => { + const { classList } = event.target + const isNotToggleElement = !classList.contains(this.accountSelectorToggleClassName) + if (accountSelectorActive && isNotToggleElement) { + this.setState({ accountSelectorActive: false }) + } + }, + }, + [ + ...this.renderAccounts(), + h( + DropdownMenuItem, + { + closeMenu: () => {}, + onClick: () => actions.addNewAccount(), + style: Object.assign( + {}, + menuItemStyles, + ), + }, + [ + h( + Identicon, + { + style: { + marginLeft: '10px', + }, + diameter: 32, + }, + ), + h('span', { style: { marginLeft: '20px', fontSize: '24px' } }, 'Create Account'), + ], + ), + h( + DropdownMenuItem, + { + closeMenu: () => {}, + onClick: () => actions.showImportPage(), + style: Object.assign( + {}, + menuItemStyles, + ), + }, + [ + h( + Identicon, + { + style: { + marginLeft: '10px', + }, + diameter: 32, + }, + ), + h('span', { + style: { + marginLeft: '20px', + fontSize: '24px', + marginBottom: '5px', + }, + }, 'Import Account'), + ] + ), + ] + ) + } + + renderAccountOptions () { + const { actions, dropdownWrapperStyle } = this.props + const { optionsMenuActive, menuItemStyles } = this.state + + return h( + Dropdown, + { + style: Object.assign( + { + marginLeft: '-10px', + position: 'absolute', + width: '29vh', // affects both mobile and laptop views + }, + dropdownWrapperStyle, + ), + isOpen: optionsMenuActive, + onClickOutside: () => { + const { classList } = event.target + const isNotToggleElement = !classList.contains(this.optionsMenuToggleClassName) + if (optionsMenuActive && isNotToggleElement) { + this.setState({ optionsMenuActive: false }) + } + }, + }, + [ + h( + DropdownMenuItem, + { + closeMenu: () => {}, + onClick: () => { + const { selected, network } = this.props + const url = genAccountLink(selected, network) + global.platform.openWindow({ url }) + }, + style: Object.assign( + {}, + menuItemStyles, + ), + }, + 'View account on Etherscan', + ), + h( + DropdownMenuItem, + { + closeMenu: () => {}, + onClick: () => { + const { selected, identities } = this.props + var identity = identities[selected] + actions.showQrView(selected, identity ? identity.name : '') + }, + style: Object.assign( + {}, + menuItemStyles, + ), + }, + 'Show QR Code', + ), + h( + DropdownMenuItem, + { + closeMenu: () => {}, + onClick: () => { + const { selected } = this.props + const checkSumAddress = selected && ethUtil.toChecksumAddress(selected) + copyToClipboard(checkSumAddress) + }, + style: Object.assign( + {}, + menuItemStyles, + ), + }, + 'Copy Address to clipboard', + ), + h( + DropdownMenuItem, + { + closeMenu: () => {}, + onClick: () => { + actions.requestAccountExport() + }, + style: Object.assign( + {}, + menuItemStyles, + ), + }, + 'Export Private Key', + ), + ] + ) + } + + render () { + const { style, enableAccountsSelector, enableAccountOptions, dropdownWrapperStyle } = this.props + const { optionsMenuActive, accountSelectorActive } = this.state + + return h( + 'span', + { + style: style, + }, + [ + enableAccountsSelector && h( + 'i.fa.fa-angle-down', + // 'div.cursor-pointer.color-orange.accounts-selector', + { + style: { + // fontSize: '135%', + // background: 'url(images/switch_acc.svg) white center center no-repeat', + // height: '25px', + // width: '25px', + // transform: 'scale(0.75)', + // marginRight: '3px', + }, + onClick: (event) => { + event.stopPropagation() + this.setState({ + accountSelectorActive: !accountSelectorActive, + optionsMenuActive: false, + }) + }, + }, + this.renderAccountSelector(), + ), + enableAccountOptions && h( + 'i.fa.fa-ellipsis-h', + { + style: { + fontSize: '135%', + }, + onClick: (event) => { + event.stopPropagation() + this.setState({ + accountSelectorActive: false, + optionsMenuActive: !optionsMenuActive, + }) + }, + }, + this.renderAccountOptions() + ), + ] + ) + } +} + +AccountDropdowns.defaultProps = { + enableAccountsSelector: false, + enableAccountOptions: false, +} + +AccountDropdowns.propTypes = { + identities: PropTypes.objectOf(PropTypes.object), + selected: PropTypes.string, // TODO: refactor to be more explicit: selectedAddress +} + +const mapDispatchToProps = (dispatch) => { + return { + actions: { + showConfigPage: () => dispatch(actions.showConfigPage()), + requestAccountExport: () => dispatch(actions.requestExportAccount()), + showAccountDetail: (address) => dispatch(actions.showAccountDetail(address)), + addNewAccount: () => dispatch(actions.addNewAccount()), + showImportPage: () => dispatch(actions.showImportPage()), + showQrView: (selected, identity) => dispatch(actions.showQrView(selected, identity)), + }, + } +} + +module.exports = connect(null, mapDispatchToProps)(AccountDropdowns) + diff --git a/ui/app/components/dropdowns/components/dropdown.js b/ui/app/components/dropdowns/components/dropdown.js new file mode 100644 index 000000000..1f35f0c70 --- /dev/null +++ b/ui/app/components/dropdowns/components/dropdown.js @@ -0,0 +1,95 @@ +const Component = require('react').Component +const PropTypes = require('react').PropTypes +const h = require('react-hyperscript') +const MenuDroppo = require('../../menu-droppo') +const extend = require('xtend') + +const noop = () => {} + +class Dropdown extends Component { + render () { + const { isOpen, onClickOutside, style, innerStyle, children, useCssTransition } = this.props + + const innerStyleDefaults = extend({ + borderRadius: '4px', + padding: '8px 16px', + background: 'rgba(0, 0, 0, 0.8)', + boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', + }, innerStyle) + + return h( + MenuDroppo, + { + useCssTransition, + isOpen, + zIndex: 30, + onClickOutside, + style, + innerStyle: innerStyleDefaults, + }, + [ + h( + 'style', + ` + li.dropdown-menu-item:hover { color:rgb(225, 225, 225); } + li.dropdown-menu-item { color: rgb(185, 185, 185); } + ` + ), + ...children, + ] + ) + } +} + +Dropdown.defaultProps = { + isOpen: false, + onClick: noop, + useCssTransition: false, +} + +Dropdown.propTypes = { + isOpen: PropTypes.bool.isRequired, + onClick: PropTypes.func.isRequired, + children: PropTypes.node, + style: PropTypes.object.isRequired, +} + +class DropdownMenuItem extends Component { + render () { + const { onClick, closeMenu, children, style } = this.props + + return h( + 'li.dropdown-menu-item', + { + onClick: () => { + onClick() + closeMenu() + }, + style: Object.assign({ + listStyle: 'none', + padding: '8px 0px', + fontSize: '18px', + fontStyle: 'normal', + fontFamily: 'Montserrat Regular', + cursor: 'pointer', + display: 'flex', + justifyContent: 'flex-start', + alignItems: 'center', + color: 'white', + }, style), + }, + children + ) + } +} + +DropdownMenuItem.propTypes = { + closeMenu: PropTypes.func.isRequired, + onClick: PropTypes.func.isRequired, + children: PropTypes.node, +} + +module.exports = { + Dropdown, + DropdownMenuItem, +} diff --git a/ui/app/components/dropdowns/index.js b/ui/app/components/dropdowns/index.js index 6723a2048..d21c795f5 100644 --- a/ui/app/components/dropdowns/index.js +++ b/ui/app/components/dropdowns/index.js @@ -1,16 +1,18 @@ // Reusable Dropdown Components -// const Dropdown = require('./dropdown') //TODO: Refactor into separate components -// const AccountDropdowns = require('./account-dropdowns') +//TODO: Refactor into separate components +const Dropdown = require('./components/dropdown').Dropdown +const DropdownMenuItem = require('./components/dropdown').DropdownMenuItem +const AccountDropdowns = require('./components/account-dropdowns') // App-Specific Instances -// const AccountSelectionDropdown = require('./account-selection-dropdown') -// const AccountOptionsDropdown = require('./account-options-dropdown') +const AccountSelectionDropdown = require('./account-selection-dropdown') +const AccountOptionsDropdown = require('./account-options-dropdown') const NetworkDropdown = require('./network-dropdown').default module.exports = { - // AccountSelectionDropdown, - // AccountOptionsDropdown, + AccountSelectionDropdown, + AccountOptionsDropdown, NetworkDropdown, - // Dropdown, - // AccountDropdowns, + Dropdown, + AccountDropdowns, } \ No newline at end of file diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 38b2787d5..2b3b55b6a 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -3,7 +3,7 @@ const connect = require('react-redux').connect const h = require('react-hyperscript') const inherits = require('util').inherits const Identicon = require('./identicon') -const AccountDropdowns = require('./account-dropdowns').AccountDropdowns +const AccountDropdowns = require('./dropdowns/index.js').AccountDropdowns const Content = require('./wallet-content-display') const actions = require('../actions') const BalanceComponent = require('./balance-component') -- cgit v1.2.3 From 5f775315bd3e9a724d9697d2604196bbe8d7436c Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 14 Aug 2017 08:40:16 +0200 Subject: Reconfigure AccoutSelector dropdown to use new fa-caret-down instead of old icon --- ui/app/components/dropdowns/components/account-dropdowns.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index ee41829c9..69bef3f1b 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -17,7 +17,9 @@ class AccountDropdowns extends Component { accountSelectorActive: false, optionsMenuActive: false, } - this.accountSelectorToggleClassName = 'accounts-selector' + // Used for orangeaccount selector icon + // this.accountSelectorToggleClassName = 'accounts-selector' + this.accountSelectorToggleClassName = 'fa-angle-down' this.optionsMenuToggleClassName = 'fa-ellipsis-h' } -- cgit v1.2.3 From 1743ccbdb5df504eab8e3c46c18172b176578be1 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 14 Aug 2017 08:50:49 +0200 Subject: Center account selection dropdown and specify useCssTransition prop --- ui/app/components/dropdowns/components/account-dropdowns.js | 11 ++++++----- ui/app/components/wallet-view.js | 2 ++ 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index 69bef3f1b..11d109d73 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -64,16 +64,16 @@ class AccountDropdowns extends Component { } renderAccountSelector () { - const { actions, dropdownWrapperStyle } = this.props + const { actions, dropdownWrapperStyle, useCssTransition } = this.props const { accountSelectorActive, menuItemStyles } = this.state return h( Dropdown, { - useCssTransition: true, // Hardcoded because account selector is temporarily in app-header + useCssTransition, style: { - marginLeft: '-238px', - marginTop: '38px', + marginLeft: '-185px', + marginTop: '50px', minWidth: '180px', overflowY: 'auto', maxHeight: '300px', @@ -150,12 +150,13 @@ class AccountDropdowns extends Component { } renderAccountOptions () { - const { actions, dropdownWrapperStyle } = this.props + const { actions, dropdownWrapperStyle, useCssTransition } = this.props const { optionsMenuActive, menuItemStyles } = this.state return h( Dropdown, { + useCssTransition, style: Object.assign( { marginLeft: '-10px', diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 2b3b55b6a..6bde2d9f4 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -72,6 +72,7 @@ WalletView.prototype.render = function () { selected: selectedAddress, network, identities, + useCssTransition: true, enableAccountOptions: true, dropdownWrapperStyle: { padding: '1px 15px', @@ -100,6 +101,7 @@ WalletView.prototype.render = function () { left: 'calc(50% + 28px + 5.5px)', top: '14px', }, + useCssTransition: true, selected: selectedAddress, network, identities, -- cgit v1.2.3 From 2eadf72fb772b5b6bd32f04c9d439cc0f1ab0453 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 14 Aug 2017 10:31:27 +0200 Subject: Lint and cleanup all scss --- ui/app/components/dropdowns/network-dropdown.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js index eb41f6f9b..6228513c9 100644 --- a/ui/app/components/dropdowns/network-dropdown.js +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -3,8 +3,8 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect const actions = require('../../actions') -const Dropdown = require('../dropdown').Dropdown -const DropdownMenuItem = require('../dropdown').DropdownMenuItem +const Dropdown = require('./components/dropdown').Dropdown +const DropdownMenuItem = require('./components/dropdown').DropdownMenuItem function mapStateToProps (state) { return { -- cgit v1.2.3 From 99be6e17caee1371eec86bd3232fc0d4600979cf Mon Sep 17 00:00:00 2001 From: sdtsui Date: Tue, 15 Aug 2017 05:46:41 +0200 Subject: [WiP] Add comments for multiple modals --- ui/app/components/modals/buy-modal.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/buy-modal.js b/ui/app/components/modals/buy-modal.js index 9a3e4dff9..c69433b1f 100644 --- a/ui/app/components/modals/buy-modal.js +++ b/ui/app/components/modals/buy-modal.js @@ -21,3 +21,23 @@ BuyModal.prototype.render = function () { } // TODO: specify default props and proptypes + +// Generalize to multiple modals: +// Modal API: +// - props { +// key: ['BUY', 'EDIT_ACCOUNT_NAME', 'ACCOUNT_DETAILS'] +// } +// - These props will be passed as 'active' +// mapStateToProps(state, ownProps) { +// active: state.appState.modal[key] +// } +// - Modal accepts: +// - mobileModalStyles, for mobile viewports +// - laptopModalStyles, for laptop viewports +// - backdropStyles +// - Do not set defaults, they are unneeded here +// +// If multiple-step modals are needed: +// - pass a component with internal state that tracks buy steps +// - steps could technically be in redux +// - it renders and does not trigger open/close actions until done \ No newline at end of file -- cgit v1.2.3 From 7d02c90510f119959ea04e374863ddfe13cc288b Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 20 Aug 2017 18:09:09 -0700 Subject: Add 'Add Token' dropdown menu item to account options dropdown --- .../components/dropdowns/components/account-dropdowns.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index b59f9bbf4..aaeb5d9bf 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -246,6 +246,21 @@ class AccountDropdowns extends Component { }, 'Export Private Key', ), + h( + DropdownMenuItem, + { + closeMenu: () => {}, + onClick: () => { + // Add Token Scren + }, + style: Object.assign( + {}, + menuItemStyles, + ), + }, + 'Add Token', + ), + ] ) } -- cgit v1.2.3 From e550d360842074a59832e41ce211fae7f38085cc Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 20 Aug 2017 18:10:06 -0700 Subject: Add 'Account Details' dropdown menu item to account options dropdown --- .../components/dropdowns/components/account-dropdowns.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index aaeb5d9bf..6af90655b 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -184,6 +184,20 @@ class AccountDropdowns extends Component { }, }, [ + h( + DropdownMenuItem, + { + closeMenu: () => {}, + onClick: () => { + this.props.showAccountDetail() + }, + style: Object.assign( + {}, + menuItemStyles, + ), + }, + 'Account Details', + ), h( DropdownMenuItem, { -- cgit v1.2.3 From 4e9376ca7129611d12a7ec263741f1dee0e4d79c Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 20 Aug 2017 18:32:58 -0700 Subject: Extend modal implementation and state management to accomodate multiple modal types --- ui/app/components/modals/modal.js | 16 ++++++++++++++-- ui/app/components/tx-view.js | 6 ++++-- 2 files changed, 18 insertions(+), 4 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 006e009b3..45aa09095 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -6,10 +6,20 @@ const FadeModal = require('boron').FadeModal const actions = require('../../actions') const isMobileView = require('../../../lib/is-mobile-view') const isPopupOrNotification = require('../../../../app/scripts/lib/is-popup-or-notification') +const BuyOptions = require('../buy-options') + +const MODALS = { + BUY: [ + h(BuyOptions, {}, []), + ], + EDIT_ACCOUNT_NAME: [], + ACCOUNT_DETAILS: [], +} function mapStateToProps (state) { return { - active: state.appState.modalOpen + active: state.appState.modal.open, + modalState: state.appState.modal.modalState, } } @@ -48,6 +58,8 @@ const backdropStyles = { Modal.prototype.render = function () { + const children = MODALS[this.props.modalState.name] || [] + return h(FadeModal, { className: 'modal', @@ -59,7 +71,7 @@ Modal.prototype.render = function () { modalStyle: isMobileView() ? mobileModalStyles : laptopModalStyles, backdropStyle: backdropStyles, }, - this.props.children, + children, ) } diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 0d1f3fc31..265893104 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -35,7 +35,7 @@ function mapDispatchToProps (dispatch) { return { showSidebar: () => { dispatch(actions.showSidebar()) }, hideSidebar: () => { dispatch(actions.hideSidebar()) }, - showModal: () => { dispatch(actions.showModal()) }, + showModal: (payload) => { dispatch(actions.showModal(payload)) }, } } @@ -104,7 +104,9 @@ TxView.prototype.render = function () { textAlign: 'center', }, onClick: () => { - this.props.showModal() + this.props.showModal({ + name: 'BUY', + }) }, }, 'BUY'), -- cgit v1.2.3 From 71b2dd290b2bbf3107d06d0616ec8858d21b44da Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 20 Aug 2017 19:10:49 -0700 Subject: Enhance global modal to handle Buy, Edit, and Details Modals --- ui/app/components/buy-options.js | 80 ---------------------- .../dropdowns/components/account-dropdowns.js | 5 +- ui/app/components/modals/account-details-modal.js | 73 ++++++++++++++++++++ ui/app/components/modals/buy-modal.js | 43 ------------ ui/app/components/modals/buy-options-modal.js | 80 ++++++++++++++++++++++ .../components/modals/edit-account-name-modal.js | 80 ++++++++++++++++++++++ ui/app/components/modals/index.js | 4 -- ui/app/components/modals/modal.js | 14 +++- 8 files changed, 248 insertions(+), 131 deletions(-) delete mode 100644 ui/app/components/buy-options.js create mode 100644 ui/app/components/modals/account-details-modal.js delete mode 100644 ui/app/components/modals/buy-modal.js create mode 100644 ui/app/components/modals/buy-options-modal.js create mode 100644 ui/app/components/modals/edit-account-name-modal.js (limited to 'ui/app/components') diff --git a/ui/app/components/buy-options.js b/ui/app/components/buy-options.js deleted file mode 100644 index 7d640c007..000000000 --- a/ui/app/components/buy-options.js +++ /dev/null @@ -1,80 +0,0 @@ -const Component = require('react').Component -const h = require('react-hyperscript') -const inherits = require('util').inherits -const connect = require('react-redux').connect -const actions = require('../actions') - -function mapStateToProps (state) { - return { - network: state.metamask.network, - address: state.metamask.selectedAddress, - } -} - -function mapDispatchToProps (dispatch) { - return { - toCoinbase: (address) => { - dispatch(actions.buyEth({ network: '1', address, amount: 0 })) - }, - hideModal: () => { - dispatch(actions.hideModal()) - } - } -} - -inherits(BuyOptions, Component) -function BuyOptions () { - Component.call(this) -} - -module.exports = connect(mapStateToProps, mapDispatchToProps)(BuyOptions) - -// BuyOptions is currently meant to be rendered inside -// It is the only component in this codebase that does so -// It utilizes modal styles -BuyOptions.prototype.render = function () { - return h('div', {}, [ - h('div.modal-content.transfers-subview', { - }, [ - h('div.modal-content-title-wrapper.flex-column.flex-center', { - style: {}, - }, [ - h('div.modal-content-title', { - style: {}, - }, 'Transfers'), - h('div', {}, 'How would you like to buy Ether?'), - ]), - - h('div.modal-content-options.flex-column.flex-center', {}, [ - - h('div.modal-content-option', { - onClick: () => { - const { toCoinbase, address } = this.props - toCoinbase(address) - }, - }, [ - h('div.modal-content-option-title', {}, 'Coinbase'), - h('div.modal-content-option-subtitle', {}, 'Buy with Fiat'), - ]), - - h('div.modal-content-option', {}, [ - h('div.modal-content-option-title', {}, 'Shapeshift'), - h('div.modal-content-option-subtitle', {}, 'Trade any digital asset for any other'), - ]), - - h('div.modal-content-option', {}, [ - h('div.modal-content-option-title', {}, 'Direct Deposit'), - h('div.modal-content-option-subtitle', {}, 'Deposit from another account'), - ]), - - ]), - - h('button', { - style: { - background: 'white', - }, - onClick: () => { this.props.hideModal() }, - }, h('div.modal-content-footer#modal-content-footer-text',{}, 'Cancel')), - ]) - ]) -} diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index 6af90655b..9a9fbc0fc 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -189,7 +189,7 @@ class AccountDropdowns extends Component { { closeMenu: () => {}, onClick: () => { - this.props.showAccountDetail() + this.props.actions.showAccountDetailModal() }, style: Object.assign( {}, @@ -348,6 +348,9 @@ const mapDispatchToProps = (dispatch) => { showConfigPage: () => dispatch(actions.showConfigPage()), requestAccountExport: () => dispatch(actions.requestExportAccount()), showAccountDetail: (address) => dispatch(actions.showAccountDetail(address)), + showAccountDetailModal: () => { + dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' })) + }, addNewAccount: () => dispatch(actions.addNewAccount()), showImportPage: () => dispatch(actions.showImportPage()), showQrView: (selected, identity) => dispatch(actions.showQrView(selected, identity)), diff --git a/ui/app/components/modals/account-details-modal.js b/ui/app/components/modals/account-details-modal.js new file mode 100644 index 000000000..45f54908f --- /dev/null +++ b/ui/app/components/modals/account-details-modal.js @@ -0,0 +1,73 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const connect = require('react-redux').connect +const actions = require('../../actions') + +function mapStateToProps (state) { + return { + address: state.metamask.selectedAddress, + } +} + +function mapDispatchToProps (dispatch) { + return { + hideModal: () => { + dispatch(actions.hideModal()) + } + } +} + +inherits(AccountDetailsModal, Component) +function AccountDetailsModal () { + Component.call(this) +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountDetailsModal) + +// AccountDetailsModal is currently meant to be rendered inside +// It is the only component in this codebase that does so +// It utilizes modal styles +AccountDetailsModal.prototype.render = function () { + return h('div', {}, [ + h('div.modal-content.transfers-subview', { + }, [ + h('div.modal-content-title-wrapper.flex-column.flex-center', { + style: {}, + }, [ + h('div.modal-content-title', { + style: {}, + }, 'Account Details Modal'), + h('div', {}, 'How would you like to buy Ether?'), + ]), + + h('div.modal-content-options.flex-column.flex-center', {}, [ + + h('div.modal-content-option', { + onClick: () => {}, + }, [ + h('div.modal-content-option-title', {}, 'Coinbase'), + h('div.modal-content-option-subtitle', {}, 'Buy with Fiat'), + ]), + + h('div.modal-content-option', {}, [ + h('div.modal-content-option-title', {}, 'Shapeshift'), + h('div.modal-content-option-subtitle', {}, 'Trade any digital asset for any other'), + ]), + + h('div.modal-content-option', {}, [ + h('div.modal-content-option-title', {}, 'Direct Deposit'), + h('div.modal-content-option-subtitle', {}, 'Deposit from another account'), + ]), + + ]), + + h('button', { + style: { + background: 'white', + }, + onClick: () => { this.props.hideModal() }, + }, h('div.modal-content-footer#modal-content-footer-text',{}, 'Cancel')), + ]) + ]) +} diff --git a/ui/app/components/modals/buy-modal.js b/ui/app/components/modals/buy-modal.js deleted file mode 100644 index c69433b1f..000000000 --- a/ui/app/components/modals/buy-modal.js +++ /dev/null @@ -1,43 +0,0 @@ -const Component = require('react').Component -const h = require('react-hyperscript') -const inherits = require('util').inherits -const BuyOptions = require('../buy-options') -const Modal = require('./modal.js') - -inherits(BuyModal, Component) -function BuyModal () { - Component.call(this) -} - -module.exports = BuyModal - -BuyModal.prototype.render = function () { - return h(Modal, { - ref: "modalRef", - }, [ - h(BuyOptions, {}, []), - ]) - -} - -// TODO: specify default props and proptypes - -// Generalize to multiple modals: -// Modal API: -// - props { -// key: ['BUY', 'EDIT_ACCOUNT_NAME', 'ACCOUNT_DETAILS'] -// } -// - These props will be passed as 'active' -// mapStateToProps(state, ownProps) { -// active: state.appState.modal[key] -// } -// - Modal accepts: -// - mobileModalStyles, for mobile viewports -// - laptopModalStyles, for laptop viewports -// - backdropStyles -// - Do not set defaults, they are unneeded here -// -// If multiple-step modals are needed: -// - pass a component with internal state that tracks buy steps -// - steps could technically be in redux -// - it renders and does not trigger open/close actions until done \ No newline at end of file diff --git a/ui/app/components/modals/buy-options-modal.js b/ui/app/components/modals/buy-options-modal.js new file mode 100644 index 000000000..170ac96b8 --- /dev/null +++ b/ui/app/components/modals/buy-options-modal.js @@ -0,0 +1,80 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const connect = require('react-redux').connect +const actions = require('../../actions') + +function mapStateToProps (state) { + return { + network: state.metamask.network, + address: state.metamask.selectedAddress, + } +} + +function mapDispatchToProps (dispatch) { + return { + toCoinbase: (address) => { + dispatch(actions.buyEth({ network: '1', address, amount: 0 })) + }, + hideModal: () => { + dispatch(actions.hideModal()) + } + } +} + +inherits(BuyOptions, Component) +function BuyOptions () { + Component.call(this) +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)(BuyOptions) + +// BuyOptions is currently meant to be rendered inside +// It is the only component in this codebase that does so +// It utilizes modal styles +BuyOptions.prototype.render = function () { + return h('div', {}, [ + h('div.modal-content.transfers-subview', { + }, [ + h('div.modal-content-title-wrapper.flex-column.flex-center', { + style: {}, + }, [ + h('div.modal-content-title', { + style: {}, + }, 'Transfers'), + h('div', {}, 'How would you like to buy Ether?'), + ]), + + h('div.modal-content-options.flex-column.flex-center', {}, [ + + h('div.modal-content-option', { + onClick: () => { + const { toCoinbase, address } = this.props + toCoinbase(address) + }, + }, [ + h('div.modal-content-option-title', {}, 'Coinbase'), + h('div.modal-content-option-subtitle', {}, 'Buy with Fiat'), + ]), + + h('div.modal-content-option', {}, [ + h('div.modal-content-option-title', {}, 'Shapeshift'), + h('div.modal-content-option-subtitle', {}, 'Trade any digital asset for any other'), + ]), + + h('div.modal-content-option', {}, [ + h('div.modal-content-option-title', {}, 'Direct Deposit'), + h('div.modal-content-option-subtitle', {}, 'Deposit from another account'), + ]), + + ]), + + h('button', { + style: { + background: 'white', + }, + onClick: () => { this.props.hideModal() }, + }, h('div.modal-content-footer#modal-content-footer-text',{}, 'Cancel')), + ]) + ]) +} diff --git a/ui/app/components/modals/edit-account-name-modal.js b/ui/app/components/modals/edit-account-name-modal.js new file mode 100644 index 000000000..5d2d2e120 --- /dev/null +++ b/ui/app/components/modals/edit-account-name-modal.js @@ -0,0 +1,80 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const connect = require('react-redux').connect +const actions = require('../../actions') + +function mapStateToProps (state) { + return { + network: state.metamask.network, + address: state.metamask.selectedAddress, + } +} + +function mapDispatchToProps (dispatch) { + return { + toCoinbase: (address) => { + dispatch(actions.buyEth({ network: '1', address, amount: 0 })) + }, + hideModal: () => { + dispatch(actions.hideModal()) + } + } +} + +inherits(BuyOptions, Component) +function BuyOptions () { + Component.call(this) +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)(BuyOptions) + +// BuyOptions is currently meant to be rendered inside +// It is the only component in this codebase that does so +// It utilizes modal styles +BuyOptions.prototype.render = function () { + return h('div', {}, [ + h('div.modal-content.transfers-subview', { + }, [ + h('div.modal-content-title-wrapper.flex-column.flex-center', { + style: {}, + }, [ + h('div.modal-content-title', { + style: {}, + }, 'Edit Account Name Modal'), + h('div', {}, 'How would you like to buy Ether?'), + ]), + + h('div.modal-content-options.flex-column.flex-center', {}, [ + + h('div.modal-content-option', { + onClick: () => { + const { toCoinbase, address } = this.props + toCoinbase(address) + }, + }, [ + h('div.modal-content-option-title', {}, 'Coinbase'), + h('div.modal-content-option-subtitle', {}, 'Buy with Fiat'), + ]), + + h('div.modal-content-option', {}, [ + h('div.modal-content-option-title', {}, 'Shapeshift'), + h('div.modal-content-option-subtitle', {}, 'Trade any digital asset for any other'), + ]), + + h('div.modal-content-option', {}, [ + h('div.modal-content-option-title', {}, 'Direct Deposit'), + h('div.modal-content-option-subtitle', {}, 'Deposit from another account'), + ]), + + ]), + + h('button', { + style: { + background: 'white', + }, + onClick: () => { this.props.hideModal() }, + }, h('div.modal-content-footer#modal-content-footer-text',{}, 'Cancel')), + ]) + ]) +} diff --git a/ui/app/components/modals/index.js b/ui/app/components/modals/index.js index 23b432b7c..e2e367af0 100644 --- a/ui/app/components/modals/index.js +++ b/ui/app/components/modals/index.js @@ -1,9 +1,5 @@ const Modal = require('./modal') -const BuyModal = require('./buy-modal') -// const h = require('account-options') -// const h = require('account-details') module.exports = { Modal, - BuyModal, } \ No newline at end of file diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 45aa09095..04a34cfed 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -6,14 +6,22 @@ const FadeModal = require('boron').FadeModal const actions = require('../../actions') const isMobileView = require('../../../lib/is-mobile-view') const isPopupOrNotification = require('../../../../app/scripts/lib/is-popup-or-notification') -const BuyOptions = require('../buy-options') + +// Modal Components +const BuyOptions = require('./buy-options-modal') +const AccountDetailsModal = require('./account-details-modal') +const EditAccountNameModal = require('./edit-account-name-modal') const MODALS = { BUY: [ h(BuyOptions, {}, []), ], - EDIT_ACCOUNT_NAME: [], - ACCOUNT_DETAILS: [], + EDIT_ACCOUNT_NAME: [ + h(AccountDetailsModal, {}, []), + ], + ACCOUNT_DETAILS: [ + h(EditAccountNameModal, {}, []), + ], } function mapStateToProps (state) { -- cgit v1.2.3 From 73a593b42e3a81b721cfa2f8913565a8b800f983 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 20 Aug 2017 19:28:20 -0700 Subject: Hook up template for New Account Modal --- .../dropdowns/components/account-dropdowns.js | 12 +++- ui/app/components/modals/modal.js | 4 ++ ui/app/components/modals/new-account-modal.js | 80 ++++++++++++++++++++++ 3 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 ui/app/components/modals/new-account-modal.js (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index 9a9fbc0fc..3d32ca7fb 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -46,6 +46,7 @@ class AccountDropdowns extends Component { ), }, [ + // MOVE CHECKMARK UP h( Identicon, { @@ -67,6 +68,7 @@ class AccountDropdowns extends Component { }, }, identity.name || ''), h('span', { style: { marginLeft: '20px', fontSize: '24px' } }, isSelected ? h('.check', '✓') : null), + // EDIT ] ) }) @@ -122,7 +124,12 @@ class AccountDropdowns extends Component { diameter: 32, }, ), - h('span', { style: { marginLeft: '20px', fontSize: '24px' } }, 'Create Account'), + h('span', { + style: { marginLeft: '20px', fontSize: '24px' }, + onClick: () => { + actions.showNewAccountModal() + }, + }, 'Create Account'), ], ), h( @@ -351,6 +358,9 @@ const mapDispatchToProps = (dispatch) => { showAccountDetailModal: () => { dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' })) }, + showNewAccountModal: () => { + dispatch(actions.showModal({ name: 'NEW_ACCOUNT' })) + }, addNewAccount: () => dispatch(actions.addNewAccount()), showImportPage: () => dispatch(actions.showImportPage()), showQrView: (selected, identity) => dispatch(actions.showQrView(selected, identity)), diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 04a34cfed..4b3d3b09c 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -11,6 +11,7 @@ const isPopupOrNotification = require('../../../../app/scripts/lib/is-popup-or-n const BuyOptions = require('./buy-options-modal') const AccountDetailsModal = require('./account-details-modal') const EditAccountNameModal = require('./edit-account-name-modal') +const NewAccountModal = require('./new-account-modal') const MODALS = { BUY: [ @@ -22,6 +23,9 @@ const MODALS = { ACCOUNT_DETAILS: [ h(EditAccountNameModal, {}, []), ], + NEW_ACCOUNT: [ + h(NewAccountModal, {}, []), + ] } function mapStateToProps (state) { diff --git a/ui/app/components/modals/new-account-modal.js b/ui/app/components/modals/new-account-modal.js new file mode 100644 index 000000000..e4b3ca328 --- /dev/null +++ b/ui/app/components/modals/new-account-modal.js @@ -0,0 +1,80 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const connect = require('react-redux').connect +const actions = require('../../actions') + +function mapStateToProps (state) { + return { + network: state.metamask.network, + address: state.metamask.selectedAddress, + } +} + +function mapDispatchToProps (dispatch) { + return { + toCoinbase: (address) => { + dispatch(actions.buyEth({ network: '1', address, amount: 0 })) + }, + hideModal: () => { + dispatch(actions.hideModal()) + } + } +} + +inherits(BuyOptions, Component) +function BuyOptions () { + Component.call(this) +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)(BuyOptions) + +// BuyOptions is currently meant to be rendered inside +// It is the only component in this codebase that does so +// It utilizes modal styles +BuyOptions.prototype.render = function () { + return h('div', {}, [ + h('div.modal-content.transfers-subview', { + }, [ + h('div.modal-content-title-wrapper.flex-column.flex-center', { + style: {}, + }, [ + h('div.modal-content-title', { + style: {}, + }, 'New Account Modal'), + h('div', {}, 'How would you like to buy Ether?'), + ]), + + h('div.modal-content-options.flex-column.flex-center', {}, [ + + h('div.modal-content-option', { + onClick: () => { + const { toCoinbase, address } = this.props + toCoinbase(address) + }, + }, [ + h('div.modal-content-option-title', {}, 'Coinbase'), + h('div.modal-content-option-subtitle', {}, 'Buy with Fiat'), + ]), + + h('div.modal-content-option', {}, [ + h('div.modal-content-option-title', {}, 'Shapeshift'), + h('div.modal-content-option-subtitle', {}, 'Trade any digital asset for any other'), + ]), + + h('div.modal-content-option', {}, [ + h('div.modal-content-option-title', {}, 'Direct Deposit'), + h('div.modal-content-option-subtitle', {}, 'Deposit from another account'), + ]), + + ]), + + h('button', { + style: { + background: 'white', + }, + onClick: () => { this.props.hideModal() }, + }, h('div.modal-content-footer#modal-content-footer-text',{}, 'Cancel')), + ]) + ]) +} -- cgit v1.2.3 From beedd5b11e6004b32aff9b45663dfdb4fb6e2d2e Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 20 Aug 2017 19:29:14 -0700 Subject: Remove old design - 'Show QR Code' dropdown menu item from account selection dropdown --- .../components/dropdowns/components/account-dropdowns.js | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index 3d32ca7fb..691c41f30 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -221,22 +221,6 @@ class AccountDropdowns extends Component { }, 'View account on Etherscan', ), - h( - DropdownMenuItem, - { - closeMenu: () => {}, - onClick: () => { - const { selected, identities } = this.props - var identity = identities[selected] - actions.showQrView(selected, identity ? identity.name : '') - }, - style: Object.assign( - {}, - menuItemStyles, - ), - }, - 'Show QR Code', - ), h( DropdownMenuItem, { -- cgit v1.2.3 From 18ea874a801c5252adb00317647c828810c33634 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 20 Aug 2017 19:39:37 -0700 Subject: Hook up edit account name modal --- .../dropdowns/components/account-dropdowns.js | 68 +++++++++++++--------- 1 file changed, 42 insertions(+), 26 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index 691c41f30..f6606d8bb 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -24,7 +24,7 @@ class AccountDropdowns extends Component { } renderAccounts () { - const { identities, selected, menuItemStyles, dropdownWrapperStyle } = this.props + const { identities, selected, menuItemStyles, dropdownWrapperStyle, actions } = this.props return Object.keys(identities).map((key, index) => { const identity = identities[key] @@ -46,29 +46,47 @@ class AccountDropdowns extends Component { ), }, [ - // MOVE CHECKMARK UP - h( - Identicon, - { - address: identity.address, - diameter: 32, + h('div.flex-row', {}, [ + + h('span', { style: { - marginLeft: '10px', + flex: '1 1 auto', + } + }, isSelected ? h('.check', '✓') : null), + + h( + Identicon, + { + address: identity.address, + diameter: 32, + style: { + flex: '1 1 auto', + }, }, - }, - ), - h('span', { - style: { - marginLeft: '20px', - fontSize: '24px', - maxWidth: '145px', - whiteSpace: 'nowrap', - overflow: 'hidden', - textOverflow: 'ellipsis', - }, - }, identity.name || ''), - h('span', { style: { marginLeft: '20px', fontSize: '24px' } }, isSelected ? h('.check', '✓') : null), - // EDIT + ), + + h('span', { + style: { + flex: '5 5 auto', + fontSize: '24px', + maxWidth: '145px', + whiteSpace: 'nowrap', + overflow: 'hidden', + textOverflow: 'ellipsis', + }, + }, identity.name || ''), + + h('span', { + style: { + flex: '2 2 auto', + fontSize: '18px', + }, + onClick: () => { + actions.showNewAccountModal() + } + }, 'Edit'), + + ]) ] ) }) @@ -90,9 +108,7 @@ class AccountDropdowns extends Component { maxHeight: '300px', width: '300px', }, - innerStyle: { - padding: '8px 25px', - }, + innerStyle: {}, isOpen: accountSelectorActive, onClickOutside: (event) => { const { classList } = event.target @@ -343,7 +359,7 @@ const mapDispatchToProps = (dispatch) => { dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' })) }, showNewAccountModal: () => { - dispatch(actions.showModal({ name: 'NEW_ACCOUNT' })) + dispatch(actions.showModal({ name: 'EDIT_ACCOUNT_NAME' })) }, addNewAccount: () => dispatch(actions.addNewAccount()), showImportPage: () => dispatch(actions.showImportPage()), -- cgit v1.2.3 From 66829b7a05322320855b077c04f885908bd95efa Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 21 Aug 2017 03:27:11 -0700 Subject: Implement new dropdown design, integrate account balances --- .../dropdowns/components/account-dropdowns.js | 84 +++++++++++++++------- ui/app/components/modals/modal.js | 4 +- ui/app/components/wallet-view.js | 6 +- 3 files changed, 67 insertions(+), 27 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index f6606d8bb..043789b6c 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -9,6 +9,7 @@ const DropdownMenuItem = require('./dropdown').DropdownMenuItem const Identicon = require('../../identicon') const ethUtil = require('ethereumjs-util') const copyToClipboard = require('copy-to-clipboard') +const { formatBalance } = require('../../../util') class AccountDropdowns extends Component { constructor (props) { @@ -24,12 +25,15 @@ class AccountDropdowns extends Component { } renderAccounts () { - const { identities, selected, menuItemStyles, dropdownWrapperStyle, actions } = this.props + const { identities, accounts, selected, menuItemStyles, dropdownWrapperStyle, actions } = this.props return Object.keys(identities).map((key, index) => { const identity = identities[key] const isSelected = identity.address === selected + const balanceValue = accounts[key].balance + const formattedBalance = balanceValue ? formatBalance(balanceValue, 6) : '...' + return h( DropdownMenuItem, { @@ -46,45 +50,77 @@ class AccountDropdowns extends Component { ), }, [ - h('div.flex-row', {}, [ + h('div.flex-row.flex-center', {}, [ h('span', { style: { - flex: '1 1 auto', + flex: '1 1 0', + minWidth: '20px', + minHeight: '30px', } - }, isSelected ? h('.check', '✓') : null), + }, [ + h('span', { + style: { + flex: '1 1 auto', + fontSize: '14px', + } + }, isSelected ? h('i.fa.fa-check') : null), + ]), h( Identicon, { address: identity.address, - diameter: 32, + diameter: 24, style: { flex: '1 1 auto', + marginLeft: '10px', }, }, ), - h('span', { + h('span.flex-column', { style: { - flex: '5 5 auto', - fontSize: '24px', - maxWidth: '145px', - whiteSpace: 'nowrap', - overflow: 'hidden', - textOverflow: 'ellipsis', - }, - }, identity.name || ''), + flex: '10 10 auto', + width: '175px', + alignItems: 'flex-start', + justifyContent: 'center', + marginLeft: '10px', + } + }, [ + h('span.account-dropdown-name', { + style: { + fontSize: '18px', + maxWidth: '145px', + whiteSpace: 'nowrap', + overflow: 'hidden', + textOverflow: 'ellipsis', + }, + }, identity.name || ''), + + h('span.account-dropdown-balance', { + style: { + fontSize: '14px', + }, + }, formattedBalance) + ]), h('span', { style: { - flex: '2 2 auto', - fontSize: '18px', + flex: '3 3 auto', }, - onClick: () => { - actions.showNewAccountModal() - } - }, 'Edit'), + }, [ + h('span.account-dropdown-edit-button', { + style: { + fontSize: '16px', + }, + onClick: () => { + actions.showNewAccountModal() + }, + }, [ + 'Edit', + ]) + ]), ]) ] @@ -93,7 +129,7 @@ class AccountDropdowns extends Component { } renderAccountSelector () { - const { actions, dropdownWrapperStyle, useCssTransition } = this.props + const { actions, dropdownWrapperStyle, useCssTransition, innerStyle } = this.props const { accountSelectorActive, menuItemStyles } = this.state return h( @@ -108,7 +144,7 @@ class AccountDropdowns extends Component { maxHeight: '300px', width: '300px', }, - innerStyle: {}, + innerStyle, isOpen: accountSelectorActive, onClickOutside: (event) => { const { classList } = event.target @@ -141,7 +177,7 @@ class AccountDropdowns extends Component { }, ), h('span', { - style: { marginLeft: '20px', fontSize: '24px' }, + style: { marginLeft: '20px', fontSize: '18px' }, onClick: () => { actions.showNewAccountModal() }, @@ -171,7 +207,7 @@ class AccountDropdowns extends Component { h('span', { style: { marginLeft: '20px', - fontSize: '24px', + fontSize: '18px', marginBottom: '5px', }, }, 'Import Account'), diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 4b3d3b09c..77391dfcc 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -18,10 +18,10 @@ const MODALS = { h(BuyOptions, {}, []), ], EDIT_ACCOUNT_NAME: [ - h(AccountDetailsModal, {}, []), + h(EditAccountNameModal, {}, []), ], ACCOUNT_DETAILS: [ - h(EditAccountNameModal, {}, []), + h(AccountDetailsModal, {}, []), ], NEW_ACCOUNT: [ h(NewAccountModal, {}, []), diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 6bde2d9f4..a92ec418e 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -39,7 +39,7 @@ function WalletView () { const noop = () => {} WalletView.prototype.render = function () { - const { network, responsiveDisplayClassname, style, identities, selectedAddress, selectedAccount } = this.props + const { network, responsiveDisplayClassname, style, identities, selectedAddress, selectedAccount, accounts } = this.props // temporary logs + fake extra wallets console.log(selectedAccount) @@ -96,11 +96,15 @@ WalletView.prototype.render = function () { } }, [ h(AccountDropdowns, { + accounts, style: { position: 'absolute', left: 'calc(50% + 28px + 5.5px)', top: '14px', }, + innerStyle: { + padding: '2px 16px', + }, useCssTransition: true, selected: selectedAddress, network, -- cgit v1.2.3 From 80a2cba38ef4fe6c01a624c5a504a7803b1a8316 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 21 Aug 2017 03:53:01 -0700 Subject: Enhance global modal to accept styles from different components --- ui/app/components/modals/modal.js | 107 ++++++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 45 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 77391dfcc..e2c5f77cc 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -14,18 +14,63 @@ const EditAccountNameModal = require('./edit-account-name-modal') const NewAccountModal = require('./new-account-modal') const MODALS = { - BUY: [ - h(BuyOptions, {}, []), - ], - EDIT_ACCOUNT_NAME: [ - h(EditAccountNameModal, {}, []), - ], - ACCOUNT_DETAILS: [ - h(AccountDetailsModal, {}, []), - ], - NEW_ACCOUNT: [ - h(NewAccountModal, {}, []), - ] + BUY: { + contents: [ + h(BuyOptions, {}, []), + ], + mobileModalStyle: { + width: '95%', + top: isPopupOrNotification() === 'popup' ? '48vh' : '36.5vh', + boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', + }, + laptopModalStyle: { + width: '66%', + top: 'calc(30% + 10px)', + boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', + }, + }, + + EDIT_ACCOUNT_NAME: { + contents: [ + h(EditAccountNameModal, {}, []), + ], + mobileModalStyle: { + width: '95%', + top: isPopupOrNotification() === 'popup' ? '48vh' : '36.5vh', + boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', + }, + laptopModalStyle: { + width: '45%', + top: 'calc(30% + 10px)', + boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', + }, + }, + + ACCOUNT_DETAILS: { + contents: [ + h(AccountDetailsModal, {}, []), + ], + mobileModalStyle: {}, + laptopModalStyle: {}, + }, + + NEW_ACCOUNT: { + contents: [ + h(NewAccountModal, {}, []), + ], + mobileModalStyle: {}, + laptopModalStyle: {} + }, + + DEFAULT: { + contents: [], + mobileModalStyle: {}, + laptopModalStyle: {}, + } +} + +const BACKDROPSTYLE = { + backgroundColor: 'rgba(245, 245, 245, 0.85)', } function mapStateToProps (state) { @@ -51,26 +96,11 @@ function Modal () { module.exports = connect(mapStateToProps, mapDispatchToProps)(Modal) -const mobileModalStyles = { - width: '95%', - // Used to create matching t/l/r/b space in mobile view. - top: isPopupOrNotification() === 'popup' ? '48vh' : '36.5vh', - boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', -} - -const laptopModalStyles = { - width: '66%', - top: 'calc(30% + 10px)', - boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', -} - -const backdropStyles = { - backgroundColor: 'rgba(245, 245, 245, 0.85)', -} - Modal.prototype.render = function () { + const modal = MODALS[this.props.modalState.name || 'DEFAULT'] - const children = MODALS[this.props.modalState.name] || [] + const children = modal.contents + const modalStyle = modal[isMobileView() ? 'mobileModalStyle' : 'laptopModalStyle'] return h(FadeModal, { @@ -80,8 +110,8 @@ Modal.prototype.render = function () { ref: (ref) => { this.modalRef = ref }, - modalStyle: isMobileView() ? mobileModalStyles : laptopModalStyles, - backdropStyle: backdropStyles, + modalStyle, + backdropStyle: BACKDROPSTYLE, }, children, ) @@ -109,16 +139,3 @@ Modal.prototype.hide = function() { Modal.prototype.show = function() { this.modalRef.show() } - -// TODO: specify default props and proptypes -// Modal.defaultProps = {} - -// const elementType = require('react-prop-types/lib/elementType') -// const PropTypes from 'prop-types' - -// Modal.propTypes = { -// active: PropTypes.bool, -// hideModal: PropTypes.func.isRequired, -// component: elementType, -// onHideCallback: PropTypes.func, -// } -- cgit v1.2.3 From d82233b95c5c3c4297a2d18b981ec6188de003c1 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 21 Aug 2017 04:46:38 -0700 Subject: Hook up actions to EditAccountNameModal --- .../dropdowns/components/account-dropdowns.js | 10 ++- ui/app/components/modals/account-details-modal.js | 28 +++---- ui/app/components/modals/buy-options-modal.js | 28 +++---- .../components/modals/edit-account-name-modal.js | 85 ++++++++++------------ ui/app/components/modals/new-account-modal.js | 28 +++---- 5 files changed, 90 insertions(+), 89 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index 043789b6c..2854ec95d 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -115,7 +115,7 @@ class AccountDropdowns extends Component { fontSize: '16px', }, onClick: () => { - actions.showNewAccountModal() + actions.showEditAccountModal(identity) }, }, [ 'Edit', @@ -394,8 +394,14 @@ const mapDispatchToProps = (dispatch) => { showAccountDetailModal: () => { dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' })) }, + showEditAccountModal: (identity) => { + dispatch(actions.showModal({ + name: 'EDIT_ACCOUNT_NAME', + identity, + })) + }, showNewAccountModal: () => { - dispatch(actions.showModal({ name: 'EDIT_ACCOUNT_NAME' })) + dispatch(actions.showModal({ name: 'NEW_ACCOUNT' })) }, addNewAccount: () => dispatch(actions.addNewAccount()), showImportPage: () => dispatch(actions.showImportPage()), diff --git a/ui/app/components/modals/account-details-modal.js b/ui/app/components/modals/account-details-modal.js index 45f54908f..38d08314b 100644 --- a/ui/app/components/modals/account-details-modal.js +++ b/ui/app/components/modals/account-details-modal.js @@ -30,34 +30,34 @@ module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountDetailsModa // It utilizes modal styles AccountDetailsModal.prototype.render = function () { return h('div', {}, [ - h('div.modal-content.transfers-subview', { + h('div.buy-modal-content.transfers-subview', { }, [ - h('div.modal-content-title-wrapper.flex-column.flex-center', { + h('div.buy-modal-content-title-wrapper.flex-column.flex-center', { style: {}, }, [ - h('div.modal-content-title', { + h('div.buy-modal-content-title', { style: {}, }, 'Account Details Modal'), h('div', {}, 'How would you like to buy Ether?'), ]), - h('div.modal-content-options.flex-column.flex-center', {}, [ + h('div.buy-modal-content-options.flex-column.flex-center', {}, [ - h('div.modal-content-option', { + h('div.buy-modal-content-option', { onClick: () => {}, }, [ - h('div.modal-content-option-title', {}, 'Coinbase'), - h('div.modal-content-option-subtitle', {}, 'Buy with Fiat'), + h('div.buy-modal-content-option-title', {}, 'Coinbase'), + h('div.buy-modal-content-option-subtitle', {}, 'Buy with Fiat'), ]), - h('div.modal-content-option', {}, [ - h('div.modal-content-option-title', {}, 'Shapeshift'), - h('div.modal-content-option-subtitle', {}, 'Trade any digital asset for any other'), + h('div.buy-modal-content-option', {}, [ + h('div.buy-modal-content-option-title', {}, 'Shapeshift'), + h('div.buy-modal-content-option-subtitle', {}, 'Trade any digital asset for any other'), ]), - h('div.modal-content-option', {}, [ - h('div.modal-content-option-title', {}, 'Direct Deposit'), - h('div.modal-content-option-subtitle', {}, 'Deposit from another account'), + h('div.buy-modal-content-option', {}, [ + h('div.buy-modal-content-option-title', {}, 'Direct Deposit'), + h('div.buy-modal-content-option-subtitle', {}, 'Deposit from another account'), ]), ]), @@ -67,7 +67,7 @@ AccountDetailsModal.prototype.render = function () { background: 'white', }, onClick: () => { this.props.hideModal() }, - }, h('div.modal-content-footer#modal-content-footer-text',{}, 'Cancel')), + }, h('div.buy-modal-content-footer#buy-modal-content-footer-text',{}, 'Cancel')), ]) ]) } diff --git a/ui/app/components/modals/buy-options-modal.js b/ui/app/components/modals/buy-options-modal.js index 170ac96b8..76e0da4f1 100644 --- a/ui/app/components/modals/buy-options-modal.js +++ b/ui/app/components/modals/buy-options-modal.js @@ -34,37 +34,37 @@ module.exports = connect(mapStateToProps, mapDispatchToProps)(BuyOptions) // It utilizes modal styles BuyOptions.prototype.render = function () { return h('div', {}, [ - h('div.modal-content.transfers-subview', { + h('div.buy-modal-content.transfers-subview', { }, [ - h('div.modal-content-title-wrapper.flex-column.flex-center', { + h('div.buy-modal-content-title-wrapper.flex-column.flex-center', { style: {}, }, [ - h('div.modal-content-title', { + h('div.buy-modal-content-title', { style: {}, }, 'Transfers'), h('div', {}, 'How would you like to buy Ether?'), ]), - h('div.modal-content-options.flex-column.flex-center', {}, [ + h('div.buy-modal-content-options.flex-column.flex-center', {}, [ - h('div.modal-content-option', { + h('div.buy-modal-content-option', { onClick: () => { const { toCoinbase, address } = this.props toCoinbase(address) }, }, [ - h('div.modal-content-option-title', {}, 'Coinbase'), - h('div.modal-content-option-subtitle', {}, 'Buy with Fiat'), + h('div.buy-modal-content-option-title', {}, 'Coinbase'), + h('div.buy-modal-content-option-subtitle', {}, 'Buy with Fiat'), ]), - h('div.modal-content-option', {}, [ - h('div.modal-content-option-title', {}, 'Shapeshift'), - h('div.modal-content-option-subtitle', {}, 'Trade any digital asset for any other'), + h('div.buy-modal-content-option', {}, [ + h('div.buy-modal-content-option-title', {}, 'Shapeshift'), + h('div.buy-modal-content-option-subtitle', {}, 'Trade any digital asset for any other'), ]), - h('div.modal-content-option', {}, [ - h('div.modal-content-option-title', {}, 'Direct Deposit'), - h('div.modal-content-option-subtitle', {}, 'Deposit from another account'), + h('div.buy-modal-content-option', {}, [ + h('div.buy-modal-content-option-title', {}, 'Direct Deposit'), + h('div.buy-modal-content-option-subtitle', {}, 'Deposit from another account'), ]), ]), @@ -74,7 +74,7 @@ BuyOptions.prototype.render = function () { background: 'white', }, onClick: () => { this.props.hideModal() }, - }, h('div.modal-content-footer#modal-content-footer-text',{}, 'Cancel')), + }, h('div.buy-modal-content-footer#buy-modal-content-footer-text',{}, 'Cancel')), ]) ]) } diff --git a/ui/app/components/modals/edit-account-name-modal.js b/ui/app/components/modals/edit-account-name-modal.js index 5d2d2e120..0128fe412 100644 --- a/ui/app/components/modals/edit-account-name-modal.js +++ b/ui/app/components/modals/edit-account-name-modal.js @@ -3,78 +3,73 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect const actions = require('../../actions') +const { getSelectedAccount } = require('../../selectors') function mapStateToProps (state) { return { - network: state.metamask.network, - address: state.metamask.selectedAddress, + selectedAccount: getSelectedAccount(state), + identity: state.appState.modal.modalState.identity, } } function mapDispatchToProps (dispatch) { return { - toCoinbase: (address) => { - dispatch(actions.buyEth({ network: '1', address, amount: 0 })) - }, hideModal: () => { dispatch(actions.hideModal()) - } + }, + saveAccountLabel: (account, label) => { + dispatch(actions.saveAccountLabel(account, label)) + }, } } -inherits(BuyOptions, Component) -function BuyOptions () { +inherits(EditAccountNameModal, Component) +function EditAccountNameModal () { Component.call(this) + this.state = { + inputText: '', + } } -module.exports = connect(mapStateToProps, mapDispatchToProps)(BuyOptions) +module.exports = connect(mapStateToProps, mapDispatchToProps)(EditAccountNameModal) -// BuyOptions is currently meant to be rendered inside +// EditAccountNameModal is currently meant to be rendered inside // It is the only component in this codebase that does so // It utilizes modal styles -BuyOptions.prototype.render = function () { +EditAccountNameModal.prototype.render = function () { + const { hideModal, saveAccountLabel, identity } = this.props + return h('div', {}, [ - h('div.modal-content.transfers-subview', { + h('div.flex-column.edit-account-name-modal-content', { }, [ - h('div.modal-content-title-wrapper.flex-column.flex-center', { - style: {}, - }, [ - h('div.modal-content-title', { - style: {}, - }, 'Edit Account Name Modal'), - h('div', {}, 'How would you like to buy Ether?'), - ]), - h('div.modal-content-options.flex-column.flex-center', {}, [ - - h('div.modal-content-option', { - onClick: () => { - const { toCoinbase, address } = this.props - toCoinbase(address) - }, - }, [ - h('div.modal-content-option-title', {}, 'Coinbase'), - h('div.modal-content-option-subtitle', {}, 'Buy with Fiat'), - ]), + h('div.edit-account-name-modal-cancel', {}, [ + h('i.fa.fa-times'), + ]), - h('div.modal-content-option', {}, [ - h('div.modal-content-option-title', {}, 'Shapeshift'), - h('div.modal-content-option-subtitle', {}, 'Trade any digital asset for any other'), - ]), + h('div.edit-account-name-modal-title', { + }, ['Edit Account Name']), - h('div.modal-content-option', {}, [ - h('div.modal-content-option-title', {}, 'Direct Deposit'), - h('div.modal-content-option-subtitle', {}, 'Deposit from another account'), - ]), + h('input.edit-account-name-modal-input', { + placeholder: identity.name, + onChange: (event) => { + this.setState({ inputText: event.target.value }) + }, + value: this.state.inputText, + }, []), + h('button.btn-clear.edit-account-name-modal-save-button', { + onClick: () => { + if (this.state.inputText.length !== 0) { + saveAccountLabel(identity.address, this.state.inputText) + hideModal() + } + }, + disabled: this.state.inputText.length === 0, + }, [ + 'SAVE', ]), - h('button', { - style: { - background: 'white', - }, - onClick: () => { this.props.hideModal() }, - }, h('div.modal-content-footer#modal-content-footer-text',{}, 'Cancel')), ]) ]) } diff --git a/ui/app/components/modals/new-account-modal.js b/ui/app/components/modals/new-account-modal.js index e4b3ca328..c55d69964 100644 --- a/ui/app/components/modals/new-account-modal.js +++ b/ui/app/components/modals/new-account-modal.js @@ -34,37 +34,37 @@ module.exports = connect(mapStateToProps, mapDispatchToProps)(BuyOptions) // It utilizes modal styles BuyOptions.prototype.render = function () { return h('div', {}, [ - h('div.modal-content.transfers-subview', { + h('div.buy-modal-content.transfers-subview', { }, [ - h('div.modal-content-title-wrapper.flex-column.flex-center', { + h('div.buy-modal-content-title-wrapper.flex-column.flex-center', { style: {}, }, [ - h('div.modal-content-title', { + h('div.buy-modal-content-title', { style: {}, }, 'New Account Modal'), h('div', {}, 'How would you like to buy Ether?'), ]), - h('div.modal-content-options.flex-column.flex-center', {}, [ + h('div.buy-modal-content-options.flex-column.flex-center', {}, [ - h('div.modal-content-option', { + h('div.buy-modal-content-option', { onClick: () => { const { toCoinbase, address } = this.props toCoinbase(address) }, }, [ - h('div.modal-content-option-title', {}, 'Coinbase'), - h('div.modal-content-option-subtitle', {}, 'Buy with Fiat'), + h('div.buy-modal-content-option-title', {}, 'Coinbase'), + h('div.buy-modal-content-option-subtitle', {}, 'Buy with Fiat'), ]), - h('div.modal-content-option', {}, [ - h('div.modal-content-option-title', {}, 'Shapeshift'), - h('div.modal-content-option-subtitle', {}, 'Trade any digital asset for any other'), + h('div.buy-modal-content-option', {}, [ + h('div.buy-modal-content-option-title', {}, 'Shapeshift'), + h('div.buy-modal-content-option-subtitle', {}, 'Trade any digital asset for any other'), ]), - h('div.modal-content-option', {}, [ - h('div.modal-content-option-title', {}, 'Direct Deposit'), - h('div.modal-content-option-subtitle', {}, 'Deposit from another account'), + h('div.buy-modal-content-option', {}, [ + h('div.buy-modal-content-option-title', {}, 'Direct Deposit'), + h('div.buy-modal-content-option-subtitle', {}, 'Deposit from another account'), ]), ]), @@ -74,7 +74,7 @@ BuyOptions.prototype.render = function () { background: 'white', }, onClick: () => { this.props.hideModal() }, - }, h('div.modal-content-footer#modal-content-footer-text',{}, 'Cancel')), + }, h('div.buy-modal-content-footer#buy-modal-content-footer-text',{}, 'Cancel')), ]) ]) } -- cgit v1.2.3 From c2636143c3c3f297c8b00e407596841908376331 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 21 Aug 2017 04:51:55 -0700 Subject: Hook up selected account label display to main wallet view --- ui/app/components/wallet-view.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index a92ec418e..9fe827da2 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -39,10 +39,9 @@ function WalletView () { const noop = () => {} WalletView.prototype.render = function () { - const { network, responsiveDisplayClassname, style, identities, selectedAddress, selectedAccount, accounts } = this.props - + const { network, responsiveDisplayClassname, style, identities, selectedAddress, selectedAccount, accounts, selectedIdentity } = this.props // temporary logs + fake extra wallets - console.log(selectedAccount) + console.log("walletview, selectedAccount:", selectedAccount) const extraWallet = h('div.flex-column.wallet-balance-wrapper', {}, [ h('div.wallet-balance', {}, [ @@ -121,7 +120,7 @@ WalletView.prototype.render = function () { h('span.account-name', { style: {} }, [ - 'Account 1' + selectedIdentity.name ]), ]), -- cgit v1.2.3 From 3fa7c5dc0814bce907c7adbd6e39e1759186120c Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 21 Aug 2017 04:53:30 -0700 Subject: Hook up hideModal action to close icon in EditAccountNameModal --- ui/app/components/modals/edit-account-name-modal.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/edit-account-name-modal.js b/ui/app/components/modals/edit-account-name-modal.js index 0128fe412..cff8b2a58 100644 --- a/ui/app/components/modals/edit-account-name-modal.js +++ b/ui/app/components/modals/edit-account-name-modal.js @@ -43,7 +43,11 @@ EditAccountNameModal.prototype.render = function () { h('div.flex-column.edit-account-name-modal-content', { }, [ - h('div.edit-account-name-modal-cancel', {}, [ + h('div.edit-account-name-modal-cancel', { + onClick: () => { + hideModal() + }, + }, [ h('i.fa.fa-times'), ]), -- cgit v1.2.3 From 35508a28984afeccac31eb7c6789e26681f02b22 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 21 Aug 2017 05:58:30 -0700 Subject: Add wrapper CSS for AccountDetailsModal --- ui/app/components/modals/account-details-modal.js | 54 +++++++++++------------ ui/app/components/modals/modal.js | 14 ++++-- 2 files changed, 36 insertions(+), 32 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/account-details-modal.js b/ui/app/components/modals/account-details-modal.js index 38d08314b..104d2c6ed 100644 --- a/ui/app/components/modals/account-details-modal.js +++ b/ui/app/components/modals/account-details-modal.js @@ -30,44 +30,40 @@ module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountDetailsModa // It utilizes modal styles AccountDetailsModal.prototype.render = function () { return h('div', {}, [ - h('div.buy-modal-content.transfers-subview', { + h('div.account-details-modal-wrapper', { }, [ - h('div.buy-modal-content-title-wrapper.flex-column.flex-center', { - style: {}, - }, [ - h('div.buy-modal-content-title', { - style: {}, - }, 'Account Details Modal'), - h('div', {}, 'How would you like to buy Ether?'), + + h('div', {}, [ + 'ICON', ]), - h('div.buy-modal-content-options.flex-column.flex-center', {}, [ + h('div', {}, [ + 'X', + ]), - h('div.buy-modal-content-option', { - onClick: () => {}, - }, [ - h('div.buy-modal-content-option-title', {}, 'Coinbase'), - h('div.buy-modal-content-option-subtitle', {}, 'Buy with Fiat'), - ]), + h('div', {}, [ + ]), - h('div.buy-modal-content-option', {}, [ - h('div.buy-modal-content-option-title', {}, 'Shapeshift'), - h('div.buy-modal-content-option-subtitle', {}, 'Trade any digital asset for any other'), - ]), + h('div', {}, [ + 'QR Code', + ]), - h('div.buy-modal-content-option', {}, [ - h('div.buy-modal-content-option-title', {}, 'Direct Deposit'), - h('div.buy-modal-content-option-subtitle', {}, 'Deposit from another account'), - ]), + h('div', {}, [ + 'Account Display', + ]), + + h('div', {}, [ + 'divider', + ]), + + h('div', {}, [ + 'View aCcount on etherscan', + ]), + h('div', {}, [ + 'export private key', ]), - h('button', { - style: { - background: 'white', - }, - onClick: () => { this.props.hideModal() }, - }, h('div.buy-modal-content-footer#buy-modal-content-footer-text',{}, 'Cancel')), ]) ]) } diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index e2c5f77cc..842c4ed51 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -40,7 +40,7 @@ const MODALS = { boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', }, laptopModalStyle: { - width: '45%', + width: '375px', top: 'calc(30% + 10px)', boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', }, @@ -50,8 +50,16 @@ const MODALS = { contents: [ h(AccountDetailsModal, {}, []), ], - mobileModalStyle: {}, - laptopModalStyle: {}, + mobileModalStyle: { + width: '95%', + top: isPopupOrNotification() === 'popup' ? '48vh' : '36.5vh', + boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', + }, + laptopModalStyle: { + width: '360px', + top: 'calc(30% + 10px)', + boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', + }, }, NEW_ACCOUNT: { -- cgit v1.2.3 From 86b71f014a4bda433532cf7cbe7d76b243d3fb70 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 21 Aug 2017 06:14:28 -0700 Subject: Add wrapper CSS for NewAccountModal --- ui/app/components/modals/new-account-modal.js | 68 ++++++++++++--------------- 1 file changed, 29 insertions(+), 39 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/new-account-modal.js b/ui/app/components/modals/new-account-modal.js index c55d69964..15341a2e9 100644 --- a/ui/app/components/modals/new-account-modal.js +++ b/ui/app/components/modals/new-account-modal.js @@ -22,59 +22,49 @@ function mapDispatchToProps (dispatch) { } } -inherits(BuyOptions, Component) -function BuyOptions () { +inherits(NewAccountModal, Component) +function NewAccountModal () { Component.call(this) } -module.exports = connect(mapStateToProps, mapDispatchToProps)(BuyOptions) +module.exports = connect(mapStateToProps, mapDispatchToProps)(NewAccountModal) -// BuyOptions is currently meant to be rendered inside -// It is the only component in this codebase that does so -// It utilizes modal styles -BuyOptions.prototype.render = function () { +NewAccountModal.prototype.render = function () { return h('div', {}, [ - h('div.buy-modal-content.transfers-subview', { + h('div.new-account-modal-wrapper', { }, [ - h('div.buy-modal-content-title-wrapper.flex-column.flex-center', { - style: {}, - }, [ - h('div.buy-modal-content-title', { - style: {}, - }, 'New Account Modal'), - h('div', {}, 'How would you like to buy Ether?'), + h('div', {}, [ + 'New Account', ]), - h('div.buy-modal-content-options.flex-column.flex-center', {}, [ - - h('div.buy-modal-content-option', { - onClick: () => { - const { toCoinbase, address } = this.props - toCoinbase(address) - }, - }, [ - h('div.buy-modal-content-option-title', {}, 'Coinbase'), - h('div.buy-modal-content-option-subtitle', {}, 'Buy with Fiat'), + h('div', {}, [ + h('i.fa.fa-times', {}, [ ]), + ]), + + h('div', {}, [ + 'Account Name', + ]), - h('div.buy-modal-content-option', {}, [ - h('div.buy-modal-content-option-title', {}, 'Shapeshift'), - h('div.buy-modal-content-option-subtitle', {}, 'Trade any digital asset for any other'), - ]), + h('div', {}, [ + h('input', { + placeholder: 'E.g. My new account' + }, []), + ]), - h('div.buy-modal-content-option', {}, [ - h('div.buy-modal-content-option-title', {}, 'Direct Deposit'), - h('div.buy-modal-content-option-subtitle', {}, 'Deposit from another account'), - ]), + h('div', {}, [ + 'or', + ]), + h('div', {}, [ + 'Import an account', ]), - h('button', { - style: { - background: 'white', - }, - onClick: () => { this.props.hideModal() }, - }, h('div.buy-modal-content-footer#buy-modal-content-footer-text',{}, 'Cancel')), + h('div', {}, [ + h('button.btn-clear', {}, [ + 'SAVE', + ]), + ]), ]) ]) } -- cgit v1.2.3 From fe5817051b00a7288fb97541c5674641e978aead Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 21 Aug 2017 09:50:22 -0700 Subject: [WIP] Aggregate data for QRView --- ui/app/components/modals/account-details-modal.js | 15 +++++++++++++-- ui/app/components/qr-code.js | 6 +++++- 2 files changed, 18 insertions(+), 3 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/account-details-modal.js b/ui/app/components/modals/account-details-modal.js index 104d2c6ed..2a5359fd4 100644 --- a/ui/app/components/modals/account-details-modal.js +++ b/ui/app/components/modals/account-details-modal.js @@ -3,10 +3,15 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect const actions = require('../../actions') +const { getSelectedIdentity, getSelectedAddress } = require('../../selectors') + +const QrView = require('../qr-code') function mapStateToProps (state) { return { address: state.metamask.selectedAddress, + selectedAddress: getSelectedAddress(state), + selectedIdentity: getSelectedIdentity(state), } } @@ -14,7 +19,8 @@ function mapDispatchToProps (dispatch) { return { hideModal: () => { dispatch(actions.hideModal()) - } + }, + showQrView: (selected, identity) => dispatch(actions.showQrView(selected, identity)), } } @@ -45,7 +51,12 @@ AccountDetailsModal.prototype.render = function () { ]), h('div', {}, [ - 'QR Code', + h(QrView, { + Qr: { + message: this.props.selectedAddress, + data: this.props.selectedIdentity, + } + }, []), ]), h('div', {}, [ diff --git a/ui/app/components/qr-code.js b/ui/app/components/qr-code.js index 06b9aed9b..df749fe17 100644 --- a/ui/app/components/qr-code.js +++ b/ui/app/components/qr-code.js @@ -10,7 +10,11 @@ module.exports = connect(mapStateToProps)(QrCodeView) function mapStateToProps (state) { return { - Qr: state.appState.Qr, + // Qr: state.appState.Qr, + /* + Qr.message - address + Qr.data - identity + */ buyView: state.appState.buyView, warning: state.appState.warning, } -- cgit v1.2.3 From b836d0483d835b0665a14e41f68f9fbd574fd655 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 21 Aug 2017 10:06:29 -0700 Subject: [WIP] Render a QR code in AccountDetailsModal --- ui/app/components/modals/account-details-modal.js | 8 +++++--- ui/app/components/qr-code.js | 6 +----- 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/account-details-modal.js b/ui/app/components/modals/account-details-modal.js index 2a5359fd4..f7dcf26eb 100644 --- a/ui/app/components/modals/account-details-modal.js +++ b/ui/app/components/modals/account-details-modal.js @@ -10,7 +10,7 @@ const QrView = require('../qr-code') function mapStateToProps (state) { return { address: state.metamask.selectedAddress, - selectedAddress: getSelectedAddress(state), + // selectedAddress: getSelectedAddress(state), selectedIdentity: getSelectedIdentity(state), } } @@ -35,6 +35,8 @@ module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountDetailsModa // It is the only component in this codebase that does so // It utilizes modal styles AccountDetailsModal.prototype.render = function () { + const { selectedIdentity } = this.props + return h('div', {}, [ h('div.account-details-modal-wrapper', { }, [ @@ -53,8 +55,8 @@ AccountDetailsModal.prototype.render = function () { h('div', {}, [ h(QrView, { Qr: { - message: this.props.selectedAddress, - data: this.props.selectedIdentity, + message: this.props.selectedIdentity.name, + data: this.props.selectedIdentity.address, } }, []), ]), diff --git a/ui/app/components/qr-code.js b/ui/app/components/qr-code.js index df749fe17..5a2e4963a 100644 --- a/ui/app/components/qr-code.js +++ b/ui/app/components/qr-code.js @@ -10,11 +10,7 @@ module.exports = connect(mapStateToProps)(QrCodeView) function mapStateToProps (state) { return { - // Qr: state.appState.Qr, - /* - Qr.message - address - Qr.data - identity - */ + // Qr code is not fetched from state. 'message' and 'data' props are passed instead. buyView: state.appState.buyView, warning: state.appState.warning, } -- cgit v1.2.3 From 877faaf09608fbb5f1ba9dd853959e7399893068 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 21 Aug 2017 10:27:56 -0700 Subject: Integrate old QR component with new modal layout --- ui/app/components/modals/account-details-modal.js | 26 ++++++++++-------- ui/app/components/qr-code.js | 32 +++++++++++------------ 2 files changed, 31 insertions(+), 27 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/account-details-modal.js b/ui/app/components/modals/account-details-modal.js index f7dcf26eb..e3d1bb26b 100644 --- a/ui/app/components/modals/account-details-modal.js +++ b/ui/app/components/modals/account-details-modal.js @@ -52,22 +52,26 @@ AccountDetailsModal.prototype.render = function () { h('div', {}, [ ]), - h('div', {}, [ - h(QrView, { - Qr: { - message: this.props.selectedIdentity.name, - data: this.props.selectedIdentity.address, - } - }, []), - ]), + h(QrView, { + Qr: { + message: this.props.selectedIdentity.name, + data: this.props.selectedIdentity.address, + } + }, []), h('div', {}, [ 'Account Display', ]), - h('div', {}, [ - 'divider', - ]), + // divider + h('div', { + style: { + width: '100%', + height: '1px', + margin: '10px 0px', + backgroundColor: '#D8D8D8', + } + }, []), h('div', {}, [ 'View aCcount on etherscan', diff --git a/ui/app/components/qr-code.js b/ui/app/components/qr-code.js index 5a2e4963a..914d3aa29 100644 --- a/ui/app/components/qr-code.js +++ b/ui/app/components/qr-code.js @@ -29,28 +29,28 @@ QrCodeView.prototype.render = function () { const qrImage = qrCode(4, 'M') qrImage.addData(address) qrImage.make() - return h('.main-container.flex-column', { - key: 'qr', + return h('.div.flex-column.flex-center', { + // key: 'qr', style: { - justifyContent: 'center', - paddingBottom: '45px', - paddingLeft: '45px', - paddingRight: '45px', - alignItems: 'center', + // justifyContent: 'center', + // paddingBottom: '45px', + // paddingLeft: '45px', + // paddingRight: '45px', + // alignItems: 'center', }, }, [ Array.isArray(Qr.message) ? h('.message-container', this.renderMultiMessage()) : h('.qr-header', Qr.message), this.props.warning ? this.props.warning && h('span.error.flex-center', { style: { - textAlign: 'center', - width: '229px', - height: '82px', + // textAlign: 'center', + // width: '229px', + // height: '82px', }, }, this.props.warning) : null, - h('#qr-container.flex-column', { + h('.div', { style: { marginTop: '25px', marginBottom: '15px', @@ -59,15 +59,15 @@ QrCodeView.prototype.render = function () { __html: qrImage.createTableTag(4), }, }), - h('.flex-row', [ - h('h3.ellip-address', { + h('.div', [ + h('span.qr-ellip-address', { style: { width: '247px', }, }, Qr.data), - h(CopyButton, { - value: Qr.data, - }), + // h(CopyButton, { + // value: Qr.data, + // }), ]), ]) } -- cgit v1.2.3 From 27b75b67b42c232051660c33da976d64a63ff407 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 21 Aug 2017 12:26:36 -0700 Subject: Hook up identicon and buttons to AccountDetailsModal, clean up colors --- ui/app/components/modals/account-details-modal.js | 45 +++++++++++++--------- ui/app/components/modals/buy-options-modal.js | 3 -- .../components/modals/edit-account-name-modal.js | 3 -- ui/app/components/qr-code.js | 9 ----- ui/app/components/wallet-content-display.js | 2 +- 5 files changed, 28 insertions(+), 34 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/account-details-modal.js b/ui/app/components/modals/account-details-modal.js index e3d1bb26b..cbddd0421 100644 --- a/ui/app/components/modals/account-details-modal.js +++ b/ui/app/components/modals/account-details-modal.js @@ -4,13 +4,15 @@ const inherits = require('util').inherits const connect = require('react-redux').connect const actions = require('../../actions') const { getSelectedIdentity, getSelectedAddress } = require('../../selectors') - +const genAccountLink = require('../../../lib/account-link.js') +const Identicon = require('../identicon') const QrView = require('../qr-code') function mapStateToProps (state) { return { + network: state.metamask.network, address: state.metamask.selectedAddress, - // selectedAddress: getSelectedAddress(state), + selectedAddress: getSelectedAddress(state), selectedIdentity: getSelectedIdentity(state), } } @@ -31,18 +33,24 @@ function AccountDetailsModal () { module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountDetailsModal) -// AccountDetailsModal is currently meant to be rendered inside -// It is the only component in this codebase that does so -// It utilizes modal styles AccountDetailsModal.prototype.render = function () { - const { selectedIdentity } = this.props + const { selectedIdentity, selectedAddress, network } = this.props return h('div', {}, [ h('div.account-details-modal-wrapper', { }, [ h('div', {}, [ - 'ICON', + + h( + Identicon, + { + address: selectedIdentity.address, + diameter: 64, + style: {}, + }, + ), + ]), h('div', {}, [ @@ -64,21 +72,22 @@ AccountDetailsModal.prototype.render = function () { ]), // divider - h('div', { - style: { - width: '100%', - height: '1px', - margin: '10px 0px', - backgroundColor: '#D8D8D8', - } + h('div.account-details-modal-divider', { + style: {} }, []), - h('div', {}, [ - 'View aCcount on etherscan', + h('button.btn-clear', { + onClick: () => { + const url = genAccountLink(selectedIdentity.address, network) + global.platform.openWindow({ url }) + }, + }, [ + 'View account on Etherscan', ]), - h('div', {}, [ - 'export private key', + // Holding on redesign for Export Private Key functionality + h('button.btn-clear', {}, [ + 'Export private key', ]), ]) diff --git a/ui/app/components/modals/buy-options-modal.js b/ui/app/components/modals/buy-options-modal.js index 76e0da4f1..6e0831768 100644 --- a/ui/app/components/modals/buy-options-modal.js +++ b/ui/app/components/modals/buy-options-modal.js @@ -29,9 +29,6 @@ function BuyOptions () { module.exports = connect(mapStateToProps, mapDispatchToProps)(BuyOptions) -// BuyOptions is currently meant to be rendered inside -// It is the only component in this codebase that does so -// It utilizes modal styles BuyOptions.prototype.render = function () { return h('div', {}, [ h('div.buy-modal-content.transfers-subview', { diff --git a/ui/app/components/modals/edit-account-name-modal.js b/ui/app/components/modals/edit-account-name-modal.js index cff8b2a58..ae5ca23d4 100644 --- a/ui/app/components/modals/edit-account-name-modal.js +++ b/ui/app/components/modals/edit-account-name-modal.js @@ -33,9 +33,6 @@ function EditAccountNameModal () { module.exports = connect(mapStateToProps, mapDispatchToProps)(EditAccountNameModal) -// EditAccountNameModal is currently meant to be rendered inside -// It is the only component in this codebase that does so -// It utilizes modal styles EditAccountNameModal.prototype.render = function () { const { hideModal, saveAccountLabel, identity } = this.props diff --git a/ui/app/components/qr-code.js b/ui/app/components/qr-code.js index 914d3aa29..1de5f7352 100644 --- a/ui/app/components/qr-code.js +++ b/ui/app/components/qr-code.js @@ -30,22 +30,13 @@ QrCodeView.prototype.render = function () { qrImage.addData(address) qrImage.make() return h('.div.flex-column.flex-center', { - // key: 'qr', style: { - // justifyContent: 'center', - // paddingBottom: '45px', - // paddingLeft: '45px', - // paddingRight: '45px', - // alignItems: 'center', }, }, [ Array.isArray(Qr.message) ? h('.message-container', this.renderMultiMessage()) : h('.qr-header', Qr.message), this.props.warning ? this.props.warning && h('span.error.flex-center', { style: { - // textAlign: 'center', - // width: '229px', - // height: '82px', }, }, this.props.warning) : null, diff --git a/ui/app/components/wallet-content-display.js b/ui/app/components/wallet-content-display.js index 3baffad69..9c5db82d2 100644 --- a/ui/app/components/wallet-content-display.js +++ b/ui/app/components/wallet-content-display.js @@ -46,7 +46,7 @@ WalletContentDisplay.prototype.render = function () { marginLeft: '-1.3em', height: '6em', width: '0.3em', - background: '#D8D8D8', // TODO: add to resuable colors + background: '#D8D8D8', // $alto } }, [ ]) -- cgit v1.2.3 From b0759ddc1881179edaf27a6cd57e5fb27bdd2c31 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 21 Aug 2017 12:53:15 -0700 Subject: Hook up send screen action to Send Button in TxView --- ui/app/components/modals/new-account-modal.js | 2 +- ui/app/components/tx-view.js | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/new-account-modal.js b/ui/app/components/modals/new-account-modal.js index 15341a2e9..90a3b7c99 100644 --- a/ui/app/components/modals/new-account-modal.js +++ b/ui/app/components/modals/new-account-modal.js @@ -18,7 +18,7 @@ function mapDispatchToProps (dispatch) { }, hideModal: () => { dispatch(actions.hideModal()) - } + }, } } diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 265893104..dbbf07710 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -36,6 +36,7 @@ function mapDispatchToProps (dispatch) { showSidebar: () => { dispatch(actions.showSidebar()) }, hideSidebar: () => { dispatch(actions.hideSidebar()) }, showModal: (payload) => { dispatch(actions.showModal(payload)) }, + showSendPage: () => { dispatch(actions.showSendPage()) }, } } @@ -115,6 +116,9 @@ TxView.prototype.render = function () { textAlign: 'center', marginLeft: '1.4em', }, + onClick: () => { + this.props.showSendPage() + }, }, 'SEND'), ]), -- cgit v1.2.3 From 97a6a8e4f6ea41373061e9dccdd1ad0b002cdcac Mon Sep 17 00:00:00 2001 From: sdtsui Date: Tue, 22 Aug 2017 12:47:48 -0700 Subject: Add layout and props for send screen inputs --- ui/app/components/ens-input.js | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/ens-input.js b/ui/app/components/ens-input.js index 93c07599d..fb8c8e579 100644 --- a/ui/app/components/ens-input.js +++ b/ui/app/components/ens-input.js @@ -44,14 +44,7 @@ EnsInput.prototype.render = function () { return h('div', { style: { width: '100%' }, }, [ - h('span', { - style: { - textAlign: 'left', - } - }, [ - 'To:' - ]), - h('input.large-input', opts), + h('input.large-input.send-screen-input', opts), // The address book functionality. h('datalist#addresses', [ @@ -132,7 +125,7 @@ EnsInput.prototype.componentDidUpdate = function (prevProps, prevState) { EnsInput.prototype.ensIcon = function (recipient) { const { hoverText } = this.state || {} - return h('span', { + return h('span.#ensIcon', { title: hoverText, style: { position: 'absolute', -- cgit v1.2.3 From 9dce1b6fd5cdf8e5e14240bbcf1088f23e92c285 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Tue, 22 Aug 2017 15:24:48 -0700 Subject: Remove fake transactions and balances from tx-list and wallet-view, respectively --- ui/app/components/tx-list.js | 38 ------------------------------------ ui/app/components/wallet-view.js | 42 ++++++++++------------------------------ 2 files changed, 10 insertions(+), 70 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 74d46728c..30e38b4d7 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -52,44 +52,6 @@ TxList.prototype.render = function () { this.renderTransactionListItem(), - contentDivider, - - this.renderTransactionListItem(), - - contentDivider, - - this.renderTransactionListItem(), - - contentDivider, - - this.renderTransactionListItem(), - - contentDivider, - - this.renderTransactionListItem(), - - contentDivider, - - this.renderTransactionListItem(), - - contentDivider, - - this.renderTransactionListItem(), - - contentDivider, - - this.renderTransactionListItem(), - - contentDivider, - - this.renderTransactionListItem(), - - contentDivider, - - this.renderTransactionListItem(), - - contentDivider, - ]) } diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 9fe827da2..59859a8e0 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -43,15 +43,6 @@ WalletView.prototype.render = function () { // temporary logs + fake extra wallets console.log("walletview, selectedAccount:", selectedAccount) - const extraWallet = h('div.flex-column.wallet-balance-wrapper', {}, [ - h('div.wallet-balance', {}, [ - h(BalanceComponent, { - balanceValue: selectedAccount.balance, - style: {}, - }), - ]), - ]) - return h('div.wallet-view.flex-column' + (responsiveDisplayClassname || ''), { style: {}, }, [ @@ -148,28 +139,15 @@ WalletView.prototype.render = function () { ]), - h('div.flex-column.wallet-balance-wrapper', {}, [ - - h('div.wallet-balance', {}, [ - - h(BalanceComponent, { - balanceValue: selectedAccount.balance, - style: {}, - }), - - ]), - - ]), - - extraWallet, - extraWallet, - extraWallet, - extraWallet, - extraWallet, - extraWallet, - extraWallet, - extraWallet, - extraWallet, - extraWallet, ]) } + +// TODO: Extra wallets, for dev testing. Remove when PRing to master. +// const extraWallet = h('div.flex-column.wallet-balance-wrapper', {}, [ +// h('div.wallet-balance', {}, [ +// h(BalanceComponent, { +// balanceValue: selectedAccount.balance, +// style: {}, +// }), +// ]), +// ]) -- cgit v1.2.3 From 18496ad8595acd9fa8ec333fcd73de1ddfb8d62a Mon Sep 17 00:00:00 2001 From: sdtsui Date: Tue, 22 Aug 2017 16:16:56 -0700 Subject: Render TxListItem component from real data: address, identicon, status, ETH value --- ui/app/components/tx-list.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 30e38b4d7..fb8d5c69b 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -4,6 +4,7 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const selectors = require('../selectors') const Identicon = require('./identicon') +const { formatBalance, formatDate } = require('../util') const valuesFor = require('../util').valuesFor @@ -50,20 +51,21 @@ TxList.prototype.render = function () { contentDivider, - this.renderTransactionListItem(), + txsToRender.map((transaction) => { + return this.renderTransactionListItem(transaction) + }), ]) } -TxList.prototype.renderTransactionListItem = function () { - // fake data +// TODO: Consider moving TxListItem into a separate component +TxList.prototype.renderTransactionListItem = function (transaction) { const props = { - dateString: 'Jul 01, 2017', - address: '0x82df11beb942beeed58d466fcb0f0791365c7684', - transactionStatus: 'Confirmed', - transactionAmount: '+ 3 ETH' + dateString: formatDate(transaction.time), + address: transaction.txParams.to, + transactionStatus: transaction.status, + transactionAmount: formatBalance(transaction.txParams.value, 6), } - const { address, transactionStatus, transactionAmount, dateString } = props return h('div.flex-column.tx-list-item-wrapper', { @@ -96,7 +98,7 @@ TxList.prototype.renderTransactionListItem = function () { style: {} }, [ h('span.tx-list-account', {}, [ - '0x82df11be...7684', //address + `${address.slice(0, 10)}...${address.slice(-4)}` ]), ]), -- cgit v1.2.3 From 9d69401041368ec5e3754f80d33fe69687c8e9cf Mon Sep 17 00:00:00 2001 From: sdtsui Date: Tue, 22 Aug 2017 16:25:23 -0700 Subject: Hook up showAddToken to dropdown menu item in account options dropdown --- ui/app/components/dropdowns/components/account-dropdowns.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index 2854ec95d..c340fdaed 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -308,7 +308,7 @@ class AccountDropdowns extends Component { { closeMenu: () => {}, onClick: () => { - // Add Token Scren + actions.showAddTokenPage() }, style: Object.assign( {}, @@ -403,6 +403,9 @@ const mapDispatchToProps = (dispatch) => { showNewAccountModal: () => { dispatch(actions.showModal({ name: 'NEW_ACCOUNT' })) }, + showAddTokenPage: () => { + dispatch(actions.showAddTokenPage()) + }, addNewAccount: () => dispatch(actions.addNewAccount()), showImportPage: () => dispatch(actions.showImportPage()), showQrView: (selected, identity) => dispatch(actions.showQrView(selected, identity)), -- cgit v1.2.3 From 5b62f10a5f0fc87a731c9c353e99770f0f66d085 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Tue, 22 Aug 2017 21:12:17 -0230 Subject: Modify buy and send buttons color, border-radius and various size properties. (#1956) --- ui/app/components/tx-view.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index dbbf07710..5ed103421 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -114,7 +114,7 @@ TxView.prototype.render = function () { h('button.btn-clear', { style: { textAlign: 'center', - marginLeft: '1.4em', + marginLeft: '0.8em', }, onClick: () => { this.props.showSendPage() -- cgit v1.2.3 From 744b78e9c8c032cdd13acf121f891c28f319ed4d Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Thu, 24 Aug 2017 21:55:27 -0230 Subject: Patch 2 account details modal (#1957) * Account details modal styling changes. * Tweaking styles. --- ui/app/components/identicon.js | 2 +- ui/app/components/modals/account-details-modal.js | 15 +++++---------- ui/app/components/modals/modal.js | 4 ++-- ui/app/components/qr-code.js | 9 +++------ 4 files changed, 11 insertions(+), 19 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index c754bc6ba..98d5d40ef 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -20,7 +20,7 @@ IdenticonComponent.prototype.render = function () { var props = this.props var diameter = props.diameter || this.defaultDiameter return ( - h('div', { + h('div.identicon', { key: 'identicon-' + this.props.address, style: { display: 'flex', diff --git a/ui/app/components/modals/account-details-modal.js b/ui/app/components/modals/account-details-modal.js index cbddd0421..3ed702192 100644 --- a/ui/app/components/modals/account-details-modal.js +++ b/ui/app/components/modals/account-details-modal.js @@ -33,6 +33,9 @@ function AccountDetailsModal () { module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountDetailsModal) +// Not yet pixel perfect todos: + // fonts of qr-header and close button + AccountDetailsModal.prototype.render = function () { const { selectedIdentity, selectedAddress, network } = this.props @@ -42,6 +45,7 @@ AccountDetailsModal.prototype.render = function () { h('div', {}, [ + // Needs a border; requires changes to svg h( Identicon, { @@ -53,12 +57,7 @@ AccountDetailsModal.prototype.render = function () { ]), - h('div', {}, [ - 'X', - ]), - - h('div', {}, [ - ]), + h('div.account-details-modal-close', {}), h(QrView, { Qr: { @@ -67,10 +66,6 @@ AccountDetailsModal.prototype.render = function () { } }, []), - h('div', {}, [ - 'Account Display', - ]), - // divider h('div.account-details-modal-divider', { style: {} diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 842c4ed51..06a3efd34 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -52,12 +52,12 @@ const MODALS = { ], mobileModalStyle: { width: '95%', - top: isPopupOrNotification() === 'popup' ? '48vh' : '36.5vh', + top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh', boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', }, laptopModalStyle: { width: '360px', - top: 'calc(30% + 10px)', + top: 'calc(33% + 45px)', boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', }, }, diff --git a/ui/app/components/qr-code.js b/ui/app/components/qr-code.js index 1de5f7352..6559fcb7a 100644 --- a/ui/app/components/qr-code.js +++ b/ui/app/components/qr-code.js @@ -41,16 +41,13 @@ QrCodeView.prototype.render = function () { }, this.props.warning) : null, - h('.div', { - style: { - marginTop: '25px', - marginBottom: '15px', - }, + h('.div.qr-wrapper', { + style: {}, dangerouslySetInnerHTML: { __html: qrImage.createTableTag(4), }, }), - h('.div', [ + h('.div.ellip-address-wrapper', [ h('span.qr-ellip-address', { style: { width: '247px', -- cgit v1.2.3 From 4076496c8ea8c5a771db421b6c6a037c6ad48df1 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Thu, 24 Aug 2017 22:01:01 -0230 Subject: Patch 3 new account modal (#1962) * Account details modal styling changes. * Tweaking styles. * New account modal re-styling. * Tweaks to paddings, margins, font sizes, colors and modal dimensions. * Replace colour codes with variables. --- ui/app/components/modals/modal.js | 10 ++++++++-- ui/app/components/modals/new-account-modal.js | 19 ++++++++----------- 2 files changed, 16 insertions(+), 13 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 06a3efd34..fdff4c99e 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -66,8 +66,14 @@ const MODALS = { contents: [ h(NewAccountModal, {}, []), ], - mobileModalStyle: {}, - laptopModalStyle: {} + mobileModalStyle: { + width: '95%', + top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh', + }, + laptopModalStyle: { + width: '449px', + top: 'calc(33% + 45px)', + }, }, DEFAULT: { diff --git a/ui/app/components/modals/new-account-modal.js b/ui/app/components/modals/new-account-modal.js index 90a3b7c99..c44b79a2e 100644 --- a/ui/app/components/modals/new-account-modal.js +++ b/ui/app/components/modals/new-account-modal.js @@ -33,34 +33,31 @@ NewAccountModal.prototype.render = function () { return h('div', {}, [ h('div.new-account-modal-wrapper', { }, [ - h('div', {}, [ + h('div.new-account-modal-header', {}, [ 'New Account', ]), - h('div', {}, [ - h('i.fa.fa-times', {}, [ - ]), - ]), + h('div.modal-close-x', {}), - h('div', {}, [ + h('div.new-account-modal-content', {}, [ 'Account Name', ]), - h('div', {}, [ - h('input', { + h('div.new-account-input-wrapper', {}, [ + h('input.new-account-input', { placeholder: 'E.g. My new account' }, []), ]), - h('div', {}, [ + h('div.new-account-modal-content', {}, [ 'or', ]), - h('div', {}, [ + h('div.new-account-modal-content.import', {}, [ 'Import an account', ]), - h('div', {}, [ + h('div.new-account-modal-content.button', {}, [ h('button.btn-clear', {}, [ 'SAVE', ]), -- cgit v1.2.3 From 5677fdaf68ff28b9d9b4b27be1737101489f3861 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 24 Aug 2017 17:25:03 -0230 Subject: Toggling tooltip. --- ui/app/components/new-tooltip.js | 66 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 ui/app/components/new-tooltip.js (limited to 'ui/app/components') diff --git a/ui/app/components/new-tooltip.js b/ui/app/components/new-tooltip.js new file mode 100644 index 000000000..e6103dc95 --- /dev/null +++ b/ui/app/components/new-tooltip.js @@ -0,0 +1,66 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const findDOMNode = require('react-dom').findDOMNode +const ReactTooltip = require('react-tooltip') + +module.exports = NewTooltip + +inherits(NewTooltip, Component) +function NewTooltip () { + Component.call(this) + this.state = { + tooltipNode: null, + tooltipBase: null, + } + + // this.pageClick = this.pageClick.bind(this) +} + +// NewTooltip.prototype.pageClick = function (e) { +// // event.preventDefault(); +// const tooltipNode = this.state.tooltipNode +// console.log(`e.target`, e.target); +// console.log(`tooltipNode.contains(e.target)`, tooltipNode.contains(e.target)); +// }, + +NewTooltip.prototype.componentDidMount = function () { + const tooltipNode = findDOMNode(this); + const tooltipBase = findDOMNode(this.refs.tester) + + this.setState({ tooltipBase, tooltipNode }) +} + +NewTooltip.prototype.componentDidUpdate = function () { + const { show } = this.props + const tooltipBase = this.state.tooltipBase + const tooltipNode = this.state.tooltipNode + + if (show) { + ReactTooltip.show(tooltipBase) + } + else { + ReactTooltip.hide(tooltipBase) + } +} + +NewTooltip.prototype.render = function () { + const props = this.props + const { position, title, children } = props + + return h('div', {}, [ + h('div', { + 'data-tip': 'test', + 'data-for': 'something', + 'ref': 'tester', + }), + h(ReactTooltip, { + place: position || 'top', + effect: 'solid', + id: 'something', + className: 'send-tooltip', + type: 'light', + }, children), + ]) + +} -- cgit v1.2.3 From e56b8c5055a19ccfb88ef71f4cef13fb6d05a54a Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 25 Aug 2017 13:48:52 -0230 Subject: Refactor tooltip to remove external lib; tooltip now updating gas fee in parent. --- ui/app/components/gas-tooltip.js | 79 +++++++++++++++++++++++++++++++++++++++ ui/app/components/input-number.js | 57 ++++++++++++++++++++++++++++ ui/app/components/new-tooltip.js | 66 -------------------------------- 3 files changed, 136 insertions(+), 66 deletions(-) create mode 100644 ui/app/components/gas-tooltip.js create mode 100644 ui/app/components/input-number.js delete mode 100644 ui/app/components/new-tooltip.js (limited to 'ui/app/components') diff --git a/ui/app/components/gas-tooltip.js b/ui/app/components/gas-tooltip.js new file mode 100644 index 000000000..13df1254a --- /dev/null +++ b/ui/app/components/gas-tooltip.js @@ -0,0 +1,79 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const InputNumber = require('./input-number.js') + +module.exports = GasTooltip + +inherits(GasTooltip, Component) +function GasTooltip () { + Component.call(this) + this.state = { + gasLimit: 0, + gasPrice: 0, + } + + this.updateGasPrice = this.updateGasPrice.bind(this); + this.updateGasLimit = this.updateGasLimit.bind(this); +} + +GasTooltip.prototype.componentWillMount == function () { + const { gasPrice = 0, gasLimit = 0 } = this.props + + this.setState({ gasPrice, gasLimit }); +} + +GasTooltip.prototype.updateGasPrice = function (newPrice) { + const { onFeeChange } = this.props + const { gasLimit } = this.state + + this.setState({ gasPrice: newPrice }) + onFeeChange({ gasLimit, gasPrice: newPrice }) +} + +GasTooltip.prototype.updateGasLimit = function (newLimit) { + const { onFeeChange } = this.props + const { gasPrice } = this.state + + this.setState({ gasLimit: newLimit }) + onFeeChange({ gasLimit: newLimit, gasPrice }) +} + +GasTooltip.prototype.render = function () { + const { position, title, children, className, isOpen } = this.props + const { gasPrice, gasLimit } = this.state + + return isOpen + ? h('div.customize-gas-tooltip-container', {}, [ + h('div.customize-gas-tooltip', {}, [ + h('div.gas-tooltip-header.gas-tooltip-label', {}, ['Customize Gas']), + h('div.gas-tooltip-input-label', {}, [ + h('span.gas-tooltip-label', {}, ['Gas Price']), + h('i.fa.fa-info-circle') + ]), + h(InputNumber, { + unitLabel: 'GWEI', + step: 0.0001, + min: 0.0000, + placeholder: '0.0000', + fixed: 4, + initValue: gasPrice, + onChange: (newPrice) => this.updateGasPrice(newPrice), + }), + h('div.gas-tooltip-input-label', {}, [ + h('span.gas-tooltip-label', {}, ['Gas Limit']), + h('i.fa.fa-info-circle') + ]), + h(InputNumber, { + unitLabel: 'UNITS', + step: 1, + min: 0, + placeholder: '0', + initValue: gasLimit, + onChange: (newLimit) => this.updateGasLimit(newLimit), + }), + ]), + h('div.gas-tooltip-arrow', {}), + ]) + : null +} diff --git a/ui/app/components/input-number.js b/ui/app/components/input-number.js new file mode 100644 index 000000000..5b4265459 --- /dev/null +++ b/ui/app/components/input-number.js @@ -0,0 +1,57 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const findDOMNode = require('react-dom').findDOMNode + +module.exports = InputNumber + +inherits(InputNumber, Component) +function InputNumber () { + Component.call(this) + + this.state = { + value: 0, + } + + this.setValue = this.setValue.bind(this); +} + +InputNumber.prototype.componentWillMount == function () { + const { initValue = 0 } = this.props + + this.setState({ value: initValue }); +} + +InputNumber.prototype.setValue = function (newValue) { + const { fixed, min, onChange } = this.props + + if (fixed) newValue = Number(newValue.toFixed(4)) + + if (newValue >= min) { + this.setState({ value: newValue }) + onChange(newValue) + } +} + +InputNumber.prototype.render = function () { + const { unitLabel, step = 1, min, placeholder } = this.props + const { value } = this.state + + return h('div.customize-gas-input-wrapper', {}, [ + h('input.customize-gas-input', { + placeholder, + type: 'number', + value, + onChange: (e) => this.setValue(Number(e.target.value)) + }), + h('span.gas-tooltip-input-detail', {}, [unitLabel]), + h('div.gas-tooltip-input-arrows', {}, [ + h('i.fa.fa-angle-up', { + onClick: () => this.setValue(value + step) + }), + h('i.fa.fa-angle-down', { + onClick: () => this.setValue(value - step) + }), + ]), + ]) +} diff --git a/ui/app/components/new-tooltip.js b/ui/app/components/new-tooltip.js deleted file mode 100644 index e6103dc95..000000000 --- a/ui/app/components/new-tooltip.js +++ /dev/null @@ -1,66 +0,0 @@ -const Component = require('react').Component -const h = require('react-hyperscript') -const inherits = require('util').inherits -const findDOMNode = require('react-dom').findDOMNode -const ReactTooltip = require('react-tooltip') - -module.exports = NewTooltip - -inherits(NewTooltip, Component) -function NewTooltip () { - Component.call(this) - this.state = { - tooltipNode: null, - tooltipBase: null, - } - - // this.pageClick = this.pageClick.bind(this) -} - -// NewTooltip.prototype.pageClick = function (e) { -// // event.preventDefault(); -// const tooltipNode = this.state.tooltipNode -// console.log(`e.target`, e.target); -// console.log(`tooltipNode.contains(e.target)`, tooltipNode.contains(e.target)); -// }, - -NewTooltip.prototype.componentDidMount = function () { - const tooltipNode = findDOMNode(this); - const tooltipBase = findDOMNode(this.refs.tester) - - this.setState({ tooltipBase, tooltipNode }) -} - -NewTooltip.prototype.componentDidUpdate = function () { - const { show } = this.props - const tooltipBase = this.state.tooltipBase - const tooltipNode = this.state.tooltipNode - - if (show) { - ReactTooltip.show(tooltipBase) - } - else { - ReactTooltip.hide(tooltipBase) - } -} - -NewTooltip.prototype.render = function () { - const props = this.props - const { position, title, children } = props - - return h('div', {}, [ - h('div', { - 'data-tip': 'test', - 'data-for': 'something', - 'ref': 'tester', - }), - h(ReactTooltip, { - place: position || 'top', - effect: 'solid', - id: 'something', - className: 'send-tooltip', - type: 'light', - }, children), - ]) - -} -- cgit v1.2.3 From ff247289aeabd5530451f93d12fbe2b2c28d75be Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 25 Aug 2017 16:50:23 -0230 Subject: Tooltip closing on click outside. --- ui/app/components/gas-tooltip.js | 62 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 6 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/gas-tooltip.js b/ui/app/components/gas-tooltip.js index 13df1254a..91a07c738 100644 --- a/ui/app/components/gas-tooltip.js +++ b/ui/app/components/gas-tooltip.js @@ -2,6 +2,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits const InputNumber = require('./input-number.js') +const findDOMNode = require('react-dom').findDOMNode module.exports = GasTooltip @@ -17,12 +18,6 @@ function GasTooltip () { this.updateGasLimit = this.updateGasLimit.bind(this); } -GasTooltip.prototype.componentWillMount == function () { - const { gasPrice = 0, gasLimit = 0 } = this.props - - this.setState({ gasPrice, gasLimit }); -} - GasTooltip.prototype.updateGasPrice = function (newPrice) { const { onFeeChange } = this.props const { gasLimit } = this.state @@ -42,6 +37,8 @@ GasTooltip.prototype.updateGasLimit = function (newLimit) { GasTooltip.prototype.render = function () { const { position, title, children, className, isOpen } = this.props const { gasPrice, gasLimit } = this.state + + this.manageListeners() return isOpen ? h('div.customize-gas-tooltip-container', {}, [ @@ -77,3 +74,56 @@ GasTooltip.prototype.render = function () { ]) : null } + +GasTooltip.prototype.manageListeners = function () { + const isOpen = this.props.isOpen + const onClickOutside = this.props.onClickOutside + + if (isOpen) { + this.outsideClickHandler = onClickOutside + } else if (!isOpen) { + this.outsideClickHandler = null + } +} + +GasTooltip.prototype.componentDidMount = function () { + if (this && document.body) { + this.globalClickHandler = this.globalClickOccurred.bind(this) + document.body.addEventListener('click', this.globalClickHandler) + var container = findDOMNode(this) + this.container = container + } +} + +GasTooltip.prototype.componentWillUnmount = function () { + if (this && document.body) { + document.body.removeEventListener('click', this.globalClickHandler) + } +} + +GasTooltip.prototype.globalClickOccurred = function (event) { + const target = event.target + const container = findDOMNode(this) + console.log(`target`, target); + console.log(`container`, container); + console.log(`this.container`, this.container); + console.log(`this.outsideClickHandler`, this.outsideClickHandler); + if (target !== container && + !isDescendant(container, target) && + this.outsideClickHandler) { + this.outsideClickHandler(event) + } +} + +function isDescendant (parent, child) { + var node = child.parentNode + while (node !== null) { + if (node === parent) { + return true + } + node = node.parentNode + } + + return false +} + -- cgit v1.2.3 From c9e134a996f69367155aab416abb683fb82d4b9a Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 25 Aug 2017 20:53:30 -0230 Subject: Fully connect gas data in send form and tooltip to state; final styling improvements. Fully connect gas fields in send form and tooltip to state --- ui/app/components/gas-tooltip.js | 17 ++++++++++++----- ui/app/components/input-number.js | 6 +++--- 2 files changed, 15 insertions(+), 8 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/gas-tooltip.js b/ui/app/components/gas-tooltip.js index 91a07c738..de2f8046b 100644 --- a/ui/app/components/gas-tooltip.js +++ b/ui/app/components/gas-tooltip.js @@ -18,6 +18,12 @@ function GasTooltip () { this.updateGasLimit = this.updateGasLimit.bind(this); } +GasTooltip.prototype.componentWillMount = function () { + const { gasPrice = 0, gasLimit = 0} = this.props + + this.setState({ gasPrice, gasLimit }) +} + GasTooltip.prototype.updateGasPrice = function (newPrice) { const { onFeeChange } = this.props const { gasLimit } = this.state @@ -57,7 +63,11 @@ GasTooltip.prototype.render = function () { initValue: gasPrice, onChange: (newPrice) => this.updateGasPrice(newPrice), }), - h('div.gas-tooltip-input-label', {}, [ + h('div.gas-tooltip-input-label', { + style: { + 'marginTop': '81px', + }, + }, [ h('span.gas-tooltip-label', {}, ['Gas Limit']), h('i.fa.fa-info-circle') ]), @@ -104,10 +114,7 @@ GasTooltip.prototype.componentWillUnmount = function () { GasTooltip.prototype.globalClickOccurred = function (event) { const target = event.target const container = findDOMNode(this) - console.log(`target`, target); - console.log(`container`, container); - console.log(`this.container`, this.container); - console.log(`this.outsideClickHandler`, this.outsideClickHandler); + if (target !== container && !isDescendant(container, target) && this.outsideClickHandler) { diff --git a/ui/app/components/input-number.js b/ui/app/components/input-number.js index 5b4265459..c8bdd5ec5 100644 --- a/ui/app/components/input-number.js +++ b/ui/app/components/input-number.js @@ -16,9 +16,9 @@ function InputNumber () { this.setValue = this.setValue.bind(this); } -InputNumber.prototype.componentWillMount == function () { +InputNumber.prototype.componentWillMount = function () { const { initValue = 0 } = this.props - + this.setState({ value: initValue }); } @@ -36,7 +36,7 @@ InputNumber.prototype.setValue = function (newValue) { InputNumber.prototype.render = function () { const { unitLabel, step = 1, min, placeholder } = this.props const { value } = this.state - + return h('div.customize-gas-input-wrapper', {}, [ h('input.customize-gas-input', { placeholder, -- cgit v1.2.3 From 0a44c824586f74a770c1e6c618e62279b5dc773b Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 28 Aug 2017 14:44:01 -0230 Subject: Styles and behaviour correct --- ui/app/components/fiat-value.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/fiat-value.js b/ui/app/components/fiat-value.js index 8a64a1cfc..665789353 100644 --- a/ui/app/components/fiat-value.js +++ b/ui/app/components/fiat-value.js @@ -12,7 +12,7 @@ function FiatValue () { FiatValue.prototype.render = function () { const props = this.props - const { conversionRate, currentCurrency } = props + const { conversionRate, currentCurrency, style } = props const value = formatBalance(props.value, 6) @@ -28,16 +28,18 @@ FiatValue.prototype.render = function () { fiatTooltipNumber = 'Unknown' } - return fiatDisplay(fiatDisplayNumber, currentCurrency) + return fiatDisplay(fiatDisplayNumber, currentCurrency, style) } -function fiatDisplay (fiatDisplayNumber, fiatSuffix) { +function fiatDisplay (fiatDisplayNumber, fiatSuffix, styleOveride = {}) { + const { fontSize, color, fontFamily, lineHeight } = styleOveride + if (fiatDisplayNumber !== 'N/A') { return h('.flex-row', { style: { alignItems: 'flex-end', - lineHeight: '13px', - fontFamily: 'Montserrat Light', + lineHeight: lineHeight || '13px', + fontFamily: fontFamily || 'Montserrat Light', textRendering: 'geometricPrecision', }, }, [ @@ -45,15 +47,15 @@ function fiatDisplay (fiatDisplayNumber, fiatSuffix) { style: { width: '100%', textAlign: 'right', - fontSize: '12px', - color: '#333333', + fontSize: fontSize || '12px', + color: color || '#333333', }, }, fiatDisplayNumber), h('div', { style: { - color: '#AEAEAE', + color: color || '#AEAEAE', marginLeft: '5px', - fontSize: '12px', + fontSize: fontSize || '12px', }, }, fiatSuffix), ]) -- cgit v1.2.3 From 43ceeacf0f0cc46a60a01fff9d94672fad5383b5 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 28 Aug 2017 15:09:05 -0230 Subject: Refactor for clean handling of tooltip close. --- ui/app/components/gas-tooltip.js | 134 ++++++++++++++------------------------- 1 file changed, 46 insertions(+), 88 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/gas-tooltip.js b/ui/app/components/gas-tooltip.js index de2f8046b..76edb9214 100644 --- a/ui/app/components/gas-tooltip.js +++ b/ui/app/components/gas-tooltip.js @@ -16,6 +16,7 @@ function GasTooltip () { this.updateGasPrice = this.updateGasPrice.bind(this); this.updateGasLimit = this.updateGasLimit.bind(this); + this.onClose = this.onClose.bind(this); } GasTooltip.prototype.componentWillMount = function () { @@ -40,97 +41,54 @@ GasTooltip.prototype.updateGasLimit = function (newLimit) { onFeeChange({ gasLimit: newLimit, gasPrice }) } +GasTooltip.prototype.onClose = function (e) { + e.stopPropagation(); + this.props.onClose(); +} + GasTooltip.prototype.render = function () { - const { position, title, children, className, isOpen } = this.props + const { position, title, children, className } = this.props const { gasPrice, gasLimit } = this.state - this.manageListeners() - - return isOpen - ? h('div.customize-gas-tooltip-container', {}, [ - h('div.customize-gas-tooltip', {}, [ - h('div.gas-tooltip-header.gas-tooltip-label', {}, ['Customize Gas']), - h('div.gas-tooltip-input-label', {}, [ - h('span.gas-tooltip-label', {}, ['Gas Price']), - h('i.fa.fa-info-circle') - ]), - h(InputNumber, { - unitLabel: 'GWEI', - step: 0.0001, - min: 0.0000, - placeholder: '0.0000', - fixed: 4, - initValue: gasPrice, - onChange: (newPrice) => this.updateGasPrice(newPrice), - }), - h('div.gas-tooltip-input-label', { - style: { - 'marginTop': '81px', - }, - }, [ - h('span.gas-tooltip-label', {}, ['Gas Limit']), - h('i.fa.fa-info-circle') - ]), - h(InputNumber, { - unitLabel: 'UNITS', - step: 1, - min: 0, - placeholder: '0', - initValue: gasLimit, - onChange: (newLimit) => this.updateGasLimit(newLimit), - }), + return h('div', {}, [ + h('div.gas-tooltip-close-area', { + onClick: this.onClose + }), + h('div.customize-gas-tooltip-container', {}, [ + h('div.customize-gas-tooltip', {}, [ + h('div.gas-tooltip-header.gas-tooltip-label', {}, ['Customize Gas']), + h('div.gas-tooltip-input-label', {}, [ + h('span.gas-tooltip-label', {}, ['Gas Price']), + h('i.fa.fa-info-circle') ]), - h('div.gas-tooltip-arrow', {}), - ]) - : null -} - -GasTooltip.prototype.manageListeners = function () { - const isOpen = this.props.isOpen - const onClickOutside = this.props.onClickOutside - - if (isOpen) { - this.outsideClickHandler = onClickOutside - } else if (!isOpen) { - this.outsideClickHandler = null - } -} - -GasTooltip.prototype.componentDidMount = function () { - if (this && document.body) { - this.globalClickHandler = this.globalClickOccurred.bind(this) - document.body.addEventListener('click', this.globalClickHandler) - var container = findDOMNode(this) - this.container = container - } -} - -GasTooltip.prototype.componentWillUnmount = function () { - if (this && document.body) { - document.body.removeEventListener('click', this.globalClickHandler) - } -} - -GasTooltip.prototype.globalClickOccurred = function (event) { - const target = event.target - const container = findDOMNode(this) - - if (target !== container && - !isDescendant(container, target) && - this.outsideClickHandler) { - this.outsideClickHandler(event) - } -} - -function isDescendant (parent, child) { - var node = child.parentNode - while (node !== null) { - if (node === parent) { - return true - } - node = node.parentNode - } - - return false + h(InputNumber, { + unitLabel: 'GWEI', + step: 0.0001, + min: 0.0000, + placeholder: '0.0000', + fixed: 4, + initValue: gasPrice, + onChange: (newPrice) => this.updateGasPrice(newPrice), + }), + h('div.gas-tooltip-input-label', { + style: { + 'marginTop': '81px', + }, + }, [ + h('span.gas-tooltip-label', {}, ['Gas Limit']), + h('i.fa.fa-info-circle') + ]), + h(InputNumber, { + unitLabel: 'UNITS', + step: 1, + min: 0, + placeholder: '0', + initValue: gasLimit, + onChange: (newLimit) => this.updateGasLimit(newLimit), + }), + ]), + h('div.gas-tooltip-arrow', {}), + ]) + ]) } -- cgit v1.2.3 From dc72c4cc918934b8dafc253ca5e7c9674551aa51 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 28 Aug 2017 20:20:40 -0230 Subject: Using eth balance component to ensure proper rounding. --- ui/app/components/eth-balance.js | 69 ++++++++++++++++++++++++---------------- ui/app/components/tooltip.js | 2 +- 2 files changed, 43 insertions(+), 28 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/eth-balance.js b/ui/app/components/eth-balance.js index 4f538fd31..32ff4efdf 100644 --- a/ui/app/components/eth-balance.js +++ b/ui/app/components/eth-balance.js @@ -37,7 +37,17 @@ EthBalanceComponent.prototype.render = function () { } EthBalanceComponent.prototype.renderBalance = function (value) { var props = this.props - const { conversionRate, shorten, incoming, currentCurrency } = props + const { + conversionRate, + shorten, + incoming, + currentCurrency, + hideTooltip, + styleOveride, + } = props + + const { fontSize, color, fontFamily, lineHeight } = styleOveride + if (value === 'None') return value if (value === '...') return value var balanceObj = generateBalanceObject(value, shorten ? 1 : 3) @@ -54,36 +64,41 @@ EthBalanceComponent.prototype.renderBalance = function (value) { } var label = balanceObj.label + const tooltipProps = hideTooltip ? {} : { + position: 'bottom', + title: `${ethNumber} ${ethSuffix}`, + }; return ( - h(Tooltip, { - position: 'bottom', - title: `${ethNumber} ${ethSuffix}`, - }, h('div.flex-column', [ - h('.flex-row', { - style: { - alignItems: 'flex-end', - lineHeight: '13px', - fontFamily: 'Montserrat Light', - textRendering: 'geometricPrecision', - }, - }, [ - h('div', { - style: { - width: '100%', - textAlign: 'right', - }, - }, incoming ? `+${balance}` : balance), - h('div', { + h(hideTooltip ? 'div' : Tooltip, + tooltipProps, + h('div.flex-column', [ + h('.flex-row', { style: { - color: ' #AEAEAE', - fontSize: '12px', - marginLeft: '5px', + alignItems: 'flex-end', + lineHeight: lineHeight || '13px', + fontFamily: fontFamily || 'Montserrat Light', + textRendering: 'geometricPrecision', }, - }, label), - ]), + }, [ + h('div', { + style: { + width: '100%', + textAlign: 'right', + fontSize: fontSize || 'inherit', + color: color || 'inherit', + }, + }, incoming ? `+${balance}` : balance), + h('div', { + style: { + color: color || '#AEAEAE', + fontSize: fontSize || '12px', + marginLeft: '5px', + }, + }, label), + ]), - showFiat ? h(FiatValue, { value: props.value, conversionRate, currentCurrency }) : null, - ])) + showFiat ? h(FiatValue, { value: props.value, conversionRate, currentCurrency }) : null, + ])) ) } diff --git a/ui/app/components/tooltip.js b/ui/app/components/tooltip.js index edbc074bb..74cf1ae43 100644 --- a/ui/app/components/tooltip.js +++ b/ui/app/components/tooltip.js @@ -12,7 +12,7 @@ function Tooltip () { Tooltip.prototype.render = function () { const props = this.props - const { position, title, children } = props + const { position, title, children, show = true } = props return h(ReactTooltip, { position: position || 'left', -- cgit v1.2.3 From cd5861541c1cb871d5e3b606501931f2aee0d048 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 29 Aug 2017 10:21:31 -0230 Subject: Use hex values only in send.js to handle limit and price; GasTooltip accepts and returns values as hex (allows user to enter floats) --- ui/app/components/gas-tooltip.js | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/gas-tooltip.js b/ui/app/components/gas-tooltip.js index 76edb9214..4b6472b44 100644 --- a/ui/app/components/gas-tooltip.js +++ b/ui/app/components/gas-tooltip.js @@ -22,7 +22,10 @@ function GasTooltip () { GasTooltip.prototype.componentWillMount = function () { const { gasPrice = 0, gasLimit = 0} = this.props - this.setState({ gasPrice, gasLimit }) + this.setState({ + gasPrice: parseInt(gasPrice, 16) / 1000000000, + gasLimit: parseInt(gasLimit, 16), + }) } GasTooltip.prototype.updateGasPrice = function (newPrice) { @@ -30,7 +33,10 @@ GasTooltip.prototype.updateGasPrice = function (newPrice) { const { gasLimit } = this.state this.setState({ gasPrice: newPrice }) - onFeeChange({ gasLimit, gasPrice: newPrice }) + onFeeChange({ + gasLimit: gasLimit.toString(16), + gasPrice: (newPrice * 1000000000).toString(16) + }) } GasTooltip.prototype.updateGasLimit = function (newLimit) { @@ -38,7 +44,10 @@ GasTooltip.prototype.updateGasLimit = function (newLimit) { const { gasPrice } = this.state this.setState({ gasLimit: newLimit }) - onFeeChange({ gasLimit: newLimit, gasPrice }) + onFeeChange({ + gasLimit: newLimit.toString(16), + gasPrice: (gasPrice * 1000000000).toString(16) + }) } GasTooltip.prototype.onClose = function (e) { @@ -63,10 +72,9 @@ GasTooltip.prototype.render = function () { ]), h(InputNumber, { unitLabel: 'GWEI', - step: 0.0001, - min: 0.0000, - placeholder: '0.0000', - fixed: 4, + step: 1, + min: 0, + placeholder: '0', initValue: gasPrice, onChange: (newPrice) => this.updateGasPrice(newPrice), }), -- cgit v1.2.3 From b251d0f675b77b56adfab12cc512f985ada79c49 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 29 Aug 2017 13:43:43 -0230 Subject: Center tooltip on small screen size by using flexbox --- ui/app/components/gas-tooltip.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/gas-tooltip.js b/ui/app/components/gas-tooltip.js index 4b6472b44..29d1af4ad 100644 --- a/ui/app/components/gas-tooltip.js +++ b/ui/app/components/gas-tooltip.js @@ -59,7 +59,12 @@ GasTooltip.prototype.render = function () { const { position, title, children, className } = this.props const { gasPrice, gasLimit } = this.state - return h('div', {}, [ + return h('div', { + style: { + display: 'flex', + justifyContent: 'center', + } + }, [ h('div.gas-tooltip-close-area', { onClick: this.onClose }), -- cgit v1.2.3 From c605c9897d40f8fc2568b63d33cfc018635bcf25 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 29 Aug 2017 16:09:56 -0230 Subject: Minor clean up. --- ui/app/components/gas-tooltip.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/gas-tooltip.js b/ui/app/components/gas-tooltip.js index 29d1af4ad..68b7aea61 100644 --- a/ui/app/components/gas-tooltip.js +++ b/ui/app/components/gas-tooltip.js @@ -59,12 +59,7 @@ GasTooltip.prototype.render = function () { const { position, title, children, className } = this.props const { gasPrice, gasLimit } = this.state - return h('div', { - style: { - display: 'flex', - justifyContent: 'center', - } - }, [ + return h('div.gas-tooltip', {}, [ h('div.gas-tooltip-close-area', { onClick: this.onClose }), -- cgit v1.2.3 From 3ce69e1b65dc4e12c51400d01b973cb0d0c79e7a Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 29 Aug 2017 10:24:58 -0230 Subject: Clean up send.js and eth-balance.js with es6. --- ui/app/components/eth-balance.js | 58 +++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 33 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/eth-balance.js b/ui/app/components/eth-balance.js index 32ff4efdf..84b719315 100644 --- a/ui/app/components/eth-balance.js +++ b/ui/app/components/eth-balance.js @@ -1,8 +1,10 @@ -const Component = require('react').Component +const { Component } = require('react') const h = require('react-hyperscript') -const inherits = require('util').inherits -const formatBalance = require('../util').formatBalance -const generateBalanceObject = require('../util').generateBalanceObject +const { inherits } = require('util') +const { + formatBalance, + generateBalanceObject +} = require('../util') const Tooltip = require('./tooltip.js') const FiatValue = require('./fiat-value.js') @@ -14,11 +16,10 @@ function EthBalanceComponent () { } EthBalanceComponent.prototype.render = function () { - var props = this.props - let { value } = props - const { style, width } = props - var needsParse = this.props.needsParse !== undefined ? this.props.needsParse : true - value = value ? formatBalance(value, 6, needsParse) : '...' + const props = this.props + const { value, style, width, needsParse = true } = props + + const formattedValue = value ? formatBalance(value, 6, needsParse) : '...' return ( @@ -30,13 +31,15 @@ EthBalanceComponent.prototype.render = function () { display: 'inline', width, }, - }, this.renderBalance(value)), + }, this.renderBalance(formattedValue)), ]) ) } EthBalanceComponent.prototype.renderBalance = function (value) { - var props = this.props + if (value === 'None') return value + if (value === '...') return value + const { conversionRate, shorten, @@ -44,34 +47,22 @@ EthBalanceComponent.prototype.renderBalance = function (value) { currentCurrency, hideTooltip, styleOveride, - } = props - + showFiat = true, + } = this.props const { fontSize, color, fontFamily, lineHeight } = styleOveride - if (value === 'None') return value - if (value === '...') return value - var balanceObj = generateBalanceObject(value, shorten ? 1 : 3) - var balance - var splitBalance = value.split(' ') - var ethNumber = splitBalance[0] - var ethSuffix = splitBalance[1] - const showFiat = 'showFiat' in props ? props.showFiat : true - - if (shorten) { - balance = balanceObj.shortBalance - } else { - balance = balanceObj.balance - } + const { shortBalance, balance, label } = generateBalanceObject(value, shorten ? 1 : 3) + const balanceToRender = shorten ? shortBalance : balance - var label = balanceObj.label - const tooltipProps = hideTooltip ? {} : { + const [ethNumber, ethSuffix] = value.split(' ') + const containerProps = hideTooltip ? {} : { position: 'bottom', title: `${ethNumber} ${ethSuffix}`, }; return ( h(hideTooltip ? 'div' : Tooltip, - tooltipProps, + containerProps, h('div.flex-column', [ h('.flex-row', { style: { @@ -88,7 +79,7 @@ EthBalanceComponent.prototype.renderBalance = function (value) { fontSize: fontSize || 'inherit', color: color || 'inherit', }, - }, incoming ? `+${balance}` : balance), + }, incoming ? `+${balanceToRender}` : balanceToRender), h('div', { style: { color: color || '#AEAEAE', @@ -98,7 +89,8 @@ EthBalanceComponent.prototype.renderBalance = function (value) { }, label), ]), - showFiat ? h(FiatValue, { value: props.value, conversionRate, currentCurrency }) : null, - ])) + showFiat ? h(FiatValue, { value: this.props.value, conversionRate, currentCurrency }) : null, + ]) + ) ) } -- cgit v1.2.3 From 1485ec7392a03a9b3a63262e0ecf0d90f0713251 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 29 Aug 2017 11:25:11 -0230 Subject: Move currency toggle to its own component. --- ui/app/components/gas-tooltip.js | 102 ------------------------------ ui/app/components/send/currency-toggle.js | 26 ++++++++ ui/app/components/send/gas-tooltip.js | 102 ++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 102 deletions(-) delete mode 100644 ui/app/components/gas-tooltip.js create mode 100644 ui/app/components/send/currency-toggle.js create mode 100644 ui/app/components/send/gas-tooltip.js (limited to 'ui/app/components') diff --git a/ui/app/components/gas-tooltip.js b/ui/app/components/gas-tooltip.js deleted file mode 100644 index 68b7aea61..000000000 --- a/ui/app/components/gas-tooltip.js +++ /dev/null @@ -1,102 +0,0 @@ -const Component = require('react').Component -const h = require('react-hyperscript') -const inherits = require('util').inherits -const InputNumber = require('./input-number.js') -const findDOMNode = require('react-dom').findDOMNode - -module.exports = GasTooltip - -inherits(GasTooltip, Component) -function GasTooltip () { - Component.call(this) - this.state = { - gasLimit: 0, - gasPrice: 0, - } - - this.updateGasPrice = this.updateGasPrice.bind(this); - this.updateGasLimit = this.updateGasLimit.bind(this); - this.onClose = this.onClose.bind(this); -} - -GasTooltip.prototype.componentWillMount = function () { - const { gasPrice = 0, gasLimit = 0} = this.props - - this.setState({ - gasPrice: parseInt(gasPrice, 16) / 1000000000, - gasLimit: parseInt(gasLimit, 16), - }) -} - -GasTooltip.prototype.updateGasPrice = function (newPrice) { - const { onFeeChange } = this.props - const { gasLimit } = this.state - - this.setState({ gasPrice: newPrice }) - onFeeChange({ - gasLimit: gasLimit.toString(16), - gasPrice: (newPrice * 1000000000).toString(16) - }) -} - -GasTooltip.prototype.updateGasLimit = function (newLimit) { - const { onFeeChange } = this.props - const { gasPrice } = this.state - - this.setState({ gasLimit: newLimit }) - onFeeChange({ - gasLimit: newLimit.toString(16), - gasPrice: (gasPrice * 1000000000).toString(16) - }) -} - -GasTooltip.prototype.onClose = function (e) { - e.stopPropagation(); - this.props.onClose(); -} - -GasTooltip.prototype.render = function () { - const { position, title, children, className } = this.props - const { gasPrice, gasLimit } = this.state - - return h('div.gas-tooltip', {}, [ - h('div.gas-tooltip-close-area', { - onClick: this.onClose - }), - h('div.customize-gas-tooltip-container', {}, [ - h('div.customize-gas-tooltip', {}, [ - h('div.gas-tooltip-header.gas-tooltip-label', {}, ['Customize Gas']), - h('div.gas-tooltip-input-label', {}, [ - h('span.gas-tooltip-label', {}, ['Gas Price']), - h('i.fa.fa-info-circle') - ]), - h(InputNumber, { - unitLabel: 'GWEI', - step: 1, - min: 0, - placeholder: '0', - initValue: gasPrice, - onChange: (newPrice) => this.updateGasPrice(newPrice), - }), - h('div.gas-tooltip-input-label', { - style: { - 'marginTop': '81px', - }, - }, [ - h('span.gas-tooltip-label', {}, ['Gas Limit']), - h('i.fa.fa-info-circle') - ]), - h(InputNumber, { - unitLabel: 'UNITS', - step: 1, - min: 0, - placeholder: '0', - initValue: gasLimit, - onChange: (newLimit) => this.updateGasLimit(newLimit), - }), - ]), - h('div.gas-tooltip-arrow', {}), - ]) - ]) -} - diff --git a/ui/app/components/send/currency-toggle.js b/ui/app/components/send/currency-toggle.js new file mode 100644 index 000000000..37c026542 --- /dev/null +++ b/ui/app/components/send/currency-toggle.js @@ -0,0 +1,26 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +module.exports = CurrencyToggle + +inherits(CurrencyToggle, Component) +function CurrencyToggle () { + Component.call(this) +} + +CurrencyToggle.prototype.render = function () { + const { onClick, currentCurrency } = this.props + + return h('span', {}, [ + h('span', { + className: currentCurrency === 'ETH' ? 'selected-currency' : 'unselected-currency', + onClick: () => onClick('ETH') + }, ['ETH']), + '<>', + h('span', { + className: currentCurrency === 'USD' ? 'selected-currency' : 'unselected-currency', + onClick: () => onClick('USD'), + }, ['USD']), + ]) //holding on icon from design +} + diff --git a/ui/app/components/send/gas-tooltip.js b/ui/app/components/send/gas-tooltip.js new file mode 100644 index 000000000..472a8e287 --- /dev/null +++ b/ui/app/components/send/gas-tooltip.js @@ -0,0 +1,102 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const InputNumber = require('../input-number.js') +const findDOMNode = require('react-dom').findDOMNode + +module.exports = GasTooltip + +inherits(GasTooltip, Component) +function GasTooltip () { + Component.call(this) + this.state = { + gasLimit: 0, + gasPrice: 0, + } + + this.updateGasPrice = this.updateGasPrice.bind(this); + this.updateGasLimit = this.updateGasLimit.bind(this); + this.onClose = this.onClose.bind(this); +} + +GasTooltip.prototype.componentWillMount = function () { + const { gasPrice = 0, gasLimit = 0} = this.props + + this.setState({ + gasPrice: parseInt(gasPrice, 16) / 1000000000, + gasLimit: parseInt(gasLimit, 16), + }) +} + +GasTooltip.prototype.updateGasPrice = function (newPrice) { + const { onFeeChange } = this.props + const { gasLimit } = this.state + + this.setState({ gasPrice: newPrice }) + onFeeChange({ + gasLimit: gasLimit.toString(16), + gasPrice: (newPrice * 1000000000).toString(16) + }) +} + +GasTooltip.prototype.updateGasLimit = function (newLimit) { + const { onFeeChange } = this.props + const { gasPrice } = this.state + + this.setState({ gasLimit: newLimit }) + onFeeChange({ + gasLimit: newLimit.toString(16), + gasPrice: (gasPrice * 1000000000).toString(16) + }) +} + +GasTooltip.prototype.onClose = function (e) { + e.stopPropagation(); + this.props.onClose(); +} + +GasTooltip.prototype.render = function () { + const { position, title, children, className } = this.props + const { gasPrice, gasLimit } = this.state + + return h('div.gas-tooltip', {}, [ + h('div.gas-tooltip-close-area', { + onClick: this.onClose + }), + h('div.customize-gas-tooltip-container', {}, [ + h('div.customize-gas-tooltip', {}, [ + h('div.gas-tooltip-header.gas-tooltip-label', {}, ['Customize Gas']), + h('div.gas-tooltip-input-label', {}, [ + h('span.gas-tooltip-label', {}, ['Gas Price']), + h('i.fa.fa-info-circle') + ]), + h(InputNumber, { + unitLabel: 'GWEI', + step: 1, + min: 0, + placeholder: '0', + initValue: gasPrice, + onChange: (newPrice) => this.updateGasPrice(newPrice), + }), + h('div.gas-tooltip-input-label', { + style: { + 'marginTop': '81px', + }, + }, [ + h('span.gas-tooltip-label', {}, ['Gas Limit']), + h('i.fa.fa-info-circle') + ]), + h(InputNumber, { + unitLabel: 'UNITS', + step: 1, + min: 0, + placeholder: '0', + initValue: gasLimit, + onChange: (newLimit) => this.updateGasLimit(newLimit), + }), + ]), + h('div.gas-tooltip-arrow', {}), + ]) + ]) +} + -- cgit v1.2.3 From 5a7e4c4e76fd92b9f797fd2088b00ce6dc4fd47a Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 29 Aug 2017 11:39:07 -0230 Subject: Move gas fee to a separate component. --- ui/app/components/send/gas-fee-display.js | 53 +++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 ui/app/components/send/gas-fee-display.js (limited to 'ui/app/components') diff --git a/ui/app/components/send/gas-fee-display.js b/ui/app/components/send/gas-fee-display.js new file mode 100644 index 000000000..3add95394 --- /dev/null +++ b/ui/app/components/send/gas-fee-display.js @@ -0,0 +1,53 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const EthBalance = require('../eth-balance') +const FiatValue = require('../fiat-value') +const { getTxFeeBn } = require('../../util') + +module.exports = GasFeeDisplay + +inherits(GasFeeDisplay, Component) +function GasFeeDisplay () { + Component.call(this) +} + +GasFeeDisplay.prototype.render = function () { + const { + currentCurrency, + conversionRate, + gas, + gasPrice, + blockGasLimit, + } = this.props + + const renderableCurrencies = { + USD: h(FiatValue, { + value: getTxFeeBn(gas, gasPrice, blockGasLimit), + conversionRate, + currentCurrency, + style: { + color: '#5d5d5d', + fontSize: '16px', + fontFamily: 'DIN OT', + lineHeight: '22.4px' + } + }), + ETH: h(EthBalance, { + value: getTxFeeBn(gas, gasPrice, blockGasLimit), + currentCurrency, + conversionRate, + showFiat: false, + hideTooltip: true, + styleOveride: { + color: '#5d5d5d', + fontSize: '16px', + fontFamily: 'DIN OT', + lineHeight: '22.4px' + } + }), + } + + return renderableCurrencies[currentCurrency]; +} + -- cgit v1.2.3 From 3ea841e27621a8e9972677e46dbd8e3f0c002632 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 30 Aug 2017 16:07:46 -0230 Subject: Refactor gas-fee-display to include usd and eth fee displays as separate components. --- ui/app/components/send/eth-fee-display.js | 37 ++++++++++++++++++++++ ui/app/components/send/gas-fee-display.js | 51 +++++++++++++------------------ ui/app/components/send/usd-fee-display.js | 35 +++++++++++++++++++++ 3 files changed, 93 insertions(+), 30 deletions(-) create mode 100644 ui/app/components/send/eth-fee-display.js create mode 100644 ui/app/components/send/usd-fee-display.js (limited to 'ui/app/components') diff --git a/ui/app/components/send/eth-fee-display.js b/ui/app/components/send/eth-fee-display.js new file mode 100644 index 000000000..3dcb711ce --- /dev/null +++ b/ui/app/components/send/eth-fee-display.js @@ -0,0 +1,37 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const EthBalance = require('../eth-balance') +const { getTxFeeBn } = require('../../util') + +module.exports = EthFeeDisplay + +inherits(EthFeeDisplay, Component) +function EthFeeDisplay () { + Component.call(this) +} + +EthFeeDisplay.prototype.render = function () { + const { + currentCurrency, + conversionRate, + gas, + gasPrice, + blockGasLimit, + } = this.props + + return h(EthBalance, { + value: getTxFeeBn(gas, gasPrice, blockGasLimit), + currentCurrency, + conversionRate, + showFiat: false, + hideTooltip: true, + styleOveride: { + color: '#5d5d5d', + fontSize: '16px', + fontFamily: 'DIN OT', + lineHeight: '22.4px' + } + }) +} + diff --git a/ui/app/components/send/gas-fee-display.js b/ui/app/components/send/gas-fee-display.js index 3add95394..5336be8a3 100644 --- a/ui/app/components/send/gas-fee-display.js +++ b/ui/app/components/send/gas-fee-display.js @@ -1,9 +1,8 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits -const EthBalance = require('../eth-balance') -const FiatValue = require('../fiat-value') -const { getTxFeeBn } = require('../../util') +const USDFeeDisplay = require('./usd-fee-display') +const EthFeeDisplay = require('./eth-fee-display') module.exports = GasFeeDisplay @@ -21,33 +20,25 @@ GasFeeDisplay.prototype.render = function () { blockGasLimit, } = this.props - const renderableCurrencies = { - USD: h(FiatValue, { - value: getTxFeeBn(gas, gasPrice, blockGasLimit), - conversionRate, - currentCurrency, - style: { - color: '#5d5d5d', - fontSize: '16px', - fontFamily: 'DIN OT', - lineHeight: '22.4px' - } - }), - ETH: h(EthBalance, { - value: getTxFeeBn(gas, gasPrice, blockGasLimit), - currentCurrency, - conversionRate, - showFiat: false, - hideTooltip: true, - styleOveride: { - color: '#5d5d5d', - fontSize: '16px', - fontFamily: 'DIN OT', - lineHeight: '22.4px' - } - }), + switch (currentCurrency) { + case 'USD': + return h(USDFeeDisplay, { + currentCurrency, + conversionRate, + gas, + gasPrice, + blockGasLimit, + }) + case 'ETH': + return h(EthFeeDisplay, { + currentCurrency, + conversionRate, + gas, + gasPrice, + blockGasLimit, + }) + default: + return h('noscript'); } - - return renderableCurrencies[currentCurrency]; } diff --git a/ui/app/components/send/usd-fee-display.js b/ui/app/components/send/usd-fee-display.js new file mode 100644 index 000000000..012bda550 --- /dev/null +++ b/ui/app/components/send/usd-fee-display.js @@ -0,0 +1,35 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const FiatValue = require('../fiat-value') +const { getTxFeeBn } = require('../../util') + +module.exports = USDFeeDisplay + +inherits(USDFeeDisplay, Component) +function USDFeeDisplay () { + Component.call(this) +} + +USDFeeDisplay.prototype.render = function () { + const { + currentCurrency, + conversionRate, + gas, + gasPrice, + blockGasLimit, + } = this.props + + return h(FiatValue, { + value: getTxFeeBn(gas, gasPrice, blockGasLimit), + conversionRate, + currentCurrency, + style: { + color: '#5d5d5d', + fontSize: '16px', + fontFamily: 'DIN OT', + lineHeight: '22.4px' + } + }) +} + -- cgit v1.2.3 From e7b3ef0708290a81dad5c469adaa6fab3f1c45b5 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 29 Aug 2017 12:20:48 -0230 Subject: Lint fixes --- .../dropdowns/account-options-dropdown.js | 7 +- .../dropdowns/account-selection-dropdown.js | 7 +- .../dropdowns/components/account-dropdowns.js | 18 ++-- ui/app/components/dropdowns/index.js | 5 +- ui/app/components/dropdowns/network-dropdown.js | 8 +- ui/app/components/eth-balance.js | 4 +- ui/app/components/input-number.js | 17 ++-- ui/app/components/menu-droppo.js | 2 +- ui/app/components/modals/account-details-modal.js | 8 +- ui/app/components/modals/buy-options-modal.js | 6 +- .../components/modals/edit-account-name-modal.js | 2 +- ui/app/components/modals/index.js | 2 +- ui/app/components/modals/modal.js | 12 +-- ui/app/components/modals/new-account-modal.js | 6 +- ui/app/components/pending-tx.js | 97 ++++++++++------------ ui/app/components/qr-code.js | 1 - ui/app/components/send/currency-toggle.js | 6 +- ui/app/components/send/gas-tooltip.js | 30 ++++--- ui/app/components/shapeshift-form.js | 4 +- ui/app/components/tooltip.js | 2 +- ui/app/components/transaction-list-item.js | 2 +- ui/app/components/tx-list.js | 28 +++---- ui/app/components/tx-view.js | 1 - ui/app/components/wallet-content-display.js | 6 +- ui/app/components/wallet-view.js | 29 +++---- 25 files changed, 144 insertions(+), 166 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/account-options-dropdown.js b/ui/app/components/dropdowns/account-options-dropdown.js index 7d7188ec4..50e793d87 100644 --- a/ui/app/components/dropdowns/account-options-dropdown.js +++ b/ui/app/components/dropdowns/account-options-dropdown.js @@ -12,6 +12,7 @@ module.exports = AccountOptionsDropdown // TODO: specify default props and proptypes // TODO: hook up to state, connect to redux to clean up API +// TODO: selectedAddress is not defined... should we use selected? AccountOptionsDropdown.prototype.render = function () { const { selected, network, identities, style, dropdownWrapperStyle, menuItemStyles } = this.props @@ -21,8 +22,8 @@ AccountOptionsDropdown.prototype.render = function () { selected: selectedAddress, network, identities, - style: !!style ? style : {}, - dropdownWrapperStyle: !!dropdownWrapperStyle ? dropdownWrapperStyle : {}, - menuItemStyles: !!menuItemStyles ? menuItemStyles : {}, + style: style || {}, + dropdownWrapperStyle: dropdownWrapperStyle || {}, + menuItemStyles: menuItemStyles || {}, }, []) } diff --git a/ui/app/components/dropdowns/account-selection-dropdown.js b/ui/app/components/dropdowns/account-selection-dropdown.js index ccb73bde7..7a8502d18 100644 --- a/ui/app/components/dropdowns/account-selection-dropdown.js +++ b/ui/app/components/dropdowns/account-selection-dropdown.js @@ -12,6 +12,7 @@ module.exports = AccountSelectionDropdown // TODO: specify default props and proptypes // TODO: hook up to state, connect to redux to clean up API +// TODO: selectedAddress is not defined... should we use selected? AccountSelectionDropdown.prototype.render = function () { const { selected, network, identities, style, dropdownWrapperStyle, menuItemStyles } = this.props @@ -21,8 +22,8 @@ AccountSelectionDropdown.prototype.render = function () { selected: selectedAddress, network, identities, - style: !!style ? style : {}, - dropdownWrapperStyle: !!dropdownWrapperStyle ? dropdownWrapperStyle : {}, - menuItemStyles: !!menuItemStyles ? menuItemStyles : {}, + style: style || {}, + dropdownWrapperStyle: dropdownWrapperStyle || {}, + menuItemStyles: menuItemStyles || {}, }, []) } diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index c340fdaed..1e869251a 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -25,7 +25,7 @@ class AccountDropdowns extends Component { } renderAccounts () { - const { identities, accounts, selected, menuItemStyles, dropdownWrapperStyle, actions } = this.props + const { identities, accounts, selected, menuItemStyles, actions } = this.props return Object.keys(identities).map((key, index) => { const identity = identities[key] @@ -57,13 +57,13 @@ class AccountDropdowns extends Component { flex: '1 1 0', minWidth: '20px', minHeight: '30px', - } + }, }, [ h('span', { style: { flex: '1 1 auto', fontSize: '14px', - } + }, }, isSelected ? h('i.fa.fa-check') : null), ]), @@ -86,7 +86,7 @@ class AccountDropdowns extends Component { alignItems: 'flex-start', justifyContent: 'center', marginLeft: '10px', - } + }, }, [ h('span.account-dropdown-name', { style: { @@ -102,7 +102,7 @@ class AccountDropdowns extends Component { style: { fontSize: '14px', }, - }, formattedBalance) + }, formattedBalance), ]), h('span', { @@ -119,17 +119,17 @@ class AccountDropdowns extends Component { }, }, [ 'Edit', - ]) + ]), ]), - ]) + ]), ] ) }) } renderAccountSelector () { - const { actions, dropdownWrapperStyle, useCssTransition, innerStyle } = this.props + const { actions, useCssTransition, innerStyle } = this.props const { accountSelectorActive, menuItemStyles } = this.state return h( @@ -323,7 +323,7 @@ class AccountDropdowns extends Component { } render () { - const { style, enableAccountsSelector, enableAccountOptions, dropdownWrapperStyle } = this.props + const { style, enableAccountsSelector, enableAccountOptions } = this.props const { optionsMenuActive, accountSelectorActive } = this.state return h( diff --git a/ui/app/components/dropdowns/index.js b/ui/app/components/dropdowns/index.js index d21c795f5..fa66f5000 100644 --- a/ui/app/components/dropdowns/index.js +++ b/ui/app/components/dropdowns/index.js @@ -1,7 +1,6 @@ // Reusable Dropdown Components -//TODO: Refactor into separate components +// TODO: Refactor into separate components const Dropdown = require('./components/dropdown').Dropdown -const DropdownMenuItem = require('./components/dropdown').DropdownMenuItem const AccountDropdowns = require('./components/account-dropdowns') // App-Specific Instances @@ -15,4 +14,4 @@ module.exports = { NetworkDropdown, Dropdown, AccountDropdowns, -} \ No newline at end of file +} diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js index 6228513c9..0c002b2f0 100644 --- a/ui/app/components/dropdowns/network-dropdown.js +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -23,6 +23,7 @@ function mapDispatchToProps (dispatch) { dispatch(actions.setProviderType(type)) }, setDefaultRpcTarget: () => { + // TODO: type is not defined. Is it needed? dispatch(actions.setDefaultRpcTarget(type)) }, setRpcTarget: (target) => { @@ -31,8 +32,8 @@ function mapDispatchToProps (dispatch) { showConfigPage: () => { dispatch(actions.showConfigPage()) }, - showNetworkDropdown: () => {dispatch(actions.showNetworkDropdown())}, - hideNetworkDropdown: () => {dispatch(actions.hideNetworkDropdown())}, + showNetworkDropdown: () => { dispatch(actions.showNetworkDropdown()) }, + hideNetworkDropdown: () => { dispatch(actions.hideNetworkDropdown()) }, } } @@ -49,7 +50,6 @@ NetworkDropdown.prototype.render = function () { const props = this.props const { provider: { type: providerType, rpcTarget: activeNetwork } } = props const rpcList = props.frequentRpcList - const state = this.state || {} const isOpen = this.props.networkDropdownOpen return h(Dropdown, { @@ -135,7 +135,7 @@ NetworkDropdown.prototype.render = function () { { key: 'rinkeby', closeMenu: () => this.props.hideNetworkDropdown(), - onClick: () => propssetProviderType('rinkeby'), + onClick: () => props.setProviderType('rinkeby'), style: { fontSize: '18px', }, diff --git a/ui/app/components/eth-balance.js b/ui/app/components/eth-balance.js index 84b719315..1be8c9731 100644 --- a/ui/app/components/eth-balance.js +++ b/ui/app/components/eth-balance.js @@ -3,7 +3,7 @@ const h = require('react-hyperscript') const { inherits } = require('util') const { formatBalance, - generateBalanceObject + generateBalanceObject, } = require('../util') const Tooltip = require('./tooltip.js') const FiatValue = require('./fiat-value.js') @@ -58,7 +58,7 @@ EthBalanceComponent.prototype.renderBalance = function (value) { const containerProps = hideTooltip ? {} : { position: 'bottom', title: `${ethNumber} ${ethSuffix}`, - }; + } return ( h(hideTooltip ? 'div' : Tooltip, diff --git a/ui/app/components/input-number.js b/ui/app/components/input-number.js index c8bdd5ec5..e3bbaf380 100644 --- a/ui/app/components/input-number.js +++ b/ui/app/components/input-number.js @@ -1,7 +1,6 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits -const findDOMNode = require('react-dom').findDOMNode module.exports = InputNumber @@ -13,13 +12,13 @@ function InputNumber () { value: 0, } - this.setValue = this.setValue.bind(this); + this.setValue = this.setValue.bind(this) } InputNumber.prototype.componentWillMount = function () { const { initValue = 0 } = this.props - - this.setState({ value: initValue }); + + this.setState({ value: initValue }) } InputNumber.prototype.setValue = function (newValue) { @@ -34,23 +33,23 @@ InputNumber.prototype.setValue = function (newValue) { } InputNumber.prototype.render = function () { - const { unitLabel, step = 1, min, placeholder } = this.props + const { unitLabel, step = 1, placeholder } = this.props const { value } = this.state - + return h('div.customize-gas-input-wrapper', {}, [ h('input.customize-gas-input', { placeholder, type: 'number', value, - onChange: (e) => this.setValue(Number(e.target.value)) + onChange: (e) => this.setValue(Number(e.target.value)), }), h('span.gas-tooltip-input-detail', {}, [unitLabel]), h('div.gas-tooltip-input-arrows', {}, [ h('i.fa.fa-angle-up', { - onClick: () => this.setValue(value + step) + onClick: () => this.setValue(value + step), }), h('i.fa.fa-angle-down', { - onClick: () => this.setValue(value - step) + onClick: () => this.setValue(value - step), }), ]), ]) diff --git a/ui/app/components/menu-droppo.js b/ui/app/components/menu-droppo.js index 66ab18954..2f173544e 100644 --- a/ui/app/components/menu-droppo.js +++ b/ui/app/components/menu-droppo.js @@ -19,7 +19,7 @@ MenuDroppoComponent.prototype.render = function () { this.manageListeners() - let style = this.props.style || {} + const style = this.props.style || {} if (!('position' in style)) { style.position = 'fixed' } diff --git a/ui/app/components/modals/account-details-modal.js b/ui/app/components/modals/account-details-modal.js index 3ed702192..fb0e70397 100644 --- a/ui/app/components/modals/account-details-modal.js +++ b/ui/app/components/modals/account-details-modal.js @@ -37,7 +37,7 @@ module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountDetailsModa // fonts of qr-header and close button AccountDetailsModal.prototype.render = function () { - const { selectedIdentity, selectedAddress, network } = this.props + const { selectedIdentity, network } = this.props return h('div', {}, [ h('div.account-details-modal-wrapper', { @@ -63,12 +63,12 @@ AccountDetailsModal.prototype.render = function () { Qr: { message: this.props.selectedIdentity.name, data: this.props.selectedIdentity.address, - } + }, }, []), // divider h('div.account-details-modal-divider', { - style: {} + style: {}, }, []), h('button.btn-clear', { @@ -85,6 +85,6 @@ AccountDetailsModal.prototype.render = function () { 'Export private key', ]), - ]) + ]), ]) } diff --git a/ui/app/components/modals/buy-options-modal.js b/ui/app/components/modals/buy-options-modal.js index 6e0831768..79bbc798b 100644 --- a/ui/app/components/modals/buy-options-modal.js +++ b/ui/app/components/modals/buy-options-modal.js @@ -18,7 +18,7 @@ function mapDispatchToProps (dispatch) { }, hideModal: () => { dispatch(actions.hideModal()) - } + }, } } @@ -71,7 +71,7 @@ BuyOptions.prototype.render = function () { background: 'white', }, onClick: () => { this.props.hideModal() }, - }, h('div.buy-modal-content-footer#buy-modal-content-footer-text',{}, 'Cancel')), - ]) + }, h('div.buy-modal-content-footer#buy-modal-content-footer-text', {}, 'Cancel')), + ]), ]) } diff --git a/ui/app/components/modals/edit-account-name-modal.js b/ui/app/components/modals/edit-account-name-modal.js index ae5ca23d4..5c25ac245 100644 --- a/ui/app/components/modals/edit-account-name-modal.js +++ b/ui/app/components/modals/edit-account-name-modal.js @@ -71,6 +71,6 @@ EditAccountNameModal.prototype.render = function () { 'SAVE', ]), - ]) + ]), ]) } diff --git a/ui/app/components/modals/index.js b/ui/app/components/modals/index.js index e2e367af0..1db1d33d4 100644 --- a/ui/app/components/modals/index.js +++ b/ui/app/components/modals/index.js @@ -2,4 +2,4 @@ const Modal = require('./modal') module.exports = { Modal, -} \ No newline at end of file +} diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index fdff4c99e..d266fe790 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -80,7 +80,7 @@ const MODALS = { contents: [], mobileModalStyle: {}, laptopModalStyle: {}, - } + }, } const BACKDROPSTYLE = { @@ -120,7 +120,7 @@ Modal.prototype.render = function () { { className: 'modal', keyboard: false, - onHide: () => {this.onHide()}, + onHide: () => { this.onHide() }, ref: (ref) => { this.modalRef = ref }, @@ -131,7 +131,7 @@ Modal.prototype.render = function () { ) } -Modal.prototype.componentWillReceiveProps = function(nextProps) { +Modal.prototype.componentWillReceiveProps = function (nextProps) { if (nextProps.active) { this.show() } else if (this.props.active) { @@ -139,17 +139,17 @@ Modal.prototype.componentWillReceiveProps = function(nextProps) { } } -Modal.prototype.onHide = function() { +Modal.prototype.onHide = function () { if (this.props.onHideCallback) { this.props.onHideCallback() } this.props.hideModal() } -Modal.prototype.hide = function() { +Modal.prototype.hide = function () { this.modalRef.hide() } -Modal.prototype.show = function() { +Modal.prototype.show = function () { this.modalRef.show() } diff --git a/ui/app/components/modals/new-account-modal.js b/ui/app/components/modals/new-account-modal.js index c44b79a2e..3caa515cd 100644 --- a/ui/app/components/modals/new-account-modal.js +++ b/ui/app/components/modals/new-account-modal.js @@ -38,14 +38,14 @@ NewAccountModal.prototype.render = function () { ]), h('div.modal-close-x', {}), - + h('div.new-account-modal-content', {}, [ 'Account Name', ]), h('div.new-account-input-wrapper', {}, [ h('input.new-account-input', { - placeholder: 'E.g. My new account' + placeholder: 'E.g. My new account', }, []), ]), @@ -62,6 +62,6 @@ NewAccountModal.prototype.render = function () { 'SAVE', ]), ]), - ]) + ]), ]) } diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index 1c47440f2..5e5110d6c 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -8,17 +8,10 @@ const ethUtil = require('ethereumjs-util') const BN = ethUtil.BN const hexToBn = require('../../../app/scripts/lib/hex-to-bn') const util = require('../util') -const MiniAccountPanel = require('./mini-account-panel') -const Copyable = require('./copyable') -const EthBalance = require('./eth-balance') -const addressSummary = util.addressSummary -const nameForAddress = require('../../lib/contract-namer') -const BNInput = require('./bn-as-decimal-input') const MIN_GAS_PRICE_GWEI_BN = new BN(1) const GWEI_FACTOR = new BN(1e9) const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR) -const MIN_GAS_LIMIT_BN = new BN(21000) // Faked, for Icon @@ -34,8 +27,8 @@ const ARAGON = '960b236A07cf122663c4303350609A66A7B288C0' // actionButtons const sectionDivider = h('div', { style: { - height:'1px', - background:'#E7E7E7', + height: '1px', + background: '#E7E7E7', }, }) @@ -43,8 +36,8 @@ const contentDivider = h('div', { style: { marginLeft: '16px', marginRight: '16px', - height:'1px', - background:'#E7E7E7', + height: '1px', + background: '#E7E7E7', }, }) @@ -61,15 +54,13 @@ function PendingTx () { PendingTx.prototype.render = function () { const props = this.props - const { currentCurrency, blockGasLimit } = props + const { blockGasLimit } = props - const conversionRate = props.conversionRate const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} // Account Details const address = txParams.from || props.selectedAddress - const identity = props.identities[address] || { address: address } const account = props.accounts[address] const balance = account ? account.balance : '0x0' @@ -79,8 +70,6 @@ PendingTx.prototype.render = function () { // Gas const gas = txParams.gas const gasBn = hexToBn(gas) - const gasLimit = new BN(parseInt(blockGasLimit)) - const safeGasLimit = this.bnMultiplyByFraction(gasLimit, 19, 20).toString(10) // Gas Price const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16) @@ -90,8 +79,6 @@ PendingTx.prototype.render = function () { const valueBn = hexToBn(txParams.value) const maxCost = txFeeBn.add(valueBn) - const dataLength = txParams.data ? (txParams.data.length - 2) / 2 : 0 - const balanceBn = hexToBn(balance) const insufficientBalance = balanceBn.lt(maxCost) @@ -112,13 +99,13 @@ PendingTx.prototype.render = function () { marginRight: '3.5%', background: '#FFFFFF', // $background-white boxShadow: '0 2px 4px 0 rgba(0,0,0,0.08)', - } + }, }, [ h('section.flex-center.flex-row', { style: { zIndex: 15, // $token-icon-z-index marginTop: '-35px', - } + }, }, [ h(Identicon, { address: ARAGON, @@ -178,23 +165,23 @@ PendingTx.prototype.render = function () { h('div', { style: { width: '50%', - } + }, }, [ h('span', { style: { textAlign: 'left', fontSize: '12px', - } + }, }, [ - 'From' - ]) + 'From', + ]), ]), h('div', { style: { width: '50%', - } - },[ + }, + }, [ h('div', { style: { textAlign: 'left', @@ -208,8 +195,8 @@ PendingTx.prototype.render = function () { textAlign: 'left', fontSize: '8px', }, - }, 'Your Balance 2.34 ANT') - ]) + }, 'Your Balance 2.34 ANT'), + ]), ]), contentDivider, @@ -219,23 +206,23 @@ PendingTx.prototype.render = function () { h('div', { style: { width: '50%', - } + }, }, [ h('span', { style: { textAlign: 'left', fontSize: '12px', - } + }, }, [ - 'To' - ]) + 'To', + ]), ]), h('div', { style: { width: '50%', - } - },[ + }, + }, [ h('div', { style: { textAlign: 'left', @@ -249,8 +236,8 @@ PendingTx.prototype.render = function () { textAlign: 'left', fontSize: '8px', }, - }, '...5924') - ]) + }, '...5924'), + ]), ]), contentDivider, @@ -260,23 +247,23 @@ PendingTx.prototype.render = function () { h('div', { style: { width: '50%', - } + }, }, [ h('span', { style: { textAlign: 'left', fontSize: '12px', - } + }, }, [ - 'Gas Fee' - ]) + 'Gas Fee', + ]), ]), h('div', { style: { width: '50%', - } - },[ + }, + }, [ h('div', { style: { textAlign: 'left', @@ -290,8 +277,8 @@ PendingTx.prototype.render = function () { textAlign: 'left', fontSize: '8px', }, - }, '0.001575 ETH') - ]) + }, '0.001575 ETH'), + ]), ]), contentDivider, @@ -305,39 +292,39 @@ PendingTx.prototype.render = function () { paddingLeft: '6px', paddingRight: '6px', marginBottom: '10px', - } + }, }, [ h('div', { style: { width: '50%', - } + }, }, [ h('div', { style: { textAlign: 'left', fontSize: '12px', marginBottom: '-10px', - } + }, }, [ - 'Total Tokens' + 'Total Tokens', ]), h('div', { style: { textAlign: 'left', fontSize: '8px', - } + }, }, [ - 'Total Gas' - ]) + 'Total Gas', + ]), ]), h('div', { style: { width: '50%', - } - },[ + }, + }, [ h('div', { style: { textAlign: 'left', @@ -351,8 +338,8 @@ PendingTx.prototype.render = function () { textAlign: 'left', fontSize: '8px', }, - }, '0.249 ETH') - ]) + }, '0.249 ETH'), + ]), ]), ]), // end of container diff --git a/ui/app/components/qr-code.js b/ui/app/components/qr-code.js index 6559fcb7a..8d6b43b6c 100644 --- a/ui/app/components/qr-code.js +++ b/ui/app/components/qr-code.js @@ -4,7 +4,6 @@ const qrCode = require('qrcode-npm').qrcode const inherits = require('util').inherits const connect = require('react-redux').connect const isHexPrefixed = require('ethereumjs-util').isHexPrefixed -const CopyButton = require('./copyButton') module.exports = connect(mapStateToProps)(QrCodeView) diff --git a/ui/app/components/send/currency-toggle.js b/ui/app/components/send/currency-toggle.js index 37c026542..d3c2222a4 100644 --- a/ui/app/components/send/currency-toggle.js +++ b/ui/app/components/send/currency-toggle.js @@ -14,13 +14,13 @@ CurrencyToggle.prototype.render = function () { return h('span', {}, [ h('span', { className: currentCurrency === 'ETH' ? 'selected-currency' : 'unselected-currency', - onClick: () => onClick('ETH') + onClick: () => onClick('ETH'), }, ['ETH']), '<>', h('span', { className: currentCurrency === 'USD' ? 'selected-currency' : 'unselected-currency', - onClick: () => onClick('USD'), + onClick: () => onClick('USD'), }, ['USD']), - ]) //holding on icon from design + ]) // holding on icon from design } diff --git a/ui/app/components/send/gas-tooltip.js b/ui/app/components/send/gas-tooltip.js index 472a8e287..bef419e48 100644 --- a/ui/app/components/send/gas-tooltip.js +++ b/ui/app/components/send/gas-tooltip.js @@ -2,7 +2,6 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits const InputNumber = require('../input-number.js') -const findDOMNode = require('react-dom').findDOMNode module.exports = GasTooltip @@ -14,14 +13,14 @@ function GasTooltip () { gasPrice: 0, } - this.updateGasPrice = this.updateGasPrice.bind(this); - this.updateGasLimit = this.updateGasLimit.bind(this); - this.onClose = this.onClose.bind(this); + this.updateGasPrice = this.updateGasPrice.bind(this) + this.updateGasLimit = this.updateGasLimit.bind(this) + this.onClose = this.onClose.bind(this) } GasTooltip.prototype.componentWillMount = function () { const { gasPrice = 0, gasLimit = 0} = this.props - + this.setState({ gasPrice: parseInt(gasPrice, 16) / 1000000000, gasLimit: parseInt(gasLimit, 16), @@ -35,7 +34,7 @@ GasTooltip.prototype.updateGasPrice = function (newPrice) { this.setState({ gasPrice: newPrice }) onFeeChange({ gasLimit: gasLimit.toString(16), - gasPrice: (newPrice * 1000000000).toString(16) + gasPrice: (newPrice * 1000000000).toString(16), }) } @@ -46,29 +45,28 @@ GasTooltip.prototype.updateGasLimit = function (newLimit) { this.setState({ gasLimit: newLimit }) onFeeChange({ gasLimit: newLimit.toString(16), - gasPrice: (gasPrice * 1000000000).toString(16) + gasPrice: (gasPrice * 1000000000).toString(16), }) } GasTooltip.prototype.onClose = function (e) { - e.stopPropagation(); - this.props.onClose(); + e.stopPropagation() + this.props.onClose() } GasTooltip.prototype.render = function () { - const { position, title, children, className } = this.props const { gasPrice, gasLimit } = this.state return h('div.gas-tooltip', {}, [ h('div.gas-tooltip-close-area', { - onClick: this.onClose + onClick: this.onClose, }), h('div.customize-gas-tooltip-container', {}, [ h('div.customize-gas-tooltip', {}, [ h('div.gas-tooltip-header.gas-tooltip-label', {}, ['Customize Gas']), h('div.gas-tooltip-input-label', {}, [ h('span.gas-tooltip-label', {}, ['Gas Price']), - h('i.fa.fa-info-circle') + h('i.fa.fa-info-circle'), ]), h(InputNumber, { unitLabel: 'GWEI', @@ -76,7 +74,7 @@ GasTooltip.prototype.render = function () { min: 0, placeholder: '0', initValue: gasPrice, - onChange: (newPrice) => this.updateGasPrice(newPrice), + onChange: (newPrice) => this.updateGasPrice(newPrice), }), h('div.gas-tooltip-input-label', { style: { @@ -84,7 +82,7 @@ GasTooltip.prototype.render = function () { }, }, [ h('span.gas-tooltip-label', {}, ['Gas Limit']), - h('i.fa.fa-info-circle') + h('i.fa.fa-info-circle'), ]), h(InputNumber, { unitLabel: 'UNITS', @@ -92,11 +90,11 @@ GasTooltip.prototype.render = function () { min: 0, placeholder: '0', initValue: gasLimit, - onChange: (newLimit) => this.updateGasLimit(newLimit), + onChange: (newLimit) => this.updateGasLimit(newLimit), }), ]), h('div.gas-tooltip-arrow', {}), - ]) + ]), ]) } diff --git a/ui/app/components/shapeshift-form.js b/ui/app/components/shapeshift-form.js index 901a4a956..96a86d3b1 100644 --- a/ui/app/components/shapeshift-form.js +++ b/ui/app/components/shapeshift-form.js @@ -131,8 +131,8 @@ ShapeshiftForm.prototype.renderMain = function () { }, }, [ this.props.warning - ? this.props.warning - && h('span.error.flex-center', { + ? this.props.warning && + h('span.error.flex-center', { style: { textAlign: 'center', width: '229px', diff --git a/ui/app/components/tooltip.js b/ui/app/components/tooltip.js index 74cf1ae43..edbc074bb 100644 --- a/ui/app/components/tooltip.js +++ b/ui/app/components/tooltip.js @@ -12,7 +12,7 @@ function Tooltip () { Tooltip.prototype.render = function () { const props = this.props - const { position, title, children, show = true } = props + const { position, title, children } = props return h(ReactTooltip, { position: position || 'left', diff --git a/ui/app/components/transaction-list-item.js b/ui/app/components/transaction-list-item.js index 9018bab06..eca2a7100 100644 --- a/ui/app/components/transaction-list-item.js +++ b/ui/app/components/transaction-list-item.js @@ -156,7 +156,7 @@ function failIfFailed (transaction) { } if (transaction.err || transaction.warning) { const { err, warning = {} } = transaction - const errFirst = !!(( err && warning ) || err) + const errFirst = !!((err && warning) || err) const message = errFirst ? err.message : warning.message errFirst ? err.message : warning.message diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index fb8d5c69b..92a9b6f46 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -6,8 +6,6 @@ const selectors = require('../selectors') const Identicon = require('./identicon') const { formatBalance, formatDate } = require('../util') -const valuesFor = require('../util').valuesFor - module.exports = connect(mapStateToProps)(TxList) function mapStateToProps (state) { @@ -28,7 +26,7 @@ const contentDivider = h('div.tx-list-content-divider', { TxList.prototype.render = function () { - const { txsToRender, conversionRate } = this.props + const { txsToRender } = this.props console.log('transactions to render', txsToRender) @@ -42,7 +40,7 @@ TxList.prototype.render = function () { }, [ h('div', { - style: {} + style: {}, }, 'TRANSACTIONS'), ]), @@ -69,41 +67,41 @@ TxList.prototype.renderTransactionListItem = function (transaction) { const { address, transactionStatus, transactionAmount, dateString } = props return 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: 24, - }) + }), ]), 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, @@ -112,7 +110,7 @@ TxList.prototype.renderTransactionListItem = function (transaction) { ]), h('div.flex-column.tx-list-details-wrapper', { - style: {} + style: {}, }, [ h('span.tx-list-value', {}, [ @@ -124,7 +122,7 @@ TxList.prototype.renderTransactionListItem = function (transaction) { ]), ]), - ]) + ]), ]) } diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 5ed103421..9f75f7b31 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -5,7 +5,6 @@ const ethUtil = require('ethereumjs-util') const inherits = require('util').inherits const actions = require('../actions') -const WalletView = require('./wallet-view') const BalanceComponent = require('./balance-component') const TxList = require('./tx-list') const Identicon = require('./identicon') diff --git a/ui/app/components/wallet-content-display.js b/ui/app/components/wallet-content-display.js index 9c5db82d2..bfa061be4 100644 --- a/ui/app/components/wallet-content-display.js +++ b/ui/app/components/wallet-content-display.js @@ -18,7 +18,7 @@ WalletContentDisplay.prototype.render = function () { marginLeft: '1.3em', alignItems: 'flex-start', ...style, - } + }, }, [ h('span', { @@ -47,9 +47,9 @@ WalletContentDisplay.prototype.render = function () { height: '6em', width: '0.3em', background: '#D8D8D8', // $alto - } + }, }, [ - ]) + ]), ]) } diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 59859a8e0..6f9269389 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -4,7 +4,6 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const Identicon = require('./identicon') const AccountDropdowns = require('./dropdowns/index.js').AccountDropdowns -const Content = require('./wallet-content-display') const actions = require('../actions') const BalanceComponent = require('./balance-component') const selectors = require('../selectors') @@ -26,8 +25,8 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { - showSendPage: () => {dispatch(actions.showSendPage())}, - hideSidebar: () => {dispatch(actions.hideSidebar())}, + showSendPage: () => { dispatch(actions.showSendPage()) }, + hideSidebar: () => { dispatch(actions.hideSidebar()) }, } } @@ -36,12 +35,10 @@ function WalletView () { Component.call(this) } -const noop = () => {} - WalletView.prototype.render = function () { - const { network, responsiveDisplayClassname, style, 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) + console.log('walletview, selectedAccount:', selectedAccount) return h('div.wallet-view.flex-column' + (responsiveDisplayClassname || ''), { style: {}, @@ -49,7 +46,7 @@ WalletView.prototype.render = function () { // TODO: Separate component: wallet account details h('div.flex-column.wallet-view-account-details', { - style: {} + style: {}, }, [ h('div.flex-row.account-options-menu', { @@ -68,12 +65,12 @@ WalletView.prototype.render = function () { padding: '1px 15px', marginLeft: '-25px', position: 'absolute', - width: '122%', //TODO, refactor all of this component out into media queries + width: '122%', // TODO, refactor all of this component out into media queries }, menuItemStyles: { padding: '0px 0px', margin: '22px 0px', - } + }, }, []), ]), @@ -83,7 +80,7 @@ WalletView.prototype.render = function () { h('div', { style: { position: 'relative', - } + }, }, [ h(AccountDropdowns, { accounts, @@ -109,23 +106,23 @@ WalletView.prototype.render = function () { }), h('span.account-name', { - style: {} + style: {}, }, [ - selectedIdentity.name + selectedIdentity.name, ]), ]), ]), - //'Wallet' - Title + // 'Wallet' - Title // Not visible on mobile h('div.flex-column.wallet-view-title-wrapper', {}, [ h('span.wallet-view-title', {}, [ 'Wallet', - ]) + ]), ]), - //Wallet Balances + // Wallet Balances h('div.flex-column.wallet-balance-wrapper.wallet-balance-wrapper-active', {}, [ h('div.wallet-balance', {}, [ -- cgit v1.2.3 From b1fc290bed26ae0ea8d182340854c82cc1f3d12d Mon Sep 17 00:00:00 2001 From: Jacky Chan Date: Thu, 31 Aug 2017 04:08:11 -0700 Subject: Fix menu style --- .../dropdowns/account-selection-dropdown.js | 2 +- .../dropdowns/components/account-dropdowns.js | 38 ++++++++-- ui/app/components/dropdowns/network-dropdown.js | 83 ++++++++++++++-------- ui/app/components/wallet-view.js | 2 +- 4 files changed, 87 insertions(+), 38 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/account-selection-dropdown.js b/ui/app/components/dropdowns/account-selection-dropdown.js index 7a8502d18..b1f4d68ce 100644 --- a/ui/app/components/dropdowns/account-selection-dropdown.js +++ b/ui/app/components/dropdowns/account-selection-dropdown.js @@ -15,7 +15,7 @@ module.exports = AccountSelectionDropdown // TODO: selectedAddress is not defined... should we use selected? AccountSelectionDropdown.prototype.render = function () { const { selected, network, identities, style, dropdownWrapperStyle, menuItemStyles } = this.props - + console.log({style}) return h(AccountDropdowns, { enableAccountOptions: false, enableAccountsSelector: true, diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index 1e869251a..be9245c0e 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -101,6 +101,8 @@ class AccountDropdowns extends Component { h('span.account-dropdown-balance', { style: { fontSize: '14px', + fontFamily: 'Avenir', + fontWeight: 500, }, }, formattedBalance), ]), @@ -177,7 +179,13 @@ class AccountDropdowns extends Component { }, ), h('span', { - style: { marginLeft: '20px', fontSize: '18px' }, + style: { + marginLeft: '20px', + fontSize: '18px', + fontFamily: 'DIN OT', + fontSize: '16px', + lineHeight: '23px', + }, onClick: () => { actions.showNewAccountModal() }, @@ -209,6 +217,9 @@ class AccountDropdowns extends Component { marginLeft: '20px', fontSize: '18px', marginBottom: '5px', + fontFamily: 'DIN OT', + fontSize: '16px', + lineHeight: '23px', }, }, 'Import Account'), ] @@ -251,7 +262,10 @@ class AccountDropdowns extends Component { this.props.actions.showAccountDetailModal() }, style: Object.assign( - {}, + { + fontFamily: 'DIN OT', + fontSize: 16, + }, menuItemStyles, ), }, @@ -267,7 +281,10 @@ class AccountDropdowns extends Component { global.platform.openWindow({ url }) }, style: Object.assign( - {}, + { + fontFamily: 'DIN OT', + fontSize: 16, + }, menuItemStyles, ), }, @@ -283,7 +300,10 @@ class AccountDropdowns extends Component { copyToClipboard(checkSumAddress) }, style: Object.assign( - {}, + { + fontFamily: 'DIN OT', + fontSize: 16, + }, menuItemStyles, ), }, @@ -297,7 +317,10 @@ class AccountDropdowns extends Component { actions.requestAccountExport() }, style: Object.assign( - {}, + { + fontFamily: 'DIN OT', + fontSize: 16, + }, menuItemStyles, ), }, @@ -311,7 +334,10 @@ class AccountDropdowns extends Component { actions.showAddTokenPage() }, style: Object.assign( - {}, + { + fontFamily: 'DIN OT', + fontSize: 16, + }, menuItemStyles, ), }, diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js index 0c002b2f0..3f4ea6274 100644 --- a/ui/app/components/dropdowns/network-dropdown.js +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -22,8 +22,7 @@ function mapDispatchToProps (dispatch) { setProviderType: (type) => { dispatch(actions.setProviderType(type)) }, - setDefaultRpcTarget: () => { - // TODO: type is not defined. Is it needed? + setDefaultRpcTarget: type => { dispatch(actions.setDefaultRpcTarget(type)) }, setRpcTarget: (target) => { @@ -51,6 +50,11 @@ NetworkDropdown.prototype.render = function () { const { provider: { type: providerType, rpcTarget: activeNetwork } } = props const rpcList = props.frequentRpcList const isOpen = this.props.networkDropdownOpen + const dropdownMenuItemStyle = { + fontFamily: 'DIN OT', + fontSize: '16px', + lineHeight: '20px', + }; return h(Dropdown, { useCssTransition: true, @@ -73,9 +77,10 @@ NetworkDropdown.prototype.render = function () { position: 'absolute', right: '2px', top: '38px', + minWidth: '309px', }, innerStyle: { - padding: '2px 16px 2px 0px', + padding: '10px 8px', }, }, [ @@ -85,14 +90,16 @@ NetworkDropdown.prototype.render = function () { key: 'main', closeMenu: () => this.props.hideNetworkDropdown(), onClick: () => props.setProviderType('mainnet'), - style: { - fontSize: '18px', - }, + style: dropdownMenuItemStyle, }, [ + providerType === 'mainnet' ? h('.network-check', '✓') : h('.network-check__transparent', '✓'), h('.menu-icon.diamond'), - 'Main Ethereum Network', - providerType === 'mainnet' ? h('.check', '✓') : null, + h('span.network-name', { + style: { + color: providerType === 'mainnet' ? '#ffffff' : '#9b9b9b' + }, + }, 'Main Ethereum Network'), ] ), @@ -102,14 +109,16 @@ NetworkDropdown.prototype.render = function () { key: 'ropsten', closeMenu: () => this.props.hideNetworkDropdown(), onClick: () => props.setProviderType('ropsten'), - style: { - fontSize: '18px', - }, + style: dropdownMenuItemStyle, }, [ + providerType === 'ropsten' ? h('.network-check', '✓') : h('.network-check__transparent', '✓'), h('.menu-icon.red-dot'), - 'Ropsten Test Network', - providerType === 'ropsten' ? h('.check', '✓') : null, + h('span.network-name', { + style: { + color: providerType === 'ropsten' ? '#ffffff' : '#9b9b9b' + }, + }, 'Ropsten Test Network'), ] ), @@ -119,14 +128,16 @@ NetworkDropdown.prototype.render = function () { key: 'kovan', closeMenu: () => this.props.hideNetworkDropdown(), onClick: () => props.setProviderType('kovan'), - style: { - fontSize: '18px', - }, + style: dropdownMenuItemStyle, }, [ + providerType === 'kovan' ? h('.network-check', '✓') : h('.network-check__transparent', '✓'), h('.menu-icon.hollow-diamond'), - 'Kovan Test Network', - providerType === 'kovan' ? h('.check', '✓') : null, + h('span.network-name', { + style: { + color: providerType === 'kovan' ? '#ffffff' : '#9b9b9b' + }, + }, 'Kovan Test Network'), ] ), @@ -136,14 +147,22 @@ NetworkDropdown.prototype.render = function () { key: 'rinkeby', closeMenu: () => this.props.hideNetworkDropdown(), onClick: () => props.setProviderType('rinkeby'), +<<<<<<< HEAD style: { fontSize: '18px', }, +======= + style: dropdownMenuItemStyle, +>>>>>>> Fix menu style }, [ + providerType === 'rinkeby' ? h('.network-check', '✓') : h('.network-check__transparent', '✓'), h('.menu-icon.golden-square'), - 'Rinkeby Test Network', - providerType === 'rinkeby' ? h('.check', '✓') : null, + h('span.network-name', { + style: { + color: providerType === 'rinkeby' ? '#ffffff' : '#9b9b9b' + }, + }, 'Rinkeby Test Network'), ] ), @@ -153,14 +172,16 @@ NetworkDropdown.prototype.render = function () { key: 'default', closeMenu: () => this.props.hideNetworkDropdown(), onClick: () => props.setDefaultRpcTarget(), - style: { - fontSize: '18px', - }, + style: dropdownMenuItemStyle, }, [ + activeNetwork === 'http://localhost:8545' ? h('.network-check', '✓') : h('.network-check__transparent', '✓'), h('i.fa.fa-question-circle.fa-lg.menu-icon'), - 'Localhost 8545', - activeNetwork === 'http://localhost:8545' ? h('.check', '✓') : null, + h('span.network-name', { + style: { + color: activeNetwork === 'http://localhost:8545' ? '#ffffff' : '#9b9b9b' + }, + }, 'Localhost 8545'), ] ), @@ -172,14 +193,16 @@ NetworkDropdown.prototype.render = function () { { closeMenu: () => this.props.hideNetworkDropdown(), onClick: () => this.props.showConfigPage(), - style: { - fontSize: '18px', - }, + style: dropdownMenuItemStyle, }, [ + activeNetwork === 'custom' ? h('.check', '✓') : h('.network-check__transparent', '✓'), h('i.fa.fa-question-circle.fa-lg.menu-icon'), - 'Custom RPC', - activeNetwork === 'custom' ? h('.check', '✓') : null, + h('span.network-name', { + style: { + color: activeNetwork === 'custom' ? '#ffffff' : '#9b9b9b' + }, + }, 'Custom RPC'), ] ), diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 6f9269389..48971a29e 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -90,7 +90,7 @@ WalletView.prototype.render = function () { top: '14px', }, innerStyle: { - padding: '2px 16px', + padding: '10px 16px', }, useCssTransition: true, selected: selectedAddress, -- cgit v1.2.3 From 9213789c44beaf4bf734bc6192dc646d706d5c44 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Mon, 4 Sep 2017 14:50:12 -0700 Subject: Fix merge conflict --- ui/app/components/dropdowns/network-dropdown.js | 6 ------ 1 file changed, 6 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js index 3f4ea6274..23af3f7e4 100644 --- a/ui/app/components/dropdowns/network-dropdown.js +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -147,13 +147,7 @@ NetworkDropdown.prototype.render = function () { key: 'rinkeby', closeMenu: () => this.props.hideNetworkDropdown(), onClick: () => props.setProviderType('rinkeby'), -<<<<<<< HEAD - style: { - fontSize: '18px', - }, -======= style: dropdownMenuItemStyle, ->>>>>>> Fix menu style }, [ providerType === 'rinkeby' ? h('.network-check', '✓') : h('.network-check__transparent', '✓'), -- cgit v1.2.3 From 75c3009f839f94a19830673673f4b9ac25342633 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Mon, 4 Sep 2017 15:55:14 -0700 Subject: Fix header style; Address comments --- .../dropdowns/account-selection-dropdown.js | 2 +- .../dropdowns/components/account-dropdowns.js | 31 +++++++--------------- ui/app/components/dropdowns/components/dropdown.js | 11 +++++++- ui/app/components/dropdowns/network-dropdown.js | 28 +++++++++---------- ui/app/components/menu-droppo.js | 4 ++- 5 files changed, 37 insertions(+), 39 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/account-selection-dropdown.js b/ui/app/components/dropdowns/account-selection-dropdown.js index b1f4d68ce..7a8502d18 100644 --- a/ui/app/components/dropdowns/account-selection-dropdown.js +++ b/ui/app/components/dropdowns/account-selection-dropdown.js @@ -15,7 +15,7 @@ module.exports = AccountSelectionDropdown // TODO: selectedAddress is not defined... should we use selected? AccountSelectionDropdown.prototype.render = function () { const { selected, network, identities, style, dropdownWrapperStyle, menuItemStyles } = this.props - console.log({style}) + return h(AccountDropdowns, { enableAccountOptions: false, enableAccountsSelector: true, diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index be9245c0e..1961a61b5 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -181,7 +181,6 @@ class AccountDropdowns extends Component { h('span', { style: { marginLeft: '20px', - fontSize: '18px', fontFamily: 'DIN OT', fontSize: '16px', lineHeight: '23px', @@ -215,7 +214,6 @@ class AccountDropdowns extends Component { h('span', { style: { marginLeft: '20px', - fontSize: '18px', marginBottom: '5px', fontFamily: 'DIN OT', fontSize: '16px', @@ -231,6 +229,10 @@ class AccountDropdowns extends Component { renderAccountOptions () { const { actions, dropdownWrapperStyle, useCssTransition } = this.props const { optionsMenuActive, menuItemStyles } = this.state + const dropdownMenuItemStyle = { + fontFamily: 'DIN OT', + fontSize: 16, + } return h( Dropdown, @@ -262,10 +264,7 @@ class AccountDropdowns extends Component { this.props.actions.showAccountDetailModal() }, style: Object.assign( - { - fontFamily: 'DIN OT', - fontSize: 16, - }, + dropdownMenuItemStyle, menuItemStyles, ), }, @@ -281,10 +280,7 @@ class AccountDropdowns extends Component { global.platform.openWindow({ url }) }, style: Object.assign( - { - fontFamily: 'DIN OT', - fontSize: 16, - }, + dropdownMenuItemStyle, menuItemStyles, ), }, @@ -300,10 +296,7 @@ class AccountDropdowns extends Component { copyToClipboard(checkSumAddress) }, style: Object.assign( - { - fontFamily: 'DIN OT', - fontSize: 16, - }, + dropdownMenuItemStyle, menuItemStyles, ), }, @@ -317,10 +310,7 @@ class AccountDropdowns extends Component { actions.requestAccountExport() }, style: Object.assign( - { - fontFamily: 'DIN OT', - fontSize: 16, - }, + dropdownMenuItemStyle, menuItemStyles, ), }, @@ -334,10 +324,7 @@ class AccountDropdowns extends Component { actions.showAddTokenPage() }, style: Object.assign( - { - fontFamily: 'DIN OT', - fontSize: 16, - }, + dropdownMenuItemStyle, menuItemStyles, ), }, diff --git a/ui/app/components/dropdowns/components/dropdown.js b/ui/app/components/dropdowns/components/dropdown.js index 1f35f0c70..c4b2c2550 100644 --- a/ui/app/components/dropdowns/components/dropdown.js +++ b/ui/app/components/dropdowns/components/dropdown.js @@ -8,7 +8,15 @@ const noop = () => {} class Dropdown extends Component { render () { - const { isOpen, onClickOutside, style, innerStyle, children, useCssTransition } = this.props + const { + containerClassName, + isOpen, + onClickOutside, + style, + innerStyle, + children, + useCssTransition, + } = this.props const innerStyleDefaults = extend({ borderRadius: '4px', @@ -20,6 +28,7 @@ class Dropdown extends Component { return h( MenuDroppo, { + containerClassName, useCssTransition, isOpen, zIndex: 30, diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js index 23af3f7e4..fa0bb899e 100644 --- a/ui/app/components/dropdowns/network-dropdown.js +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -54,7 +54,7 @@ NetworkDropdown.prototype.render = function () { fontFamily: 'DIN OT', fontSize: '16px', lineHeight: '20px', - }; + } return h(Dropdown, { useCssTransition: true, @@ -72,10 +72,10 @@ NetworkDropdown.prototype.render = function () { this.props.hideNetworkDropdown() } }, + containerClassName: 'network-droppo', zIndex: 11, style: { position: 'absolute', - right: '2px', top: '38px', minWidth: '309px', }, @@ -95,9 +95,9 @@ NetworkDropdown.prototype.render = function () { [ providerType === 'mainnet' ? h('.network-check', '✓') : h('.network-check__transparent', '✓'), h('.menu-icon.diamond'), - h('span.network-name', { + h('span.network-name-item', { style: { - color: providerType === 'mainnet' ? '#ffffff' : '#9b9b9b' + color: providerType === 'mainnet' ? '#ffffff' : '#9b9b9b', }, }, 'Main Ethereum Network'), ] @@ -114,9 +114,9 @@ NetworkDropdown.prototype.render = function () { [ providerType === 'ropsten' ? h('.network-check', '✓') : h('.network-check__transparent', '✓'), h('.menu-icon.red-dot'), - h('span.network-name', { + h('span.network-name-item', { style: { - color: providerType === 'ropsten' ? '#ffffff' : '#9b9b9b' + color: providerType === 'ropsten' ? '#ffffff' : '#9b9b9b', }, }, 'Ropsten Test Network'), ] @@ -133,9 +133,9 @@ NetworkDropdown.prototype.render = function () { [ providerType === 'kovan' ? h('.network-check', '✓') : h('.network-check__transparent', '✓'), h('.menu-icon.hollow-diamond'), - h('span.network-name', { + h('span.network-name-item', { style: { - color: providerType === 'kovan' ? '#ffffff' : '#9b9b9b' + color: providerType === 'kovan' ? '#ffffff' : '#9b9b9b', }, }, 'Kovan Test Network'), ] @@ -152,9 +152,9 @@ NetworkDropdown.prototype.render = function () { [ providerType === 'rinkeby' ? h('.network-check', '✓') : h('.network-check__transparent', '✓'), h('.menu-icon.golden-square'), - h('span.network-name', { + h('span.network-name-item', { style: { - color: providerType === 'rinkeby' ? '#ffffff' : '#9b9b9b' + color: providerType === 'rinkeby' ? '#ffffff' : '#9b9b9b', }, }, 'Rinkeby Test Network'), ] @@ -171,9 +171,9 @@ NetworkDropdown.prototype.render = function () { [ activeNetwork === 'http://localhost:8545' ? h('.network-check', '✓') : h('.network-check__transparent', '✓'), h('i.fa.fa-question-circle.fa-lg.menu-icon'), - h('span.network-name', { + h('span.network-name-item', { style: { - color: activeNetwork === 'http://localhost:8545' ? '#ffffff' : '#9b9b9b' + color: activeNetwork === 'http://localhost:8545' ? '#ffffff' : '#9b9b9b', }, }, 'Localhost 8545'), ] @@ -192,9 +192,9 @@ NetworkDropdown.prototype.render = function () { [ activeNetwork === 'custom' ? h('.check', '✓') : h('.network-check__transparent', '✓'), h('i.fa.fa-question-circle.fa-lg.menu-icon'), - h('span.network-name', { + h('span.network-name-item', { style: { - color: activeNetwork === 'custom' ? '#ffffff' : '#9b9b9b' + color: activeNetwork === 'custom' ? '#ffffff' : '#9b9b9b', }, }, 'Custom RPC'), ] diff --git a/ui/app/components/menu-droppo.js b/ui/app/components/menu-droppo.js index 2f173544e..95b75f54c 100644 --- a/ui/app/components/menu-droppo.js +++ b/ui/app/components/menu-droppo.js @@ -13,6 +13,7 @@ function MenuDroppoComponent () { } MenuDroppoComponent.prototype.render = function () { + const { containerClassName = '' } = this.props const speed = this.props.speed || '300ms' const useCssTransition = this.props.useCssTransition const zIndex = ('zIndex' in this.props) ? this.props.zIndex : 0 @@ -26,8 +27,9 @@ MenuDroppoComponent.prototype.render = function () { style.zIndex = zIndex return ( - h('.menu-droppo-container', { + h('div', { style, + className: `.menu-droppo-container ${containerClassName}`, }, [ h('style', ` .menu-droppo-enter { -- cgit v1.2.3 From 3cb51e32c9706aebd47859018aff4e1917065b16 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 30 Aug 2017 22:33:32 -0230 Subject: Capitalizations via text-transform for main screen transactions. --- ui/app/components/tx-list.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 92a9b6f46..c63284b7e 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -40,8 +40,8 @@ TxList.prototype.render = function () { }, [ h('div', { - style: {}, - }, 'TRANSACTIONS'), + style: {} + }, 'transactions'), ]), -- cgit v1.2.3 From 7d6ad48f15aa65d28de724f550f911234ad2c58e Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 31 Aug 2017 04:58:45 -0230 Subject: Touch up transaction list item styles, remove main-content scroll bars, align buttons with main-content.. --- ui/app/components/tx-list.js | 85 +++++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 40 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index c63284b7e..bd7d77c48 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -66,63 +66,68 @@ TxList.prototype.renderTransactionListItem = function (transaction) { } const { address, transactionStatus, transactionAmount, dateString } = props - return h('div.flex-column.tx-list-item-wrapper', { - style: {}, - }, [ - - h('div.tx-list-date-wrapper', { - style: {}, - }, [ - h('span.tx-list-date', {}, [ - dateString, - ]), - ]), - - h('div.flex-row.tx-list-content-wrapper', { - style: {}, + return h('div', {}, [ + h('div.flex-column.tx-list-item-wrapper', { + style: {} }, [ - h('div.tx-list-identicon-wrapper', { - style: {}, + h('div.tx-list-date-wrapper', { + style: {} }, [ - h(Identicon, { - address, - diameter: 24, - }), + h('span.tx-list-date', {}, [ + dateString, + ]) ]), - h('div.tx-list-account-and-status-wrapper', {}, [ - h('div.tx-list-account-wrapper', { - style: {}, + h('div.flex-row.tx-list-content-wrapper', { + style: {} + }, [ + + h('div.tx-list-identicon-wrapper', { + style: {} }, [ - h('span.tx-list-account', {}, [ - `${address.slice(0, 10)}...${address.slice(-4)}`, - ]), + h(Identicon, { + address, + diameter: 28, + }) ]), - h('div.tx-list-status-wrapper', { - style: {}, - }, [ - h('span.tx-list-status', {}, [ - transactionStatus, + h('div.tx-list-account-and-status-wrapper', {}, [ + h('div.tx-list-account-wrapper', { + style: {} + }, [ + h('span.tx-list-account', {}, [ + `${address.slice(0, 10)}...${address.slice(-4)}` + ]), + ]), + + h('div.tx-list-status-wrapper', { + style: {} + }, [ + h('span.tx-list-status', {}, [ + transactionStatus, + ]), ]), ]), - ]), - h('div.flex-column.tx-list-details-wrapper', { - style: {}, - }, [ + h('div.flex-column.tx-list-details-wrapper', { + style: {} + }, [ - h('span.tx-list-value', {}, [ - transactionAmount, - ]), + h('span.tx-list-value', {}, [ + transactionAmount, + ]), + + h('span.tx-list-fiat-value', {}, [ + '+ $300 USD', + ]), - h('span.tx-list-fiat-value', {}, [ - '+ $300 USD', ]), ]), ]), + contentDivider + ]) } -- cgit v1.2.3 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 ++++++++- 5 files changed, 83 insertions(+), 104 deletions(-) (limited to 'ui/app/components') 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(), + ]) } -- cgit v1.2.3 From 690ddf5ed75967537aa5513986146c262012832a Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Wed, 6 Sep 2017 00:33:39 -0700 Subject: Fix token list --- ui/app/components/token-list.js | 35 +++++++++++++++++++++-------------- ui/app/components/tx-list.js | 4 +++- 2 files changed, 24 insertions(+), 15 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js index 7fe072fac..fea87a733 100644 --- a/ui/app/components/token-list.js +++ b/ui/app/components/token-list.js @@ -45,7 +45,7 @@ TokenList.prototype.render = function () { const { userAddress, network } = this.props if (isLoading) { - return this.message('Loading') + return this.message('Loading Tokens...') } if (error) { @@ -115,22 +115,29 @@ TokenList.prototype.createFreshTokenTracker = function () { }) } -TokenList.prototype.componentWillUpdate = function (nextProps) { - if (nextProps.network === 'loading') return - const oldNet = this.props.network - const newNet = nextProps.network - - if (oldNet && newNet && newNet !== oldNet) { - this.setState({ isLoading: true }) - this.createFreshTokenTracker() - } +TokenList.prototype.componentDidUpdate = function (nextProps) { + const { + network: oldNet, + userAddress: oldAddress, + } = this.props + const { + network: newNet, + userAddress: newAddress, + } = nextProps + + if (newNet === 'loading') return + if (!oldNet || !newNet || !oldAddress || !newAddress) return + if (oldAddress === newAddress && oldNet === newNet) return + + this.setState({ isLoading: true }) + this.createFreshTokenTracker() } TokenList.prototype.updateBalances = function (tokens) { - // const heldTokens = tokens.filter(token => { - // return token.balance !== '0' && token.string !== '0.000' - // }) - this.setState({ tokens: tokens, isLoading: false }) + const heldTokens = tokens.filter(token => { + return token.balance !== '0' && token.string !== '0.000' + }) + this.setState({ tokens: heldTokens, isLoading: false }) } TokenList.prototype.componentWillUnmount = function () { diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index b8a18970f..0eb15aa70 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -65,12 +65,14 @@ TxList.prototype.renderTransactionListItem = function (transaction) { transactionAmount: formatBalance(transaction.txParams.value, 6), } const { - address = '', + address, transactionStatus, transactionAmount, dateString, } = props + if (!address) return null + return h('div', { key: transaction.id, }, [ -- cgit v1.2.3 From f1fb9e10a06d1811d97f61b6369684979b7ecf70 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Wed, 6 Sep 2017 03:17:49 -0700 Subject: Adding Token transaction detail screen --- ui/app/components/balance-component.js | 28 +++++++-- ui/app/components/token-balance.js | 104 +++++++++++++++++++++++++++++++++ ui/app/components/token-cell.js | 25 +++++++- ui/app/components/token-list.js | 10 +--- ui/app/components/tx-view.js | 75 ++++++++++++------------ ui/app/components/wallet-view.js | 48 +++++++-------- 6 files changed, 213 insertions(+), 77 deletions(-) create mode 100644 ui/app/components/token-balance.js (limited to 'ui/app/components') diff --git a/ui/app/components/balance-component.js b/ui/app/components/balance-component.js index 48efc7b6a..6b997944f 100644 --- a/ui/app/components/balance-component.js +++ b/ui/app/components/balance-component.js @@ -2,13 +2,19 @@ const Component = require('react').Component const connect = require('react-redux').connect const h = require('react-hyperscript') const inherits = require('util').inherits +const TokenBalance = require('./token-balance') const { formatBalance, generateBalanceObject } = require('../util') module.exports = connect(mapStateToProps)(BalanceComponent) function mapStateToProps (state) { + const accounts = state.metamask.accounts + const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] + const account = accounts[selectedAddress] + return { + account, conversionRate: state.metamask.conversionRate, currentCurrency: state.metamask.currentCurrency, } @@ -21,9 +27,8 @@ function BalanceComponent () { BalanceComponent.prototype.render = function () { const props = this.props - const { balanceValue } = props - const needsParse = 'needsParse' in props ? props.needsParse : true - const formattedBalance = balanceValue ? formatBalance(balanceValue, 6, needsParse) : '...' + // const { balanceValue } = props + const { token } = props return h('div.balance-container', {}, [ @@ -33,13 +38,24 @@ BalanceComponent.prototype.render = function () { style: {}, }), - this.renderBalance(formattedBalance), + token ? this.renderTokenBalance() : this.renderBalance(), ]) } -BalanceComponent.prototype.renderBalance = function (formattedBalance) { +BalanceComponent.prototype.renderTokenBalance = function () { + const { token } = this.props + + return h('div.flex-column.balance-display', [ + h('div.token-amount', [ h(TokenBalance, { token }) ]), + ]) +} + +BalanceComponent.prototype.renderBalance = function () { const props = this.props - const { shorten } = props + const { shorten, account } = props + const balanceValue = account && account.balance + const needsParse = 'needsParse' in props ? props.needsParse : true + const formattedBalance = balanceValue ? formatBalance(balanceValue, 6, needsParse) : '...' const showFiat = 'showFiat' in props ? props.showFiat : true if (formattedBalance === 'None' || formattedBalance === '...') { diff --git a/ui/app/components/token-balance.js b/ui/app/components/token-balance.js new file mode 100644 index 000000000..0757cc65c --- /dev/null +++ b/ui/app/components/token-balance.js @@ -0,0 +1,104 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const TokenTracker = require('eth-token-tracker') +const connect = require('react-redux').connect +const selectors = require('../selectors') + +function mapStateToProps (state) { + return { + userAddress: selectors.getSelectedAddress(state), + } +} + +module.exports = connect(mapStateToProps)(TokenBalance) + + +inherits(TokenBalance, Component) +function TokenBalance () { + this.state = { + balance: '', + isLoading: true, + error: null, + } + Component.call(this) +} + +TokenBalance.prototype.render = function () { + const state = this.state + const { balance, isLoading } = state + + return isLoading + ? h('span', '') + : h('span', balance) +} + +TokenBalance.prototype.componentDidMount = function () { + this.createFreshTokenTracker() +} + +TokenBalance.prototype.createFreshTokenTracker = function () { + if (this.tracker) { + // Clean up old trackers when refreshing: + this.tracker.stop() + this.tracker.removeListener('update', this.balanceUpdater) + this.tracker.removeListener('error', this.showError) + } + + if (!global.ethereumProvider) return + const { userAddress, token } = this.props + + this.tracker = new TokenTracker({ + userAddress, + provider: global.ethereumProvider, + tokens: [token], + pollingInterval: 8000, + }) + + + // Set up listener instances for cleaning up + this.balanceUpdater = this.updateBalance.bind(this) + this.showError = error => { + this.setState({ error, isLoading: false }) + } + this.tracker.on('update', this.balanceUpdater) + this.tracker.on('error', this.showError) + + this.tracker.updateBalances() + .then(() => { + this.updateBalance(this.tracker.serialize()) + }) + .catch((reason) => { + log.error(`Problem updating balances`, reason) + this.setState({ isLoading: false }) + }) +} + +TokenBalance.prototype.componentDidUpdate = function (nextProps) { + const { + userAddress: oldAddress, + } = this.props + const { + userAddress: newAddress, + } = nextProps + + if (!oldAddress || !newAddress) return + if (oldAddress === newAddress) return + + this.setState({ isLoading: true }) + this.createFreshTokenTracker() +} + +TokenBalance.prototype.updateBalance = function (tokens = []) { + const [{ string }] = tokens + this.setState({ + balance: string, + isLoading: false, + }) +} + +TokenBalance.prototype.componentWillUnmount = function () { + if (!this.tracker) return + this.tracker.stop() +} + diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index a24e4e1ac..7fae67de6 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -1,10 +1,27 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits +const connect = require('react-redux').connect const Identicon = require('./identicon') const prefixForNetwork = require('../../lib/etherscan-prefix-for-network') +const selectors = require('../selectors') +const actions = require('../actions') -module.exports = TokenCell +function mapStateToProps (state) { + return { + network: state.metamask.network, + selectedTokenAddress: state.metamask.selectedTokenAddress, + userAddress: selectors.getSelectedAddress(state), + } +} + +function mapDispatchToProps (dispatch) { + return { + setSelectedToken: address => dispatch(actions.setSelectedToken(address)), + } +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)(TokenCell) inherits(TokenCell, Component) function TokenCell () { @@ -18,13 +35,17 @@ TokenCell.prototype.render = function () { symbol, string, network, + setSelectedToken, + selectedTokenAddress, // userAddress, } = props return ( h('div.token-list-item', { - style: { cursor: network === '1' ? 'pointer' : 'default' }, + className: `token-list-item ${selectedTokenAddress ? 'token-list-item--active' : ''}`, + // style: { cursor: network === '1' ? 'pointer' : 'default' }, // onClick: this.view.bind(this, address, userAddress, network), + onClick: () => setSelectedToken(address), }, [ h(Identicon, { diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js index fea87a733..2d1dd0ea7 100644 --- a/ui/app/components/token-list.js +++ b/ui/app/components/token-list.js @@ -8,7 +8,6 @@ const connect = require('react-redux').connect const selectors = require('../selectors') function mapStateToProps (state) { - return { network: state.metamask.network, tokens: state.metamask.tokens, @@ -42,7 +41,6 @@ function TokenList () { TokenList.prototype.render = function () { const state = this.state const { tokens, isLoading, error } = state - const { userAddress, network } = this.props if (isLoading) { return this.message('Loading Tokens...') @@ -53,13 +51,7 @@ TokenList.prototype.render = function () { return this.message('There was a problem loading your token balances.') } - const tokenViews = tokens.map((tokenData) => { - tokenData.network = network - tokenData.userAddress = userAddress - return h(TokenCell, tokenData) - }) - - return h('div', tokenViews) + return h('div', tokens.map((tokenData) => h(TokenCell, tokenData))) } TokenList.prototype.message = function (body) { diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 9f75f7b31..d7e4a5b4b 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -4,10 +4,12 @@ const h = require('react-hyperscript') const ethUtil = require('ethereumjs-util') const inherits = require('util').inherits const actions = require('../actions') +const selectors = require('../selectors') const BalanceComponent = require('./balance-component') const TxList = require('./tx-list') const Identicon = require('./identicon') +const TokenBalance = require('./token-balance') module.exports = connect(mapStateToProps, mapDispatchToProps)(TxView) @@ -16,6 +18,7 @@ function mapStateToProps (state) { const identities = state.metamask.identities const accounts = state.metamask.accounts + const selectedTokenAddress = state.metamask.selectedTokenAddress const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] const checksumAddress = selectedAddress && ethUtil.toChecksumAddress(selectedAddress) const identity = identities[selectedAddress] @@ -25,6 +28,8 @@ function mapStateToProps (state) { sidebarOpen, selectedAddress, checksumAddress, + selectedTokenAddress, + selectedToken: selectors.getSelectedToken(state), identity, account, } @@ -44,9 +49,41 @@ function TxView () { Component.call(this) } +TxView.prototype.renderHeroBalance = function () { + const {account, selectedToken, showModal, showSendPage } = this.props + + return h('div.hero-balance', {}, [ + + h(BalanceComponent, { + balanceValue: account && account.balance, + token: selectedToken, + }), + + h('div.flex-row.flex-center.hero-balance-buttons', {}, [ + h('button.btn-clear', { + style: { + textAlign: 'center', + }, + onClick: () => showModal({ + name: 'BUY', + }), + }, 'BUY'), + + h('button.btn-clear', { + style: { + textAlign: 'center', + marginLeft: '0.8em', + }, + onClick: showSendPage, + }, 'SEND'), + + ]), + ]) +} + TxView.prototype.render = function () { - const { selectedAddress, identity, account } = this.props + const { selectedAddress, identity } = this.props return h('div.tx-view.flex-column', { style: {}, @@ -87,41 +124,7 @@ TxView.prototype.render = function () { ]), - h('div.hero-balance', { - style: {}, - }, [ - - h(BalanceComponent, { - balanceValue: account && account.balance, - style: {}, - }), - - h('div.flex-row.flex-center.hero-balance-buttons', { - style: {}, - }, [ - h('button.btn-clear', { - style: { - textAlign: 'center', - }, - onClick: () => { - this.props.showModal({ - name: 'BUY', - }) - }, - }, 'BUY'), - - h('button.btn-clear', { - style: { - textAlign: 'center', - marginLeft: '0.8em', - }, - onClick: () => { - this.props.showSendPage() - }, - }, 'SEND'), - - ]), - ]), + this.renderHeroBalance(), h(TxList, {}), diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 304b5daba..f9710ea4c 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -22,6 +22,7 @@ function mapStateToProps (state) { selectedAddress: selectors.getSelectedAddress(state), selectedIdentity: selectors.getSelectedIdentity(state), selectedAccount: selectors.getSelectedAccount(state), + selectedTokenAddress: state.metamask.selectedTokenAddress, } } @@ -29,6 +30,7 @@ function mapDispatchToProps (dispatch) { return { showSendPage: () => { dispatch(actions.showSendPage()) }, hideSidebar: () => { dispatch(actions.hideSidebar()) }, + unsetSelectedToken: () => dispatch(actions.setSelectedToken()), } } @@ -37,15 +39,26 @@ 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.renderWalletBalance = function () { + const { selectedTokenAddress, selectedAccount, unsetSelectedToken } = this.props + const selectedClass = selectedTokenAddress + ? '' + : 'wallet-balance-wrapper--active' + const className = `flex-column wallet-balance-wrapper ${selectedClass}` + + return h('div', { className }, [ + h('div.wallet-balance', + { + onClick: () => unsetSelectedToken(), + }, + [ + h(BalanceComponent, { + balanceValue: selectedAccount.balance, + style: {}, + }), + ] + ), + ]) } WalletView.prototype.render = function () { @@ -139,22 +152,9 @@ WalletView.prototype.render = function () { ]), ]), - // Wallet Balances - h('div.flex-column.wallet-balance-wrapper.wallet-balance-wrapper-active', {}, [ - - h('div.wallet-balance', {}, [ - - h(BalanceComponent, { - balanceValue: selectedAccount.balance, - style: {}, - }), - - ]), - - - ]), + this.renderWalletBalance(), - this.renderTokenBalances(), + h(TokenList), ]) } -- cgit v1.2.3 From 14b2f3e391752cca02c05ae0137e490bfdcdd7a7 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Wed, 6 Sep 2017 23:03:23 -0700 Subject: Show token balance and identicon --- ui/app/components/balance-component.js | 17 +++++--- ui/app/components/identicon.js | 44 ++++++++++++-------- ui/app/components/token-balance.js | 4 +- ui/app/components/token-cell.js | 6 +-- ui/app/components/tx-list.js | 1 - ui/app/components/tx-view.js | 73 ++++++++++++++++++++-------------- ui/app/components/wallet-view.js | 2 +- 7 files changed, 90 insertions(+), 57 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/balance-component.js b/ui/app/components/balance-component.js index 6b997944f..6d73d5b4a 100644 --- a/ui/app/components/balance-component.js +++ b/ui/app/components/balance-component.js @@ -3,6 +3,7 @@ const connect = require('react-redux').connect const h = require('react-hyperscript') const inherits = require('util').inherits const TokenBalance = require('./token-balance') +const Identicon = require('./identicon') const { formatBalance, generateBalanceObject } = require('../util') @@ -10,11 +11,13 @@ module.exports = connect(mapStateToProps)(BalanceComponent) function mapStateToProps (state) { const accounts = state.metamask.accounts + const network = state.metamask.network const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] const account = accounts[selectedAddress] return { account, + network, conversionRate: state.metamask.conversionRate, currentCurrency: state.metamask.currentCurrency, } @@ -27,15 +30,19 @@ function BalanceComponent () { BalanceComponent.prototype.render = function () { const props = this.props - // const { balanceValue } = props - const { token } = props + const { token, network } = props return h('div.balance-container', {}, [ // TODO: balance icon needs to be passed in - h('img.balance-icon', { - src: '../images/eth_logo.svg', - style: {}, + // h('img.balance-icon', { + // src: '../images/eth_logo.svg', + // style: {}, + // }), + h(Identicon, { + diameter: 45, + address: token && token.address, + network, }), token ? this.renderTokenBalance() : this.renderBalance(), diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index 71831fe71..259fa4d73 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -18,23 +18,35 @@ function IdenticonComponent () { IdenticonComponent.prototype.render = function () { var props = this.props - const { className = '' } = props + const { className = '', address } = props var diameter = props.diameter || this.defaultDiameter - return ( - h('div', { - className: `${className} identicon`, - key: 'identicon-' + this.props.address, - style: { - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - height: diameter, - width: diameter, - borderRadius: diameter / 2, - overflow: 'hidden', - }, - }) - ) + + return address + ? ( + h('div', { + className: `${className} identicon`, + key: 'identicon-' + address, + style: { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + height: diameter, + width: diameter, + borderRadius: diameter / 2, + overflow: 'hidden', + }, + }) + ) + : ( + h('img.balance-icon', { + src: '../images/eth_logo.svg', + style: { + height: diameter, + width: diameter, + borderRadius: diameter / 2, + }, + }) + ) } IdenticonComponent.prototype.componentDidMount = function () { diff --git a/ui/app/components/token-balance.js b/ui/app/components/token-balance.js index 0757cc65c..d7fe168eb 100644 --- a/ui/app/components/token-balance.js +++ b/ui/app/components/token-balance.js @@ -90,9 +90,9 @@ TokenBalance.prototype.componentDidUpdate = function (nextProps) { } TokenBalance.prototype.updateBalance = function (tokens = []) { - const [{ string }] = tokens + const [{ string, symbol }] = tokens this.setState({ - balance: string, + balance: `${string} ${symbol}`, isLoading: false, }) } diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index 7fae67de6..e3ed734f4 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -58,9 +58,9 @@ TokenCell.prototype.render = function () { h('h.token-list-item__balance-wrapper', null, [ h('h3.token-list-item__token-balance', `${string || 0} ${symbol}`), - h('div.token-list-item__fiat-amount', { - style: {}, - }, '210 FPO'), + // h('div.token-list-item__fiat-amount', { + // style: {}, + // }, '210 FPO'), ]), /* diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 0eb15aa70..524808e2e 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -27,7 +27,6 @@ const contentDivider = h('div.tx-list-content-divider', { TxList.prototype.render = function () { const { txsToRender } = this.props - console.log('transactions to render', txsToRender) return h('div.flex-column.tx-list-container', {}, [ diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index d7e4a5b4b..c9be0d67d 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -9,7 +9,6 @@ const selectors = require('../selectors') const BalanceComponent = require('./balance-component') const TxList = require('./tx-list') const Identicon = require('./identicon') -const TokenBalance = require('./token-balance') module.exports = connect(mapStateToProps, mapDispatchToProps)(TxView) @@ -18,11 +17,11 @@ function mapStateToProps (state) { const identities = state.metamask.identities const accounts = state.metamask.accounts + const network = state.metamask.network const selectedTokenAddress = state.metamask.selectedTokenAddress const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] const checksumAddress = selectedAddress && ethUtil.toChecksumAddress(selectedAddress) const identity = identities[selectedAddress] - const account = accounts[selectedAddress] return { sidebarOpen, @@ -31,7 +30,7 @@ function mapStateToProps (state) { selectedTokenAddress, selectedToken: selectors.getSelectedToken(state), identity, - account, + network, } } @@ -50,40 +49,55 @@ function TxView () { } TxView.prototype.renderHeroBalance = function () { - const {account, selectedToken, showModal, showSendPage } = this.props + const { selectedToken } = this.props return h('div.hero-balance', {}, [ - h(BalanceComponent, { - balanceValue: account && account.balance, - token: selectedToken, - }), + h(BalanceComponent, { token: selectedToken }), - h('div.flex-row.flex-center.hero-balance-buttons', {}, [ - h('button.btn-clear', { - style: { - textAlign: 'center', - }, - onClick: () => showModal({ - name: 'BUY', - }), - }, 'BUY'), - - h('button.btn-clear', { - style: { - textAlign: 'center', - marginLeft: '0.8em', - }, - onClick: showSendPage, - }, 'SEND'), - - ]), + this.renderButtons(), ]) } -TxView.prototype.render = function () { +TxView.prototype.renderButtons = function () { + const {selectedToken, showModal, showSendPage } = this.props + + return !selectedToken + ? ( + h('div.flex-row.flex-center.hero-balance-buttons', [ + h('button.btn-clear', { + style: { + textAlign: 'center', + }, + onClick: () => showModal({ + name: 'BUY', + }), + }, 'BUY'), + + h('button.btn-clear', { + style: { + textAlign: 'center', + marginLeft: '0.8em', + }, + onClick: showSendPage, + }, 'SEND'), + ]) + ) + : ( + h('div.flex-row.flex-center.hero-balance-buttons', [ + h('button.btn-clear', { + style: { + textAlign: 'center', + marginLeft: '0.8em', + }, + onClick: showSendPage, + }, 'SEND'), + ]) + ) +} - const { selectedAddress, identity } = this.props +TxView.prototype.render = function () { + const { selectedAddress, identity, network } = this.props return h('div.tx-view.flex-column', { style: {}, @@ -113,6 +127,7 @@ TxView.prototype.render = function () { h(Identicon, { diameter: 24, address: selectedAddress, + network, }), ]), diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index f9710ea4c..08c28f1dc 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -49,7 +49,7 @@ WalletView.prototype.renderWalletBalance = function () { return h('div', { className }, [ h('div.wallet-balance', { - onClick: () => unsetSelectedToken(), + onClick: unsetSelectedToken, }, [ h(BalanceComponent, { -- cgit v1.2.3 From 983fa2a11721aa7d1307ef76d516e25a50d0eedf Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Thu, 7 Sep 2017 03:14:53 -0700 Subject: Add Contract Tx List Item; Update Token Tx on select --- ui/app/components/token-balance.js | 6 ++++-- ui/app/components/token-cell.js | 2 +- ui/app/components/tx-list.js | 42 +++++++++++++++++++++++--------------- ui/app/components/wallet-view.js | 4 ++-- 4 files changed, 32 insertions(+), 22 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/token-balance.js b/ui/app/components/token-balance.js index d7fe168eb..b4a249300 100644 --- a/ui/app/components/token-balance.js +++ b/ui/app/components/token-balance.js @@ -77,13 +77,15 @@ TokenBalance.prototype.createFreshTokenTracker = function () { TokenBalance.prototype.componentDidUpdate = function (nextProps) { const { userAddress: oldAddress, + token: { address: oldTokenAddress }, } = this.props const { userAddress: newAddress, + token: { address: newTokenAddress }, } = nextProps - if (!oldAddress || !newAddress) return - if (oldAddress === newAddress) return + if ((!oldAddress || !newAddress) && (!oldTokenAddress || !newTokenAddress)) return + if ((oldAddress === newAddress) && (oldTokenAddress === newTokenAddress)) return this.setState({ isLoading: true }) this.createFreshTokenTracker() diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index e3ed734f4..a6fe8fc61 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -42,7 +42,7 @@ TokenCell.prototype.render = function () { return ( h('div.token-list-item', { - className: `token-list-item ${selectedTokenAddress ? 'token-list-item--active' : ''}`, + className: `token-list-item ${selectedTokenAddress === address ? 'token-list-item--active' : ''}`, // style: { cursor: network === '1' ? 'pointer' : 'default' }, // onClick: this.view.bind(this, address, userAddress, network), onClick: () => setSelectedToken(address), diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 524808e2e..04d2eaa79 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -20,14 +20,9 @@ function TxList () { Component.call(this) } -const contentDivider = h('div.tx-list-content-divider', { - style: {}, -}) - TxList.prototype.render = function () { - const { txsToRender } = this.props - console.log('transactions to render', txsToRender) + // console.log('transactions to render', txsToRender) return h('div.flex-column.tx-list-container', {}, [ @@ -46,15 +41,31 @@ TxList.prototype.render = function () { ]), - contentDivider, - - txsToRender.map((transaction) => { - return this.renderTransactionListItem(transaction) - }), + this.renderTranstions(), ]) } +TxList.prototype.getAddressText = function (transaction) { + const { + txParams: { to }, + } = transaction + + return to + ? `${to.slice(0, 10)}...${to.slice(-4)}` + : 'Contract Published' +} + +TxList.prototype.renderTranstions = function () { + const { txsToRender } = this.props + + return txsToRender.length + ? txsToRender.map((transaction) => { + return this.renderTransactionListItem(transaction) + }) + : h('div.tx-list-item.tx-list-item--empty', [ 'No Transactions' ]) +} + // TODO: Consider moving TxListItem into a separate component TxList.prototype.renderTransactionListItem = function (transaction) { const props = { @@ -70,12 +81,10 @@ TxList.prototype.renderTransactionListItem = function (transaction) { dateString, } = props - if (!address) return null - - return h('div', { + return h('div.tx-list-item', { key: transaction.id, }, [ - h('div.flex-column.tx-list-item-wrapper', { + h('div.flex-column.tx-list-item__wrapper', { style: {}, }, [ @@ -105,7 +114,7 @@ TxList.prototype.renderTransactionListItem = function (transaction) { style: {}, }, [ h('span.tx-list-account', {}, [ - `${address.slice(0, 10)}...${address.slice(-4)}`, + this.getAddressText(transaction), ]), ]), @@ -134,7 +143,6 @@ TxList.prototype.renderTransactionListItem = function (transaction) { ]), ]), - contentDivider, ]) } diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 08c28f1dc..b306fb7d4 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -64,11 +64,11 @@ WalletView.prototype.renderWalletBalance = function () { WalletView.prototype.render = function () { const { network, responsiveDisplayClassname, identities, - selectedAddress, selectedAccount, accounts, + selectedAddress, accounts, selectedIdentity, } = this.props // temporary logs + fake extra wallets - console.log('walletview, selectedAccount:', selectedAccount) + // console.log('walletview, selectedAccount:', selectedAccount) return h('div.wallet-view.flex-column' + (responsiveDisplayClassname || ''), { style: {}, -- cgit v1.2.3 From 8b919758e51e16536b6edaf33d4978d551363249 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Thu, 7 Sep 2017 04:24:03 -0700 Subject: Send Token screen partial UI --- ui/app/components/send-token/index.js | 213 ++++++++++++++++++++++++++++++++++ ui/app/components/token-balance.js | 4 +- ui/app/components/tx-view.js | 5 +- 3 files changed, 219 insertions(+), 3 deletions(-) create mode 100644 ui/app/components/send-token/index.js (limited to 'ui/app/components') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js new file mode 100644 index 000000000..a49e559dc --- /dev/null +++ b/ui/app/components/send-token/index.js @@ -0,0 +1,213 @@ +const Component = require('react').Component +const connect = require('react-redux').connect +const h = require('react-hyperscript') +const ethUtil = require('ethereumjs-util') +const inherits = require('util').inherits +const actions = require('../../actions') +const selectors = require('../../selectors') + +// const BalanceComponent = require('./balance-component') +const Identicon = require('../identicon') +const TokenBalance = require('../token-balance') +const CurrencyToggle = require('../send/currency-toggle') +const GasTooltip = require('../send/gas-tooltip') +const GasFeeDisplay = require('../send/gas-fee-display') + + +module.exports = connect(mapStateToProps, mapDispatchToProps)(SendTokenScreen) + +function mapStateToProps (state) { + // const sidebarOpen = state.appState.sidebarOpen + + const identities = state.metamask.identities + const addressBook = state.metamask.addressBook + const conversionRate = state.metamask.conversionRate + const currentBlockGasLimit = state.metamask.currentBlockGasLimit + // const accounts = state.metamask.accounts + // const network = state.metamask.network + const selectedTokenAddress = state.metamask.selectedTokenAddress + // const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] + // const checksumAddress = selectedAddress && ethUtil.toChecksumAddress(selectedAddress) + // const identity = identities[selectedAddress] + + return { + // sidebarOpen, + // selectedAddress, + // checksumAddress, + selectedTokenAddress, + identities, + addressBook, + conversionRate, + currentBlockGasLimit, + selectedToken: selectors.getSelectedToken(state), + // selectedToken: selectors.getSelectedToken(state), + // identity, + // network, + } +} + +function mapDispatchToProps (dispatch) { + return { + // showSidebar: () => { dispatch(actions.showSidebar()) }, + // hideSidebar: () => { dispatch(actions.hideSidebar()) }, + // showModal: (payload) => { dispatch(actions.showModal(payload)) }, + // showSendPage: () => { dispatch(actions.showSendPage()) }, + // showSendTokenPage: () => { dispatch(actions.showSendTokenPage()) }, + } +} + +inherits(SendTokenScreen, Component) +function SendTokenScreen () { + Component.call(this) + this.state = { + to: '', + selectedCurrency: 'USD', + isGasTooltipOpen: false, + gasPrice: '0x5d21dba00', + gasLimit: '0x7b0d', + } +} + +SendTokenScreen.prototype.renderToAddressInput = function () { + const { + identities, + addressBook, + } = this.props + + const { + to, + } = this.state + + return h('div.send-screen-input-wrapper', {}, [ + h('div', ['To:']), + h('input.large-input.send-screen-input', { + name: 'address', + list: 'addresses', + placeholder: 'Address', + value: to, + onChange: e => this.setState({ to: e.target.value }), + }), + h('datalist#addresses', [ + // Corresponds to the addresses owned. + Object.entries(identities).map(([key, { address, name }]) => { + return h('option', { + value: address, + label: name, + key: address, + }) + }), + addressBook.map(({ address, name }) => { + return h('option', { + value: address, + label: name, + key: address, + }) + }), + ]), + ]) +} + +SendTokenScreen.prototype.renderAmountInput = function () { + const { + selectedCurrency, + } = this.state + + const { + selectedToken: {symbol}, + } = this.props + + return h('div.send-screen-input-wrapper', {}, [ + h('div.send-screen-amount-labels', [ + h('span', ['Amount']), + h(CurrencyToggle, { + selectedCurrency, + onClick: currency => this.setState({ selectedCurrency: currency }), + }), + ]), + h('input.large-input.send-screen-input', { + placeholder: `0 ${symbol}`, + type: 'number', + onChange: e => this.setState({ amount: e.target.value }), + }), + ]) +} + +SendTokenScreen.prototype.renderGasInput = function () { + const { + isGasTooltipOpen, + gasPrice, + gasLimit, + selectedCurrency, + } = this.state + + const { + conversionRate, + currentBlockGasLimit, + } = this.props + + return h('div.send-screen-input-wrapper', [ + isGasTooltipOpen && h(GasTooltip, { + className: 'send-tooltip', + gasPrice, + gasLimit, + onClose: () => this.setState({ isGasTooltipOpen: false }), + onFeeChange: ({ gasLimit, gasPrice }) => { + this.setState({ gasLimit, gasPrice }) + }, + }), + + h('div.send-screen-gas-labels', {}, [ + h('span', [ h('i.fa.fa-bolt'), 'Gas fee:']), + h('span', ['What\'s this?']), + ]), + h('div.large-input.send-screen-gas-input', [ + h(GasFeeDisplay, { + conversionRate, + gasPrice, + currentCurrency: selectedCurrency, + gas: gasLimit, + blockGasLimit: currentBlockGasLimit, + }), + h( + 'div.send-screen-gas-input-customize', + { onClick: () => this.setState({ isGasTooltipOpen: !isGasTooltipOpen }) }, + ['Customize'] + ), + ]), + ]) +} + +SendTokenScreen.prototype.renderMemoInput = function () { + return h('div.send-screen-input-wrapper', {}, [ + h('div', {}, ['Transaction memo (optional)']), + h( + 'input.large-input.send-screen-input', + { onChange: e => this.setState({ memo: e.target.value }) } + ), + ]) +} + +SendTokenScreen.prototype.render = function () { + const { + selectedTokenAddress, + selectedToken, + } = this.props + + return h('div.send-token', [ + h(Identicon, { + diameter: 75, + address: selectedTokenAddress, + }), + h('div.send-token__title', ['Send Tokens']), + h('div.send-token__description', ['Send Tokens to anyone with an Ethereum account']), + h('div.send-token__balance-text', ['Your Token Balance is:']), + h('div.send-token__token-balance', [ + h(TokenBalance, { token: selectedToken, balanceOnly: true }), + ]), + h('div.send-token__token-symbol', [selectedToken.symbol]), + this.renderToAddressInput(), + this.renderAmountInput(), + this.renderGasInput(), + this.renderMemoInput(), + ]) +} diff --git a/ui/app/components/token-balance.js b/ui/app/components/token-balance.js index b4a249300..3a923eb9d 100644 --- a/ui/app/components/token-balance.js +++ b/ui/app/components/token-balance.js @@ -93,8 +93,10 @@ TokenBalance.prototype.componentDidUpdate = function (nextProps) { TokenBalance.prototype.updateBalance = function (tokens = []) { const [{ string, symbol }] = tokens + const { balanceOnly } = this.props + this.setState({ - balance: `${string} ${symbol}`, + balance: balanceOnly ? string : `${string} ${symbol}`, isLoading: false, }) } diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index c9be0d67d..f5ac6e2dc 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -40,6 +40,7 @@ function mapDispatchToProps (dispatch) { hideSidebar: () => { dispatch(actions.hideSidebar()) }, showModal: (payload) => { dispatch(actions.showModal(payload)) }, showSendPage: () => { dispatch(actions.showSendPage()) }, + showSendTokenPage: () => { dispatch(actions.showSendTokenPage()) }, } } @@ -60,7 +61,7 @@ TxView.prototype.renderHeroBalance = function () { } TxView.prototype.renderButtons = function () { - const {selectedToken, showModal, showSendPage } = this.props + const {selectedToken, showModal, showSendPage, showSendTokenPage } = this.props return !selectedToken ? ( @@ -90,7 +91,7 @@ TxView.prototype.renderButtons = function () { textAlign: 'center', marginLeft: '0.8em', }, - onClick: showSendPage, + onClick: showSendTokenPage, }, 'SEND'), ]) ) -- cgit v1.2.3 From 6d3b3d42034c88475cd90172ddd97b95f04df60e Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 30 Aug 2017 00:46:30 -0230 Subject: Show confirm transaction screen when clicking a pending transaction in the list. --- ui/app/components/buy-button-subview.js | 2 +- ui/app/components/tx-list.js | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/buy-button-subview.js b/ui/app/components/buy-button-subview.js index 15281171c..6cf6e9eb9 100644 --- a/ui/app/components/buy-button-subview.js +++ b/ui/app/components/buy-button-subview.js @@ -245,7 +245,7 @@ BuyButtonSubview.prototype.navigateTo = function (url) { BuyButtonSubview.prototype.backButtonContext = function () { if (this.props.context === 'confTx') { - this.props.dispatch(actions.showConfTxPage(false)) + this.props.dispatch(actions.showConfTxPage({transForward: false})) } else { this.props.dispatch(actions.goHome()) } diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 04d2eaa79..6cbd123f8 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -5,8 +5,9 @@ const inherits = require('util').inherits const selectors = require('../selectors') const Identicon = require('./identicon') const { formatBalance, formatDate } = require('../util') +const { showConfTxPage } = require('../actions') -module.exports = connect(mapStateToProps)(TxList) +module.exports = connect(mapStateToProps, mapDispatchToProps)(TxList) function mapStateToProps (state) { return { @@ -15,6 +16,12 @@ function mapStateToProps (state) { } } +function mapDispatchToProps (dispatch) { + return { + showConfTxPage: ({ id }) => dispatch(showConfTxPage({ id })) + } +} + inherits(TxList, Component) function TxList () { Component.call(this) @@ -22,7 +29,7 @@ function TxList () { TxList.prototype.render = function () { - // console.log('transactions to render', txsToRender) + const { txsToRender, showConfTxPage } = this.props return h('div.flex-column.tx-list-container', {}, [ @@ -73,18 +80,23 @@ TxList.prototype.renderTransactionListItem = function (transaction) { address: transaction.txParams.to, transactionStatus: transaction.status, transactionAmount: formatBalance(transaction.txParams.value, 6), + transActionId: transaction.id, } + const { address, transactionStatus, transactionAmount, dateString, + transActionId, } = props + const { showConfTxPage } = this.props return h('div.tx-list-item', { key: transaction.id, }, [ h('div.flex-column.tx-list-item__wrapper', { + onClick: () => transactionStatus === 'unapproved' && showConfTxPage({id: transActionId}), style: {}, }, [ -- cgit v1.2.3 From 17b5afb8deb50bf117a888ab24856661f67d3547 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 30 Aug 2017 08:03:00 -0230 Subject: Create tx-list-item component. --- ui/app/components/tx-list-item.js | 92 +++++++++++++++++++++++++++++++++++++++ ui/app/components/tx-list.js | 89 +++++++------------------------------ 2 files changed, 107 insertions(+), 74 deletions(-) create mode 100644 ui/app/components/tx-list-item.js (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js new file mode 100644 index 000000000..85699ceeb --- /dev/null +++ b/ui/app/components/tx-list-item.js @@ -0,0 +1,92 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const Identicon = require('./identicon') + +module.exports = TxListItem + +inherits(TxListItem, Component) +function TxListItem () { + Component.call(this) +} + +TxListItem.prototype.getAddressText = function (address) { + return address + ? `${address.slice(0, 10)}...${address.slice(-4)}` + : 'Contract Published' +} + +TxListItem.prototype.render = function () { + const { + transactionStatus, + onClick, + transActionId, + dateString, + address, + transactionAmount, + className + } = this.props + + return h(`div${className || ''}`, { + key: transActionId, + onClick: () => onClick && onClick(transActionId), + }, [ + h(`div.flex-column.tx-list-item-wrapper`, {}, [ + + h('div.tx-list-date-wrapper', { + style: {}, + }, [ + h('span.tx-list-date', {}, [ + dateString, + ]), + ]), + + h('div.flex-row.tx-list-content-wrapper', { + style: {}, + }, [ + + h('div.tx-list-identicon-wrapper', { + style: {}, + }, [ + h(Identicon, { + address, + diameter: 28, + }), + ]), + + h('div.tx-list-account-and-status-wrapper', {}, [ + h('div.tx-list-account-wrapper', { + style: {}, + }, [ + h('span.tx-list-account', {}, [ + this.getAddressText(address), + ]), + ]), + + h('div.tx-list-status-wrapper', { + style: {}, + }, [ + h('span.tx-list-status', {}, [ + transactionStatus, + ]), + ]), + ]), + + h('div.flex-column.tx-list-details-wrapper', { + style: {}, + }, [ + + h('span.tx-list-value', {}, [ + transactionAmount, + ]), + + h('span.tx-list-fiat-value', {}, [ + '+ $300 USD', + ]), + + ]), + ]), + ]) // holding on icon from design + ]) +} + diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 6cbd123f8..654b95416 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -3,7 +3,7 @@ const connect = require('react-redux').connect const h = require('react-hyperscript') const inherits = require('util').inherits const selectors = require('../selectors') -const Identicon = require('./identicon') +const TxListItem = require('./tx-list-item') const { formatBalance, formatDate } = require('../util') const { showConfTxPage } = require('../actions') @@ -53,16 +53,6 @@ TxList.prototype.render = function () { ]) } -TxList.prototype.getAddressText = function (transaction) { - const { - txParams: { to }, - } = transaction - - return to - ? `${to.slice(0, 10)}...${to.slice(-4)}` - : 'Contract Published' -} - TxList.prototype.renderTranstions = function () { const { txsToRender } = this.props @@ -92,70 +82,21 @@ TxList.prototype.renderTransactionListItem = function (transaction) { } = props const { showConfTxPage } = this.props - return h('div.tx-list-item', { - key: transaction.id, - }, [ - h('div.flex-column.tx-list-item__wrapper', { - onClick: () => transactionStatus === 'unapproved' && showConfTxPage({id: transActionId}), - style: {}, - }, [ - - h('div.tx-list-date-wrapper', { - style: {}, - }, [ - h('span.tx-list-date', {}, [ - dateString, - ]), - ]), - - h('div.flex-row.tx-list-content-wrapper', { - style: {}, - }, [ - - h('div.tx-list-identicon-wrapper', { - style: {}, - }, [ - h(Identicon, { - address, - diameter: 28, - }), - ]), - - h('div.tx-list-account-and-status-wrapper', {}, [ - h('div.tx-list-account-wrapper', { - style: {}, - }, [ - h('span.tx-list-account', {}, [ - this.getAddressText(transaction), - ]), - ]), - - h('div.tx-list-status-wrapper', { - style: {}, - }, [ - h('span.tx-list-status', {}, [ - transactionStatus, - ]), - ]), - ]), - - h('div.flex-column.tx-list-details-wrapper', { - style: {}, - }, [ - - h('span.tx-list-value', {}, [ - transactionAmount, - ]), - - h('span.tx-list-fiat-value', {}, [ - '+ $300 USD', - ]), - - ]), + if (!address) return null + + const opts = { + transactionStatus, + transActionId, + dateString, + address, + transactionAmount, + } - ]), - ]), + if (transactionStatus === 'unapproved') { + opts.onClick = () => showConfTxPage({id: transActionId}) + opts.className = '.tx-list-pending-item-container' + } - ]) + return h(TxListItem, opts) } -- cgit v1.2.3 From eabbfb83197ce948f59e0762a30d1d30266ad11c Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 7 Sep 2017 13:48:13 -0230 Subject: Link user from transaction list to etherscan if they have a transaction hash. --- ui/app/components/tx-list-item.js | 4 ++-- ui/app/components/tx-list.js | 27 ++++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 85699ceeb..62127b153 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -1,6 +1,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits +const prefixForNetwork = require('../../lib/etherscan-prefix-for-network') const Identicon = require('./identicon') module.exports = TxListItem @@ -24,7 +25,7 @@ TxListItem.prototype.render = function () { dateString, address, transactionAmount, - className + className, } = this.props return h(`div${className || ''}`, { @@ -89,4 +90,3 @@ TxListItem.prototype.render = function () { ]) // holding on icon from design ]) } - diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 654b95416..6a0849daf 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -2,6 +2,7 @@ const Component = require('react').Component const connect = require('react-redux').connect const h = require('react-hyperscript') const inherits = require('util').inherits +const prefixForNetwork = require('../../lib/etherscan-prefix-for-network') const selectors = require('../selectors') const TxListItem = require('./tx-list-item') const { formatBalance, formatDate } = require('../util') @@ -71,6 +72,8 @@ TxList.prototype.renderTransactionListItem = function (transaction) { transactionStatus: transaction.status, transactionAmount: formatBalance(transaction.txParams.value, 6), transActionId: transaction.id, + transactionHash: transaction.hash, + transactionNetworkId: transaction.metamaskNetworkId, } const { @@ -79,6 +82,8 @@ TxList.prototype.renderTransactionListItem = function (transaction) { transactionAmount, dateString, transActionId, + transactionHash, + transactionNetworkId, } = props const { showConfTxPage } = this.props @@ -90,13 +95,33 @@ TxList.prototype.renderTransactionListItem = function (transaction) { dateString, address, transactionAmount, + transactionHash, + className: '.tx-list-clickable', } if (transactionStatus === 'unapproved') { opts.onClick = () => showConfTxPage({id: transActionId}) - opts.className = '.tx-list-pending-item-container' + opts.className += '.tx-list-pending-item-container' + } + else if (transactionHash) { + opts.onClick = () => this.view(transactionHash, transactionNetworkId) } return h(TxListItem, opts) } +TxList.prototype.view = function (txHash, network) { + const url = etherscanLinkFor(txHash, network) + if (url) { + navigateTo(url) + } +} + +function navigateTo (url) { + global.platform.openWindow({ url }) +} + +function etherscanLinkFor (txHash, network) { + const prefix = prefixForNetwork(network) + return `https://${prefix}etherscan.io/tx/${txHash}` +} -- cgit v1.2.3 From 7fb1c6836da9cac50e29ff861c61b782fac365e6 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 7 Sep 2017 14:28:24 -0230 Subject: Modify status copy for status === 'unapproved' --- ui/app/components/tx-list.js | 1 + 1 file changed, 1 insertion(+) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 6a0849daf..724e86c21 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -102,6 +102,7 @@ TxList.prototype.renderTransactionListItem = function (transaction) { if (transactionStatus === 'unapproved') { opts.onClick = () => showConfTxPage({id: transActionId}) opts.className += '.tx-list-pending-item-container' + opt.transactionStatus = 'Not Started' } else if (transactionHash) { opts.onClick = () => this.view(transactionHash, transactionNetworkId) -- cgit v1.2.3 From 61b965fe14ccc44332d4e3a90ce531142da65a71 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 6 Sep 2017 07:13:32 -0230 Subject: Touch up style of account-details-modal. --- ui/app/components/modals/modal.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index d266fe790..85bed66e1 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -54,11 +54,13 @@ const MODALS = { width: '95%', top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh', boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', + borderRadius: '4px', }, laptopModalStyle: { width: '360px', top: 'calc(33% + 45px)', boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', + borderRadius: '4px', }, }, -- cgit v1.2.3 From 1d5a725ffbcd0fe3123d3bbb5889abce99cbaabe Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 6 Sep 2017 10:09:58 -0230 Subject: Close button in account-details-modal working. --- ui/app/components/modals/account-details-modal.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/account-details-modal.js b/ui/app/components/modals/account-details-modal.js index fb0e70397..838000fed 100644 --- a/ui/app/components/modals/account-details-modal.js +++ b/ui/app/components/modals/account-details-modal.js @@ -57,7 +57,9 @@ AccountDetailsModal.prototype.render = function () { ]), - h('div.account-details-modal-close', {}), + h('div.account-details-modal-close', { + onClick: this.props.hideModal, + }), h(QrView, { Qr: { -- cgit v1.2.3 From c4eb2fb3ea1c1f0753a6bed736503528f4e539cf Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 6 Sep 2017 10:54:27 -0230 Subject: Account-detail address is a readonly input. --- ui/app/components/qr-code.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/qr-code.js b/ui/app/components/qr-code.js index 8d6b43b6c..8e4d01c00 100644 --- a/ui/app/components/qr-code.js +++ b/ui/app/components/qr-code.js @@ -47,11 +47,13 @@ QrCodeView.prototype.render = function () { }, }), h('.div.ellip-address-wrapper', [ - h('span.qr-ellip-address', { + h('input.qr-ellip-address', { style: { width: '247px', }, - }, Qr.data), + value: Qr.data, + readonly: 'readonly', + }), // h(CopyButton, { // value: Qr.data, // }), -- cgit v1.2.3 From a0ca3fab774307e806fc881f1ce2bc6fc3a789ce Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 7 Sep 2017 14:15:21 -0230 Subject: Modify readonly value in for input in qr-code. --- ui/app/components/qr-code.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/qr-code.js b/ui/app/components/qr-code.js index 8e4d01c00..4257c1a15 100644 --- a/ui/app/components/qr-code.js +++ b/ui/app/components/qr-code.js @@ -52,7 +52,7 @@ QrCodeView.prototype.render = function () { width: '247px', }, value: Qr.data, - readonly: 'readonly', + readonly: true, }), // h(CopyButton, { // value: Qr.data, -- cgit v1.2.3 From 687d2f755d4fe9129d785603e5332c8af71a3481 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Thu, 7 Sep 2017 11:25:31 -0700 Subject: Fix css merge conflicts --- ui/app/components/tx-list.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 724e86c21..5066ab387 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -96,7 +96,7 @@ TxList.prototype.renderTransactionListItem = function (transaction) { address, transactionAmount, transactionHash, - className: '.tx-list-clickable', + className: '.tx-list-item.tx-list-clickable', } if (transactionStatus === 'unapproved') { -- cgit v1.2.3 From ca69fa5d910351e1c813a431df9603b34cb7a901 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Thu, 7 Sep 2017 11:38:21 -0700 Subject: Re-enable Contract tx list item --- ui/app/components/tx-list.js | 25 +++++++------------------ ui/app/components/tx-view.js | 2 +- 2 files changed, 8 insertions(+), 19 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 5066ab387..26782900c 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -34,19 +34,10 @@ TxList.prototype.render = function () { return h('div.flex-column.tx-list-container', {}, [ - h('div.flex-row.tx-list-header-wrapper', { - style: {}, - }, [ - - h('div.flex-row.tx-list-header', { - }, [ - - h('div', { - style: {}, - }, 'transactions'), - + h('div.flex-row.tx-list-header-wrapper', [ + h('div.flex-row.tx-list-header', [ + h('div', 'transactions'), ]), - ]), this.renderTranstions(), @@ -61,7 +52,7 @@ TxList.prototype.renderTranstions = function () { ? txsToRender.map((transaction) => { return this.renderTransactionListItem(transaction) }) - : h('div.tx-list-item.tx-list-item--empty', [ 'No Transactions' ]) + : [h('div.tx-list-item.tx-list-item--empty', [ 'No Transactions' ])] } // TODO: Consider moving TxListItem into a separate component @@ -87,9 +78,8 @@ TxList.prototype.renderTransactionListItem = function (transaction) { } = props const { showConfTxPage } = this.props - if (!address) return null - const opts = { + key: transactionHash, transactionStatus, transActionId, dateString, @@ -102,9 +92,8 @@ TxList.prototype.renderTransactionListItem = function (transaction) { if (transactionStatus === 'unapproved') { opts.onClick = () => showConfTxPage({id: transActionId}) opts.className += '.tx-list-pending-item-container' - opt.transactionStatus = 'Not Started' - } - else if (transactionHash) { + opts.transactionStatus = 'Not Started' + } else if (transactionHash) { opts.onClick = () => this.view(transactionHash, transactionNetworkId) } diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index f5ac6e2dc..59f55d485 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -142,7 +142,7 @@ TxView.prototype.render = function () { this.renderHeroBalance(), - h(TxList, {}), + h(TxList), ]) } -- cgit v1.2.3 From ab4005cab85755d9f260b9e304ff2eeda81a10a5 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 6 Sep 2017 14:38:05 -0230 Subject: Tweak styles in new-account-modal. --- ui/app/components/modals/new-account-modal.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/new-account-modal.js b/ui/app/components/modals/new-account-modal.js index 3caa515cd..80c70c47f 100644 --- a/ui/app/components/modals/new-account-modal.js +++ b/ui/app/components/modals/new-account-modal.js @@ -49,11 +49,11 @@ NewAccountModal.prototype.render = function () { }, []), ]), - h('div.new-account-modal-content', {}, [ + h('div.new-account-modal-content.after-input', {}, [ 'or', ]), - h('div.new-account-modal-content.import', {}, [ + h('div.new-account-modal-content.after-input', {}, [ 'Import an account', ]), -- cgit v1.2.3 From 5a8433b6cef88996b65108c7faecbaf819fd3b64 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 6 Sep 2017 14:40:27 -0230 Subject: New account modal top right close button working. --- ui/app/components/modals/new-account-modal.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/new-account-modal.js b/ui/app/components/modals/new-account-modal.js index 80c70c47f..8d67762ac 100644 --- a/ui/app/components/modals/new-account-modal.js +++ b/ui/app/components/modals/new-account-modal.js @@ -37,7 +37,9 @@ NewAccountModal.prototype.render = function () { 'New Account', ]), - h('div.modal-close-x', {}), + h('div.modal-close-x', { + onClick: this.props.hideModal, + }), h('div.new-account-modal-content', {}, [ 'Account Name', -- cgit v1.2.3 From 663cb758b345d7138b9e9c68489e1859dbfaa78e Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Mon, 11 Sep 2017 00:45:06 -0700 Subject: Style send token screen --- .../dropdowns/components/account-dropdowns.js | 11 +++---- ui/app/components/dropdowns/components/dropdown.js | 6 +++- ui/app/components/input-number.js | 1 + ui/app/components/modals/account-details-modal.js | 34 ++++++++-------------- ui/app/components/modals/modal.js | 5 ++++ 5 files changed, 27 insertions(+), 30 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index 1961a61b5..48354ff94 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -232,6 +232,8 @@ class AccountDropdowns extends Component { const dropdownMenuItemStyle = { fontFamily: 'DIN OT', fontSize: 16, + lineHeight: '24px', + padding: '8px', } return h( @@ -347,15 +349,9 @@ class AccountDropdowns extends Component { [ enableAccountsSelector && h( 'i.fa.fa-angle-down', - // 'div.cursor-pointer.color-orange.accounts-selector', { style: { - // fontSize: '135%', - // background: 'url(images/switch_acc.svg) white center center no-repeat', - // height: '25px', - // width: '25px', - // transform: 'scale(0.75)', - // marginRight: '3px', + cursor: 'pointer', }, onClick: (event) => { event.stopPropagation() @@ -372,6 +368,7 @@ class AccountDropdowns extends Component { { style: { fontSize: '135%', + cursor: 'pointer', }, onClick: (event) => { event.stopPropagation() diff --git a/ui/app/components/dropdowns/components/dropdown.js b/ui/app/components/dropdowns/components/dropdown.js index c4b2c2550..991c89cb8 100644 --- a/ui/app/components/dropdowns/components/dropdown.js +++ b/ui/app/components/dropdowns/components/dropdown.js @@ -40,7 +40,11 @@ class Dropdown extends Component { h( 'style', ` - li.dropdown-menu-item:hover { color:rgb(225, 225, 225); } + li.dropdown-menu-item:hover { + color:rgb(225, 225, 225); + background-color: rgba(255, 255, 255, 0.05); + border-radius: 4px; + } li.dropdown-menu-item { color: rgb(185, 185, 185); } ` ), diff --git a/ui/app/components/input-number.js b/ui/app/components/input-number.js index e3bbaf380..63e841288 100644 --- a/ui/app/components/input-number.js +++ b/ui/app/components/input-number.js @@ -49,6 +49,7 @@ InputNumber.prototype.render = function () { onClick: () => this.setValue(value + step), }), h('i.fa.fa-angle-down', { + style: { cursor: 'pointer' }, onClick: () => this.setValue(value - step), }), ]), diff --git a/ui/app/components/modals/account-details-modal.js b/ui/app/components/modals/account-details-modal.js index 838000fed..ec7e4b500 100644 --- a/ui/app/components/modals/account-details-modal.js +++ b/ui/app/components/modals/account-details-modal.js @@ -39,21 +39,17 @@ module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountDetailsModa AccountDetailsModal.prototype.render = function () { const { selectedIdentity, network } = this.props - return h('div', {}, [ - h('div.account-details-modal-wrapper', { - }, [ + return h('div', { style: { borderRadius: '4px' }}, [ + h('div.account-details-modal-wrapper', [ - h('div', {}, [ + h('div', [ // Needs a border; requires changes to svg - h( - Identicon, - { - address: selectedIdentity.address, - diameter: 64, - style: {}, - }, - ), + h(Identicon, { + address: selectedIdentity.address, + diameter: 64, + style: {}, + }), ]), @@ -66,26 +62,20 @@ AccountDetailsModal.prototype.render = function () { message: this.props.selectedIdentity.name, data: this.props.selectedIdentity.address, }, - }, []), + }), // divider - h('div.account-details-modal-divider', { - style: {}, - }, []), + h('div.account-details-modal-divider'), h('button.btn-clear', { onClick: () => { const url = genAccountLink(selectedIdentity.address, network) global.platform.openWindow({ url }) }, - }, [ - 'View account on Etherscan', - ]), + }, [ 'View account on Etherscan' ]), // Holding on redesign for Export Private Key functionality - h('button.btn-clear', {}, [ - 'Export private key', - ]), + h('button.btn-clear', [ 'Export private key' ]), ]), ]) diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 85bed66e1..477dcbe86 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -62,6 +62,9 @@ const MODALS = { boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', borderRadius: '4px', }, + contentStyle: { + borderRadius: '4px', + } }, NEW_ACCOUNT: { @@ -117,6 +120,7 @@ Modal.prototype.render = function () { const children = modal.contents const modalStyle = modal[isMobileView() ? 'mobileModalStyle' : 'laptopModalStyle'] + const contentStyle = modal.contentStyle || {}; return h(FadeModal, { @@ -127,6 +131,7 @@ Modal.prototype.render = function () { this.modalRef = ref }, modalStyle, + contentStyle, backdropStyle: BACKDROPSTYLE, }, children, -- cgit v1.2.3 From 6a3c59e409cf4467ca2c59a0303f2df85ffde73f Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 6 Sep 2017 20:07:48 -0230 Subject: Highlighted circle icons for the network menu. --- .../dropdowns/components/network-dropdown-icon.js | 32 ++++++++++++++++++++ ui/app/components/dropdowns/network-dropdown.js | 35 ++++++++++++++++++---- ui/app/components/network.js | 21 ++++++++++--- 3 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 ui/app/components/dropdowns/components/network-dropdown-icon.js (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/components/network-dropdown-icon.js b/ui/app/components/dropdowns/components/network-dropdown-icon.js new file mode 100644 index 000000000..01cb95215 --- /dev/null +++ b/ui/app/components/dropdowns/components/network-dropdown-icon.js @@ -0,0 +1,32 @@ +const inherits = require('util').inherits +const Component = require('react').Component +const h = require('react-hyperscript') + + +inherits(NetworkDropdownIcon, Component) +module.exports = NetworkDropdownIcon + +function NetworkDropdownIcon () { + Component.call(this) +} + +NetworkDropdownIcon.prototype.render = function () { + const { + backgroundColor, + isSelected, + innerBorder, + nonSelectBackgroundColor + } = this.props + + return h('.menu-icon-circle-select', { + style: { + border: isSelected && '1px solid white', + background: isSelected ? 'rgba(100, 100, 100, 0.4)' : 'none', + }, + }, h('.menu-icon-circle', { + style: { + background: isSelected ? backgroundColor : nonSelectBackgroundColor, + border: innerBorder ? innerBorder : 'none', + }, + })) +} diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js index fa0bb899e..f1c6f8221 100644 --- a/ui/app/components/dropdowns/network-dropdown.js +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -5,6 +5,7 @@ const connect = require('react-redux').connect const actions = require('../../actions') const Dropdown = require('./components/dropdown').Dropdown const DropdownMenuItem = require('./components/dropdown').DropdownMenuItem +const NetworkDropdownIcon = require('./components/network-dropdown-icon') function mapStateToProps (state) { return { @@ -94,7 +95,11 @@ NetworkDropdown.prototype.render = function () { }, [ providerType === 'mainnet' ? h('.network-check', '✓') : h('.network-check__transparent', '✓'), - h('.menu-icon.diamond'), + h(NetworkDropdownIcon, { + backgroundColor: '#038789', // $blue-lagoon + nonSelectBackgroundColor: '#15afb2', + isSelected: providerType === 'mainnet', + }), h('span.network-name-item', { style: { color: providerType === 'mainnet' ? '#ffffff' : '#9b9b9b', @@ -113,7 +118,11 @@ NetworkDropdown.prototype.render = function () { }, [ providerType === 'ropsten' ? h('.network-check', '✓') : h('.network-check__transparent', '✓'), - h('.menu-icon.red-dot'), + h(NetworkDropdownIcon, { + backgroundColor: '#e91550', // $crimson + nonSelectBackgroundColor: '#ec2c50', + isSelected: providerType === 'ropsten', + }), h('span.network-name-item', { style: { color: providerType === 'ropsten' ? '#ffffff' : '#9b9b9b', @@ -132,7 +141,11 @@ NetworkDropdown.prototype.render = function () { }, [ providerType === 'kovan' ? h('.network-check', '✓') : h('.network-check__transparent', '✓'), - h('.menu-icon.hollow-diamond'), + h(NetworkDropdownIcon, { + backgroundColor: '#690496', // $purple + nonSelectBackgroundColor: '#b039f3', + isSelected: providerType === 'kovan', + }), h('span.network-name-item', { style: { color: providerType === 'kovan' ? '#ffffff' : '#9b9b9b', @@ -151,7 +164,11 @@ NetworkDropdown.prototype.render = function () { }, [ providerType === 'rinkeby' ? h('.network-check', '✓') : h('.network-check__transparent', '✓'), - h('.menu-icon.golden-square'), + h(NetworkDropdownIcon, { + backgroundColor: '#ebb33f', // $tulip-tree + nonSelectBackgroundColor: '#ecb23e', + isSelected: providerType === 'rinkeby', + }), h('span.network-name-item', { style: { color: providerType === 'rinkeby' ? '#ffffff' : '#9b9b9b', @@ -170,7 +187,10 @@ NetworkDropdown.prototype.render = function () { }, [ activeNetwork === 'http://localhost:8545' ? h('.network-check', '✓') : h('.network-check__transparent', '✓'), - h('i.fa.fa-question-circle.fa-lg.menu-icon'), + h(NetworkDropdownIcon, { + isSelected: activeNetwork === 'http://localhost:8545', + innerBorder: '1px solid #9b9b9b', + }), h('span.network-name-item', { style: { color: activeNetwork === 'http://localhost:8545' ? '#ffffff' : '#9b9b9b', @@ -191,7 +211,10 @@ NetworkDropdown.prototype.render = function () { }, [ activeNetwork === 'custom' ? h('.check', '✓') : h('.network-check__transparent', '✓'), - h('i.fa.fa-question-circle.fa-lg.menu-icon'), + h(NetworkDropdownIcon, { + isSelected: activeNetwork === 'custom', + innerBorder: '1px solid #9b9b9b', + }), h('span.network-name-item', { style: { color: activeNetwork === 'custom' ? '#ffffff' : '#9b9b9b', diff --git a/ui/app/components/network.js b/ui/app/components/network.js index ba1d0ea11..9133c78e3 100644 --- a/ui/app/components/network.js +++ b/ui/app/components/network.js @@ -1,6 +1,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits +const NetworkDropdownIcon = require('./dropdowns/components/network-dropdown-icon') module.exports = Network @@ -68,7 +69,10 @@ Network.prototype.render = function () { switch (iconName) { case 'ethereum-network': return h('.network-indicator', [ - h('.menu-icon.diamond'), + h(NetworkDropdownIcon, { + backgroundColor: '#038789', // $blue-lagoon + nonSelectBackgroundColor: '#15afb2' + }), h('.network-name', { style: { color: '#039396', @@ -77,7 +81,10 @@ Network.prototype.render = function () { ]) case 'ropsten-test-network': return h('.network-indicator', [ - h('.menu-icon.red-dot'), + h(NetworkDropdownIcon, { + backgroundColor: '#e91550', // $crimson + nonSelectBackgroundColor: '#ec2c50', + }), h('.network-name', { style: { color: '#ff6666', @@ -86,7 +93,10 @@ Network.prototype.render = function () { ]) case 'kovan-test-network': return h('.network-indicator', [ - h('.menu-icon.hollow-diamond'), + h(NetworkDropdownIcon, { + backgroundColor: '#690496', // $purple + nonSelectBackgroundColor: '#b039f3', + }), h('.network-name', { style: { color: '#690496', @@ -95,7 +105,10 @@ Network.prototype.render = function () { ]) case 'rinkeby-test-network': return h('.network-indicator', [ - h('.menu-icon.golden-square'), + h(NetworkDropdownIcon, { + backgroundColor: '#ebb33f', // $tulip-tree + nonSelectBackgroundColor: '#ecb23e', + }), h('.network-name', { style: { color: '#e7a218', -- cgit v1.2.3 From 99047e3ef4650ee982d6c7ed606cdaacd4965d64 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 6 Sep 2017 20:26:54 -0230 Subject: Adds title, divider and descriptive text to network dropdown. --- ui/app/components/dropdowns/network-dropdown.js | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js index f1c6f8221..f79c8b29a 100644 --- a/ui/app/components/dropdowns/network-dropdown.js +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -85,6 +85,17 @@ NetworkDropdown.prototype.render = function () { }, }, [ + h('div.network-dropdown-header', {}, [ + h('div.network-dropdown-title', {}, 'Networks'), + + h('div.network-dropdown-divider'), + + h('div.network-dropdown-content', + {}, + 'The default network for Ether transactions is Main Net.' + ), + ]), + h( DropdownMenuItem, { -- cgit v1.2.3 From 6beb1b33bb20a5bb2bf38b030a5838cf9edff413 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 6 Sep 2017 20:27:29 -0230 Subject: Replace checkmark with font-awesome equivalent. --- ui/app/components/dropdowns/network-dropdown.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js index f79c8b29a..1b6bd2385 100644 --- a/ui/app/components/dropdowns/network-dropdown.js +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -105,7 +105,7 @@ NetworkDropdown.prototype.render = function () { style: dropdownMenuItemStyle, }, [ - providerType === 'mainnet' ? h('.network-check', '✓') : h('.network-check__transparent', '✓'), + providerType === 'mainnet' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'), h(NetworkDropdownIcon, { backgroundColor: '#038789', // $blue-lagoon nonSelectBackgroundColor: '#15afb2', @@ -128,7 +128,7 @@ NetworkDropdown.prototype.render = function () { style: dropdownMenuItemStyle, }, [ - providerType === 'ropsten' ? h('.network-check', '✓') : h('.network-check__transparent', '✓'), + providerType === 'ropsten' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'), h(NetworkDropdownIcon, { backgroundColor: '#e91550', // $crimson nonSelectBackgroundColor: '#ec2c50', @@ -151,7 +151,7 @@ NetworkDropdown.prototype.render = function () { style: dropdownMenuItemStyle, }, [ - providerType === 'kovan' ? h('.network-check', '✓') : h('.network-check__transparent', '✓'), + providerType === 'kovan' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'), h(NetworkDropdownIcon, { backgroundColor: '#690496', // $purple nonSelectBackgroundColor: '#b039f3', @@ -174,7 +174,7 @@ NetworkDropdown.prototype.render = function () { style: dropdownMenuItemStyle, }, [ - providerType === 'rinkeby' ? h('.network-check', '✓') : h('.network-check__transparent', '✓'), + providerType === 'rinkeby' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'), h(NetworkDropdownIcon, { backgroundColor: '#ebb33f', // $tulip-tree nonSelectBackgroundColor: '#ecb23e', @@ -197,7 +197,7 @@ NetworkDropdown.prototype.render = function () { style: dropdownMenuItemStyle, }, [ - activeNetwork === 'http://localhost:8545' ? h('.network-check', '✓') : h('.network-check__transparent', '✓'), + activeNetwork === 'http://localhost:8545' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'), h(NetworkDropdownIcon, { isSelected: activeNetwork === 'http://localhost:8545', innerBorder: '1px solid #9b9b9b', @@ -221,7 +221,7 @@ NetworkDropdown.prototype.render = function () { style: dropdownMenuItemStyle, }, [ - activeNetwork === 'custom' ? h('.check', '✓') : h('.network-check__transparent', '✓'), + activeNetwork === 'custom' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'), h(NetworkDropdownIcon, { isSelected: activeNetwork === 'custom', innerBorder: '1px solid #9b9b9b', -- cgit v1.2.3 From 8342c20b58a0b90806a592992b6212ee6fa6f0ad Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 7 Sep 2017 21:17:07 -0230 Subject: Cleaner css for circle icon. --- .../dropdowns/components/network-dropdown-icon.js | 22 +++++++++------------- ui/app/components/dropdowns/network-dropdown.js | 4 ---- 2 files changed, 9 insertions(+), 17 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/components/network-dropdown-icon.js b/ui/app/components/dropdowns/components/network-dropdown-icon.js index 01cb95215..7e94e0af5 100644 --- a/ui/app/components/dropdowns/components/network-dropdown-icon.js +++ b/ui/app/components/dropdowns/components/network-dropdown-icon.js @@ -14,19 +14,15 @@ NetworkDropdownIcon.prototype.render = function () { const { backgroundColor, isSelected, - innerBorder, - nonSelectBackgroundColor + innerBorder = 'none', } = this.props - return h('.menu-icon-circle-select', { - style: { - border: isSelected && '1px solid white', - background: isSelected ? 'rgba(100, 100, 100, 0.4)' : 'none', - }, - }, h('.menu-icon-circle', { - style: { - background: isSelected ? backgroundColor : nonSelectBackgroundColor, - border: innerBorder ? innerBorder : 'none', - }, - })) + return h(`.menu-icon-circle${isSelected ? '--active' : ''}`, {}, + h('div', { + style: { + background: backgroundColor, + border: innerBorder, + }, + }) + ) } diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js index 1b6bd2385..4c578fbeb 100644 --- a/ui/app/components/dropdowns/network-dropdown.js +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -108,7 +108,6 @@ NetworkDropdown.prototype.render = function () { providerType === 'mainnet' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'), h(NetworkDropdownIcon, { backgroundColor: '#038789', // $blue-lagoon - nonSelectBackgroundColor: '#15afb2', isSelected: providerType === 'mainnet', }), h('span.network-name-item', { @@ -131,7 +130,6 @@ NetworkDropdown.prototype.render = function () { providerType === 'ropsten' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'), h(NetworkDropdownIcon, { backgroundColor: '#e91550', // $crimson - nonSelectBackgroundColor: '#ec2c50', isSelected: providerType === 'ropsten', }), h('span.network-name-item', { @@ -154,7 +152,6 @@ NetworkDropdown.prototype.render = function () { providerType === 'kovan' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'), h(NetworkDropdownIcon, { backgroundColor: '#690496', // $purple - nonSelectBackgroundColor: '#b039f3', isSelected: providerType === 'kovan', }), h('span.network-name-item', { @@ -177,7 +174,6 @@ NetworkDropdown.prototype.render = function () { providerType === 'rinkeby' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'), h(NetworkDropdownIcon, { backgroundColor: '#ebb33f', // $tulip-tree - nonSelectBackgroundColor: '#ecb23e', isSelected: providerType === 'rinkeby', }), h('span.network-name-item', { -- cgit v1.2.3 From 062e67bff83fd79647231be6e2448d35b5f312f9 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Mon, 11 Sep 2017 22:14:09 -0700 Subject: Add buttons; handle back; add yarn.lock --- ui/app/components/send-token/index.js | 54 ++++++++++++++++++++----------- ui/app/components/send/currency-toggle.js | 19 ++++++++--- ui/app/components/tx-list.js | 4 +-- 3 files changed, 51 insertions(+), 26 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index a49e559dc..985116409 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -23,16 +23,16 @@ function mapStateToProps (state) { const addressBook = state.metamask.addressBook const conversionRate = state.metamask.conversionRate const currentBlockGasLimit = state.metamask.currentBlockGasLimit - // const accounts = state.metamask.accounts + const accounts = state.metamask.accounts // const network = state.metamask.network const selectedTokenAddress = state.metamask.selectedTokenAddress - // const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] + const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] // const checksumAddress = selectedAddress && ethUtil.toChecksumAddress(selectedAddress) // const identity = identities[selectedAddress] return { // sidebarOpen, - // selectedAddress, + selectedAddress, // checksumAddress, selectedTokenAddress, identities, @@ -48,6 +48,7 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { + backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)), // showSidebar: () => { dispatch(actions.showSidebar()) }, // hideSidebar: () => { dispatch(actions.hideSidebar()) }, // showModal: (payload) => { dispatch(actions.showModal(payload)) }, @@ -121,6 +122,7 @@ SendTokenScreen.prototype.renderAmountInput = function () { h('span', ['Amount']), h(CurrencyToggle, { selectedCurrency, + currencies: [ symbol, 'USD' ], onClick: currency => this.setState({ selectedCurrency: currency }), }), ]), @@ -178,7 +180,7 @@ SendTokenScreen.prototype.renderGasInput = function () { } SendTokenScreen.prototype.renderMemoInput = function () { - return h('div.send-screen-input-wrapper', {}, [ + return h('div.send-screen-input-wrapper', [ h('div', {}, ['Transaction memo (optional)']), h( 'input.large-input.send-screen-input', @@ -187,6 +189,19 @@ SendTokenScreen.prototype.renderMemoInput = function () { ]) } +SendTokenScreen.prototype.renderButtons = function () { + const { selectedAddress, backToAccountDetail } = this.props + + return h('div.send-token__button-group', [ + h('button.send-token__button-next.btn-secondary', { + + }, ['Next']), + h('button.send-token__button-cancel.btn-tertiary', { + onClick: () => backToAccountDetail(selectedAddress), + }, ['Cancel']), + ]) +} + SendTokenScreen.prototype.render = function () { const { selectedTokenAddress, @@ -194,20 +209,23 @@ SendTokenScreen.prototype.render = function () { } = this.props return h('div.send-token', [ - h(Identicon, { - diameter: 75, - address: selectedTokenAddress, - }), - h('div.send-token__title', ['Send Tokens']), - h('div.send-token__description', ['Send Tokens to anyone with an Ethereum account']), - h('div.send-token__balance-text', ['Your Token Balance is:']), - h('div.send-token__token-balance', [ - h(TokenBalance, { token: selectedToken, balanceOnly: true }), + h('div.send-token__content', [ + h(Identicon, { + diameter: 75, + address: selectedTokenAddress, + }), + h('div.send-token__title', ['Send Tokens']), + h('div.send-token__description', ['Send Tokens to anyone with an Ethereum account']), + h('div.send-token__balance-text', ['Your Token Balance is:']), + h('div.send-token__token-balance', [ + h(TokenBalance, { token: selectedToken, balanceOnly: true }), + ]), + h('div.send-token__token-symbol', [selectedToken.symbol]), + this.renderToAddressInput(), + this.renderAmountInput(), + this.renderGasInput(), + this.renderMemoInput(), ]), - h('div.send-token__token-symbol', [selectedToken.symbol]), - this.renderToAddressInput(), - this.renderAmountInput(), - this.renderGasInput(), - this.renderMemoInput(), + this.renderButtons(), ]) } diff --git a/ui/app/components/send/currency-toggle.js b/ui/app/components/send/currency-toggle.js index d3c2222a4..adaade301 100644 --- a/ui/app/components/send/currency-toggle.js +++ b/ui/app/components/send/currency-toggle.js @@ -1,6 +1,8 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits +const classnames = require('classnames') + module.exports = CurrencyToggle inherits(CurrencyToggle, Component) @@ -8,18 +10,25 @@ function CurrencyToggle () { Component.call(this) } +const defaultCurrencies = [ 'ETH', 'USD' ] + CurrencyToggle.prototype.render = function () { const { onClick, currentCurrency } = this.props + const [currencyA, currencyB] = this.props.currencies || defaultCurrencies - return h('span', {}, [ + return h('span.currency-toggle', {}, [ h('span', { - className: currentCurrency === 'ETH' ? 'selected-currency' : 'unselected-currency', - onClick: () => onClick('ETH'), + className: classnames('currency-toggle__item', { + 'currency-toggle__item--selected': currencyA === currentCurrency, + }), + onClick: () => onClick(currencyA), }, ['ETH']), '<>', h('span', { - className: currentCurrency === 'USD' ? 'selected-currency' : 'unselected-currency', - onClick: () => onClick('USD'), + className: classnames('currency-toggle__item', { + 'currency-toggle__item--selected': currencyB === currentCurrency, + }), + onClick: () => onClick(currencyB), }, ['USD']), ]) // holding on icon from design } diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 26782900c..a7d11203d 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -49,9 +49,7 @@ TxList.prototype.renderTranstions = function () { const { txsToRender } = this.props return txsToRender.length - ? txsToRender.map((transaction) => { - return this.renderTransactionListItem(transaction) - }) + ? txsToRender.map((transaction) => this.renderTransactionListItem(transaction)) : [h('div.tx-list-item.tx-list-item--empty', [ 'No Transactions' ])] } -- cgit v1.2.3 From 1e83835ba8cce0fdf794092a8c55b6c68664204a Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Tue, 12 Sep 2017 02:49:05 -0230 Subject: [New-UI] Confirm Screen restyle and connect to state (#2042) * Adds utility for converting currencies (WIP) * Implements confirm screen * Style tweaks. * Confirm screen total ammount now uses real data. * Confirm screen total ammount now uses real data. * Replace content divider with sibling css. * Replace section divider with scss. --- ui/app/components/pending-tx.js | 336 +++++++++++++++++----------------------- 1 file changed, 139 insertions(+), 197 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index 5e5110d6c..31281faf2 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -1,23 +1,23 @@ const Component = require('react').Component +const { connect } = require('react-redux') const h = require('react-hyperscript') const inherits = require('util').inherits const actions = require('../actions') const clone = require('clone') +const FiatValue = require('./fiat-value') +const Identicon = require('./identicon') +const { setCurrentCurrency } = require('../actions') const ethUtil = require('ethereumjs-util') const BN = ethUtil.BN const hexToBn = require('../../../app/scripts/lib/hex-to-bn') const util = require('../util') +const { conversionUtil } = require('../conversion-util') const MIN_GAS_PRICE_GWEI_BN = new BN(1) const GWEI_FACTOR = new BN(1e9) const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR) - -// Faked, for Icon -const Identicon = require('./identicon') -const ARAGON = '960b236A07cf122663c4303350609A66A7B288C0' - // Next: create separate react components // roughly 5 components: // heroIcon @@ -25,23 +25,27 @@ const ARAGON = '960b236A07cf122663c4303350609A66A7B288C0' // divider // contentBox // actionButtons -const sectionDivider = h('div', { - style: { - height: '1px', - background: '#E7E7E7', - }, -}) - -const contentDivider = h('div', { - style: { - marginLeft: '16px', - marginRight: '16px', - height: '1px', - background: '#E7E7E7', - }, -}) - -module.exports = PendingTx + +module.exports = connect(mapStateToProps, mapDispatchToProps)(PendingTx) + +function mapStateToProps (state) { + const { + conversionRate, + identities, + } = state.metamask + + return { + conversionRate, + identities, + } +} + +function mapDispatchToProps (dispatch) { + return { + setCurrentCurrencyToUSD: () => dispatch(setCurrentCurrency('USD')) + } +} + inherits(PendingTx, Component) function PendingTx () { Component.call(this) @@ -52,9 +56,13 @@ function PendingTx () { } } +PendingTx.prototype.componentWillMount = function () { + this.props.setCurrentCurrencyToUSD() +} + PendingTx.prototype.render = function () { const props = this.props - const { blockGasLimit } = props + const { blockGasLimit, conversionRate, identities } = props const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} @@ -76,16 +84,48 @@ PendingTx.prototype.render = function () { const gasPriceBn = hexToBn(gasPrice) const txFeeBn = gasBn.mul(gasPriceBn) - const valueBn = hexToBn(txParams.value) - const maxCost = txFeeBn.add(valueBn) - const balanceBn = hexToBn(balance) - const insufficientBalance = balanceBn.lt(maxCost) + const amountBn = hexToBn(txParams.value) + + // TODO: insufficient balance should be handled on send screen + // const maxCost = txFeeBn.add(amountBn) + // const balanceBn = hexToBn(balance) + // const insufficientBalance = balanceBn.lt(maxCost) + + const fromName = identities[txParams.from].name; + const toName = identities[txParams.to].name; + + const endOfFromAddress = txParams.from.slice(txParams.from.length - 4) + const endOfToAddress = txParams.to.slice(txParams.to.length - 4) + + const gasFeeInUSD = conversionUtil(txFeeBn, { + fromFormat: 'BN', + fromCurrency: 'GWEI', + toCurrency: 'USD', + conversionRate, + }) + const gasFeeInETH = conversionUtil(txFeeBn, { + fromFormat: 'BN', + fromCurrency: 'GWEI', + toCurrency: 'ETH', + conversionRate, + }) + + const totalInUSD = conversionUtil(amountBn, { + fromFormat: 'BN', + toCurrency: 'USD', + conversionRate, + }) + const totalInETH = conversionUtil(amountBn, { + fromFormat: 'BN', + toCurrency: 'ETH', + conversionRate, + }) this.inputs = [] return ( - h('div.flex-column.flex-grow', { + h('div.flex-column.flex-grow.confirm-screen-container', { style: { // overflow: 'scroll', minWidth: '355px', // TODO: maxWidth TBD, use home.html @@ -93,86 +133,79 @@ PendingTx.prototype.render = function () { }, [ // Main Send token Card - h('div.send-screen.flex-column.flex-grow', { - style: { - marginLeft: '3.5%', - marginRight: '3.5%', - background: '#FFFFFF', // $background-white - boxShadow: '0 2px 4px 0 rgba(0,0,0,0.08)', - }, - }, [ - h('section.flex-center.flex-row', { - style: { - zIndex: 15, // $token-icon-z-index - marginTop: '-35px', - }, - }, [ - h(Identicon, { - address: ARAGON, - diameter: 76, - }), - ]), + h('div.confirm-screen-wrapper.flex-column.flex-grow', {}, [ - // - // Required Fields - // + h('h3.flex-center.confirm-screen-header', {}, [ - h('h3.flex-center', { - style: { - marginTop: '-18px', - fontSize: '16px', - }, - }, [ - 'Confirm Transaction', + h('button.confirm-screen-back-button', {}, 'BACK'), + + h('div.confirm-screen-title', {}, 'Confirm Transaction'), + ]), - h('h3.flex-center', { - style: { - textAlign: 'center', - fontSize: '12px', - }, - }, [ - 'You\'re sending to Recipient ...5924', + h('div.flex-row.flex-center.confirm-screen-identicons', {}, [ + + h('div.confirm-screen-account-wrapper', {}, [ + h( + Identicon, + { + address: txParams.from, + diameter: 64, + style: {}, + }, + ), + h('span.confirm-screen-account-name', {}, fromName), + h('span.confirm-screen-account-number', {}, endOfFromAddress), + + ]), + + h('i.fa.fa-arrow-right.fa-lg'), + + h('div.confirm-screen-account-wrapper', {}, [ + h( + Identicon, + { + address: txParams.to, + diameter: 64, + style: {}, + }, + ), + h('span.confirm-screen-account-name', {}, toName), + h('span.confirm-screen-account-number', {}, endOfToAddress), + ]) + ]), - h('h3.flex-center', { + h('h3.flex-center.confirm-screen-sending-to-message', { style: { textAlign: 'center', - fontSize: '36px', - marginTop: '8px', - }, + fontSize: '16px', + } }, [ - '0.24', + `You're sending to Recipient ...${endOfToAddress}` ]), - h('h3.flex-center', { - style: { - textAlign: 'center', - fontSize: '12px', - marginTop: '4px', - }, - }, [ - 'ANT', + h('h3.flex-center.confirm-screen-send-amount', {}, [`$${totalInUSD}`]), + + h('h3.flex-center.confirm-screen-send-amount-currency', {}, [ + 'USD', ]), - // error message - props.error && h('span.error.flex-center', props.error), + h('div.flex-center.confirm-memo-wrapper', {}, h( + 'h3.confirm-screen-send-memo', {}, txParams.memo || 'Fake memo' + )), - sectionDivider, + // TODO: put this error message in the right place + // props.error && h('span.error.flex-center', props.error), - h('section.flex-row.flex-center', { + h('section.flex-row.flex-center.confirm-screen-row', { }, [ h('div', { style: { width: '50%', }, }, [ - h('span', { - style: { - textAlign: 'left', - fontSize: '12px', - }, - }, [ + h('span.confirm-screen-label', {}, [ 'From', ]), ]), @@ -182,38 +215,21 @@ PendingTx.prototype.render = function () { width: '50%', }, }, [ - h('div', { - style: { - textAlign: 'left', - fontSize: '10px', - marginBottom: '-10px', - }, - }, 'Aragon Token'), + h('div.confirm-screen-row-info', {}, fromName), - h('div', { - style: { - textAlign: 'left', - fontSize: '8px', - }, - }, 'Your Balance 2.34 ANT'), + h('div.confirm-screen-row-detail', {}, `...${endOfFromAddress}`), ]), ]), - contentDivider, - h('section.flex-row.flex-center', { + h('section.flex-row.flex-center.confirm-screen-row', { }, [ h('div', { style: { width: '50%', }, }, [ - h('span', { - style: { - textAlign: 'left', - fontSize: '12px', - }, - }, [ + h('span.confirm-screen-label', {}, [ 'To', ]), ]), @@ -223,38 +239,21 @@ PendingTx.prototype.render = function () { width: '50%', }, }, [ - h('div', { - style: { - textAlign: 'left', - fontSize: '10px', - marginBottom: '-10px', - }, - }, 'Ethereum Address'), + h('div.confirm-screen-row-info', {}, toName), - h('div', { - style: { - textAlign: 'left', - fontSize: '8px', - }, - }, '...5924'), + h('div.confirm-screen-row-detail', {}, `...${endOfToAddress}`), ]), ]), - contentDivider, - h('section.flex-row.flex-center', { + h('section.flex-row.flex-center.confirm-screen-row', { }, [ h('div', { style: { width: '50%', }, }, [ - h('span', { - style: { - textAlign: 'left', - fontSize: '12px', - }, - }, [ + h('span.confirm-screen-label', {}, [ 'Gas Fee', ]), ]), @@ -264,49 +263,21 @@ PendingTx.prototype.render = function () { width: '50%', }, }, [ - h('div', { - style: { - textAlign: 'left', - fontSize: '10px', - marginBottom: '-10px', - }, - }, '$0.04 USD'), + h('div.confirm-screen-row-info', {}, `$${gasFeeInUSD} USD`), - h('div', { - style: { - textAlign: 'left', - fontSize: '8px', - }, - }, '0.001575 ETH'), + h('div.confirm-screen-row-detail', {}, `${gasFeeInETH} ETH`), ]), ]), - contentDivider, - h('section.flex-row.flex-center', { - style: { - backgroundColor: '#F6F6F6', // $wild-sand - borderRadius: '8px', - marginLeft: '10px', - marginRight: '10px', - paddingLeft: '6px', - paddingRight: '6px', - marginBottom: '10px', - }, - }, [ + h('section.flex-row.flex-center.confirm-screen-total-box ', {}, [ h('div', { style: { width: '50%', }, }, [ - h('div', { - style: { - textAlign: 'left', - fontSize: '12px', - marginBottom: '-10px', - }, - }, [ - 'Total Tokens', + h('span.confirm-screen-label', {}, [ + 'Total ', ]), h('div', { @@ -315,7 +286,7 @@ PendingTx.prototype.render = function () { fontSize: '8px', }, }, [ - 'Total Gas', + 'Amount + Gas', ]), ]), @@ -325,20 +296,9 @@ PendingTx.prototype.render = function () { width: '50%', }, }, [ - h('div', { - style: { - textAlign: 'left', - fontSize: '10px', - marginBottom: '-10px', - }, - }, '0.24 ANT (127.00 USD)'), + h('div.confirm-screen-row-info', {}, `$${totalInUSD} USD`), - h('div', { - style: { - textAlign: 'left', - fontSize: '8px', - }, - }, '0.249 ETH'), + h('div.confirm-screen-row-detail', {}, `${totalInETH} ETH`), ]), ]), @@ -356,32 +316,14 @@ PendingTx.prototype.render = function () { // }, 'Reset'), // Accept Button - h('input.confirm.btn-green', { + h('input.confirm-screen-confirm-button', { type: 'submit', value: 'CONFIRM', - style: { - marginTop: '8px', - width: '8em', - color: '#FFFFFF', - borderRadius: '2px', - fontSize: '12px', - lineHeight: '20px', - textAlign: 'center', - borderStyle: 'none', - }, - disabled: insufficientBalance || !this.state.valid || !isValidAddress || this.state.submitting, + // disabled: insufficientBalance || !this.state.valid || !isValidAddress || this.state.submitting, }), // Cancel Button - h('button.cancel.btn-light', { - style: { - background: '#F7F7F7', // $alabaster - border: 'none', - opacity: 1, - width: '8em', - }, - onClick: props.cancelTransaction, - }, 'CANCEL'), + h('button.cancel.btn-light.confirm-screen-cancel-button', {}, 'CANCEL'), ]), ]) // end of minwidth wrapper ) -- cgit v1.2.3 From 836bf2e1a38bb6917f1b7fe9db0604c8143c7adf Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Mon, 11 Sep 2017 23:18:54 -0700 Subject: Add frontend validation to send-token --- ui/app/components/input-number.js | 2 +- ui/app/components/send-token/index.js | 98 ++++++++++++++++++++++++++++--- ui/app/components/send/currency-toggle.js | 4 +- 3 files changed, 93 insertions(+), 11 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/input-number.js b/ui/app/components/input-number.js index 63e841288..2824d77aa 100644 --- a/ui/app/components/input-number.js +++ b/ui/app/components/input-number.js @@ -22,7 +22,7 @@ InputNumber.prototype.componentWillMount = function () { } InputNumber.prototype.setValue = function (newValue) { - const { fixed, min, onChange } = this.props + const { fixed, min = -1, onChange } = this.props if (fixed) newValue = Number(newValue.toFixed(4)) diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 985116409..439ea45b7 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -2,6 +2,7 @@ const Component = require('react').Component const connect = require('react-redux').connect const h = require('react-hyperscript') const ethUtil = require('ethereumjs-util') +const classnames = require('classnames') const inherits = require('util').inherits const actions = require('../../actions') const selectors = require('../../selectors') @@ -62,10 +63,60 @@ function SendTokenScreen () { Component.call(this) this.state = { to: '', + amount: null, selectedCurrency: 'USD', isGasTooltipOpen: false, gasPrice: '0x5d21dba00', gasLimit: '0x7b0d', + errors: {}, + } +} + +SendTokenScreen.prototype.validate = function () { + const { + to, + amount, + gasPrice: hexGasPrice, + gasLimit: hexGasLimit, + } = this.state + + const gasPrice = parseInt(hexGasPrice, 16) + const gasLimit = parseInt(hexGasLimit, 16) / 1000000000 + + if (to && amount && gasPrice && gasLimit) { + return { + isValid: true, + errors: {}, + } + } + + const errors = { + to: !to ? 'Required' : null, + amount: !Number(amount) ? 'Required' : null, + gasPrice: !gasPrice ? 'Gas Price Required' : null, + gasLimit: !gasLimit ? 'Gas Limit Required' : null, + } + + return { + isValid: false, + errors, + } +} + +SendTokenScreen.prototype.submit = function () { + // const { + // to, + // amount, + // selectedCurrency, + // isGasTooltipOpen, + // gasPrice, + // gasLimit, + // } = this.state + + const { isValid, errors } = this.validate() + + if (!isValid) { + return this.setState({ errors }) } } @@ -77,16 +128,24 @@ SendTokenScreen.prototype.renderToAddressInput = function () { const { to, + errors: { to: errorMessage }, } = this.state - return h('div.send-screen-input-wrapper', {}, [ + return h('div', { + className: classnames('send-screen-input-wrapper', { + 'send-screen-input-wrapper--error': errorMessage, + }), + }, [ h('div', ['To:']), h('input.large-input.send-screen-input', { name: 'address', list: 'addresses', placeholder: 'Address', value: to, - onChange: e => this.setState({ to: e.target.value }), + onChange: e => this.setState({ + to: e.target.value, + errors: {}, + }), }), h('datalist#addresses', [ // Corresponds to the addresses owned. @@ -105,23 +164,30 @@ SendTokenScreen.prototype.renderToAddressInput = function () { }) }), ]), + h('div.send-screen-input-wrapper__error-message', [ errorMessage ]), ]) } SendTokenScreen.prototype.renderAmountInput = function () { const { selectedCurrency, + amount, + errors: { amount: errorMessage }, } = this.state const { selectedToken: {symbol}, } = this.props - return h('div.send-screen-input-wrapper', {}, [ + return h('div.send-screen-input-wrapper', { + className: classnames('send-screen-input-wrapper', { + 'send-screen-input-wrapper--error': errorMessage, + }), + }, [ h('div.send-screen-amount-labels', [ h('span', ['Amount']), h(CurrencyToggle, { - selectedCurrency, + currentCurrency: selectedCurrency, currencies: [ symbol, 'USD' ], onClick: currency => this.setState({ selectedCurrency: currency }), }), @@ -129,8 +195,13 @@ SendTokenScreen.prototype.renderAmountInput = function () { h('input.large-input.send-screen-input', { placeholder: `0 ${symbol}`, type: 'number', - onChange: e => this.setState({ amount: e.target.value }), + value: amount, + onChange: e => this.setState({ + amount: e.target.value, + errors: {}, + }), }), + h('div.send-screen-input-wrapper__error-message', [ errorMessage ]), ]) } @@ -140,6 +211,10 @@ SendTokenScreen.prototype.renderGasInput = function () { gasPrice, gasLimit, selectedCurrency, + errors: { + gasPrice: gasPriceErrorMessage, + gasLimit: gasLimitErrorMessage, + }, } = this.state const { @@ -147,14 +222,18 @@ SendTokenScreen.prototype.renderGasInput = function () { currentBlockGasLimit, } = this.props - return h('div.send-screen-input-wrapper', [ + return h('div.send-screen-input-wrapper', { + className: classnames('send-screen-input-wrapper', { + 'send-screen-input-wrapper--error': gasPriceErrorMessage || gasLimitErrorMessage, + }), + }, [ isGasTooltipOpen && h(GasTooltip, { className: 'send-tooltip', gasPrice, gasLimit, onClose: () => this.setState({ isGasTooltipOpen: false }), onFeeChange: ({ gasLimit, gasPrice }) => { - this.setState({ gasLimit, gasPrice }) + this.setState({ gasLimit, gasPrice, errors: {} }) }, }), @@ -176,6 +255,9 @@ SendTokenScreen.prototype.renderGasInput = function () { ['Customize'] ), ]), + h('div.send-screen-input-wrapper__error-message', [ + gasPriceErrorMessage || gasLimitErrorMessage, + ]), ]) } @@ -194,7 +276,7 @@ SendTokenScreen.prototype.renderButtons = function () { return h('div.send-token__button-group', [ h('button.send-token__button-next.btn-secondary', { - + onClick: () => this.submit(), }, ['Next']), h('button.send-token__button-cancel.btn-tertiary', { onClick: () => backToAccountDetail(selectedAddress), diff --git a/ui/app/components/send/currency-toggle.js b/ui/app/components/send/currency-toggle.js index adaade301..2b59ace4a 100644 --- a/ui/app/components/send/currency-toggle.js +++ b/ui/app/components/send/currency-toggle.js @@ -22,14 +22,14 @@ CurrencyToggle.prototype.render = function () { 'currency-toggle__item--selected': currencyA === currentCurrency, }), onClick: () => onClick(currencyA), - }, ['ETH']), + }, [ currencyA ]), '<>', h('span', { className: classnames('currency-toggle__item', { 'currency-toggle__item--selected': currencyB === currentCurrency, }), onClick: () => onClick(currencyB), - }, ['USD']), + }, [ currencyB ]), ]) // holding on icon from design } -- cgit v1.2.3 From 7eb6dae4185d083ebb967256fdd09203b5092480 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 12 Sep 2017 02:22:23 -0700 Subject: Added signTokenTx; Adding token confirmation screen --- ui/app/components/pending-tx.js | 6 ++-- ui/app/components/send-token/index.js | 52 +++++++++++++++++++++++++++-------- 2 files changed, 44 insertions(+), 14 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index 31281faf2..ab425abf5 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -91,9 +91,9 @@ PendingTx.prototype.render = function () { // const maxCost = txFeeBn.add(amountBn) // const balanceBn = hexToBn(balance) // const insufficientBalance = balanceBn.lt(maxCost) - - const fromName = identities[txParams.from].name; - const toName = identities[txParams.to].name; + const fromName = identities[txParams.from].name + const to = identities[txParams.to] + const toName = to ? to.name : ' ' const endOfFromAddress = txParams.from.slice(txParams.from.length - 4) const endOfToAddress = txParams.to.slice(txParams.to.length - 4) diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 439ea45b7..8c02ec45d 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -1,7 +1,7 @@ const Component = require('react').Component const connect = require('react-redux').connect const h = require('react-hyperscript') -const ethUtil = require('ethereumjs-util') +const { addHexPrefix } = require('ethereumjs-util') const classnames = require('classnames') const inherits = require('util').inherits const actions = require('../../actions') @@ -50,6 +50,14 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)), + hideWarning: () => dispatch(actions.hideWarning()), + addToAddressBook: (recipient, nickname) => dispatch( + actions.addToAddressBook(recipient, nickname) + ), + signTx: txParams => dispatch(actions.signTx(txParams)), + signTokenTx: (tokenAddress, toAddress, amount, txData) => ( + dispatch(actions.signTokenTx(tokenAddress, toAddress, amount, txData)) + ), // showSidebar: () => { dispatch(actions.showSidebar()) }, // hideSidebar: () => { dispatch(actions.hideSidebar()) }, // showModal: (payload) => { dispatch(actions.showModal(payload)) }, @@ -75,13 +83,14 @@ function SendTokenScreen () { SendTokenScreen.prototype.validate = function () { const { to, - amount, + amount: stringAmount, gasPrice: hexGasPrice, gasLimit: hexGasLimit, } = this.state const gasPrice = parseInt(hexGasPrice, 16) const gasLimit = parseInt(hexGasLimit, 16) / 1000000000 + const amount = Number(stringAmount) if (to && amount && gasPrice && gasLimit) { return { @@ -92,7 +101,7 @@ SendTokenScreen.prototype.validate = function () { const errors = { to: !to ? 'Required' : null, - amount: !Number(amount) ? 'Required' : null, + amount: !amount ? 'Required' : null, gasPrice: !gasPrice ? 'Gas Price Required' : null, gasLimit: !gasLimit ? 'Gas Limit Required' : null, } @@ -104,20 +113,41 @@ SendTokenScreen.prototype.validate = function () { } SendTokenScreen.prototype.submit = function () { - // const { - // to, - // amount, - // selectedCurrency, - // isGasTooltipOpen, - // gasPrice, - // gasLimit, - // } = this.state + const { + to, + amount, + gasPrice, + gasLimit, + } = this.state + + const { + identities, + selectedAddress, + selectedTokenAddress, + hideWarning, + addToAddressBook, + signTokenTx, + } = this.props + + const { nickname = ' ' } = identities[to] || {} const { isValid, errors } = this.validate() if (!isValid) { return this.setState({ errors }) } + + hideWarning() + addToAddressBook(to, nickname) + + const txParams = { + from: selectedAddress, + value: '0', + gas: gasLimit, + gasPrice: gasPrice, + } + + signTokenTx(selectedTokenAddress, to, Number(amount).toString(16), txParams) } SendTokenScreen.prototype.renderToAddressInput = function () { -- cgit v1.2.3 From 492507aa94cb5713d5eaa700cfd7e88b2a16ca7a Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Tue, 12 Sep 2017 19:29:33 -0230 Subject: [NewUI] Color tx-list-item text depending on transaction status. (#2050) * Color tx-list-item text depending on transaction status. * Handle css change of text colour with scss instead on inline styles, add classnames package and helper function. * Refactored to use classnames with component property className. --- ui/app/components/tx-list-item.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 62127b153..9c681644e 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -1,6 +1,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits +const classnames = require('classnames') const prefixForNetwork = require('../../lib/etherscan-prefix-for-network') const Identicon = require('./identicon') @@ -67,9 +68,13 @@ TxListItem.prototype.render = function () { h('div.tx-list-status-wrapper', { style: {}, }, [ - h('span.tx-list-status', {}, [ + h('span', { + className: classnames('tx-list-status', { + 'tx-list-status--rejected': transactionStatus === 'rejected' + }) + }, transactionStatus, - ]), + ), ]), ]), @@ -77,9 +82,13 @@ TxListItem.prototype.render = function () { style: {}, }, [ - h('span.tx-list-value', {}, [ - transactionAmount, - ]), + h('span', { + className: classnames('tx-list-value', { + 'tx-list-value--confirmed': transactionStatus === 'confirmed' + }) + }, + transactionAmount + ), h('span.tx-list-fiat-value', {}, [ '+ $300 USD', -- cgit v1.2.3 From 080890a46ec98814bce8680f561fae3b52d81ed2 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 12 Sep 2017 18:08:02 -0230 Subject: Overhaul currency conversion utility and update calls to utility in pending-tx. --- ui/app/components/pending-tx.js | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index ab425abf5..a0d59207d 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -85,8 +85,6 @@ PendingTx.prototype.render = function () { const txFeeBn = gasBn.mul(gasPriceBn) - const amountBn = hexToBn(txParams.value) - // TODO: insufficient balance should be handled on send screen // const maxCost = txFeeBn.add(amountBn) // const balanceBn = hexToBn(balance) @@ -99,27 +97,39 @@ PendingTx.prototype.render = function () { const endOfToAddress = txParams.to.slice(txParams.to.length - 4) const gasFeeInUSD = conversionUtil(txFeeBn, { - fromFormat: 'BN', - fromCurrency: 'GWEI', + fromNumericBase: 'BN', + toNumericBase: 'dec', + fromDenomination: 'WEI', + fromCurrency: 'ETH', toCurrency: 'USD', + numberOfDecimals: 2, conversionRate, }) const gasFeeInETH = conversionUtil(txFeeBn, { - fromFormat: 'BN', - fromCurrency: 'GWEI', + fromNumericBase: 'BN', + toNumericBase: 'dec', + fromDenomination: 'WEI', + fromCurrency: 'ETH', toCurrency: 'ETH', + numberOfDecimals: 6, conversionRate, }) - const totalInUSD = conversionUtil(amountBn, { - fromFormat: 'BN', + const totalInUSD = conversionUtil(txParams.value, { + fromNumericBase: 'hex', + toNumericBase: 'dec', + fromCurrency: 'ETH', toCurrency: 'USD', + numberOfDecimals: 2, conversionRate, }) - const totalInETH = conversionUtil(amountBn, { - fromFormat: 'BN', + const totalInETH = conversionUtil(txParams.value, { + fromNumericBase: 'hex', + toNumericBase: 'dec', + fromCurrency: 'ETH', toCurrency: 'ETH', conversionRate, + numberOfDecimals: 6, }) this.inputs = [] -- cgit v1.2.3 From b64471833fc925899acb0e9d858624e978eb29af Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 12 Sep 2017 19:05:00 -0700 Subject: Revert "Overhaul currency conversion utility and update calls to utility in pending-tx." This reverts commit 080890a46ec98814bce8680f561fae3b52d81ed2. --- ui/app/components/pending-tx.js | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index a0d59207d..ab425abf5 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -85,6 +85,8 @@ PendingTx.prototype.render = function () { const txFeeBn = gasBn.mul(gasPriceBn) + const amountBn = hexToBn(txParams.value) + // TODO: insufficient balance should be handled on send screen // const maxCost = txFeeBn.add(amountBn) // const balanceBn = hexToBn(balance) @@ -97,39 +99,27 @@ PendingTx.prototype.render = function () { const endOfToAddress = txParams.to.slice(txParams.to.length - 4) const gasFeeInUSD = conversionUtil(txFeeBn, { - fromNumericBase: 'BN', - toNumericBase: 'dec', - fromDenomination: 'WEI', - fromCurrency: 'ETH', + fromFormat: 'BN', + fromCurrency: 'GWEI', toCurrency: 'USD', - numberOfDecimals: 2, conversionRate, }) const gasFeeInETH = conversionUtil(txFeeBn, { - fromNumericBase: 'BN', - toNumericBase: 'dec', - fromDenomination: 'WEI', - fromCurrency: 'ETH', + fromFormat: 'BN', + fromCurrency: 'GWEI', toCurrency: 'ETH', - numberOfDecimals: 6, conversionRate, }) - const totalInUSD = conversionUtil(txParams.value, { - fromNumericBase: 'hex', - toNumericBase: 'dec', - fromCurrency: 'ETH', + const totalInUSD = conversionUtil(amountBn, { + fromFormat: 'BN', toCurrency: 'USD', - numberOfDecimals: 2, conversionRate, }) - const totalInETH = conversionUtil(txParams.value, { - fromNumericBase: 'hex', - toNumericBase: 'dec', - fromCurrency: 'ETH', + const totalInETH = conversionUtil(amountBn, { + fromFormat: 'BN', toCurrency: 'ETH', conversionRate, - numberOfDecimals: 6, }) this.inputs = [] -- cgit v1.2.3 From 8b5f2a95df45c24061c13c51ca874e933e743381 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 12 Sep 2017 23:02:51 -0700 Subject: Improve styling in Confirmation Screen; Show decoded send token data --- ui/app/components/pending-tx.js | 339 +++++++++++++++++++--------------------- 1 file changed, 164 insertions(+), 175 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index ab425abf5..5b2aa253f 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -1,12 +1,14 @@ const Component = require('react').Component const { connect } = require('react-redux') const h = require('react-hyperscript') +const abi = require('human-standard-token-abi') +const abiDecoder = require('abi-decoder') +abiDecoder.addABI(abi) const inherits = require('util').inherits const actions = require('../actions') const clone = require('clone') const FiatValue = require('./fiat-value') const Identicon = require('./identicon') -const { setCurrentCurrency } = require('../actions') const ethUtil = require('ethereumjs-util') const BN = ethUtil.BN @@ -33,16 +35,19 @@ function mapStateToProps (state) { conversionRate, identities, } = state.metamask - + const accounts = state.metamask.accounts + const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] return { conversionRate, identities, + selectedAddress, } } function mapDispatchToProps (dispatch) { return { - setCurrentCurrencyToUSD: () => dispatch(setCurrentCurrency('USD')) + setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('USD')), + backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)), } } @@ -54,258 +59,242 @@ function PendingTx () { txData: null, submitting: false, } + this.onSubmit = this.onSubmit.bind(this) } PendingTx.prototype.componentWillMount = function () { this.props.setCurrentCurrencyToUSD() } -PendingTx.prototype.render = function () { - const props = this.props - const { blockGasLimit, conversionRate, identities } = props - +PendingTx.prototype.getTotal = function () { + const { conversionRate } = this.props const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} + const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data) + const { params = [] } = decodedData || {} + const { name, value } = params[1] || {} + const amountBn = name === '_value' + ? new BN(value) + : hexToBn(txParams.value) + + const USD = conversionUtil(amountBn, { + fromFormat: 'BN', + toCurrency: 'USD', + conversionRate, + }) + const ETH = conversionUtil(amountBn, { + fromFormat: 'BN', + toCurrency: 'ETH', + conversionRate, + }) - // Account Details - const address = txParams.from || props.selectedAddress - const account = props.accounts[address] - const balance = account ? account.balance : '0x0' + return { + USD, + ETH, + } +} - // recipient check - const isValidAddress = !txParams.to || util.isValidAddress(txParams.to) +PendingTx.prototype.getGasFee = function () { + const { conversionRate } = this.props + const txMeta = this.gatherTxMeta() + const txParams = txMeta.txParams || {} // Gas const gas = txParams.gas const gasBn = hexToBn(gas) - // Gas Price const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16) const gasPriceBn = hexToBn(gasPrice) const txFeeBn = gasBn.mul(gasPriceBn) - const amountBn = hexToBn(txParams.value) - - // TODO: insufficient balance should be handled on send screen - // const maxCost = txFeeBn.add(amountBn) - // const balanceBn = hexToBn(balance) - // const insufficientBalance = balanceBn.lt(maxCost) - const fromName = identities[txParams.from].name - const to = identities[txParams.to] - const toName = to ? to.name : ' ' - - const endOfFromAddress = txParams.from.slice(txParams.from.length - 4) - const endOfToAddress = txParams.to.slice(txParams.to.length - 4) - - const gasFeeInUSD = conversionUtil(txFeeBn, { + const USD = conversionUtil(txFeeBn, { fromFormat: 'BN', fromCurrency: 'GWEI', toCurrency: 'USD', conversionRate, }) - const gasFeeInETH = conversionUtil(txFeeBn, { + const ETH = conversionUtil(txFeeBn, { fromFormat: 'BN', fromCurrency: 'GWEI', toCurrency: 'ETH', conversionRate, }) - const totalInUSD = conversionUtil(amountBn, { - fromFormat: 'BN', - toCurrency: 'USD', - conversionRate, - }) - const totalInETH = conversionUtil(amountBn, { - fromFormat: 'BN', - toCurrency: 'ETH', - conversionRate, - }) + return { + USD, + ETH, + } +} + +PendingTx.prototype.getData = function () { + const { identities } = this.props + const txMeta = this.gatherTxMeta() + const txParams = txMeta.txParams || {} + const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data) + const { name, params = [] } = decodedData || {} + const { type, value } = params[0] || {} + const { USD: gasFeeInUSD, ETH: gasFeeInETH } = this.getGasFee() + const { USD: totalInUSD, ETH: totalInETH } = this.getTotal() + + if (name === 'transfer' && type === 'address') { + return { + from: { + address: txParams.from, + name: identities[txParams.from].name, + }, + to: { + address: value, + name: identities[value] ? identities[value].name : 'New Recipient', + }, + memo: txParams.memo || '', + gasFeeInUSD, + gasFeeInETH, + totalInUSD, + totalInETH, + } + } else { + return { + from: { + address: txParams.from, + name: identities[txParams.from].name, + }, + to: { + address: txParams.to, + name: identities[txParams.to] ? identities[txParams.to].name : 'New Recipient', + }, + memo: txParams.memo || '', + gasFeeInUSD, + gasFeeInETH, + totalInUSD, + totalInETH, + } + } +} + +PendingTx.prototype.render = function () { + const { backToAccountDetail, selectedAddress } = this.props + const txMeta = this.gatherTxMeta() + const txParams = txMeta.txParams || {} + + // recipient check + // const isValidAddress = !txParams.to || util.isValidAddress(txParams.to) + + const { + from: { + address: fromAddress, + name: fromName, + }, + to: { + address: toAddress, + name: toName, + }, + memo, + gasFeeInUSD, + gasFeeInETH, + totalInUSD, + totalInETH, + } = this.getData() this.inputs = [] return ( h('div.flex-column.flex-grow.confirm-screen-container', { - style: { - // overflow: 'scroll', - minWidth: '355px', // TODO: maxWidth TBD, use home.html - }, + style: { minWidth: '355px' }, }, [ - // Main Send token Card - h('div.confirm-screen-wrapper.flex-column.flex-grow', {}, [ - - h('h3.flex-center.confirm-screen-header', {}, [ - - h('button.confirm-screen-back-button', {}, 'BACK'), - - h('div.confirm-screen-title', {}, 'Confirm Transaction'), - + h('div.confirm-screen-wrapper.flex-column.flex-grow', [ + h('h3.flex-center.confirm-screen-header', [ + h('button.confirm-screen-back-button', { + onClick: () => backToAccountDetail(selectedAddress), + }, 'BACK'), + h('div.confirm-screen-title', 'Confirm Transaction'), ]), - - h('div.flex-row.flex-center.confirm-screen-identicons', {}, [ - - h('div.confirm-screen-account-wrapper', {}, [ + h('div.flex-row.flex-center.confirm-screen-identicons', [ + h('div.confirm-screen-account-wrapper', [ h( Identicon, { - address: txParams.from, - diameter: 64, - style: {}, + address: fromAddress, + diameter: 100, }, ), - h('span.confirm-screen-account-name', {}, fromName), - h('span.confirm-screen-account-number', {}, endOfFromAddress), - + h('span.confirm-screen-account-name', fromName), + h('span.confirm-screen-account-number', fromAddress.slice(fromAddress.length - 4)), ]), - h('i.fa.fa-arrow-right.fa-lg'), - - h('div.confirm-screen-account-wrapper', {}, [ + h('div.confirm-screen-account-wrapper', [ h( Identicon, { address: txParams.to, - diameter: 64, - style: {}, + diameter: 100, }, ), - h('span.confirm-screen-account-name', {}, toName), - h('span.confirm-screen-account-number', {}, endOfToAddress), - ]) - + h('span.confirm-screen-account-name', toName), + h('span.confirm-screen-account-number', toAddress.slice(toAddress.length - 4)), + ]), ]), h('h3.flex-center.confirm-screen-sending-to-message', { style: { textAlign: 'center', fontSize: '16px', - } + }, }, [ - `You're sending to Recipient ...${endOfToAddress}` + `You're sending to Recipient ...${toAddress.slice(toAddress.length - 4)}`, ]), - h('h3.flex-center.confirm-screen-send-amount', {}, [`$${totalInUSD}`]), - - h('h3.flex-center.confirm-screen-send-amount-currency', {}, [ - 'USD', + h('h3.flex-center.confirm-screen-send-amount', [`$${totalInUSD}`]), + h('h3.flex-center.confirm-screen-send-amount-currency', [ 'USD' ]), + h('div.flex-center.confirm-memo-wrapper', [ + h('h3.confirm-screen-send-memo', [ memo ]), ]), - h('div.flex-center.confirm-memo-wrapper', {}, h( - 'h3.confirm-screen-send-memo', {}, txParams.memo || 'Fake memo' - )), - - // TODO: put this error message in the right place - // props.error && h('span.error.flex-center', props.error), - - h('section.flex-row.flex-center.confirm-screen-row', { - }, [ - h('div', { - style: { - width: '50%', - }, - }, [ - h('span.confirm-screen-label', {}, [ - 'From', + h('div.confirm-screen-rows', [ + h('section.flex-row.flex-center.confirm-screen-row', [ + h('span.confirm-screen-label.confirm-screen-section-column', [ 'From' ]), + h('div.confirm-screen-section-column', [ + h('div.confirm-screen-row-info', fromName), + h('div.confirm-screen-row-detail', `...${fromAddress.slice(fromAddress.length - 4)}`), ]), ]), - h('div', { - style: { - width: '50%', - }, - }, [ - h('div.confirm-screen-row-info', {}, fromName), - - h('div.confirm-screen-row-detail', {}, `...${endOfFromAddress}`), - ]), - ]), - - - h('section.flex-row.flex-center.confirm-screen-row', { - }, [ - h('div', { - style: { - width: '50%', - }, - }, [ - h('span.confirm-screen-label', {}, [ - 'To', + h('section.flex-row.flex-center.confirm-screen-row', [ + h('span.confirm-screen-label.confirm-screen-section-column', [ 'To' ]), + h('div.confirm-screen-section-column', [ + h('div.confirm-screen-row-info', toName), + h('div.confirm-screen-row-detail', `...${toAddress.slice(toAddress.length - 4)}`), ]), ]), - h('div', { - style: { - width: '50%', - }, - }, [ - h('div.confirm-screen-row-info', {}, toName), + h('section.flex-row.flex-center.confirm-screen-row', [ + h('span.confirm-screen-label.confirm-screen-section-column', [ 'Gas Fee' ]), + h('div.confirm-screen-section-column', [ + h('div.confirm-screen-row-info', `$${gasFeeInUSD} USD`), - h('div.confirm-screen-row-detail', {}, `...${endOfToAddress}`), - ]), - ]), - - - h('section.flex-row.flex-center.confirm-screen-row', { - }, [ - h('div', { - style: { - width: '50%', - }, - }, [ - h('span.confirm-screen-label', {}, [ - 'Gas Fee', + h('div.confirm-screen-row-detail', `${gasFeeInETH} ETH`), ]), ]), - h('div', { - style: { - width: '50%', - }, - }, [ - h('div.confirm-screen-row-info', {}, `$${gasFeeInUSD} USD`), - - h('div.confirm-screen-row-detail', {}, `${gasFeeInETH} ETH`), - ]), - ]), - - h('section.flex-row.flex-center.confirm-screen-total-box ', {}, [ - h('div', { - style: { - width: '50%', - }, - }, [ - h('span.confirm-screen-label', {}, [ - 'Total ', + h('section.flex-row.flex-center.confirm-screen-total-box ', [ + h('div.confirm-screen-section-column', [ + h('span.confirm-screen-label', [ 'Total ' ]), + h('div.confirm-screen-total-box__subtitle', [ 'Amount + Gas' ]), ]), - h('div', { - style: { - textAlign: 'left', - fontSize: '8px', - }, - }, [ - 'Amount + Gas', + h('div.confirm-screen-section-column', [ + h('div.confirm-screen-row-info', `$${totalInUSD} USD`), + h('div.confirm-screen-row-detail', `${totalInETH} ETH`), ]), - - ]), - - h('div', { - style: { - width: '50%', - }, - }, [ - h('div.confirm-screen-row-info', {}, `$${totalInUSD} USD`), - - h('div.confirm-screen-row-detail', {}, `${totalInETH} ETH`), - ]), + ]), ]), - ]), // end of container + ]), h('form#pending-tx-form.flex-column.flex-center', { - onSubmit: this.onSubmit.bind(this), + onSubmit: this.onSubmit, }, [ // Reset Button // h('button', { @@ -325,7 +314,7 @@ PendingTx.prototype.render = function () { // Cancel Button h('button.cancel.btn-light.confirm-screen-cancel-button', {}, 'CANCEL'), ]), - ]) // end of minwidth wrapper + ]) ) } -- cgit v1.2.3 From 8f31b05ac5b7d8383c720b8b0c9f7f3cecc937f5 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Wed, 13 Sep 2017 01:25:39 -0700 Subject: Add token exchange rates --- ui/app/components/pending-tx.js | 6 +----- ui/app/components/send-token/index.js | 27 ++++++++++++++++++++++----- ui/app/components/send/currency-toggle.js | 15 ++++++++++++--- ui/app/components/send/gas-fee-display.js | 20 +++++++++++++++++++- 4 files changed, 54 insertions(+), 14 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index 5b2aa253f..6ae0444e7 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -305,11 +305,7 @@ PendingTx.prototype.render = function () { // }, 'Reset'), // Accept Button - h('input.confirm-screen-confirm-button', { - type: 'submit', - value: 'CONFIRM', - // disabled: insufficientBalance || !this.state.valid || !isValidAddress || this.state.submitting, - }), + h('button.confirm-screen-confirm-button', ['CONFIRM']), // Cancel Button h('button.cancel.btn-light.confirm-screen-cancel-button', {}, 'CANCEL'), diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 8c02ec45d..851d463eb 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -28,9 +28,12 @@ function mapStateToProps (state) { // const network = state.metamask.network const selectedTokenAddress = state.metamask.selectedTokenAddress const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] + const selectedToken = selectors.getSelectedToken(state) + const tokenExchangeRates = state.metamask.tokenExchangeRates + const pair = `${selectedToken.symbol.toLowerCase()}_eth` + const { rate: tokenExchangeRate = 0 } = tokenExchangeRates[pair] || {} // const checksumAddress = selectedAddress && ethUtil.toChecksumAddress(selectedAddress) // const identity = identities[selectedAddress] - return { // sidebarOpen, selectedAddress, @@ -39,8 +42,9 @@ function mapStateToProps (state) { identities, addressBook, conversionRate, + tokenExchangeRate, currentBlockGasLimit, - selectedToken: selectors.getSelectedToken(state), + selectedToken, // selectedToken: selectors.getSelectedToken(state), // identity, // network, @@ -58,6 +62,7 @@ function mapDispatchToProps (dispatch) { signTokenTx: (tokenAddress, toAddress, amount, txData) => ( dispatch(actions.signTokenTx(tokenAddress, toAddress, amount, txData)) ), + updateTokenExchangeRate: token => dispatch(actions.updateTokenExchangeRate(token)), // showSidebar: () => { dispatch(actions.showSidebar()) }, // hideSidebar: () => { dispatch(actions.hideSidebar()) }, // showModal: (payload) => { dispatch(actions.showModal(payload)) }, @@ -71,7 +76,7 @@ function SendTokenScreen () { Component.call(this) this.state = { to: '', - amount: null, + amount: '', selectedCurrency: 'USD', isGasTooltipOpen: false, gasPrice: '0x5d21dba00', @@ -80,6 +85,15 @@ function SendTokenScreen () { } } +SendTokenScreen.prototype.componentWillMount = function () { + const { + updateTokenExchangeRate, + selectedToken: { symbol }, + } = this.props + + updateTokenExchangeRate(symbol) +} + SendTokenScreen.prototype.validate = function () { const { to, @@ -206,6 +220,7 @@ SendTokenScreen.prototype.renderAmountInput = function () { } = this.state const { + tokenExchangeRate, selectedToken: {symbol}, } = this.props @@ -217,8 +232,8 @@ SendTokenScreen.prototype.renderAmountInput = function () { h('div.send-screen-amount-labels', [ h('span', ['Amount']), h(CurrencyToggle, { - currentCurrency: selectedCurrency, - currencies: [ symbol, 'USD' ], + currentCurrency: tokenExchangeRate ? selectedCurrency : 'USD', + currencies: tokenExchangeRate ? [ symbol, 'USD' ] : [], onClick: currency => this.setState({ selectedCurrency: currency }), }), ]), @@ -249,6 +264,7 @@ SendTokenScreen.prototype.renderGasInput = function () { const { conversionRate, + tokenExchangeRate, currentBlockGasLimit, } = this.props @@ -274,6 +290,7 @@ SendTokenScreen.prototype.renderGasInput = function () { h('div.large-input.send-screen-gas-input', [ h(GasFeeDisplay, { conversionRate, + tokenExchangeRate, gasPrice, currentCurrency: selectedCurrency, gas: gasLimit, diff --git a/ui/app/components/send/currency-toggle.js b/ui/app/components/send/currency-toggle.js index 2b59ace4a..d777f0aea 100644 --- a/ui/app/components/send/currency-toggle.js +++ b/ui/app/components/send/currency-toggle.js @@ -12,11 +12,11 @@ function CurrencyToggle () { const defaultCurrencies = [ 'ETH', 'USD' ] -CurrencyToggle.prototype.render = function () { +CurrencyToggle.prototype.renderToggles = function () { const { onClick, currentCurrency } = this.props const [currencyA, currencyB] = this.props.currencies || defaultCurrencies - return h('span.currency-toggle', {}, [ + return [ h('span', { className: classnames('currency-toggle__item', { 'currency-toggle__item--selected': currencyA === currentCurrency, @@ -30,6 +30,15 @@ CurrencyToggle.prototype.render = function () { }), onClick: () => onClick(currencyB), }, [ currencyB ]), - ]) // holding on icon from design + ] +} + +CurrencyToggle.prototype.render = function () { + const currencies = this.props.currencies || defaultCurrencies + + return h('span.currency-toggle', currencies.length + ? this.renderToggles() + : [] + ) } diff --git a/ui/app/components/send/gas-fee-display.js b/ui/app/components/send/gas-fee-display.js index 5336be8a3..979062882 100644 --- a/ui/app/components/send/gas-fee-display.js +++ b/ui/app/components/send/gas-fee-display.js @@ -3,6 +3,7 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const USDFeeDisplay = require('./usd-fee-display') const EthFeeDisplay = require('./eth-fee-display') +const { getTxFeeBn, formatBalance, shortenBalance } = require('../../util') module.exports = GasFeeDisplay @@ -11,6 +12,20 @@ function GasFeeDisplay () { Component.call(this) } +GasFeeDisplay.prototype.getTokenValue = function () { + const { + tokenExchangeRate, + gas, + gasPrice, + blockGasLimit, + } = this.props + + const value = formatBalance(getTxFeeBn(gas, gasPrice, blockGasLimit), 6, true) + const [ethNumber] = value.split(' ') + + return shortenBalance(Number(ethNumber) / tokenExchangeRate, 6) +} + GasFeeDisplay.prototype.render = function () { const { currentCurrency, @@ -38,7 +53,10 @@ GasFeeDisplay.prototype.render = function () { blockGasLimit, }) default: - return h('noscript'); + return h('div.token-gas', [ + h('div.token-gas__amount', this.getTokenValue()), + h('div.token-gas__symbol', currentCurrency), + ]) } } -- cgit v1.2.3 From 6fa1cd62258ba96d1a55bee140f2d1f10f091ed2 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 12 Sep 2017 18:08:02 -0230 Subject: Reapply conversion utility changes and fix calls to utility in pending-tx. --- ui/app/components/pending-tx.js | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index 6ae0444e7..0bc995afb 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -74,18 +74,24 @@ PendingTx.prototype.getTotal = function () { const { params = [] } = decodedData || {} const { name, value } = params[1] || {} const amountBn = name === '_value' - ? new BN(value) - : hexToBn(txParams.value) - + ? value + : txParams.value + const USD = conversionUtil(amountBn, { - fromFormat: 'BN', + fromNumericBase: 'hex', + toNumericBase: 'dec', + fromCurrency: 'ETH', toCurrency: 'USD', + numberOfDecimals: 2, conversionRate, }) const ETH = conversionUtil(amountBn, { - fromFormat: 'BN', + fromNumericBase: 'hex', + toNumericBase: 'dec', + fromCurrency: 'ETH', toCurrency: 'ETH', conversionRate, + numberOfDecimals: 6, }) return { @@ -109,15 +115,21 @@ PendingTx.prototype.getGasFee = function () { const txFeeBn = gasBn.mul(gasPriceBn) const USD = conversionUtil(txFeeBn, { - fromFormat: 'BN', - fromCurrency: 'GWEI', + fromNumericBase: 'BN', + toNumericBase: 'dec', + fromDenomination: 'WEI', + fromCurrency: 'ETH', toCurrency: 'USD', + numberOfDecimals: 2, conversionRate, }) const ETH = conversionUtil(txFeeBn, { - fromFormat: 'BN', - fromCurrency: 'GWEI', + fromNumericBase: 'BN', + toNumericBase: 'dec', + fromDenomination: 'WEI', + fromCurrency: 'ETH', toCurrency: 'ETH', + numberOfDecimals: 6, conversionRate, }) -- cgit v1.2.3 From 55d62190e3ec06b1b21ed3ba24b2f2a9bc137568 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 12 Sep 2017 18:10:28 -0230 Subject: Fixes the saving of transactions in send and display in tx-list with conversion utility. --- ui/app/components/tx-list-item.js | 24 ++++++++++++++++++++++-- ui/app/components/tx-list.js | 13 +++++++------ 2 files changed, 29 insertions(+), 8 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 9c681644e..4be8dfcb3 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -5,6 +5,8 @@ const classnames = require('classnames') const prefixForNetwork = require('../../lib/etherscan-prefix-for-network') const Identicon = require('./identicon') +const { conversionUtil } = require('../conversion-util') + module.exports = TxListItem inherits(TxListItem, Component) @@ -27,8 +29,26 @@ TxListItem.prototype.render = function () { address, transactionAmount, className, + conversionRate, } = this.props + const totalInUSD = conversionUtil(transactionAmount, { + fromNumericBase: 'hex', + toNumericBase: 'dec', + fromCurrency: 'ETH', + toCurrency: 'USD', + numberOfDecimals: 2, + conversionRate, + }) + const totalInETH = conversionUtil(transactionAmount, { + fromNumericBase: 'hex', + toNumericBase: 'dec', + fromCurrency: 'ETH', + toCurrency: 'ETH', + conversionRate, + numberOfDecimals: 6, + }) + return h(`div${className || ''}`, { key: transActionId, onClick: () => onClick && onClick(transActionId), @@ -87,11 +107,11 @@ TxListItem.prototype.render = function () { 'tx-list-value--confirmed': transactionStatus === 'confirmed' }) }, - transactionAmount + `${totalInETH} ETH`, ), h('span.tx-list-fiat-value', {}, [ - '+ $300 USD', + `${totalInUSD} USD`, ]), ]), diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index a7d11203d..e3578646b 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -40,26 +40,26 @@ TxList.prototype.render = function () { ]), ]), - this.renderTranstions(), + this.renderTransaction(), ]) } -TxList.prototype.renderTranstions = function () { - const { txsToRender } = this.props +TxList.prototype.renderTransaction = function () { + const { txsToRender, conversionRate } = this.props return txsToRender.length - ? txsToRender.map((transaction) => this.renderTransactionListItem(transaction)) + ? txsToRender.map((transaction) => this.renderTransactionListItem(transaction, conversionRate)) : [h('div.tx-list-item.tx-list-item--empty', [ 'No Transactions' ])] } // TODO: Consider moving TxListItem into a separate component -TxList.prototype.renderTransactionListItem = function (transaction) { +TxList.prototype.renderTransactionListItem = function (transaction, conversionRate) { const props = { dateString: formatDate(transaction.time), address: transaction.txParams.to, transactionStatus: transaction.status, - transactionAmount: formatBalance(transaction.txParams.value, 6), + transactionAmount: transaction.txParams.value, transActionId: transaction.id, transactionHash: transaction.hash, transactionNetworkId: transaction.metamaskNetworkId, @@ -85,6 +85,7 @@ TxList.prototype.renderTransactionListItem = function (transaction) { transactionAmount, transactionHash, className: '.tx-list-item.tx-list-clickable', + conversionRate, } if (transactionStatus === 'unapproved') { -- cgit v1.2.3 From a5ab91e572eec05450a760d4a65e3a28df67c0d1 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 13 Sep 2017 12:41:03 -0230 Subject: Enables Cancel button in confirmation screen. --- ui/app/components/pending-tx.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index 0bc995afb..69dd2107a 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -48,6 +48,7 @@ function mapDispatchToProps (dispatch) { return { setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('USD')), backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)), + cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })) } } @@ -306,7 +307,7 @@ PendingTx.prototype.render = function () { ]), h('form#pending-tx-form.flex-column.flex-center', { - onSubmit: this.onSubmit, + // onSubmit: this.onSubmit, }, [ // Reset Button // h('button', { @@ -320,7 +321,9 @@ PendingTx.prototype.render = function () { h('button.confirm-screen-confirm-button', ['CONFIRM']), // Cancel Button - h('button.cancel.btn-light.confirm-screen-cancel-button', {}, 'CANCEL'), + h('div.cancel.btn-light.confirm-screen-cancel-button', { + onClick: (event) => this.cancel(event, txMeta), + }, 'CANCEL'), ]), ]) ) @@ -366,6 +369,7 @@ PendingTx.prototype.onSubmit = function (event) { const txMeta = this.gatherTxMeta() const valid = this.checkValidity() this.setState({ valid, submitting: true }) + if (valid && this.verifyGasParams()) { this.props.sendTransaction(txMeta, event) } else { @@ -374,6 +378,11 @@ PendingTx.prototype.onSubmit = function (event) { } } +PendingTx.prototype.cancel = function (event, txMeta) { + event.preventDefault() + this.props.cancelTransaction(txMeta) +} + PendingTx.prototype.checkValidity = function () { const form = this.getFormEl() const valid = form.checkValidity() -- cgit v1.2.3 From ca46bd200b24456d692cf1ede47506be5fdcc76d Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 13 Sep 2017 15:27:15 -0230 Subject: Stop setting 'currentCurrency' and use local state for active currency in send.js --- ui/app/components/send/currency-toggle.js | 6 +++--- ui/app/components/send/eth-fee-display.js | 4 ++-- ui/app/components/send/gas-fee-display.js | 10 +++++----- ui/app/components/send/usd-fee-display.js | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send/currency-toggle.js b/ui/app/components/send/currency-toggle.js index d777f0aea..7aaccd490 100644 --- a/ui/app/components/send/currency-toggle.js +++ b/ui/app/components/send/currency-toggle.js @@ -13,20 +13,20 @@ function CurrencyToggle () { const defaultCurrencies = [ 'ETH', 'USD' ] CurrencyToggle.prototype.renderToggles = function () { - const { onClick, currentCurrency } = this.props + const { onClick, activeCurrency } = this.props const [currencyA, currencyB] = this.props.currencies || defaultCurrencies return [ h('span', { className: classnames('currency-toggle__item', { - 'currency-toggle__item--selected': currencyA === currentCurrency, + 'currency-toggle__item--selected': currencyA === activeCurrency, }), onClick: () => onClick(currencyA), }, [ currencyA ]), '<>', h('span', { className: classnames('currency-toggle__item', { - 'currency-toggle__item--selected': currencyB === currentCurrency, + 'currency-toggle__item--selected': currencyB === activeCurrency, }), onClick: () => onClick(currencyB), }, [ currencyB ]), diff --git a/ui/app/components/send/eth-fee-display.js b/ui/app/components/send/eth-fee-display.js index 3dcb711ce..8b4cec16c 100644 --- a/ui/app/components/send/eth-fee-display.js +++ b/ui/app/components/send/eth-fee-display.js @@ -13,7 +13,7 @@ function EthFeeDisplay () { EthFeeDisplay.prototype.render = function () { const { - currentCurrency, + activeCurrency, conversionRate, gas, gasPrice, @@ -22,7 +22,7 @@ EthFeeDisplay.prototype.render = function () { return h(EthBalance, { value: getTxFeeBn(gas, gasPrice, blockGasLimit), - currentCurrency, + currentCurrency: activeCurrency, conversionRate, showFiat: false, hideTooltip: true, diff --git a/ui/app/components/send/gas-fee-display.js b/ui/app/components/send/gas-fee-display.js index 979062882..a9a3f3f49 100644 --- a/ui/app/components/send/gas-fee-display.js +++ b/ui/app/components/send/gas-fee-display.js @@ -28,17 +28,17 @@ GasFeeDisplay.prototype.getTokenValue = function () { GasFeeDisplay.prototype.render = function () { const { - currentCurrency, + activeCurrency, conversionRate, gas, gasPrice, blockGasLimit, } = this.props - switch (currentCurrency) { + switch (activeCurrency) { case 'USD': return h(USDFeeDisplay, { - currentCurrency, + activeCurrency, conversionRate, gas, gasPrice, @@ -46,7 +46,7 @@ GasFeeDisplay.prototype.render = function () { }) case 'ETH': return h(EthFeeDisplay, { - currentCurrency, + activeCurrency, conversionRate, gas, gasPrice, @@ -55,7 +55,7 @@ GasFeeDisplay.prototype.render = function () { default: return h('div.token-gas', [ h('div.token-gas__amount', this.getTokenValue()), - h('div.token-gas__symbol', currentCurrency), + h('div.token-gas__symbol', activeCurrency), ]) } } diff --git a/ui/app/components/send/usd-fee-display.js b/ui/app/components/send/usd-fee-display.js index 012bda550..6ee38f1b5 100644 --- a/ui/app/components/send/usd-fee-display.js +++ b/ui/app/components/send/usd-fee-display.js @@ -13,7 +13,7 @@ function USDFeeDisplay () { USDFeeDisplay.prototype.render = function () { const { - currentCurrency, + activeCurrency, conversionRate, gas, gasPrice, @@ -23,7 +23,7 @@ USDFeeDisplay.prototype.render = function () { return h(FiatValue, { value: getTxFeeBn(gas, gasPrice, blockGasLimit), conversionRate, - currentCurrency, + currentCurrency: activeCurrency, style: { color: '#5d5d5d', fontSize: '16px', -- cgit v1.2.3 From 6bd71d69378c74de8748bdfb5476ec082077676c Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 13 Sep 2017 20:43:47 -0230 Subject: Fix send and pending. --- ui/app/components/pending-tx.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index 69dd2107a..99769e4e6 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -307,7 +307,7 @@ PendingTx.prototype.render = function () { ]), h('form#pending-tx-form.flex-column.flex-center', { - // onSubmit: this.onSubmit, + onSubmit: this.onSubmit, }, [ // Reset Button // h('button', { -- cgit v1.2.3 From d722c1045f70954cb1a97de52cae5084a6f14815 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Wed, 13 Sep 2017 19:57:33 -0700 Subject: Update yarn.lock; Fix tx-list-item overflow; Fix gas exchange rate --- ui/app/components/pending-tx.js | 72 ++++++++++++++++++++++++----------- ui/app/components/send-token/index.js | 2 +- 2 files changed, 50 insertions(+), 24 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index 99769e4e6..6eb2fb2b2 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -48,7 +48,7 @@ function mapDispatchToProps (dispatch) { return { setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('USD')), backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)), - cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })) + cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), } } @@ -77,28 +77,55 @@ PendingTx.prototype.getTotal = function () { const amountBn = name === '_value' ? value : txParams.value - - const USD = conversionUtil(amountBn, { - fromNumericBase: 'hex', - toNumericBase: 'dec', - fromCurrency: 'ETH', - toCurrency: 'USD', - numberOfDecimals: 2, - conversionRate, - }) - const ETH = conversionUtil(amountBn, { - fromNumericBase: 'hex', - toNumericBase: 'dec', - fromCurrency: 'ETH', - toCurrency: 'ETH', - conversionRate, - numberOfDecimals: 6, - }) - return { - USD, - ETH, + if (name === '_value') { + const token = util.getContractAtAddress(txParams.to) + token.symbol().then(symbol => console.log({symbol})) + console.log({txParams, txMeta, decodedData, token}) + const USD = conversionUtil(amountBn, { + fromNumericBase: 'hex', + toNumericBase: 'dec', + fromCurrency: 'ETH', + toCurrency: 'USD', + numberOfDecimals: 2, + conversionRate, + }) + const ETH = conversionUtil(amountBn, { + fromNumericBase: 'hex', + toNumericBase: 'dec', + fromCurrency: 'ETH', + toCurrency: 'ETH', + conversionRate, + numberOfDecimals: 6, + }) + return { + USD, + ETH, + } + } else { + const USD = conversionUtil(amountBn, { + fromNumericBase: 'hex', + toNumericBase: 'dec', + fromCurrency: 'ETH', + toCurrency: 'USD', + numberOfDecimals: 2, + conversionRate, + }) + const ETH = conversionUtil(amountBn, { + fromNumericBase: 'hex', + toNumericBase: 'dec', + fromCurrency: 'ETH', + toCurrency: 'ETH', + conversionRate, + numberOfDecimals: 6, + }) + + return { + USD, + ETH, + } } + } PendingTx.prototype.getGasFee = function () { @@ -400,12 +427,11 @@ PendingTx.prototype.getFormEl = function () { // After a customizable state value has been updated, PendingTx.prototype.gatherTxMeta = function () { - log.debug(`pending-tx gatherTxMeta`) const props = this.props const state = this.state const txData = clone(state.txData) || clone(props.txData) - log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`) + // log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`) return txData } diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 851d463eb..a3332ca9e 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -292,7 +292,7 @@ SendTokenScreen.prototype.renderGasInput = function () { conversionRate, tokenExchangeRate, gasPrice, - currentCurrency: selectedCurrency, + activeCurrency: selectedCurrency, gas: gasLimit, blockGasLimit: currentBlockGasLimit, }), -- cgit v1.2.3 From 93a1089e085cb70ddbd58721a140ab8d3b6b79eb Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Thu, 14 Sep 2017 01:09:57 -0700 Subject: Show token tx properly --- ui/app/components/send-token/index.js | 7 ++- ui/app/components/tx-list-item.js | 112 ++++++++++++++++++++++++++-------- ui/app/components/tx-list.js | 5 +- 3 files changed, 97 insertions(+), 27 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index a3332ca9e..72fb593be 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -141,6 +141,7 @@ SendTokenScreen.prototype.submit = function () { hideWarning, addToAddressBook, signTokenTx, + selectedToken, } = this.props const { nickname = ' ' } = identities[to] || {} @@ -161,7 +162,11 @@ SendTokenScreen.prototype.submit = function () { gasPrice: gasPrice, } - signTokenTx(selectedTokenAddress, to, Number(amount).toString(16), txParams) + const { decimals } = selectedToken || {} + const multiplier = Math.pow(10, Number(decimals || 0)) + const sendAmount = Number(amount * multiplier).toString(16) + + signTokenTx(selectedTokenAddress, to, sendAmount, txParams) } SendTokenScreen.prototype.renderToAddressInput = function () { diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 4be8dfcb3..70b4486dd 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -1,37 +1,60 @@ const Component = require('react').Component const h = require('react-hyperscript') +const connect = require('react-redux').connect const inherits = require('util').inherits const classnames = require('classnames') +const abi = require('human-standard-token-abi') +const abiDecoder = require('abi-decoder') +abiDecoder.addABI(abi) const prefixForNetwork = require('../../lib/etherscan-prefix-for-network') const Identicon = require('./identicon') const { conversionUtil } = require('../conversion-util') -module.exports = TxListItem +module.exports = connect(mapStateToProps)(TxListItem) + +function mapStateToProps (state) { + return { + tokens: state.metamask.tokens, + } +} inherits(TxListItem, Component) function TxListItem () { Component.call(this) } -TxListItem.prototype.getAddressText = function (address) { - return address - ? `${address.slice(0, 10)}...${address.slice(-4)}` - : 'Contract Published' +TxListItem.prototype.getAddressText = function () { + const { + address, + txParams = {}, + } = this.props + + const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data) + const { name: txDataName, params = [] } = decodedData || {} + const { value } = params[0] || {} + + switch (txDataName) { + case 'transfer': + return `${value.slice(0, 10)}...${value.slice(-4)}` + default: + return address + ? `${address.slice(0, 10)}...${address.slice(-4)}` + : 'Contract Published' + } } -TxListItem.prototype.render = function () { +TxListItem.prototype.getSendEtherTotal = function () { const { - transactionStatus, - onClick, - transActionId, - dateString, - address, transactionAmount, - className, conversionRate, + address, } = this.props + if (!address) { + return {} + } + const totalInUSD = conversionUtil(transactionAmount, { fromNumericBase: 'hex', toNumericBase: 'dec', @@ -49,6 +72,50 @@ TxListItem.prototype.render = function () { numberOfDecimals: 6, }) + return { + total: `${totalInETH} ETH`, + fiatTotal: `${totalInUSD} USD`, + } +} + +TxListItem.prototype.getSendTokenTotal = function () { + const { + txParams = {}, + tokens, + } = this.props + + const toAddress = txParams.to + const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data) + const { params = [] } = decodedData || {} + const { value } = params[1] || {} + const { decimals, symbol } = tokens.filter(({ address }) => address === toAddress)[0] || {} + + const multiplier = Math.pow(10, Number(decimals || 0)) + const total = Number(value / multiplier) + + return { + total: `${total} ${symbol}`, + } +} + +TxListItem.prototype.render = function () { + const { + transactionStatus, + onClick, + transActionId, + dateString, + address, + className, + txParams = {}, + } = this.props + + const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data) + const { name: txDataName } = decodedData || {} + + const { total, fiatTotal } = txDataName === 'transfer' + ? this.getSendTokenTotal() + : this.getSendEtherTotal() + return h(`div${className || ''}`, { key: transActionId, onClick: () => onClick && onClick(transActionId), @@ -90,9 +157,10 @@ TxListItem.prototype.render = function () { }, [ h('span', { className: classnames('tx-list-status', { - 'tx-list-status--rejected': transactionStatus === 'rejected' - }) - }, + 'tx-list-status--rejected': transactionStatus === 'rejected', + 'tx-list-status--failed': transactionStatus === 'failed', + }), + }, transactionStatus, ), ]), @@ -104,15 +172,11 @@ TxListItem.prototype.render = function () { h('span', { className: classnames('tx-list-value', { - 'tx-list-value--confirmed': transactionStatus === 'confirmed' - }) - }, - `${totalInETH} ETH`, - ), - - h('span.tx-list-fiat-value', {}, [ - `${totalInUSD} USD`, - ]), + 'tx-list-value--confirmed': transactionStatus === 'confirmed', + }), + }, total), + + h('span.tx-list-fiat-value', fiatTotal), ]), ]), diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index e3578646b..7a147e942 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -49,7 +49,7 @@ TxList.prototype.renderTransaction = function () { const { txsToRender, conversionRate } = this.props return txsToRender.length - ? txsToRender.map((transaction) => this.renderTransactionListItem(transaction, conversionRate)) + ? txsToRender.map((transaction, i) => this.renderTransactionListItem(transaction, conversionRate)) : [h('div.tx-list-item.tx-list-item--empty', [ 'No Transactions' ])] } @@ -77,7 +77,8 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa const { showConfTxPage } = this.props const opts = { - key: transactionHash, + key: transActionId, + txParams: transaction.txParams, transactionStatus, transActionId, dateString, -- cgit v1.2.3 From ab77142c90a532a775636cf20a7e23191ff47f8f Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 15 Sep 2017 08:53:12 -0230 Subject: Show dollar sign before USD on account details page. --- ui/app/components/balance-component.js | 8 +++++--- ui/app/components/tx-list-item.js | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/balance-component.js b/ui/app/components/balance-component.js index 6d73d5b4a..d14aa675f 100644 --- a/ui/app/components/balance-component.js +++ b/ui/app/components/balance-component.js @@ -88,15 +88,17 @@ BalanceComponent.prototype.renderFiatValue = function (formattedBalance) { const fiatDisplayNumber = this.getFiatDisplayNumber(formattedBalance, conversionRate) - return this.renderFiatAmount(fiatDisplayNumber, currentCurrency) + const fiatPrefix = currentCurrency === 'USD' ? '$' : '' + + return this.renderFiatAmount(fiatDisplayNumber, currentCurrency, fiatPrefix) } -BalanceComponent.prototype.renderFiatAmount = function (fiatDisplayNumber, fiatSuffix) { +BalanceComponent.prototype.renderFiatAmount = function (fiatDisplayNumber, fiatSuffix, fiatPrefix) { if (fiatDisplayNumber === 'N/A') return null return h('div.fiat-amount', { style: {}, - }, `${fiatDisplayNumber} ${fiatSuffix}`) + }, `${fiatPrefix}${fiatDisplayNumber} ${fiatSuffix}`) } BalanceComponent.prototype.getTokenBalance = function (formattedBalance, shorten) { diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 70b4486dd..d45aea964 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -74,7 +74,7 @@ TxListItem.prototype.getSendEtherTotal = function () { return { total: `${totalInETH} ETH`, - fiatTotal: `${totalInUSD} USD`, + fiatTotal: `$${totalInUSD} USD`, } } -- cgit v1.2.3 From 095d327140fe4bb2b4a131a66e2774bdfeb8ce37 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 15 Sep 2017 10:01:25 -0230 Subject: Adds USD to token list. --- ui/app/components/token-cell.js | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index a6fe8fc61..dc1c7f46f 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -6,18 +6,22 @@ const Identicon = require('./identicon') const prefixForNetwork = require('../../lib/etherscan-prefix-for-network') const selectors = require('../selectors') const actions = require('../actions') +const { conversionUtil } = require('../conversion-util') function mapStateToProps (state) { return { network: state.metamask.network, selectedTokenAddress: state.metamask.selectedTokenAddress, userAddress: selectors.getSelectedAddress(state), + tokenExchangeRates: state.metamask.tokenExchangeRates, + ethToUSDRate: state.metamask.conversionRate, } } function mapDispatchToProps (dispatch) { return { setSelectedToken: address => dispatch(actions.setSelectedToken(address)), + updateTokenExchangeRate: token => dispatch(actions.updateTokenExchangeRate(token)), } } @@ -28,6 +32,15 @@ function TokenCell () { Component.call(this) } +TokenCell.prototype.componentWillMount = function () { + const { + updateTokenExchangeRate, + symbol, + } = this.props + + updateTokenExchangeRate(symbol) +} + TokenCell.prototype.render = function () { const props = this.props const { @@ -37,8 +50,29 @@ TokenCell.prototype.render = function () { network, setSelectedToken, selectedTokenAddress, + tokenExchangeRates, + ethToUSDRate, // userAddress, } = props + + const pair = `${symbol.toLowerCase()}_eth`; + + let currentTokenToEthRate; + let currentTokenInUSD; + let formattedUSD = '' + + if (tokenExchangeRates[pair]) { + currentTokenToEthRate = tokenExchangeRates[pair].rate; + currentTokenInUSD = conversionUtil(string, { + fromNumericBase: 'dec', + fromCurrency: symbol, + toCurrency: 'USD', + numberOfDecimals: 2, + conversionRate: currentTokenToEthRate, + ethToUSDRate, + }) + formattedUSD = `$${currentTokenInUSD} USD`; + } return ( h('div.token-list-item', { @@ -58,9 +92,9 @@ TokenCell.prototype.render = function () { h('h.token-list-item__balance-wrapper', null, [ h('h3.token-list-item__token-balance', `${string || 0} ${symbol}`), - // h('div.token-list-item__fiat-amount', { - // style: {}, - // }, '210 FPO'), + h('div.token-list-item__fiat-amount', { + style: {}, + }, formattedUSD), ]), /* -- cgit v1.2.3 From b0f1fba2e5fbde573b46a284285985e63f1a3618 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 15 Sep 2017 12:39:34 -0230 Subject: Ensures that new accounts are only created from the modal, and not when clicking 'Create New Account' --- ui/app/components/dropdowns/components/account-dropdowns.js | 5 +---- ui/app/components/modals/new-account-modal.js | 8 +++++++- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index 48354ff94..bb112dcca 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -162,11 +162,11 @@ class AccountDropdowns extends Component { DropdownMenuItem, { closeMenu: () => {}, - onClick: () => actions.addNewAccount(), style: Object.assign( {}, menuItemStyles, ), + onClick: () => actions.showNewAccountModal(), }, [ h( @@ -185,9 +185,6 @@ class AccountDropdowns extends Component { fontSize: '16px', lineHeight: '23px', }, - onClick: () => { - actions.showNewAccountModal() - }, }, 'Create Account'), ], ), diff --git a/ui/app/components/modals/new-account-modal.js b/ui/app/components/modals/new-account-modal.js index 8d67762ac..910f3c0ca 100644 --- a/ui/app/components/modals/new-account-modal.js +++ b/ui/app/components/modals/new-account-modal.js @@ -19,6 +19,10 @@ function mapDispatchToProps (dispatch) { hideModal: () => { dispatch(actions.hideModal()) }, + createAccount: () => { + dispatch(actions.addNewAccount()) + dispatch(actions.hideModal()) + }, } } @@ -60,7 +64,9 @@ NewAccountModal.prototype.render = function () { ]), h('div.new-account-modal-content.button', {}, [ - h('button.btn-clear', {}, [ + h('button.btn-clear', { + onClick: this.props.createAccount + }, [ 'SAVE', ]), ]), -- cgit v1.2.3 From 54bbf8d8590014b92e7857f30bdc2d8f3779431a Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 13 Sep 2017 23:50:13 -0230 Subject: Handle transaction totals in WEI in tx-list, send and pending. --- ui/app/components/pending-tx.js | 4 ++++ ui/app/components/tx-list-item.js | 2 ++ 2 files changed, 6 insertions(+) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index 6eb2fb2b2..c1b079a25 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -88,6 +88,7 @@ PendingTx.prototype.getTotal = function () { fromCurrency: 'ETH', toCurrency: 'USD', numberOfDecimals: 2, + fromDenomination: 'WEI', conversionRate, }) const ETH = conversionUtil(amountBn, { @@ -95,6 +96,7 @@ PendingTx.prototype.getTotal = function () { toNumericBase: 'dec', fromCurrency: 'ETH', toCurrency: 'ETH', + fromDenomination: 'WEI', conversionRate, numberOfDecimals: 6, }) @@ -109,6 +111,7 @@ PendingTx.prototype.getTotal = function () { fromCurrency: 'ETH', toCurrency: 'USD', numberOfDecimals: 2, + fromDenomination: 'WEI', conversionRate, }) const ETH = conversionUtil(amountBn, { @@ -116,6 +119,7 @@ PendingTx.prototype.getTotal = function () { toNumericBase: 'dec', fromCurrency: 'ETH', toCurrency: 'ETH', + fromDenomination: 'WEI', conversionRate, numberOfDecimals: 6, }) diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index d45aea964..8422c02b9 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -60,6 +60,7 @@ TxListItem.prototype.getSendEtherTotal = function () { toNumericBase: 'dec', fromCurrency: 'ETH', toCurrency: 'USD', + fromDenomination: 'WEI', numberOfDecimals: 2, conversionRate, }) @@ -68,6 +69,7 @@ TxListItem.prototype.getSendEtherTotal = function () { toNumericBase: 'dec', fromCurrency: 'ETH', toCurrency: 'ETH', + fromDenomination: 'WEI', conversionRate, numberOfDecimals: 6, }) -- cgit v1.2.3 From 162a3827c7ba418ce8180d81c54ad09d9b9560b8 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Mon, 18 Sep 2017 11:34:07 -0700 Subject: Fix Merge Problems; update yarn lock --- ui/app/components/dropdowns/components/account-dropdowns.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index fe80af8b3..e2d3d6d64 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -453,5 +453,11 @@ const mapDispatchToProps = (dispatch) => { } } -module.exports = connect(null, mapDispatchToProps)(AccountDropdowns) +function mapStateToProps (state) { + return { + keyrings: state.metamask.keyrings, + } +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountDropdowns) -- cgit v1.2.3 From e7f1fc44361829f05a713218f8b1837a8574c2f2 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 19 Sep 2017 18:49:35 -0700 Subject: Buy Modal Styling --- ui/app/components/modals/modal.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 477dcbe86..04a2f5f40 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -21,12 +21,13 @@ const MODALS = { mobileModalStyle: { width: '95%', top: isPopupOrNotification() === 'popup' ? '48vh' : '36.5vh', - boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', + boxShadow: '0 0 7px 0 rgba(0,0,0,0.08)', }, laptopModalStyle: { width: '66%', + maxWidth: '550px', top: 'calc(30% + 10px)', - boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', + boxShadow: '0 0 7px 0 rgba(0,0,0,0.08)', }, }, @@ -64,7 +65,7 @@ const MODALS = { }, contentStyle: { borderRadius: '4px', - } + }, }, NEW_ACCOUNT: { -- cgit v1.2.3 From 97810acb5355be575914a2e1e57a1cacd9fbccfa Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 20 Sep 2017 20:34:03 -0230 Subject: Handles errors with to field and renders warnings from backend in send token. --- ui/app/components/send-token/index.js | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 72fb593be..7adbf48dc 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -6,6 +6,7 @@ const classnames = require('classnames') const inherits = require('util').inherits const actions = require('../../actions') const selectors = require('../../selectors') +const { isValidAddress } = require('../../util') // const BalanceComponent = require('./balance-component') const Identicon = require('../identicon') @@ -14,12 +15,12 @@ const CurrencyToggle = require('../send/currency-toggle') const GasTooltip = require('../send/gas-tooltip') const GasFeeDisplay = require('../send/gas-fee-display') - module.exports = connect(mapStateToProps, mapDispatchToProps)(SendTokenScreen) function mapStateToProps (state) { // const sidebarOpen = state.appState.sidebarOpen + const { warning } = state.appState const identities = state.metamask.identities const addressBook = state.metamask.addressBook const conversionRate = state.metamask.conversionRate @@ -34,6 +35,7 @@ function mapStateToProps (state) { const { rate: tokenExchangeRate = 0 } = tokenExchangeRates[pair] || {} // const checksumAddress = selectedAddress && ethUtil.toChecksumAddress(selectedAddress) // const identity = identities[selectedAddress] + return { // sidebarOpen, selectedAddress, @@ -45,6 +47,7 @@ function mapStateToProps (state) { tokenExchangeRate, currentBlockGasLimit, selectedToken, + warning, // selectedToken: selectors.getSelectedToken(state), // identity, // network, @@ -106,13 +109,6 @@ SendTokenScreen.prototype.validate = function () { const gasLimit = parseInt(hexGasLimit, 16) / 1000000000 const amount = Number(stringAmount) - if (to && amount && gasPrice && gasLimit) { - return { - isValid: true, - errors: {}, - } - } - const errors = { to: !to ? 'Required' : null, amount: !amount ? 'Required' : null, @@ -120,9 +116,14 @@ SendTokenScreen.prototype.validate = function () { gasLimit: !gasLimit ? 'Gas Limit Required' : null, } + if(to && !isValidAddress(to)) { + errors.to = 'Invalid address' + } + + const isValid = Object.entries(errors).every(([key, value]) => value === null) return { - isValid: false, - errors, + isValid, + errors: isValid ? {} : errors, } } @@ -145,7 +146,6 @@ SendTokenScreen.prototype.submit = function () { } = this.props const { nickname = ' ' } = identities[to] || {} - const { isValid, errors } = this.validate() if (!isValid) { @@ -340,6 +340,7 @@ SendTokenScreen.prototype.render = function () { const { selectedTokenAddress, selectedToken, + warning, } = this.props return h('div.send-token', [ @@ -359,6 +360,11 @@ SendTokenScreen.prototype.render = function () { this.renderAmountInput(), this.renderGasInput(), this.renderMemoInput(), + warning && h('div.send-screen-input-wrapper--error', {}, + h('div.send-screen-input-wrapper__error-message', [ + warning, + ]) + ), ]), this.renderButtons(), ]) -- cgit v1.2.3 From 39afbea7aaf17cfee5d7fc11299cb82e657edd7e Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 20 Sep 2017 11:26:20 -0230 Subject: Confirm screen shows amount plus gas in total field --- ui/app/components/pending-tx.js | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index 18b622925..a8fac4c28 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -14,7 +14,7 @@ const ethUtil = require('ethereumjs-util') const BN = ethUtil.BN const hexToBn = require('../../../app/scripts/lib/hex-to-bn') const util = require('../util') -const { conversionUtil } = require('../conversion-util') +const { conversionUtil, addCurrencies } = require('../conversion-util') const MIN_GAS_PRICE_GWEI_BN = new BN(1) const GWEI_FACTOR = new BN(1e9) @@ -67,7 +67,7 @@ PendingTx.prototype.componentWillMount = function () { this.props.setCurrentCurrencyToUSD() } -PendingTx.prototype.getTotal = function () { +PendingTx.prototype.getAmount = function () { const { conversionRate } = this.props const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} @@ -186,7 +186,16 @@ PendingTx.prototype.getData = function () { const { name, params = [] } = decodedData || {} const { type, value } = params[0] || {} const { USD: gasFeeInUSD, ETH: gasFeeInETH } = this.getGasFee() - const { USD: totalInUSD, ETH: totalInETH } = this.getTotal() + const { USD: amountInUSD, ETH: amountInETH } = this.getAmount() + + const totalInUSD = addCurrencies(gasFeeInUSD, amountInUSD, { + toNumericBase: 'dec', + numberOfDecimals: 2, + }) + const totalInETH = addCurrencies(gasFeeInETH, amountInETH, { + toNumericBase: 'dec', + numberOfDecimals: 6, + }) if (name === 'transfer' && type === 'address') { return { @@ -201,8 +210,8 @@ PendingTx.prototype.getData = function () { memo: txParams.memo || '', gasFeeInUSD, gasFeeInETH, - totalInUSD, - totalInETH, + amountInUSD, + amountInETH, } } else { return { @@ -217,6 +226,8 @@ PendingTx.prototype.getData = function () { memo: txParams.memo || '', gasFeeInUSD, gasFeeInETH, + amountInUSD, + amountInETH, totalInUSD, totalInETH, } @@ -243,6 +254,8 @@ PendingTx.prototype.render = function () { memo, gasFeeInUSD, gasFeeInETH, + amountInUSD, + amountInETH, totalInUSD, totalInETH, } = this.getData() @@ -307,7 +320,7 @@ PendingTx.prototype.render = function () { `You're sending to Recipient ...${toAddress.slice(toAddress.length - 4)}`, ]), - h('h3.flex-center.confirm-screen-send-amount', [`$${totalInUSD}`]), + h('h3.flex-center.confirm-screen-send-amount', [`$${amountInUSD}`]), h('h3.flex-center.confirm-screen-send-amount-currency', [ 'USD' ]), h('div.flex-center.confirm-memo-wrapper', [ h('h3.confirm-screen-send-memo', [ memo ]), -- cgit v1.2.3 From 24fd16b1bee31352ef7f364804eb5f06c08c3bf6 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 19 Sep 2017 22:26:10 -0230 Subject: Abstract account modal. --- ui/app/components/modals/account-details-modal.js | 45 ++++-------------- .../components/modals/account-modal-container.js | 55 ++++++++++++++++++++++ ui/app/components/qr-code.js | 2 +- 3 files changed, 66 insertions(+), 36 deletions(-) create mode 100644 ui/app/components/modals/account-modal-container.js (limited to 'ui/app/components') diff --git a/ui/app/components/modals/account-details-modal.js b/ui/app/components/modals/account-details-modal.js index ec7e4b500..6c2eba7bd 100644 --- a/ui/app/components/modals/account-details-modal.js +++ b/ui/app/components/modals/account-details-modal.js @@ -3,25 +3,21 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect const actions = require('../../actions') +const AccountModalContainer = require('./account-modal-container') const { getSelectedIdentity, getSelectedAddress } = require('../../selectors') const genAccountLink = require('../../../lib/account-link.js') -const Identicon = require('../identicon') const QrView = require('../qr-code') function mapStateToProps (state) { return { network: state.metamask.network, - address: state.metamask.selectedAddress, - selectedAddress: getSelectedAddress(state), selectedIdentity: getSelectedIdentity(state), } } function mapDispatchToProps (dispatch) { return { - hideModal: () => { - dispatch(actions.hideModal()) - }, + // Is this supposed to be used somewhere? showQrView: (selected, identity) => dispatch(actions.showQrView(selected, identity)), } } @@ -34,49 +30,28 @@ function AccountDetailsModal () { module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountDetailsModal) // Not yet pixel perfect todos: - // fonts of qr-header and close button + // fonts of qr-header AccountDetailsModal.prototype.render = function () { const { selectedIdentity, network } = this.props + const { name, address } = selectedIdentity - return h('div', { style: { borderRadius: '4px' }}, [ - h('div.account-details-modal-wrapper', [ - - h('div', [ - - // Needs a border; requires changes to svg - h(Identicon, { - address: selectedIdentity.address, - diameter: 64, - style: {}, - }), - - ]), - - h('div.account-details-modal-close', { - onClick: this.props.hideModal, - }), - + return h(AccountModalContainer, {}, [ h(QrView, { Qr: { - message: this.props.selectedIdentity.name, - data: this.props.selectedIdentity.address, + message: name, + data: address, }, }), - // divider - h('div.account-details-modal-divider'), + h('div.account-modal-divider'), h('button.btn-clear', { - onClick: () => { - const url = genAccountLink(selectedIdentity.address, network) - global.platform.openWindow({ url }) - }, + onClick: () => global.platform.openWindow({ url: genAccountLink(address, network) }), }, [ 'View account on Etherscan' ]), // Holding on redesign for Export Private Key functionality h('button.btn-clear', [ 'Export private key' ]), - - ]), + ]) } diff --git a/ui/app/components/modals/account-modal-container.js b/ui/app/components/modals/account-modal-container.js new file mode 100644 index 000000000..69650ca15 --- /dev/null +++ b/ui/app/components/modals/account-modal-container.js @@ -0,0 +1,55 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const connect = require('react-redux').connect +const actions = require('../../actions') +const { getSelectedIdentity } = require('../../selectors') +const Identicon = require('../identicon') + +function mapStateToProps (state) { + return { + selectedIdentity: getSelectedIdentity(state), + } +} + +function mapDispatchToProps (dispatch) { + return { + hideModal: () => { + dispatch(actions.hideModal()) + }, + } +} + +inherits(AccountModalContainer, Component) +function AccountModalContainer () { + Component.call(this) +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountModalContainer) + +AccountModalContainer.prototype.render = function () { + const { selectedIdentity, children } = this.props + console.log(`children`, children); + return h('div', { style: { borderRadius: '4px' }}, [ + h('div.account-modal-container', [ + + h('div', [ + + // Needs a border; requires changes to svg + h(Identicon, { + address: selectedIdentity.address, + diameter: 64, + style: {}, + }), + + ]), + + h('div.account-modal-close', { + onClick: this.props.hideModal, + }), + + ...children, + + ]), + ]) +} diff --git a/ui/app/components/qr-code.js b/ui/app/components/qr-code.js index 4257c1a15..dca5c8c47 100644 --- a/ui/app/components/qr-code.js +++ b/ui/app/components/qr-code.js @@ -52,7 +52,7 @@ QrCodeView.prototype.render = function () { width: '247px', }, value: Qr.data, - readonly: true, + readOnly: true, }), // h(CopyButton, { // value: Qr.data, -- cgit v1.2.3 From 3ec2f534632426876c28b22c58cbbf14b4904d97 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Thu, 21 Sep 2017 18:44:52 -0700 Subject: Integrate Add Token --- ui/app/components/token-balance.js | 14 +++++++++----- ui/app/components/tx-list.js | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/token-balance.js b/ui/app/components/token-balance.js index 3a923eb9d..0342c1da9 100644 --- a/ui/app/components/token-balance.js +++ b/ui/app/components/token-balance.js @@ -17,7 +17,8 @@ module.exports = connect(mapStateToProps)(TokenBalance) inherits(TokenBalance, Component) function TokenBalance () { this.state = { - balance: '', + string: '', + symbol: '', isLoading: true, error: null, } @@ -26,11 +27,14 @@ function TokenBalance () { TokenBalance.prototype.render = function () { const state = this.state - const { balance, isLoading } = state + const { symbol, string, balanceOnly, isLoading } = state return isLoading ? h('span', '') - : h('span', balance) + : h('span.token-balance', [ + h('span.token-balance__amount', string), + !balanceOnly && h('span.token-balance__symbol', symbol), + ]) } TokenBalance.prototype.componentDidMount = function () { @@ -93,10 +97,10 @@ TokenBalance.prototype.componentDidUpdate = function (nextProps) { TokenBalance.prototype.updateBalance = function (tokens = []) { const [{ string, symbol }] = tokens - const { balanceOnly } = this.props this.setState({ - balance: balanceOnly ? string : `${string} ${symbol}`, + string, + symbol, isLoading: false, }) } diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 7a147e942..f817d03a9 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -77,7 +77,7 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa const { showConfTxPage } = this.props const opts = { - key: transActionId, + key: transActionId || transactionHash, txParams: transaction.txParams, transactionStatus, transActionId, -- cgit v1.2.3 From 83cda2b82e082a5a9b2ee35a9b6d55be43b0d788 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Thu, 21 Sep 2017 22:25:16 -0700 Subject: Refactor Confirmation Tx to render different screen --- ui/app/components/pending-tx.js | 569 --------------------- ui/app/components/pending-tx/confirm-send-ether.js | 446 ++++++++++++++++ ui/app/components/pending-tx/index.js | 103 ++++ 3 files changed, 549 insertions(+), 569 deletions(-) delete mode 100644 ui/app/components/pending-tx.js create mode 100644 ui/app/components/pending-tx/confirm-send-ether.js create mode 100644 ui/app/components/pending-tx/index.js (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js deleted file mode 100644 index a8fac4c28..000000000 --- a/ui/app/components/pending-tx.js +++ /dev/null @@ -1,569 +0,0 @@ -const Component = require('react').Component -const { connect } = require('react-redux') -const h = require('react-hyperscript') -const abi = require('human-standard-token-abi') -const abiDecoder = require('abi-decoder') -abiDecoder.addABI(abi) -const inherits = require('util').inherits -const actions = require('../actions') -const clone = require('clone') -const FiatValue = require('./fiat-value') -const Identicon = require('./identicon') - -const ethUtil = require('ethereumjs-util') -const BN = ethUtil.BN -const hexToBn = require('../../../app/scripts/lib/hex-to-bn') -const util = require('../util') -const { conversionUtil, addCurrencies } = require('../conversion-util') - -const MIN_GAS_PRICE_GWEI_BN = new BN(1) -const GWEI_FACTOR = new BN(1e9) -const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR) - -// Next: create separate react components -// roughly 5 components: -// heroIcon -// numericDisplay (contains symbol + currency) -// divider -// contentBox -// actionButtons - -module.exports = connect(mapStateToProps, mapDispatchToProps)(PendingTx) - -function mapStateToProps (state) { - const { - conversionRate, - identities, - } = state.metamask - const accounts = state.metamask.accounts - const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] - return { - conversionRate, - identities, - selectedAddress, - } -} - -function mapDispatchToProps (dispatch) { - return { - setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('USD')), - backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)), - cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), - } -} - -inherits(PendingTx, Component) -function PendingTx () { - Component.call(this) - this.state = { - valid: true, - txData: null, - submitting: false, - } - this.onSubmit = this.onSubmit.bind(this) -} - -PendingTx.prototype.componentWillMount = function () { - this.props.setCurrentCurrencyToUSD() -} - -PendingTx.prototype.getAmount = function () { - const { conversionRate } = this.props - const txMeta = this.gatherTxMeta() - const txParams = txMeta.txParams || {} - const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data) - const { params = [] } = decodedData || {} - const { name, value } = params[1] || {} - const amountBn = name === '_value' - ? value - : txParams.value - - if (name === '_value') { - const token = util.getContractAtAddress(txParams.to) - token.symbol().then(symbol => console.log({symbol})) - console.log({txParams, txMeta, decodedData, token}) - const USD = conversionUtil(amountBn, { - fromNumericBase: 'hex', - toNumericBase: 'dec', - fromCurrency: 'ETH', - toCurrency: 'USD', - numberOfDecimals: 2, - fromDenomination: 'WEI', - conversionRate, - }) - const ETH = conversionUtil(amountBn, { - fromNumericBase: 'hex', - toNumericBase: 'dec', - fromCurrency: 'ETH', - toCurrency: 'ETH', - fromDenomination: 'WEI', - conversionRate, - numberOfDecimals: 6, - }) - return { - USD, - ETH, - } - } else { - const USD = conversionUtil(amountBn, { - fromNumericBase: 'hex', - toNumericBase: 'dec', - fromCurrency: 'ETH', - toCurrency: 'USD', - numberOfDecimals: 2, - fromDenomination: 'WEI', - conversionRate, - }) - const ETH = conversionUtil(amountBn, { - fromNumericBase: 'hex', - toNumericBase: 'dec', - fromCurrency: 'ETH', - toCurrency: 'ETH', - fromDenomination: 'WEI', - conversionRate, - numberOfDecimals: 6, - }) - - return { - USD, - ETH, - } - } - -} - -PendingTx.prototype.getGasFee = function () { - const { conversionRate } = this.props - const txMeta = this.gatherTxMeta() - const txParams = txMeta.txParams || {} - - // Gas - const gas = txParams.gas - const gasBn = hexToBn(gas) - - // From latest master -// const gasLimit = new BN(parseInt(blockGasLimit)) -// const safeGasLimitBN = this.bnMultiplyByFraction(gasLimit, 19, 20) -// const saferGasLimitBN = this.bnMultiplyByFraction(gasLimit, 18, 20) -// const safeGasLimit = safeGasLimitBN.toString(10) - - // Gas Price - const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16) - const gasPriceBn = hexToBn(gasPrice) - - const txFeeBn = gasBn.mul(gasPriceBn) - - const USD = conversionUtil(txFeeBn, { - fromNumericBase: 'BN', - toNumericBase: 'dec', - fromDenomination: 'WEI', - fromCurrency: 'ETH', - toCurrency: 'USD', - numberOfDecimals: 2, - conversionRate, - }) - const ETH = conversionUtil(txFeeBn, { - fromNumericBase: 'BN', - toNumericBase: 'dec', - fromDenomination: 'WEI', - fromCurrency: 'ETH', - toCurrency: 'ETH', - numberOfDecimals: 6, - conversionRate, - }) - - return { - USD, - ETH, - } -} - -PendingTx.prototype.getData = function () { - const { identities } = this.props - const txMeta = this.gatherTxMeta() - const txParams = txMeta.txParams || {} - const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data) - const { name, params = [] } = decodedData || {} - const { type, value } = params[0] || {} - const { USD: gasFeeInUSD, ETH: gasFeeInETH } = this.getGasFee() - const { USD: amountInUSD, ETH: amountInETH } = this.getAmount() - - const totalInUSD = addCurrencies(gasFeeInUSD, amountInUSD, { - toNumericBase: 'dec', - numberOfDecimals: 2, - }) - const totalInETH = addCurrencies(gasFeeInETH, amountInETH, { - toNumericBase: 'dec', - numberOfDecimals: 6, - }) - - if (name === 'transfer' && type === 'address') { - return { - from: { - address: txParams.from, - name: identities[txParams.from].name, - }, - to: { - address: value, - name: identities[value] ? identities[value].name : 'New Recipient', - }, - memo: txParams.memo || '', - gasFeeInUSD, - gasFeeInETH, - amountInUSD, - amountInETH, - } - } else { - return { - from: { - address: txParams.from, - name: identities[txParams.from].name, - }, - to: { - address: txParams.to, - name: identities[txParams.to] ? identities[txParams.to].name : 'New Recipient', - }, - memo: txParams.memo || '', - gasFeeInUSD, - gasFeeInETH, - amountInUSD, - amountInETH, - totalInUSD, - totalInETH, - } - } -} - -PendingTx.prototype.render = function () { - const { backToAccountDetail, selectedAddress } = this.props - const txMeta = this.gatherTxMeta() - const txParams = txMeta.txParams || {} - - // recipient check - // const isValidAddress = !txParams.to || util.isValidAddress(txParams.to) - - const { - from: { - address: fromAddress, - name: fromName, - }, - to: { - address: toAddress, - name: toName, - }, - memo, - gasFeeInUSD, - gasFeeInETH, - amountInUSD, - amountInETH, - totalInUSD, - totalInETH, - } = this.getData() - - // This is from the latest master - // It handles some of the errors that we are not currently handling - // Leaving as comments fo reference - - // const balanceBn = hexToBn(balance) - // const insufficientBalance = balanceBn.lt(maxCost) - // const buyDisabled = insufficientBalance || !this.state.valid || !isValidAddress || this.state.submitting - // const showRejectAll = props.unconfTxListLength > 1 -// const dangerousGasLimit = gasBn.gte(saferGasLimitBN) -// const gasLimitSpecified = txMeta.gasLimitSpecified - - this.inputs = [] - - return ( - h('div.flex-column.flex-grow.confirm-screen-container', { - style: { minWidth: '355px' }, - }, [ - // Main Send token Card - h('div.confirm-screen-wrapper.flex-column.flex-grow', [ - h('h3.flex-center.confirm-screen-header', [ - h('button.confirm-screen-back-button', { - onClick: () => backToAccountDetail(selectedAddress), - }, 'BACK'), - h('div.confirm-screen-title', 'Confirm Transaction'), - ]), - h('div.flex-row.flex-center.confirm-screen-identicons', [ - h('div.confirm-screen-account-wrapper', [ - h( - Identicon, - { - address: fromAddress, - diameter: 100, - }, - ), - h('span.confirm-screen-account-name', fromName), - h('span.confirm-screen-account-number', fromAddress.slice(fromAddress.length - 4)), - ]), - h('i.fa.fa-arrow-right.fa-lg'), - h('div.confirm-screen-account-wrapper', [ - h( - Identicon, - { - address: txParams.to, - diameter: 100, - }, - ), - h('span.confirm-screen-account-name', toName), - h('span.confirm-screen-account-number', toAddress.slice(toAddress.length - 4)), - ]), - ]), - - h('h3.flex-center.confirm-screen-sending-to-message', { - style: { - textAlign: 'center', - fontSize: '16px', - }, - }, [ - `You're sending to Recipient ...${toAddress.slice(toAddress.length - 4)}`, - ]), - - h('h3.flex-center.confirm-screen-send-amount', [`$${amountInUSD}`]), - h('h3.flex-center.confirm-screen-send-amount-currency', [ 'USD' ]), - h('div.flex-center.confirm-memo-wrapper', [ - h('h3.confirm-screen-send-memo', [ memo ]), - ]), - - h('div.confirm-screen-rows', [ - h('section.flex-row.flex-center.confirm-screen-row', [ - h('span.confirm-screen-label.confirm-screen-section-column', [ 'From' ]), - h('div.confirm-screen-section-column', [ - h('div.confirm-screen-row-info', fromName), - h('div.confirm-screen-row-detail', `...${fromAddress.slice(fromAddress.length - 4)}`), - ]), - ]), - - h('section.flex-row.flex-center.confirm-screen-row', [ - h('span.confirm-screen-label.confirm-screen-section-column', [ 'To' ]), - h('div.confirm-screen-section-column', [ - h('div.confirm-screen-row-info', toName), - h('div.confirm-screen-row-detail', `...${toAddress.slice(toAddress.length - 4)}`), - ]), - ]), - - h('section.flex-row.flex-center.confirm-screen-row', [ - h('span.confirm-screen-label.confirm-screen-section-column', [ 'Gas Fee' ]), - h('div.confirm-screen-section-column', [ - h('div.confirm-screen-row-info', `$${gasFeeInUSD} USD`), - - h('div.confirm-screen-row-detail', `${gasFeeInETH} ETH`), - ]), - ]), - - - h('section.flex-row.flex-center.confirm-screen-total-box ', [ - h('div.confirm-screen-section-column', [ - h('span.confirm-screen-label', [ 'Total ' ]), - h('div.confirm-screen-total-box__subtitle', [ 'Amount + Gas' ]), - ]), - - h('div.confirm-screen-section-column', [ - h('div.confirm-screen-row-info', `$${totalInUSD} USD`), - h('div.confirm-screen-row-detail', `${totalInETH} ETH`), - ]), - ]), - ]), - -// These are latest errors handling from master -// Leaving as comments as reference when we start implementing error handling -// h('style', ` -// .conf-buttons button { -// margin-left: 10px; -// text-transform: uppercase; -// } -// `), - -// txMeta.simulationFails ? -// h('.error', { -// style: { -// marginLeft: 50, -// fontSize: '0.9em', -// }, -// }, 'Transaction Error. Exception thrown in contract code.') -// : null, - -// !isValidAddress ? -// h('.error', { -// style: { -// marginLeft: 50, -// fontSize: '0.9em', -// }, -// }, 'Recipient address is invalid. Sending this transaction will result in a loss of ETH.') -// : null, - -// insufficientBalance ? -// h('span.error', { -// style: { -// marginLeft: 50, -// fontSize: '0.9em', -// }, -// }, 'Insufficient balance for transaction') -// : null, - -// // send + cancel -// h('.flex-row.flex-space-around.conf-buttons', { -// style: { -// display: 'flex', -// justifyContent: 'flex-end', -// margin: '14px 25px', -// }, -// }, [ -// h('button', { -// onClick: (event) => { -// this.resetGasFields() -// event.preventDefault() -// }, -// }, 'Reset'), - -// // Accept Button or Buy Button -// insufficientBalance ? h('button.btn-green', { onClick: props.buyEth }, 'Buy Ether') : -// h('input.confirm.btn-green', { -// type: 'submit', -// value: 'SUBMIT', -// style: { marginLeft: '10px' }, -// disabled: buyDisabled, -// }), - -// h('button.cancel.btn-red', { -// onClick: props.cancelTransaction, -// }, 'Reject'), -// ]), -// showRejectAll ? h('.flex-row.flex-space-around.conf-buttons', { -// style: { -// display: 'flex', -// justifyContent: 'flex-end', -// margin: '14px 25px', -// }, -// }, [ -// h('button.cancel.btn-red', { -// onClick: props.cancelAllTransactions, -// }, 'Reject All'), -// ]) : null, -// ]), -// ]) -// ) -// } - ]), - - h('form#pending-tx-form.flex-column.flex-center', { - onSubmit: this.onSubmit, - }, [ - // Reset Button - // h('button', { - // onClick: (event) => { - // this.resetGasFields() - // event.preventDefault() - // }, - // }, 'Reset'), - - // Accept Button - h('button.confirm-screen-confirm-button', ['CONFIRM']), - - // Cancel Button - h('div.cancel.btn-light.confirm-screen-cancel-button', { - onClick: (event) => this.cancel(event, txMeta), - }, 'CANCEL'), - ]), - ]) - ) -} - -// PendingTx.prototype.gasPriceChanged = function (newBN, valid) { -// log.info(`Gas price changed to: ${newBN.toString(10)}`) -// const txMeta = this.gatherTxMeta() -// txMeta.txParams.gasPrice = '0x' + newBN.toString('hex') -// this.setState({ -// txData: clone(txMeta), -// valid, -// }) -// } - -// PendingTx.prototype.gasLimitChanged = function (newBN, valid) { -// log.info(`Gas limit changed to ${newBN.toString(10)}`) -// const txMeta = this.gatherTxMeta() -// txMeta.txParams.gas = '0x' + newBN.toString('hex') -// this.setState({ -// txData: clone(txMeta), -// valid, -// }) -// } - -// PendingTx.prototype.resetGasFields = function () { -// log.debug(`pending-tx resetGasFields`) - -// this.inputs.forEach((hexInput) => { -// if (hexInput) { -// hexInput.setValid() -// } -// }) - -// this.setState({ -// txData: null, -// valid: true, -// }) -// } - -PendingTx.prototype.onSubmit = function (event) { - event.preventDefault() - const txMeta = this.gatherTxMeta() - const valid = this.checkValidity() - this.setState({ valid, submitting: true }) - - if (valid && this.verifyGasParams()) { - this.props.sendTransaction(txMeta, event) - } else { - this.props.dispatch(actions.displayWarning('Invalid Gas Parameters')) - this.setState({ submitting: false }) - } -} - -PendingTx.prototype.cancel = function (event, txMeta) { - event.preventDefault() - this.props.cancelTransaction(txMeta) -} - -PendingTx.prototype.checkValidity = function () { - const form = this.getFormEl() - const valid = form.checkValidity() - return valid -} - -PendingTx.prototype.getFormEl = function () { - const form = document.querySelector('form#pending-tx-form') - // Stub out form for unit tests: - if (!form) { - return { checkValidity () { return true } } - } - return form -} - -// After a customizable state value has been updated, -PendingTx.prototype.gatherTxMeta = function () { - const props = this.props - const state = this.state - const txData = clone(state.txData) || clone(props.txData) - - // log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`) - return txData -} - -PendingTx.prototype.verifyGasParams = function () { - // We call this in case the gas has not been modified at all - if (!this.state) { return true } - return ( - this._notZeroOrEmptyString(this.state.gas) && - this._notZeroOrEmptyString(this.state.gasPrice) - ) -} - -PendingTx.prototype._notZeroOrEmptyString = function (obj) { - return obj !== '' && obj !== '0x0' -} - -PendingTx.prototype.bnMultiplyByFraction = function (targetBN, numerator, denominator) { - const numBN = new BN(numerator) - const denomBN = new BN(denominator) - return targetBN.mul(numBN).div(denomBN) -} diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js new file mode 100644 index 000000000..29c6d349c --- /dev/null +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -0,0 +1,446 @@ +const Component = require('react').Component +const { connect } = require('react-redux') +const h = require('react-hyperscript') +const inherits = require('util').inherits +const actions = require('../../actions') +const clone = require('clone') +const Identicon = require('../identicon') +const ethUtil = require('ethereumjs-util') +const BN = ethUtil.BN +const hexToBn = require('../../../../app/scripts/lib/hex-to-bn') +const { conversionUtil, addCurrencies } = require('../../conversion-util') + +const MIN_GAS_PRICE_GWEI_BN = new BN(1) +const GWEI_FACTOR = new BN(1e9) +const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR) + +module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmSendEther) + +function mapStateToProps (state) { + const { + conversionRate, + identities, + } = state.metamask + const accounts = state.metamask.accounts + const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] + return { + conversionRate, + identities, + selectedAddress, + } +} + +function mapDispatchToProps (dispatch) { + return { + setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('USD')), + backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)), + cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), + } +} + +inherits(ConfirmSendEther, Component) +function ConfirmSendEther () { + Component.call(this) + this.state = {} + this.onSubmit = this.onSubmit.bind(this) +} + +ConfirmSendEther.prototype.getAmount = function () { + const { conversionRate } = this.props + const txMeta = this.gatherTxMeta() + const txParams = txMeta.txParams || {} + + const USD = conversionUtil(txParams.value, { + fromNumericBase: 'hex', + toNumericBase: 'dec', + fromCurrency: 'ETH', + toCurrency: 'USD', + numberOfDecimals: 2, + fromDenomination: 'WEI', + conversionRate, + }) + const ETH = conversionUtil(txParams.value, { + fromNumericBase: 'hex', + toNumericBase: 'dec', + fromCurrency: 'ETH', + toCurrency: 'ETH', + fromDenomination: 'WEI', + conversionRate, + numberOfDecimals: 6, + }) + + return { + USD, + ETH, + } + +} + +ConfirmSendEther.prototype.getGasFee = function () { + const { conversionRate } = this.props + const txMeta = this.gatherTxMeta() + const txParams = txMeta.txParams || {} + + // Gas + const gas = txParams.gas + const gasBn = hexToBn(gas) + + // From latest master +// const gasLimit = new BN(parseInt(blockGasLimit)) +// const safeGasLimitBN = this.bnMultiplyByFraction(gasLimit, 19, 20) +// const saferGasLimitBN = this.bnMultiplyByFraction(gasLimit, 18, 20) +// const safeGasLimit = safeGasLimitBN.toString(10) + + // Gas Price + const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16) + const gasPriceBn = hexToBn(gasPrice) + + const txFeeBn = gasBn.mul(gasPriceBn) + + const USD = conversionUtil(txFeeBn, { + fromNumericBase: 'BN', + toNumericBase: 'dec', + fromDenomination: 'WEI', + fromCurrency: 'ETH', + toCurrency: 'USD', + numberOfDecimals: 2, + conversionRate, + }) + const ETH = conversionUtil(txFeeBn, { + fromNumericBase: 'BN', + toNumericBase: 'dec', + fromDenomination: 'WEI', + fromCurrency: 'ETH', + toCurrency: 'ETH', + numberOfDecimals: 6, + conversionRate, + }) + + return { + USD, + ETH, + } +} + +ConfirmSendEther.prototype.getData = function () { + const { identities } = this.props + const txMeta = this.gatherTxMeta() + const txParams = txMeta.txParams || {} + const { USD: gasFeeInUSD, ETH: gasFeeInETH } = this.getGasFee() + const { USD: amountInUSD, ETH: amountInETH } = this.getAmount() + + const totalInUSD = addCurrencies(gasFeeInUSD, amountInUSD, { + toNumericBase: 'dec', + numberOfDecimals: 2, + }) + const totalInETH = addCurrencies(gasFeeInETH, amountInETH, { + toNumericBase: 'dec', + numberOfDecimals: 6, + }) + + return { + from: { + address: txParams.from, + name: identities[txParams.from].name, + }, + to: { + address: txParams.to, + name: identities[txParams.to] ? identities[txParams.to].name : 'New Recipient', + }, + memo: txParams.memo || '', + gasFeeInUSD, + gasFeeInETH, + amountInUSD, + amountInETH, + totalInUSD, + totalInETH, + } +} + +ConfirmSendEther.prototype.render = function () { + const { backToAccountDetail, selectedAddress } = this.props + const txMeta = this.gatherTxMeta() + const txParams = txMeta.txParams || {} + + const { + from: { + address: fromAddress, + name: fromName, + }, + to: { + address: toAddress, + name: toName, + }, + memo, + gasFeeInUSD, + gasFeeInETH, + amountInUSD, + totalInUSD, + totalInETH, + } = this.getData() + + // This is from the latest master + // It handles some of the errors that we are not currently handling + // Leaving as comments fo reference + + // const balanceBn = hexToBn(balance) + // const insufficientBalance = balanceBn.lt(maxCost) + // const buyDisabled = insufficientBalance || !this.state.valid || !isValidAddress || this.state.submitting + // const showRejectAll = props.unconfTxListLength > 1 +// const dangerousGasLimit = gasBn.gte(saferGasLimitBN) +// const gasLimitSpecified = txMeta.gasLimitSpecified + + this.inputs = [] + + return ( + h('div.flex-column.flex-grow.confirm-screen-container', { + style: { minWidth: '355px' }, + }, [ + // Main Send token Card + h('div.confirm-screen-wrapper.flex-column.flex-grow', [ + h('h3.flex-center.confirm-screen-header', [ + h('button.confirm-screen-back-button', { + onClick: () => backToAccountDetail(selectedAddress), + }, 'BACK'), + h('div.confirm-screen-title', 'Confirm Transaction'), + ]), + h('div.flex-row.flex-center.confirm-screen-identicons', [ + h('div.confirm-screen-account-wrapper', [ + h( + Identicon, + { + address: fromAddress, + diameter: 100, + }, + ), + h('span.confirm-screen-account-name', fromName), + h('span.confirm-screen-account-number', fromAddress.slice(fromAddress.length - 4)), + ]), + h('i.fa.fa-arrow-right.fa-lg'), + h('div.confirm-screen-account-wrapper', [ + h( + Identicon, + { + address: txParams.to, + diameter: 100, + }, + ), + h('span.confirm-screen-account-name', toName), + h('span.confirm-screen-account-number', toAddress.slice(toAddress.length - 4)), + ]), + ]), + + h('h3.flex-center.confirm-screen-sending-to-message', { + style: { + textAlign: 'center', + fontSize: '16px', + }, + }, [ + `You're sending to Recipient ...${toAddress.slice(toAddress.length - 4)}`, + ]), + + h('h3.flex-center.confirm-screen-send-amount', [`$${amountInUSD}`]), + h('h3.flex-center.confirm-screen-send-amount-currency', [ 'USD' ]), + h('div.flex-center.confirm-memo-wrapper', [ + h('h3.confirm-screen-send-memo', [ memo ]), + ]), + + h('div.confirm-screen-rows', [ + h('section.flex-row.flex-center.confirm-screen-row', [ + h('span.confirm-screen-label.confirm-screen-section-column', [ 'From' ]), + h('div.confirm-screen-section-column', [ + h('div.confirm-screen-row-info', fromName), + h('div.confirm-screen-row-detail', `...${fromAddress.slice(fromAddress.length - 4)}`), + ]), + ]), + + h('section.flex-row.flex-center.confirm-screen-row', [ + h('span.confirm-screen-label.confirm-screen-section-column', [ 'To' ]), + h('div.confirm-screen-section-column', [ + h('div.confirm-screen-row-info', toName), + h('div.confirm-screen-row-detail', `...${toAddress.slice(toAddress.length - 4)}`), + ]), + ]), + + h('section.flex-row.flex-center.confirm-screen-row', [ + h('span.confirm-screen-label.confirm-screen-section-column', [ 'Gas Fee' ]), + h('div.confirm-screen-section-column', [ + h('div.confirm-screen-row-info', `$${gasFeeInUSD} USD`), + + h('div.confirm-screen-row-detail', `${gasFeeInETH} ETH`), + ]), + ]), + + + h('section.flex-row.flex-center.confirm-screen-total-box ', [ + h('div.confirm-screen-section-column', [ + h('span.confirm-screen-label', [ 'Total ' ]), + h('div.confirm-screen-total-box__subtitle', [ 'Amount + Gas' ]), + ]), + + h('div.confirm-screen-section-column', [ + h('div.confirm-screen-row-info', `$${totalInUSD} USD`), + h('div.confirm-screen-row-detail', `${totalInETH} ETH`), + ]), + ]), + ]), + +// These are latest errors handling from master +// Leaving as comments as reference when we start implementing error handling +// h('style', ` +// .conf-buttons button { +// margin-left: 10px; +// text-transform: uppercase; +// } +// `), + +// txMeta.simulationFails ? +// h('.error', { +// style: { +// marginLeft: 50, +// fontSize: '0.9em', +// }, +// }, 'Transaction Error. Exception thrown in contract code.') +// : null, + +// !isValidAddress ? +// h('.error', { +// style: { +// marginLeft: 50, +// fontSize: '0.9em', +// }, +// }, 'Recipient address is invalid. Sending this transaction will result in a loss of ETH.') +// : null, + +// insufficientBalance ? +// h('span.error', { +// style: { +// marginLeft: 50, +// fontSize: '0.9em', +// }, +// }, 'Insufficient balance for transaction') +// : null, + +// // send + cancel +// h('.flex-row.flex-space-around.conf-buttons', { +// style: { +// display: 'flex', +// justifyContent: 'flex-end', +// margin: '14px 25px', +// }, +// }, [ +// h('button', { +// onClick: (event) => { +// this.resetGasFields() +// event.preventDefault() +// }, +// }, 'Reset'), + +// // Accept Button or Buy Button +// insufficientBalance ? h('button.btn-green', { onClick: props.buyEth }, 'Buy Ether') : +// h('input.confirm.btn-green', { +// type: 'submit', +// value: 'SUBMIT', +// style: { marginLeft: '10px' }, +// disabled: buyDisabled, +// }), + +// h('button.cancel.btn-red', { +// onClick: props.cancelTransaction, +// }, 'Reject'), +// ]), +// showRejectAll ? h('.flex-row.flex-space-around.conf-buttons', { +// style: { +// display: 'flex', +// justifyContent: 'flex-end', +// margin: '14px 25px', +// }, +// }, [ +// h('button.cancel.btn-red', { +// onClick: props.cancelAllTransactions, +// }, 'Reject All'), +// ]) : null, +// ]), +// ]) +// ) +// } + ]), + + h('form#pending-tx-form.flex-column.flex-center', { + onSubmit: this.onSubmit, + }, [ + + // Accept Button + h('button.confirm-screen-confirm-button', ['CONFIRM']), + + // Cancel Button + h('div.cancel.btn-light.confirm-screen-cancel-button', { + onClick: (event) => this.cancel(event, txMeta), + }, 'CANCEL'), + ]), + ]) + ) +} + +ConfirmSendEther.prototype.onSubmit = function (event) { + event.preventDefault() + const txMeta = this.gatherTxMeta() + const valid = this.checkValidity() + this.setState({ valid, submitting: true }) + + if (valid && this.verifyGasParams()) { + this.props.sendTransaction(txMeta, event) + } else { + this.props.dispatch(actions.displayWarning('Invalid Gas Parameters')) + this.setState({ submitting: false }) + } +} + +ConfirmSendEther.prototype.cancel = function (event, txMeta) { + event.preventDefault() + this.props.cancelTransaction(txMeta) +} + +ConfirmSendEther.prototype.checkValidity = function () { + const form = this.getFormEl() + const valid = form.checkValidity() + return valid +} + +ConfirmSendEther.prototype.getFormEl = function () { + const form = document.querySelector('form#pending-tx-form') + // Stub out form for unit tests: + if (!form) { + return { checkValidity () { return true } } + } + return form +} + +// After a customizable state value has been updated, +ConfirmSendEther.prototype.gatherTxMeta = function () { + const props = this.props + const state = this.state + const txData = clone(state.txData) || clone(props.txData) + + // log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`) + return txData +} + +ConfirmSendEther.prototype.verifyGasParams = function () { + // We call this in case the gas has not been modified at all + if (!this.state) { return true } + return ( + this._notZeroOrEmptyString(this.state.gas) && + this._notZeroOrEmptyString(this.state.gasPrice) + ) +} + +ConfirmSendEther.prototype._notZeroOrEmptyString = function (obj) { + return obj !== '' && obj !== '0x0' +} + +ConfirmSendEther.prototype.bnMultiplyByFraction = function (targetBN, numerator, denominator) { + const numBN = new BN(numerator) + const denomBN = new BN(denominator) + return targetBN.mul(numBN).div(denomBN) +} diff --git a/ui/app/components/pending-tx/index.js b/ui/app/components/pending-tx/index.js new file mode 100644 index 000000000..3797b5642 --- /dev/null +++ b/ui/app/components/pending-tx/index.js @@ -0,0 +1,103 @@ +const Component = require('react').Component +const { connect } = require('react-redux') +const h = require('react-hyperscript') +const clone = require('clone') +const abi = require('human-standard-token-abi') +const abiDecoder = require('abi-decoder') +abiDecoder.addABI(abi) +const inherits = require('util').inherits +const actions = require('../../actions') +const util = require('../../util') +const ConfirmSendEther = require('./confirm-send-ether') + +const TX_TYPES = { + DEPLOY_CONTRACT: 'deploy_contract', + SEND_ETHER: 'send_ether', + SEND_TOKEN: 'send_token', +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)(PendingTx) + +function mapStateToProps (state) { + const { + conversionRate, + identities, + } = state.metamask + const accounts = state.metamask.accounts + const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] + return { + conversionRate, + identities, + selectedAddress, + } +} + +function mapDispatchToProps (dispatch) { + return { + setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('USD')), + backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)), + cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), + } +} + +inherits(PendingTx, Component) +function PendingTx () { + Component.call(this) + this.state = { + isFetching: true, + transactionType: '', + } +} + +PendingTx.prototype.componentWillMount = function () { + const txMeta = this.gatherTxMeta() + const txParams = txMeta.txParams || {} + + this.props.setCurrentCurrencyToUSD() + + if (txParams.to) { + const token = util.getContractAtAddress(txParams.to) + token + .symbol() + .then(result => { + const symbol = result[0] || null + this.setState({ + transactionType: symbol ? TX_TYPES.SEND_TOKEN : TX_TYPES.SEND_ETHER, + isFetching: false, + }) + }) + .catch(() => this.setState({ + transactionType: TX_TYPES.SEND_ETHER, + isFetching: false, + })) + } else { + this.setState({ + transactionType: TX_TYPES.DEPLOY_CONTRACT, + isFetching: false, + }) + } +} + +PendingTx.prototype.gatherTxMeta = function () { + const props = this.props + const state = this.state + const txData = clone(state.txData) || clone(props.txData) + + return txData +} + +PendingTx.prototype.render = function () { + const { isFetching, transactionType } = this.state + + if (isFetching) { + return h('noscript') + } + + + switch (transactionType) { + case TX_TYPES.SEND_ETHER: + return h(ConfirmSendEther, { txData: this.gatherTxMeta() }) + default: + return h('noscript') + } +} -- cgit v1.2.3 From fe37dd7ecd142bbb0b51d62abfdc0a25240aef42 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 22 Sep 2017 01:56:10 -0230 Subject: Open account details modal on buy -> direct deposit. --- ui/app/components/modals/buy-options-modal.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/buy-options-modal.js b/ui/app/components/modals/buy-options-modal.js index 79bbc798b..a8033d288 100644 --- a/ui/app/components/modals/buy-options-modal.js +++ b/ui/app/components/modals/buy-options-modal.js @@ -19,6 +19,9 @@ function mapDispatchToProps (dispatch) { hideModal: () => { dispatch(actions.hideModal()) }, + showAccountDetailModal: () => { + dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' })) + }, } } @@ -59,7 +62,9 @@ BuyOptions.prototype.render = function () { h('div.buy-modal-content-option-subtitle', {}, 'Trade any digital asset for any other'), ]), - h('div.buy-modal-content-option', {}, [ + h('div.buy-modal-content-option', { + onClick: () => this.goToAccountDetailsModal() + }, [ h('div.buy-modal-content-option-title', {}, 'Direct Deposit'), h('div.buy-modal-content-option-subtitle', {}, 'Deposit from another account'), ]), @@ -75,3 +80,8 @@ BuyOptions.prototype.render = function () { ]), ]) } + +BuyOptions.prototype.goToAccountDetailsModal = function () { + this.props.hideModal() + this.props.showAccountDetailModal() +} -- cgit v1.2.3 From 48867d95fe1a064683f96ad60fd36c893500f62c Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 19 Sep 2017 22:46:51 -0230 Subject: ReadOnlyInput component. --- ui/app/components/qr-code.js | 18 ++++++------------ ui/app/components/readonly-input.js | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 12 deletions(-) create mode 100644 ui/app/components/readonly-input.js (limited to 'ui/app/components') diff --git a/ui/app/components/qr-code.js b/ui/app/components/qr-code.js index dca5c8c47..cc723df14 100644 --- a/ui/app/components/qr-code.js +++ b/ui/app/components/qr-code.js @@ -4,6 +4,7 @@ const qrCode = require('qrcode-npm').qrcode const inherits = require('util').inherits const connect = require('react-redux').connect const isHexPrefixed = require('ethereumjs-util').isHexPrefixed +const ReadOnlyInput = require('./readonly-input') module.exports = connect(mapStateToProps)(QrCodeView) @@ -46,18 +47,11 @@ QrCodeView.prototype.render = function () { __html: qrImage.createTableTag(4), }, }), - h('.div.ellip-address-wrapper', [ - h('input.qr-ellip-address', { - style: { - width: '247px', - }, - value: Qr.data, - readOnly: true, - }), - // h(CopyButton, { - // value: Qr.data, - // }), - ]), + h(ReadOnlyInput, { + wrapperClass: 'ellip-address-wrapper', + inputClass: 'qr-ellip-address', + value: Qr.data, + }), ]) } diff --git a/ui/app/components/readonly-input.js b/ui/app/components/readonly-input.js new file mode 100644 index 000000000..b688e0722 --- /dev/null +++ b/ui/app/components/readonly-input.js @@ -0,0 +1,27 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits + +module.exports = ReadOnlyInput + +inherits(ReadOnlyInput, Component) +function ReadOnlyInput () { + Component.call(this) +} + +ReadOnlyInput.prototype.render = function () { + const { + wrapperClass, + inputClass, + value, + } = this.props + + return h('div', {className: wrapperClass}, [ + h('input', { + className: inputClass, + value, + readOnly: true, + }), + ]) +} + -- cgit v1.2.3 From e325e5e2f5f9d09ade29bc86ec160b6da0eb6b71 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 22 Sep 2017 17:31:32 -0230 Subject: Default class params to empty string in readonly-input --- ui/app/components/readonly-input.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/readonly-input.js b/ui/app/components/readonly-input.js index b688e0722..934cbefae 100644 --- a/ui/app/components/readonly-input.js +++ b/ui/app/components/readonly-input.js @@ -11,8 +11,8 @@ function ReadOnlyInput () { ReadOnlyInput.prototype.render = function () { const { - wrapperClass, - inputClass, + wrapperClass = '', + inputClass = '', value, } = this.props -- cgit v1.2.3 From a1d72a59fe5b03363820d6e1ac2c383ec15ccbcb Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 22 Sep 2017 04:29:27 -0230 Subject: New account modal now allows for addition of account name. --- ui/app/components/modals/new-account-modal.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/new-account-modal.js b/ui/app/components/modals/new-account-modal.js index 910f3c0ca..1adc9e7c7 100644 --- a/ui/app/components/modals/new-account-modal.js +++ b/ui/app/components/modals/new-account-modal.js @@ -8,6 +8,7 @@ function mapStateToProps (state) { return { network: state.metamask.network, address: state.metamask.selectedAddress, + identities: state.metamask.identities, } } @@ -19,9 +20,12 @@ function mapDispatchToProps (dispatch) { hideModal: () => { dispatch(actions.hideModal()) }, - createAccount: () => { - dispatch(actions.addNewAccount()) - dispatch(actions.hideModal()) + createAccount: (identities, newAccountName) => { + dispatch(actions.addNewAccount(identities)) + .then((newAccountAddress) => { + dispatch(actions.saveAccountLabel(newAccountAddress, newAccountName)) + dispatch(actions.hideModal()) + }) }, } } @@ -29,11 +33,18 @@ function mapDispatchToProps (dispatch) { inherits(NewAccountModal, Component) function NewAccountModal () { Component.call(this) + + this.state = { + newAccountName: '' + } } module.exports = connect(mapStateToProps, mapDispatchToProps)(NewAccountModal) NewAccountModal.prototype.render = function () { + const { identities } = this.props + const { newAccountName } = this.state + return h('div', {}, [ h('div.new-account-modal-wrapper', { }, [ @@ -52,6 +63,7 @@ NewAccountModal.prototype.render = function () { h('div.new-account-input-wrapper', {}, [ h('input.new-account-input', { placeholder: 'E.g. My new account', + onChange: (event) => this.setState({ newAccountName: event.target.value }) }, []), ]), @@ -65,7 +77,7 @@ NewAccountModal.prototype.render = function () { h('div.new-account-modal-content.button', {}, [ h('button.btn-clear', { - onClick: this.props.createAccount + onClick: () => this.props.createAccount(identities, newAccountName) }, [ 'SAVE', ]), -- cgit v1.2.3 From 13f22ff6b087f3865f84a0672a9013ada88be61a Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 22 Sep 2017 18:30:00 -0230 Subject: get identities from getState() instead of passing from caller, only set new account label if label set. --- ui/app/components/modals/new-account-modal.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/new-account-modal.js b/ui/app/components/modals/new-account-modal.js index 1adc9e7c7..25beb6745 100644 --- a/ui/app/components/modals/new-account-modal.js +++ b/ui/app/components/modals/new-account-modal.js @@ -8,7 +8,6 @@ function mapStateToProps (state) { return { network: state.metamask.network, address: state.metamask.selectedAddress, - identities: state.metamask.identities, } } @@ -20,10 +19,12 @@ function mapDispatchToProps (dispatch) { hideModal: () => { dispatch(actions.hideModal()) }, - createAccount: (identities, newAccountName) => { - dispatch(actions.addNewAccount(identities)) + createAccount: (newAccountName) => { + dispatch(actions.addNewAccount()) .then((newAccountAddress) => { - dispatch(actions.saveAccountLabel(newAccountAddress, newAccountName)) + if (newAccountName) { + dispatch(actions.saveAccountLabel(newAccountAddress, newAccountName)) + } dispatch(actions.hideModal()) }) }, @@ -42,7 +43,6 @@ function NewAccountModal () { module.exports = connect(mapStateToProps, mapDispatchToProps)(NewAccountModal) NewAccountModal.prototype.render = function () { - const { identities } = this.props const { newAccountName } = this.state return h('div', {}, [ @@ -77,7 +77,7 @@ NewAccountModal.prototype.render = function () { h('div.new-account-modal-content.button', {}, [ h('button.btn-clear', { - onClick: () => this.props.createAccount(identities, newAccountName) + onClick: () => this.props.createAccount(newAccountName) }, [ 'SAVE', ]), -- cgit v1.2.3 From e1077836ce916e2bd788451e3f365324024a1c0c Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Fri, 22 Sep 2017 14:34:56 -0700 Subject: Add Confirm Send token screen --- ui/app/components/pending-tx/confirm-send-ether.js | 2 +- ui/app/components/pending-tx/confirm-send-token.js | 394 +++++++++++++++++++++ ui/app/components/pending-tx/index.js | 73 +++- ui/app/components/send-token/index.js | 18 +- 4 files changed, 453 insertions(+), 34 deletions(-) create mode 100644 ui/app/components/pending-tx/confirm-send-token.js (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 29c6d349c..b03ec0552 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -49,7 +49,7 @@ ConfirmSendEther.prototype.getAmount = function () { const { conversionRate } = this.props const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} - + console.log(txParams) const USD = conversionUtil(txParams.value, { fromNumericBase: 'hex', toNumericBase: 'dec', diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js new file mode 100644 index 000000000..384ac92cc --- /dev/null +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -0,0 +1,394 @@ +const Component = require('react').Component +const { connect } = require('react-redux') +const h = require('react-hyperscript') +const inherits = require('util').inherits +const abi = require('human-standard-token-abi') +const abiDecoder = require('abi-decoder') +abiDecoder.addABI(abi) +const actions = require('../../actions') +const clone = require('clone') +const Identicon = require('../identicon') +const ethUtil = require('ethereumjs-util') +const BN = ethUtil.BN +const hexToBn = require('../../../../app/scripts/lib/hex-to-bn') +const { conversionUtil } = require('../../conversion-util') + +const MIN_GAS_PRICE_GWEI_BN = new BN(1) +const GWEI_FACTOR = new BN(1e9) +const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR) + +module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmSendToken) + +function mapStateToProps (state, ownProps) { + const { token: { symbol }, txData } = ownProps + const { txParams } = txData || {} + const tokenData = txParams.data && abiDecoder.decodeMethod(txParams.data) + const { + conversionRate, + identities, + } = state.metamask + const accounts = state.metamask.accounts + const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] + const tokenExchangeRates = state.metamask.tokenExchangeRates + const pair = `${symbol.toLowerCase()}_eth` + const { rate: tokenExchangeRate = 0 } = tokenExchangeRates[pair] || {} + + return { + conversionRate, + identities, + selectedAddress, + tokenExchangeRate, + tokenData: tokenData || {}, + } +} + +function mapDispatchToProps (dispatch, ownProps) { + const { token: { symbol } } = ownProps + + return { + backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)), + cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), + updateTokenExchangeRate: () => dispatch(actions.updateTokenExchangeRate(symbol)), + } +} + +inherits(ConfirmSendToken, Component) +function ConfirmSendToken () { + Component.call(this) + this.state = {} + this.onSubmit = this.onSubmit.bind(this) +} + +ConfirmSendToken.prototype.componentWillMount = function () { + this.props.updateTokenExchangeRate() +} + +ConfirmSendToken.prototype.getAmount = function () { + const { conversionRate, tokenExchangeRate, token, tokenData } = this.props + const { params = [] } = tokenData + const { value } = params[1] || {} + const { decimals } = token + const multiplier = Math.pow(10, Number(decimals || 0)) + const sendTokenAmount = Number(value / multiplier) + + return { + fiat: tokenExchangeRate + ? +(sendTokenAmount * tokenExchangeRate * conversionRate).toFixed(2) + : null, + token: +sendTokenAmount.toFixed(decimals), + } + +} + +ConfirmSendToken.prototype.getGasFee = function () { + const { conversionRate, tokenExchangeRate, token } = this.props + const txMeta = this.gatherTxMeta() + const txParams = txMeta.txParams || {} + const { decimals } = token + + // Gas + const gas = txParams.gas + const gasBn = hexToBn(gas) + + // Gas Price + const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16) + const gasPriceBn = hexToBn(gasPrice) + const txFeeBn = gasBn.mul(gasPriceBn) + + + const USD = conversionUtil(txFeeBn, { + fromNumericBase: 'BN', + toNumericBase: 'dec', + fromDenomination: 'WEI', + fromCurrency: 'ETH', + toCurrency: 'USD', + numberOfDecimals: 2, + conversionRate, + }) + const ETH = conversionUtil(txFeeBn, { + fromNumericBase: 'BN', + toNumericBase: 'dec', + fromDenomination: 'WEI', + fromCurrency: 'ETH', + toCurrency: 'ETH', + numberOfDecimals: 6, + conversionRate, + }) + + return { + fiat: +Number(USD).toFixed(2), + eth: ETH, + token: tokenExchangeRate + ? +(ETH * tokenExchangeRate).toFixed(decimals) + : null, + } +} + +ConfirmSendToken.prototype.getData = function () { + const { identities } = this.props + const txMeta = this.gatherTxMeta() + const txParams = txMeta.txParams || {} + + return { + from: { + address: txParams.from, + name: identities[txParams.from].name, + }, + to: { + address: txParams.to, + name: identities[txParams.to] ? identities[txParams.to].name : 'New Recipient', + }, + memo: txParams.memo || '', + } +} + +ConfirmSendToken.prototype.renderHeroAmount = function () { + const { token: { symbol } } = this.props + const { fiat: fiatAmount, token: tokenAmount } = this.getAmount() + const txMeta = this.gatherTxMeta() + const txParams = txMeta.txParams || {} + const { memo = '' } = txParams + + return fiatAmount + ? ( + h('div.confirm-send-token__hero-amount-wrapper', [ + h('h3.flex-center.confirm-screen-send-amount', `$${fiatAmount}`), + h('h3.flex-center.confirm-screen-send-amount-currency', 'USD'), + h('div.flex-center.confirm-memo-wrapper', [ + h('h3.confirm-screen-send-memo', memo), + ]), + ]) + ) + : ( + h('div.confirm-send-token__hero-amount-wrapper', [ + h('h3.flex-center.confirm-screen-send-amount', tokenAmount), + h('h3.flex-center.confirm-screen-send-amount-currency', symbol), + h('div.flex-center.confirm-memo-wrapper', [ + h('h3.confirm-screen-send-memo', memo), + ]), + ]) + ) +} + +ConfirmSendToken.prototype.renderGasFee = function () { + const { token: { symbol } } = this.props + const { fiat: fiatGas, token: tokenGas, eth: ethGas } = this.getGasFee() + + return ( + h('section.flex-row.flex-center.confirm-screen-row', [ + h('span.confirm-screen-label.confirm-screen-section-column', [ 'Gas Fee' ]), + h('div.confirm-screen-section-column', [ + h('div.confirm-screen-row-info', `$${fiatGas} USD`), + + h( + 'div.confirm-screen-row-detail', + tokenGas ? `${tokenGas} ${symbol}` : `${ethGas} ETH` + ), + ]), + ]) + ) +} + +ConfirmSendToken.prototype.renderTotalPlusGas = function () { + const { token: { symbol } } = this.props + const { fiat: fiatAmount, token: tokenAmount } = this.getAmount() + const { fiat: fiatGas, token: tokenGas } = this.getGasFee() + + return fiatAmount && fiatGas + ? ( + h('section.flex-row.flex-center.confirm-screen-total-box ', [ + h('div.confirm-screen-section-column', [ + h('span.confirm-screen-label', [ 'Total ' ]), + h('div.confirm-screen-total-box__subtitle', [ 'Amount + Gas' ]), + ]), + + h('div.confirm-screen-section-column', [ + h('div.confirm-screen-row-info', `$${fiatAmount + fiatGas} USD`), + h('div.confirm-screen-row-detail', `${tokenAmount + tokenGas} ${symbol}`), + ]), + ]) + ) + : ( + h('section.flex-row.flex-center.confirm-screen-total-box ', [ + h('div.confirm-screen-section-column', [ + h('span.confirm-screen-label', [ 'Total ' ]), + h('div.confirm-screen-total-box__subtitle', [ 'Amount + Gas' ]), + ]), + + h('div.confirm-screen-section-column', [ + h('div.confirm-screen-row-info', `${tokenAmount} ${symbol}`), + h('div.confirm-screen-row-detail', `+ ${fiatGas} USD Gas`), + ]), + ]) + ) +} + +ConfirmSendToken.prototype.render = function () { + const { backToAccountDetail, selectedAddress } = this.props + const txMeta = this.gatherTxMeta() + const txParams = txMeta.txParams || {} + + const { + from: { + address: fromAddress, + name: fromName, + }, + to: { + address: toAddress, + name: toName, + }, + } = this.getData() + + this.inputs = [] + + return ( + h('div.flex-column.flex-grow.confirm-screen-container', { + style: { minWidth: '355px' }, + }, [ + // Main Send token Card + h('div.confirm-screen-wrapper.flex-column.flex-grow', [ + h('h3.flex-center.confirm-screen-header', [ + h('button.confirm-screen-back-button', { + onClick: () => backToAccountDetail(selectedAddress), + }, 'BACK'), + h('div.confirm-screen-title', 'Confirm Transaction'), + ]), + h('div.flex-row.flex-center.confirm-screen-identicons', [ + h('div.confirm-screen-account-wrapper', [ + h( + Identicon, + { + address: fromAddress, + diameter: 100, + }, + ), + h('span.confirm-screen-account-name', fromName), + h('span.confirm-screen-account-number', fromAddress.slice(fromAddress.length - 4)), + ]), + h('i.fa.fa-arrow-right.fa-lg'), + h('div.confirm-screen-account-wrapper', [ + h( + Identicon, + { + address: txParams.to, + diameter: 100, + }, + ), + h('span.confirm-screen-account-name', toName), + h('span.confirm-screen-account-number', toAddress.slice(toAddress.length - 4)), + ]), + ]), + + h('h3.flex-center.confirm-screen-sending-to-message', { + style: { + textAlign: 'center', + fontSize: '16px', + }, + }, [ + `You're sending to Recipient ...${toAddress.slice(toAddress.length - 4)}`, + ]), + + this.renderHeroAmount(), + + h('div.confirm-screen-rows', [ + h('section.flex-row.flex-center.confirm-screen-row', [ + h('span.confirm-screen-label.confirm-screen-section-column', [ 'From' ]), + h('div.confirm-screen-section-column', [ + h('div.confirm-screen-row-info', fromName), + h('div.confirm-screen-row-detail', `...${fromAddress.slice(fromAddress.length - 4)}`), + ]), + ]), + + h('section.flex-row.flex-center.confirm-screen-row', [ + h('span.confirm-screen-label.confirm-screen-section-column', [ 'To' ]), + h('div.confirm-screen-section-column', [ + h('div.confirm-screen-row-info', toName), + h('div.confirm-screen-row-detail', `...${toAddress.slice(toAddress.length - 4)}`), + ]), + ]), + + this.renderGasFee(), + + this.renderTotalPlusGas(), + + ]), + ]), + + h('form#pending-tx-form.flex-column.flex-center', { + onSubmit: this.onSubmit, + }, [ + + // Accept Button + h('button.confirm-screen-confirm-button', ['CONFIRM']), + + // Cancel Button + h('div.cancel.btn-light.confirm-screen-cancel-button', { + onClick: (event) => this.cancel(event, txMeta), + }, 'CANCEL'), + ]), + ]) + ) +} + +ConfirmSendToken.prototype.onSubmit = function (event) { + event.preventDefault() + const txMeta = this.gatherTxMeta() + const valid = this.checkValidity() + this.setState({ valid, submitting: true }) + + if (valid && this.verifyGasParams()) { + this.props.sendTransaction(txMeta, event) + } else { + this.props.dispatch(actions.displayWarning('Invalid Gas Parameters')) + this.setState({ submitting: false }) + } +} + +ConfirmSendToken.prototype.cancel = function (event, txMeta) { + event.preventDefault() + this.props.cancelTransaction(txMeta) +} + +ConfirmSendToken.prototype.checkValidity = function () { + const form = this.getFormEl() + const valid = form.checkValidity() + return valid +} + +ConfirmSendToken.prototype.getFormEl = function () { + const form = document.querySelector('form#pending-tx-form') + // Stub out form for unit tests: + if (!form) { + return { checkValidity () { return true } } + } + return form +} + +// After a customizable state value has been updated, +ConfirmSendToken.prototype.gatherTxMeta = function () { + const props = this.props + const state = this.state + const txData = clone(state.txData) || clone(props.txData) + + // log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`) + return txData +} + +ConfirmSendToken.prototype.verifyGasParams = function () { + // We call this in case the gas has not been modified at all + if (!this.state) { return true } + return ( + this._notZeroOrEmptyString(this.state.gas) && + this._notZeroOrEmptyString(this.state.gasPrice) + ) +} + +ConfirmSendToken.prototype._notZeroOrEmptyString = function (obj) { + return obj !== '' && obj !== '0x0' +} + +ConfirmSendToken.prototype.bnMultiplyByFraction = function (targetBN, numerator, denominator) { + const numBN = new BN(numerator) + const denomBN = new BN(denominator) + return targetBN.mul(numBN).div(denomBN) +} diff --git a/ui/app/components/pending-tx/index.js b/ui/app/components/pending-tx/index.js index 3797b5642..915319958 100644 --- a/ui/app/components/pending-tx/index.js +++ b/ui/app/components/pending-tx/index.js @@ -9,6 +9,7 @@ const inherits = require('util').inherits const actions = require('../../actions') const util = require('../../util') const ConfirmSendEther = require('./confirm-send-ether') +const ConfirmSendToken = require('./confirm-send-token') const TX_TYPES = { DEPLOY_CONTRACT: 'deploy_contract', @@ -46,33 +47,51 @@ function PendingTx () { this.state = { isFetching: true, transactionType: '', + tokenAddress: '', + tokenSymbol: '', + tokenDecimals: '', } } -PendingTx.prototype.componentWillMount = function () { +PendingTx.prototype.componentWillMount = async function () { const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} this.props.setCurrentCurrencyToUSD() - if (txParams.to) { + if (!txParams.to) { + return this.setState({ + transactionType: TX_TYPES.DEPLOY_CONTRACT, + isFetching: false, + }) + } + + try { const token = util.getContractAtAddress(txParams.to) - token - .symbol() - .then(result => { - const symbol = result[0] || null + const results = await Promise.all([ + token.symbol(), + token.decimals(), + ]) + + const [ symbol, decimals ] = results + + if (symbol[0] && decimals[0]) { this.setState({ - transactionType: symbol ? TX_TYPES.SEND_TOKEN : TX_TYPES.SEND_ETHER, + transactionType: TX_TYPES.SEND_TOKEN, + tokenAddress: txParams.to, + tokenSymbol: symbol[0], + tokenDecimals: decimals[0], isFetching: false, }) - }) - .catch(() => this.setState({ - transactionType: TX_TYPES.SEND_ETHER, - isFetching: false, - })) - } else { + } else { + this.setState({ + transactionType: TX_TYPES.SEND_ETHER, + isFetching: false, + }) + } + } catch (e) { this.setState({ - transactionType: TX_TYPES.DEPLOY_CONTRACT, + transactionType: TX_TYPES.SEND_ETHER, isFetching: false, }) } @@ -87,16 +106,36 @@ PendingTx.prototype.gatherTxMeta = function () { } PendingTx.prototype.render = function () { - const { isFetching, transactionType } = this.state + const { + isFetching, + transactionType, + tokenAddress, + tokenSymbol, + tokenDecimals, + } = this.state + + const { sendTransaction } = this.props if (isFetching) { return h('noscript') } - switch (transactionType) { case TX_TYPES.SEND_ETHER: - return h(ConfirmSendEther, { txData: this.gatherTxMeta() }) + return h(ConfirmSendEther, { + txData: this.gatherTxMeta(), + sendTransaction, + }) + case TX_TYPES.SEND_TOKEN: + return h(ConfirmSendToken, { + txData: this.gatherTxMeta(), + sendTransaction, + token: { + address: tokenAddress, + symbol: tokenSymbol, + decimals: tokenDecimals, + }, + }) default: return h('noscript') } diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 7adbf48dc..dd8ca6b9d 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -1,7 +1,6 @@ const Component = require('react').Component const connect = require('react-redux').connect const h = require('react-hyperscript') -const { addHexPrefix } = require('ethereumjs-util') const classnames = require('classnames') const inherits = require('util').inherits const actions = require('../../actions') @@ -26,20 +25,15 @@ function mapStateToProps (state) { const conversionRate = state.metamask.conversionRate const currentBlockGasLimit = state.metamask.currentBlockGasLimit const accounts = state.metamask.accounts - // const network = state.metamask.network const selectedTokenAddress = state.metamask.selectedTokenAddress const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] const selectedToken = selectors.getSelectedToken(state) const tokenExchangeRates = state.metamask.tokenExchangeRates const pair = `${selectedToken.symbol.toLowerCase()}_eth` const { rate: tokenExchangeRate = 0 } = tokenExchangeRates[pair] || {} - // const checksumAddress = selectedAddress && ethUtil.toChecksumAddress(selectedAddress) - // const identity = identities[selectedAddress] return { - // sidebarOpen, selectedAddress, - // checksumAddress, selectedTokenAddress, identities, addressBook, @@ -48,9 +42,6 @@ function mapStateToProps (state) { currentBlockGasLimit, selectedToken, warning, - // selectedToken: selectors.getSelectedToken(state), - // identity, - // network, } } @@ -66,11 +57,6 @@ function mapDispatchToProps (dispatch) { dispatch(actions.signTokenTx(tokenAddress, toAddress, amount, txData)) ), updateTokenExchangeRate: token => dispatch(actions.updateTokenExchangeRate(token)), - // showSidebar: () => { dispatch(actions.showSidebar()) }, - // hideSidebar: () => { dispatch(actions.hideSidebar()) }, - // showModal: (payload) => { dispatch(actions.showModal(payload)) }, - // showSendPage: () => { dispatch(actions.showSendPage()) }, - // showSendTokenPage: () => { dispatch(actions.showSendTokenPage()) }, } } @@ -116,7 +102,7 @@ SendTokenScreen.prototype.validate = function () { gasLimit: !gasLimit ? 'Gas Limit Required' : null, } - if(to && !isValidAddress(to)) { + if (to && !isValidAddress(to)) { errors.to = 'Invalid address' } @@ -360,7 +346,7 @@ SendTokenScreen.prototype.render = function () { this.renderAmountInput(), this.renderGasInput(), this.renderMemoInput(), - warning && h('div.send-screen-input-wrapper--error', {}, + warning && h('div.send-screen-input-wrapper--error', h('div.send-screen-input-wrapper__error-message', [ warning, ]) -- cgit v1.2.3 From 0eeba3771c2396c12de3f254dbfaae957344411d Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 20 Sep 2017 05:35:27 -0230 Subject: Exports private key modal opens from dropdown. --- .../dropdowns/components/account-dropdowns.js | 8 ++--- .../components/modals/export-private-key-modal.js | 41 +++++++++++++++++++++ ui/app/components/modals/modal.js | 42 ++++++++++++++-------- 3 files changed, 72 insertions(+), 19 deletions(-) create mode 100644 ui/app/components/modals/export-private-key-modal.js (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index e2d3d6d64..76f186a3f 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -337,9 +337,7 @@ class AccountDropdowns extends Component { DropdownMenuItem, { closeMenu: () => {}, - onClick: () => { - actions.requestAccountExport() - }, + onClick: () => this.props.actions.showExportPrivateKeyModal(), style: Object.assign( dropdownMenuItemStyle, menuItemStyles, @@ -429,7 +427,6 @@ const mapDispatchToProps = (dispatch) => { return { actions: { showConfigPage: () => dispatch(actions.showConfigPage()), - requestAccountExport: () => dispatch(actions.requestExportAccount()), showAccountDetail: (address) => dispatch(actions.showAccountDetail(address)), showAccountDetailModal: () => { dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' })) @@ -443,6 +440,9 @@ const mapDispatchToProps = (dispatch) => { showNewAccountModal: () => { dispatch(actions.showModal({ name: 'NEW_ACCOUNT' })) }, + showExportPrivateKeyModal: () => { + dispatch(actions.showModal({ name: 'EXPORT_PRIVATE_KEY' })) + }, showAddTokenPage: () => { dispatch(actions.showAddTokenPage()) }, diff --git a/ui/app/components/modals/export-private-key-modal.js b/ui/app/components/modals/export-private-key-modal.js new file mode 100644 index 000000000..bbcd25e0d --- /dev/null +++ b/ui/app/components/modals/export-private-key-modal.js @@ -0,0 +1,41 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const connect = require('react-redux').connect +const actions = require('../../actions') +const AccountModalContainer = require('./account-modal-container') +const { getSelectedIdentity } = require('../../selectors') +const ReadOnlyInput = require('../readonly-input') + +function mapStateToProps (state) { + return { + network: state.metamask.network, + selectedIdentity: getSelectedIdentity(state), + } +} + +inherits(ExportPrivateKeyModal, Component) +function ExportPrivateKeyModal () { + Component.call(this) +} + +module.exports = connect(mapStateToProps)(ExportPrivateKeyModal) + +ExportPrivateKeyModal.prototype.render = function () { + const { selectedIdentity, network } = this.props + const { name, address } = selectedIdentity + + return h(AccountModalContainer, {}, [ + + h('span.account-name', name), + + h(ReadOnlyInput, { + wrapperClass: 'ellip-address-wrapper', + inputClass: 'ellip-address', + value: address, + }), + + h('div.account-modal-divider'), + + ]) +} diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 04a2f5f40..138efc3ea 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -11,8 +11,27 @@ const isPopupOrNotification = require('../../../../app/scripts/lib/is-popup-or-n const BuyOptions = require('./buy-options-modal') const AccountDetailsModal = require('./account-details-modal') const EditAccountNameModal = require('./edit-account-name-modal') +const ExportPrivateKeyModal = require('./export-private-key-modal') const NewAccountModal = require('./new-account-modal') +const accountModalStyle = { + mobileModalStyle: { + width: '95%', + top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh', + boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', + borderRadius: '4px', + }, + laptopModalStyle: { + width: '360px', + top: 'calc(33% + 45px)', + boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', + borderRadius: '4px', + }, + contentStyle: { + borderRadius: '4px', + }, +} + const MODALS = { BUY: { contents: [ @@ -51,21 +70,14 @@ const MODALS = { contents: [ h(AccountDetailsModal, {}, []), ], - mobileModalStyle: { - width: '95%', - top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh', - boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', - borderRadius: '4px', - }, - laptopModalStyle: { - width: '360px', - top: 'calc(33% + 45px)', - boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', - borderRadius: '4px', - }, - contentStyle: { - borderRadius: '4px', - }, + ...accountModalStyle, + }, + + EXPORT_PRIVATE_KEY: { + contents: [ + h(ExportPrivateKeyModal, {}, []), + ], + ...accountModalStyle, }, NEW_ACCOUNT: { -- cgit v1.2.3 From 171d38c8dbbe78c206e57c5d838ab672ef61f23b Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 20 Sep 2017 20:34:03 -0230 Subject: Handles errors with to field and renders warnings from backend in send token. --- ui/app/components/send-token/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index dd8ca6b9d..8dd277f1d 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -346,7 +346,7 @@ SendTokenScreen.prototype.render = function () { this.renderAmountInput(), this.renderGasInput(), this.renderMemoInput(), - warning && h('div.send-screen-input-wrapper--error', + warning && h('div.send-screen-input-wrapper--error', {}, h('div.send-screen-input-wrapper__error-message', [ warning, ]) -- cgit v1.2.3 From a1d87b821b7e0a444257065d284b13f98e4d3173 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 25 Sep 2017 21:45:51 -0230 Subject: Update send token to handle errors onBlur events and prevent clicking send until all errors handled --- ui/app/components/send-token/index.js | 71 +++++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 12 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 8dd277f1d..166088898 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -5,7 +5,7 @@ const classnames = require('classnames') const inherits = require('util').inherits const actions = require('../../actions') const selectors = require('../../selectors') -const { isValidAddress } = require('../../util') +const { isValidAddress, allNull } = require('../../util') // const BalanceComponent = require('./balance-component') const Identicon = require('../identicon') @@ -65,7 +65,8 @@ function SendTokenScreen () { Component.call(this) this.state = { to: '', - amount: '', + amount: '0x0', + amountToSend: '0x0', selectedCurrency: 'USD', isGasTooltipOpen: false, gasPrice: '0x5d21dba00', @@ -113,6 +114,46 @@ SendTokenScreen.prototype.validate = function () { } } +SendTokenScreen.prototype.setErrorsFor = function (field) { + const { balance, selectedToken } = this.props + const { errors: previousErrors } = this.state + + const { + isValid, + errors: newErrors + } = this.validate() + + const nextErrors = Object.assign({}, previousErrors, { + [field]: newErrors[field] || null + }) + + if (!isValid) { + this.setState({ + errors: nextErrors, + isValid, + }) + } +} + +SendTokenScreen.prototype.clearErrorsFor = function (field) { + const { errors: previousErrors } = this.state + const nextErrors = Object.assign({}, previousErrors, { + [field]: null + }) + + this.setState({ + errors: nextErrors, + isValid: allNull(nextErrors), + }) +} + +SendTokenScreen.prototype.getAmountToSend = function (amount, selectedToken) { + const { decimals } = selectedToken || {} + const multiplier = Math.pow(10, Number(decimals || 0)) + const sendAmount = Number(amount * multiplier).toString(16) + return sendAmount +} + SendTokenScreen.prototype.submit = function () { const { to, @@ -132,11 +173,6 @@ SendTokenScreen.prototype.submit = function () { } = this.props const { nickname = ' ' } = identities[to] || {} - const { isValid, errors } = this.validate() - - if (!isValid) { - return this.setState({ errors }) - } hideWarning() addToAddressBook(to, nickname) @@ -148,9 +184,7 @@ SendTokenScreen.prototype.submit = function () { gasPrice: gasPrice, } - const { decimals } = selectedToken || {} - const multiplier = Math.pow(10, Number(decimals || 0)) - const sendAmount = Number(amount * multiplier).toString(16) + const sendAmount = this.getAmountToSend(amount, selectedToken) signTokenTx(selectedTokenAddress, to, sendAmount, txParams) } @@ -181,6 +215,8 @@ SendTokenScreen.prototype.renderToAddressInput = function () { to: e.target.value, errors: {}, }), + onBlur: () => this.setErrorsFor('to'), + onFocus: () => this.clearErrorsFor('to'), }), h('datalist#addresses', [ // Corresponds to the addresses owned. @@ -234,8 +270,9 @@ SendTokenScreen.prototype.renderAmountInput = function () { value: amount, onChange: e => this.setState({ amount: e.target.value, - errors: {}, }), + onBlur: () => this.setErrorsFor('amount'), + onFocus: () => this.clearErrorsFor('amount'), }), h('div.send-screen-input-wrapper__error-message', [ errorMessage ]), ]) @@ -272,6 +309,14 @@ SendTokenScreen.prototype.renderGasInput = function () { onFeeChange: ({ gasLimit, gasPrice }) => { this.setState({ gasLimit, gasPrice, errors: {} }) }, + onBlur: () => { + this.setErrorsFor('gasLimit') + this.setErrorsFor('gasPrice') + }, + onFocus: () => { + this.clearErrorsFor('gasLimit') + this.clearErrorsFor('gasPrice') + }, }), h('div.send-screen-gas-labels', {}, [ @@ -311,10 +356,12 @@ SendTokenScreen.prototype.renderMemoInput = function () { SendTokenScreen.prototype.renderButtons = function () { const { selectedAddress, backToAccountDetail } = this.props + const { isValid } = this.validate() return h('div.send-token__button-group', [ h('button.send-token__button-next.btn-secondary', { - onClick: () => this.submit(), + className: !isValid && 'send-screen__send-button__disabled', + onClick: () => isValid && this.submit(), }, ['Next']), h('button.send-token__button-cancel.btn-tertiary', { onClick: () => backToAccountDetail(selectedAddress), -- cgit v1.2.3 From fc3e071ad699f6c3586a20f12e06e6f456b0eea3 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 25 Sep 2017 22:09:10 -0230 Subject: Send token now estimates gas and price. --- ui/app/components/send-token/index.js | 45 ++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 8 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 166088898..e4f13a874 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -57,6 +57,9 @@ function mapDispatchToProps (dispatch) { dispatch(actions.signTokenTx(tokenAddress, toAddress, amount, txData)) ), updateTokenExchangeRate: token => dispatch(actions.updateTokenExchangeRate(token)), + estimateGas: ({ to, amount }) => dispatch(actions.estimateGas({ to, amount })), + getGasPrice: () => dispatch(actions.getGasPrice()), + } } @@ -69,8 +72,8 @@ function SendTokenScreen () { amountToSend: '0x0', selectedCurrency: 'USD', isGasTooltipOpen: false, - gasPrice: '0x5d21dba00', - gasLimit: '0x7b0d', + gasPrice: null, + gasLimit: null, errors: {}, } } @@ -84,6 +87,24 @@ SendTokenScreen.prototype.componentWillMount = function () { updateTokenExchangeRate(symbol) } +SendTokenScreen.prototype.estimateGasAndPrice = function () { + const { selectedToken } = this.props + const { errors, amount, to } = this.state + + if (!errors.to && !errors.amount && amount > 0) { + Promise.all([ + this.props.getGasPrice(), + this.props.estimateGas({ to, amount: this.getAmountToSend(amount, selectedToken) }), + ]) + .then(([blockGasPrice, estimatedGas]) => { + this.setState({ + blockGasPrice, + estimatedGas, + }) + }) + } +} + SendTokenScreen.prototype.validate = function () { const { to, @@ -215,7 +236,10 @@ SendTokenScreen.prototype.renderToAddressInput = function () { to: e.target.value, errors: {}, }), - onBlur: () => this.setErrorsFor('to'), + onBlur: () => { + this.setErrorsFor('to') + this.estimateGasAndPrice() + }, onFocus: () => this.clearErrorsFor('to'), }), h('datalist#addresses', [ @@ -271,7 +295,10 @@ SendTokenScreen.prototype.renderAmountInput = function () { onChange: e => this.setState({ amount: e.target.value, }), - onBlur: () => this.setErrorsFor('amount'), + onBlur: () => { + this.setErrorsFor('amount') + this.estimateGasAndPrice() + }, onFocus: () => this.clearErrorsFor('amount'), }), h('div.send-screen-input-wrapper__error-message', [ errorMessage ]), @@ -283,6 +310,8 @@ SendTokenScreen.prototype.renderGasInput = function () { isGasTooltipOpen, gasPrice, gasLimit, + blockGasPrice, + estimatedGas, selectedCurrency, errors: { gasPrice: gasPriceErrorMessage, @@ -303,8 +332,8 @@ SendTokenScreen.prototype.renderGasInput = function () { }, [ isGasTooltipOpen && h(GasTooltip, { className: 'send-tooltip', - gasPrice, - gasLimit, + gasPrice: gasPrice || blockGasPrice || '0x0', + gasLimit: gasLimit || estimatedGas || '0x0', onClose: () => this.setState({ isGasTooltipOpen: false }), onFeeChange: ({ gasLimit, gasPrice }) => { this.setState({ gasLimit, gasPrice, errors: {} }) @@ -327,9 +356,9 @@ SendTokenScreen.prototype.renderGasInput = function () { h(GasFeeDisplay, { conversionRate, tokenExchangeRate, - gasPrice, + gasPrice: gasPrice || blockGasPrice || '0x0', activeCurrency: selectedCurrency, - gas: gasLimit, + gas: gasLimit || estimatedGas || '0x0', blockGasLimit: currentBlockGasLimit, }), h( -- cgit v1.2.3 From 2c474b0d6e487652cf16e224e19deb0bf68abedb Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 20 Sep 2017 05:36:31 -0230 Subject: Export private key modal body ui. --- .../components/modals/export-private-key-modal.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/export-private-key-modal.js b/ui/app/components/modals/export-private-key-modal.js index bbcd25e0d..28b988f5a 100644 --- a/ui/app/components/modals/export-private-key-modal.js +++ b/ui/app/components/modals/export-private-key-modal.js @@ -37,5 +37,27 @@ ExportPrivateKeyModal.prototype.render = function () { h('div.account-modal-divider'), + h('span.modal-body-title', 'Download Private Keys'), + + h('div.private-key-password', {}, [ + h('span.private-key-password-label', 'Type Your Password'), + + h('input.private-key-password-input', { + type: 'password', + placeholder: 'Type password', + }), + ]), + + h('div.private-key-password-warning', `Warning: Never disclose this key. + Anyone with your private keys can take steal any assets held in your + account.` + ), + + h('div.export-private-key-buttons', {}, [ + h('button.btn-clear.btn-cancel', {}, 'Cancel'), + + h('button.btn-clear', 'Download'), + ]), + ]) } -- cgit v1.2.3 From eae40e054418c195310224194d9435ccfbf14e46 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 22 Sep 2017 05:58:43 -0230 Subject: Able to change selections in to and from fields of send and send token. --- ui/app/components/send-token/index.js | 1 + 1 file changed, 1 insertion(+) (limited to 'ui/app/components') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index dd8ca6b9d..cc77c2699 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -181,6 +181,7 @@ SendTokenScreen.prototype.renderToAddressInput = function () { to: e.target.value, errors: {}, }), + onFocus: () => to && this.setState({ to: '' }), }), h('datalist#addresses', [ // Corresponds to the addresses owned. -- cgit v1.2.3 From 56697ea9a4399ecaccf33ae3ae1a42283bdc9dc7 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 22 Sep 2017 18:47:05 -0230 Subject: Select all in to and from of send screens, instead of clearing on focus. --- ui/app/components/send-token/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index cc77c2699..60fe2ac8b 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -181,7 +181,7 @@ SendTokenScreen.prototype.renderToAddressInput = function () { to: e.target.value, errors: {}, }), - onFocus: () => to && this.setState({ to: '' }), + onFocus: event => to && event.target.select(), }), h('datalist#addresses', [ // Corresponds to the addresses owned. -- cgit v1.2.3 From 7102772c3a4a73d594ccc20e760defa2999f2d3f Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 20 Sep 2017 10:02:18 -0230 Subject: Connect export key modal to state and enable actions. --- .../components/modals/export-private-key-modal.js | 85 ++++++++++++++++++---- ui/app/components/readonly-input.js | 6 +- 2 files changed, 77 insertions(+), 14 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/export-private-key-modal.js b/ui/app/components/modals/export-private-key-modal.js index 28b988f5a..b1d551781 100644 --- a/ui/app/components/modals/export-private-key-modal.js +++ b/ui/app/components/modals/export-private-key-modal.js @@ -2,6 +2,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect +const ethUtil = require('ethereumjs-util') const actions = require('../../actions') const AccountModalContainer = require('./account-modal-container') const { getSelectedIdentity } = require('../../selectors') @@ -9,20 +10,83 @@ const ReadOnlyInput = require('../readonly-input') function mapStateToProps (state) { return { + warning: state.appState.warning, + privateKey: state.appState.accountDetail.privateKey, network: state.metamask.network, selectedIdentity: getSelectedIdentity(state), } } +function mapDispatchToProps (dispatch) { + return { + exportAccount: (password, address) => dispatch(actions.exportAccount(password, address)), + hideModal: () => dispatch(actions.hideModal()), + } +} + inherits(ExportPrivateKeyModal, Component) function ExportPrivateKeyModal () { Component.call(this) + + this.state = { + password: '' + } +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)(ExportPrivateKeyModal) + +ExportPrivateKeyModal.prototype.renderPasswordLabel = function (privateKey) { + return h('span.private-key-password-label', privateKey + ? 'This is your private key (click to copy)' + : 'Type Your Password' + ) +} + +ExportPrivateKeyModal.prototype.renderPasswordInput = function (privateKey) { + const plainKey = privateKey && ethUtil.stripHexPrefix(privateKey) + + return privateKey + ? h(ReadOnlyInput, { + wrapperClass: 'private-key-password-display-wrapper', + inputClass: 'private-key-password-display-textarea', + textarea: true, + value: plainKey, + }) + : h('input.private-key-password-input', { + type: 'password', + placeholder: 'Type password', + onChange: event => this.setState({ password: event.target.value }) + }) +} + +ExportPrivateKeyModal.prototype.renderButton = function (className, onClick, label) { + return h('button', { + className, + onClick, + }, label) } -module.exports = connect(mapStateToProps)(ExportPrivateKeyModal) +ExportPrivateKeyModal.prototype.renderButtons = function (privateKey, password, address) { + const { hideModal, exportAccount } = this.props + + return h('div.export-private-key-buttons', {}, [ + !privateKey && this.renderButton('btn-clear btn-cancel', () => hideModal(), 'Cancel'), + + (privateKey + ? this.renderButton('btn-clear', () => hideModal(), 'Done') + : this.renderButton('btn-clear', () => exportAccount(this.state.password, address), 'Download') + ), + + ]) +} ExportPrivateKeyModal.prototype.render = function () { - const { selectedIdentity, network } = this.props + const { + selectedIdentity, + network, + privateKey, + warning, + } = this.props const { name, address } = selectedIdentity return h(AccountModalContainer, {}, [ @@ -31,7 +95,7 @@ ExportPrivateKeyModal.prototype.render = function () { h(ReadOnlyInput, { wrapperClass: 'ellip-address-wrapper', - inputClass: 'ellip-address', + inputClass: 'qr-ellip-address ellip-address', value: address, }), @@ -40,12 +104,11 @@ ExportPrivateKeyModal.prototype.render = function () { h('span.modal-body-title', 'Download Private Keys'), h('div.private-key-password', {}, [ - h('span.private-key-password-label', 'Type Your Password'), + this.renderPasswordLabel(privateKey), + + this.renderPasswordInput(privateKey), - h('input.private-key-password-input', { - type: 'password', - placeholder: 'Type password', - }), + !warning ? null : h('span.private-key-password-error', warning), ]), h('div.private-key-password-warning', `Warning: Never disclose this key. @@ -53,11 +116,7 @@ ExportPrivateKeyModal.prototype.render = function () { account.` ), - h('div.export-private-key-buttons', {}, [ - h('button.btn-clear.btn-cancel', {}, 'Cancel'), - - h('button.btn-clear', 'Download'), - ]), + this.renderButtons(privateKey, this.state.password, address), ]) } diff --git a/ui/app/components/readonly-input.js b/ui/app/components/readonly-input.js index 934cbefae..33b93b5a0 100644 --- a/ui/app/components/readonly-input.js +++ b/ui/app/components/readonly-input.js @@ -14,13 +14,17 @@ ReadOnlyInput.prototype.render = function () { wrapperClass = '', inputClass = '', value, + textarea, } = this.props + const inputType = textarea ? 'textarea' : 'input' + return h('div', {className: wrapperClass}, [ - h('input', { + h(inputType, { className: inputClass, value, readOnly: true, + onFocus: event => event.target.select(), }), ]) } -- cgit v1.2.3 From bdd1e58e552b50ab5d060a1671d29cf3c2fdf7fa Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 26 Sep 2017 09:15:14 -0700 Subject: Return null if transaction.key is shapeshift --- ui/app/components/tx-list.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index f817d03a9..ef5cfa245 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -47,7 +47,6 @@ TxList.prototype.render = function () { TxList.prototype.renderTransaction = function () { const { txsToRender, conversionRate } = this.props - return txsToRender.length ? txsToRender.map((transaction, i) => this.renderTransactionListItem(transaction, conversionRate)) : [h('div.tx-list-item.tx-list-item--empty', [ 'No Transactions' ])] @@ -55,6 +54,12 @@ TxList.prototype.renderTransaction = function () { // TODO: Consider moving TxListItem into a separate component TxList.prototype.renderTransactionListItem = function (transaction, conversionRate) { + // console.log({transaction}) + // refer to transaction-list.js:line 58 + if (transaction.key === 'shapeshift') { + return null + } + const props = { dateString: formatDate(transaction.time), address: transaction.txParams.to, -- cgit v1.2.3 From 541b69dda9a5ddbb0ea4e4c0df805e886f53645c Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 26 Sep 2017 21:51:45 -0230 Subject: Gets gas and price estimates when send components mount. --- ui/app/components/send-token/index.js | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 379f63883..02423a348 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -57,9 +57,8 @@ function mapDispatchToProps (dispatch) { dispatch(actions.signTokenTx(tokenAddress, toAddress, amount, txData)) ), updateTokenExchangeRate: token => dispatch(actions.updateTokenExchangeRate(token)), - estimateGas: ({ to, amount }) => dispatch(actions.estimateGas({ to, amount })), + estimateGas: () => dispatch(actions.estimateGas()), getGasPrice: () => dispatch(actions.getGasPrice()), - } } @@ -82,27 +81,22 @@ SendTokenScreen.prototype.componentWillMount = function () { const { updateTokenExchangeRate, selectedToken: { symbol }, + getGasPrice, + estimateGas, } = this.props updateTokenExchangeRate(symbol) -} -SendTokenScreen.prototype.estimateGasAndPrice = function () { - const { selectedToken } = this.props - const { errors, amount, to } = this.state - - if (!errors.to && !errors.amount && amount > 0) { - Promise.all([ - this.props.getGasPrice(), - this.props.estimateGas({ to, amount: this.getAmountToSend(amount, selectedToken) }), - ]) - .then(([blockGasPrice, estimatedGas]) => { - this.setState({ - blockGasPrice, - estimatedGas, - }) + Promise.all([ + getGasPrice(), + estimateGas(), + ]) + .then(([blockGasPrice, estimatedGas]) => { + this.setState({ + blockGasPrice, + estimatedGas, }) - } + }) } SendTokenScreen.prototype.validate = function () { @@ -238,7 +232,6 @@ SendTokenScreen.prototype.renderToAddressInput = function () { }), onBlur: () => { this.setErrorsFor('to') - this.estimateGasAndPrice() }, onFocus: event => { if (to) event.target.select() @@ -300,7 +293,6 @@ SendTokenScreen.prototype.renderAmountInput = function () { }), onBlur: () => { this.setErrorsFor('amount') - this.estimateGasAndPrice() }, onFocus: () => this.clearErrorsFor('amount'), }), -- cgit v1.2.3 From 39365f2cc419ee824988e6dad4e8a75e650ad1cc Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 26 Sep 2017 23:03:03 -0230 Subject: Update the correct values in state when estimates are received. --- ui/app/components/send-token/index.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 02423a348..8a827e951 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -93,8 +93,8 @@ SendTokenScreen.prototype.componentWillMount = function () { ]) .then(([blockGasPrice, estimatedGas]) => { this.setState({ - blockGasPrice, - estimatedGas, + gasPrice: blockGasPrice, + gasLimit: estimatedGas, }) }) } @@ -305,8 +305,6 @@ SendTokenScreen.prototype.renderGasInput = function () { isGasTooltipOpen, gasPrice, gasLimit, - blockGasPrice, - estimatedGas, selectedCurrency, errors: { gasPrice: gasPriceErrorMessage, @@ -327,8 +325,8 @@ SendTokenScreen.prototype.renderGasInput = function () { }, [ isGasTooltipOpen && h(GasTooltip, { className: 'send-tooltip', - gasPrice: gasPrice || blockGasPrice || '0x0', - gasLimit: gasLimit || estimatedGas || '0x0', + gasPrice: gasPrice || '0x0', + gasLimit: gasLimit || '0x0', onClose: () => this.setState({ isGasTooltipOpen: false }), onFeeChange: ({ gasLimit, gasPrice }) => { this.setState({ gasLimit, gasPrice, errors: {} }) @@ -351,9 +349,9 @@ SendTokenScreen.prototype.renderGasInput = function () { h(GasFeeDisplay, { conversionRate, tokenExchangeRate, - gasPrice: gasPrice || blockGasPrice || '0x0', + gasPrice: gasPrice || '0x0', activeCurrency: selectedCurrency, - gas: gasLimit || estimatedGas || '0x0', + gas: gasLimit || '0x0', blockGasLimit: currentBlockGasLimit, }), h( -- cgit v1.2.3 From c77029ea90560b4210f9204e99314d30f9b59989 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 26 Sep 2017 19:21:04 -0700 Subject: Implement Confirm Deploy Contract screen --- .../pending-tx/confirm-deploy-contract.js | 344 +++++++++++++++++++++ ui/app/components/pending-tx/index.js | 6 + 2 files changed, 350 insertions(+) create mode 100644 ui/app/components/pending-tx/confirm-deploy-contract.js (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-deploy-contract.js b/ui/app/components/pending-tx/confirm-deploy-contract.js new file mode 100644 index 000000000..89a0389d7 --- /dev/null +++ b/ui/app/components/pending-tx/confirm-deploy-contract.js @@ -0,0 +1,344 @@ +const Component = require('react').Component +const { connect } = require('react-redux') +const h = require('react-hyperscript') +const inherits = require('util').inherits +const actions = require('../../actions') +const clone = require('clone') +const Identicon = require('../identicon') +const ethUtil = require('ethereumjs-util') +const BN = ethUtil.BN +const hexToBn = require('../../../../app/scripts/lib/hex-to-bn') +const { conversionUtil } = require('../../conversion-util') + +const MIN_GAS_PRICE_GWEI_BN = new BN(1) +const GWEI_FACTOR = new BN(1e9) +const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR) + + +module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmDeployContract) + +function mapStateToProps (state) { + const { + conversionRate, + identities, + } = state.metamask + const accounts = state.metamask.accounts + const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] + return { + conversionRate, + identities, + selectedAddress, + } +} + +function mapDispatchToProps (dispatch) { + return { + setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('USD')), + backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)), + cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), + } +} + + +inherits(ConfirmDeployContract, Component) +function ConfirmDeployContract () { + Component.call(this) + this.state = {} + this.onSubmit = this.onSubmit.bind(this) +} + +ConfirmDeployContract.prototype.onSubmit = function (event) { + event.preventDefault() + const txMeta = this.gatherTxMeta() + const valid = this.checkValidity() + this.setState({ valid, submitting: true }) + + if (valid && this.verifyGasParams()) { + this.props.sendTransaction(txMeta, event) + } else { + this.props.dispatch(actions.displayWarning('Invalid Gas Parameters')) + this.setState({ submitting: false }) + } +} + +ConfirmDeployContract.prototype.cancel = function (event, txMeta) { + event.preventDefault() + this.props.cancelTransaction(txMeta) +} + +ConfirmDeployContract.prototype.checkValidity = function () { + const form = this.getFormEl() + const valid = form.checkValidity() + return valid +} + +ConfirmDeployContract.prototype.getFormEl = function () { + const form = document.querySelector('form#pending-tx-form') + // Stub out form for unit tests: + if (!form) { + return { checkValidity () { return true } } + } + return form +} + +// After a customizable state value has been updated, +ConfirmDeployContract.prototype.gatherTxMeta = function () { + const props = this.props + const state = this.state + const txData = clone(state.txData) || clone(props.txData) + + // log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`) + return txData +} + +ConfirmDeployContract.prototype.verifyGasParams = function () { + // We call this in case the gas has not been modified at all + if (!this.state) { return true } + return ( + this._notZeroOrEmptyString(this.state.gas) && + this._notZeroOrEmptyString(this.state.gasPrice) + ) +} + +ConfirmDeployContract.prototype._notZeroOrEmptyString = function (obj) { + return obj !== '' && obj !== '0x0' +} + +ConfirmDeployContract.prototype.bnMultiplyByFraction = function (targetBN, numerator, denominator) { + const numBN = new BN(numerator) + const denomBN = new BN(denominator) + return targetBN.mul(numBN).div(denomBN) +} + +ConfirmDeployContract.prototype.getData = function () { + const { identities } = this.props + const txMeta = this.gatherTxMeta() + const txParams = txMeta.txParams || {} + + return { + from: { + address: txParams.from, + name: identities[txParams.from].name, + }, + memo: txParams.memo || '', + } +} + +ConfirmDeployContract.prototype.getAmount = function () { + const { conversionRate } = this.props + const txMeta = this.gatherTxMeta() + const txParams = txMeta.txParams || {} + + const USD = conversionUtil(txParams.value, { + fromNumericBase: 'hex', + toNumericBase: 'dec', + fromCurrency: 'ETH', + toCurrency: 'USD', + numberOfDecimals: 2, + fromDenomination: 'WEI', + conversionRate, + }) + const ETH = conversionUtil(txParams.value, { + fromNumericBase: 'hex', + toNumericBase: 'dec', + fromCurrency: 'ETH', + toCurrency: 'ETH', + fromDenomination: 'WEI', + conversionRate, + numberOfDecimals: 6, + }) + + return { + fiat: Number(USD), + token: Number(ETH), + } + +} + +ConfirmDeployContract.prototype.getGasFee = function () { + const { conversionRate } = this.props + const txMeta = this.gatherTxMeta() + const txParams = txMeta.txParams || {} + + // Gas + const gas = txParams.gas + const gasBn = hexToBn(gas) + + // Gas Price + const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16) + const gasPriceBn = hexToBn(gasPrice) + + const txFeeBn = gasBn.mul(gasPriceBn) + + const USD = conversionUtil(txFeeBn, { + fromNumericBase: 'BN', + toNumericBase: 'dec', + fromDenomination: 'WEI', + fromCurrency: 'ETH', + toCurrency: 'USD', + numberOfDecimals: 2, + conversionRate, + }) + const ETH = conversionUtil(txFeeBn, { + fromNumericBase: 'BN', + toNumericBase: 'dec', + fromDenomination: 'WEI', + fromCurrency: 'ETH', + toCurrency: 'ETH', + numberOfDecimals: 6, + conversionRate, + }) + + return { + fiat: Number(USD), + eth: Number(ETH), + } +} +ConfirmDeployContract.prototype.renderGasFee = function () { + const { fiat: fiatGas, eth: ethGas } = this.getGasFee() + + return ( + h('section.flex-row.flex-center.confirm-screen-row', [ + h('span.confirm-screen-label.confirm-screen-section-column', [ 'Gas Fee' ]), + h('div.confirm-screen-section-column', [ + h('div.confirm-screen-row-info', `$${fiatGas} USD`), + + h( + 'div.confirm-screen-row-detail', + `${ethGas} ETH` + ), + ]), + ]) + ) +} + +ConfirmDeployContract.prototype.renderHeroAmount = function () { + const { fiat: fiatAmount } = this.getAmount() + const txMeta = this.gatherTxMeta() + const txParams = txMeta.txParams || {} + const { memo = '' } = txParams + + return ( + h('div.confirm-send-token__hero-amount-wrapper', [ + h('h3.flex-center.confirm-screen-send-amount', `$${fiatAmount}`), + h('h3.flex-center.confirm-screen-send-amount-currency', 'USD'), + h('div.flex-center.confirm-memo-wrapper', [ + h('h3.confirm-screen-send-memo', memo), + ]), + ]) + ) +} + +ConfirmDeployContract.prototype.renderTotalPlusGas = function () { + const { fiat: fiatAmount, token: tokenAmount } = this.getAmount() + const { fiat: fiatGas, eth: ethGas } = this.getGasFee() + + return ( + h('section.flex-row.flex-center.confirm-screen-total-box ', [ + h('div.confirm-screen-section-column', [ + h('span.confirm-screen-label', [ 'Total ' ]), + h('div.confirm-screen-total-box__subtitle', [ 'Amount + Gas' ]), + ]), + + h('div.confirm-screen-section-column', [ + h('div.confirm-screen-row-info', `$${fiatAmount + fiatGas} USD`), + h('div.confirm-screen-row-detail', `${tokenAmount + ethGas} ETH`), + ]), + ]) + ) +} + +ConfirmDeployContract.prototype.render = function () { + const { backToAccountDetail, selectedAddress } = this.props + const txMeta = this.gatherTxMeta() + + const { + from: { + address: fromAddress, + name: fromName, + }, + } = this.getData() + + this.inputs = [] + + return ( + h('div.flex-column.flex-grow.confirm-screen-container', { + style: { minWidth: '355px' }, + }, [ + // Main Send token Card + h('div.confirm-screen-wrapper.flex-column.flex-grow', [ + h('h3.flex-center.confirm-screen-header', [ + h('button.confirm-screen-back-button', { + onClick: () => backToAccountDetail(selectedAddress), + }, 'BACK'), + h('div.confirm-screen-title', 'Confirm Transaction'), + ]), + h('div.flex-row.flex-center.confirm-screen-identicons', [ + h('div.confirm-screen-account-wrapper', [ + h( + Identicon, + { + address: fromAddress, + diameter: 100, + }, + ), + h('span.confirm-screen-account-name', fromName), + h('span.confirm-screen-account-number', fromAddress.slice(fromAddress.length - 4)), + ]), + h('i.fa.fa-arrow-right.fa-lg'), + h('div.confirm-screen-account-wrapper', [ + h('i.fa.fa-file-text-o'), + h('span.confirm-screen-account-name', 'New Contract'), + h('span.confirm-screen-account-number', ' '), + ]), + ]), + + h('h3.flex-center.confirm-screen-sending-to-message', { + style: { + textAlign: 'center', + fontSize: '16px', + }, + }, [ + `You're deploying a new contract.`, + ]), + + this.renderHeroAmount(), + + h('div.confirm-screen-rows', [ + h('section.flex-row.flex-center.confirm-screen-row', [ + h('span.confirm-screen-label.confirm-screen-section-column', [ 'From' ]), + h('div.confirm-screen-section-column', [ + h('div.confirm-screen-row-info', fromName), + h('div.confirm-screen-row-detail', `...${fromAddress.slice(fromAddress.length - 4)}`), + ]), + ]), + + h('section.flex-row.flex-center.confirm-screen-row', [ + h('span.confirm-screen-label.confirm-screen-section-column', [ 'To' ]), + h('div.confirm-screen-section-column', [ + h('div.confirm-screen-row-info', 'New Contract'), + ]), + ]), + + this.renderGasFee(), + + this.renderTotalPlusGas(), + + ]), + ]), + + h('form#pending-tx-form.flex-column.flex-center', { + onSubmit: this.onSubmit, + }, [ + + // Accept Button + h('button.confirm-screen-confirm-button', ['CONFIRM']), + + // Cancel Button + h('div.cancel.btn-light.confirm-screen-cancel-button', { + onClick: (event) => this.cancel(event, txMeta), + }, 'CANCEL'), + ]), + ]) + ) +} diff --git a/ui/app/components/pending-tx/index.js b/ui/app/components/pending-tx/index.js index 915319958..b7dd50ff1 100644 --- a/ui/app/components/pending-tx/index.js +++ b/ui/app/components/pending-tx/index.js @@ -10,6 +10,7 @@ const actions = require('../../actions') const util = require('../../util') const ConfirmSendEther = require('./confirm-send-ether') const ConfirmSendToken = require('./confirm-send-token') +const ConfirmDeployContract = require('./confirm-deploy-contract') const TX_TYPES = { DEPLOY_CONTRACT: 'deploy_contract', @@ -136,6 +137,11 @@ PendingTx.prototype.render = function () { decimals: tokenDecimals, }, }) + case TX_TYPES.DEPLOY_CONTRACT: + return h(ConfirmDeployContract, { + txData: this.gatherTxMeta(), + sendTransaction, + }) default: return h('noscript') } -- cgit v1.2.3 From 01816e1b2216e0cf849ec3d67f01b1e571d69fa4 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 22 Sep 2017 17:27:18 -0230 Subject: Adds a back button to export private key modal; connects account details to same modal. --- ui/app/components/modals/account-details-modal.js | 17 +++++++++++++++-- ui/app/components/modals/account-modal-container.js | 19 +++++++++++++++++-- ui/app/components/modals/export-private-key-modal.js | 10 +++++++++- 3 files changed, 41 insertions(+), 5 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/account-details-modal.js b/ui/app/components/modals/account-details-modal.js index 6c2eba7bd..37a62e1c0 100644 --- a/ui/app/components/modals/account-details-modal.js +++ b/ui/app/components/modals/account-details-modal.js @@ -19,6 +19,10 @@ function mapDispatchToProps (dispatch) { return { // Is this supposed to be used somewhere? showQrView: (selected, identity) => dispatch(actions.showQrView(selected, identity)), + showExportPrivateKeyModal: () => { + dispatch(actions.showModal({ name: 'EXPORT_PRIVATE_KEY' })) + }, + hideModal: () => dispatch(actions.hideModal()), } } @@ -33,7 +37,12 @@ module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountDetailsModa // fonts of qr-header AccountDetailsModal.prototype.render = function () { - const { selectedIdentity, network } = this.props + const { + selectedIdentity, + network, + showExportPrivateKeyModal, + hideModal, + } = this.props const { name, address } = selectedIdentity return h(AccountModalContainer, {}, [ @@ -51,7 +60,11 @@ AccountDetailsModal.prototype.render = function () { }, [ 'View account on Etherscan' ]), // Holding on redesign for Export Private Key functionality - h('button.btn-clear', [ 'Export private key' ]), + h('button.btn-clear', { + onClick: () => { + showExportPrivateKeyModal() + }, + }, [ 'Export private key' ]), ]) } diff --git a/ui/app/components/modals/account-modal-container.js b/ui/app/components/modals/account-modal-container.js index 69650ca15..3cad72067 100644 --- a/ui/app/components/modals/account-modal-container.js +++ b/ui/app/components/modals/account-modal-container.js @@ -28,8 +28,13 @@ function AccountModalContainer () { module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountModalContainer) AccountModalContainer.prototype.render = function () { - const { selectedIdentity, children } = this.props - console.log(`children`, children); + const { + selectedIdentity, + children, + showBackButton = false, + backButtonAction, + } = this.props + return h('div', { style: { borderRadius: '4px' }}, [ h('div.account-modal-container', [ @@ -44,6 +49,16 @@ AccountModalContainer.prototype.render = function () { ]), + showBackButton && h('div.account-modal-back', { + onClick: backButtonAction, + }, [ + + h('i.fa.fa-angle-left.fa-lg'), + + h('span.account-modal-back__text', ' Back'), + + ]), + h('div.account-modal-close', { onClick: this.props.hideModal, }), diff --git a/ui/app/components/modals/export-private-key-modal.js b/ui/app/components/modals/export-private-key-modal.js index b1d551781..4bb34f8c6 100644 --- a/ui/app/components/modals/export-private-key-modal.js +++ b/ui/app/components/modals/export-private-key-modal.js @@ -14,12 +14,14 @@ function mapStateToProps (state) { privateKey: state.appState.accountDetail.privateKey, network: state.metamask.network, selectedIdentity: getSelectedIdentity(state), + previousModalState: state.appState.modal.previousModalState.name, } } function mapDispatchToProps (dispatch) { return { exportAccount: (password, address) => dispatch(actions.exportAccount(password, address)), + showAccountDetailModal: () => dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' })), hideModal: () => dispatch(actions.hideModal()), } } @@ -86,10 +88,16 @@ ExportPrivateKeyModal.prototype.render = function () { network, privateKey, warning, + showAccountDetailModal, + hideModal, + previousModalState, } = this.props const { name, address } = selectedIdentity - return h(AccountModalContainer, {}, [ + return h(AccountModalContainer, { + showBackButton: previousModalState === 'ACCOUNT_DETAILS', + backButtonAction: () => showAccountDetailModal(), + }, [ h('span.account-name', name), -- cgit v1.2.3 From 10345a12c2f812fabbcd9950da14beaa03cb2502 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 26 Sep 2017 20:33:33 -0230 Subject: Keep privateKey out of state and clear it after closing export private key modal. --- .../components/modals/export-private-key-modal.js | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/export-private-key-modal.js b/ui/app/components/modals/export-private-key-modal.js index 4bb34f8c6..ddc7f1352 100644 --- a/ui/app/components/modals/export-private-key-modal.js +++ b/ui/app/components/modals/export-private-key-modal.js @@ -31,12 +31,20 @@ function ExportPrivateKeyModal () { Component.call(this) this.state = { - password: '' + password: '', + privateKey: null, } } module.exports = connect(mapStateToProps, mapDispatchToProps)(ExportPrivateKeyModal) +ExportPrivateKeyModal.prototype.exportAccountAndGetPrivateKey = function (password, address) { + const { exportAccount } = this.props + + exportAccount(password, address) + .then(privateKey => this.setState({ privateKey })) +} + ExportPrivateKeyModal.prototype.renderPasswordLabel = function (privateKey) { return h('span.private-key-password-label', privateKey ? 'This is your private key (click to copy)' @@ -68,15 +76,13 @@ ExportPrivateKeyModal.prototype.renderButton = function (className, onClick, lab }, label) } -ExportPrivateKeyModal.prototype.renderButtons = function (privateKey, password, address) { - const { hideModal, exportAccount } = this.props - +ExportPrivateKeyModal.prototype.renderButtons = function (privateKey, password, address, hideModal) { return h('div.export-private-key-buttons', {}, [ !privateKey && this.renderButton('btn-clear btn-cancel', () => hideModal(), 'Cancel'), (privateKey ? this.renderButton('btn-clear', () => hideModal(), 'Done') - : this.renderButton('btn-clear', () => exportAccount(this.state.password, address), 'Download') + : this.renderButton('btn-clear', () => this.exportAccountAndGetPrivateKey(this.state.password, address), 'Download') ), ]) @@ -86,7 +92,6 @@ ExportPrivateKeyModal.prototype.render = function () { const { selectedIdentity, network, - privateKey, warning, showAccountDetailModal, hideModal, @@ -94,6 +99,8 @@ ExportPrivateKeyModal.prototype.render = function () { } = this.props const { name, address } = selectedIdentity + const { privateKey } = this.state + return h(AccountModalContainer, { showBackButton: previousModalState === 'ACCOUNT_DETAILS', backButtonAction: () => showAccountDetailModal(), @@ -124,7 +131,7 @@ ExportPrivateKeyModal.prototype.render = function () { account.` ), - this.renderButtons(privateKey, this.state.password, address), + this.renderButtons(privateKey, this.state.password, address, hideModal), ]) } -- cgit v1.2.3 From c2ccd6e90ed15245ed4e9e2965f2f5c9f293f115 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 27 Sep 2017 21:45:27 -0230 Subject: Makes styling fixes to account dropdown. --- .../dropdowns/components/account-dropdowns.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index 76f186a3f..3e31412c6 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -51,6 +51,7 @@ class AccountDropdowns extends Component { { marginTop: index === 0 ? '5px' : '', fontSize: '24px', + width: '260px', }, menuItemStyles, ), @@ -92,6 +93,7 @@ class AccountDropdowns extends Component { alignItems: 'flex-start', justifyContent: 'center', marginLeft: '10px', + position: 'relative', }, }, [ this.indicateIfLoose(keyring), @@ -104,7 +106,6 @@ class AccountDropdowns extends Component { textOverflow: 'ellipsis', }, }, identity.name || ''), - h('span', { style: { marginLeft: '20px', fontSize: '24px' } }, isSelected ? h('.check', '✓') : null), h('span.account-dropdown-balance', { style: { @@ -202,17 +203,19 @@ class AccountDropdowns extends Component { }, [ h( - Identicon, + 'div', { style: { - marginLeft: '10px', + marginLeft: '8px', + fontFamily: 'Montserrat UltraLight', + fontSize: '30px', }, - diameter: 32, }, + '+' ), h('span', { style: { - marginLeft: '20px', + marginLeft: '14px', fontFamily: 'DIN OT', fontSize: '16px', lineHeight: '23px', @@ -232,13 +235,13 @@ class AccountDropdowns extends Component { }, [ h( - Identicon, + 'div', { style: { marginLeft: '10px', }, - diameter: 32, }, + String.fromCharCode(10515) ), h('span', { style: { -- cgit v1.2.3 From deee689426f0b6236093128b47be81faf56d6b75 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 27 Sep 2017 22:26:44 -0230 Subject: Use font-awesome icons for create and import account. --- .../components/dropdowns/components/account-dropdowns.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index 3e31412c6..d53d2a81b 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -203,15 +203,12 @@ class AccountDropdowns extends Component { }, [ h( - 'div', + 'i.fa.fa-plus.fa-lg', { style: { marginLeft: '8px', - fontFamily: 'Montserrat UltraLight', - fontSize: '30px', }, - }, - '+' + } ), h('span', { style: { @@ -235,13 +232,12 @@ class AccountDropdowns extends Component { }, [ h( - 'div', + 'i.fa.fa-download.fa-lg', { style: { - marginLeft: '10px', + marginLeft: '8px', }, - }, - String.fromCharCode(10515) + } ), h('span', { style: { -- cgit v1.2.3 From a4838b1c575f08f9a83457222737075bab374936 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 27 Sep 2017 22:11:46 -0230 Subject: Close mobile sidebar when selecting 'Add token' from account options dropdown. --- ui/app/components/dropdowns/components/account-dropdowns.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index d53d2a81b..fc60c6005 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -349,6 +349,7 @@ class AccountDropdowns extends Component { { closeMenu: () => {}, onClick: () => { + actions.hideSidebar() actions.showAddTokenPage() }, style: Object.assign( @@ -425,6 +426,7 @@ AccountDropdowns.propTypes = { const mapDispatchToProps = (dispatch) => { return { actions: { + hideSidebar: () => dispatch(actions.hideSidebar()), showConfigPage: () => dispatch(actions.showConfigPage()), showAccountDetail: (address) => dispatch(actions.showAccountDetail(address)), showAccountDetailModal: () => { -- cgit v1.2.3 From b55a40c7f144645a29569294996893cb1b519779 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 28 Sep 2017 09:25:04 -0230 Subject: Close sidebar on token selection. --- ui/app/components/token-cell.js | 11 +++++++++-- ui/app/components/wallet-view.js | 13 +++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index dc1c7f46f..e87d2c859 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -15,6 +15,7 @@ function mapStateToProps (state) { userAddress: selectors.getSelectedAddress(state), tokenExchangeRates: state.metamask.tokenExchangeRates, ethToUSDRate: state.metamask.conversionRate, + sidebarOpen: state.appState.sidebarOpen, } } @@ -22,6 +23,7 @@ function mapDispatchToProps (dispatch) { return { setSelectedToken: address => dispatch(actions.setSelectedToken(address)), updateTokenExchangeRate: token => dispatch(actions.updateTokenExchangeRate(token)), + hideSidebar: () => dispatch(actions.hideSidebar()), } } @@ -52,6 +54,8 @@ TokenCell.prototype.render = function () { selectedTokenAddress, tokenExchangeRates, ethToUSDRate, + hideSidebar, + sidebarOpen, // userAddress, } = props @@ -73,13 +77,16 @@ TokenCell.prototype.render = function () { }) formattedUSD = `$${currentTokenInUSD} USD`; } - + return ( h('div.token-list-item', { className: `token-list-item ${selectedTokenAddress === address ? 'token-list-item--active' : ''}`, // style: { cursor: network === '1' ? 'pointer' : 'default' }, // onClick: this.view.bind(this, address, userAddress, network), - onClick: () => setSelectedToken(address), + onClick: () => { + setSelectedToken(address) + selectedTokenAddress !== address && sidebarOpen && hideSidebar() + }, }, [ h(Identicon, { diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index b306fb7d4..00c86298d 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -40,7 +40,13 @@ function WalletView () { } WalletView.prototype.renderWalletBalance = function () { - const { selectedTokenAddress, selectedAccount, unsetSelectedToken } = this.props + const { + selectedTokenAddress, + selectedAccount, + unsetSelectedToken, + hideSidebar, + sidebarOpen + } = this.props const selectedClass = selectedTokenAddress ? '' : 'wallet-balance-wrapper--active' @@ -49,7 +55,10 @@ WalletView.prototype.renderWalletBalance = function () { return h('div', { className }, [ h('div.wallet-balance', { - onClick: unsetSelectedToken, + onClick: () => { + unsetSelectedToken() + selectedTokenAddress && sidebarOpen && hideSidebar() + }, }, [ h(BalanceComponent, { -- cgit v1.2.3 From 66ed4dfaa31be826f0d5a4a34410e34eca34d007 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 28 Sep 2017 12:18:25 -0230 Subject: Ensure sent token value is recognized as hex. --- ui/app/components/send-token/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 8a827e951..6e4c909be 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -165,7 +165,7 @@ SendTokenScreen.prototype.clearErrorsFor = function (field) { SendTokenScreen.prototype.getAmountToSend = function (amount, selectedToken) { const { decimals } = selectedToken || {} const multiplier = Math.pow(10, Number(decimals || 0)) - const sendAmount = Number(amount * multiplier).toString(16) + const sendAmount = '0x' + Number(amount * multiplier).toString(16) return sendAmount } -- cgit v1.2.3 From 06292107d756f0b25805f819cd276e4b6303ccb0 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Thu, 28 Sep 2017 16:13:53 -0700 Subject: Always set currency to USD on app mount --- ui/app/components/pending-tx/confirm-deploy-contract.js | 1 - ui/app/components/pending-tx/confirm-send-ether.js | 1 - ui/app/components/pending-tx/index.js | 2 +- ui/app/components/token-balance.js | 3 ++- 4 files changed, 3 insertions(+), 4 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-deploy-contract.js b/ui/app/components/pending-tx/confirm-deploy-contract.js index 89a0389d7..386e14afe 100644 --- a/ui/app/components/pending-tx/confirm-deploy-contract.js +++ b/ui/app/components/pending-tx/confirm-deploy-contract.js @@ -33,7 +33,6 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { - setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('USD')), backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)), cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), } diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index b03ec0552..330a55cce 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -32,7 +32,6 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { - setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('USD')), backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)), cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), } diff --git a/ui/app/components/pending-tx/index.js b/ui/app/components/pending-tx/index.js index b7dd50ff1..770fb1dfd 100644 --- a/ui/app/components/pending-tx/index.js +++ b/ui/app/components/pending-tx/index.js @@ -36,7 +36,7 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { - setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('USD')), + setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('usd')), backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)), cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), } diff --git a/ui/app/components/token-balance.js b/ui/app/components/token-balance.js index 0342c1da9..2f71c0687 100644 --- a/ui/app/components/token-balance.js +++ b/ui/app/components/token-balance.js @@ -27,7 +27,8 @@ function TokenBalance () { TokenBalance.prototype.render = function () { const state = this.state - const { symbol, string, balanceOnly, isLoading } = state + const { symbol, string, isLoading } = state + const { balanceOnly } = this.props return isLoading ? h('span', '') -- cgit v1.2.3 From 4f106854ba6bbfd22b49598f9ef019aa620f5b4f Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Thu, 28 Sep 2017 16:34:42 -0700 Subject: Hide ShapeShift and Fix Modal Stylings --- ui/app/components/modals/buy-options-modal.js | 10 ++--- ui/app/components/modals/modal.js | 55 +++++++++++++++++++++++---- 2 files changed, 52 insertions(+), 13 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/buy-options-modal.js b/ui/app/components/modals/buy-options-modal.js index a8033d288..f1a5aa9fd 100644 --- a/ui/app/components/modals/buy-options-modal.js +++ b/ui/app/components/modals/buy-options-modal.js @@ -57,13 +57,13 @@ BuyOptions.prototype.render = function () { h('div.buy-modal-content-option-subtitle', {}, 'Buy with Fiat'), ]), - h('div.buy-modal-content-option', {}, [ - h('div.buy-modal-content-option-title', {}, 'Shapeshift'), - h('div.buy-modal-content-option-subtitle', {}, 'Trade any digital asset for any other'), - ]), + // h('div.buy-modal-content-option', {}, [ + // h('div.buy-modal-content-option-title', {}, 'Shapeshift'), + // h('div.buy-modal-content-option-subtitle', {}, 'Trade any digital asset for any other'), + // ]), h('div.buy-modal-content-option', { - onClick: () => this.goToAccountDetailsModal() + onClick: () => this.goToAccountDetailsModal(), }, [ h('div.buy-modal-content-option-title', {}, 'Direct Deposit'), h('div.buy-modal-content-option-subtitle', {}, 'Deposit from another account'), diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 138efc3ea..2bd56fb0a 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -17,15 +17,25 @@ const NewAccountModal = require('./new-account-modal') const accountModalStyle = { mobileModalStyle: { width: '95%', - top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh', + // top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh', boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', borderRadius: '4px', + top: '10%', + transform: 'none', + left: '0', + right: '0', + margin: '0 auto', }, laptopModalStyle: { width: '360px', - top: 'calc(33% + 45px)', + // top: 'calc(33% + 45px)', boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', borderRadius: '4px', + top: '10%', + transform: 'none', + left: '0', + right: '0', + margin: '0 auto', }, contentStyle: { borderRadius: '4px', @@ -39,14 +49,23 @@ const MODALS = { ], mobileModalStyle: { width: '95%', - top: isPopupOrNotification() === 'popup' ? '48vh' : '36.5vh', + // top: isPopupOrNotification() === 'popup' ? '48vh' : '36.5vh', + transform: 'none', + left: '0', + right: '0', + margin: '0 auto', boxShadow: '0 0 7px 0 rgba(0,0,0,0.08)', + top: '10%', }, laptopModalStyle: { width: '66%', maxWidth: '550px', - top: 'calc(30% + 10px)', + top: 'calc(10% + 10px)', + left: '0', + right: '0', + margin: '0 auto', boxShadow: '0 0 7px 0 rgba(0,0,0,0.08)', + transform: 'none', }, }, @@ -56,13 +75,23 @@ const MODALS = { ], mobileModalStyle: { width: '95%', - top: isPopupOrNotification() === 'popup' ? '48vh' : '36.5vh', + // top: isPopupOrNotification() === 'popup' ? '48vh' : '36.5vh', + top: '10%', boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', + transform: 'none', + left: '0', + right: '0', + margin: '0 auto', }, laptopModalStyle: { width: '375px', - top: 'calc(30% + 10px)', + // top: 'calc(30% + 10px)', + top: '10%', boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', + transform: 'none', + left: '0', + right: '0', + margin: '0 auto', }, }, @@ -86,11 +115,21 @@ const MODALS = { ], mobileModalStyle: { width: '95%', - top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh', + // top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh', + top: '10%', + transform: 'none', + left: '0', + right: '0', + margin: '0 auto', }, laptopModalStyle: { width: '449px', - top: 'calc(33% + 45px)', + // top: 'calc(33% + 45px)', + top: '10%', + transform: 'none', + left: '0', + right: '0', + margin: '0 auto', }, }, -- cgit v1.2.3 From 67ee5b21e6f64ac22e65f2712ae13dd8c09ed113 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Thu, 28 Sep 2017 17:39:53 -0700 Subject: Query for gas estimates --- ui/app/components/send-token/index.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 6e4c909be..a95a0a6d8 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -2,6 +2,7 @@ const Component = require('react').Component const connect = require('react-redux').connect const h = require('react-hyperscript') const classnames = require('classnames') +const abi = require('ethereumjs-abi') const inherits = require('util').inherits const actions = require('../../actions') const selectors = require('../../selectors') @@ -57,7 +58,7 @@ function mapDispatchToProps (dispatch) { dispatch(actions.signTokenTx(tokenAddress, toAddress, amount, txData)) ), updateTokenExchangeRate: token => dispatch(actions.updateTokenExchangeRate(token)), - estimateGas: () => dispatch(actions.estimateGas()), + estimateGas: params => dispatch(actions.estimateGas(params)), getGasPrice: () => dispatch(actions.getGasPrice()), } } @@ -83,15 +84,28 @@ SendTokenScreen.prototype.componentWillMount = function () { selectedToken: { symbol }, getGasPrice, estimateGas, + selectedAddress, } = this.props updateTokenExchangeRate(symbol) + const data = Array.prototype.map.call( + abi.rawEncode(['address', 'uint256'], [selectedAddress, '0x0']), + x => ('00' + x.toString(16)).slice(-2) + ).join('') + + console.log(data) Promise.all([ getGasPrice(), - estimateGas(), + estimateGas({ + from: selectedAddress, + value: '0x0', + gas: '746a528800', + data, + }), ]) .then(([blockGasPrice, estimatedGas]) => { + console.log({ blockGasPrice, estimatedGas}) this.setState({ gasPrice: blockGasPrice, gasLimit: estimatedGas, -- cgit v1.2.3 From 7c4d8c45624ef840b8806589b47997e7c7c396f3 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 29 Sep 2017 12:20:09 -0230 Subject: Enables the old shapeshift UI within new ui. --- ui/app/components/shift-list-item.js | 2 +- ui/app/components/tx-list.js | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/shift-list-item.js b/ui/app/components/shift-list-item.js index 079f05e31..392b67630 100644 --- a/ui/app/components/shift-list-item.js +++ b/ui/app/components/shift-list-item.js @@ -29,7 +29,7 @@ function ShiftListItem () { ShiftListItem.prototype.render = function () { return ( - h('.transaction-list-item.flex-row', { + h('div.tx-list-item.tx-list-clickable', { style: { paddingTop: '20px', paddingBottom: '20px', diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index ef5cfa245..82541704e 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -5,6 +5,7 @@ const inherits = require('util').inherits const prefixForNetwork = require('../../lib/etherscan-prefix-for-network') const selectors = require('../selectors') const TxListItem = require('./tx-list-item') +const ShiftListItem = require('./shift-list-item') const { formatBalance, formatDate } = require('../util') const { showConfTxPage } = require('../actions') @@ -56,8 +57,9 @@ TxList.prototype.renderTransaction = function () { TxList.prototype.renderTransactionListItem = function (transaction, conversionRate) { // console.log({transaction}) // refer to transaction-list.js:line 58 + const shapeshiftProps = {}; if (transaction.key === 'shapeshift') { - return null + return h(ShiftListItem, transaction) } const props = { -- cgit v1.2.3 From ff64fe98dde7746775396cbf94d63a1a0e91d069 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 29 Sep 2017 13:10:57 -0230 Subject: Shapeshift deposit tx modal. --- .../components/modals/account-modal-container.js | 6 +++- ui/app/components/modals/modal.js | 8 +++++ .../modals/shapeshift-deposit-tx-modal.js | 40 ++++++++++++++++++++++ ui/app/components/tx-list.js | 2 +- 4 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 ui/app/components/modals/shapeshift-deposit-tx-modal.js (limited to 'ui/app/components') diff --git a/ui/app/components/modals/account-modal-container.js b/ui/app/components/modals/account-modal-container.js index 3cad72067..c548fb7b3 100644 --- a/ui/app/components/modals/account-modal-container.js +++ b/ui/app/components/modals/account-modal-container.js @@ -30,10 +30,14 @@ module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountModalContai AccountModalContainer.prototype.render = function () { const { selectedIdentity, - children, showBackButton = false, backButtonAction, } = this.props + let { children } = this.props + + if (children.constructor !== Array) { + children = [children] + } return h('div', { style: { borderRadius: '4px' }}, [ h('div.account-modal-container', [ diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 2bd56fb0a..765e46312 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -13,6 +13,7 @@ const AccountDetailsModal = require('./account-details-modal') const EditAccountNameModal = require('./edit-account-name-modal') const ExportPrivateKeyModal = require('./export-private-key-modal') const NewAccountModal = require('./new-account-modal') +const ShapeshiftDepositTxModal = require('./shapeshift-deposit-tx-modal.js') const accountModalStyle = { mobileModalStyle: { @@ -109,6 +110,13 @@ const MODALS = { ...accountModalStyle, }, + SHAPESHIFT_DEPOSIT_TX: { + contents: [ + h(ShapeshiftDepositTxModal), + ], + ...accountModalStyle, + }, + NEW_ACCOUNT: { contents: [ h(NewAccountModal, {}, []), diff --git a/ui/app/components/modals/shapeshift-deposit-tx-modal.js b/ui/app/components/modals/shapeshift-deposit-tx-modal.js new file mode 100644 index 000000000..1fd1ade00 --- /dev/null +++ b/ui/app/components/modals/shapeshift-deposit-tx-modal.js @@ -0,0 +1,40 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const connect = require('react-redux').connect +const actions = require('../../actions') +const QrView = require('../qr-code') +const AccountModalContainer = require('./account-modal-container') + +function mapStateToProps (state) { + return { + Qr: state.appState.modal.modalState.Qr, + } +} + +function mapDispatchToProps (dispatch) { + return { + hideModal: () => { + dispatch(actions.hideModal()) + }, + } +} + +inherits(ShapeshiftDepositTxModal, Component) +function ShapeshiftDepositTxModal () { + Component.call(this) + +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)(ShapeshiftDepositTxModal) + +ShapeshiftDepositTxModal.prototype.render = function () { + const { Qr } = this.props + + return h(AccountModalContainer, { + }, [ + h('div', {}, [ + h(QrView, {key: 'qr', Qr}), + ]) + ]) +} diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 82541704e..97d937aca 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -57,7 +57,7 @@ TxList.prototype.renderTransaction = function () { TxList.prototype.renderTransactionListItem = function (transaction, conversionRate) { // console.log({transaction}) // refer to transaction-list.js:line 58 - const shapeshiftProps = {}; + if (transaction.key === 'shapeshift') { return h(ShiftListItem, transaction) } -- cgit v1.2.3 From 47ebcbb2ed09a4cd4b062c5fa4cb6d259369149f Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 29 Sep 2017 07:40:50 -0230 Subject: Token menu ui. --- ui/app/components/dropdowns/token-menu-dropdown.js | 38 ++++++++++++++++++++++ ui/app/components/token-cell.js | 18 ++++++++++ 2 files changed, 56 insertions(+) create mode 100644 ui/app/components/dropdowns/token-menu-dropdown.js (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/token-menu-dropdown.js b/ui/app/components/dropdowns/token-menu-dropdown.js new file mode 100644 index 000000000..b948534c2 --- /dev/null +++ b/ui/app/components/dropdowns/token-menu-dropdown.js @@ -0,0 +1,38 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits + +module.exports = TokenMenuDropdown + +inherits(TokenMenuDropdown, Component) +function TokenMenuDropdown () { + Component.call(this) + + this.onClose = this.onClose.bind(this) +} + +TokenMenuDropdown.prototype.onClose = function (e) { + e.stopPropagation() + this.props.onClose() +} + +TokenMenuDropdown.prototype.render = function () { + return h('div.token-menu-dropdown', {}, [ + h('div.token-menu-dropdown__close-area', { + onClick: this.onClose, + }), + h('div.token-menu-dropdown__container', {}, [ + h('div.token-menu-dropdown__options', {}, [ + + h('div.token-menu-dropdown__option', { + onClick: (e) => { + e.stopPropagation() + console.log('div.token-menu-dropdown__option!') + }, + }, 'Hide Token') + + ]), + ]), + ]) +} + diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index e87d2c859..df73577e9 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -8,6 +8,8 @@ const selectors = require('../selectors') const actions = require('../actions') const { conversionUtil } = require('../conversion-util') +const TokenMenuDropdown = require('./dropdowns/token-menu-dropdown.js') + function mapStateToProps (state) { return { network: state.metamask.network, @@ -32,6 +34,10 @@ module.exports = connect(mapStateToProps, mapDispatchToProps)(TokenCell) inherits(TokenCell, Component) function TokenCell () { Component.call(this) + + this.state = { + tokenMenuOpen: false, + } } TokenCell.prototype.componentWillMount = function () { @@ -44,6 +50,7 @@ TokenCell.prototype.componentWillMount = function () { } TokenCell.prototype.render = function () { + const { tokenMenuOpen } = this.state const props = this.props const { address, @@ -104,6 +111,17 @@ TokenCell.prototype.render = function () { }, formattedUSD), ]), + h('i.fa.fa-ellipsis-h.fa-lg.token-list-item__ellipsis.cursor-pointer', { + onClick: (e) => { + e.stopPropagation() + this.setState({ tokenMenuOpen: true }) + }, + }), + + tokenMenuOpen && h(TokenMenuDropdown, { + onClose: () => this.setState({ tokenMenuOpen: false }), + }), + /* h('button', { onClick: this.send.bind(this, address), -- cgit v1.2.3 From d206f183f5a07787535acd196c506145f00a199e Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 29 Sep 2017 16:33:29 -0230 Subject: Hide token confirmation modal ui --- ui/app/components/dropdowns/token-menu-dropdown.js | 18 +++++- .../modals/hide-token-confirmation-modal.js | 66 ++++++++++++++++++++++ ui/app/components/modals/modal.js | 15 +++++ ui/app/components/token-cell.js | 1 + 4 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 ui/app/components/modals/hide-token-confirmation-modal.js (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/token-menu-dropdown.js b/ui/app/components/dropdowns/token-menu-dropdown.js index b948534c2..0f4bc2b87 100644 --- a/ui/app/components/dropdowns/token-menu-dropdown.js +++ b/ui/app/components/dropdowns/token-menu-dropdown.js @@ -1,8 +1,19 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits +const connect = require('react-redux').connect +const actions = require('../../actions') + +module.exports = connect(null, mapDispatchToProps)(TokenMenuDropdown) + +function mapDispatchToProps (dispatch) { + return { + showHideTokenConfirmationModal: (token) => { + dispatch(actions.showModal({ name: 'HIDE_TOKEN_CONFIRMATION', token })) + } + } +} -module.exports = TokenMenuDropdown inherits(TokenMenuDropdown, Component) function TokenMenuDropdown () { @@ -17,6 +28,8 @@ TokenMenuDropdown.prototype.onClose = function (e) { } TokenMenuDropdown.prototype.render = function () { + const { showHideTokenConfirmationModal } = this.props + return h('div.token-menu-dropdown', {}, [ h('div.token-menu-dropdown__close-area', { onClick: this.onClose, @@ -27,7 +40,7 @@ TokenMenuDropdown.prototype.render = function () { h('div.token-menu-dropdown__option', { onClick: (e) => { e.stopPropagation() - console.log('div.token-menu-dropdown__option!') + showHideTokenConfirmationModal(this.props.token) }, }, 'Hide Token') @@ -35,4 +48,3 @@ TokenMenuDropdown.prototype.render = function () { ]), ]) } - diff --git a/ui/app/components/modals/hide-token-confirmation-modal.js b/ui/app/components/modals/hide-token-confirmation-modal.js new file mode 100644 index 000000000..d3f06b483 --- /dev/null +++ b/ui/app/components/modals/hide-token-confirmation-modal.js @@ -0,0 +1,66 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const connect = require('react-redux').connect +const actions = require('../../actions') +const Identicon = require('../identicon') + +function mapStateToProps (state) { + return { + network: state.metamask.network, + token: state.appState.modal.modalState.token, + } +} + +function mapDispatchToProps (dispatch) { + return {} +} + +inherits(HideTokenConfirmationModal, Component) +function HideTokenConfirmationModal () { + Component.call(this) + + this.state = {} +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)(HideTokenConfirmationModal) + +HideTokenConfirmationModal.prototype.render = function () { + const { token, network } = this.props + const { symbol, address } = token + + return h('div.hide-token-confirmation', {}, [ + h('div.hide-token-confirmation__container', { + }, [ + h('div.hide-token-confirmation__title', {}, [ + 'Hide Token?', + ]), + + h(Identicon, { + className: 'hide-token-confirmation__identicon', + diameter: 45, + address, + network, + }), + + h('div.hide-token-confirmation__symbol', {}, symbol), + + h('div.hide-token-confirmation__copy', {}, [ + 'You can add this token back in the future by going go to “Add token” in your accounts options menu.', + ]), + + h('div.hide-token-confirmation__buttons', {}, [ + h('button.btn-clear', { + onClick: () => {}, + }, [ + 'CANCEL', + ]), + h('button.btn-clear', { + onClick: () => {}, + }, [ + 'HIDE', + ]), + ]), + ]), + ]) +} diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 765e46312..7247d840e 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -14,6 +14,7 @@ const EditAccountNameModal = require('./edit-account-name-modal') const ExportPrivateKeyModal = require('./export-private-key-modal') const NewAccountModal = require('./new-account-modal') const ShapeshiftDepositTxModal = require('./shapeshift-deposit-tx-modal.js') +const HideTokenConfirmationModal = require('./hide-token-confirmation-modal') const accountModalStyle = { mobileModalStyle: { @@ -117,6 +118,20 @@ const MODALS = { ...accountModalStyle, }, + HIDE_TOKEN_CONFIRMATION: { + contents: [ + h(HideTokenConfirmationModal, {}, []), + ], + mobileModalStyle: { + width: '95%', + top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh', + }, + laptopModalStyle: { + width: '449px', + top: 'calc(33% + 45px)', + }, + }, + NEW_ACCOUNT: { contents: [ h(NewAccountModal, {}, []), diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index df73577e9..ad431df69 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -120,6 +120,7 @@ TokenCell.prototype.render = function () { tokenMenuOpen && h(TokenMenuDropdown, { onClose: () => this.setState({ tokenMenuOpen: false }), + token: { symbol, address }, }), /* -- cgit v1.2.3 From 45dbd017e65e5698db4580c77d723bface0e9b63 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 2 Oct 2017 21:58:15 -0230 Subject: Add needed iterator in tx-list and path to account in selectors. --- ui/app/components/tx-list.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 97d937aca..137cccf37 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -50,7 +50,11 @@ TxList.prototype.renderTransaction = function () { const { txsToRender, conversionRate } = this.props return txsToRender.length ? txsToRender.map((transaction, i) => this.renderTransactionListItem(transaction, conversionRate)) - : [h('div.tx-list-item.tx-list-item--empty', [ 'No Transactions' ])] + : [h( + 'div.tx-list-item.tx-list-item--empty', + { key: 'tx-list-none' }, + [ 'No Transactions' ], + )] } // TODO: Consider moving TxListItem into a separate component @@ -88,6 +92,7 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa txParams: transaction.txParams, transactionStatus, transActionId, + key: transActionId, dateString, address, transactionAmount, -- cgit v1.2.3 From ac4868170f4c61d13291389d01bf1002fe240ed4 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 3 Oct 2017 14:55:52 -0230 Subject: Enables remove token and ensures add/remove update the list without need for refresh. --- ui/app/components/dropdowns/token-menu-dropdown.js | 1 + .../components/modals/hide-token-confirmation-modal.js | 16 ++++++++++++---- ui/app/components/token-list.js | 14 ++++++++++---- 3 files changed, 23 insertions(+), 8 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/token-menu-dropdown.js b/ui/app/components/dropdowns/token-menu-dropdown.js index 0f4bc2b87..7234a9b21 100644 --- a/ui/app/components/dropdowns/token-menu-dropdown.js +++ b/ui/app/components/dropdowns/token-menu-dropdown.js @@ -41,6 +41,7 @@ TokenMenuDropdown.prototype.render = function () { onClick: (e) => { e.stopPropagation() showHideTokenConfirmationModal(this.props.token) + this.props.onClose() }, }, 'Hide Token') diff --git a/ui/app/components/modals/hide-token-confirmation-modal.js b/ui/app/components/modals/hide-token-confirmation-modal.js index d3f06b483..fa3ad0b1e 100644 --- a/ui/app/components/modals/hide-token-confirmation-modal.js +++ b/ui/app/components/modals/hide-token-confirmation-modal.js @@ -13,7 +13,15 @@ function mapStateToProps (state) { } function mapDispatchToProps (dispatch) { - return {} + return { + hideModal: () => dispatch(actions.hideModal()), + hideToken: address => { + dispatch(actions.removeToken(address)) + .then(() => { + dispatch(actions.hideModal()) + }) + }, + } } inherits(HideTokenConfirmationModal, Component) @@ -26,7 +34,7 @@ function HideTokenConfirmationModal () { module.exports = connect(mapStateToProps, mapDispatchToProps)(HideTokenConfirmationModal) HideTokenConfirmationModal.prototype.render = function () { - const { token, network } = this.props + const { token, network, hideToken, hideModal } = this.props const { symbol, address } = token return h('div.hide-token-confirmation', {}, [ @@ -51,12 +59,12 @@ HideTokenConfirmationModal.prototype.render = function () { h('div.hide-token-confirmation__buttons', {}, [ h('button.btn-clear', { - onClick: () => {}, + onClick: () => hideModal(), }, [ 'CANCEL', ]), h('button.btn-clear', { - onClick: () => {}, + onClick: () => hideToken(address), }, [ 'HIDE', ]), diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js index 0efa89c63..fb11be826 100644 --- a/ui/app/components/token-list.js +++ b/ui/app/components/token-list.js @@ -27,7 +27,6 @@ for (const address in contracts) { module.exports = connect(mapStateToProps)(TokenList) - inherits(TokenList, Component) function TokenList () { this.state = { @@ -129,15 +128,22 @@ TokenList.prototype.componentDidUpdate = function (nextProps) { const { network: oldNet, userAddress: oldAddress, + tokens, } = this.props const { network: newNet, userAddress: newAddress, + tokens: newTokens, } = nextProps - if (newNet === 'loading') return - if (!oldNet || !newNet || !oldAddress || !newAddress) return - if (oldAddress === newAddress && oldNet === newNet) return + const isLoading = newNet === 'loading' + const missingInfo = !oldNet || !newNet || !oldAddress || !newAddress + const sameUserAndNetwork = oldAddress === newAddress && oldNet === newNet + const shouldUpdateTokens = isLoading || missingInfo || sameUserAndNetwork + + const tokensLengthUnchanged = tokens.length === newTokens.length + + if (tokensLengthUnchanged && shouldUpdateTokens) return this.setState({ isLoading: true }) this.createFreshTokenTracker() -- cgit v1.2.3 From 49aa6e73eadc5b343353c4312afc1e3b40dc18df Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 4 Oct 2017 21:01:12 -0230 Subject: Edit account modal shows and allows editing of name from props, not just placeholder. --- ui/app/components/modals/edit-account-name-modal.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/edit-account-name-modal.js b/ui/app/components/modals/edit-account-name-modal.js index 5c25ac245..e2361140d 100644 --- a/ui/app/components/modals/edit-account-name-modal.js +++ b/ui/app/components/modals/edit-account-name-modal.js @@ -24,10 +24,11 @@ function mapDispatchToProps (dispatch) { } inherits(EditAccountNameModal, Component) -function EditAccountNameModal () { +function EditAccountNameModal (props) { Component.call(this) + this.state = { - inputText: '', + inputText: props.identity.name, } } -- cgit v1.2.3 From 80463072b5c0c9e826582e066fbc962b667ee355 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 6 Oct 2017 02:04:00 -0230 Subject: UI for readonly from component. From dropdown opening and closing. Mockdata. --- ui/app/components/send/from-dropdown.js | 94 +++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 ui/app/components/send/from-dropdown.js (limited to 'ui/app/components') diff --git a/ui/app/components/send/from-dropdown.js b/ui/app/components/send/from-dropdown.js new file mode 100644 index 000000000..c438cefd5 --- /dev/null +++ b/ui/app/components/send/from-dropdown.js @@ -0,0 +1,94 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const Identicon = require('../identicon') + +module.exports = FromDropdown + +inherits(FromDropdown, Component) +function FromDropdown () { + Component.call(this) +} + +FromDropdown.prototype.renderSingleIdentity = function ( + account, + handleClick, + inList = false, + selectedIdentity = {} +) { + const { identity, balancesToRender } = account + const { name, address } = identity + const { primary, secondary } = balancesToRender + + const iconType = inList ? 'check' : 'caret-down' + const showIcon = !inList || address === selectedIdentity.address + + return h('div.send-v2__from-dropdown__account', { + onClick: () => handleClick(identity), + }, [ + + h('div.send-v2__from-dropdown__top-row', {}, [ + + h( + Identicon, + { + address, + diameter: 18, + className: 'send-v2__from-dropdown__identicon', + }, + ), + + h('div.send-v2__from-dropdown__account-name', {}, name), + + showIcon && h(`i.fa.fa-${iconType}.fa-lg.send-v2__from-dropdown__${iconType}`), + + ]), + + h('div.send-v2__from-dropdown__account-primary-balance', {}, primary), + + h('div.send-v2__from-dropdown__account-secondary-balance', {}, secondary), + + ]) +} + +FromDropdown.prototype.renderDropdown = function (identities, selectedIdentity, closeDropdown) { + return h('div', {}, [ + + h('div.send-v2__from-dropdown__close-area', { + onClick: closeDropdown, + }), + + h('div.send-v2__from-dropdown__list', {}, [ + + ...identities.map(identity => this.renderSingleIdentity( + identity, + () => console.log('Select identity'), + true, + selectedIdentity + )) + + ]), + + ]) +} + +FromDropdown.prototype.render = function () { + const { + identities, + selectedIdentity, + setFromField, + openDropdown, + closeDropdown, + dropdownOpen, + } = this.props + + return h('div.send-v2__from-dropdown', {}, [ + + this.renderSingleIdentity(selectedIdentity, openDropdown), + + dropdownOpen && this.renderDropdown(identities, selectedIdentity.identity, closeDropdown), + + ]) + +} + -- cgit v1.2.3 From 71d6463984f040b2aa495a13429f6ea3505defaf Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 9 Oct 2017 20:47:52 -0230 Subject: Refactor 'rendersingleidentity' to a stand alone account-list-item component. --- ui/app/components/send/account-list-item.js | 51 +++++++++++++++++++++ ui/app/components/send/from-dropdown.js | 69 +++++++++-------------------- 2 files changed, 71 insertions(+), 49 deletions(-) create mode 100644 ui/app/components/send/account-list-item.js (limited to 'ui/app/components') diff --git a/ui/app/components/send/account-list-item.js b/ui/app/components/send/account-list-item.js new file mode 100644 index 000000000..b11527d95 --- /dev/null +++ b/ui/app/components/send/account-list-item.js @@ -0,0 +1,51 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const connect = require('react-redux').connect +const Identicon = require('../identicon') + +inherits(AccountListItem, Component) +function AccountListItem () { + Component.call(this) +} + +module.exports = AccountListItem + +AccountListItem.prototype.render = function () { + const { + account, + handleClick, + icon = null, + } = this.props + + const { identity, balancesToRender } = account + const { name, address } = identity + const { primary, secondary } = balancesToRender + + return h('div.account-list-item', { + onClick: () => handleClick(identity), + }, [ + + h('div.account-list-item__top-row', {}, [ + + h( + Identicon, + { + address, + diameter: 18, + className: 'account-list-item__identicon', + }, + ), + + h('div.account-list-item__account-name', {}, name), + + icon && h('div.account-list-item__icon', [icon]), + + ]), + + h('div.account-list-item__account-primary-balance', {}, primary), + + h('div.account-list-item__account-secondary-balance', {}, secondary), + + ]) +} \ No newline at end of file diff --git a/ui/app/components/send/from-dropdown.js b/ui/app/components/send/from-dropdown.js index c438cefd5..fb0a00cc2 100644 --- a/ui/app/components/send/from-dropdown.js +++ b/ui/app/components/send/from-dropdown.js @@ -2,6 +2,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits const Identicon = require('../identicon') +const AccountListItem = require('./account-list-item') module.exports = FromDropdown @@ -10,48 +11,15 @@ function FromDropdown () { Component.call(this) } -FromDropdown.prototype.renderSingleIdentity = function ( - account, - handleClick, - inList = false, - selectedIdentity = {} -) { - const { identity, balancesToRender } = account - const { name, address } = identity - const { primary, secondary } = balancesToRender +FromDropdown.prototype.getListItemIcon = function (currentAccount, selectedAccount) { + const listItemIcon = h(`i.fa.fa-check.fa-lg`, { style: { color: '#02c9b1' } }) - const iconType = inList ? 'check' : 'caret-down' - const showIcon = !inList || address === selectedIdentity.address - - return h('div.send-v2__from-dropdown__account', { - onClick: () => handleClick(identity), - }, [ - - h('div.send-v2__from-dropdown__top-row', {}, [ - - h( - Identicon, - { - address, - diameter: 18, - className: 'send-v2__from-dropdown__identicon', - }, - ), - - h('div.send-v2__from-dropdown__account-name', {}, name), - - showIcon && h(`i.fa.fa-${iconType}.fa-lg.send-v2__from-dropdown__${iconType}`), - - ]), - - h('div.send-v2__from-dropdown__account-primary-balance', {}, primary), - - h('div.send-v2__from-dropdown__account-secondary-balance', {}, secondary), - - ]) + return currentAccount.identity.address === selectedAccount.identity.address + ? listItemIcon + : null } -FromDropdown.prototype.renderDropdown = function (identities, selectedIdentity, closeDropdown) { +FromDropdown.prototype.renderDropdown = function (accounts, selectedAccount, closeDropdown) { return h('div', {}, [ h('div.send-v2__from-dropdown__close-area', { @@ -60,12 +28,11 @@ FromDropdown.prototype.renderDropdown = function (identities, selectedIdentity, h('div.send-v2__from-dropdown__list', {}, [ - ...identities.map(identity => this.renderSingleIdentity( - identity, - () => console.log('Select identity'), - true, - selectedIdentity - )) + ...accounts.map(account => h(AccountListItem, { + account, + handleClick: () => console.log('Select identity'), + icon: this.getListItemIcon(account, selectedAccount), + })) ]), @@ -74,8 +41,8 @@ FromDropdown.prototype.renderDropdown = function (identities, selectedIdentity, FromDropdown.prototype.render = function () { const { - identities, - selectedIdentity, + accounts, + selectedAccount, setFromField, openDropdown, closeDropdown, @@ -84,9 +51,13 @@ FromDropdown.prototype.render = function () { return h('div.send-v2__from-dropdown', {}, [ - this.renderSingleIdentity(selectedIdentity, openDropdown), + h(AccountListItem, { + account: selectedAccount, + handleClick: openDropdown, + icon: h(`i.fa.fa-caret-down.fa-lg`, { style: { color: '#dedede' } }) + }), - dropdownOpen && this.renderDropdown(identities, selectedIdentity.identity, closeDropdown), + dropdownOpen && this.renderDropdown(accounts, selectedAccount, closeDropdown), ]) -- cgit v1.2.3 From 119c2b24238b84d5a9e3beabe572da42f8e2ffcb Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 10 Oct 2017 14:16:57 -0700 Subject: Confirm eth v2 --- ui/app/components/pending-tx/confirm-send-ether.js | 38 +++++++++++----------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 330a55cce..537a9a659 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -192,7 +192,7 @@ ConfirmSendEther.prototype.render = function () { this.inputs = [] return ( - h('div.flex-column.flex-grow.confirm-screen-container', { + h('div.confirm-screen-container', { style: { minWidth: '355px' }, }, [ // Main Send token Card @@ -202,6 +202,7 @@ ConfirmSendEther.prototype.render = function () { onClick: () => backToAccountDetail(selectedAddress), }, 'BACK'), h('div.confirm-screen-title', 'Confirm Transaction'), + h('div.confirm-screen-header-tip'), ]), h('div.flex-row.flex-center.confirm-screen-identicons', [ h('div.confirm-screen-account-wrapper', [ @@ -209,11 +210,11 @@ ConfirmSendEther.prototype.render = function () { Identicon, { address: fromAddress, - diameter: 100, + diameter: 60, }, ), h('span.confirm-screen-account-name', fromName), - h('span.confirm-screen-account-number', fromAddress.slice(fromAddress.length - 4)), + // h('span.confirm-screen-account-number', fromAddress.slice(fromAddress.length - 4)), ]), h('i.fa.fa-arrow-right.fa-lg'), h('div.confirm-screen-account-wrapper', [ @@ -221,27 +222,27 @@ ConfirmSendEther.prototype.render = function () { Identicon, { address: txParams.to, - diameter: 100, + diameter: 60, }, ), h('span.confirm-screen-account-name', toName), - h('span.confirm-screen-account-number', toAddress.slice(toAddress.length - 4)), + // h('span.confirm-screen-account-number', toAddress.slice(toAddress.length - 4)), ]), ]), - h('h3.flex-center.confirm-screen-sending-to-message', { - style: { - textAlign: 'center', - fontSize: '16px', - }, - }, [ - `You're sending to Recipient ...${toAddress.slice(toAddress.length - 4)}`, - ]), + // h('h3.flex-center.confirm-screen-sending-to-message', { + // style: { + // textAlign: 'center', + // fontSize: '16px', + // }, + // }, [ + // `You're sending to Recipient ...${toAddress.slice(toAddress.length - 4)}`, + // ]), h('h3.flex-center.confirm-screen-send-amount', [`$${amountInUSD}`]), h('h3.flex-center.confirm-screen-send-amount-currency', [ 'USD' ]), h('div.flex-center.confirm-memo-wrapper', [ - h('h3.confirm-screen-send-memo', [ memo ]), + h('h3.confirm-screen-send-memo', [ memo ? `"${memo}"` : '' ]), ]), h('div.confirm-screen-rows', [ @@ -365,17 +366,16 @@ ConfirmSendEther.prototype.render = function () { // } ]), - h('form#pending-tx-form.flex-column.flex-center', { + h('form#pending-tx-form', { onSubmit: this.onSubmit, }, [ - - // Accept Button - h('button.confirm-screen-confirm-button', ['CONFIRM']), - // Cancel Button h('div.cancel.btn-light.confirm-screen-cancel-button', { onClick: (event) => this.cancel(event, txMeta), }, 'CANCEL'), + + // Accept Button + h('button.confirm-screen-confirm-button', ['CONFIRM']), ]), ]) ) -- cgit v1.2.3 From c221f5ce79a1e24df4672e16bda8e85c434e11ba Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 10 Oct 2017 14:30:20 -0700 Subject: Confirm Token and Confirm Contract v2 --- .../pending-tx/confirm-deploy-contract.js | 33 ++++++++--------- ui/app/components/pending-tx/confirm-send-token.js | 42 +++++++++++----------- 2 files changed, 39 insertions(+), 36 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-deploy-contract.js b/ui/app/components/pending-tx/confirm-deploy-contract.js index 386e14afe..ea4aa1dde 100644 --- a/ui/app/components/pending-tx/confirm-deploy-contract.js +++ b/ui/app/components/pending-tx/confirm-deploy-contract.js @@ -270,7 +270,8 @@ ConfirmDeployContract.prototype.render = function () { h('button.confirm-screen-back-button', { onClick: () => backToAccountDetail(selectedAddress), }, 'BACK'), - h('div.confirm-screen-title', 'Confirm Transaction'), + h('div.confirm-screen-title', 'Confirm Contract'), + h('div.confirm-screen-header-tip'), ]), h('div.flex-row.flex-center.confirm-screen-identicons', [ h('div.confirm-screen-account-wrapper', [ @@ -278,11 +279,11 @@ ConfirmDeployContract.prototype.render = function () { Identicon, { address: fromAddress, - diameter: 100, + diameter: 60, }, ), h('span.confirm-screen-account-name', fromName), - h('span.confirm-screen-account-number', fromAddress.slice(fromAddress.length - 4)), + // h('span.confirm-screen-account-number', fromAddress.slice(fromAddress.length - 4)), ]), h('i.fa.fa-arrow-right.fa-lg'), h('div.confirm-screen-account-wrapper', [ @@ -292,14 +293,14 @@ ConfirmDeployContract.prototype.render = function () { ]), ]), - h('h3.flex-center.confirm-screen-sending-to-message', { - style: { - textAlign: 'center', - fontSize: '16px', - }, - }, [ - `You're deploying a new contract.`, - ]), + // h('h3.flex-center.confirm-screen-sending-to-message', { + // style: { + // textAlign: 'center', + // fontSize: '16px', + // }, + // }, [ + // `You're deploying a new contract.`, + // ]), this.renderHeroAmount(), @@ -326,17 +327,17 @@ ConfirmDeployContract.prototype.render = function () { ]), ]), - h('form#pending-tx-form.flex-column.flex-center', { + h('form#pending-tx-form', { onSubmit: this.onSubmit, }, [ - - // Accept Button - h('button.confirm-screen-confirm-button', ['CONFIRM']), - // Cancel Button h('div.cancel.btn-light.confirm-screen-cancel-button', { onClick: (event) => this.cancel(event, txMeta), }, 'CANCEL'), + + // Accept Button + h('button.confirm-screen-confirm-button', ['CONFIRM']), + ]), ]) ) diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index 384ac92cc..d6ff5a5af 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -155,7 +155,7 @@ ConfirmSendToken.prototype.renderHeroAmount = function () { h('h3.flex-center.confirm-screen-send-amount', `$${fiatAmount}`), h('h3.flex-center.confirm-screen-send-amount-currency', 'USD'), h('div.flex-center.confirm-memo-wrapper', [ - h('h3.confirm-screen-send-memo', memo), + h('h3.confirm-screen-send-memo', [ memo ? `"${memo}"` : '' ]), ]), ]) ) @@ -164,7 +164,7 @@ ConfirmSendToken.prototype.renderHeroAmount = function () { h('h3.flex-center.confirm-screen-send-amount', tokenAmount), h('h3.flex-center.confirm-screen-send-amount-currency', symbol), h('div.flex-center.confirm-memo-wrapper', [ - h('h3.confirm-screen-send-memo', memo), + h('h3.confirm-screen-send-memo', [ memo ? `"${memo}"` : '' ]), ]), ]) ) @@ -242,7 +242,7 @@ ConfirmSendToken.prototype.render = function () { this.inputs = [] return ( - h('div.flex-column.flex-grow.confirm-screen-container', { + h('div.confirm-screen-container', { style: { minWidth: '355px' }, }, [ // Main Send token Card @@ -252,6 +252,7 @@ ConfirmSendToken.prototype.render = function () { onClick: () => backToAccountDetail(selectedAddress), }, 'BACK'), h('div.confirm-screen-title', 'Confirm Transaction'), + h('div.confirm-screen-header-tip'), ]), h('div.flex-row.flex-center.confirm-screen-identicons', [ h('div.confirm-screen-account-wrapper', [ @@ -259,11 +260,11 @@ ConfirmSendToken.prototype.render = function () { Identicon, { address: fromAddress, - diameter: 100, + diameter: 60, }, ), h('span.confirm-screen-account-name', fromName), - h('span.confirm-screen-account-number', fromAddress.slice(fromAddress.length - 4)), + // h('span.confirm-screen-account-number', fromAddress.slice(fromAddress.length - 4)), ]), h('i.fa.fa-arrow-right.fa-lg'), h('div.confirm-screen-account-wrapper', [ @@ -271,22 +272,22 @@ ConfirmSendToken.prototype.render = function () { Identicon, { address: txParams.to, - diameter: 100, + diameter: 60, }, ), h('span.confirm-screen-account-name', toName), - h('span.confirm-screen-account-number', toAddress.slice(toAddress.length - 4)), + // h('span.confirm-screen-account-number', toAddress.slice(toAddress.length - 4)), ]), ]), - h('h3.flex-center.confirm-screen-sending-to-message', { - style: { - textAlign: 'center', - fontSize: '16px', - }, - }, [ - `You're sending to Recipient ...${toAddress.slice(toAddress.length - 4)}`, - ]), + // h('h3.flex-center.confirm-screen-sending-to-message', { + // style: { + // textAlign: 'center', + // fontSize: '16px', + // }, + // }, [ + // `You're sending to Recipient ...${toAddress.slice(toAddress.length - 4)}`, + // ]), this.renderHeroAmount(), @@ -314,18 +315,19 @@ ConfirmSendToken.prototype.render = function () { ]), ]), - h('form#pending-tx-form.flex-column.flex-center', { + h('form#pending-tx-form', { onSubmit: this.onSubmit, }, [ - - // Accept Button - h('button.confirm-screen-confirm-button', ['CONFIRM']), - // Cancel Button h('div.cancel.btn-light.confirm-screen-cancel-button', { onClick: (event) => this.cancel(event, txMeta), }, 'CANCEL'), + + // Accept Button + h('button.confirm-screen-confirm-button', ['CONFIRM']), ]), + + ]) ) } -- cgit v1.2.3 From d4343fe7e57de1652d1401f70bf4c0c823d53820 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 10 Oct 2017 14:36:13 -0700 Subject: Fix recipient on send token --- ui/app/components/pending-tx/confirm-send-token.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index d6ff5a5af..92bba8f62 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -125,7 +125,9 @@ ConfirmSendToken.prototype.getGasFee = function () { } ConfirmSendToken.prototype.getData = function () { - const { identities } = this.props + const { identities, tokenData } = this.props + const { params = [] } = tokenData + const { value } = params[0] || {} const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} @@ -136,7 +138,7 @@ ConfirmSendToken.prototype.getData = function () { }, to: { address: txParams.to, - name: identities[txParams.to] ? identities[txParams.to].name : 'New Recipient', + name: identities[value] ? identities[value].name : 'New Recipient', }, memo: txParams.memo || '', } -- cgit v1.2.3 From fbab0f3a1f1bf78fdaf6b5639fb6a23d996f3645 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 6 Oct 2017 08:00:45 -0230 Subject: Send v2 to autocomplete. --- ui/app/components/send/to-autocomplete.js | 55 +++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 ui/app/components/send/to-autocomplete.js (limited to 'ui/app/components') diff --git a/ui/app/components/send/to-autocomplete.js b/ui/app/components/send/to-autocomplete.js new file mode 100644 index 000000000..3808bf496 --- /dev/null +++ b/ui/app/components/send/to-autocomplete.js @@ -0,0 +1,55 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const Identicon = require('../identicon') + +module.exports = ToAutoComplete + +inherits(ToAutoComplete, Component) +function ToAutoComplete () { + Component.call(this) +} + +ToAutoComplete.prototype.render = function () { + const { to, identities, onChange } = this.props + + return h('div.send-v2__to-autocomplete', [ + + h('input.send-v2__to-autocomplete__input', { + name: 'address', + list: 'addresses', + placeholder: 'Recipient Address', + value: to, + onChange, + // onBlur: () => { + // this.setErrorsFor('to') + // }, + onFocus: event => { + // this.clearErrorsFor('to') + to && event.target.select() + }, + }), + + h('datalist#addresses', [ + // Corresponds to the addresses owned. + ...Object.entries(identities).map(([key, { address, name }]) => { + return h('option', { + value: address, + label: name, + key: address, + }) + }), + // Corresponds to previously sent-to addresses. + // ...addressBook.map(({ address, name }) => { + // return h('option', { + // value: address, + // label: name, + // key: address, + // }) + // }), + ]), + + ]) + +} + -- cgit v1.2.3 From ea7926c211965e2e529e5795a4e1655e97e32144 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 9 Oct 2017 13:55:23 -0230 Subject: Adds amount and gas field to sendV2. --- ui/app/components/send/currency-display.js | 85 ++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 ui/app/components/send/currency-display.js (limited to 'ui/app/components') diff --git a/ui/app/components/send/currency-display.js b/ui/app/components/send/currency-display.js new file mode 100644 index 000000000..e0147012f --- /dev/null +++ b/ui/app/components/send/currency-display.js @@ -0,0 +1,85 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const Identicon = require('../identicon') +const AutosizeInput = require('react-input-autosize').default +const { conversionUtil } = require('../../conversion-util') + +module.exports = CurrencyDisplay + +inherits(CurrencyDisplay, Component) +function CurrencyDisplay () { + Component.call(this) + + this.state = { + minWidth: null, + } +} + +function isValidNumber (text) { + const re = /^([1-9]\d*|0)(\.|\.\d*)?$/ + return re.test(text) +} + +CurrencyDisplay.prototype.componentDidMount = function () { + this.setState({ minWidth: this.refs.currencyDisplayInput.sizer.scrollWidth + 10 }) +} + +CurrencyDisplay.prototype.render = function () { + const { + className, + primaryCurrency, + convertedCurrency, + value = '', + placeholder = '0', + conversionRate, + convertedPrefix = '', + readOnly = false, + handleChange, + inputFontSize, + } = this.props + const { minWidth } = this.state + + const convertedValue = conversionUtil(value, { + fromNumericBase: 'dec', + fromCurrency: primaryCurrency, + toCurrency: convertedCurrency, + conversionRate, + }) + + return h('div.currency-display', { + className, + }, [ + + h('div.currency-display__primary-row', [ + + h(AutosizeInput, { + ref: 'currencyDisplayInput', + className: 'currency-display__input-wrapper', + inputClassName: 'currency-display__input', + value, + placeholder, + readOnly, + minWidth, + onChange: (event) => { + const newValue = event.target.value + if (newValue && !isValidNumber(newValue)) { + event.preventDefault() + } + else { + handleChange(newValue) + } + }, + style: { fontSize: inputFontSize }, + }), + + h('span.currency-display__primary-currency', {}, primaryCurrency), + + ]), + + h('div.currency-display__converted-value', {}, `${convertedPrefix}${convertedValue} ${convertedCurrency}`), + + ]) + +} + -- cgit v1.2.3 From 2898914a544c4f934cdbe592b7b44df4d08127c8 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 10 Oct 2017 22:15:31 -0230 Subject: Send v2 amount unit moves correctly. --- ui/app/components/send/currency-display.js | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send/currency-display.js b/ui/app/components/send/currency-display.js index e0147012f..2ffddb178 100644 --- a/ui/app/components/send/currency-display.js +++ b/ui/app/components/send/currency-display.js @@ -13,6 +13,7 @@ function CurrencyDisplay () { this.state = { minWidth: null, + currentScrollWidth: null, } } @@ -22,7 +23,24 @@ function isValidNumber (text) { } CurrencyDisplay.prototype.componentDidMount = function () { - this.setState({ minWidth: this.refs.currencyDisplayInput.sizer.scrollWidth + 10 }) + this.setState({ + minWidth: this.refs.currencyDisplayInput.sizer.clientWidth + 10, + currentclientWidth: this.refs.currencyDisplayInput.sizer.clientWidth, + }) +} + +CurrencyDisplay.prototype.componentWillUpdate = function ({ value: nextValue }) { + const { value: currentValue } = this.props + const { currentclientWidth } = this.state + const newclientWidth = this.refs.currencyDisplayInput.sizer.clientWidth + + if (currentclientWidth !== newclientWidth) { + const clientWidthChange = newclientWidth - currentclientWidth + this.setState({ + minWidth: this.state.minWidth + clientWidthChange, + currentclientWidth: newclientWidth, + }) + } } CurrencyDisplay.prototype.render = function () { -- cgit v1.2.3 From 7ec77e0b4580c52bbf1723ed52d647c9d7516bd5 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 11 Oct 2017 10:48:27 -0230 Subject: Refactor amount input: dynamic input width with vanilla js. --- ui/app/components/send/currency-display.js | 73 +++++++++++++----------------- 1 file changed, 32 insertions(+), 41 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send/currency-display.js b/ui/app/components/send/currency-display.js index 2ffddb178..332d722ec 100644 --- a/ui/app/components/send/currency-display.js +++ b/ui/app/components/send/currency-display.js @@ -2,7 +2,6 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits const Identicon = require('../identicon') -const AutosizeInput = require('react-input-autosize').default const { conversionUtil } = require('../../conversion-util') module.exports = CurrencyDisplay @@ -17,29 +16,16 @@ function CurrencyDisplay () { } } -function isValidNumber (text) { +function isValidInput (text) { const re = /^([1-9]\d*|0)(\.|\.\d*)?$/ return re.test(text) } -CurrencyDisplay.prototype.componentDidMount = function () { - this.setState({ - minWidth: this.refs.currencyDisplayInput.sizer.clientWidth + 10, - currentclientWidth: this.refs.currencyDisplayInput.sizer.clientWidth, - }) -} +function resetCaretIfPastEnd (value, event) { + const caretPosition = event.target.selectionStart -CurrencyDisplay.prototype.componentWillUpdate = function ({ value: nextValue }) { - const { value: currentValue } = this.props - const { currentclientWidth } = this.state - const newclientWidth = this.refs.currencyDisplayInput.sizer.clientWidth - - if (currentclientWidth !== newclientWidth) { - const clientWidthChange = newclientWidth - currentclientWidth - this.setState({ - minWidth: this.state.minWidth + clientWidthChange, - currentclientWidth: newclientWidth, - }) + if (caretPosition > value.length) { + event.target.setSelectionRange(value.length, value.length) } } @@ -54,7 +40,6 @@ CurrencyDisplay.prototype.render = function () { convertedPrefix = '', readOnly = false, handleChange, - inputFontSize, } = this.props const { minWidth } = this.state @@ -71,27 +56,33 @@ CurrencyDisplay.prototype.render = function () { h('div.currency-display__primary-row', [ - h(AutosizeInput, { - ref: 'currencyDisplayInput', - className: 'currency-display__input-wrapper', - inputClassName: 'currency-display__input', - value, - placeholder, - readOnly, - minWidth, - onChange: (event) => { - const newValue = event.target.value - if (newValue && !isValidNumber(newValue)) { - event.preventDefault() - } - else { - handleChange(newValue) - } - }, - style: { fontSize: inputFontSize }, - }), - - h('span.currency-display__primary-currency', {}, primaryCurrency), + h('div.currency-display__input-wrapper', [ + + h('input.currency-display__input', { + value: `${value} ${primaryCurrency}`, + placeholder: `${0} ${primaryCurrency}`, + readOnly, + onChange: (event) => { + let newValue = event.target.value.split(' ')[0] + + if (newValue === '') { + handleChange('0') + } + else if (newValue.match(/^0[1-9]$/)) { + handleChange(newValue.match(/[1-9]/)[0]) + } + else if (newValue && !isValidInput(newValue)) { + event.preventDefault() + } + else { + handleChange(newValue) + } + }, + onKeyUp: event => resetCaretIfPastEnd(value, event), + onClick: event => resetCaretIfPastEnd(value, event), + }), + + ]), ]), -- cgit v1.2.3 From 57179d2b05a4efae06c2375e01e9a01a5519543b Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Thu, 12 Oct 2017 18:46:09 -0400 Subject: Various styling fixes --- ui/app/components/dropdowns/network-dropdown.js | 2 +- ui/app/components/network.js | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js index 4c578fbeb..567bf07a0 100644 --- a/ui/app/components/dropdowns/network-dropdown.js +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -102,7 +102,7 @@ NetworkDropdown.prototype.render = function () { key: 'main', closeMenu: () => this.props.hideNetworkDropdown(), onClick: () => props.setProviderType('mainnet'), - style: dropdownMenuItemStyle, + style: { ...dropdownMenuItemStyle, borderColor: '#038789' }, }, [ providerType === 'mainnet' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'), diff --git a/ui/app/components/network.js b/ui/app/components/network.js index 8424a479a..b24505750 100644 --- a/ui/app/components/network.js +++ b/ui/app/components/network.js @@ -1,5 +1,6 @@ const Component = require('react').Component const h = require('react-hyperscript') +const classnames = require('classnames'); const inherits = require('util').inherits const NetworkDropdownIcon = require('./dropdowns/components/network-dropdown-icon') @@ -61,7 +62,13 @@ Network.prototype.render = function () { } return ( - h('.network-component.pointer', { + h('div.network-component.pointer', { + className: classnames('network-component pointer', { + 'ethereum-network': providerName === 'mainnet', + 'ropsten-test-network': providerName === 'ropsten' || parseInt(networkNumber) === 3, + 'kovan-test-network': providerName === 'kovan', + 'rinkeby-test-network': providerName === 'rinkeby', + }), title: hoverText, onClick: (event) => this.props.onClick(event), }, [ @@ -71,7 +78,7 @@ Network.prototype.render = function () { return h('.network-indicator', [ h(NetworkDropdownIcon, { backgroundColor: '#038789', // $blue-lagoon - nonSelectBackgroundColor: '#15afb2' + nonSelectBackgroundColor: '#15afb2', }), h('.network-name', { style: { -- cgit v1.2.3 From 81f62a7443d47461b5f9b20f442392562458c79a Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Fri, 13 Oct 2017 02:10:58 -0400 Subject: Adding Account Dropdown V2 --- ui/app/components/account-menu/index.js | 56 ++++++++++++++++++++++++++ ui/app/components/dropdowns/components/menu.js | 44 ++++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 ui/app/components/account-menu/index.js create mode 100644 ui/app/components/dropdowns/components/menu.js (limited to 'ui/app/components') diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js new file mode 100644 index 000000000..7dc3d10a5 --- /dev/null +++ b/ui/app/components/account-menu/index.js @@ -0,0 +1,56 @@ +const inherits = require('util').inherits +const Component = require('react').Component +const connect = require('react-redux').connect +const h = require('react-hyperscript') +const actions = require('../../actions') +const { Menu, Item, Divider } = require('../dropdowns/components/menu') + +module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountMenu) + +inherits(AccountMenu, Component) +function AccountMenu () { Component.call(this) } + +function mapStateToProps (state) { + return { + selectedAddress: state.metamask.selectedAddress, + } +} + +function mapDispatchToProps () { + return {} +} + +AccountMenu.prototype.render = function () { + return h(Menu, { className: 'account-menu' }, [ + h(Item, { className: 'account-menu__header' }, [ + 'My Accounts', + h('button.account-menu__logout-button', 'Log out'), + ]), + h(Divider), + h(Item, { text: 'hi' }), + h(Divider), + h(Item, { + onClick: true, + icon: h('img', { src: 'images/plus-btn-white.svg' }), + text: 'Create Account', + }), + h(Item, { + onClick: true, + icon: h('img', { src: 'images/import-account.svg' }), + text: 'Import Account', + }), + h(Divider), + h(Item, { + onClick: true, + icon: h('img', { src: 'images/mm-info-icon.svg' }), + text: 'Info & Help', + }), + h(Item, { + onClick: true, + icon: h('img', { src: 'images/settings.svg' }), + text: 'Settings', + }), + ]) +} + + diff --git a/ui/app/components/dropdowns/components/menu.js b/ui/app/components/dropdowns/components/menu.js new file mode 100644 index 000000000..0cbe0f342 --- /dev/null +++ b/ui/app/components/dropdowns/components/menu.js @@ -0,0 +1,44 @@ +const inherits = require('util').inherits +const Component = require('react').Component +const h = require('react-hyperscript') + +inherits(Menu, Component) +function Menu () { Component.call(this) } + +Menu.prototype.render = function () { + const { className = '', children, isShowing } = this.props + return isShowing + ? h('div', { className: `menu ${className}` }, children) + : h('noscript') +} + +inherits(Item, Component) +function Item () { Component.call(this) } + +Item.prototype.render = function () { + const { + icon, + children, + text, + className = '', + onClick, + } = this.props + const itemClassName = `menu__item ${className} ${onClick ? 'menu__item--clickable' : ''}` + const iconComponent = icon ? h('div.menu__item__icon', [icon]) : null + const textComponent = text ? h('div.menu__item__text', text) : null + + return children + ? h('div', { className: itemClassName }, children) + : h('div.menu__item', { className: itemClassName }, [ iconComponent, textComponent ] + .filter(d => Boolean(d)) + ) +} + +inherits(Divider, Component) +function Divider () { Component.call(this) } + +Divider.prototype.render = function () { + return h('div.menu__divider') +} + +module.exports = { Menu, Item, Divider } -- cgit v1.2.3 From 803eaaf968161f16aaf72d59b979dfbb7fb9b352 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Fri, 13 Oct 2017 16:19:22 -0400 Subject: [NewUI] SendV2-#8: Send container handles tokens; gas info dynamic from state (#2364) * Adds memo field to send-v2. * Vertical align transaction with flexbox. * Customize Gas UI * Remove internal state from InputNumber and fix use in gastooltip. * Move customize-gas-modal to its own folder and minor cleanup * Create send container, get account info from state, and make currency display more reusable * Adjusts send-v2 and container for send-token. Dynamically getting suggested gas prices. --- .../customize-gas-modal/gas-modal-card.js | 55 +++++++++++++ .../components/customize-gas-modal/gas-slider.js | 50 ++++++++++++ ui/app/components/customize-gas-modal/index.js | 91 ++++++++++++++++++++++ ui/app/components/input-number.js | 29 +++---- ui/app/components/modals/modal.js | 26 +++++++ ui/app/components/send/account-list-item.js | 33 +++++--- ui/app/components/send/currency-display.js | 61 ++++++++++----- ui/app/components/send/from-dropdown.js | 2 +- ui/app/components/send/gas-fee-display-v2.js | 47 +++++++++++ ui/app/components/send/gas-tooltip.js | 4 +- ui/app/components/send/memo-textarea.js | 33 ++++++++ ui/app/components/send/send-v2-container.js | 62 +++++++++++++++ ui/app/components/send/to-autocomplete.js | 4 +- 13 files changed, 445 insertions(+), 52 deletions(-) create mode 100644 ui/app/components/customize-gas-modal/gas-modal-card.js create mode 100644 ui/app/components/customize-gas-modal/gas-slider.js create mode 100644 ui/app/components/customize-gas-modal/index.js create mode 100644 ui/app/components/send/gas-fee-display-v2.js create mode 100644 ui/app/components/send/memo-textarea.js create mode 100644 ui/app/components/send/send-v2-container.js (limited to 'ui/app/components') diff --git a/ui/app/components/customize-gas-modal/gas-modal-card.js b/ui/app/components/customize-gas-modal/gas-modal-card.js new file mode 100644 index 000000000..8e739ee40 --- /dev/null +++ b/ui/app/components/customize-gas-modal/gas-modal-card.js @@ -0,0 +1,55 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const InputNumber = require('../input-number.js') +const GasSlider = require('./gas-slider.js') + +module.exports = GasModalCard + +inherits(GasModalCard, Component) +function GasModalCard () { + Component.call(this) +} + +GasModalCard.prototype.render = function () { + const { + memo, + identities, + onChange, + unitLabel, + value, + min, + max, + step, + title, + copy + } = this.props + + return h('div.send-v2__gas-modal-card', [ + + h('div.send-v2__gas-modal-card__title', {}, title), + + h('div.send-v2__gas-modal-card__copy', {}, copy), + + h(InputNumber, { + unitLabel, + step, + max, + min, + placeholder: '0', + value, + onChange, + }), + + h(GasSlider, { + value, + step, + max, + min, + onChange, + }), + + ]) + +} + diff --git a/ui/app/components/customize-gas-modal/gas-slider.js b/ui/app/components/customize-gas-modal/gas-slider.js new file mode 100644 index 000000000..e76e96545 --- /dev/null +++ b/ui/app/components/customize-gas-modal/gas-slider.js @@ -0,0 +1,50 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits + +module.exports = GasSlider + +inherits(GasSlider, Component) +function GasSlider () { + Component.call(this) +} + +GasSlider.prototype.render = function () { + const { + memo, + identities, + onChange, + unitLabel, + value, + id, + step, + max, + min, + } = this.props + + return h('div.gas-slider', [ + + h('input.gas-slider__input', { + type: 'range', + step, + max, + min, + value, + id: 'gasSlider', + onChange: event => onChange(event.target.value), + }, []), + + h('div.gas-slider__bar', [ + + h('div.gas-slider__low'), + + h('div.gas-slider__mid'), + + h('div.gas-slider__high'), + + ]), + + ]) + +} + diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js new file mode 100644 index 000000000..91e2626b4 --- /dev/null +++ b/ui/app/components/customize-gas-modal/index.js @@ -0,0 +1,91 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const connect = require('react-redux').connect +const actions = require('../../actions') +const GasModalCard = require('./gas-modal-card') + +function mapStateToProps (state) { + return {} +} + +function mapDispatchToProps (dispatch) { + return { + hideModal: () => dispatch(actions.hideModal()), + } +} + +inherits(CustomizeGasModal, Component) +function CustomizeGasModal () { + Component.call(this) + + this.state = { + gasPrice: '0.23', + gasLimit: '25000', + } +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)(CustomizeGasModal) + +CustomizeGasModal.prototype.render = function () { + const { hideModal } = this.props + const { gasPrice, gasLimit } = this.state + + return h('div.send-v2__customize-gas', {}, [ + h('div', { + }, [ + h('div.send-v2__customize-gas__header', {}, [ + + h('div.send-v2__customize-gas__title', 'Customize Gas'), + + h('div.send-v2__customize-gas__close', { + onClick: hideModal, + }), + + ]), + + h('div.send-v2__customize-gas__body', {}, [ + + h(GasModalCard, { + value: gasPrice, + min: 0.0, + max: 5.0, + step: 0.01, + onChange: gasPrice => this.setState({ gasPrice }), + title: 'Gas Price', + copy: 'We calculate the suggested gas prices based on network success rates.', + }), + + h(GasModalCard, { + value: gasLimit, + min: 20000, + max: 100000, + step: 1, + onChange: gasLimit => this.setState({ gasLimit }), + title: 'Gas Limit', + copy: 'We calculate the suggested gas limit based on network success rates.', + }), + + ]), + + h('div.send-v2__customize-gas__footer', {}, [ + + h('div.send-v2__customize-gas__revert', { + onClick: () => console.log('Revert'), + }, ['Revert']), + + h('div.send-v2__customize-gas__buttons', [ + h('div.send-v2__customize-gas__cancel', { + onClick: this.props.hideModal, + }, ['CANCEL']), + + h('div.send-v2__customize-gas__save', { + onClick: () => console.log('Save'), + }, ['SAVE']), + ]) + + ]), + + ]), + ]) +} diff --git a/ui/app/components/input-number.js b/ui/app/components/input-number.js index 2824d77aa..16347fd5e 100644 --- a/ui/app/components/input-number.js +++ b/ui/app/components/input-number.js @@ -1,6 +1,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits +const { addCurrencies } = require('../conversion-util') module.exports = InputNumber @@ -8,49 +9,37 @@ inherits(InputNumber, Component) function InputNumber () { Component.call(this) - this.state = { - value: 0, - } - this.setValue = this.setValue.bind(this) } -InputNumber.prototype.componentWillMount = function () { - const { initValue = 0 } = this.props - - this.setState({ value: initValue }) -} - InputNumber.prototype.setValue = function (newValue) { - const { fixed, min = -1, onChange } = this.props + const { fixed, min = -1, max = Infinity, onChange } = this.props - if (fixed) newValue = Number(newValue.toFixed(4)) + newValue = Number(fixed ? newValue.toFixed(4) : newValue) - if (newValue >= min) { - this.setState({ value: newValue }) + if (newValue >= min && newValue <= max) { onChange(newValue) } } InputNumber.prototype.render = function () { - const { unitLabel, step = 1, placeholder } = this.props - const { value } = this.state + const { unitLabel, step = 1, placeholder, value = 0 } = this.props return h('div.customize-gas-input-wrapper', {}, [ h('input.customize-gas-input', { placeholder, type: 'number', - value, - onChange: (e) => this.setValue(Number(e.target.value)), + value: value, + onChange: (e) => this.setValue(e.target.value), }), h('span.gas-tooltip-input-detail', {}, [unitLabel]), h('div.gas-tooltip-input-arrows', {}, [ h('i.fa.fa-angle-up', { - onClick: () => this.setValue(value + step), + onClick: () => this.setValue(addCurrencies(value, step)), }), h('i.fa.fa-angle-down', { style: { cursor: 'pointer' }, - onClick: () => this.setValue(value - step), + onClick: () => this.setValue(addCurrencies(value, step * -1)), }), ]), ]) diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 7247d840e..88deb2bb0 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -15,6 +15,7 @@ const ExportPrivateKeyModal = require('./export-private-key-modal') const NewAccountModal = require('./new-account-modal') const ShapeshiftDepositTxModal = require('./shapeshift-deposit-tx-modal.js') const HideTokenConfirmationModal = require('./hide-token-confirmation-modal') +const CustomizeGasModal = require('../customize-gas-modal') const accountModalStyle = { mobileModalStyle: { @@ -156,6 +157,31 @@ const MODALS = { }, }, + CUSTOMIZE_GAS: { + contents: [ + h(CustomizeGasModal, {}, []), + ], + mobileModalStyle: { + width: '355px', + height: '598px', + // top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh', + top: '5%', + transform: 'none', + left: '0', + right: '0', + margin: '0 auto', + }, + laptopModalStyle: { + width: '720px', + height: '377px', + top: '80px', + transform: 'none', + left: '0', + right: '0', + margin: '0 auto', + }, + }, + DEFAULT: { contents: [], mobileModalStyle: {}, diff --git a/ui/app/components/send/account-list-item.js b/ui/app/components/send/account-list-item.js index b11527d95..64acde767 100644 --- a/ui/app/components/send/account-list-item.js +++ b/ui/app/components/send/account-list-item.js @@ -3,27 +3,34 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect const Identicon = require('../identicon') +const CurrencyDisplay = require('./currency-display') +const { conversionRateSelector } = require('../../selectors') inherits(AccountListItem, Component) function AccountListItem () { Component.call(this) } -module.exports = AccountListItem +function mapStateToProps(state) { + return { + conversionRate: conversionRateSelector(state) + } +} + +module.exports = connect(mapStateToProps)(AccountListItem) AccountListItem.prototype.render = function () { const { account, handleClick, icon = null, + conversionRate, } = this.props - const { identity, balancesToRender } = account - const { name, address } = identity - const { primary, secondary } = balancesToRender + const { name, address, balance } = account return h('div.account-list-item', { - onClick: () => handleClick(identity), + onClick: () => handleClick({ name, address, balance }), }, [ h('div.account-list-item__top-row', {}, [ @@ -35,7 +42,7 @@ AccountListItem.prototype.render = function () { diameter: 18, className: 'account-list-item__identicon', }, - ), + ), h('div.account-list-item__account-name', {}, name), @@ -43,9 +50,17 @@ AccountListItem.prototype.render = function () { ]), - h('div.account-list-item__account-primary-balance', {}, primary), - - h('div.account-list-item__account-secondary-balance', {}, secondary), + h(CurrencyDisplay, { + primaryCurrency: 'ETH', + convertedCurrency: 'USD', + value: balance, + conversionRate, + convertedPrefix: '$', + readOnly: true, + className: 'account-list-item__account-balances', + primaryBalanceClassName: 'account-list-item__account-primary-balance', + convertedBalanceClassName: 'account-list-item__account-secondary-balance', + }, name), ]) } \ No newline at end of file diff --git a/ui/app/components/send/currency-display.js b/ui/app/components/send/currency-display.js index 332d722ec..ed9847fdb 100644 --- a/ui/app/components/send/currency-display.js +++ b/ui/app/components/send/currency-display.js @@ -11,8 +11,7 @@ function CurrencyDisplay () { Component.call(this) this.state = { - minWidth: null, - currentScrollWidth: null, + value: null, } } @@ -29,28 +28,50 @@ function resetCaretIfPastEnd (value, event) { } } +CurrencyDisplay.prototype.handleChangeInHexWei = function (value) { + const { handleChange } = this.props + + const valueInHexWei = conversionUtil(value, { + fromNumericBase: 'dec', + toNumericBase: 'hex', + toDenomination: 'WEI', + }) + + handleChange(valueInHexWei) +} + CurrencyDisplay.prototype.render = function () { const { - className, + className = 'currency-display', + primaryBalanceClassName = 'currency-display__input', + convertedBalanceClassName = 'currency-display__converted-value', + conversionRate, primaryCurrency, convertedCurrency, - value = '', - placeholder = '0', - conversionRate, convertedPrefix = '', + placeholder = '0', readOnly = false, - handleChange, + value: initValue, } = this.props - const { minWidth } = this.state + const { value } = this.state + + const initValueToRender = conversionUtil(initValue, { + fromNumericBase: 'hex', + toNumericBase: 'dec', + fromDenomination: 'WEI', + numberOfDecimals: 6, + conversionRate, + }) - const convertedValue = conversionUtil(value, { + const convertedValue = conversionUtil(value || initValueToRender, { fromNumericBase: 'dec', fromCurrency: primaryCurrency, toCurrency: convertedCurrency, + numberOfDecimals: 2, conversionRate, }) - return h('div.currency-display', { + return h('div', { className, }, [ @@ -58,35 +79,39 @@ CurrencyDisplay.prototype.render = function () { h('div.currency-display__input-wrapper', [ - h('input.currency-display__input', { - value: `${value} ${primaryCurrency}`, + h('input', { + className: primaryBalanceClassName, + value: `${value || initValueToRender} ${primaryCurrency}`, placeholder: `${0} ${primaryCurrency}`, readOnly, onChange: (event) => { let newValue = event.target.value.split(' ')[0] if (newValue === '') { - handleChange('0') + this.setState({ value: '0' }) } else if (newValue.match(/^0[1-9]$/)) { - handleChange(newValue.match(/[1-9]/)[0]) + this.setState({ value: newValue.match(/[1-9]/)[0] }) } else if (newValue && !isValidInput(newValue)) { event.preventDefault() } else { - handleChange(newValue) + this.setState({ value: newValue }) } }, - onKeyUp: event => resetCaretIfPastEnd(value, event), - onClick: event => resetCaretIfPastEnd(value, event), + onBlur: event => this.handleChangeInHexWei(event.target.value.split(' ')[0]), + onKeyUp: event => resetCaretIfPastEnd(value || initValueToRender, event), + onClick: event => resetCaretIfPastEnd(value || initValueToRender, event), }), ]), ]), - h('div.currency-display__converted-value', {}, `${convertedPrefix}${convertedValue} ${convertedCurrency}`), + h('div', { + className: convertedBalanceClassName, + }, `${convertedPrefix}${convertedValue} ${convertedCurrency}`), ]) diff --git a/ui/app/components/send/from-dropdown.js b/ui/app/components/send/from-dropdown.js index fb0a00cc2..e8e1d43f0 100644 --- a/ui/app/components/send/from-dropdown.js +++ b/ui/app/components/send/from-dropdown.js @@ -14,7 +14,7 @@ function FromDropdown () { FromDropdown.prototype.getListItemIcon = function (currentAccount, selectedAccount) { const listItemIcon = h(`i.fa.fa-check.fa-lg`, { style: { color: '#02c9b1' } }) - return currentAccount.identity.address === selectedAccount.identity.address + return currentAccount.address === selectedAccount.address ? listItemIcon : null } diff --git a/ui/app/components/send/gas-fee-display-v2.js b/ui/app/components/send/gas-fee-display-v2.js new file mode 100644 index 000000000..226ae93f8 --- /dev/null +++ b/ui/app/components/send/gas-fee-display-v2.js @@ -0,0 +1,47 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const CurrencyDisplay = require('./currency-display'); + +const { multiplyCurrencies } = require('../../conversion-util') + +module.exports = GasFeeDisplay + +inherits(GasFeeDisplay, Component) +function GasFeeDisplay () { + Component.call(this) +} + +GasFeeDisplay.prototype.render = function () { + const { + conversionRate, + gasLimit, + gasPrice, + onClick, + } = this.props + + const readyToRender = Boolean(gasLimit && gasPrice) + + return h('div', [ + + readyToRender + ? h(CurrencyDisplay, { + primaryCurrency: 'ETH', + convertedCurrency: 'USD', + value: multiplyCurrencies(gasLimit, gasPrice, { toNumericBase: 'hex' }), + conversionRate, + convertedPrefix: '$', + readOnly: true, + }) + : h('div.currency-display', 'Loading...') + , + + h('div.send-v2__sliders-icon-container', { + onClick, + }, [ + h('i.fa.fa-sliders.send-v2__sliders-icon'), + ]) + + ]) +} + diff --git a/ui/app/components/send/gas-tooltip.js b/ui/app/components/send/gas-tooltip.js index bef419e48..46aff3499 100644 --- a/ui/app/components/send/gas-tooltip.js +++ b/ui/app/components/send/gas-tooltip.js @@ -73,7 +73,7 @@ GasTooltip.prototype.render = function () { step: 1, min: 0, placeholder: '0', - initValue: gasPrice, + value: gasPrice, onChange: (newPrice) => this.updateGasPrice(newPrice), }), h('div.gas-tooltip-input-label', { @@ -89,7 +89,7 @@ GasTooltip.prototype.render = function () { step: 1, min: 0, placeholder: '0', - initValue: gasLimit, + value: gasLimit, onChange: (newLimit) => this.updateGasLimit(newLimit), }), ]), diff --git a/ui/app/components/send/memo-textarea.js b/ui/app/components/send/memo-textarea.js new file mode 100644 index 000000000..4005b9493 --- /dev/null +++ b/ui/app/components/send/memo-textarea.js @@ -0,0 +1,33 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const Identicon = require('../identicon') + +module.exports = MemoTextArea + +inherits(MemoTextArea, Component) +function MemoTextArea () { + Component.call(this) +} + +MemoTextArea.prototype.render = function () { + const { memo, identities, onChange } = this.props + + return h('div.send-v2__memo-text-area', [ + + h('textarea.send-v2__memo-text-area__input', { + placeholder: 'Optional', + value: memo, + onChange, + // onBlur: () => { + // this.setErrorsFor('memo') + // }, + onFocus: event => { + // this.clearErrorsFor('memo') + }, + }), + + ]) + +} + diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js new file mode 100644 index 000000000..0c8dd5335 --- /dev/null +++ b/ui/app/components/send/send-v2-container.js @@ -0,0 +1,62 @@ +const connect = require('react-redux').connect +const actions = require('../../actions') +const abi = require('ethereumjs-abi') +const SendEther = require('../../send-v2') + +const { multiplyCurrencies } = require('../../conversion-util') + +const { + accountsWithSendEtherInfoSelector, + getCurrentAccountWithSendEtherInfo, + conversionRateSelector, + getSelectedToken, + getSelectedTokenExchangeRate, + getSelectedAddress, +} = require('../../selectors') + +module.exports = connect(mapStateToProps, mapDispatchToProps)(SendEther) + +function mapStateToProps (state) { + const selectedAddress = getSelectedAddress(state); + const selectedToken = getSelectedToken(state); + const tokenExchangeRates = state.metamask.tokenExchangeRates + const selectedTokenExchangeRate = getSelectedTokenExchangeRate(state) + const conversionRate = conversionRateSelector(state) + + let data; + let primaryCurrency; + let tokenToUSDRate; + if (selectedToken) { + data = Array.prototype.map.call( + abi.rawEncode(['address', 'uint256'], [selectedAddress, '0x0']), + x => ('00' + x.toString(16)).slice(-2) + ).join('') + + primaryCurrency = selectedToken.symbol + + tokenToUSDRate = multiplyCurrencies( + conversionRate, + selectedTokenExchangeRate, + { toNumericBase: 'dec' } + ) + } + + return { + selectedAccount: getCurrentAccountWithSendEtherInfo(state), + accounts: accountsWithSendEtherInfoSelector(state), + conversionRate, + selectedToken, + primaryCurrency, + data, + tokenToUSDRate, + } +} + +function mapDispatchToProps (dispatch) { + return { + showCustomizeGasModal: () => dispatch(actions.showModal({ name: 'CUSTOMIZE_GAS' })), + estimateGas: params => dispatch(actions.estimateGas(params)), + getGasPrice: () => dispatch(actions.getGasPrice()), + updateTokenExchangeRate: token => dispatch(actions.updateTokenExchangeRate(token)), + } +} diff --git a/ui/app/components/send/to-autocomplete.js b/ui/app/components/send/to-autocomplete.js index 3808bf496..1bf1e1907 100644 --- a/ui/app/components/send/to-autocomplete.js +++ b/ui/app/components/send/to-autocomplete.js @@ -11,7 +11,7 @@ function ToAutoComplete () { } ToAutoComplete.prototype.render = function () { - const { to, identities, onChange } = this.props + const { to, accounts, onChange } = this.props return h('div.send-v2__to-autocomplete', [ @@ -32,7 +32,7 @@ ToAutoComplete.prototype.render = function () { h('datalist#addresses', [ // Corresponds to the addresses owned. - ...Object.entries(identities).map(([key, { address, name }]) => { + ...Object.entries(accounts).map(([key, { address, name }]) => { return h('option', { value: address, label: name, -- cgit v1.2.3 From 222a203353dd977f497d44bf6581c16200b5de4f Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Fri, 13 Oct 2017 16:23:10 -0400 Subject: Fix click to copy for private key not working (#2360) --- ui/app/components/modals/export-private-key-modal.js | 8 +++++--- ui/app/components/readonly-input.js | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/export-private-key-modal.js b/ui/app/components/modals/export-private-key-modal.js index ddc7f1352..302596eda 100644 --- a/ui/app/components/modals/export-private-key-modal.js +++ b/ui/app/components/modals/export-private-key-modal.js @@ -7,6 +7,7 @@ const actions = require('../../actions') const AccountModalContainer = require('./account-modal-container') const { getSelectedIdentity } = require('../../selectors') const ReadOnlyInput = require('../readonly-input') +const copyToClipboard = require('copy-to-clipboard') function mapStateToProps (state) { return { @@ -61,11 +62,12 @@ ExportPrivateKeyModal.prototype.renderPasswordInput = function (privateKey) { inputClass: 'private-key-password-display-textarea', textarea: true, value: plainKey, + onClick: () => copyToClipboard(plainKey), }) : h('input.private-key-password-input', { type: 'password', placeholder: 'Type password', - onChange: event => this.setState({ password: event.target.value }) + onChange: event => this.setState({ password: event.target.value }), }) } @@ -115,7 +117,7 @@ ExportPrivateKeyModal.prototype.render = function () { }), h('div.account-modal-divider'), - + h('span.modal-body-title', 'Download Private Keys'), h('div.private-key-password', {}, [ @@ -132,6 +134,6 @@ ExportPrivateKeyModal.prototype.render = function () { ), this.renderButtons(privateKey, this.state.password, address, hideModal), - + ]) } diff --git a/ui/app/components/readonly-input.js b/ui/app/components/readonly-input.js index 33b93b5a0..fcf05fb9e 100644 --- a/ui/app/components/readonly-input.js +++ b/ui/app/components/readonly-input.js @@ -15,6 +15,7 @@ ReadOnlyInput.prototype.render = function () { inputClass = '', value, textarea, + onClick, } = this.props const inputType = textarea ? 'textarea' : 'input' @@ -25,6 +26,7 @@ ReadOnlyInput.prototype.render = function () { value, readOnly: true, onFocus: event => event.target.select(), + onClick, }), ]) } -- cgit v1.2.3 From 54a61a40215878e4f8538b440340734fdd46fd67 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Fri, 13 Oct 2017 16:24:17 -0400 Subject: Fix styling for Accept buttons in notices (#2358) --- ui/app/components/notice.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/notice.js b/ui/app/components/notice.js index c26505193..abfff1f5c 100644 --- a/ui/app/components/notice.js +++ b/ui/app/components/notice.js @@ -102,7 +102,7 @@ Notice.prototype.render = function () { }), ]), - h('button', { + h('button.primary', { disabled, onClick: () => { this.setState({disclaimerDisabled: true}) -- cgit v1.2.3 From a84014eff8e008fff6db5ebba7323bb52a2d2d9f Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Fri, 13 Oct 2017 16:25:33 -0400 Subject: Fix Localhost 8545 option in network dropdown (#2357) --- ui/app/components/dropdowns/network-dropdown.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js index 567bf07a0..c64e7a1d1 100644 --- a/ui/app/components/dropdowns/network-dropdown.js +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -189,7 +189,7 @@ NetworkDropdown.prototype.render = function () { { key: 'default', closeMenu: () => this.props.hideNetworkDropdown(), - onClick: () => props.setDefaultRpcTarget(), + onClick: () => props.setRpcTarget('http://localhost:8545'), style: dropdownMenuItemStyle, }, [ -- cgit v1.2.3 From b149cceda01318d04195fc2196c29c5d9f67cda0 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Fri, 13 Oct 2017 16:34:28 -0400 Subject: Fix exception thrown when tokens is null (#2355) --- ui/app/components/token-list.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js index fb11be826..4959f1cd5 100644 --- a/ui/app/components/token-list.js +++ b/ui/app/components/token-list.js @@ -141,7 +141,8 @@ TokenList.prototype.componentDidUpdate = function (nextProps) { const sameUserAndNetwork = oldAddress === newAddress && oldNet === newNet const shouldUpdateTokens = isLoading || missingInfo || sameUserAndNetwork - const tokensLengthUnchanged = tokens.length === newTokens.length + const oldTokensLength = tokens ? tokens.length : 0 + const tokensLengthUnchanged = oldTokensLength === newTokens.length if (tokensLengthUnchanged && shouldUpdateTokens) return -- cgit v1.2.3 From 3fd9c8b57fe46d14772086980e0e92573c1799f2 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Fri, 13 Oct 2017 17:14:26 -0400 Subject: Fix cursor on unclickable transactions (#2356) --- ui/app/components/tx-list.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 137cccf37..a02849d0e 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -8,6 +8,7 @@ const TxListItem = require('./tx-list-item') const ShiftListItem = require('./shift-list-item') const { formatBalance, formatDate } = require('../util') const { showConfTxPage } = require('../actions') +const classnames = require('classnames') module.exports = connect(mapStateToProps, mapDispatchToProps)(TxList) @@ -97,18 +98,23 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa address, transactionAmount, transactionHash, - className: '.tx-list-item.tx-list-clickable', conversionRate, } - if (transactionStatus === 'unapproved') { + const isUnapproved = transactionStatus === 'unapproved'; + + if (isUnapproved) { opts.onClick = () => showConfTxPage({id: transActionId}) - opts.className += '.tx-list-pending-item-container' opts.transactionStatus = 'Not Started' } else if (transactionHash) { opts.onClick = () => this.view(transactionHash, transactionNetworkId) } + opts.className = classnames('.tx-list-item', { + '.tx-list-pending-item-container': isUnapproved, + '.tx-list-clickable': Boolean(transactionHash) || isUnapproved, + }) + return h(TxListItem, opts) } -- cgit v1.2.3 From a9244f5e426d6572ef135e07ab75a49c00e84942 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 12 Oct 2017 14:12:14 -0230 Subject: Customize Gas connected to state --- ui/app/components/customize-gas-modal/index.js | 84 ++++++++++++++++++++++---- ui/app/components/send/gas-fee-display-v2.js | 6 +- ui/app/components/send/send-v2-container.js | 4 ++ 3 files changed, 80 insertions(+), 14 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 91e2626b4..2df24b4e1 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -5,32 +5,90 @@ const connect = require('react-redux').connect const actions = require('../../actions') const GasModalCard = require('./gas-modal-card') +const { conversionUtil } = require('../../conversion-util') + +const { + getGasPrice, + getGasLimit, + conversionRateSelector, +} = require('../../selectors') + function mapStateToProps (state) { - return {} + return { + gasPrice: getGasPrice(state), + gasLimit: getGasLimit(state), + conversionRate: conversionRateSelector(state), + } } function mapDispatchToProps (dispatch) { return { hideModal: () => dispatch(actions.hideModal()), + updateGasPrice: newGasPrice => dispatch(actions.updateGasPrice(newGasPrice)), + updateGasLimit: newGasLimit => dispatch(actions.updateGasLimit(newGasLimit)), } } inherits(CustomizeGasModal, Component) -function CustomizeGasModal () { +function CustomizeGasModal (props) { Component.call(this) this.state = { - gasPrice: '0.23', - gasLimit: '25000', + gasPrice: props.gasPrice, + gasLimit: props.gasLimit, } } module.exports = connect(mapStateToProps, mapDispatchToProps)(CustomizeGasModal) +CustomizeGasModal.prototype.save = function (gasPrice, gasLimit) { + const { + updateGasPrice, + updateGasLimit, + hideModal, + } = this.props + + updateGasPrice(gasPrice) + updateGasLimit(gasLimit) + hideModal() +} + +CustomizeGasModal.prototype.convertAndSetGasLimit = function (newGasLimit) { + const convertedGasLimit = conversionUtil(newGasLimit, { + fromNumericBase: 'dec', + toNumericBase: 'hex', + }) + + this.setState({ gasLimit: convertedGasLimit }) +} + +CustomizeGasModal.prototype.convertAndSetGasPrice = function (newGasPrice) { + const convertedGasPrice = conversionUtil(newGasPrice, { + fromNumericBase: 'dec', + toNumericBase: 'hex', + fromDenomination: 'GWEI', + toDenomination: 'WEI', + }) + + this.setState({ gasPrice: convertedGasPrice }) +} + CustomizeGasModal.prototype.render = function () { - const { hideModal } = this.props + const { hideModal, conversionRate } = this.props const { gasPrice, gasLimit } = this.state + const convertedGasPrice = conversionUtil(gasPrice, { + fromNumericBase: 'hex', + toNumericBase: 'dec', + fromDenomination: 'WEI', + toDenomination: 'GWEI', + }) + + const convertedGasLimit = conversionUtil(gasLimit, { + fromNumericBase: 'hex', + toNumericBase: 'dec', + }) + return h('div.send-v2__customize-gas', {}, [ h('div', { }, [ @@ -47,21 +105,21 @@ CustomizeGasModal.prototype.render = function () { h('div.send-v2__customize-gas__body', {}, [ h(GasModalCard, { - value: gasPrice, - min: 0.0, - max: 5.0, - step: 0.01, - onChange: gasPrice => this.setState({ gasPrice }), + value: convertedGasPrice, + min: 0, + max: 1000, + step: 1, + onChange: value => this.convertAndSetGasPrice(value), title: 'Gas Price', copy: 'We calculate the suggested gas prices based on network success rates.', }), h(GasModalCard, { - value: gasLimit, + value: convertedGasLimit, min: 20000, max: 100000, step: 1, - onChange: gasLimit => this.setState({ gasLimit }), + onChange: value => this.convertAndSetGasLimit(value), title: 'Gas Limit', copy: 'We calculate the suggested gas limit based on network success rates.', }), @@ -80,7 +138,7 @@ CustomizeGasModal.prototype.render = function () { }, ['CANCEL']), h('div.send-v2__customize-gas__save', { - onClick: () => console.log('Save'), + onClick: () => this.save(gasPrice, gasLimit), }, ['SAVE']), ]) diff --git a/ui/app/components/send/gas-fee-display-v2.js b/ui/app/components/send/gas-fee-display-v2.js index 226ae93f8..961d55610 100644 --- a/ui/app/components/send/gas-fee-display-v2.js +++ b/ui/app/components/send/gas-fee-display-v2.js @@ -28,7 +28,11 @@ GasFeeDisplay.prototype.render = function () { ? h(CurrencyDisplay, { primaryCurrency: 'ETH', convertedCurrency: 'USD', - value: multiplyCurrencies(gasLimit, gasPrice, { toNumericBase: 'hex' }), + value: multiplyCurrencies(gasLimit, gasPrice, { + toNumericBase: 'hex', + multiplicandBase: 16, + multiplierBase: 16, + }), conversionRate, convertedPrefix: '$', readOnly: true, diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js index 0c8dd5335..c3af1c972 100644 --- a/ui/app/components/send/send-v2-container.js +++ b/ui/app/components/send/send-v2-container.js @@ -12,6 +12,8 @@ const { getSelectedToken, getSelectedTokenExchangeRate, getSelectedAddress, + getGasPrice, + getGasLimit, } = require('../../selectors') module.exports = connect(mapStateToProps, mapDispatchToProps)(SendEther) @@ -49,6 +51,8 @@ function mapStateToProps (state) { primaryCurrency, data, tokenToUSDRate, + gasPrice: getGasPrice(state), + gasLimit: getGasLimit(state), } } -- cgit v1.2.3 From 7caa9142235cc0eca20d638a066d666d8cfaabee Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Mon, 16 Oct 2017 01:27:51 -0400 Subject: Fix Import Account link not hiding sidebar --- ui/app/components/dropdowns/components/account-dropdowns.js | 9 +++++++-- ui/app/components/wallet-view.js | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index fc60c6005..e2eed1e4b 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -164,7 +164,7 @@ class AccountDropdowns extends Component { } renderAccountSelector () { - const { actions, useCssTransition, innerStyle } = this.props + const { actions, useCssTransition, innerStyle, sidebarOpen } = this.props const { accountSelectorActive, menuItemStyles } = this.state return h( @@ -223,7 +223,11 @@ class AccountDropdowns extends Component { h( DropdownMenuItem, { - closeMenu: () => {}, + closeMenu: () => { + if (sidebarOpen) { + actions.hideSidebar() + } + }, onClick: () => actions.showImportPage(), style: Object.assign( {}, @@ -457,6 +461,7 @@ const mapDispatchToProps = (dispatch) => { function mapStateToProps (state) { return { keyrings: state.metamask.keyrings, + sidebarOpen: state.appState.sidebarOpen, } } diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 00c86298d..54d90b7ac 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -45,8 +45,9 @@ WalletView.prototype.renderWalletBalance = function () { selectedAccount, unsetSelectedToken, hideSidebar, - sidebarOpen + sidebarOpen, } = this.props + const selectedClass = selectedTokenAddress ? '' : 'wallet-balance-wrapper--active' -- cgit v1.2.3 From ac43872c1a1468057974648c8ae90bf1edd708d7 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 12 Oct 2017 14:59:03 -0230 Subject: Enable send-v2 functionality. --- ui/app/components/send/currency-display.js | 6 +++--- ui/app/components/send/from-dropdown.js | 17 +++++++++++++---- ui/app/components/send/send-v2-container.js | 5 +++++ 3 files changed, 21 insertions(+), 7 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send/currency-display.js b/ui/app/components/send/currency-display.js index ed9847fdb..d56c119f1 100644 --- a/ui/app/components/send/currency-display.js +++ b/ui/app/components/send/currency-display.js @@ -100,9 +100,9 @@ CurrencyDisplay.prototype.render = function () { this.setState({ value: newValue }) } }, - onBlur: event => this.handleChangeInHexWei(event.target.value.split(' ')[0]), - onKeyUp: event => resetCaretIfPastEnd(value || initValueToRender, event), - onClick: event => resetCaretIfPastEnd(value || initValueToRender, event), + onBlur: event => !readOnly && this.handleChangeInHexWei(event.target.value.split(' ')[0]), + onKeyUp: event => !readOnly && resetCaretIfPastEnd(value || initValueToRender, event), + onClick: event => !readOnly && resetCaretIfPastEnd(value || initValueToRender, event), }), ]), diff --git a/ui/app/components/send/from-dropdown.js b/ui/app/components/send/from-dropdown.js index e8e1d43f0..fd6fb7e64 100644 --- a/ui/app/components/send/from-dropdown.js +++ b/ui/app/components/send/from-dropdown.js @@ -19,7 +19,14 @@ FromDropdown.prototype.getListItemIcon = function (currentAccount, selectedAccou : null } -FromDropdown.prototype.renderDropdown = function (accounts, selectedAccount, closeDropdown) { +FromDropdown.prototype.renderDropdown = function () { + const { + accounts, + selectedAccount, + closeDropdown, + onSelect, + } = this.props + return h('div', {}, [ h('div.send-v2__from-dropdown__close-area', { @@ -30,7 +37,10 @@ FromDropdown.prototype.renderDropdown = function (accounts, selectedAccount, clo ...accounts.map(account => h(AccountListItem, { account, - handleClick: () => console.log('Select identity'), + handleClick: () => { + onSelect(account.address) + closeDropdown() + }, icon: this.getListItemIcon(account, selectedAccount), })) @@ -43,7 +53,6 @@ FromDropdown.prototype.render = function () { const { accounts, selectedAccount, - setFromField, openDropdown, closeDropdown, dropdownOpen, @@ -57,7 +66,7 @@ FromDropdown.prototype.render = function () { icon: h(`i.fa.fa-caret-down.fa-lg`, { style: { color: '#dedede' } }) }), - dropdownOpen && this.renderDropdown(accounts, selectedAccount, closeDropdown), + dropdownOpen && this.renderDropdown(), ]) diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js index c3af1c972..5935a8fee 100644 --- a/ui/app/components/send/send-v2-container.js +++ b/ui/app/components/send/send-v2-container.js @@ -62,5 +62,10 @@ function mapDispatchToProps (dispatch) { estimateGas: params => dispatch(actions.estimateGas(params)), getGasPrice: () => dispatch(actions.getGasPrice()), updateTokenExchangeRate: token => dispatch(actions.updateTokenExchangeRate(token)), + signTokenTx: (tokenAddress, toAddress, amount, txData) => ( + dispatch(actions.signTokenTx(tokenAddress, toAddress, amount, txData)) + ), + signTx: txParams => dispatch(actions.signTx(txParams)), + setSelectedAddress: address => dispatch(actions.setSelectedAddress(address)) } } -- cgit v1.2.3 From 5ee6e4d3b3d61d804340c22b73a608fb6b44a9b2 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Mon, 16 Oct 2017 01:28:25 -0400 Subject: wip --- ui/app/components/account-menu/index.js | 110 +++++++++++++++++++++++-- ui/app/components/dropdowns/components/menu.js | 9 +- ui/app/components/wallet-view.js | 1 - 3 files changed, 113 insertions(+), 7 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index 7dc3d10a5..3b1118271 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -3,7 +3,9 @@ const Component = require('react').Component const connect = require('react-redux').connect const h = require('react-hyperscript') const actions = require('../../actions') -const { Menu, Item, Divider } = require('../dropdowns/components/menu') +const { Menu, Item, Divider, CloseArea } = require('../dropdowns/components/menu') +const Identicon = require('../identicon') +const { formatBalance } = require('../../util') module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountMenu) @@ -13,21 +15,33 @@ function AccountMenu () { Component.call(this) } function mapStateToProps (state) { return { selectedAddress: state.metamask.selectedAddress, + isAccountMenuOpen: state.metamask.isAccountMenuOpen, + keyrings: state.metamask.keyrings, + identities: state.metamask.identities, + accounts: state.metamask.accounts, + } } -function mapDispatchToProps () { - return {} +// identities, accounts, selected, menuItemStyles, actions, keyrings + +function mapDispatchToProps (dispatch) { + return { + toggleAccountMenu: () => dispatch(actions.toggleAccountMenu()), + } } AccountMenu.prototype.render = function () { - return h(Menu, { className: 'account-menu' }, [ + const { isAccountMenuOpen, toggleAccountMenu } = this.props + + return h(Menu, { className: 'account-menu', isShowing: isAccountMenuOpen }, [ + h(CloseArea, { onClick: toggleAccountMenu }), h(Item, { className: 'account-menu__header' }, [ 'My Accounts', h('button.account-menu__logout-button', 'Log out'), ]), h(Divider), - h(Item, { text: 'hi' }), + h('div.account-menu__accounts', this.renderAccounts()), h(Divider), h(Item, { onClick: true, @@ -53,4 +67,90 @@ AccountMenu.prototype.render = function () { ]) } +AccountMenu.prototype.renderAccounts = function () { + const { identities, accounts, selected, actions, keyrings } = this.props + + return Object.keys(identities).map((key, index) => { + const identity = identities[key] + const isSelected = identity.address === selected + + const balanceValue = accounts[key].balance + const formattedBalance = balanceValue ? formatBalance(balanceValue, 6) : '...' + const simpleAddress = identity.address.substring(2).toLowerCase() + + const keyring = keyrings.find((kr) => { + return kr.accounts.includes(simpleAddress) || + kr.accounts.includes(identity.address) + }) + + return h( + 'div.account-menu__account', + { + onClick: () => { + this.props.actions.showAccountDetail(identity.address) + }, + }, + [ + h('div.account-menu__check-mark', [ + isSelected ? h('i.fa.fa-check') : null, + ]), + h( + Identicon, + { + address: identity.address, + diameter: 24, + }, + ), + + h('div.account-menu__account-info', [ + + this.indicateIfLoose(keyring), + + h('div.account-menu__name', { + style: { + fontSize: '18px', + maxWidth: '145px', + whiteSpace: 'nowrap', + overflow: 'hidden', + textOverflow: 'ellipsis', + }, + }, identity.name || ''), + + h('div.account-menu__balance', formattedBalance), + ]), + + h('div.account-menu__action', { + onClick: () => { + actions.showEditAccountModal(identity) + }, + }, 'Edit'), + +// ======= +// }, +// ), +// this.indicateIfLoose(keyring), +// h('span', { +// style: { +// marginLeft: '20px', +// fontSize: '24px', +// maxWidth: '145px', +// whiteSpace: 'nowrap', +// overflow: 'hidden', +// textOverflow: 'ellipsis', +// }, +// }, identity.name || ''), +// h('span', { style: { marginLeft: '20px', fontSize: '24px' } }, isSelected ? h('.check', '✓') : null), +// >>>>>>> master:ui/app/components/account-dropdowns.js + ], + ) + }) +} + +AccountMenu.prototype.indicateIfLoose = function (keyring) { + try { // Sometimes keyrings aren't loaded yet: + const type = keyring.type + const isLoose = type !== 'HD Key Tree' + return isLoose ? h('.keyring-label', 'LOOSE') : null + } catch (e) { return } +} diff --git a/ui/app/components/dropdowns/components/menu.js b/ui/app/components/dropdowns/components/menu.js index 0cbe0f342..323103f0b 100644 --- a/ui/app/components/dropdowns/components/menu.js +++ b/ui/app/components/dropdowns/components/menu.js @@ -41,4 +41,11 @@ Divider.prototype.render = function () { return h('div.menu__divider') } -module.exports = { Menu, Item, Divider } +inherits(CloseArea, Component) +function CloseArea () { Component.call(this) } + +CloseArea.prototype.render = function () { + return h('div.menu__close-area', { onClick: this.props.onClick }) +} + +module.exports = { Menu, Item, Divider, CloseArea } diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 54d90b7ac..f06c4d512 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -136,7 +136,6 @@ WalletView.prototype.render = function () { selected: selectedAddress, network, identities, - enableAccountsSelector: true, }, []), ]), -- cgit v1.2.3 From 085551b7e6b7dab21c21b99a40c4f79c413799d5 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 17 Oct 2017 22:36:53 -0700 Subject: New Account modal --- ui/app/components/account-menu/index.js | 100 ++++++++++++------------- ui/app/components/dropdowns/components/menu.js | 4 +- 2 files changed, 51 insertions(+), 53 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index 3b1118271..2ebdba24a 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -23,20 +23,50 @@ function mapStateToProps (state) { } } -// identities, accounts, selected, menuItemStyles, actions, keyrings - function mapDispatchToProps (dispatch) { return { toggleAccountMenu: () => dispatch(actions.toggleAccountMenu()), + showAccountDetail: address => { + dispatch(actions.showAccountDetail(address)) + dispatch(actions.toggleAccountMenu()) + }, + lockMetamask: () => { + dispatch(actions.lockMetamask()) + dispatch(actions.toggleAccountMenu()) + }, + showConfigPage: () => { + console.log('hihihih') + dispatch(actions.showConfigPage()) + dispatch(actions.toggleAccountMenu()) + }, + showNewAccountModal: () => { + dispatch(actions.showModal({ name: 'NEW_ACCOUNT' })) + dispatch(actions.toggleAccountMenu()) + }, + showImportPage: () => { + dispatch(actions.showImportPage()) + dispatch(actions.toggleAccountMenu()) + }, } } AccountMenu.prototype.render = function () { - const { isAccountMenuOpen, toggleAccountMenu } = this.props - + const { + isAccountMenuOpen, + toggleAccountMenu, + showNewAccountModal, + showImportPage, + lockMetamask, + showConfigPage, + } = this.props + + console.log(showConfigPage) return h(Menu, { className: 'account-menu', isShowing: isAccountMenuOpen }, [ h(CloseArea, { onClick: toggleAccountMenu }), - h(Item, { className: 'account-menu__header' }, [ + h(Item, { + className: 'account-menu__header', + onClick: lockMetamask, + }, [ 'My Accounts', h('button.account-menu__logout-button', 'Log out'), ]), @@ -44,23 +74,22 @@ AccountMenu.prototype.render = function () { h('div.account-menu__accounts', this.renderAccounts()), h(Divider), h(Item, { - onClick: true, + onClick: showNewAccountModal, icon: h('img', { src: 'images/plus-btn-white.svg' }), text: 'Create Account', }), h(Item, { - onClick: true, + onClick: showImportPage, icon: h('img', { src: 'images/import-account.svg' }), text: 'Import Account', }), h(Divider), h(Item, { - onClick: true, icon: h('img', { src: 'images/mm-info-icon.svg' }), text: 'Info & Help', }), h(Item, { - onClick: true, + onClick: showConfigPage, icon: h('img', { src: 'images/settings.svg' }), text: 'Settings', }), @@ -68,7 +97,13 @@ AccountMenu.prototype.render = function () { } AccountMenu.prototype.renderAccounts = function () { - const { identities, accounts, selected, actions, keyrings } = this.props + const { + identities, + accounts, + selected, + keyrings, + showAccountDetail, + } = this.props return Object.keys(identities).map((key, index) => { const identity = identities[key] @@ -84,12 +119,8 @@ AccountMenu.prototype.renderAccounts = function () { }) return h( - 'div.account-menu__account', - { - onClick: () => { - this.props.actions.showAccountDetail(identity.address) - }, - }, + 'div.account-menu__account.menu__item--clickable', + { onClick: () => showAccountDetail(identity.address) }, [ h('div.account-menu__check-mark', [ isSelected ? h('i.fa.fa-check') : null, @@ -104,44 +135,11 @@ AccountMenu.prototype.renderAccounts = function () { ), h('div.account-menu__account-info', [ - - this.indicateIfLoose(keyring), - - h('div.account-menu__name', { - style: { - fontSize: '18px', - maxWidth: '145px', - whiteSpace: 'nowrap', - overflow: 'hidden', - textOverflow: 'ellipsis', - }, - }, identity.name || ''), - + h('div.account-menu__name', identity.name || ''), h('div.account-menu__balance', formattedBalance), ]), - h('div.account-menu__action', { - onClick: () => { - actions.showEditAccountModal(identity) - }, - }, 'Edit'), - -// ======= -// }, -// ), -// this.indicateIfLoose(keyring), -// h('span', { -// style: { -// marginLeft: '20px', -// fontSize: '24px', -// maxWidth: '145px', -// whiteSpace: 'nowrap', -// overflow: 'hidden', -// textOverflow: 'ellipsis', -// }, -// }, identity.name || ''), -// h('span', { style: { marginLeft: '20px', fontSize: '24px' } }, isSelected ? h('.check', '✓') : null), -// >>>>>>> master:ui/app/components/account-dropdowns.js + this.indicateIfLoose(keyring), ], ) }) diff --git a/ui/app/components/dropdowns/components/menu.js b/ui/app/components/dropdowns/components/menu.js index 323103f0b..f6d8a139e 100644 --- a/ui/app/components/dropdowns/components/menu.js +++ b/ui/app/components/dropdowns/components/menu.js @@ -28,8 +28,8 @@ Item.prototype.render = function () { const textComponent = text ? h('div.menu__item__text', text) : null return children - ? h('div', { className: itemClassName }, children) - : h('div.menu__item', { className: itemClassName }, [ iconComponent, textComponent ] + ? h('div', { className: itemClassName, onClick }, children) + : h('div.menu__item', { className: itemClassName, onClick }, [ iconComponent, textComponent ] .filter(d => Boolean(d)) ) } -- cgit v1.2.3 From 03685c64b8e45d893c86478869200933de043da8 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 17 Oct 2017 22:42:56 -0700 Subject: Network dropdown update --- ui/app/components/dropdowns/network-dropdown.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js index c64e7a1d1..736019c39 100644 --- a/ui/app/components/dropdowns/network-dropdown.js +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -55,6 +55,7 @@ NetworkDropdown.prototype.render = function () { fontFamily: 'DIN OT', fontSize: '16px', lineHeight: '20px', + padding: '12px 0', } return h(Dropdown, { @@ -81,7 +82,7 @@ NetworkDropdown.prototype.render = function () { minWidth: '309px', }, innerStyle: { - padding: '10px 8px', + padding: '18px 8px', }, }, [ -- cgit v1.2.3 From 4f9ac1c4fe67ec4c196ce1891ecc1743552d45ce Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 17 Oct 2017 13:16:36 -0230 Subject: Get from and update addressBook in send-v2 --- ui/app/components/send/send-v2-container.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js index 5935a8fee..8ac5cc961 100644 --- a/ui/app/components/send/send-v2-container.js +++ b/ui/app/components/send/send-v2-container.js @@ -14,13 +14,15 @@ const { getSelectedAddress, getGasPrice, getGasLimit, + getAddressBook, } = require('../../selectors') module.exports = connect(mapStateToProps, mapDispatchToProps)(SendEther) function mapStateToProps (state) { - const selectedAddress = getSelectedAddress(state); - const selectedToken = getSelectedToken(state); + const fromAccounts = accountsWithSendEtherInfoSelector(state) + const selectedAddress = getSelectedAddress(state) + const selectedToken = getSelectedToken(state) const tokenExchangeRates = state.metamask.tokenExchangeRates const selectedTokenExchangeRate = getSelectedTokenExchangeRate(state) const conversionRate = conversionRateSelector(state) @@ -45,7 +47,8 @@ function mapStateToProps (state) { return { selectedAccount: getCurrentAccountWithSendEtherInfo(state), - accounts: accountsWithSendEtherInfoSelector(state), + fromAccounts, + toAccounts: [...fromAccounts, ...getAddressBook(state)], conversionRate, selectedToken, primaryCurrency, @@ -66,6 +69,7 @@ function mapDispatchToProps (dispatch) { dispatch(actions.signTokenTx(tokenAddress, toAddress, amount, txData)) ), signTx: txParams => dispatch(actions.signTx(txParams)), - setSelectedAddress: address => dispatch(actions.setSelectedAddress(address)) + setSelectedAddress: address => dispatch(actions.setSelectedAddress(address)), + addToAddressBook: address => dispatch(actions.addToAddressBook(address)), } } -- cgit v1.2.3 From f81226fbe9f98d5a6c408e289fa0ea61a467e7dc Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 17 Oct 2017 14:52:23 -0230 Subject: Move all of send state to metamask state. --- ui/app/components/customize-gas-modal/index.js | 11 ++++++++++- ui/app/components/send/from-dropdown.js | 2 +- ui/app/components/send/gas-fee-display-v2.js | 17 ++++------------- ui/app/components/send/send-v2-container.js | 13 +++++++++---- 4 files changed, 24 insertions(+), 19 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 2df24b4e1..0ba768893 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -5,7 +5,7 @@ const connect = require('react-redux').connect const actions = require('../../actions') const GasModalCard = require('./gas-modal-card') -const { conversionUtil } = require('../../conversion-util') +const { conversionUtil, multiplyCurrencies } = require('../../conversion-util') const { getGasPrice, @@ -26,6 +26,7 @@ function mapDispatchToProps (dispatch) { hideModal: () => dispatch(actions.hideModal()), updateGasPrice: newGasPrice => dispatch(actions.updateGasPrice(newGasPrice)), updateGasLimit: newGasLimit => dispatch(actions.updateGasLimit(newGasLimit)), + updateGasTotal: newGasTotal => dispatch(actions.updateGasTotal(newGasTotal)), } } @@ -46,10 +47,18 @@ CustomizeGasModal.prototype.save = function (gasPrice, gasLimit) { updateGasPrice, updateGasLimit, hideModal, + updateGasTotal } = this.props + const newGasTotal = multiplyCurrencies(gasLimit, gasPrice, { + toNumericBase: 'hex', + multiplicandBase: 16, + multiplierBase: 16, + }) + updateGasPrice(gasPrice) updateGasLimit(gasLimit) + updateGasTotal(newGasTotal) hideModal() } diff --git a/ui/app/components/send/from-dropdown.js b/ui/app/components/send/from-dropdown.js index fd6fb7e64..6f2b9da68 100644 --- a/ui/app/components/send/from-dropdown.js +++ b/ui/app/components/send/from-dropdown.js @@ -38,7 +38,7 @@ FromDropdown.prototype.renderDropdown = function () { ...accounts.map(account => h(AccountListItem, { account, handleClick: () => { - onSelect(account.address) + onSelect(account) closeDropdown() }, icon: this.getListItemIcon(account, selectedAccount), diff --git a/ui/app/components/send/gas-fee-display-v2.js b/ui/app/components/send/gas-fee-display-v2.js index 961d55610..7c3913c7f 100644 --- a/ui/app/components/send/gas-fee-display-v2.js +++ b/ui/app/components/send/gas-fee-display-v2.js @@ -1,9 +1,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits -const CurrencyDisplay = require('./currency-display'); - -const { multiplyCurrencies } = require('../../conversion-util') +const CurrencyDisplay = require('./currency-display') module.exports = GasFeeDisplay @@ -15,24 +13,17 @@ function GasFeeDisplay () { GasFeeDisplay.prototype.render = function () { const { conversionRate, - gasLimit, - gasPrice, + gasTotal, onClick, } = this.props - const readyToRender = Boolean(gasLimit && gasPrice) - return h('div', [ - readyToRender + gasTotal ? h(CurrencyDisplay, { primaryCurrency: 'ETH', convertedCurrency: 'USD', - value: multiplyCurrencies(gasLimit, gasPrice, { - toNumericBase: 'hex', - multiplicandBase: 16, - multiplierBase: 16, - }), + value: gasTotal, conversionRate, convertedPrefix: '$', readOnly: true, diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js index 8ac5cc961..dcf764048 100644 --- a/ui/app/components/send/send-v2-container.js +++ b/ui/app/components/send/send-v2-container.js @@ -15,6 +15,7 @@ const { getGasPrice, getGasLimit, getAddressBook, + getSendFrom, } = require('../../selectors') module.exports = connect(mapStateToProps, mapDispatchToProps)(SendEther) @@ -46,16 +47,15 @@ function mapStateToProps (state) { } return { - selectedAccount: getCurrentAccountWithSendEtherInfo(state), + ...state.metamask.send, + from: getSendFrom(state) || getCurrentAccountWithSendEtherInfo(state), fromAccounts, toAccounts: [...fromAccounts, ...getAddressBook(state)], conversionRate, selectedToken, primaryCurrency, data, - tokenToUSDRate, - gasPrice: getGasPrice(state), - gasLimit: getGasLimit(state), + amountConversionRate: selectedToken ? tokenToUSDRate : conversionRate, } } @@ -71,5 +71,10 @@ function mapDispatchToProps (dispatch) { signTx: txParams => dispatch(actions.signTx(txParams)), setSelectedAddress: address => dispatch(actions.setSelectedAddress(address)), addToAddressBook: address => dispatch(actions.addToAddressBook(address)), + updateGasTotal: newTotal => dispatch(actions.updateGasTotal(newTotal)), + updateSendFrom: newFrom => dispatch(actions.updateSendFrom(newFrom)), + updateSendTo: newTo => dispatch(actions.updateSendTo(newTo)), + updateSendAmount: newAmount => dispatch(actions.updateSendAmount(newAmount)), + updateSendMemo: newMemo => dispatch(actions.updateSendMemo(newMemo)), } } -- cgit v1.2.3 From 60eda592b5979ac1fdbfb6d5b3418a4924abc14d Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 17 Oct 2017 17:43:20 -0230 Subject: Handling to and amount errors. --- ui/app/components/send/currency-display.js | 23 +++++++++++++++-------- ui/app/components/send/send-v2-container.js | 1 + ui/app/components/send/to-autocomplete.js | 10 +++++----- 3 files changed, 21 insertions(+), 13 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send/currency-display.js b/ui/app/components/send/currency-display.js index d56c119f1..f7fbb2379 100644 --- a/ui/app/components/send/currency-display.js +++ b/ui/app/components/send/currency-display.js @@ -28,16 +28,12 @@ function resetCaretIfPastEnd (value, event) { } } -CurrencyDisplay.prototype.handleChangeInHexWei = function (value) { - const { handleChange } = this.props - - const valueInHexWei = conversionUtil(value, { +function toHexWei (value) { + return conversionUtil(value, { fromNumericBase: 'dec', toNumericBase: 'hex', toDenomination: 'WEI', }) - - handleChange(valueInHexWei) } CurrencyDisplay.prototype.render = function () { @@ -51,7 +47,10 @@ CurrencyDisplay.prototype.render = function () { convertedPrefix = '', placeholder = '0', readOnly = false, + inError = false, value: initValue, + handleChange, + validate, } = this.props const { value } = this.state @@ -73,6 +72,9 @@ CurrencyDisplay.prototype.render = function () { return h('div', { className, + style: { + borderColor: inError ? 'red' : null, + }, }, [ h('div.currency-display__primary-row', [ @@ -100,8 +102,13 @@ CurrencyDisplay.prototype.render = function () { this.setState({ value: newValue }) } }, - onBlur: event => !readOnly && this.handleChangeInHexWei(event.target.value.split(' ')[0]), - onKeyUp: event => !readOnly && resetCaretIfPastEnd(value || initValueToRender, event), + onBlur: event => !readOnly && handleChange(toHexWei(event.target.value.split(' ')[0])), + onKeyUp: event => { + if (!readOnly) { + validate(toHexWei(value || initValueToRender)) + resetCaretIfPastEnd(value || initValueToRender, event) + } + }, onClick: event => !readOnly && resetCaretIfPastEnd(value || initValueToRender, event), }), diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js index dcf764048..f20d80073 100644 --- a/ui/app/components/send/send-v2-container.js +++ b/ui/app/components/send/send-v2-container.js @@ -76,5 +76,6 @@ function mapDispatchToProps (dispatch) { updateSendTo: newTo => dispatch(actions.updateSendTo(newTo)), updateSendAmount: newAmount => dispatch(actions.updateSendAmount(newAmount)), updateSendMemo: newMemo => dispatch(actions.updateSendMemo(newMemo)), + updateSendErrors: newError => dispatch(actions.updateSendErrors(newError)), } } diff --git a/ui/app/components/send/to-autocomplete.js b/ui/app/components/send/to-autocomplete.js index 1bf1e1907..686a7a23e 100644 --- a/ui/app/components/send/to-autocomplete.js +++ b/ui/app/components/send/to-autocomplete.js @@ -11,7 +11,7 @@ function ToAutoComplete () { } ToAutoComplete.prototype.render = function () { - const { to, accounts, onChange } = this.props + const { to, accounts, onChange, inError } = this.props return h('div.send-v2__to-autocomplete', [ @@ -19,15 +19,15 @@ ToAutoComplete.prototype.render = function () { name: 'address', list: 'addresses', placeholder: 'Recipient Address', + className: inError ? `send-v2__error-border` : '', value: to, onChange, - // onBlur: () => { - // this.setErrorsFor('to') - // }, onFocus: event => { - // this.clearErrorsFor('to') to && event.target.select() }, + style: { + borderColor: inError ? 'red' : null, + } }), h('datalist#addresses', [ -- cgit v1.2.3 From de1da7d1b215ade650fc644adf63384a401dc240 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 18 Oct 2017 23:58:01 -0230 Subject: Fix cancel button on send screen. --- ui/app/components/send/send-v2-container.js | 1 + 1 file changed, 1 insertion(+) (limited to 'ui/app/components') diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js index f20d80073..ebe2b878b 100644 --- a/ui/app/components/send/send-v2-container.js +++ b/ui/app/components/send/send-v2-container.js @@ -77,5 +77,6 @@ function mapDispatchToProps (dispatch) { updateSendAmount: newAmount => dispatch(actions.updateSendAmount(newAmount)), updateSendMemo: newMemo => dispatch(actions.updateSendMemo(newMemo)), updateSendErrors: newError => dispatch(actions.updateSendErrors(newError)), + goHome: () => dispatch(actions.goHome()), } } -- cgit v1.2.3 From f01d119cc1a6237b88e543be821d91778bcbb128 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 19 Oct 2017 15:23:56 -0230 Subject: Fixes mobile styling. --- ui/app/components/send/gas-fee-display-v2.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send/gas-fee-display-v2.js b/ui/app/components/send/gas-fee-display-v2.js index 7c3913c7f..3b39312ec 100644 --- a/ui/app/components/send/gas-fee-display-v2.js +++ b/ui/app/components/send/gas-fee-display-v2.js @@ -17,7 +17,7 @@ GasFeeDisplay.prototype.render = function () { onClick, } = this.props - return h('div', [ + return h('div.send-v2__gas-fee-display', [ gasTotal ? h(CurrencyDisplay, { -- cgit v1.2.3 From 59015cccef72210f828b344aaedde9b8dd31be3b Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 18 Oct 2017 16:53:35 -0230 Subject: Min and default gas price, limit, total; comments out code for gas slider. --- .../customize-gas-modal/gas-modal-card.js | 18 ++++++++--------- ui/app/components/customize-gas-modal/index.js | 17 ++++++++++------ ui/app/components/send/send-constants.js | 23 ++++++++++++++++++++++ 3 files changed, 43 insertions(+), 15 deletions(-) create mode 100644 ui/app/components/send/send-constants.js (limited to 'ui/app/components') diff --git a/ui/app/components/customize-gas-modal/gas-modal-card.js b/ui/app/components/customize-gas-modal/gas-modal-card.js index 8e739ee40..de181dc67 100644 --- a/ui/app/components/customize-gas-modal/gas-modal-card.js +++ b/ui/app/components/customize-gas-modal/gas-modal-card.js @@ -19,7 +19,7 @@ GasModalCard.prototype.render = function () { unitLabel, value, min, - max, + // max, step, title, copy @@ -34,20 +34,20 @@ GasModalCard.prototype.render = function () { h(InputNumber, { unitLabel, step, - max, + // max, min, placeholder: '0', value, onChange, }), - h(GasSlider, { - value, - step, - max, - min, - onChange, - }), + // h(GasSlider, { + // value, + // step, + // max, + // min, + // onChange, + // }), ]) diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 0ba768893..744891c47 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -5,6 +5,11 @@ const connect = require('react-redux').connect const actions = require('../../actions') const GasModalCard = require('./gas-modal-card') +const { + MIN_GAS_PRICE, + MIN_GAS_LIMIT, +} = require('../send/send-constants') + const { conversionUtil, multiplyCurrencies } = require('../../conversion-util') const { @@ -35,8 +40,8 @@ function CustomizeGasModal (props) { Component.call(this) this.state = { - gasPrice: props.gasPrice, - gasLimit: props.gasLimit, + gasPrice: props.gasPrice || MIN_GAS_PRICE, + gasLimit: props.gasLimit || MIN_GAS_LIMIT, } } @@ -115,8 +120,8 @@ CustomizeGasModal.prototype.render = function () { h(GasModalCard, { value: convertedGasPrice, - min: 0, - max: 1000, + min: MIN_GAS_PRICE, + // max: 1000, step: 1, onChange: value => this.convertAndSetGasPrice(value), title: 'Gas Price', @@ -125,8 +130,8 @@ CustomizeGasModal.prototype.render = function () { h(GasModalCard, { value: convertedGasLimit, - min: 20000, - max: 100000, + min: MIN_GAS_LIMIT, + // max: 100000, step: 1, onChange: value => this.convertAndSetGasLimit(value), title: 'Gas Limit', diff --git a/ui/app/components/send/send-constants.js b/ui/app/components/send/send-constants.js new file mode 100644 index 000000000..a819a8c28 --- /dev/null +++ b/ui/app/components/send/send-constants.js @@ -0,0 +1,23 @@ +const Identicon = require('../identicon') +const { multiplyCurrencies } = require('../../conversion-util') + +const MIN_GAS_PRICE_GWEI = '1' +const GWEI_FACTOR = '1e9' +const MIN_GAS_PRICE = multiplyCurrencies(GWEI_FACTOR, MIN_GAS_PRICE_GWEI, { + multiplicandBase: 16, + multiplierBase: 16, +}) +const MIN_GAS_LIMIT = (21000).toString(16) +const MIN_GAS_TOTAL = multiplyCurrencies(MIN_GAS_LIMIT, MIN_GAS_PRICE, { + toNumericBase: 'hex', + multiplicandBase: 16, + multiplierBase: 16, +}) + +module.exports = { + MIN_GAS_PRICE_GWEI, + GWEI_FACTOR, + MIN_GAS_PRICE, + MIN_GAS_LIMIT, + MIN_GAS_TOTAL, +} -- cgit v1.2.3 From 332c7441b656ec82ebfba863e3feb4dbf365d67b Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 18 Oct 2017 23:39:26 -0230 Subject: Get currency from state in account details, send and confirm screens. --- .../pending-tx/confirm-deploy-contract.js | 28 +++++++------ ui/app/components/pending-tx/confirm-send-ether.js | 48 +++++++++++----------- ui/app/components/pending-tx/confirm-send-token.js | 24 +++++------ ui/app/components/pending-tx/index.js | 3 -- ui/app/components/send/account-list-item.js | 9 ++-- ui/app/components/send/currency-display.js | 2 +- ui/app/components/send/gas-fee-display-v2.js | 4 +- ui/app/components/send/send-v2-container.js | 8 ++-- ui/app/components/tx-list-item.js | 10 +++-- 9 files changed, 74 insertions(+), 62 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-deploy-contract.js b/ui/app/components/pending-tx/confirm-deploy-contract.js index ea4aa1dde..d19cec755 100644 --- a/ui/app/components/pending-tx/confirm-deploy-contract.js +++ b/ui/app/components/pending-tx/confirm-deploy-contract.js @@ -21,10 +21,12 @@ function mapStateToProps (state) { const { conversionRate, identities, + currentCurrency, } = state.metamask const accounts = state.metamask.accounts const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] return { + currentCurrency, conversionRate, identities, selectedAddress, @@ -124,15 +126,15 @@ ConfirmDeployContract.prototype.getData = function () { } ConfirmDeployContract.prototype.getAmount = function () { - const { conversionRate } = this.props + const { conversionRate, currentCurrency } = this.props const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} - const USD = conversionUtil(txParams.value, { + const FIAT = conversionUtil(txParams.value, { fromNumericBase: 'hex', toNumericBase: 'dec', fromCurrency: 'ETH', - toCurrency: 'USD', + toCurrency: currentCurrency, numberOfDecimals: 2, fromDenomination: 'WEI', conversionRate, @@ -148,14 +150,14 @@ ConfirmDeployContract.prototype.getAmount = function () { }) return { - fiat: Number(USD), + fiat: Number(FIAT), token: Number(ETH), } } ConfirmDeployContract.prototype.getGasFee = function () { - const { conversionRate } = this.props + const { conversionRate, currentCurrency } = this.props const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} @@ -169,12 +171,12 @@ ConfirmDeployContract.prototype.getGasFee = function () { const txFeeBn = gasBn.mul(gasPriceBn) - const USD = conversionUtil(txFeeBn, { + const FIAT = conversionUtil(txFeeBn, { fromNumericBase: 'BN', toNumericBase: 'dec', fromDenomination: 'WEI', fromCurrency: 'ETH', - toCurrency: 'USD', + toCurrency: currentCurrency, numberOfDecimals: 2, conversionRate, }) @@ -189,7 +191,7 @@ ConfirmDeployContract.prototype.getGasFee = function () { }) return { - fiat: Number(USD), + fiat: Number(FIAT), eth: Number(ETH), } } @@ -200,7 +202,7 @@ ConfirmDeployContract.prototype.renderGasFee = function () { h('section.flex-row.flex-center.confirm-screen-row', [ h('span.confirm-screen-label.confirm-screen-section-column', [ 'Gas Fee' ]), h('div.confirm-screen-section-column', [ - h('div.confirm-screen-row-info', `$${fiatGas} USD`), + h('div.confirm-screen-row-info', `${fiatGas} FIAT`), h( 'div.confirm-screen-row-detail', @@ -212,6 +214,7 @@ ConfirmDeployContract.prototype.renderGasFee = function () { } ConfirmDeployContract.prototype.renderHeroAmount = function () { + const { currentCurrency } = this.props const { fiat: fiatAmount } = this.getAmount() const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} @@ -219,8 +222,8 @@ ConfirmDeployContract.prototype.renderHeroAmount = function () { return ( h('div.confirm-send-token__hero-amount-wrapper', [ - h('h3.flex-center.confirm-screen-send-amount', `$${fiatAmount}`), - h('h3.flex-center.confirm-screen-send-amount-currency', 'USD'), + h('h3.flex-center.confirm-screen-send-amount', `${fiatAmount}`), + h('h3.flex-center.confirm-screen-send-amount-currency', currentCurrency.toUpperCase()), h('div.flex-center.confirm-memo-wrapper', [ h('h3.confirm-screen-send-memo', memo), ]), @@ -229,6 +232,7 @@ ConfirmDeployContract.prototype.renderHeroAmount = function () { } ConfirmDeployContract.prototype.renderTotalPlusGas = function () { + const { currentCurrency } = this.props const { fiat: fiatAmount, token: tokenAmount } = this.getAmount() const { fiat: fiatGas, eth: ethGas } = this.getGasFee() @@ -240,7 +244,7 @@ ConfirmDeployContract.prototype.renderTotalPlusGas = function () { ]), h('div.confirm-screen-section-column', [ - h('div.confirm-screen-row-info', `$${fiatAmount + fiatGas} USD`), + h('div.confirm-screen-row-info', `${fiatAmount + fiatGas} ${currentCurrency.toUpperCase()}`), h('div.confirm-screen-row-detail', `${tokenAmount + ethGas} ETH`), ]), ]) diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 537a9a659..51c36ba42 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -20,6 +20,7 @@ function mapStateToProps (state) { const { conversionRate, identities, + currentCurrency, } = state.metamask const accounts = state.metamask.accounts const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] @@ -27,6 +28,7 @@ function mapStateToProps (state) { conversionRate, identities, selectedAddress, + currentCurrency, } } @@ -45,15 +47,15 @@ function ConfirmSendEther () { } ConfirmSendEther.prototype.getAmount = function () { - const { conversionRate } = this.props + const { conversionRate, currentCurrency } = this.props const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} - console.log(txParams) - const USD = conversionUtil(txParams.value, { + console.log(`conversionRate, currentCurrency`, conversionRate, currentCurrency); + const FIAT = conversionUtil(txParams.value, { fromNumericBase: 'hex', toNumericBase: 'dec', fromCurrency: 'ETH', - toCurrency: 'USD', + toCurrency: currentCurrency, numberOfDecimals: 2, fromDenomination: 'WEI', conversionRate, @@ -69,14 +71,14 @@ ConfirmSendEther.prototype.getAmount = function () { }) return { - USD, + FIAT, ETH, } } ConfirmSendEther.prototype.getGasFee = function () { - const { conversionRate } = this.props + const { conversionRate, currentCurrency } = this.props const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} @@ -96,12 +98,12 @@ ConfirmSendEther.prototype.getGasFee = function () { const txFeeBn = gasBn.mul(gasPriceBn) - const USD = conversionUtil(txFeeBn, { + const FIAT = conversionUtil(txFeeBn, { fromNumericBase: 'BN', toNumericBase: 'dec', fromDenomination: 'WEI', fromCurrency: 'ETH', - toCurrency: 'USD', + toCurrency: currentCurrency, numberOfDecimals: 2, conversionRate, }) @@ -116,7 +118,7 @@ ConfirmSendEther.prototype.getGasFee = function () { }) return { - USD, + FIAT, ETH, } } @@ -125,10 +127,10 @@ ConfirmSendEther.prototype.getData = function () { const { identities } = this.props const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} - const { USD: gasFeeInUSD, ETH: gasFeeInETH } = this.getGasFee() - const { USD: amountInUSD, ETH: amountInETH } = this.getAmount() + const { FIAT: gasFeeInFIAT, ETH: gasFeeInETH } = this.getGasFee() + const { FIAT: amountInFIAT, ETH: amountInETH } = this.getAmount() - const totalInUSD = addCurrencies(gasFeeInUSD, amountInUSD, { + const totalInFIAT = addCurrencies(gasFeeInFIAT, amountInFIAT, { toNumericBase: 'dec', numberOfDecimals: 2, }) @@ -147,17 +149,17 @@ ConfirmSendEther.prototype.getData = function () { name: identities[txParams.to] ? identities[txParams.to].name : 'New Recipient', }, memo: txParams.memo || '', - gasFeeInUSD, + gasFeeInFIAT, gasFeeInETH, - amountInUSD, + amountInFIAT, amountInETH, - totalInUSD, + totalInFIAT, totalInETH, } } ConfirmSendEther.prototype.render = function () { - const { backToAccountDetail, selectedAddress } = this.props + const { backToAccountDetail, selectedAddress, currentCurrency } = this.props const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} @@ -171,10 +173,10 @@ ConfirmSendEther.prototype.render = function () { name: toName, }, memo, - gasFeeInUSD, + gasFeeInFIAT, gasFeeInETH, - amountInUSD, - totalInUSD, + amountInFIAT, + totalInFIAT, totalInETH, } = this.getData() @@ -239,8 +241,8 @@ ConfirmSendEther.prototype.render = function () { // `You're sending to Recipient ...${toAddress.slice(toAddress.length - 4)}`, // ]), - h('h3.flex-center.confirm-screen-send-amount', [`$${amountInUSD}`]), - h('h3.flex-center.confirm-screen-send-amount-currency', [ 'USD' ]), + h('h3.flex-center.confirm-screen-send-amount', [`$${amountInFIAT}`]), + h('h3.flex-center.confirm-screen-send-amount-currency', [ currentCurrency.toUpperCase() ]), h('div.flex-center.confirm-memo-wrapper', [ h('h3.confirm-screen-send-memo', [ memo ? `"${memo}"` : '' ]), ]), @@ -265,7 +267,7 @@ ConfirmSendEther.prototype.render = function () { h('section.flex-row.flex-center.confirm-screen-row', [ h('span.confirm-screen-label.confirm-screen-section-column', [ 'Gas Fee' ]), h('div.confirm-screen-section-column', [ - h('div.confirm-screen-row-info', `$${gasFeeInUSD} USD`), + h('div.confirm-screen-row-info', `${gasFeeInFIAT} ${currentCurrency.toUpperCase()}`), h('div.confirm-screen-row-detail', `${gasFeeInETH} ETH`), ]), @@ -279,7 +281,7 @@ ConfirmSendEther.prototype.render = function () { ]), h('div.confirm-screen-section-column', [ - h('div.confirm-screen-row-info', `$${totalInUSD} USD`), + h('div.confirm-screen-row-info', `${totalInFIAT} ${currentCurrency.toUpperCase()}`), h('div.confirm-screen-row-detail', `${totalInETH} ETH`), ]), ]), diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index 92bba8f62..155242f56 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -81,7 +81,7 @@ ConfirmSendToken.prototype.getAmount = function () { } ConfirmSendToken.prototype.getGasFee = function () { - const { conversionRate, tokenExchangeRate, token } = this.props + const { conversionRate, tokenExchangeRate, token, currentCurrency } = this.props const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} const { decimals } = token @@ -96,12 +96,12 @@ ConfirmSendToken.prototype.getGasFee = function () { const txFeeBn = gasBn.mul(gasPriceBn) - const USD = conversionUtil(txFeeBn, { + const FIAT = conversionUtil(txFeeBn, { fromNumericBase: 'BN', toNumericBase: 'dec', fromDenomination: 'WEI', fromCurrency: 'ETH', - toCurrency: 'USD', + toCurrency: currentCurrency, numberOfDecimals: 2, conversionRate, }) @@ -116,7 +116,7 @@ ConfirmSendToken.prototype.getGasFee = function () { }) return { - fiat: +Number(USD).toFixed(2), + fiat: +Number(FIAT).toFixed(2), eth: ETH, token: tokenExchangeRate ? +(ETH * tokenExchangeRate).toFixed(decimals) @@ -145,7 +145,7 @@ ConfirmSendToken.prototype.getData = function () { } ConfirmSendToken.prototype.renderHeroAmount = function () { - const { token: { symbol } } = this.props + const { token: { symbol }, currentCurrency } = this.props const { fiat: fiatAmount, token: tokenAmount } = this.getAmount() const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} @@ -154,8 +154,8 @@ ConfirmSendToken.prototype.renderHeroAmount = function () { return fiatAmount ? ( h('div.confirm-send-token__hero-amount-wrapper', [ - h('h3.flex-center.confirm-screen-send-amount', `$${fiatAmount}`), - h('h3.flex-center.confirm-screen-send-amount-currency', 'USD'), + h('h3.flex-center.confirm-screen-send-amount', `${fiatAmount}`), + h('h3.flex-center.confirm-screen-send-amount-currency', currentCurrency), h('div.flex-center.confirm-memo-wrapper', [ h('h3.confirm-screen-send-memo', [ memo ? `"${memo}"` : '' ]), ]), @@ -173,14 +173,14 @@ ConfirmSendToken.prototype.renderHeroAmount = function () { } ConfirmSendToken.prototype.renderGasFee = function () { - const { token: { symbol } } = this.props + const { token: { symbol }, currentCurrency } = this.props const { fiat: fiatGas, token: tokenGas, eth: ethGas } = this.getGasFee() return ( h('section.flex-row.flex-center.confirm-screen-row', [ h('span.confirm-screen-label.confirm-screen-section-column', [ 'Gas Fee' ]), h('div.confirm-screen-section-column', [ - h('div.confirm-screen-row-info', `$${fiatGas} USD`), + h('div.confirm-screen-row-info', `${fiatGas} ${currentCurrency}`), h( 'div.confirm-screen-row-detail', @@ -192,7 +192,7 @@ ConfirmSendToken.prototype.renderGasFee = function () { } ConfirmSendToken.prototype.renderTotalPlusGas = function () { - const { token: { symbol } } = this.props + const { token: { symbol }, currentCurrency } = this.props const { fiat: fiatAmount, token: tokenAmount } = this.getAmount() const { fiat: fiatGas, token: tokenGas } = this.getGasFee() @@ -205,7 +205,7 @@ ConfirmSendToken.prototype.renderTotalPlusGas = function () { ]), h('div.confirm-screen-section-column', [ - h('div.confirm-screen-row-info', `$${fiatAmount + fiatGas} USD`), + h('div.confirm-screen-row-info', `${fiatAmount + fiatGas} ${currentCurrency}`), h('div.confirm-screen-row-detail', `${tokenAmount + tokenGas} ${symbol}`), ]), ]) @@ -219,7 +219,7 @@ ConfirmSendToken.prototype.renderTotalPlusGas = function () { h('div.confirm-screen-section-column', [ h('div.confirm-screen-row-info', `${tokenAmount} ${symbol}`), - h('div.confirm-screen-row-detail', `+ ${fiatGas} USD Gas`), + h('div.confirm-screen-row-detail', `+ ${fiatGas} ${currentCurrency} Gas`), ]), ]) ) diff --git a/ui/app/components/pending-tx/index.js b/ui/app/components/pending-tx/index.js index 770fb1dfd..f4f6afb8f 100644 --- a/ui/app/components/pending-tx/index.js +++ b/ui/app/components/pending-tx/index.js @@ -36,7 +36,6 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { - setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('usd')), backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)), cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), } @@ -58,8 +57,6 @@ PendingTx.prototype.componentWillMount = async function () { const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} - this.props.setCurrentCurrencyToUSD() - if (!txParams.to) { return this.setState({ transactionType: TX_TYPES.DEPLOY_CONTRACT, diff --git a/ui/app/components/send/account-list-item.js b/ui/app/components/send/account-list-item.js index 64acde767..0938f4cad 100644 --- a/ui/app/components/send/account-list-item.js +++ b/ui/app/components/send/account-list-item.js @@ -4,7 +4,7 @@ const inherits = require('util').inherits const connect = require('react-redux').connect const Identicon = require('../identicon') const CurrencyDisplay = require('./currency-display') -const { conversionRateSelector } = require('../../selectors') +const { conversionRateSelector, getCurrentCurrency } = require('../../selectors') inherits(AccountListItem, Component) function AccountListItem () { @@ -13,7 +13,8 @@ function AccountListItem () { function mapStateToProps(state) { return { - conversionRate: conversionRateSelector(state) + conversionRate: conversionRateSelector(state), + currentCurrency: getCurrentCurrency(state), } } @@ -25,6 +26,7 @@ AccountListItem.prototype.render = function () { handleClick, icon = null, conversionRate, + currentCurrency, } = this.props const { name, address, balance } = account @@ -52,10 +54,9 @@ AccountListItem.prototype.render = function () { h(CurrencyDisplay, { primaryCurrency: 'ETH', - convertedCurrency: 'USD', + convertedCurrency: currentCurrency, value: balance, conversionRate, - convertedPrefix: '$', readOnly: true, className: 'account-list-item__account-balances', primaryBalanceClassName: 'account-list-item__account-primary-balance', diff --git a/ui/app/components/send/currency-display.js b/ui/app/components/send/currency-display.js index f7fbb2379..2c9a2d33b 100644 --- a/ui/app/components/send/currency-display.js +++ b/ui/app/components/send/currency-display.js @@ -118,7 +118,7 @@ CurrencyDisplay.prototype.render = function () { h('div', { className: convertedBalanceClassName, - }, `${convertedPrefix}${convertedValue} ${convertedCurrency}`), + }, `${convertedValue} ${convertedCurrency.toUpperCase()}`), ]) diff --git a/ui/app/components/send/gas-fee-display-v2.js b/ui/app/components/send/gas-fee-display-v2.js index 3b39312ec..0e23b63ac 100644 --- a/ui/app/components/send/gas-fee-display-v2.js +++ b/ui/app/components/send/gas-fee-display-v2.js @@ -15,6 +15,8 @@ GasFeeDisplay.prototype.render = function () { conversionRate, gasTotal, onClick, + primaryCurrency = 'ETH', + convertedCurrency, } = this.props return h('div.send-v2__gas-fee-display', [ @@ -22,7 +24,7 @@ GasFeeDisplay.prototype.render = function () { gasTotal ? h(CurrencyDisplay, { primaryCurrency: 'ETH', - convertedCurrency: 'USD', + convertedCurrency, value: gasTotal, conversionRate, convertedPrefix: '$', diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js index ebe2b878b..c14865e9f 100644 --- a/ui/app/components/send/send-v2-container.js +++ b/ui/app/components/send/send-v2-container.js @@ -16,6 +16,7 @@ const { getGasLimit, getAddressBook, getSendFrom, + getCurrentCurrency, } = require('../../selectors') module.exports = connect(mapStateToProps, mapDispatchToProps)(SendEther) @@ -30,7 +31,7 @@ function mapStateToProps (state) { let data; let primaryCurrency; - let tokenToUSDRate; + let tokenToFiatRate; if (selectedToken) { data = Array.prototype.map.call( abi.rawEncode(['address', 'uint256'], [selectedAddress, '0x0']), @@ -39,7 +40,7 @@ function mapStateToProps (state) { primaryCurrency = selectedToken.symbol - tokenToUSDRate = multiplyCurrencies( + tokenToFiatRate = multiplyCurrencies( conversionRate, selectedTokenExchangeRate, { toNumericBase: 'dec' } @@ -54,8 +55,9 @@ function mapStateToProps (state) { conversionRate, selectedToken, primaryCurrency, + convertedCurrency: getCurrentCurrency(state), data, - amountConversionRate: selectedToken ? tokenToUSDRate : conversionRate, + amountConversionRate: selectedToken ? tokenToFiatRate : conversionRate, } } diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 8422c02b9..3bb9a2eda 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -11,11 +11,14 @@ const Identicon = require('./identicon') const { conversionUtil } = require('../conversion-util') +const { getCurrentCurrency } = require('../selectors') + module.exports = connect(mapStateToProps)(TxListItem) function mapStateToProps (state) { return { tokens: state.metamask.tokens, + currentCurrency: getCurrentCurrency(state), } } @@ -49,17 +52,18 @@ TxListItem.prototype.getSendEtherTotal = function () { transactionAmount, conversionRate, address, + currentCurrency, } = this.props if (!address) { return {} } - const totalInUSD = conversionUtil(transactionAmount, { + const totalInFiat = conversionUtil(transactionAmount, { fromNumericBase: 'hex', toNumericBase: 'dec', fromCurrency: 'ETH', - toCurrency: 'USD', + toCurrency: currentCurrency, fromDenomination: 'WEI', numberOfDecimals: 2, conversionRate, @@ -76,7 +80,7 @@ TxListItem.prototype.getSendEtherTotal = function () { return { total: `${totalInETH} ETH`, - fiatTotal: `$${totalInUSD} USD`, + fiatTotal: `${totalInFiat} ${currentCurrency.toUpperCase()}`, } } -- cgit v1.2.3 From 89af385a352daf66ad1a6fb3bba75676fd3b9e7f Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 18 Oct 2017 15:38:53 -0230 Subject: Fix handling of arithmetic on token gas in confirm-send-token. --- ui/app/components/pending-tx/confirm-send-token.js | 49 +++++++++++++++------- 1 file changed, 33 insertions(+), 16 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index 92bba8f62..de716a26a 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -11,12 +11,22 @@ const Identicon = require('../identicon') const ethUtil = require('ethereumjs-util') const BN = ethUtil.BN const hexToBn = require('../../../../app/scripts/lib/hex-to-bn') -const { conversionUtil } = require('../../conversion-util') +const { + conversionUtil, + multiplyCurrencies, + addCurrencies, +} = require('../../conversion-util') const MIN_GAS_PRICE_GWEI_BN = new BN(1) const GWEI_FACTOR = new BN(1e9) const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR) +const { + getSelectedTokenExchangeRate, + getTokenExchangeRate, + getSelectedAddress, +} = require('../../selectors') + module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmSendToken) function mapStateToProps (state, ownProps) { @@ -28,10 +38,8 @@ function mapStateToProps (state, ownProps) { identities, } = state.metamask const accounts = state.metamask.accounts - const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] - const tokenExchangeRates = state.metamask.tokenExchangeRates - const pair = `${symbol.toLowerCase()}_eth` - const { rate: tokenExchangeRate = 0 } = tokenExchangeRates[pair] || {} + const selectedAddress = getSelectedAddress(state) + const tokenExchangeRate = getTokenExchangeRate(state, symbol) return { conversionRate, @@ -86,17 +94,14 @@ ConfirmSendToken.prototype.getGasFee = function () { const txParams = txMeta.txParams || {} const { decimals } = token - // Gas const gas = txParams.gas - const gasBn = hexToBn(gas) - - // Gas Price const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16) - const gasPriceBn = hexToBn(gasPrice) - const txFeeBn = gasBn.mul(gasPriceBn) - + const gasTotal = multiplyCurrencies(gas, gasPrice, { + multiplicandBase: 16, + multiplierBase: 16, + }) - const USD = conversionUtil(txFeeBn, { + const USD = conversionUtil(gasTotal, { fromNumericBase: 'BN', toNumericBase: 'dec', fromDenomination: 'WEI', @@ -105,7 +110,7 @@ ConfirmSendToken.prototype.getGasFee = function () { numberOfDecimals: 2, conversionRate, }) - const ETH = conversionUtil(txFeeBn, { + const ETH = conversionUtil(gasTotal, { fromNumericBase: 'BN', toNumericBase: 'dec', fromDenomination: 'WEI', @@ -114,12 +119,22 @@ ConfirmSendToken.prototype.getGasFee = function () { numberOfDecimals: 6, conversionRate, }) + const tokenGas = multiplyCurrencies(gas, gasPrice, { + toNumericBase: 'dec', + multiplicandBase: 16, + multiplierBase: 16, + toCurrency: 'BAT', + conversionRate: tokenExchangeRate, + invertConversionRate: true, + fromDenomination: 'WEI', + numberOfDecimals: decimals || 4, + }) return { fiat: +Number(USD).toFixed(2), eth: ETH, token: tokenExchangeRate - ? +(ETH * tokenExchangeRate).toFixed(decimals) + ? tokenGas : null, } } @@ -196,6 +211,8 @@ ConfirmSendToken.prototype.renderTotalPlusGas = function () { const { fiat: fiatAmount, token: tokenAmount } = this.getAmount() const { fiat: fiatGas, token: tokenGas } = this.getGasFee() + const tokenTotal = addCurrencies(tokenAmount, tokenGas || '0') + return fiatAmount && fiatGas ? ( h('section.flex-row.flex-center.confirm-screen-total-box ', [ @@ -206,7 +223,7 @@ ConfirmSendToken.prototype.renderTotalPlusGas = function () { h('div.confirm-screen-section-column', [ h('div.confirm-screen-row-info', `$${fiatAmount + fiatGas} USD`), - h('div.confirm-screen-row-detail', `${tokenAmount + tokenGas} ${symbol}`), + h('div.confirm-screen-row-detail', `${tokenTotal} ${symbol}`), ]), ]) ) -- cgit v1.2.3 From 7362fb8dfc5b8d9f3ae9a3399f9448ea5720cd43 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 18 Oct 2017 15:56:13 -0230 Subject: Identicon in send token show who you are sending to, not the token's identicon. --- ui/app/components/pending-tx/confirm-send-token.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index de716a26a..356da36c3 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -145,14 +145,14 @@ ConfirmSendToken.prototype.getData = function () { const { value } = params[0] || {} const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} - + return { from: { address: txParams.from, name: identities[txParams.from].name, }, to: { - address: txParams.to, + address: value, name: identities[value] ? identities[value].name : 'New Recipient', }, memo: txParams.memo || '', @@ -290,7 +290,7 @@ ConfirmSendToken.prototype.render = function () { h( Identicon, { - address: txParams.to, + address: toAddress, diameter: 60, }, ), -- cgit v1.2.3 From c2880c4b8fe56f3b175d75b6ae8a84271dde3e28 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 18 Oct 2017 16:53:35 -0230 Subject: Min and default gas price, limit, total; comments out code for gas slider. --- .../customize-gas-modal/gas-modal-card.js | 18 ++++++++--------- ui/app/components/customize-gas-modal/index.js | 17 ++++++++++------ ui/app/components/send/send-constants.js | 23 ++++++++++++++++++++++ 3 files changed, 43 insertions(+), 15 deletions(-) create mode 100644 ui/app/components/send/send-constants.js (limited to 'ui/app/components') diff --git a/ui/app/components/customize-gas-modal/gas-modal-card.js b/ui/app/components/customize-gas-modal/gas-modal-card.js index 8e739ee40..de181dc67 100644 --- a/ui/app/components/customize-gas-modal/gas-modal-card.js +++ b/ui/app/components/customize-gas-modal/gas-modal-card.js @@ -19,7 +19,7 @@ GasModalCard.prototype.render = function () { unitLabel, value, min, - max, + // max, step, title, copy @@ -34,20 +34,20 @@ GasModalCard.prototype.render = function () { h(InputNumber, { unitLabel, step, - max, + // max, min, placeholder: '0', value, onChange, }), - h(GasSlider, { - value, - step, - max, - min, - onChange, - }), + // h(GasSlider, { + // value, + // step, + // max, + // min, + // onChange, + // }), ]) diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 0ba768893..744891c47 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -5,6 +5,11 @@ const connect = require('react-redux').connect const actions = require('../../actions') const GasModalCard = require('./gas-modal-card') +const { + MIN_GAS_PRICE, + MIN_GAS_LIMIT, +} = require('../send/send-constants') + const { conversionUtil, multiplyCurrencies } = require('../../conversion-util') const { @@ -35,8 +40,8 @@ function CustomizeGasModal (props) { Component.call(this) this.state = { - gasPrice: props.gasPrice, - gasLimit: props.gasLimit, + gasPrice: props.gasPrice || MIN_GAS_PRICE, + gasLimit: props.gasLimit || MIN_GAS_LIMIT, } } @@ -115,8 +120,8 @@ CustomizeGasModal.prototype.render = function () { h(GasModalCard, { value: convertedGasPrice, - min: 0, - max: 1000, + min: MIN_GAS_PRICE, + // max: 1000, step: 1, onChange: value => this.convertAndSetGasPrice(value), title: 'Gas Price', @@ -125,8 +130,8 @@ CustomizeGasModal.prototype.render = function () { h(GasModalCard, { value: convertedGasLimit, - min: 20000, - max: 100000, + min: MIN_GAS_LIMIT, + // max: 100000, step: 1, onChange: value => this.convertAndSetGasLimit(value), title: 'Gas Limit', diff --git a/ui/app/components/send/send-constants.js b/ui/app/components/send/send-constants.js new file mode 100644 index 000000000..a819a8c28 --- /dev/null +++ b/ui/app/components/send/send-constants.js @@ -0,0 +1,23 @@ +const Identicon = require('../identicon') +const { multiplyCurrencies } = require('../../conversion-util') + +const MIN_GAS_PRICE_GWEI = '1' +const GWEI_FACTOR = '1e9' +const MIN_GAS_PRICE = multiplyCurrencies(GWEI_FACTOR, MIN_GAS_PRICE_GWEI, { + multiplicandBase: 16, + multiplierBase: 16, +}) +const MIN_GAS_LIMIT = (21000).toString(16) +const MIN_GAS_TOTAL = multiplyCurrencies(MIN_GAS_LIMIT, MIN_GAS_PRICE, { + toNumericBase: 'hex', + multiplicandBase: 16, + multiplierBase: 16, +}) + +module.exports = { + MIN_GAS_PRICE_GWEI, + GWEI_FACTOR, + MIN_GAS_PRICE, + MIN_GAS_LIMIT, + MIN_GAS_TOTAL, +} -- cgit v1.2.3 From 376ae032fedb99d22b7c71438ec9482d2013c78e Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Thu, 19 Oct 2017 12:47:44 -0700 Subject: Fix selectors --- ui/app/components/account-menu/index.js | 5 ++--- ui/app/components/wallet-view.js | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index 2ebdba24a..85bd21076 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -35,7 +35,6 @@ function mapDispatchToProps (dispatch) { dispatch(actions.toggleAccountMenu()) }, showConfigPage: () => { - console.log('hihihih') dispatch(actions.showConfigPage()) dispatch(actions.toggleAccountMenu()) }, @@ -60,7 +59,6 @@ AccountMenu.prototype.render = function () { showConfigPage, } = this.props - console.log(showConfigPage) return h(Menu, { className: 'account-menu', isShowing: isAccountMenuOpen }, [ h(CloseArea, { onClick: toggleAccountMenu }), h(Item, { @@ -105,11 +103,12 @@ AccountMenu.prototype.renderAccounts = function () { showAccountDetail, } = this.props + console.log({ accounts }) return Object.keys(identities).map((key, index) => { const identity = identities[key] const isSelected = identity.address === selected - const balanceValue = accounts[key].balance + const balanceValue = accounts[key] ? accounts[key].balance : '' const formattedBalance = balanceValue ? formatBalance(balanceValue, 6) : '...' const simpleAddress = identity.address.substring(2).toLowerCase() diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index f06c4d512..a870a24e3 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -47,7 +47,7 @@ WalletView.prototype.renderWalletBalance = function () { hideSidebar, sidebarOpen, } = this.props - + console.log({ selectedAccount }) const selectedClass = selectedTokenAddress ? '' : 'wallet-balance-wrapper--active' @@ -63,7 +63,7 @@ WalletView.prototype.renderWalletBalance = function () { }, [ h(BalanceComponent, { - balanceValue: selectedAccount.balance, + balanceValue: selectedAccount ? selectedAccount.balance : '', style: {}, }), ] -- cgit v1.2.3 From 0458643f104d7b328e24c4403e4e3d91b4d5de92 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Thu, 19 Oct 2017 14:08:52 -0700 Subject: various styling fix on mobile --- ui/app/components/send/account-list-item.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send/account-list-item.js b/ui/app/components/send/account-list-item.js index 0938f4cad..ba7eec940 100644 --- a/ui/app/components/send/account-list-item.js +++ b/ui/app/components/send/account-list-item.js @@ -11,7 +11,7 @@ function AccountListItem () { Component.call(this) } -function mapStateToProps(state) { +function mapStateToProps (state) { return { conversionRate: conversionRateSelector(state), currentCurrency: getCurrentCurrency(state), @@ -22,14 +22,14 @@ module.exports = connect(mapStateToProps)(AccountListItem) AccountListItem.prototype.render = function () { const { - account, - handleClick, + account, + handleClick, icon = null, conversionRate, currentCurrency, } = this.props - const { name, address, balance } = account + const { name, address, balance } = account || {} return h('div.account-list-item', { onClick: () => handleClick({ name, address, balance }), -- cgit v1.2.3 From 79be956be9f5297d6d601941e50d5ae4eca58560 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Thu, 19 Oct 2017 14:10:29 -0700 Subject: Fix network dropdown styles --- ui/app/components/dropdowns/network-dropdown.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js index 736019c39..20dfca590 100644 --- a/ui/app/components/dropdowns/network-dropdown.js +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -78,7 +78,7 @@ NetworkDropdown.prototype.render = function () { zIndex: 11, style: { position: 'absolute', - top: '38px', + top: '58px', minWidth: '309px', }, innerStyle: { -- cgit v1.2.3 From 5a93ec02523e8b54222cc44cba5b80dcf8f07a7a Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Thu, 19 Oct 2017 21:06:14 -0700 Subject: Fix loading animation not showing on network change --- ui/app/components/buy-button-subview.js | 2 +- ui/app/components/loading.js | 75 +++++++++++++++------------------ 2 files changed, 35 insertions(+), 42 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/buy-button-subview.js b/ui/app/components/buy-button-subview.js index 6cf6e9eb9..a36f41df5 100644 --- a/ui/app/components/buy-button-subview.js +++ b/ui/app/components/buy-button-subview.js @@ -87,7 +87,7 @@ BuyButtonSubview.prototype.headerSubview = function () { left: '49vw', }, }, [ - h(Loading, { isLoading }), + isLoading && h(Loading), ]), // account panel diff --git a/ui/app/components/loading.js b/ui/app/components/loading.js index 163792584..e6d841aa0 100644 --- a/ui/app/components/loading.js +++ b/ui/app/components/loading.js @@ -1,45 +1,38 @@ -const inherits = require('util').inherits -const Component = require('react').Component +const { Component } = require('react') const h = require('react-hyperscript') - -inherits(LoadingIndicator, Component) -module.exports = LoadingIndicator - -function LoadingIndicator () { - Component.call(this) -} - -LoadingIndicator.prototype.render = function () { - const { isLoading, loadingMessage } = this.props - - return ( - isLoading ? h('.full-flex-height', { - style: { - left: '0px', - zIndex: 10, - position: 'absolute', - flexDirection: 'column', - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - height: '100%', - width: '100%', - background: 'rgba(255, 255, 255, 0.8)', - }, - }, [ - h('img', { - src: 'images/loading.svg', - }), - - h('br'), - - showMessageIfAny(loadingMessage), - ]) : null - ) +class LoadingIndicator extends Component { + renderMessage () { + const { loadingMessage } = this.props + return loadingMessage && h('span', loadingMessage) + } + + render () { + return ( + h('.full-flex-height', { + style: { + left: '0px', + zIndex: 50, + position: 'absolute', + flexDirection: 'column', + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + height: '100%', + width: '100%', + background: 'rgba(255, 255, 255, 0.8)', + }, + }, [ + h('img', { + src: 'images/loading.svg', + }), + + h('br'), + + this.renderMessage(), + ]) + ) + } } -function showMessageIfAny (loadingMessage) { - if (!loadingMessage) return null - return h('span', loadingMessage) -} +module.exports = LoadingIndicator -- cgit v1.2.3 From 80025e278b6c02f87bcfce3b8d5443722f4f9e52 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 20 Oct 2017 18:13:55 -0230 Subject: Fixes regression in confirm-send-token --- ui/app/components/pending-tx/confirm-send-token.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index 42b676954..6fb4ddf70 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -36,6 +36,7 @@ function mapStateToProps (state, ownProps) { const { conversionRate, identities, + currentCurrency, } = state.metamask const accounts = state.metamask.accounts const selectedAddress = getSelectedAddress(state) @@ -47,6 +48,7 @@ function mapStateToProps (state, ownProps) { selectedAddress, tokenExchangeRate, tokenData: tokenData || {}, + currentCurrency: currentCurrency.toUpperCase(), } } @@ -101,7 +103,7 @@ ConfirmSendToken.prototype.getGasFee = function () { multiplierBase: 16, }) - const FIAT = conversionUtil(txFeeBn, { + const FIAT = conversionUtil(gasTotal, { fromNumericBase: 'BN', toNumericBase: 'dec', fromDenomination: 'WEI', @@ -223,7 +225,7 @@ ConfirmSendToken.prototype.renderTotalPlusGas = function () { h('div.confirm-screen-section-column', [ h('div.confirm-screen-row-info', `${fiatAmount + fiatGas} ${currentCurrency}`), - h('div.confirm-screen-row-detail', `${tokenAmount + tokenGas} ${symbol}`), + h('div.confirm-screen-row-detail', `${tokenTotal} ${symbol}`), ]), ]) ) -- cgit v1.2.3 From 5eb3cf43bfab3728dde151bc84439993b1a93184 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Fri, 20 Oct 2017 16:18:25 -0700 Subject: Add resiliency to confirm-send-token --- ui/app/components/pending-tx/confirm-send-token.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index 6fb4ddf70..a4c3d16e3 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -85,7 +85,9 @@ ConfirmSendToken.prototype.getAmount = function () { fiat: tokenExchangeRate ? +(sendTokenAmount * tokenExchangeRate * conversionRate).toFixed(2) : null, - token: +sendTokenAmount.toFixed(decimals), + token: typeof value === 'undefined' + ? 'Unknown' + : +sendTokenAmount.toFixed(decimals), } } @@ -213,8 +215,6 @@ ConfirmSendToken.prototype.renderTotalPlusGas = function () { const { fiat: fiatAmount, token: tokenAmount } = this.getAmount() const { fiat: fiatGas, token: tokenGas } = this.getGasFee() - const tokenTotal = addCurrencies(tokenAmount, tokenGas || '0') - return fiatAmount && fiatGas ? ( h('section.flex-row.flex-center.confirm-screen-total-box ', [ @@ -225,7 +225,7 @@ ConfirmSendToken.prototype.renderTotalPlusGas = function () { h('div.confirm-screen-section-column', [ h('div.confirm-screen-row-info', `${fiatAmount + fiatGas} ${currentCurrency}`), - h('div.confirm-screen-row-detail', `${tokenTotal} ${symbol}`), + h('div.confirm-screen-row-detail', `${addCurrencies(tokenAmount, tokenGas || '0')} ${symbol}`), ]), ]) ) @@ -321,7 +321,7 @@ ConfirmSendToken.prototype.render = function () { ]), ]), - h('section.flex-row.flex-center.confirm-screen-row', [ + toAddress && h('section.flex-row.flex-center.confirm-screen-row', [ h('span.confirm-screen-label.confirm-screen-section-column', [ 'To' ]), h('div.confirm-screen-section-column', [ h('div.confirm-screen-row-info', toName), -- cgit v1.2.3 From 8f3b762461ada222f82089e686a61183dd167428 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Fri, 20 Oct 2017 18:26:18 -0700 Subject: Fix Conversions bugs; Fiat value bugs --- ui/app/components/pending-tx/confirm-deploy-contract.js | 4 +++- ui/app/components/pending-tx/confirm-send-ether.js | 2 +- ui/app/components/send/currency-display.js | 12 +++++++++++- ui/app/components/token-cell.js | 8 +++++--- 4 files changed, 20 insertions(+), 6 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-deploy-contract.js b/ui/app/components/pending-tx/confirm-deploy-contract.js index d19cec755..a0ba94045 100644 --- a/ui/app/components/pending-tx/confirm-deploy-contract.js +++ b/ui/app/components/pending-tx/confirm-deploy-contract.js @@ -195,14 +195,16 @@ ConfirmDeployContract.prototype.getGasFee = function () { eth: Number(ETH), } } + ConfirmDeployContract.prototype.renderGasFee = function () { + const { currentCurrency } = this.props const { fiat: fiatGas, eth: ethGas } = this.getGasFee() return ( h('section.flex-row.flex-center.confirm-screen-row', [ h('span.confirm-screen-label.confirm-screen-section-column', [ 'Gas Fee' ]), h('div.confirm-screen-section-column', [ - h('div.confirm-screen-row-info', `${fiatGas} FIAT`), + h('div.confirm-screen-row-info', `${fiatGas} ${currentCurrency.toUpperCase()}`), h( 'div.confirm-screen-row-detail', diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 51c36ba42..7162c7122 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -241,7 +241,7 @@ ConfirmSendEther.prototype.render = function () { // `You're sending to Recipient ...${toAddress.slice(toAddress.length - 4)}`, // ]), - h('h3.flex-center.confirm-screen-send-amount', [`$${amountInFIAT}`]), + h('h3.flex-center.confirm-screen-send-amount', [`${amountInFIAT}`]), h('h3.flex-center.confirm-screen-send-amount-currency', [ currentCurrency.toUpperCase() ]), h('div.flex-center.confirm-memo-wrapper', [ h('h3.confirm-screen-send-memo', [ memo ? `"${memo}"` : '' ]), diff --git a/ui/app/components/send/currency-display.js b/ui/app/components/send/currency-display.js index 2c9a2d33b..7180b94d3 100644 --- a/ui/app/components/send/currency-display.js +++ b/ui/app/components/send/currency-display.js @@ -36,6 +36,16 @@ function toHexWei (value) { }) } +CurrencyDisplay.prototype.getAmount = function (value) { + const { selectedToken } = this.props + const { decimals } = selectedToken || {} + const multiplier = Math.pow(10, Number(decimals || 0)) + const sendAmount = '0x' + Number(value * multiplier).toString(16) + return selectedToken + ? sendAmount + : toHexWei(value) +} + CurrencyDisplay.prototype.render = function () { const { className = 'currency-display', @@ -102,7 +112,7 @@ CurrencyDisplay.prototype.render = function () { this.setState({ value: newValue }) } }, - onBlur: event => !readOnly && handleChange(toHexWei(event.target.value.split(' ')[0])), + onBlur: event => !readOnly && handleChange(this.getAmount(event.target.value.split(' ')[0])), onKeyUp: event => { if (!readOnly) { validate(toHexWei(value || initValueToRender)) diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index ad431df69..6bb42204e 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -13,6 +13,7 @@ const TokenMenuDropdown = require('./dropdowns/token-menu-dropdown.js') function mapStateToProps (state) { return { network: state.metamask.network, + currentCurrency: state.metamask.currentCurrency, selectedTokenAddress: state.metamask.selectedTokenAddress, userAddress: selectors.getSelectedAddress(state), tokenExchangeRates: state.metamask.tokenExchangeRates, @@ -63,18 +64,19 @@ TokenCell.prototype.render = function () { ethToUSDRate, hideSidebar, sidebarOpen, + currentCurrency, // userAddress, } = props const pair = `${symbol.toLowerCase()}_eth`; let currentTokenToEthRate; - let currentTokenInUSD; + let currentTokenInFiat; let formattedUSD = '' if (tokenExchangeRates[pair]) { currentTokenToEthRate = tokenExchangeRates[pair].rate; - currentTokenInUSD = conversionUtil(string, { + currentTokenInFiat = conversionUtil(string, { fromNumericBase: 'dec', fromCurrency: symbol, toCurrency: 'USD', @@ -82,7 +84,7 @@ TokenCell.prototype.render = function () { conversionRate: currentTokenToEthRate, ethToUSDRate, }) - formattedUSD = `$${currentTokenInUSD} USD`; + formattedUSD = `${currentTokenInFiat} ${currentCurrency.toUpperCase()}`; } return ( -- cgit v1.2.3 From 2c032e0df44a2d589aae62d3fc532df82441580b Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Sun, 22 Oct 2017 22:40:03 -0700 Subject: Update settings screen to new UI --- ui/app/components/dropdowns/simple-dropdown.js | 91 ++++++++++++++++++++++++++ ui/app/components/tab-bar.js | 63 +++++++++--------- 2 files changed, 124 insertions(+), 30 deletions(-) create mode 100644 ui/app/components/dropdowns/simple-dropdown.js (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/simple-dropdown.js b/ui/app/components/dropdowns/simple-dropdown.js new file mode 100644 index 000000000..8cea78518 --- /dev/null +++ b/ui/app/components/dropdowns/simple-dropdown.js @@ -0,0 +1,91 @@ +const { Component, PropTypes } = require('react') +const h = require('react-hyperscript') +const classnames = require('classnames') +const R = require('ramda') + +class SimpleDropdown extends Component { + constructor (props) { + super(props) + this.state = { + isOpen: false, + } + } + + getDisplayValue () { + const { selectedOption, options } = this.props + const matchesOption = option => option.value === selectedOption + const matchingOption = R.find(matchesOption)(options) + return matchingOption + ? matchingOption.displayValue || matchingOption.value + : selectedOption + } + + handleClose () { + this.setState({ isOpen: false }) + } + + toggleOpen () { + const { isOpen } = this.state + this.setState({ isOpen: !isOpen }) + } + + renderOptions () { + const { options, onSelect, selectedOption } = this.props + + return h('div', [ + h('div.simple-dropdown__close-area', { + onClick: event => { + event.stopPropagation() + this.handleClose() + }, + }), + h('div.simple-dropdown__options', [ + ...options.map(option => { + return h( + 'div.simple-dropdown__option', + { + className: classnames({ + 'simple-dropdown__option--selected': option.value === selectedOption, + }), + key: option.value, + onClick: () => { + if (option.value !== selectedOption) { + onSelect(option.value) + } + + this.handleClose() + }, + }, + option.displayValue || option.value, + ) + }), + ]), + ]) + } + + render () { + const { placeholder } = this.props + const { isOpen } = this.state + + return h( + 'div.simple-dropdown', + { + onClick: () => this.toggleOpen(), + }, + [ + h('div.simple-dropdown__selected', this.getDisplayValue() || placeholder || 'Select'), + h('i.fa.fa-caret-down.fa-lg.simple-dropdown__caret'), + isOpen && this.renderOptions(), + ] + ) + } +} + +SimpleDropdown.propTypes = { + options: PropTypes.array.isRequired, + placeholder: PropTypes.string, + onSelect: PropTypes.func, + selectedOption: PropTypes.string, +} + +module.exports = SimpleDropdown diff --git a/ui/app/components/tab-bar.js b/ui/app/components/tab-bar.js index bef444a48..fe4076ed0 100644 --- a/ui/app/components/tab-bar.js +++ b/ui/app/components/tab-bar.js @@ -1,37 +1,40 @@ -const Component = require('react').Component +const { Component } = require('react') const h = require('react-hyperscript') -const inherits = require('util').inherits +const classnames = require('classnames') -module.exports = TabBar +class TabBar extends Component { + constructor (props) { + super(props) + const { defaultTab, tabs } = props -inherits(TabBar, Component) -function TabBar () { - Component.call(this) -} + this.state = { + subview: defaultTab || tabs[0].key, + } + } -TabBar.prototype.render = function () { - const props = this.props - const state = this.state || {} - const { tabs = [], defaultTab, tabSelected } = props - const { subview = defaultTab } = state + render () { + const { tabs = [], tabSelected } = this.props + const { subview } = this.state - return ( - h('.flex-row.space-around.text-transform-uppercase', { - style: { - background: '#EBEBEB', - color: '#AEAEAE', - paddingTop: '4px', - minHeight: '30px', - }, - }, tabs.map((tab) => { - const { key, content } = tab - return h(subview === key ? '.activeForm' : '.inactiveForm.pointer', { - onClick: () => { - this.setState({ subview: key }) - tabSelected(key) - }, - }, content) - })) - ) + return ( + h('.tab-bar', {}, [ + tabs.map((tab) => { + const { key, content } = tab + return h('div', { + className: classnames('tab-bar__tab pointer', { + 'tab-bar__tab--active': subview === key, + }), + onClick: () => { + this.setState({ subview: key }) + tabSelected(key) + }, + key, + }, content) + }), + h('div.tab-bar__tab.tab-bar__grow-tab'), + ]) + ) + } } +module.exports = TabBar -- cgit v1.2.3 From bef1405a50af219dc02108d7f437654690aec73e Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Sun, 22 Oct 2017 22:59:55 -0700 Subject: Change all "Buy" to "Deposit" --- ui/app/components/buy-button-subview.js | 2 +- ui/app/components/modals/buy-options-modal.js | 4 ++-- ui/app/components/tx-view.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/buy-button-subview.js b/ui/app/components/buy-button-subview.js index a36f41df5..d5958787b 100644 --- a/ui/app/components/buy-button-subview.js +++ b/ui/app/components/buy-button-subview.js @@ -76,7 +76,7 @@ BuyButtonSubview.prototype.headerSubview = function () { paddingTop: '4px', paddingBottom: '4px', }, - }, 'Buy Eth'), + }, 'Deposit Eth'), ]), // loading indication diff --git a/ui/app/components/modals/buy-options-modal.js b/ui/app/components/modals/buy-options-modal.js index f1a5aa9fd..33615c483 100644 --- a/ui/app/components/modals/buy-options-modal.js +++ b/ui/app/components/modals/buy-options-modal.js @@ -42,7 +42,7 @@ BuyOptions.prototype.render = function () { h('div.buy-modal-content-title', { style: {}, }, 'Transfers'), - h('div', {}, 'How would you like to buy Ether?'), + h('div', {}, 'How would you like to deposit Ether?'), ]), h('div.buy-modal-content-options.flex-column.flex-center', {}, [ @@ -54,7 +54,7 @@ BuyOptions.prototype.render = function () { }, }, [ h('div.buy-modal-content-option-title', {}, 'Coinbase'), - h('div.buy-modal-content-option-subtitle', {}, 'Buy with Fiat'), + h('div.buy-modal-content-option-subtitle', {}, 'Deposit with Fiat'), ]), // h('div.buy-modal-content-option', {}, [ diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 59f55d485..d903998c0 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -73,7 +73,7 @@ TxView.prototype.renderButtons = function () { onClick: () => showModal({ name: 'BUY', }), - }, 'BUY'), + }, 'DEPOSIT'), h('button.btn-clear', { style: { -- cgit v1.2.3 From b3dad510b7119c6bd89afb0059d95a6684402538 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 20 Oct 2017 23:27:59 -0230 Subject: Improve precision in send and confirm. --- ui/app/components/pending-tx/confirm-send-token.js | 2 +- ui/app/components/send/currency-display.js | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index a4c3d16e3..cc4c5f5f4 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -224,7 +224,7 @@ ConfirmSendToken.prototype.renderTotalPlusGas = function () { ]), h('div.confirm-screen-section-column', [ - h('div.confirm-screen-row-info', `${fiatAmount + fiatGas} ${currentCurrency}`), + h('div.confirm-screen-row-info', `${addCurrencies(fiatAmount, fiatGas)} ${currentCurrency}`), h('div.confirm-screen-row-detail', `${addCurrencies(tokenAmount, tokenGas || '0')} ${symbol}`), ]), ]) diff --git a/ui/app/components/send/currency-display.js b/ui/app/components/send/currency-display.js index 7180b94d3..799e9b56d 100644 --- a/ui/app/components/send/currency-display.js +++ b/ui/app/components/send/currency-display.js @@ -2,7 +2,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits const Identicon = require('../identicon') -const { conversionUtil } = require('../../conversion-util') +const { conversionUtil, multiplyCurrencies } = require('../../conversion-util') module.exports = CurrencyDisplay @@ -40,7 +40,9 @@ CurrencyDisplay.prototype.getAmount = function (value) { const { selectedToken } = this.props const { decimals } = selectedToken || {} const multiplier = Math.pow(10, Number(decimals || 0)) - const sendAmount = '0x' + Number(value * multiplier).toString(16) + + const sendAmount = multiplyCurrencies(value, multiplier, {toNumericBase: 'hex'}) + return selectedToken ? sendAmount : toHexWei(value) -- cgit v1.2.3 From b96ba5522993915cf809ba2f438c2c5a9c776e1f Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 20 Oct 2017 23:35:22 -0230 Subject: Clear send state on cancelling and signing. --- ui/app/components/send/send-v2-container.js | 1 + 1 file changed, 1 insertion(+) (limited to 'ui/app/components') diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js index c14865e9f..80b52a3ab 100644 --- a/ui/app/components/send/send-v2-container.js +++ b/ui/app/components/send/send-v2-container.js @@ -80,5 +80,6 @@ function mapDispatchToProps (dispatch) { updateSendMemo: newMemo => dispatch(actions.updateSendMemo(newMemo)), updateSendErrors: newError => dispatch(actions.updateSendErrors(newError)), goHome: () => dispatch(actions.goHome()), + clearSend: () => dispatch(actions.clearSend()) } } -- cgit v1.2.3 From 09d659614ed8a3d7627002eb77f0953b7f495f7e Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 23 Oct 2017 09:35:53 -0230 Subject: Cleaner implementation of currency-display input. --- ui/app/components/send/currency-display.js | 36 ++++++++++++------------------ 1 file changed, 14 insertions(+), 22 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send/currency-display.js b/ui/app/components/send/currency-display.js index 799e9b56d..5dba6a8dd 100644 --- a/ui/app/components/send/currency-display.js +++ b/ui/app/components/send/currency-display.js @@ -20,14 +20,6 @@ function isValidInput (text) { return re.test(text) } -function resetCaretIfPastEnd (value, event) { - const caretPosition = event.target.selectionStart - - if (caretPosition > value.length) { - event.target.setSelectionRange(value.length, value.length) - } -} - function toHexWei (value) { return conversionUtil(value, { fromNumericBase: 'dec', @@ -82,6 +74,8 @@ CurrencyDisplay.prototype.render = function () { conversionRate, }) + const inputSizeMultiplier = readOnly ? 1 : 1.2; + return h('div', { className, style: { @@ -95,35 +89,33 @@ CurrencyDisplay.prototype.render = function () { h('input', { className: primaryBalanceClassName, - value: `${value || initValueToRender} ${primaryCurrency}`, - placeholder: `${0} ${primaryCurrency}`, + value: `${value || initValueToRender}`, + placeholder: '0', + size: (value || initValueToRender).length * inputSizeMultiplier, readOnly, onChange: (event) => { - let newValue = event.target.value.split(' ')[0] + let newValue = event.target.value if (newValue === '') { - this.setState({ value: '0' }) + newValue = '0' } else if (newValue.match(/^0[1-9]$/)) { - this.setState({ value: newValue.match(/[1-9]/)[0] }) + newValue = newValue.match(/[1-9]/)[0] } - else if (newValue && !isValidInput(newValue)) { + + if (newValue && !isValidInput(newValue)) { event.preventDefault() } else { + validate(this.getAmount(newValue)) this.setState({ value: newValue }) } }, - onBlur: event => !readOnly && handleChange(this.getAmount(event.target.value.split(' ')[0])), - onKeyUp: event => { - if (!readOnly) { - validate(toHexWei(value || initValueToRender)) - resetCaretIfPastEnd(value || initValueToRender, event) - } - }, - onClick: event => !readOnly && resetCaretIfPastEnd(value || initValueToRender, event), + onBlur: event => !readOnly && handleChange(this.getAmount(event.target.value)), }), + h('span.currency-display__currency-symbol', primaryCurrency), + ]), ]), -- cgit v1.2.3 From e737a9565a6b78639b74511d026339c1b54bca1a Mon Sep 17 00:00:00 2001 From: Dan Date: Sun, 22 Oct 2017 17:44:03 -0230 Subject: Improve customize gas modal error handling --- ui/app/components/customize-gas-modal/index.js | 144 +++++++++++++++++---- ui/app/components/pending-tx/confirm-send-ether.js | 2 +- ui/app/components/send/send-constants.js | 20 ++- ui/app/components/send/send-utils.js | 39 ++++++ ui/app/components/send/send-v2-container.js | 8 +- 5 files changed, 177 insertions(+), 36 deletions(-) create mode 100644 ui/app/components/send/send-utils.js (limited to 'ui/app/components') diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 744891c47..710ee24c0 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -6,23 +6,46 @@ const actions = require('../../actions') const GasModalCard = require('./gas-modal-card') const { - MIN_GAS_PRICE, - MIN_GAS_LIMIT, + MIN_GAS_PRICE_DEC, + MIN_GAS_LIMIT_DEC, + MIN_GAS_PRICE_GWEI, } = require('../send/send-constants') -const { conversionUtil, multiplyCurrencies } = require('../../conversion-util') +const { + isBalanceSufficient, +} = require('../send/send-utils') + +const { + conversionUtil, + multiplyCurrencies, + conversionGreaterThan, +} = require('../../conversion-util') const { getGasPrice, getGasLimit, conversionRateSelector, + getSendAmount, + getSelectedToken, + getSendFrom, + getCurrentAccountWithSendEtherInfo, + getSelectedTokenToFiatRate, } = require('../../selectors') function mapStateToProps (state) { + const selectedToken = getSelectedToken(state) + const currentAccount = getSendFrom(state) || getCurrentAccountWithSendEtherInfo(state) + const conversionRate = conversionRateSelector(state) + return { gasPrice: getGasPrice(state), gasLimit: getGasLimit(state), - conversionRate: conversionRateSelector(state), + conversionRate, + amount: getSendAmount(state), + balance: currentAccount.balance, + primaryCurrency: selectedToken && selectedToken.symbol, + selectedToken, + amountConversionRate: selectedToken ? getSelectedTokenToFiatRate(state) : conversionRate, } } @@ -39,15 +62,26 @@ inherits(CustomizeGasModal, Component) function CustomizeGasModal (props) { Component.call(this) + const gasPrice = props.gasPrice || MIN_GAS_PRICE_DEC + const gasLimit = props.gasLimit || MIN_GAS_LIMIT_DEC + + const gasTotal = multiplyCurrencies(gasLimit, gasPrice, { + toNumericBase: 'hex', + multiplicandBase: 16, + multiplierBase: 16, + }) + this.state = { - gasPrice: props.gasPrice || MIN_GAS_PRICE, - gasLimit: props.gasLimit || MIN_GAS_LIMIT, + gasPrice, + gasLimit, + gasTotal, + error: null, } } module.exports = connect(mapStateToProps, mapDispatchToProps)(CustomizeGasModal) -CustomizeGasModal.prototype.save = function (gasPrice, gasLimit) { +CustomizeGasModal.prototype.save = function (gasPrice, gasLimit, gasTotal) { const { updateGasPrice, updateGasLimit, @@ -55,41 +89,101 @@ CustomizeGasModal.prototype.save = function (gasPrice, gasLimit) { updateGasTotal } = this.props - const newGasTotal = multiplyCurrencies(gasLimit, gasPrice, { - toNumericBase: 'hex', - multiplicandBase: 16, - multiplierBase: 16, - }) - updateGasPrice(gasPrice) updateGasLimit(gasLimit) - updateGasTotal(newGasTotal) + updateGasTotal(gasTotal) hideModal() } +CustomizeGasModal.prototype.validate = function ({ gasTotal, gasLimit }) { + const { + amount, + balance, + primaryCurrency, + selectedToken, + amountConversionRate, + conversionRate, + } = this.props + + let error = null + + const balanceIsSufficient = isBalanceSufficient({ + amount, + gasTotal, + balance, + primaryCurrency, + selectedToken, + amountConversionRate, + conversionRate, + }) + + if (!balanceIsSufficient) { + error = 'Insufficient balance for current gas total' + } + + const gasLimitTooLow = gasLimit && conversionGreaterThan( + { + value: MIN_GAS_LIMIT_DEC, + fromNumericBase: 'dec', + conversionRate, + }, + { + value: gasLimit, + fromNumericBase: 'hex', + }, + ) + + if (gasLimitTooLow) { + error = 'Gas limit must be at least 21000' + } + + this.setState({ error }) + return error +} + CustomizeGasModal.prototype.convertAndSetGasLimit = function (newGasLimit) { - const convertedGasLimit = conversionUtil(newGasLimit, { + const { gasPrice } = this.state + + const gasLimit = conversionUtil(newGasLimit, { fromNumericBase: 'dec', toNumericBase: 'hex', }) - this.setState({ gasLimit: convertedGasLimit }) + const gasTotal = multiplyCurrencies(gasLimit, gasPrice, { + toNumericBase: 'hex', + multiplicandBase: 16, + multiplierBase: 16, + }) + + this.validate({ gasTotal, gasLimit }) + + this.setState({ gasTotal, gasLimit }) } CustomizeGasModal.prototype.convertAndSetGasPrice = function (newGasPrice) { - const convertedGasPrice = conversionUtil(newGasPrice, { + const { gasLimit } = this.state + + const gasPrice = conversionUtil(newGasPrice, { fromNumericBase: 'dec', toNumericBase: 'hex', fromDenomination: 'GWEI', toDenomination: 'WEI', }) - this.setState({ gasPrice: convertedGasPrice }) + const gasTotal = multiplyCurrencies(gasLimit, gasPrice, { + toNumericBase: 'hex', + multiplicandBase: 16, + multiplierBase: 16, + }) + + this.validate({ gasTotal }) + + this.setState({ gasTotal, gasPrice }) } CustomizeGasModal.prototype.render = function () { const { hideModal, conversionRate } = this.props - const { gasPrice, gasLimit } = this.state + const { gasPrice, gasLimit, gasTotal, error } = this.state const convertedGasPrice = conversionUtil(gasPrice, { fromNumericBase: 'hex', @@ -120,7 +214,7 @@ CustomizeGasModal.prototype.render = function () { h(GasModalCard, { value: convertedGasPrice, - min: MIN_GAS_PRICE, + min: MIN_GAS_PRICE_GWEI, // max: 1000, step: 1, onChange: value => this.convertAndSetGasPrice(value), @@ -130,7 +224,7 @@ CustomizeGasModal.prototype.render = function () { h(GasModalCard, { value: convertedGasLimit, - min: MIN_GAS_LIMIT, + min: 1, // max: 100000, step: 1, onChange: value => this.convertAndSetGasLimit(value), @@ -141,6 +235,10 @@ CustomizeGasModal.prototype.render = function () { ]), h('div.send-v2__customize-gas__footer', {}, [ + + error && h('div.send-v2__customize-gas__error-message', [ + error, + ]), h('div.send-v2__customize-gas__revert', { onClick: () => console.log('Revert'), @@ -151,8 +249,8 @@ CustomizeGasModal.prototype.render = function () { onClick: this.props.hideModal, }, ['CANCEL']), - h('div.send-v2__customize-gas__save', { - onClick: () => this.save(gasPrice, gasLimit), + h(`div.send-v2__customize-gas__save${error ? '__error' : ''}`, { + onClick: () => !error && this.save(gasPrice, gasLimit, gasTotal), }, ['SAVE']), ]) diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 7162c7122..64da630f6 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -50,7 +50,7 @@ ConfirmSendEther.prototype.getAmount = function () { const { conversionRate, currentCurrency } = this.props const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} - console.log(`conversionRate, currentCurrency`, conversionRate, currentCurrency); + const FIAT = conversionUtil(txParams.value, { fromNumericBase: 'hex', toNumericBase: 'dec', diff --git a/ui/app/components/send/send-constants.js b/ui/app/components/send/send-constants.js index a819a8c28..8b56607cc 100644 --- a/ui/app/components/send/send-constants.js +++ b/ui/app/components/send/send-constants.js @@ -3,12 +3,19 @@ const { multiplyCurrencies } = require('../../conversion-util') const MIN_GAS_PRICE_GWEI = '1' const GWEI_FACTOR = '1e9' -const MIN_GAS_PRICE = multiplyCurrencies(GWEI_FACTOR, MIN_GAS_PRICE_GWEI, { +const MIN_GAS_PRICE_HEX = multiplyCurrencies(GWEI_FACTOR, MIN_GAS_PRICE_GWEI, { multiplicandBase: 16, multiplierBase: 16, + toNumericBase: 'hex', +}) +const MIN_GAS_PRICE_DEC = multiplyCurrencies(GWEI_FACTOR, MIN_GAS_PRICE_GWEI, { + multiplicandBase: 16, + multiplierBase: 16, + toNumericBase: 'dec', }) -const MIN_GAS_LIMIT = (21000).toString(16) -const MIN_GAS_TOTAL = multiplyCurrencies(MIN_GAS_LIMIT, MIN_GAS_PRICE, { +const MIN_GAS_LIMIT_HEX = (21000).toString(16) +const MIN_GAS_LIMIT_DEC = 21000 +const MIN_GAS_TOTAL = multiplyCurrencies(MIN_GAS_LIMIT_HEX, MIN_GAS_PRICE_HEX, { toNumericBase: 'hex', multiplicandBase: 16, multiplierBase: 16, @@ -16,8 +23,9 @@ const MIN_GAS_TOTAL = multiplyCurrencies(MIN_GAS_LIMIT, MIN_GAS_PRICE, { module.exports = { MIN_GAS_PRICE_GWEI, - GWEI_FACTOR, - MIN_GAS_PRICE, - MIN_GAS_LIMIT, + MIN_GAS_PRICE_HEX, + MIN_GAS_PRICE_DEC, + MIN_GAS_LIMIT_HEX, + MIN_GAS_LIMIT_DEC, MIN_GAS_TOTAL, } diff --git a/ui/app/components/send/send-utils.js b/ui/app/components/send/send-utils.js new file mode 100644 index 000000000..bf096d610 --- /dev/null +++ b/ui/app/components/send/send-utils.js @@ -0,0 +1,39 @@ +const { addCurrencies, conversionGreaterThan } = require('../../conversion-util') + +function isBalanceSufficient({ + amount, + gasTotal, + balance, + primaryCurrency, + selectedToken, + amountConversionRate, + conversionRate, +}) { + const totalAmount = addCurrencies(amount, gasTotal, { + aBase: 16, + bBase: 16, + toNumericBase: 'hex', + }) + + const balanceIsSufficient = conversionGreaterThan( + { + value: balance, + fromNumericBase: 'hex', + fromCurrency: primaryCurrency, + conversionRate, + }, + { + value: totalAmount, + fromNumericBase: 'hex', + conversionRate: amountConversionRate, + fromCurrency: selectedToken || primaryCurrency, + conversionRate: amountConversionRate, + }, + ) + + return balanceIsSufficient +} + +module.exports = { + isBalanceSufficient, +} \ No newline at end of file diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js index 80b52a3ab..fb2634de2 100644 --- a/ui/app/components/send/send-v2-container.js +++ b/ui/app/components/send/send-v2-container.js @@ -17,6 +17,7 @@ const { getAddressBook, getSendFrom, getCurrentCurrency, + getSelectedTokenToFiatRate, } = require('../../selectors') module.exports = connect(mapStateToProps, mapDispatchToProps)(SendEther) @@ -26,7 +27,6 @@ function mapStateToProps (state) { const selectedAddress = getSelectedAddress(state) const selectedToken = getSelectedToken(state) const tokenExchangeRates = state.metamask.tokenExchangeRates - const selectedTokenExchangeRate = getSelectedTokenExchangeRate(state) const conversionRate = conversionRateSelector(state) let data; @@ -40,11 +40,7 @@ function mapStateToProps (state) { primaryCurrency = selectedToken.symbol - tokenToFiatRate = multiplyCurrencies( - conversionRate, - selectedTokenExchangeRate, - { toNumericBase: 'dec' } - ) + tokenToFiatRate = getSelectedTokenToFiatRate(state) } return { -- cgit v1.2.3 From 6d3f261b2f923782279be5e2ce05e8d6cc558a9e Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Mon, 23 Oct 2017 23:11:47 -0700 Subject: Change LOOSE label to IMPORTED --- ui/app/components/account-menu/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index 85bd21076..32e7bc466 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -148,6 +148,6 @@ AccountMenu.prototype.indicateIfLoose = function (keyring) { try { // Sometimes keyrings aren't loaded yet: const type = keyring.type const isLoose = type !== 'HD Key Tree' - return isLoose ? h('.keyring-label', 'LOOSE') : null + return isLoose ? h('.keyring-label', 'IMPORTED') : null } catch (e) { return } } -- cgit v1.2.3 From a63373401b9983b991d4b2a0e28eec8d66c18e78 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Mon, 23 Oct 2017 23:59:21 -0700 Subject: New Sidebar uplift --- ui/app/components/account-menu/index.js | 1 - ui/app/components/wallet-view.js | 92 +++++++++++++-------------------- 2 files changed, 36 insertions(+), 57 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index 32e7bc466..45e39e8ba 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -103,7 +103,6 @@ AccountMenu.prototype.renderAccounts = function () { showAccountDetail, } = this.props - console.log({ accounts }) return Object.keys(identities).map((key, index) => { const identity = identities[key] const isSelected = identity.address === selected diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index a870a24e3..06123fd0e 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -3,7 +3,8 @@ const connect = require('react-redux').connect const h = require('react-hyperscript') const inherits = require('util').inherits const Identicon = require('./identicon') -const AccountDropdowns = require('./dropdowns/index.js').AccountDropdowns +// const AccountDropdowns = require('./dropdowns/index.js').AccountDropdowns +const copyToClipboard = require('copy-to-clipboard') const actions = require('../actions') const BalanceComponent = require('./balance-component') const TokenList = require('./token-list') @@ -19,6 +20,7 @@ function mapStateToProps (state) { identities: state.metamask.identities, accounts: state.metamask.accounts, tokens: state.metamask.tokens, + keyrings: state.metamask.keyrings, selectedAddress: selectors.getSelectedAddress(state), selectedIdentity: selectors.getSelectedIdentity(state), selectedAccount: selectors.getSelectedAccount(state), @@ -28,9 +30,12 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { - showSendPage: () => { dispatch(actions.showSendPage()) }, - hideSidebar: () => { dispatch(actions.hideSidebar()) }, + showSendPage: () => dispatch(actions.showSendPage()), + hideSidebar: () => dispatch(actions.hideSidebar()), unsetSelectedToken: () => dispatch(actions.setSelectedToken()), + showAccountDetailModal: () => { + dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' })) + }, } } @@ -47,7 +52,7 @@ WalletView.prototype.renderWalletBalance = function () { hideSidebar, sidebarOpen, } = this.props - console.log({ selectedAccount }) + const selectedClass = selectedTokenAddress ? '' : 'wallet-balance-wrapper--active' @@ -73,13 +78,24 @@ WalletView.prototype.renderWalletBalance = function () { WalletView.prototype.render = function () { const { - network, responsiveDisplayClassname, identities, - selectedAddress, accounts, + responsiveDisplayClassname, + selectedAddress, selectedIdentity, + keyrings, + showAccountDetailModal, + hideSidebar, } = this.props // temporary logs + fake extra wallets // console.log('walletview, selectedAccount:', selectedAccount) + const keyring = keyrings.find((kr) => { + return kr.accounts.includes(selectedAddress) || + kr.accounts.includes(selectedIdentity.address) + }) + + const type = keyring.type + const isLoose = type !== 'HD Key Tree' + return h('div.wallet-view.flex-column' + (responsiveDisplayClassname || ''), { style: {}, }, [ @@ -88,57 +104,15 @@ WalletView.prototype.render = function () { h('div.flex-column.wallet-view-account-details', { style: {}, }, [ + h('div.wallet-view__sidebar-close', { + onClick: hideSidebar, + }), - h('div.flex-row.account-options-menu', { - style: { - position: 'relative', - }, - }, [ - - h(AccountDropdowns, { - selected: selectedAddress, - network, - identities, - useCssTransition: true, - enableAccountOptions: true, - dropdownWrapperStyle: { - padding: '1px 15px', - marginLeft: '-25px', - position: 'absolute', - width: '122%', // TODO, refactor all of this component out into media queries - }, - menuItemStyles: { - padding: '0px 0px', - margin: '22px 0px', - }, - }, []), - - ]), + h('div.wallet-view__keyring-label', isLoose ? 'IMPORTED' : ''), h('div.flex-column.flex-center', { + style: { margin: '0 auto' }, }, [ - h('div', { - style: { - position: 'relative', - }, - }, [ - h(AccountDropdowns, { - accounts, - style: { - position: 'absolute', - left: 'calc(50% + 28px + 5.5px)', - top: '14px', - }, - innerStyle: { - padding: '10px 16px', - }, - useCssTransition: true, - selected: selectedAddress, - network, - identities, - }, []), - ]), - h(Identicon, { diameter: 54, address: selectedAddress, @@ -149,14 +123,20 @@ WalletView.prototype.render = function () { }, [ selectedIdentity.name, ]), - ]), ]), + h('button.wallet-view__details-button', { onClick: showAccountDetailModal }, 'DETAILS'), + + h('div.wallet-view__address', { onClick: () => copyToClipboard(selectedAddress) }, [ + `${selectedAddress.slice(0, 4)}...${selectedAddress.slice(-4)}`, + h('i.fa.fa-clipboard', { style: { marginLeft: '8px' } }), + ]), + // 'Wallet' - Title // Not visible on mobile - h('div.flex-column.wallet-view-title-wrapper', {}, [ - h('span.wallet-view-title', {}, [ + h('div.flex-column.wallet-view-title-wrapper', [ + h('span.wallet-view-title', [ 'Wallet', ]), ]), -- cgit v1.2.3 From 4401800a42eccbd77f11b332e1052431328401bb Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 24 Oct 2017 00:13:49 -0700 Subject: Account menu white check mark --- ui/app/components/account-menu/index.js | 6 +++--- ui/app/components/tx-view.js | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index 45e39e8ba..da2c86233 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -98,14 +98,14 @@ AccountMenu.prototype.renderAccounts = function () { const { identities, accounts, - selected, + selectedAddress, keyrings, showAccountDetail, } = this.props return Object.keys(identities).map((key, index) => { const identity = identities[key] - const isSelected = identity.address === selected + const isSelected = identity.address === selectedAddress const balanceValue = accounts[key] ? accounts[key].balance : '' const formattedBalance = balanceValue ? formatBalance(balanceValue, 6) : '...' @@ -121,7 +121,7 @@ AccountMenu.prototype.renderAccounts = function () { { onClick: () => showAccountDetail(identity.address) }, [ h('div.account-menu__check-mark', [ - isSelected ? h('i.fa.fa-check') : null, + isSelected ? h('div.account-menu__check-mark-icon') : null, ]), h( diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index d903998c0..ebef22680 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -109,14 +109,15 @@ TxView.prototype.render = function () { margin: '1em 0.9em', alignItems: 'center', }, - onClick: () => { - this.props.sidebarOpen ? this.props.hideSidebar() : this.props.showSidebar() - }, }, [ h('div.fa.fa-bars', { style: { fontSize: '1.3em', + cursor: 'pointer', + }, + onClick: () => { + this.props.sidebarOpen ? this.props.hideSidebar() : this.props.showSidebar() }, }, []), -- cgit v1.2.3 From 3891cf1af6130126781b12aaee410c0831fa43e9 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 24 Oct 2017 00:16:19 -0700 Subject: Fix clickable area on logout --- ui/app/components/account-menu/index.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index da2c86233..e0f38ae78 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -63,10 +63,11 @@ AccountMenu.prototype.render = function () { h(CloseArea, { onClick: toggleAccountMenu }), h(Item, { className: 'account-menu__header', - onClick: lockMetamask, }, [ 'My Accounts', - h('button.account-menu__logout-button', 'Log out'), + h('button.account-menu__logout-button', { + onClick: lockMetamask, + }, 'Log out'), ]), h(Divider), h('div.account-menu__accounts', this.renderAccounts()), -- cgit v1.2.3 From 2871beebe61418ce148069c932301d89e85923fa Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 24 Oct 2017 00:29:20 -0700 Subject: Add "Add Token" button to side bar --- ui/app/components/wallet-view.js | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 06123fd0e..580ac54aa 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -36,6 +36,7 @@ function mapDispatchToProps (dispatch) { showAccountDetailModal: () => { dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' })) }, + showAddTokenPage: () => dispatch(actions.showAddTokenPage()), } } @@ -84,6 +85,7 @@ WalletView.prototype.render = function () { keyrings, showAccountDetailModal, hideSidebar, + showAddTokenPage, } = this.props // temporary logs + fake extra wallets // console.log('walletview, selectedAccount:', selectedAccount) @@ -145,6 +147,9 @@ WalletView.prototype.render = function () { h(TokenList), + h('button.wallet-view__add-token-button', { + onClick: showAddTokenPage, + }, 'Add Token'), ]) } -- cgit v1.2.3 From 4336794355e819f798343e0de3cea6933c8121ee Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 24 Oct 2017 00:43:12 -0700 Subject: Fix styling in private key modal --- ui/app/components/modals/export-private-key-modal.js | 1 - 1 file changed, 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/export-private-key-modal.js b/ui/app/components/modals/export-private-key-modal.js index 302596eda..80d7779ef 100644 --- a/ui/app/components/modals/export-private-key-modal.js +++ b/ui/app/components/modals/export-private-key-modal.js @@ -66,7 +66,6 @@ ExportPrivateKeyModal.prototype.renderPasswordInput = function (privateKey) { }) : h('input.private-key-password-input', { type: 'password', - placeholder: 'Type password', onChange: event => this.setState({ password: event.target.value }), }) } -- cgit v1.2.3 From 966e4cfd1189f7c115cfc552796c1353060d2125 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 24 Oct 2017 00:54:49 -0700 Subject: Change clickable area for account detail; change network dot size --- ui/app/components/wallet-view.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 580ac54aa..215103396 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -112,8 +112,9 @@ WalletView.prototype.render = function () { h('div.wallet-view__keyring-label', isLoose ? 'IMPORTED' : ''), - h('div.flex-column.flex-center', { + h('div.flex-column.flex-center.wallet-view__name-container', { style: { margin: '0 auto' }, + onClick: showAccountDetailModal, }, [ h(Identicon, { diameter: 54, @@ -125,10 +126,11 @@ WalletView.prototype.render = function () { }, [ selectedIdentity.name, ]), + + h('button.wallet-view__details-button', 'DETAILS'), ]), ]), - h('button.wallet-view__details-button', { onClick: showAccountDetailModal }, 'DETAILS'), h('div.wallet-view__address', { onClick: () => copyToClipboard(selectedAddress) }, [ `${selectedAddress.slice(0, 4)}...${selectedAddress.slice(-4)}`, -- cgit v1.2.3 From 6daa8343234cf2a0bc32ed434ee3acae6100fd38 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 24 Oct 2017 01:07:51 -0700 Subject: Disable network dropdown on conf tx screen --- ui/app/components/network.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/network.js b/ui/app/components/network.js index b24505750..229d02e36 100644 --- a/ui/app/components/network.js +++ b/ui/app/components/network.js @@ -64,13 +64,18 @@ Network.prototype.render = function () { return ( h('div.network-component.pointer', { className: classnames('network-component pointer', { + 'network-component--disabled': this.props.disabled, 'ethereum-network': providerName === 'mainnet', 'ropsten-test-network': providerName === 'ropsten' || parseInt(networkNumber) === 3, 'kovan-test-network': providerName === 'kovan', 'rinkeby-test-network': providerName === 'rinkeby', }), title: hoverText, - onClick: (event) => this.props.onClick(event), + onClick: (event) => { + if (!this.props.disabled) { + this.props.onClick(event) + } + }, }, [ (function () { switch (iconName) { -- cgit v1.2.3 From 07c4c92db64ffaaefbb9eb661d24bbb4c8c5ddb6 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 23 Oct 2017 13:54:47 -0230 Subject: Style dropdown of to-autocomplete. --- ui/app/components/send/account-list-item.js | 8 +- ui/app/components/send/to-autocomplete.js | 126 ++++++++++++++++++++++------ 2 files changed, 105 insertions(+), 29 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send/account-list-item.js b/ui/app/components/send/account-list-item.js index ba7eec940..cc514cbd4 100644 --- a/ui/app/components/send/account-list-item.js +++ b/ui/app/components/send/account-list-item.js @@ -27,6 +27,8 @@ AccountListItem.prototype.render = function () { icon = null, conversionRate, currentCurrency, + displayBalance = true, + displayAddress = false, } = this.props const { name, address, balance } = account || {} @@ -46,13 +48,15 @@ AccountListItem.prototype.render = function () { }, ), - h('div.account-list-item__account-name', {}, name), + h('div.account-list-item__account-name', {}, name || address), icon && h('div.account-list-item__icon', [icon]), ]), - h(CurrencyDisplay, { + displayAddress && name && h('div.account-list-item__account-address', address), + + displayBalance && h(CurrencyDisplay, { primaryCurrency: 'ETH', convertedCurrency: currentCurrency, value: balance, diff --git a/ui/app/components/send/to-autocomplete.js b/ui/app/components/send/to-autocomplete.js index 686a7a23e..081b85ab7 100644 --- a/ui/app/components/send/to-autocomplete.js +++ b/ui/app/components/send/to-autocomplete.js @@ -2,54 +2,126 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits const Identicon = require('../identicon') +const AccountListItem = require('./account-list-item') module.exports = ToAutoComplete inherits(ToAutoComplete, Component) function ToAutoComplete () { Component.call(this) + + this.state = { accountsToRender: [] } +} + +ToAutoComplete.prototype.getListItemIcon = function (listItemAddress, toAddress) { + const listItemIcon = h(`i.fa.fa-check.fa-lg`, { style: { color: '#02c9b1' } }) + + return toAddress && listItemAddress === toAddress + ? listItemIcon + : null +} + +ToAutoComplete.prototype.renderDropdown = function () { + const { + accounts, + closeDropdown, + onChange, + to, + } = this.props + const { accountsToRender } = this.state + + return accountsToRender.length && h('div', {}, [ + + h('div.send-v2__from-dropdown__close-area', { + onClick: closeDropdown, + }), + + h('div.send-v2__from-dropdown__list', {}, [ + + ...accountsToRender.map(account => h(AccountListItem, { + account, + handleClick: () => { + onChange(account.address) + closeDropdown() + }, + icon: this.getListItemIcon(account.address, to), + displayBalance: false, + displayAddress: true, + })) + + ]), + + ]) +} + +ToAutoComplete.prototype.handleInputEvent = function (event = {}, cb) { + const { + to, + accounts, + closeDropdown, + openDropdown, + } = this.props + + const matchingAccounts = accounts.filter(({ address }) => address.match(to)) + + if (!to) { + this.setState({ accountsToRender: accounts }) + openDropdown() + } + else if (matchingAccounts.length === 1 && matchingAccounts[0].address === to) { + this.setState({ accountsToRender: [] }) + event.target && event.target.select() + closeDropdown() + } + else if (matchingAccounts.length) { + this.setState({ accountsToRender: matchingAccounts }) + openDropdown() + } + else { + this.setState({ accountsToRender: [] }) + event.target && event.target.select() + closeDropdown() + } + cb && cb(event.target.value) +} + +ToAutoComplete.prototype.componentDidUpdate = function (nextProps, nextState) { + if (this.props.to !== nextProps.to) { + this.handleInputEvent() + } } ToAutoComplete.prototype.render = function () { - const { to, accounts, onChange, inError } = this.props + const { + to, + accounts, + openDropdown, + closeDropdown, + dropdownOpen, + onChange, + inError, + } = this.props - return h('div.send-v2__to-autocomplete', [ + return h('div.to-autocomplete', {}, [ h('input.send-v2__to-autocomplete__input', { - name: 'address', - list: 'addresses', placeholder: 'Recipient Address', className: inError ? `send-v2__error-border` : '', value: to, - onChange, - onFocus: event => { - to && event.target.select() - }, + onChange: event => onChange(event.target.value), + onFocus: event => this.handleInputEvent(event), style: { borderColor: inError ? 'red' : null, } }), - h('datalist#addresses', [ - // Corresponds to the addresses owned. - ...Object.entries(accounts).map(([key, { address, name }]) => { - return h('option', { - value: address, - label: name, - key: address, - }) - }), - // Corresponds to previously sent-to addresses. - // ...addressBook.map(({ address, name }) => { - // return h('option', { - // value: address, - // label: name, - // key: address, - // }) - // }), - ]), + !to && h(`i.fa.fa-caret-down.fa-lg.send-v2__to-autocomplete__down-caret`, { + style: { color: '#dedede' }, + onClick: () => this.handleInputEvent(), + }), + + dropdownOpen && this.renderDropdown(), ]) - } -- cgit v1.2.3 From ef2b0d848582788c6cf69a11e17a12358bb2aa7b Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 24 Oct 2017 12:56:42 -0230 Subject: Simply logic for rendering matching accounts in to-autocomplete dropdown. --- ui/app/components/send/to-autocomplete.js | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send/to-autocomplete.js b/ui/app/components/send/to-autocomplete.js index 081b85ab7..ab490155b 100644 --- a/ui/app/components/send/to-autocomplete.js +++ b/ui/app/components/send/to-autocomplete.js @@ -62,26 +62,18 @@ ToAutoComplete.prototype.handleInputEvent = function (event = {}, cb) { openDropdown, } = this.props - const matchingAccounts = accounts.filter(({ address }) => address.match(to)) + const matchingAccounts = accounts.filter(({ address }) => address.match(to || '')) + const matches = matchingAccounts.length - if (!to) { - this.setState({ accountsToRender: accounts }) - openDropdown() - } - else if (matchingAccounts.length === 1 && matchingAccounts[0].address === to) { + if (!matches || matchingAccounts[0].address === to) { this.setState({ accountsToRender: [] }) event.target && event.target.select() closeDropdown() } - else if (matchingAccounts.length) { + else { this.setState({ accountsToRender: matchingAccounts }) openDropdown() } - else { - this.setState({ accountsToRender: [] }) - event.target && event.target.select() - closeDropdown() - } cb && cb(event.target.value) } -- cgit v1.2.3 From 3f1ae92bb7d4ca4629995f32dc03f37e6460a864 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 24 Oct 2017 16:55:02 -0700 Subject: Hide sidebar on add token --- ui/app/components/wallet-view.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 215103396..9c11ca4a5 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -150,7 +150,10 @@ WalletView.prototype.render = function () { h(TokenList), h('button.wallet-view__add-token-button', { - onClick: showAddTokenPage, + onClick: () => { + showAddTokenPage() + hideSidebar() + }, }, 'Add Token'), ]) } -- cgit v1.2.3 From 630ab79cc313fa280e6a3d6a2655dafacb6b9659 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 24 Oct 2017 20:04:29 -0700 Subject: Styling and UX changes on sidebar --- ui/app/components/wallet-view.js | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 9c11ca4a5..3cb7a8b76 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -43,6 +43,9 @@ function mapDispatchToProps (dispatch) { inherits(WalletView, Component) function WalletView () { Component.call(this) + this.state = { + hasCopied: false, + } } WalletView.prototype.renderWalletBalance = function () { @@ -132,19 +135,18 @@ WalletView.prototype.render = function () { ]), - h('div.wallet-view__address', { onClick: () => copyToClipboard(selectedAddress) }, [ - `${selectedAddress.slice(0, 4)}...${selectedAddress.slice(-4)}`, + h('div.wallet-view__address', { + onClick: () => { + copyToClipboard(selectedAddress) + this.setState({ hasCopied: true }) + setTimeout(() => this.setState({ hasCopied: false }), 3000) + }, + }, [ + this.state.hasCopied && 'Copied to Clipboard', + !this.state.hasCopied && `${selectedAddress.slice(0, 4)}...${selectedAddress.slice(-4)}`, h('i.fa.fa-clipboard', { style: { marginLeft: '8px' } }), ]), - // 'Wallet' - Title - // Not visible on mobile - h('div.flex-column.wallet-view-title-wrapper', [ - h('span.wallet-view-title', [ - 'Wallet', - ]), - ]), - this.renderWalletBalance(), h(TokenList), -- cgit v1.2.3 From 62314318948067cddd97fe1092f9949a2b80bf7f Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 24 Oct 2017 22:48:20 -0700 Subject: Change download to show in Export Private Key Modal --- ui/app/components/modals/export-private-key-modal.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/export-private-key-modal.js b/ui/app/components/modals/export-private-key-modal.js index 80d7779ef..2d8470634 100644 --- a/ui/app/components/modals/export-private-key-modal.js +++ b/ui/app/components/modals/export-private-key-modal.js @@ -83,7 +83,7 @@ ExportPrivateKeyModal.prototype.renderButtons = function (privateKey, password, (privateKey ? this.renderButton('btn-clear', () => hideModal(), 'Done') - : this.renderButton('btn-clear', () => this.exportAccountAndGetPrivateKey(this.state.password, address), 'Download') + : this.renderButton('btn-clear', () => this.exportAccountAndGetPrivateKey(this.state.password, address), 'Show') ), ]) @@ -117,7 +117,7 @@ ExportPrivateKeyModal.prototype.render = function () { h('div.account-modal-divider'), - h('span.modal-body-title', 'Download Private Keys'), + h('span.modal-body-title', 'Show Private Keys'), h('div.private-key-password', {}, [ this.renderPasswordLabel(privateKey), -- cgit v1.2.3 From 7c10cda8a4f8423a95f4c64024b07572d76dc266 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Wed, 25 Oct 2017 00:24:26 -0700 Subject: Fix alignment on right arrow of confirm tx screens --- ui/app/components/pending-tx/confirm-send-ether.js | 2 +- ui/app/components/pending-tx/confirm-send-token.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 64da630f6..2f178f179 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -194,7 +194,7 @@ ConfirmSendEther.prototype.render = function () { this.inputs = [] return ( - h('div.confirm-screen-container', { + h('div.confirm-screen-container.confirm-send-ether', { style: { minWidth: '355px' }, }, [ // Main Send token Card diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index cc4c5f5f4..abb7a0770 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -263,7 +263,7 @@ ConfirmSendToken.prototype.render = function () { this.inputs = [] return ( - h('div.confirm-screen-container', { + h('div.confirm-screen-container.confirm-send-token', { style: { minWidth: '355px' }, }, [ // Main Send token Card -- cgit v1.2.3 From 0d522139ba7c5372e0ef4219a69a4b8e8f83706a Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Wed, 25 Oct 2017 01:08:14 -0700 Subject: Fix gas input styling on mobile view --- ui/app/components/customize-gas-modal/index.js | 7 ++++--- ui/app/components/modals/modal.js | 7 +++---- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 710ee24c0..e5bfcfc63 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -198,7 +198,7 @@ CustomizeGasModal.prototype.render = function () { }) return h('div.send-v2__customize-gas', {}, [ - h('div', { + h('div.send-v2__customize-gas__content', { }, [ h('div.send-v2__customize-gas__header', {}, [ @@ -241,8 +241,9 @@ CustomizeGasModal.prototype.render = function () { ]), h('div.send-v2__customize-gas__revert', { - onClick: () => console.log('Revert'), - }, ['Revert']), + // onClick: () => console.log('Revert'), + }, ['']), + // }, ['Revert']), h('div.send-v2__customize-gas__buttons', [ h('div.send-v2__customize-gas__cancel', { diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 88deb2bb0..e15dd6c1b 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -162,10 +162,9 @@ const MODALS = { h(CustomizeGasModal, {}, []), ], mobileModalStyle: { - width: '355px', - height: '598px', - // top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh', - top: '5%', + width: '100vw', + height: '100vh', + top: '0', transform: 'none', left: '0', right: '0', -- cgit v1.2.3 From 2b72b70647caaa81c0077e224a7dc8b9f823c872 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Wed, 25 Oct 2017 01:17:17 -0700 Subject: Add GWEI to gas price unit --- ui/app/components/customize-gas-modal/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index e5bfcfc63..598247497 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -218,7 +218,7 @@ CustomizeGasModal.prototype.render = function () { // max: 1000, step: 1, onChange: value => this.convertAndSetGasPrice(value), - title: 'Gas Price', + title: 'Gas Price (GWEI)', copy: 'We calculate the suggested gas prices based on network success rates.', }), -- cgit v1.2.3 From 3d8182f5d54730d3908a210c3deb71b49dd08100 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Wed, 25 Oct 2017 09:26:05 -0700 Subject: Add Info section --- ui/app/components/account-menu/index.js | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'ui/app/components') diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index e0f38ae78..38c7bcb2d 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -46,6 +46,10 @@ function mapDispatchToProps (dispatch) { dispatch(actions.showImportPage()) dispatch(actions.toggleAccountMenu()) }, + showInfoPage: () => { + dispatch(actions.showInfoPage()) + dispatch(actions.toggleAccountMenu()) + }, } } @@ -57,6 +61,7 @@ AccountMenu.prototype.render = function () { showImportPage, lockMetamask, showConfigPage, + showInfoPage, } = this.props return h(Menu, { className: 'account-menu', isShowing: isAccountMenuOpen }, [ @@ -84,6 +89,7 @@ AccountMenu.prototype.render = function () { }), h(Divider), h(Item, { + onClick: showInfoPage, icon: h('img', { src: 'images/mm-info-icon.svg' }), text: 'Info & Help', }), -- cgit v1.2.3 From f89b76653434ff801779e10b9f8a9a546997cb9b Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 25 Oct 2017 14:10:03 -0230 Subject: Adds revert feature to customize gas modal. --- ui/app/components/customize-gas-modal/index.js | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 598247497..722ed2b23 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -58,10 +58,7 @@ function mapDispatchToProps (dispatch) { } } -inherits(CustomizeGasModal, Component) -function CustomizeGasModal (props) { - Component.call(this) - +function getOriginalState(props) { const gasPrice = props.gasPrice || MIN_GAS_PRICE_DEC const gasLimit = props.gasLimit || MIN_GAS_LIMIT_DEC @@ -71,7 +68,7 @@ function CustomizeGasModal (props) { multiplierBase: 16, }) - this.state = { + return { gasPrice, gasLimit, gasTotal, @@ -79,6 +76,13 @@ function CustomizeGasModal (props) { } } +inherits(CustomizeGasModal, Component) +function CustomizeGasModal (props) { + Component.call(this) + + this.state = getOriginalState(props) +} + module.exports = connect(mapStateToProps, mapDispatchToProps)(CustomizeGasModal) CustomizeGasModal.prototype.save = function (gasPrice, gasLimit, gasTotal) { @@ -95,6 +99,10 @@ CustomizeGasModal.prototype.save = function (gasPrice, gasLimit, gasTotal) { hideModal() } +CustomizeGasModal.prototype.revert = function () { + this.setState(getOriginalState(this.props)) +} + CustomizeGasModal.prototype.validate = function ({ gasTotal, gasLimit }) { const { amount, @@ -241,9 +249,8 @@ CustomizeGasModal.prototype.render = function () { ]), h('div.send-v2__customize-gas__revert', { - // onClick: () => console.log('Revert'), - }, ['']), - // }, ['Revert']), + onClick: () => this.revert(), + }, ['Revert']), h('div.send-v2__customize-gas__buttons', [ h('div.send-v2__customize-gas__cancel', { -- cgit v1.2.3 From 78836b0ead0e1b2307a48868c109a5412effc78b Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 25 Oct 2017 13:31:58 -0230 Subject: Signature Request --- .../components/dropdowns/account-dropdown-mini.js | 78 +++++++ ui/app/components/pending-personal-msg.js | 47 ---- ui/app/components/signature-request.js | 245 +++++++++++++++++++++ 3 files changed, 323 insertions(+), 47 deletions(-) create mode 100644 ui/app/components/dropdowns/account-dropdown-mini.js delete mode 100644 ui/app/components/pending-personal-msg.js create mode 100644 ui/app/components/signature-request.js (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/account-dropdown-mini.js b/ui/app/components/dropdowns/account-dropdown-mini.js new file mode 100644 index 000000000..96057d2b4 --- /dev/null +++ b/ui/app/components/dropdowns/account-dropdown-mini.js @@ -0,0 +1,78 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const Identicon = require('../identicon') +const AccountListItem = require('../send/account-list-item') + +module.exports = AccountDropdownMini + +inherits(AccountDropdownMini, Component) +function AccountDropdownMini () { + Component.call(this) +} + +AccountDropdownMini.prototype.getListItemIcon = function (currentAccount, selectedAccount) { + const listItemIcon = h(`i.fa.fa-check.fa-lg`, { style: { color: '#02c9b1' } }) + + return currentAccount.address === selectedAccount.address + ? listItemIcon + : null +} + +AccountDropdownMini.prototype.renderDropdown = function () { + const { + accounts, + selectedAccount, + closeDropdown, + onSelect, + } = this.props + + return h('div', {}, [ + + h('div.account-dropdown-mini__close-area', { + onClick: closeDropdown, + }), + + h('div.account-dropdown-mini__list', {}, [ + + ...accounts.map(account => h(AccountListItem, { + account, + displayBalance: false, + displayAddress: false, + handleClick: () => { + onSelect(account) + closeDropdown() + }, + icon: this.getListItemIcon(account, selectedAccount), + })) + + ]), + + ]) +} + +AccountDropdownMini.prototype.render = function () { + const { + accounts, + selectedAccount, + openDropdown, + closeDropdown, + dropdownOpen, + } = this.props + + return h('div.account-dropdown-mini', {}, [ + + h(AccountListItem, { + account: selectedAccount, + handleClick: openDropdown, + displayBalance: false, + displayAddress: false, + icon: h(`i.fa.fa-caret-down.fa-lg`, { style: { color: '#dedede' } }) + }), + + dropdownOpen && this.renderDropdown(), + + ]) + +} + diff --git a/ui/app/components/pending-personal-msg.js b/ui/app/components/pending-personal-msg.js deleted file mode 100644 index 4542adb28..000000000 --- a/ui/app/components/pending-personal-msg.js +++ /dev/null @@ -1,47 +0,0 @@ -const Component = require('react').Component -const h = require('react-hyperscript') -const inherits = require('util').inherits -const PendingTxDetails = require('./pending-personal-msg-details') - -module.exports = PendingMsg - -inherits(PendingMsg, Component) -function PendingMsg () { - Component.call(this) -} - -PendingMsg.prototype.render = function () { - var state = this.props - var msgData = state.txData - - return ( - - h('div', { - key: msgData.id, - }, [ - - // header - h('h3', { - style: { - fontWeight: 'bold', - textAlign: 'center', - }, - }, 'Sign Message'), - - // message details - h(PendingTxDetails, state), - - // sign + cancel - h('.flex-row.flex-space-around', [ - h('button', { - onClick: state.cancelPersonalMessage, - }, 'Cancel'), - h('button', { - onClick: state.signPersonalMessage, - }, 'Sign'), - ]), - ]) - - ) -} - diff --git a/ui/app/components/signature-request.js b/ui/app/components/signature-request.js new file mode 100644 index 000000000..4df4f9193 --- /dev/null +++ b/ui/app/components/signature-request.js @@ -0,0 +1,245 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const Identicon = require('./identicon') +const connect = require('react-redux').connect +const ethUtil = require('ethereumjs-util') +const PendingTxDetails = require('./pending-personal-msg-details') +const AccountDropdownMini = require('./dropdowns/account-dropdown-mini') +const BinaryRenderer = require('./binary-renderer') + +const actions = require('../actions') +const { conversionUtil } = require('../conversion-util') + +const { + getSelectedAccount, + getCurrentAccountWithSendEtherInfo, + getSelectedAddress, + accountsWithSendEtherInfoSelector, + conversionRateSelector, +} = require('../selectors.js') + +function mapStateToProps (state) { + return { + balance: getSelectedAccount(state).balance, + selectedAccount: getCurrentAccountWithSendEtherInfo(state), + selectedAddress: getSelectedAddress(state), + requester: null, + requesterAddress: null, + accounts: accountsWithSendEtherInfoSelector(state), + conversionRate: conversionRateSelector(state) + } +} + +function mapDispatchToProps (dispatch) { + return { + goHome: () => dispatch(actions.goHome()) + } +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)(SignatureRequest) + +inherits(SignatureRequest, Component) +function SignatureRequest (props) { + Component.call(this) + + this.state = { + selectedAccount: props.selectedAccount, + accountDropdownOpen: false, + } +} + +SignatureRequest.prototype.renderHeader = function () { + return h('div.request-signature__header', [ + + h('div.request-signature__header-background'), + + h('div.request-signature__header__text', 'Signature Request'), + + h('div.request-signature__header__tip-container', [ + h('div.request-signature__header__tip'), + ]), + + ]) +} + +SignatureRequest.prototype.renderAccountDropdown = function () { + const { + selectedAccount, + accountDropdownOpen, + } = this.state + + const { + accounts, + } = this.props + + return h('div.request-signature__account', [ + + h('div.request-signature__account-text', ['Account:']), + + h(AccountDropdownMini, { + selectedAccount, + accounts, + onSelect: selectedAccount => this.setState({ selectedAccount }), + dropdownOpen: accountDropdownOpen, + openDropdown: () => this.setState({ accountDropdownOpen: true }), + closeDropdown: () => this.setState({ accountDropdownOpen: false }), + }) + + ]) +} + +SignatureRequest.prototype.renderBalance = function () { + const { balance, conversionRate } = this.props + + const balanceInEther = conversionUtil(balance, { + fromNumericBase: 'hex', + toNumericBase: 'dec', + fromDenomination: 'WEI', + numberOfDecimals: 6, + conversionRate, + }) + + return h('div.request-signature__balance', [ + + h('div.request-signature__balance-text', ['Balance:']), + + h('div.request-signature__balance-value', `${balanceInEther} ETH`), + + ]) +} + +SignatureRequest.prototype.renderAccountInfo = function () { + return h('div.request-signature__account-info', [ + + this.renderAccountDropdown(), + + this.renderRequestIcon(), + + this.renderBalance(), + + ]) +} + +SignatureRequest.prototype.renderRequestIcon = function () { + const { requesterAddress } = this.props + + return h('div.request-signature__request-icon', [ + h(Identicon, { + diameter: 40, + address: requesterAddress, + }) + ]) +} + +SignatureRequest.prototype.renderRequestInfo = function () { + const { requester } = this.props + + return h('div.request-signature__request-info', [ + + h('div.request-signature__headline', [ + `Your signature is being requested`, + ]) + + ]) +} + +SignatureRequest.prototype.msgHexToText = function (hex) { + try { + const stripped = ethUtil.stripHexPrefix(hex) + const buff = Buffer.from(stripped, 'hex') + return buff.toString('utf8') + } catch (e) { + return hex + } +} + +SignatureRequest.prototype.renderBody = function () { + let rows + + const { txData } = this.props + const { type, msgParams: { data } } = txData + + if (type === 'personal_sign') { + rows = [{ name: 'Message:', value: this.msgHexToText(data) }] + } + else if (type === 'eth_signTypedData') { + rows = data + } + // given the warning in './pending-msg.js', eth_sign' has not been implemented on NewUI-flat at this time + // else if (type === 'eth_sign') { + // console.log('Not currently supported') + // } + + return h('div.request-signature__body', {}, [ + + this.renderAccountInfo(), + + this.renderRequestInfo(), + + h('div.request-signature__notice', ['You are signing:']), + + h('div.request-signature__rows', [ + + ...rows.map(({ name, value }) => { + return h('div.request-signature__row', [ + h('div.request-signature__row-title', [`${name}:`]), + h('div.request-signature__row-value', value), + ]) + }), + + ]), + + ]) +} + +SignatureRequest.prototype.renderFooter = function () { + const { + goHome, + signPersonalMessage, + signTypedMessage, + cancelPersonalMessage, + cancelTypedMessage, + } = this.props + + const { txData } = this.props + const { type } = txData + + let cancel + let sign + if (type === 'personal_sign') { + cancel = cancelPersonalMessage + sign = signPersonalMessage + } + else if (type === 'eth_signTypedData') { + cancel = cancelTypedMessage + sign = signTypedMessage + } + + return h('div.request-signature__footer', [ + h('div.request-signature__footer__cancel-button', { + onClick: cancel, + }, 'CANCEL'), + h('div.request-signature__footer__sign-button', { + onClick: sign, + }, 'SIGN'), + ]) +} + +SignatureRequest.prototype.render = function () { + return ( + + h('div.request-signature__container', [ + + this.renderHeader(), + + this.renderBody(), + + this.renderFooter(), + + ]) + + ) + +} + -- cgit v1.2.3 From 39d4fe311f694a659d1d1454159417719d552b9d Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Wed, 25 Oct 2017 14:36:12 -0700 Subject: Fix Import an Account link not working in Create Account modal --- ui/app/components/modals/new-account-modal.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/new-account-modal.js b/ui/app/components/modals/new-account-modal.js index 25beb6745..b78de1d8d 100644 --- a/ui/app/components/modals/new-account-modal.js +++ b/ui/app/components/modals/new-account-modal.js @@ -28,6 +28,7 @@ function mapDispatchToProps (dispatch) { dispatch(actions.hideModal()) }) }, + showImportPage: () => dispatch(actions.showImportPage()), } } @@ -36,7 +37,7 @@ function NewAccountModal () { Component.call(this) this.state = { - newAccountName: '' + newAccountName: '', } } @@ -63,7 +64,7 @@ NewAccountModal.prototype.render = function () { h('div.new-account-input-wrapper', {}, [ h('input.new-account-input', { placeholder: 'E.g. My new account', - onChange: (event) => this.setState({ newAccountName: event.target.value }) + onChange: event => this.setState({ newAccountName: event.target.value }), }, []), ]), @@ -71,13 +72,16 @@ NewAccountModal.prototype.render = function () { 'or', ]), - h('div.new-account-modal-content.after-input', {}, [ - 'Import an account', - ]), + h('div.new-account-modal-content.after-input.pointer', { + onClick: () => { + this.props.hideModal() + this.props.showImportPage() + }, + }, 'Import an account'), h('div.new-account-modal-content.button', {}, [ h('button.btn-clear', { - onClick: () => this.props.createAccount(newAccountName) + onClick: () => this.props.createAccount(newAccountName), }, [ 'SAVE', ]), -- cgit v1.2.3 From ddf11011c9467209e6b9810dff2df84ea9e4a040 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 25 Oct 2017 21:58:56 -0230 Subject: Signature request fixes. --- ui/app/components/signature-request.js | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/signature-request.js b/ui/app/components/signature-request.js index 4df4f9193..35a739a8f 100644 --- a/ui/app/components/signature-request.js +++ b/ui/app/components/signature-request.js @@ -156,20 +156,24 @@ SignatureRequest.prototype.msgHexToText = function (hex) { SignatureRequest.prototype.renderBody = function () { let rows + let notice = 'You are signing:' const { txData } = this.props const { type, msgParams: { data } } = txData if (type === 'personal_sign') { - rows = [{ name: 'Message:', value: this.msgHexToText(data) }] + rows = [{ name: 'Message', value: this.msgHexToText(data) }] } else if (type === 'eth_signTypedData') { rows = data } - // given the warning in './pending-msg.js', eth_sign' has not been implemented on NewUI-flat at this time - // else if (type === 'eth_sign') { - // console.log('Not currently supported') - // } + else if (type === 'eth_sign') { + rows = [{ name: 'Message', value: data }] + notice = `Signing this message can have + dangerous side effects. Only sign messages from + sites you fully trust with your entire account. + This dangerous method will be removed in a future version. ` + } return h('div.request-signature__body', {}, [ @@ -177,7 +181,7 @@ SignatureRequest.prototype.renderBody = function () { this.renderRequestInfo(), - h('div.request-signature__notice', ['You are signing:']), + h('div.request-signature__notice', [notice]), h('div.request-signature__rows', [ @@ -200,6 +204,8 @@ SignatureRequest.prototype.renderFooter = function () { signTypedMessage, cancelPersonalMessage, cancelTypedMessage, + signMessage, + cancelMessage, } = this.props const { txData } = this.props @@ -215,6 +221,10 @@ SignatureRequest.prototype.renderFooter = function () { cancel = cancelTypedMessage sign = signTypedMessage } + else if (type === 'eth_sign') { + cancel = cancelMessage + sign = signMessage + } return h('div.request-signature__footer', [ h('div.request-signature__footer__cancel-button', { -- cgit v1.2.3 From fa95303e1efef03db6c44878b89ccca680639598 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Wed, 25 Oct 2017 18:05:52 -0700 Subject: Sign Typed Request styling fixes --- ui/app/components/signature-request.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/signature-request.js b/ui/app/components/signature-request.js index 35a739a8f..a0ecbe8ec 100644 --- a/ui/app/components/signature-request.js +++ b/ui/app/components/signature-request.js @@ -227,10 +227,10 @@ SignatureRequest.prototype.renderFooter = function () { } return h('div.request-signature__footer', [ - h('div.request-signature__footer__cancel-button', { + h('button.request-signature__footer__cancel-button', { onClick: cancel, }, 'CANCEL'), - h('div.request-signature__footer__sign-button', { + h('button.request-signature__footer__sign-button', { onClick: sign, }, 'SIGN'), ]) -- cgit v1.2.3 From 22d9e3a7e6dfd21b3ea52007030d71f53e29b851 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Wed, 25 Oct 2017 18:23:46 -0700 Subject: Allow editing account name in account details modal --- ui/app/components/editable-label.js | 115 ++++++++++++++-------- ui/app/components/modals/account-details-modal.js | 21 ++-- ui/app/components/qr-code.js | 10 +- 3 files changed, 91 insertions(+), 55 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/editable-label.js b/ui/app/components/editable-label.js index 8a5c8954f..eb41ec50c 100644 --- a/ui/app/components/editable-label.js +++ b/ui/app/components/editable-label.js @@ -1,57 +1,88 @@ -const Component = require('react').Component +const { Component } = require('react') +const PropTypes = require('prop-types') const h = require('react-hyperscript') -const inherits = require('util').inherits -const findDOMNode = require('react-dom').findDOMNode +const classnames = require('classnames') -module.exports = EditableLabel +class EditableLabel extends Component { + constructor (props) { + super(props) -inherits(EditableLabel, Component) -function EditableLabel () { - Component.call(this) -} + this.state = { + isEditing: false, + value: props.defaultValue || '', + } + } + + handleSubmit () { + const { value } = this.state + + if (value === '') { + return + } + + Promise.resolve(this.props.onSubmit(value)) + .then(() => this.setState({ isEditing: false })) + } + + saveIfEnter (event) { + if (event.key === 'Enter') { + this.handleSubmit() + } + } -EditableLabel.prototype.render = function () { - const props = this.props - const state = this.state + renderEditing () { + const { value } = this.state - if (state && state.isEditingLabel) { - return h('div.editable-label', [ - h('input.sizing-input', { - defaultValue: props.textValue, - maxLength: '20', + return ([ + h('input.large-input.editable-label__input', { + type: 'text', + required: true, + value: this.state.value, onKeyPress: (event) => { - this.saveIfEnter(event) + if (event.key === 'Enter') { + this.handleSubmit() + } }, + onChange: event => this.setState({ value: event.target.value }), + className: classnames({ 'editable-label__input--error': value === '' }), }), - h('button.editable-button', { - onClick: () => this.saveText(), - }, 'Save'), + h('div.editable-label__icon-wrapper', [ + h('i.fa.fa-check.editable-label__icon', { + onClick: () => this.handleSubmit(), + }), + ]), ]) - } else { - return h('div.name-label', { - onClick: (event) => { - const nameAttribute = event.target.getAttribute('name') - // checks for class to handle smaller CTA above the account name - const classAttribute = event.target.getAttribute('class') - if (nameAttribute === 'edit' || classAttribute === 'edit-text') { - this.setState({ isEditingLabel: true }) - } - }, - }, this.props.children) } -} -EditableLabel.prototype.saveIfEnter = function (event) { - if (event.key === 'Enter') { - this.saveText() + renderReadonly () { + return ([ + h('div.editable-label__value', this.state.value), + h('div.editable-label__icon-wrapper', [ + h('i.fa.fa-pencil.editable-label__icon', { + onClick: () => this.setState({ isEditing: true }), + }), + ]), + ]) + } + + render () { + const { isEditing } = this.state + const { className } = this.props + + return ( + h('div.editable-label', { className: classnames(className) }, + isEditing + ? this.renderEditing() + : this.renderReadonly() + ) + ) } } -EditableLabel.prototype.saveText = function () { - // eslint-disable-next-line react/no-find-dom-node - var container = findDOMNode(this) - var text = container.querySelector('.editable-label input').value - var truncatedText = text.substring(0, 20) - this.props.saveText(truncatedText) - this.setState({ isEditingLabel: false, textLabel: truncatedText }) +EditableLabel.propTypes = { + onSubmit: PropTypes.func.isRequired, + defaultValue: PropTypes.string, + className: PropTypes.string, } + +module.exports = EditableLabel diff --git a/ui/app/components/modals/account-details-modal.js b/ui/app/components/modals/account-details-modal.js index 37a62e1c0..e3c936702 100644 --- a/ui/app/components/modals/account-details-modal.js +++ b/ui/app/components/modals/account-details-modal.js @@ -7,6 +7,7 @@ const AccountModalContainer = require('./account-modal-container') const { getSelectedIdentity, getSelectedAddress } = require('../../selectors') const genAccountLink = require('../../../lib/account-link.js') const QrView = require('../qr-code') +const EditableLabel = require('../editable-label') function mapStateToProps (state) { return { @@ -23,6 +24,7 @@ function mapDispatchToProps (dispatch) { dispatch(actions.showModal({ name: 'EXPORT_PRIVATE_KEY' })) }, hideModal: () => dispatch(actions.hideModal()), + saveAccountLabel: (address, label) => dispatch(actions.saveAccountLabel(address, label)), } } @@ -41,14 +43,19 @@ AccountDetailsModal.prototype.render = function () { selectedIdentity, network, showExportPrivateKeyModal, - hideModal, + saveAccountLabel, } = this.props const { name, address } = selectedIdentity return h(AccountModalContainer, {}, [ + h(EditableLabel, { + className: 'account-modal__name', + defaultValue: name, + onSubmit: label => saveAccountLabel(address, label), + }), + h(QrView, { Qr: { - message: name, data: address, }, }), @@ -57,14 +64,12 @@ AccountDetailsModal.prototype.render = function () { h('button.btn-clear', { onClick: () => global.platform.openWindow({ url: genAccountLink(address, network) }), - }, [ 'View account on Etherscan' ]), + }, 'View account on Etherscan'), // Holding on redesign for Export Private Key functionality h('button.btn-clear', { - onClick: () => { - showExportPrivateKeyModal() - }, - }, [ 'Export private key' ]), - + onClick: () => showExportPrivateKeyModal(), + }, 'Export private key'), + ]) } diff --git a/ui/app/components/qr-code.js b/ui/app/components/qr-code.js index cc723df14..83885539c 100644 --- a/ui/app/components/qr-code.js +++ b/ui/app/components/qr-code.js @@ -29,11 +29,11 @@ QrCodeView.prototype.render = function () { const qrImage = qrCode(4, 'M') qrImage.addData(address) qrImage.make() - return h('.div.flex-column.flex-center', { - style: { - }, - }, [ - Array.isArray(Qr.message) ? h('.message-container', this.renderMultiMessage()) : h('.qr-header', Qr.message), + + return h('.div.flex-column.flex-center', [ + Array.isArray(Qr.message) + ? h('.message-container', this.renderMultiMessage()) + : Qr.message && h('.qr-header', Qr.message), this.props.warning ? this.props.warning && h('span.error.flex-center', { style: { -- cgit v1.2.3 From 220da24f9ab4a57a10bc1fc3e249c511a98ecb46 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 26 Oct 2017 13:36:34 -0230 Subject: Change min gas price to 0.1 GWEI --- ui/app/components/customize-gas-modal/index.js | 3 ++- ui/app/components/input-number.js | 26 ++++++++++++++++++---- .../pending-tx/confirm-deploy-contract.js | 6 ++--- ui/app/components/pending-tx/confirm-send-ether.js | 6 ++--- ui/app/components/pending-tx/confirm-send-token.js | 6 ++--- ui/app/components/send/send-constants.js | 25 ++++++++++----------- 6 files changed, 42 insertions(+), 30 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 722ed2b23..80ea98cc8 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -2,6 +2,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect +const ethUtil = require('ethereumjs-util') const actions = require('../../actions') const GasModalCard = require('./gas-modal-card') @@ -224,7 +225,7 @@ CustomizeGasModal.prototype.render = function () { value: convertedGasPrice, min: MIN_GAS_PRICE_GWEI, // max: 1000, - step: 1, + step: MIN_GAS_PRICE_GWEI, onChange: value => this.convertAndSetGasPrice(value), title: 'Gas Price (GWEI)', copy: 'We calculate the suggested gas prices based on network success rates.', diff --git a/ui/app/components/input-number.js b/ui/app/components/input-number.js index 16347fd5e..e28807c13 100644 --- a/ui/app/components/input-number.js +++ b/ui/app/components/input-number.js @@ -1,7 +1,12 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits -const { addCurrencies } = require('../conversion-util') +const { + addCurrencies, + conversionGTE, + conversionLTE, + toNegative, +} = require('../conversion-util') module.exports = InputNumber @@ -17,8 +22,21 @@ InputNumber.prototype.setValue = function (newValue) { newValue = Number(fixed ? newValue.toFixed(4) : newValue) - if (newValue >= min && newValue <= max) { + const newValueGreaterThanMin = conversionGTE( + { value: newValue, fromNumericBase: 'dec' }, + { value: min, fromNumericBase: 'hex' }, + ) + + const newValueLessThanMax = conversionLTE( + { value: newValue, fromNumericBase: 'dec' }, + { value: max, fromNumericBase: 'hex' }, + ) + if (newValueGreaterThanMin && newValueLessThanMax) { onChange(newValue) + } else if (!newValueGreaterThanMin) { + onChange(min) + } else if (!newValueLessThanMax) { + onChange(max) } } @@ -29,7 +47,7 @@ InputNumber.prototype.render = function () { h('input.customize-gas-input', { placeholder, type: 'number', - value: value, + value, onChange: (e) => this.setValue(e.target.value), }), h('span.gas-tooltip-input-detail', {}, [unitLabel]), @@ -39,7 +57,7 @@ InputNumber.prototype.render = function () { }), h('i.fa.fa-angle-down', { style: { cursor: 'pointer' }, - onClick: () => this.setValue(addCurrencies(value, step * -1)), + onClick: () => this.setValue(addCurrencies(value, toNegative(step))), }), ]), ]) diff --git a/ui/app/components/pending-tx/confirm-deploy-contract.js b/ui/app/components/pending-tx/confirm-deploy-contract.js index a0ba94045..ae6c6ef7b 100644 --- a/ui/app/components/pending-tx/confirm-deploy-contract.js +++ b/ui/app/components/pending-tx/confirm-deploy-contract.js @@ -10,9 +10,7 @@ const BN = ethUtil.BN const hexToBn = require('../../../../app/scripts/lib/hex-to-bn') const { conversionUtil } = require('../../conversion-util') -const MIN_GAS_PRICE_GWEI_BN = new BN(1) -const GWEI_FACTOR = new BN(1e9) -const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR) +const { MIN_GAS_PRICE_HEX } = require('../send/send-constants') module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmDeployContract) @@ -166,7 +164,7 @@ ConfirmDeployContract.prototype.getGasFee = function () { const gasBn = hexToBn(gas) // Gas Price - const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16) + const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_HEX const gasPriceBn = hexToBn(gasPrice) const txFeeBn = gasBn.mul(gasPriceBn) diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 2f178f179..d12bc499b 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -10,9 +10,7 @@ const BN = ethUtil.BN const hexToBn = require('../../../../app/scripts/lib/hex-to-bn') const { conversionUtil, addCurrencies } = require('../../conversion-util') -const MIN_GAS_PRICE_GWEI_BN = new BN(1) -const GWEI_FACTOR = new BN(1e9) -const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR) +const { MIN_GAS_PRICE_HEX } = require('../send/send-constants') module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmSendEther) @@ -93,7 +91,7 @@ ConfirmSendEther.prototype.getGasFee = function () { // const safeGasLimit = safeGasLimitBN.toString(10) // Gas Price - const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16) + const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_HEX const gasPriceBn = hexToBn(gasPrice) const txFeeBn = gasBn.mul(gasPriceBn) diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index abb7a0770..19826f47c 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -17,9 +17,7 @@ const { addCurrencies, } = require('../../conversion-util') -const MIN_GAS_PRICE_GWEI_BN = new BN(1) -const GWEI_FACTOR = new BN(1e9) -const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR) +const { MIN_GAS_PRICE_HEX } = require('../send/send-constants') const { getSelectedTokenExchangeRate, @@ -99,7 +97,7 @@ ConfirmSendToken.prototype.getGasFee = function () { const { decimals } = token const gas = txParams.gas - const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16) + const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_HEX const gasTotal = multiplyCurrencies(gas, gasPrice, { multiplicandBase: 16, multiplierBase: 16, diff --git a/ui/app/components/send/send-constants.js b/ui/app/components/send/send-constants.js index 8b56607cc..471e01e2a 100644 --- a/ui/app/components/send/send-constants.js +++ b/ui/app/components/send/send-constants.js @@ -1,20 +1,19 @@ +const ethUtil = require('ethereumjs-util') const Identicon = require('../identicon') -const { multiplyCurrencies } = require('../../conversion-util') +const { conversionUtil, multiplyCurrencies } = require('../../conversion-util') -const MIN_GAS_PRICE_GWEI = '1' -const GWEI_FACTOR = '1e9' -const MIN_GAS_PRICE_HEX = multiplyCurrencies(GWEI_FACTOR, MIN_GAS_PRICE_GWEI, { - multiplicandBase: 16, - multiplierBase: 16, - toNumericBase: 'hex', -}) -const MIN_GAS_PRICE_DEC = multiplyCurrencies(GWEI_FACTOR, MIN_GAS_PRICE_GWEI, { - multiplicandBase: 16, - multiplierBase: 16, - toNumericBase: 'dec', -}) +const MIN_GAS_PRICE_HEX = (100000000).toString(16) +const MIN_GAS_PRICE_DEC = '100000000' const MIN_GAS_LIMIT_HEX = (21000).toString(16) const MIN_GAS_LIMIT_DEC = 21000 + +const MIN_GAS_PRICE_GWEI = ethUtil.addHexPrefix(conversionUtil(MIN_GAS_PRICE_HEX, { + fromDenomination: 'WEI', + toDenomination: 'GWEI', + fromNumericBase: 'hex', + toNumericBase: 'hex', +})) + const MIN_GAS_TOTAL = multiplyCurrencies(MIN_GAS_LIMIT_HEX, MIN_GAS_PRICE_HEX, { toNumericBase: 'hex', multiplicandBase: 16, -- cgit v1.2.3 From f9fc6cec3b01357dd5bb182b6389426d1f17260a Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 26 Oct 2017 14:29:22 -0230 Subject: eth_sign warning color --- ui/app/components/signature-request.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/signature-request.js b/ui/app/components/signature-request.js index a0ecbe8ec..e617fdbd6 100644 --- a/ui/app/components/signature-request.js +++ b/ui/app/components/signature-request.js @@ -4,6 +4,8 @@ const inherits = require('util').inherits const Identicon = require('./identicon') const connect = require('react-redux').connect const ethUtil = require('ethereumjs-util') +const classnames = require('classnames') + const PendingTxDetails = require('./pending-personal-msg-details') const AccountDropdownMini = require('./dropdowns/account-dropdown-mini') const BinaryRenderer = require('./binary-renderer') @@ -181,7 +183,12 @@ SignatureRequest.prototype.renderBody = function () { this.renderRequestInfo(), - h('div.request-signature__notice', [notice]), + h('div.request-signature__notice', { + className: classnames({ + 'request-signature__notice': type === 'personal_sign' || type === 'eth_signTypedData', + 'request-signature__warning': type === 'eth_sign', + }) + }, [notice]), h('div.request-signature__rows', [ -- cgit v1.2.3 From 0ed1add110ec630ed358aa44af030623bab1ad92 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 26 Oct 2017 14:45:05 -0230 Subject: Clear import error state on logout. --- ui/app/components/account-menu/index.js | 1 + 1 file changed, 1 insertion(+) (limited to 'ui/app/components') diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index 38c7bcb2d..a9f075ec7 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -32,6 +32,7 @@ function mapDispatchToProps (dispatch) { }, lockMetamask: () => { dispatch(actions.lockMetamask()) + dispatch(actions.displayWarning(null)) dispatch(actions.toggleAccountMenu()) }, showConfigPage: () => { -- cgit v1.2.3 From 3d53716f4366212ed7a51b49ce747584b13fd1ce Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Fri, 27 Oct 2017 03:25:34 -0230 Subject: Correct rendering of conversions when conversion rate is a token. (#2498) --- ui/app/components/token-cell.js | 28 ++++++++++++++++------------ ui/app/components/tx-list-item.js | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 46 insertions(+), 15 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index 6bb42204e..f55e23f9e 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -6,7 +6,7 @@ const Identicon = require('./identicon') const prefixForNetwork = require('../../lib/etherscan-prefix-for-network') const selectors = require('../selectors') const actions = require('../actions') -const { conversionUtil } = require('../conversion-util') +const { conversionUtil, multiplyCurrencies } = require('../conversion-util') const TokenMenuDropdown = require('./dropdowns/token-menu-dropdown.js') @@ -17,7 +17,7 @@ function mapStateToProps (state) { selectedTokenAddress: state.metamask.selectedTokenAddress, userAddress: selectors.getSelectedAddress(state), tokenExchangeRates: state.metamask.tokenExchangeRates, - ethToUSDRate: state.metamask.conversionRate, + conversionRate: state.metamask.conversionRate, sidebarOpen: state.appState.sidebarOpen, } } @@ -61,7 +61,7 @@ TokenCell.prototype.render = function () { setSelectedToken, selectedTokenAddress, tokenExchangeRates, - ethToUSDRate, + conversionRate, hideSidebar, sidebarOpen, currentCurrency, @@ -70,22 +70,26 @@ TokenCell.prototype.render = function () { const pair = `${symbol.toLowerCase()}_eth`; - let currentTokenToEthRate; + let currentTokenToFiatRate; let currentTokenInFiat; - let formattedUSD = '' + let formattedFiat = '' if (tokenExchangeRates[pair]) { - currentTokenToEthRate = tokenExchangeRates[pair].rate; + currentTokenToFiatRate = multiplyCurrencies( + tokenExchangeRates[pair].rate, + conversionRate + ) currentTokenInFiat = conversionUtil(string, { fromNumericBase: 'dec', fromCurrency: symbol, - toCurrency: 'USD', + toCurrency: currentCurrency.toUpperCase(), numberOfDecimals: 2, - conversionRate: currentTokenToEthRate, - ethToUSDRate, + conversionRate: currentTokenToFiatRate, }) - formattedUSD = `${currentTokenInFiat} ${currentCurrency.toUpperCase()}`; + formattedFiat = `${currentTokenInFiat} ${currentCurrency.toUpperCase()}`; } + + const showFiat = Boolean(currentTokenInFiat) && currentCurrency.toUpperCase() !== symbol return ( h('div.token-list-item', { @@ -108,9 +112,9 @@ TokenCell.prototype.render = function () { h('h.token-list-item__balance-wrapper', null, [ h('h3.token-list-item__token-balance', `${string || 0} ${symbol}`), - h('div.token-list-item__fiat-amount', { + showFiat && h('div.token-list-item__fiat-amount', { style: {}, - }, formattedUSD), + }, formattedFiat), ]), h('i.fa.fa-ellipsis-h.fa-lg.token-list-item__ellipsis.cursor-pointer', { diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 3bb9a2eda..84026700b 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -9,7 +9,7 @@ abiDecoder.addABI(abi) const prefixForNetwork = require('../../lib/etherscan-prefix-for-network') const Identicon = require('./identicon') -const { conversionUtil } = require('../conversion-util') +const { conversionUtil, multiplyCurrencies } = require('../conversion-util') const { getCurrentCurrency } = require('../selectors') @@ -19,6 +19,7 @@ function mapStateToProps (state) { return { tokens: state.metamask.tokens, currentCurrency: getCurrentCurrency(state), + tokenExchangeRates: state.metamask.tokenExchangeRates, } } @@ -88,6 +89,9 @@ TxListItem.prototype.getSendTokenTotal = function () { const { txParams = {}, tokens, + conversionRate, + tokenExchangeRates, + currentCurrency, } = this.props const toAddress = txParams.to @@ -95,12 +99,35 @@ TxListItem.prototype.getSendTokenTotal = function () { const { params = [] } = decodedData || {} const { value } = params[1] || {} const { decimals, symbol } = tokens.filter(({ address }) => address === toAddress)[0] || {} - const multiplier = Math.pow(10, Number(decimals || 0)) const total = Number(value / multiplier) + const pair = symbol && `${symbol.toLowerCase()}_eth`; + + let tokenToFiatRate + let totalInFiat + + if (tokenExchangeRates[pair]) { + tokenToFiatRate = multiplyCurrencies( + tokenExchangeRates[pair].rate, + conversionRate + ) + + totalInFiat = conversionUtil(total, { + fromNumericBase: 'dec', + toNumericBase: 'dec', + fromCurrency: symbol, + toCurrency: currentCurrency, + numberOfDecimals: 2, + conversionRate: tokenToFiatRate, + }) + } + + const showFiat = Boolean(totalInFiat) && currentCurrency.toUpperCase() !== symbol + return { total: `${total} ${symbol}`, + fiatTotal: showFiat && `${totalInFiat} ${currentCurrency.toUpperCase()}`, } } @@ -182,7 +209,7 @@ TxListItem.prototype.render = function () { }), }, total), - h('span.tx-list-fiat-value', fiatTotal), + fiatTotal && h('span.tx-list-fiat-value', fiatTotal), ]), ]), -- cgit v1.2.3 From 5d8b53bcf491bfe6dd59f4986f02da70b91df5cd Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Thu, 26 Oct 2017 11:36:13 -0700 Subject: Provide default new account name --- ui/app/components/modals/new-account-modal.js | 141 ++++++++++++++------------ 1 file changed, 78 insertions(+), 63 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/new-account-modal.js b/ui/app/components/modals/new-account-modal.js index b78de1d8d..fc1fd413d 100644 --- a/ui/app/components/modals/new-account-modal.js +++ b/ui/app/components/modals/new-account-modal.js @@ -1,17 +1,88 @@ -const Component = require('react').Component +const { Component } = require('react') +const PropTypes = require('prop-types') const h = require('react-hyperscript') -const inherits = require('util').inherits -const connect = require('react-redux').connect +const { connect } = require('react-redux') const actions = require('../../actions') -function mapStateToProps (state) { +class NewAccountModal extends Component { + constructor (props) { + super(props) + const { numberOfExistingAccounts = 0 } = props + const newAccountNumber = numberOfExistingAccounts + 1 + + this.state = { + newAccountName: `Account ${newAccountNumber}`, + } + } + + render () { + const { newAccountName } = this.state + + return h('div', [ + h('div.new-account-modal-wrapper', { + }, [ + h('div.new-account-modal-header', {}, [ + 'New Account', + ]), + + h('div.modal-close-x', { + onClick: this.props.hideModal, + }), + + h('div.new-account-modal-content', {}, [ + 'Account Name', + ]), + + h('div.new-account-input-wrapper', {}, [ + h('input.new-account-input', { + value: this.state.newAccountName, + placeholder: 'E.g. My new account', + onChange: event => this.setState({ newAccountName: event.target.value }), + }, []), + ]), + + h('div.new-account-modal-content.after-input', {}, [ + 'or', + ]), + + h('div.new-account-modal-content.after-input.pointer', { + onClick: () => { + this.props.hideModal() + this.props.showImportPage() + }, + }, 'Import an account'), + + h('div.new-account-modal-content.button', {}, [ + h('button.btn-clear', { + onClick: () => this.props.createAccount(newAccountName), + }, [ + 'SAVE', + ]), + ]), + ]), + ]) + } +} + +NewAccountModal.propTypes = { + hideModal: PropTypes.func, + showImportPage: PropTypes.func, + createAccount: PropTypes.func, + numberOfExistingAccounts: PropTypes.number, +} + +const mapStateToProps = state => { + const { metamask: { network, selectedAddress, identities = {} } } = state + const numberOfExistingAccounts = Object.keys(identities).length + return { - network: state.metamask.network, - address: state.metamask.selectedAddress, + network, + address: selectedAddress, + numberOfExistingAccounts, } } -function mapDispatchToProps (dispatch) { +const mapDispatchToProps = dispatch => { return { toCoinbase: (address) => { dispatch(actions.buyEth({ network: '1', address, amount: 0 })) @@ -32,60 +103,4 @@ function mapDispatchToProps (dispatch) { } } -inherits(NewAccountModal, Component) -function NewAccountModal () { - Component.call(this) - - this.state = { - newAccountName: '', - } -} - module.exports = connect(mapStateToProps, mapDispatchToProps)(NewAccountModal) - -NewAccountModal.prototype.render = function () { - const { newAccountName } = this.state - - return h('div', {}, [ - h('div.new-account-modal-wrapper', { - }, [ - h('div.new-account-modal-header', {}, [ - 'New Account', - ]), - - h('div.modal-close-x', { - onClick: this.props.hideModal, - }), - - h('div.new-account-modal-content', {}, [ - 'Account Name', - ]), - - h('div.new-account-input-wrapper', {}, [ - h('input.new-account-input', { - placeholder: 'E.g. My new account', - onChange: event => this.setState({ newAccountName: event.target.value }), - }, []), - ]), - - h('div.new-account-modal-content.after-input', {}, [ - 'or', - ]), - - h('div.new-account-modal-content.after-input.pointer', { - onClick: () => { - this.props.hideModal() - this.props.showImportPage() - }, - }, 'Import an account'), - - h('div.new-account-modal-content.button', {}, [ - h('button.btn-clear', { - onClick: () => this.props.createAccount(newAccountName), - }, [ - 'SAVE', - ]), - ]), - ]), - ]) -} -- cgit v1.2.3 From c8c918d44e26e9541beead982ef0ed79a56d6e6f Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 27 Oct 2017 15:09:40 -0230 Subject: Add utility for getting token data; get token data in tx-list even if token has been removed. --- ui/app/components/tx-list-item.js | 53 +++++++++++++++++++++++++++++++-------- ui/app/components/tx-list.js | 6 +++++ 2 files changed, 48 insertions(+), 11 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 84026700b..a59b6509b 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -8,6 +8,7 @@ const abiDecoder = require('abi-decoder') abiDecoder.addABI(abi) const prefixForNetwork = require('../../lib/etherscan-prefix-for-network') const Identicon = require('./identicon') +const contractMap = require('eth-contract-metadata') const { conversionUtil, multiplyCurrencies } = require('../conversion-util') @@ -26,6 +27,24 @@ function mapStateToProps (state) { inherits(TxListItem, Component) function TxListItem () { Component.call(this) + + this.state = { + total: null, + fiatTotal: null, + } +} + +TxListItem.prototype.componentDidMount = async function () { + const { txParams = {} } = this.props + + const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data) + const { name: txDataName } = decodedData || {} + + const { total, fiatTotal } = txDataName === 'transfer' + ? await this.getSendTokenTotal() + : this.getSendEtherTotal() + + this.setState({ total, fiatTotal }) } TxListItem.prototype.getAddressText = function () { @@ -85,7 +104,27 @@ TxListItem.prototype.getSendEtherTotal = function () { } } -TxListItem.prototype.getSendTokenTotal = function () { +TxListItem.prototype.getTokenInfo = async function () { + const { txParams = {}, tokenInfoGetter, tokens } = this.props + const toAddress = txParams.to + + let decimals + let symbol + + ({ decimals, symbol } = tokens.filter(({ address }) => address === toAddress)[0] || {}) + + if (!decimals && !symbol) { + ({ decimals, symbol } = contractMap[toAddress] || {}) + } + + if (!decimals && !symbol) { + ({ decimals, symbol } = await tokenInfoGetter(toAddress)) + } + + return { decimals, symbol } +} + +TxListItem.prototype.getSendTokenTotal = async function () { const { txParams = {}, tokens, @@ -94,11 +133,10 @@ TxListItem.prototype.getSendTokenTotal = function () { currentCurrency, } = this.props - const toAddress = txParams.to const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data) const { params = [] } = decodedData || {} const { value } = params[1] || {} - const { decimals, symbol } = tokens.filter(({ address }) => address === toAddress)[0] || {} + const { decimals, symbol } = await this.getTokenInfo() const multiplier = Math.pow(10, Number(decimals || 0)) const total = Number(value / multiplier) @@ -139,15 +177,8 @@ TxListItem.prototype.render = function () { dateString, address, className, - txParams = {}, } = this.props - - const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data) - const { name: txDataName } = decodedData || {} - - const { total, fiatTotal } = txDataName === 'transfer' - ? this.getSendTokenTotal() - : this.getSendEtherTotal() + const { total, fiatTotal } = this.state return h(`div${className || ''}`, { key: transActionId, diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index a02849d0e..2f6c1fee8 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -9,6 +9,7 @@ const ShiftListItem = require('./shift-list-item') const { formatBalance, formatDate } = require('../util') const { showConfTxPage } = require('../actions') const classnames = require('classnames') +const { tokenInfoGetter } = require('../token-util') module.exports = connect(mapStateToProps, mapDispatchToProps)(TxList) @@ -30,6 +31,10 @@ function TxList () { Component.call(this) } +TxList.prototype.componentWillMount = function () { + this.tokenInfoGetter = tokenInfoGetter() +} + TxList.prototype.render = function () { const { txsToRender, showConfTxPage } = this.props @@ -99,6 +104,7 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa transactionAmount, transactionHash, conversionRate, + tokenInfoGetter: this.tokenInfoGetter, } const isUnapproved = transactionStatus === 'unapproved'; -- cgit v1.2.3 From 06a931f9884165941d693bca20273bbe64b622ac Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 31 Oct 2017 14:01:10 -0500 Subject: ui - allow optional size for mascot --- ui/app/components/mascot.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/mascot.js b/ui/app/components/mascot.js index 973ec2cad..3b0d3e31b 100644 --- a/ui/app/components/mascot.js +++ b/ui/app/components/mascot.js @@ -7,13 +7,13 @@ const debounce = require('debounce') module.exports = Mascot inherits(Mascot, Component) -function Mascot () { +function Mascot ({width = '200', height = '200'}) { Component.call(this) this.logo = metamaskLogo({ followMouse: true, pxNotRatio: true, - width: 200, - height: 200, + width, + height, }) this.refollowMouse = debounce(this.logo.setFollowMouse.bind(this.logo, true), 1000) -- cgit v1.2.3 From 5a94775b3fa22517a71232ebe229ee83e9debcf1 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 2 Nov 2017 00:00:33 -0230 Subject: Lint fixes for NewUI-flat. --- .../customize-gas-modal/gas-modal-card.js | 5 +- .../components/customize-gas-modal/gas-slider.js | 94 +++++++++++----------- ui/app/components/customize-gas-modal/index.js | 3 +- .../components/dropdowns/account-dropdown-mini.js | 3 - .../dropdowns/account-options-dropdown.js | 2 +- .../dropdowns/account-selection-dropdown.js | 2 +- .../dropdowns/components/account-dropdowns.js | 15 ++++ ui/app/components/dropdowns/components/dropdown.js | 1 + ui/app/components/dropdowns/simple-dropdown.js | 3 +- ui/app/components/loading.js | 5 ++ ui/app/components/modals/account-details-modal.js | 2 +- .../components/modals/export-private-key-modal.js | 1 - ui/app/components/pending-tx/confirm-send-token.js | 4 - ui/app/components/send-token/index.js | 1 - ui/app/components/send/currency-display.js | 3 - ui/app/components/send/from-dropdown.js | 3 - ui/app/components/send/gas-fee-display-v2.js | 2 +- ui/app/components/send/memo-textarea.js | 50 ++++++------ ui/app/components/send/send-constants.js | 1 - ui/app/components/send/send-utils.js | 1 - ui/app/components/send/send-v2-container.js | 6 -- ui/app/components/send/to-autocomplete.js | 5 -- ui/app/components/signature-request.js | 5 -- ui/app/components/tab-bar.js | 7 ++ ui/app/components/token-list.js | 26 +++--- ui/app/components/transaction-list-item.js | 48 +++++------ ui/app/components/tx-list-item.js | 2 - ui/app/components/tx-list.js | 6 +- 28 files changed, 147 insertions(+), 159 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/customize-gas-modal/gas-modal-card.js b/ui/app/components/customize-gas-modal/gas-modal-card.js index de181dc67..0172d8afb 100644 --- a/ui/app/components/customize-gas-modal/gas-modal-card.js +++ b/ui/app/components/customize-gas-modal/gas-modal-card.js @@ -2,7 +2,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits const InputNumber = require('../input-number.js') -const GasSlider = require('./gas-slider.js') +// const GasSlider = require('./gas-slider.js') module.exports = GasModalCard @@ -13,8 +13,7 @@ function GasModalCard () { GasModalCard.prototype.render = function () { const { - memo, - identities, + // memo, onChange, unitLabel, value, diff --git a/ui/app/components/customize-gas-modal/gas-slider.js b/ui/app/components/customize-gas-modal/gas-slider.js index e76e96545..7a9636094 100644 --- a/ui/app/components/customize-gas-modal/gas-slider.js +++ b/ui/app/components/customize-gas-modal/gas-slider.js @@ -1,50 +1,50 @@ -const Component = require('react').Component -const h = require('react-hyperscript') -const inherits = require('util').inherits - -module.exports = GasSlider - -inherits(GasSlider, Component) -function GasSlider () { - Component.call(this) -} - -GasSlider.prototype.render = function () { - const { - memo, - identities, - onChange, - unitLabel, - value, - id, - step, - max, - min, - } = this.props - - return h('div.gas-slider', [ - - h('input.gas-slider__input', { - type: 'range', - step, - max, - min, - value, - id: 'gasSlider', - onChange: event => onChange(event.target.value), - }, []), - - h('div.gas-slider__bar', [ - - h('div.gas-slider__low'), - - h('div.gas-slider__mid'), - - h('div.gas-slider__high'), - - ]), +// const Component = require('react').Component +// const h = require('react-hyperscript') +// const inherits = require('util').inherits + +// module.exports = GasSlider + +// inherits(GasSlider, Component) +// function GasSlider () { +// Component.call(this) +// } + +// GasSlider.prototype.render = function () { +// const { +// memo, +// identities, +// onChange, +// unitLabel, +// value, +// id, +// step, +// max, +// min, +// } = this.props + +// return h('div.gas-slider', [ + +// h('input.gas-slider__input', { +// type: 'range', +// step, +// max, +// min, +// value, +// id: 'gasSlider', +// onChange: event => onChange(event.target.value), +// }, []), + +// h('div.gas-slider__bar', [ + +// h('div.gas-slider__low'), + +// h('div.gas-slider__mid'), + +// h('div.gas-slider__high'), + +// ]), - ]) +// ]) -} +// } diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 80ea98cc8..4bd9d079a 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -2,7 +2,6 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect -const ethUtil = require('ethereumjs-util') const actions = require('../../actions') const GasModalCard = require('./gas-modal-card') @@ -191,7 +190,7 @@ CustomizeGasModal.prototype.convertAndSetGasPrice = function (newGasPrice) { } CustomizeGasModal.prototype.render = function () { - const { hideModal, conversionRate } = this.props + const { hideModal } = this.props const { gasPrice, gasLimit, gasTotal, error } = this.state const convertedGasPrice = conversionUtil(gasPrice, { diff --git a/ui/app/components/dropdowns/account-dropdown-mini.js b/ui/app/components/dropdowns/account-dropdown-mini.js index 96057d2b4..f403c56b9 100644 --- a/ui/app/components/dropdowns/account-dropdown-mini.js +++ b/ui/app/components/dropdowns/account-dropdown-mini.js @@ -1,7 +1,6 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits -const Identicon = require('../identicon') const AccountListItem = require('../send/account-list-item') module.exports = AccountDropdownMini @@ -53,10 +52,8 @@ AccountDropdownMini.prototype.renderDropdown = function () { AccountDropdownMini.prototype.render = function () { const { - accounts, selectedAccount, openDropdown, - closeDropdown, dropdownOpen, } = this.props diff --git a/ui/app/components/dropdowns/account-options-dropdown.js b/ui/app/components/dropdowns/account-options-dropdown.js index 50e793d87..f74c0a2d4 100644 --- a/ui/app/components/dropdowns/account-options-dropdown.js +++ b/ui/app/components/dropdowns/account-options-dropdown.js @@ -19,7 +19,7 @@ AccountOptionsDropdown.prototype.render = function () { return h(AccountDropdowns, { enableAccountOptions: true, enableAccountsSelector: false, - selected: selectedAddress, + selected, network, identities, style: style || {}, diff --git a/ui/app/components/dropdowns/account-selection-dropdown.js b/ui/app/components/dropdowns/account-selection-dropdown.js index 7a8502d18..2f6452b15 100644 --- a/ui/app/components/dropdowns/account-selection-dropdown.js +++ b/ui/app/components/dropdowns/account-selection-dropdown.js @@ -19,7 +19,7 @@ AccountSelectionDropdown.prototype.render = function () { return h(AccountDropdowns, { enableAccountOptions: false, enableAccountsSelector: true, - selected: selectedAddress, + selected, network, identities, style: style || {}, diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index e2eed1e4b..58326b13c 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -425,6 +425,21 @@ AccountDropdowns.propTypes = { identities: PropTypes.objectOf(PropTypes.object), selected: PropTypes.string, keyrings: PropTypes.array, + accounts: PropTypes.object, + menuItemStyles: PropTypes.object, + actions: PropTypes.object, + // actions.showAccountDetail: , + useCssTransition: PropTypes.bool, + innerStyle: PropTypes.object, + sidebarOpen: PropTypes.bool, + dropdownWrapperStyle: PropTypes.string, + // actions.showAccountDetailModal: , + network: PropTypes.number, + // actions.showExportPrivateKeyModal: , + style: PropTypes.object, + enableAccountsSelector: PropTypes.bool, + enableAccountOption: PropTypes.bool, + enableAccountOptions: PropTypes.bool, } const mapDispatchToProps = (dispatch) => { diff --git a/ui/app/components/dropdowns/components/dropdown.js b/ui/app/components/dropdowns/components/dropdown.js index ca68e55f7..ddcb7998f 100644 --- a/ui/app/components/dropdowns/components/dropdown.js +++ b/ui/app/components/dropdowns/components/dropdown.js @@ -68,6 +68,7 @@ Dropdown.propTypes = { onClickOutside: PropTypes.func, innerStyle: PropTypes.object, useCssTransition: PropTypes.bool, + containerClassName: PropTypes.string, } class DropdownMenuItem extends Component { diff --git a/ui/app/components/dropdowns/simple-dropdown.js b/ui/app/components/dropdowns/simple-dropdown.js index 8cea78518..7bb48e57b 100644 --- a/ui/app/components/dropdowns/simple-dropdown.js +++ b/ui/app/components/dropdowns/simple-dropdown.js @@ -1,4 +1,5 @@ -const { Component, PropTypes } = require('react') +const { Component } = require('react') +const PropTypes = require('react').PropTypes const h = require('react-hyperscript') const classnames = require('classnames') const R = require('ramda') diff --git a/ui/app/components/loading.js b/ui/app/components/loading.js index e6d841aa0..587212015 100644 --- a/ui/app/components/loading.js +++ b/ui/app/components/loading.js @@ -1,5 +1,6 @@ const { Component } = require('react') const h = require('react-hyperscript') +const PropTypes = require('react').PropTypes class LoadingIndicator extends Component { renderMessage () { @@ -35,4 +36,8 @@ class LoadingIndicator extends Component { } } +LoadingIndicator.propTypes = { + loadingMessage: PropTypes.string, +} + module.exports = LoadingIndicator diff --git a/ui/app/components/modals/account-details-modal.js b/ui/app/components/modals/account-details-modal.js index e3c936702..4bf671834 100644 --- a/ui/app/components/modals/account-details-modal.js +++ b/ui/app/components/modals/account-details-modal.js @@ -4,7 +4,7 @@ const inherits = require('util').inherits const connect = require('react-redux').connect const actions = require('../../actions') const AccountModalContainer = require('./account-modal-container') -const { getSelectedIdentity, getSelectedAddress } = require('../../selectors') +const { getSelectedIdentity } = require('../../selectors') const genAccountLink = require('../../../lib/account-link.js') const QrView = require('../qr-code') const EditableLabel = require('../editable-label') diff --git a/ui/app/components/modals/export-private-key-modal.js b/ui/app/components/modals/export-private-key-modal.js index 2d8470634..193755df5 100644 --- a/ui/app/components/modals/export-private-key-modal.js +++ b/ui/app/components/modals/export-private-key-modal.js @@ -92,7 +92,6 @@ ExportPrivateKeyModal.prototype.renderButtons = function (privateKey, password, ExportPrivateKeyModal.prototype.render = function () { const { selectedIdentity, - network, warning, showAccountDetailModal, hideModal, diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index 19826f47c..4a57553d7 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -10,7 +10,6 @@ const clone = require('clone') const Identicon = require('../identicon') const ethUtil = require('ethereumjs-util') const BN = ethUtil.BN -const hexToBn = require('../../../../app/scripts/lib/hex-to-bn') const { conversionUtil, multiplyCurrencies, @@ -20,7 +19,6 @@ const { const { MIN_GAS_PRICE_HEX } = require('../send/send-constants') const { - getSelectedTokenExchangeRate, getTokenExchangeRate, getSelectedAddress, } = require('../../selectors') @@ -36,7 +34,6 @@ function mapStateToProps (state, ownProps) { identities, currentCurrency, } = state.metamask - const accounts = state.metamask.accounts const selectedAddress = getSelectedAddress(state) const tokenExchangeRate = getTokenExchangeRate(state, symbol) @@ -245,7 +242,6 @@ ConfirmSendToken.prototype.renderTotalPlusGas = function () { ConfirmSendToken.prototype.render = function () { const { backToAccountDetail, selectedAddress } = this.props const txMeta = this.gatherTxMeta() - const txParams = txMeta.txParams || {} const { from: { diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index a95a0a6d8..c5c7a0b46 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -144,7 +144,6 @@ SendTokenScreen.prototype.validate = function () { } SendTokenScreen.prototype.setErrorsFor = function (field) { - const { balance, selectedToken } = this.props const { errors: previousErrors } = this.state const { diff --git a/ui/app/components/send/currency-display.js b/ui/app/components/send/currency-display.js index 5dba6a8dd..34939c767 100644 --- a/ui/app/components/send/currency-display.js +++ b/ui/app/components/send/currency-display.js @@ -1,7 +1,6 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits -const Identicon = require('../identicon') const { conversionUtil, multiplyCurrencies } = require('../../conversion-util') module.exports = CurrencyDisplay @@ -48,8 +47,6 @@ CurrencyDisplay.prototype.render = function () { conversionRate, primaryCurrency, convertedCurrency, - convertedPrefix = '', - placeholder = '0', readOnly = false, inError = false, value: initValue, diff --git a/ui/app/components/send/from-dropdown.js b/ui/app/components/send/from-dropdown.js index 6f2b9da68..b404dde14 100644 --- a/ui/app/components/send/from-dropdown.js +++ b/ui/app/components/send/from-dropdown.js @@ -1,7 +1,6 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits -const Identicon = require('../identicon') const AccountListItem = require('./account-list-item') module.exports = FromDropdown @@ -51,10 +50,8 @@ FromDropdown.prototype.renderDropdown = function () { FromDropdown.prototype.render = function () { const { - accounts, selectedAccount, openDropdown, - closeDropdown, dropdownOpen, } = this.props diff --git a/ui/app/components/send/gas-fee-display-v2.js b/ui/app/components/send/gas-fee-display-v2.js index 0e23b63ac..0b4377d29 100644 --- a/ui/app/components/send/gas-fee-display-v2.js +++ b/ui/app/components/send/gas-fee-display-v2.js @@ -23,7 +23,7 @@ GasFeeDisplay.prototype.render = function () { gasTotal ? h(CurrencyDisplay, { - primaryCurrency: 'ETH', + primaryCurrency, convertedCurrency, value: gasTotal, conversionRate, diff --git a/ui/app/components/send/memo-textarea.js b/ui/app/components/send/memo-textarea.js index 4005b9493..f5fe5e790 100644 --- a/ui/app/components/send/memo-textarea.js +++ b/ui/app/components/send/memo-textarea.js @@ -1,33 +1,33 @@ -const Component = require('react').Component -const h = require('react-hyperscript') -const inherits = require('util').inherits -const Identicon = require('../identicon') +// const Component = require('react').Component +// const h = require('react-hyperscript') +// const inherits = require('util').inherits +// const Identicon = require('../identicon') -module.exports = MemoTextArea +// module.exports = MemoTextArea -inherits(MemoTextArea, Component) -function MemoTextArea () { - Component.call(this) -} +// inherits(MemoTextArea, Component) +// function MemoTextArea () { +// Component.call(this) +// } -MemoTextArea.prototype.render = function () { - const { memo, identities, onChange } = this.props +// MemoTextArea.prototype.render = function () { +// const { memo, identities, onChange } = this.props - return h('div.send-v2__memo-text-area', [ +// return h('div.send-v2__memo-text-area', [ - h('textarea.send-v2__memo-text-area__input', { - placeholder: 'Optional', - value: memo, - onChange, - // onBlur: () => { - // this.setErrorsFor('memo') - // }, - onFocus: event => { - // this.clearErrorsFor('memo') - }, - }), +// h('textarea.send-v2__memo-text-area__input', { +// placeholder: 'Optional', +// value: memo, +// onChange, +// // onBlur: () => { +// // this.setErrorsFor('memo') +// // }, +// onFocus: event => { +// // this.clearErrorsFor('memo') +// }, +// }), - ]) +// ]) -} +// } diff --git a/ui/app/components/send/send-constants.js b/ui/app/components/send/send-constants.js index 471e01e2a..0a4f85bc9 100644 --- a/ui/app/components/send/send-constants.js +++ b/ui/app/components/send/send-constants.js @@ -1,5 +1,4 @@ const ethUtil = require('ethereumjs-util') -const Identicon = require('../identicon') const { conversionUtil, multiplyCurrencies } = require('../../conversion-util') const MIN_GAS_PRICE_HEX = (100000000).toString(16) diff --git a/ui/app/components/send/send-utils.js b/ui/app/components/send/send-utils.js index bf096d610..2def62842 100644 --- a/ui/app/components/send/send-utils.js +++ b/ui/app/components/send/send-utils.js @@ -27,7 +27,6 @@ function isBalanceSufficient({ fromNumericBase: 'hex', conversionRate: amountConversionRate, fromCurrency: selectedToken || primaryCurrency, - conversionRate: amountConversionRate, }, ) diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js index fb2634de2..efdf69795 100644 --- a/ui/app/components/send/send-v2-container.js +++ b/ui/app/components/send/send-v2-container.js @@ -3,17 +3,12 @@ const actions = require('../../actions') const abi = require('ethereumjs-abi') const SendEther = require('../../send-v2') -const { multiplyCurrencies } = require('../../conversion-util') - const { accountsWithSendEtherInfoSelector, getCurrentAccountWithSendEtherInfo, conversionRateSelector, getSelectedToken, - getSelectedTokenExchangeRate, getSelectedAddress, - getGasPrice, - getGasLimit, getAddressBook, getSendFrom, getCurrentCurrency, @@ -26,7 +21,6 @@ function mapStateToProps (state) { const fromAccounts = accountsWithSendEtherInfoSelector(state) const selectedAddress = getSelectedAddress(state) const selectedToken = getSelectedToken(state) - const tokenExchangeRates = state.metamask.tokenExchangeRates const conversionRate = conversionRateSelector(state) let data; diff --git a/ui/app/components/send/to-autocomplete.js b/ui/app/components/send/to-autocomplete.js index ab490155b..ebc63a7c5 100644 --- a/ui/app/components/send/to-autocomplete.js +++ b/ui/app/components/send/to-autocomplete.js @@ -1,7 +1,6 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits -const Identicon = require('../identicon') const AccountListItem = require('./account-list-item') module.exports = ToAutoComplete @@ -23,7 +22,6 @@ ToAutoComplete.prototype.getListItemIcon = function (listItemAddress, toAddress) ToAutoComplete.prototype.renderDropdown = function () { const { - accounts, closeDropdown, onChange, to, @@ -86,9 +84,6 @@ ToAutoComplete.prototype.componentDidUpdate = function (nextProps, nextState) { ToAutoComplete.prototype.render = function () { const { to, - accounts, - openDropdown, - closeDropdown, dropdownOpen, onChange, inError, diff --git a/ui/app/components/signature-request.js b/ui/app/components/signature-request.js index e617fdbd6..529449ff0 100644 --- a/ui/app/components/signature-request.js +++ b/ui/app/components/signature-request.js @@ -6,9 +6,7 @@ const connect = require('react-redux').connect const ethUtil = require('ethereumjs-util') const classnames = require('classnames') -const PendingTxDetails = require('./pending-personal-msg-details') const AccountDropdownMini = require('./dropdowns/account-dropdown-mini') -const BinaryRenderer = require('./binary-renderer') const actions = require('../actions') const { conversionUtil } = require('../conversion-util') @@ -135,8 +133,6 @@ SignatureRequest.prototype.renderRequestIcon = function () { } SignatureRequest.prototype.renderRequestInfo = function () { - const { requester } = this.props - return h('div.request-signature__request-info', [ h('div.request-signature__headline', [ @@ -206,7 +202,6 @@ SignatureRequest.prototype.renderBody = function () { SignatureRequest.prototype.renderFooter = function () { const { - goHome, signPersonalMessage, signTypedMessage, cancelPersonalMessage, diff --git a/ui/app/components/tab-bar.js b/ui/app/components/tab-bar.js index fe4076ed0..0edced119 100644 --- a/ui/app/components/tab-bar.js +++ b/ui/app/components/tab-bar.js @@ -1,5 +1,6 @@ const { Component } = require('react') const h = require('react-hyperscript') +const PropTypes = require('react').PropTypes const classnames = require('classnames') class TabBar extends Component { @@ -37,4 +38,10 @@ class TabBar extends Component { } } +TabBar.propTypes = { + defaultTab: PropTypes.string, + tabs: PropTypes.array, + tabSelected: PropTypes.func, +} + module.exports = TabBar diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js index 4959f1cd5..b6a27fd5a 100644 --- a/ui/app/components/token-list.js +++ b/ui/app/components/token-list.js @@ -3,7 +3,6 @@ const h = require('react-hyperscript') 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') @@ -38,6 +37,7 @@ function TokenList () { } TokenList.prototype.render = function () { + const { userAddress } = this.props const state = this.state const { tokens, isLoading, error } = state @@ -162,15 +162,15 @@ TokenList.prototype.componentWillUnmount = function () { this.tracker.stop() } -function uniqueMergeTokens (tokensA, tokensB = []) { - const uniqueAddresses = [] - const result = [] - tokensA.concat(tokensB).forEach((token) => { - const normal = normalizeAddress(token.address) - if (!uniqueAddresses.includes(normal)) { - uniqueAddresses.push(normal) - result.push(token) - } - }) - return result -} +// function uniqueMergeTokens (tokensA, tokensB = []) { +// const uniqueAddresses = [] +// const result = [] +// tokensA.concat(tokensB).forEach((token) => { +// const normal = normalizeAddress(token.address) +// if (!uniqueAddresses.includes(normal)) { +// uniqueAddresses.push(normal) +// result.push(token) +// } +// }) +// return result +// } diff --git a/ui/app/components/transaction-list-item.js b/ui/app/components/transaction-list-item.js index 21f2b8236..255f0e5eb 100644 --- a/ui/app/components/transaction-list-item.js +++ b/ui/app/components/transaction-list-item.js @@ -142,7 +142,7 @@ function formatDate (date) { } function renderErrorOrWarning (transaction) { - const { status, err, warning } = transaction + const { status } = transaction // show rejected if (status === 'rejected') { @@ -151,31 +151,31 @@ function renderErrorOrWarning (transaction) { if (transaction.err || transaction.warning) { const { err, warning = {} } = transaction const errFirst = !!((err && warning) || err) - const message = errFirst ? err.message : warning.message errFirst ? err.message : warning.message - // show error - if (err) { - const message = err.message || '' - return ( - h(Tooltip, { - title: message, - position: 'bottom', - }, [ - h(`span.error`, ` (Failed)`), - ]) - ) - } - - // show warning - if (warning) { - const message = warning.message - return h(Tooltip, { - title: message, - position: 'bottom', - }, [ - h(`span.warning`, ` (Warning)`), - ]) + // show error + if (err) { + const message = err.message || '' + return ( + h(Tooltip, { + title: message, + position: 'bottom', + }, [ + h(`span.error`, ` (Failed)`), + ]) + ) + } + + // show warning + if (warning) { + const message = warning.message + return h(Tooltip, { + title: message, + position: 'bottom', + }, [ + h(`span.warning`, ` (Warning)`), + ]) + } } } diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index a59b6509b..ac7944ba2 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -6,7 +6,6 @@ const classnames = require('classnames') const abi = require('human-standard-token-abi') const abiDecoder = require('abi-decoder') abiDecoder.addABI(abi) -const prefixForNetwork = require('../../lib/etherscan-prefix-for-network') const Identicon = require('./identicon') const contractMap = require('eth-contract-metadata') @@ -127,7 +126,6 @@ TxListItem.prototype.getTokenInfo = async function () { TxListItem.prototype.getSendTokenTotal = async function () { const { txParams = {}, - tokens, conversionRate, tokenExchangeRates, currentCurrency, diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 2f6c1fee8..6ea8776af 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -6,7 +6,7 @@ const prefixForNetwork = require('../../lib/etherscan-prefix-for-network') const selectors = require('../selectors') const TxListItem = require('./tx-list-item') const ShiftListItem = require('./shift-list-item') -const { formatBalance, formatDate } = require('../util') +const { formatDate } = require('../util') const { showConfTxPage } = require('../actions') const classnames = require('classnames') const { tokenInfoGetter } = require('../token-util') @@ -36,9 +36,6 @@ TxList.prototype.componentWillMount = function () { } TxList.prototype.render = function () { - - const { txsToRender, showConfTxPage } = this.props - return h('div.flex-column.tx-list-container', {}, [ h('div.flex-row.tx-list-header-wrapper', [ @@ -98,7 +95,6 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa txParams: transaction.txParams, transactionStatus, transActionId, - key: transActionId, dateString, address, transactionAmount, -- cgit v1.2.3 From 56e9f98bd05de8ae26f653d15eec4304f0c72155 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 2 Nov 2017 09:45:59 -0230 Subject: More lint fixes --- .../customize-gas-modal/gas-modal-card.js | 6 ++--- .../components/customize-gas-modal/gas-slider.js | 4 ++-- ui/app/components/customize-gas-modal/index.js | 16 ++++++------- .../components/dropdowns/account-dropdown-mini.js | 10 ++++---- ui/app/components/dropdowns/token-menu-dropdown.js | 6 ++--- ui/app/components/modals/modal.js | 2 +- .../modals/shapeshift-deposit-tx-modal.js | 2 +- ui/app/components/network.js | 2 +- ui/app/components/pending-tx/confirm-send-token.js | 2 +- ui/app/components/send-token/index.js | 8 +++---- ui/app/components/send/account-list-item.js | 2 +- ui/app/components/send/currency-display.js | 10 ++++---- ui/app/components/send/eth-fee-display.js | 4 ++-- ui/app/components/send/from-dropdown.js | 10 ++++---- ui/app/components/send/gas-fee-display-v2.js | 5 ++-- ui/app/components/send/memo-textarea.js | 2 +- ui/app/components/send/send-utils.js | 4 ++-- ui/app/components/send/send-v2-container.js | 8 +++---- ui/app/components/send/to-autocomplete.js | 13 +++++----- ui/app/components/send/usd-fee-display.js | 4 ++-- ui/app/components/signature-request.js | 28 ++++++++++------------ ui/app/components/token-cell.js | 12 +++++----- ui/app/components/tx-list-item.js | 6 ++--- ui/app/components/tx-list.js | 4 ++-- 24 files changed, 81 insertions(+), 89 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/customize-gas-modal/gas-modal-card.js b/ui/app/components/customize-gas-modal/gas-modal-card.js index 0172d8afb..23754d819 100644 --- a/ui/app/components/customize-gas-modal/gas-modal-card.js +++ b/ui/app/components/customize-gas-modal/gas-modal-card.js @@ -21,7 +21,7 @@ GasModalCard.prototype.render = function () { // max, step, title, - copy + copy, } = this.props return h('div.send-v2__gas-modal-card', [ @@ -47,8 +47,8 @@ GasModalCard.prototype.render = function () { // min, // onChange, // }), - + ]) - + } diff --git a/ui/app/components/customize-gas-modal/gas-slider.js b/ui/app/components/customize-gas-modal/gas-slider.js index 7a9636094..69fd6f985 100644 --- a/ui/app/components/customize-gas-modal/gas-slider.js +++ b/ui/app/components/customize-gas-modal/gas-slider.js @@ -43,8 +43,8 @@ // h('div.gas-slider__high'), // ]), - + // ]) - + // } diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 4bd9d079a..101a19d9f 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -58,7 +58,7 @@ function mapDispatchToProps (dispatch) { } } -function getOriginalState(props) { +function getOriginalState (props) { const gasPrice = props.gasPrice || MIN_GAS_PRICE_DEC const gasLimit = props.gasLimit || MIN_GAS_LIMIT_DEC @@ -90,7 +90,7 @@ CustomizeGasModal.prototype.save = function (gasPrice, gasLimit, gasTotal) { updateGasPrice, updateGasLimit, hideModal, - updateGasTotal + updateGasTotal, } = this.props updateGasPrice(gasPrice) @@ -126,9 +126,9 @@ CustomizeGasModal.prototype.validate = function ({ gasTotal, gasLimit }) { }) if (!balanceIsSufficient) { - error = 'Insufficient balance for current gas total' + error = 'Insufficient balance for current gas total' } - + const gasLimitTooLow = gasLimit && conversionGreaterThan( { value: MIN_GAS_LIMIT_DEC, @@ -142,7 +142,7 @@ CustomizeGasModal.prototype.validate = function ({ gasTotal, gasLimit }) { ) if (gasLimitTooLow) { - error = 'Gas limit must be at least 21000' + error = 'Gas limit must be at least 21000' } this.setState({ error }) @@ -219,7 +219,7 @@ CustomizeGasModal.prototype.render = function () { ]), h('div.send-v2__customize-gas__body', {}, [ - + h(GasModalCard, { value: convertedGasPrice, min: MIN_GAS_PRICE_GWEI, @@ -247,7 +247,7 @@ CustomizeGasModal.prototype.render = function () { error && h('div.send-v2__customize-gas__error-message', [ error, ]), - + h('div.send-v2__customize-gas__revert', { onClick: () => this.revert(), }, ['Revert']), @@ -260,7 +260,7 @@ CustomizeGasModal.prototype.render = function () { h(`div.send-v2__customize-gas__save${error ? '__error' : ''}`, { onClick: () => !error && this.save(gasPrice, gasLimit, gasTotal), }, ['SAVE']), - ]) + ]), ]), diff --git a/ui/app/components/dropdowns/account-dropdown-mini.js b/ui/app/components/dropdowns/account-dropdown-mini.js index f403c56b9..a3d41af90 100644 --- a/ui/app/components/dropdowns/account-dropdown-mini.js +++ b/ui/app/components/dropdowns/account-dropdown-mini.js @@ -37,13 +37,13 @@ AccountDropdownMini.prototype.renderDropdown = function () { ...accounts.map(account => h(AccountListItem, { account, displayBalance: false, - displayAddress: false, + displayAddress: false, handleClick: () => { onSelect(account) closeDropdown() - }, + }, icon: this.getListItemIcon(account, selectedAccount), - })) + })), ]), @@ -64,12 +64,12 @@ AccountDropdownMini.prototype.render = function () { handleClick: openDropdown, displayBalance: false, displayAddress: false, - icon: h(`i.fa.fa-caret-down.fa-lg`, { style: { color: '#dedede' } }) + icon: h(`i.fa.fa-caret-down.fa-lg`, { style: { color: '#dedede' } }), }), dropdownOpen && this.renderDropdown(), ]) - + } diff --git a/ui/app/components/dropdowns/token-menu-dropdown.js b/ui/app/components/dropdowns/token-menu-dropdown.js index 7234a9b21..dc7a985e3 100644 --- a/ui/app/components/dropdowns/token-menu-dropdown.js +++ b/ui/app/components/dropdowns/token-menu-dropdown.js @@ -10,7 +10,7 @@ function mapDispatchToProps (dispatch) { return { showHideTokenConfirmationModal: (token) => { dispatch(actions.showModal({ name: 'HIDE_TOKEN_CONFIRMATION', token })) - } + }, } } @@ -36,14 +36,14 @@ TokenMenuDropdown.prototype.render = function () { }), h('div.token-menu-dropdown__container', {}, [ h('div.token-menu-dropdown__options', {}, [ - + h('div.token-menu-dropdown__option', { onClick: (e) => { e.stopPropagation() showHideTokenConfirmationModal(this.props.token) this.props.onClose() }, - }, 'Hide Token') + }, 'Hide Token'), ]), ]), diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index e15dd6c1b..842081f40 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -220,7 +220,7 @@ Modal.prototype.render = function () { const children = modal.contents const modalStyle = modal[isMobileView() ? 'mobileModalStyle' : 'laptopModalStyle'] - const contentStyle = modal.contentStyle || {}; + const contentStyle = modal.contentStyle || {} return h(FadeModal, { diff --git a/ui/app/components/modals/shapeshift-deposit-tx-modal.js b/ui/app/components/modals/shapeshift-deposit-tx-modal.js index 1fd1ade00..24af5a0de 100644 --- a/ui/app/components/modals/shapeshift-deposit-tx-modal.js +++ b/ui/app/components/modals/shapeshift-deposit-tx-modal.js @@ -35,6 +35,6 @@ ShapeshiftDepositTxModal.prototype.render = function () { }, [ h('div', {}, [ h(QrView, {key: 'qr', Qr}), - ]) + ]), ]) } diff --git a/ui/app/components/network.js b/ui/app/components/network.js index 229d02e36..915818009 100644 --- a/ui/app/components/network.js +++ b/ui/app/components/network.js @@ -1,6 +1,6 @@ const Component = require('react').Component const h = require('react-hyperscript') -const classnames = require('classnames'); +const classnames = require('classnames') const inherits = require('util').inherits const NetworkDropdownIcon = require('./dropdowns/components/network-dropdown-icon') diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index 4a57553d7..3b8ae7f7f 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -144,7 +144,7 @@ ConfirmSendToken.prototype.getData = function () { const { value } = params[0] || {} const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} - + return { from: { address: txParams.from, diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index c5c7a0b46..99d078251 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -148,11 +148,11 @@ SendTokenScreen.prototype.setErrorsFor = function (field) { const { isValid, - errors: newErrors + errors: newErrors, } = this.validate() const nextErrors = Object.assign({}, previousErrors, { - [field]: newErrors[field] || null + [field]: newErrors[field] || null, }) if (!isValid) { @@ -166,7 +166,7 @@ SendTokenScreen.prototype.setErrorsFor = function (field) { SendTokenScreen.prototype.clearErrorsFor = function (field) { const { errors: previousErrors } = this.state const nextErrors = Object.assign({}, previousErrors, { - [field]: null + [field]: null, }) this.setState({ @@ -428,7 +428,7 @@ SendTokenScreen.prototype.render = function () { this.renderAmountInput(), this.renderGasInput(), this.renderMemoInput(), - warning && h('div.send-screen-input-wrapper--error', {}, + warning && h('div.send-screen-input-wrapper--error', {}, h('div.send-screen-input-wrapper__error-message', [ warning, ]) diff --git a/ui/app/components/send/account-list-item.js b/ui/app/components/send/account-list-item.js index cc514cbd4..2378a4671 100644 --- a/ui/app/components/send/account-list-item.js +++ b/ui/app/components/send/account-list-item.js @@ -68,4 +68,4 @@ AccountListItem.prototype.render = function () { }, name), ]) -} \ No newline at end of file +} diff --git a/ui/app/components/send/currency-display.js b/ui/app/components/send/currency-display.js index 34939c767..45986e371 100644 --- a/ui/app/components/send/currency-display.js +++ b/ui/app/components/send/currency-display.js @@ -71,7 +71,7 @@ CurrencyDisplay.prototype.render = function () { conversionRate, }) - const inputSizeMultiplier = readOnly ? 1 : 1.2; + const inputSizeMultiplier = readOnly ? 1 : 1.2 return h('div', { className, @@ -95,15 +95,13 @@ CurrencyDisplay.prototype.render = function () { if (newValue === '') { newValue = '0' - } - else if (newValue.match(/^0[1-9]$/)) { + } else if (newValue.match(/^0[1-9]$/)) { newValue = newValue.match(/[1-9]/)[0] } if (newValue && !isValidInput(newValue)) { event.preventDefault() - } - else { + } else { validate(this.getAmount(newValue)) this.setState({ value: newValue }) } @@ -122,6 +120,6 @@ CurrencyDisplay.prototype.render = function () { }, `${convertedValue} ${convertedCurrency.toUpperCase()}`), ]) - + } diff --git a/ui/app/components/send/eth-fee-display.js b/ui/app/components/send/eth-fee-display.js index 8b4cec16c..9eda5ec62 100644 --- a/ui/app/components/send/eth-fee-display.js +++ b/ui/app/components/send/eth-fee-display.js @@ -30,8 +30,8 @@ EthFeeDisplay.prototype.render = function () { color: '#5d5d5d', fontSize: '16px', fontFamily: 'DIN OT', - lineHeight: '22.4px' - } + lineHeight: '22.4px', + }, }) } diff --git a/ui/app/components/send/from-dropdown.js b/ui/app/components/send/from-dropdown.js index b404dde14..bcae5ede8 100644 --- a/ui/app/components/send/from-dropdown.js +++ b/ui/app/components/send/from-dropdown.js @@ -35,13 +35,13 @@ FromDropdown.prototype.renderDropdown = function () { h('div.send-v2__from-dropdown__list', {}, [ ...accounts.map(account => h(AccountListItem, { - account, + account, handleClick: () => { onSelect(account) closeDropdown() - }, + }, icon: this.getListItemIcon(account, selectedAccount), - })) + })), ]), @@ -60,12 +60,12 @@ FromDropdown.prototype.render = function () { h(AccountListItem, { account: selectedAccount, handleClick: openDropdown, - icon: h(`i.fa.fa-caret-down.fa-lg`, { style: { color: '#dedede' } }) + icon: h(`i.fa.fa-caret-down.fa-lg`, { style: { color: '#dedede' } }), }), dropdownOpen && this.renderDropdown(), ]) - + } diff --git a/ui/app/components/send/gas-fee-display-v2.js b/ui/app/components/send/gas-fee-display-v2.js index 0b4377d29..806c33f0a 100644 --- a/ui/app/components/send/gas-fee-display-v2.js +++ b/ui/app/components/send/gas-fee-display-v2.js @@ -30,14 +30,13 @@ GasFeeDisplay.prototype.render = function () { convertedPrefix: '$', readOnly: true, }) - : h('div.currency-display', 'Loading...') - , + : h('div.currency-display', 'Loading...'), h('div.send-v2__sliders-icon-container', { onClick, }, [ h('i.fa.fa-sliders.send-v2__sliders-icon'), - ]) + ]), ]) } diff --git a/ui/app/components/send/memo-textarea.js b/ui/app/components/send/memo-textarea.js index f5fe5e790..f4bb24bf8 100644 --- a/ui/app/components/send/memo-textarea.js +++ b/ui/app/components/send/memo-textarea.js @@ -28,6 +28,6 @@ // }), // ]) - + // } diff --git a/ui/app/components/send/send-utils.js b/ui/app/components/send/send-utils.js index 2def62842..6ec04a223 100644 --- a/ui/app/components/send/send-utils.js +++ b/ui/app/components/send/send-utils.js @@ -1,6 +1,6 @@ const { addCurrencies, conversionGreaterThan } = require('../../conversion-util') -function isBalanceSufficient({ +function isBalanceSufficient ({ amount, gasTotal, balance, @@ -35,4 +35,4 @@ function isBalanceSufficient({ module.exports = { isBalanceSufficient, -} \ No newline at end of file +} diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js index efdf69795..5a6e83ae6 100644 --- a/ui/app/components/send/send-v2-container.js +++ b/ui/app/components/send/send-v2-container.js @@ -23,9 +23,9 @@ function mapStateToProps (state) { const selectedToken = getSelectedToken(state) const conversionRate = conversionRateSelector(state) - let data; - let primaryCurrency; - let tokenToFiatRate; + let data + let primaryCurrency + let tokenToFiatRate if (selectedToken) { data = Array.prototype.map.call( abi.rawEncode(['address', 'uint256'], [selectedAddress, '0x0']), @@ -70,6 +70,6 @@ function mapDispatchToProps (dispatch) { updateSendMemo: newMemo => dispatch(actions.updateSendMemo(newMemo)), updateSendErrors: newError => dispatch(actions.updateSendErrors(newError)), goHome: () => dispatch(actions.goHome()), - clearSend: () => dispatch(actions.clearSend()) + clearSend: () => dispatch(actions.clearSend()), } } diff --git a/ui/app/components/send/to-autocomplete.js b/ui/app/components/send/to-autocomplete.js index ebc63a7c5..df43fcc4a 100644 --- a/ui/app/components/send/to-autocomplete.js +++ b/ui/app/components/send/to-autocomplete.js @@ -37,15 +37,15 @@ ToAutoComplete.prototype.renderDropdown = function () { h('div.send-v2__from-dropdown__list', {}, [ ...accountsToRender.map(account => h(AccountListItem, { - account, + account, handleClick: () => { onChange(account.address) closeDropdown() - }, + }, icon: this.getListItemIcon(account.address, to), displayBalance: false, displayAddress: true, - })) + })), ]), @@ -67,8 +67,7 @@ ToAutoComplete.prototype.handleInputEvent = function (event = {}, cb) { this.setState({ accountsToRender: [] }) event.target && event.target.select() closeDropdown() - } - else { + } else { this.setState({ accountsToRender: matchingAccounts }) openDropdown() } @@ -93,13 +92,13 @@ ToAutoComplete.prototype.render = function () { h('input.send-v2__to-autocomplete__input', { placeholder: 'Recipient Address', - className: inError ? `send-v2__error-border` : '', + className: inError ? `send-v2__error-border` : '', value: to, onChange: event => onChange(event.target.value), onFocus: event => this.handleInputEvent(event), style: { borderColor: inError ? 'red' : null, - } + }, }), !to && h(`i.fa.fa-caret-down.fa-lg.send-v2__to-autocomplete__down-caret`, { diff --git a/ui/app/components/send/usd-fee-display.js b/ui/app/components/send/usd-fee-display.js index 6ee38f1b5..4cf31a493 100644 --- a/ui/app/components/send/usd-fee-display.js +++ b/ui/app/components/send/usd-fee-display.js @@ -28,8 +28,8 @@ USDFeeDisplay.prototype.render = function () { color: '#5d5d5d', fontSize: '16px', fontFamily: 'DIN OT', - lineHeight: '22.4px' - } + lineHeight: '22.4px', + }, }) } diff --git a/ui/app/components/signature-request.js b/ui/app/components/signature-request.js index 529449ff0..c5cc23aa8 100644 --- a/ui/app/components/signature-request.js +++ b/ui/app/components/signature-request.js @@ -27,13 +27,13 @@ function mapStateToProps (state) { requester: null, requesterAddress: null, accounts: accountsWithSendEtherInfoSelector(state), - conversionRate: conversionRateSelector(state) + conversionRate: conversionRateSelector(state), } } function mapDispatchToProps (dispatch) { return { - goHome: () => dispatch(actions.goHome()) + goHome: () => dispatch(actions.goHome()), } } @@ -84,7 +84,7 @@ SignatureRequest.prototype.renderAccountDropdown = function () { dropdownOpen: accountDropdownOpen, openDropdown: () => this.setState({ accountDropdownOpen: true }), closeDropdown: () => this.setState({ accountDropdownOpen: false }), - }) + }), ]) } @@ -113,7 +113,7 @@ SignatureRequest.prototype.renderAccountInfo = function () { return h('div.request-signature__account-info', [ this.renderAccountDropdown(), - + this.renderRequestIcon(), this.renderBalance(), @@ -128,7 +128,7 @@ SignatureRequest.prototype.renderRequestIcon = function () { h(Identicon, { diameter: 40, address: requesterAddress, - }) + }), ]) } @@ -137,7 +137,7 @@ SignatureRequest.prototype.renderRequestInfo = function () { h('div.request-signature__headline', [ `Your signature is being requested`, - ]) + ]), ]) } @@ -161,11 +161,9 @@ SignatureRequest.prototype.renderBody = function () { if (type === 'personal_sign') { rows = [{ name: 'Message', value: this.msgHexToText(data) }] - } - else if (type === 'eth_signTypedData') { + } else if (type === 'eth_signTypedData') { rows = data - } - else if (type === 'eth_sign') { + } else if (type === 'eth_sign') { rows = [{ name: 'Message', value: data }] notice = `Signing this message can have dangerous side effects. Only sign messages from @@ -183,14 +181,14 @@ SignatureRequest.prototype.renderBody = function () { className: classnames({ 'request-signature__notice': type === 'personal_sign' || type === 'eth_signTypedData', 'request-signature__warning': type === 'eth_sign', - }) + }), }, [notice]), h('div.request-signature__rows', [ ...rows.map(({ name, value }) => { return h('div.request-signature__row', [ - h('div.request-signature__row-title', [`${name}:`]), + h('div.request-signature__row-title', [`${name}:`]), h('div.request-signature__row-value', value), ]) }), @@ -218,12 +216,10 @@ SignatureRequest.prototype.renderFooter = function () { if (type === 'personal_sign') { cancel = cancelPersonalMessage sign = signPersonalMessage - } - else if (type === 'eth_signTypedData') { + } else if (type === 'eth_signTypedData') { cancel = cancelTypedMessage sign = signTypedMessage - } - else if (type === 'eth_sign') { + } else if (type === 'eth_sign') { cancel = cancelMessage sign = signMessage } diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index f55e23f9e..b40c0ec0d 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -67,11 +67,11 @@ TokenCell.prototype.render = function () { currentCurrency, // userAddress, } = props - - const pair = `${symbol.toLowerCase()}_eth`; - let currentTokenToFiatRate; - let currentTokenInFiat; + const pair = `${symbol.toLowerCase()}_eth` + + let currentTokenToFiatRate + let currentTokenInFiat let formattedFiat = '' if (tokenExchangeRates[pair]) { @@ -86,11 +86,11 @@ TokenCell.prototype.render = function () { numberOfDecimals: 2, conversionRate: currentTokenToFiatRate, }) - formattedFiat = `${currentTokenInFiat} ${currentCurrency.toUpperCase()}`; + formattedFiat = `${currentTokenInFiat} ${currentCurrency.toUpperCase()}` } const showFiat = Boolean(currentTokenInFiat) && currentCurrency.toUpperCase() !== symbol - + return ( h('div.token-list-item', { className: `token-list-item ${selectedTokenAddress === address ? 'token-list-item--active' : ''}`, diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index ac7944ba2..26de19f15 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -138,8 +138,8 @@ TxListItem.prototype.getSendTokenTotal = async function () { const multiplier = Math.pow(10, Number(decimals || 0)) const total = Number(value / multiplier) - const pair = symbol && `${symbol.toLowerCase()}_eth`; - + const pair = symbol && `${symbol.toLowerCase()}_eth` + let tokenToFiatRate let totalInFiat @@ -242,6 +242,6 @@ TxListItem.prototype.render = function () { ]), ]), - ]) // holding on icon from design + ]), // holding on icon from design ]) } diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 6ea8776af..70722f43e 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -22,7 +22,7 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { - showConfTxPage: ({ id }) => dispatch(showConfTxPage({ id })) + showConfTxPage: ({ id }) => dispatch(showConfTxPage({ id })), } } @@ -103,7 +103,7 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa tokenInfoGetter: this.tokenInfoGetter, } - const isUnapproved = transactionStatus === 'unapproved'; + const isUnapproved = transactionStatus === 'unapproved' if (isUnapproved) { opts.onClick = () => showConfTxPage({id: transActionId}) -- cgit v1.2.3 From dc0b3255cf908320b5b46f02765ea03b5b4db6b7 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 30 Oct 2017 20:09:27 -0230 Subject: Fixes width of from and to dropdowns in extension and on mobile views. --- ui/app/components/send/to-autocomplete.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send/to-autocomplete.js b/ui/app/components/send/to-autocomplete.js index ab490155b..fdb093baa 100644 --- a/ui/app/components/send/to-autocomplete.js +++ b/ui/app/components/send/to-autocomplete.js @@ -94,7 +94,7 @@ ToAutoComplete.prototype.render = function () { inError, } = this.props - return h('div.to-autocomplete', {}, [ + return h('div.send-v2__to-autocomplete', {}, [ h('input.send-v2__to-autocomplete__input', { placeholder: 'Recipient Address', -- cgit v1.2.3 From 67bdfe87e31e695f8c4beab1659a3a4b764ccf24 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 30 Oct 2017 15:18:50 -0230 Subject: Token balance in send state; validating sufficient tokens, validation updates on 'from' switching. --- ui/app/components/pending-tx/confirm-send-token.js | 6 ++- ui/app/components/send/send-utils.js | 43 +++++++++++++++++++--- ui/app/components/send/send-v2-container.js | 3 ++ ui/app/components/tx-list-item.js | 4 +- 4 files changed, 46 insertions(+), 10 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index 3b8ae7f7f..f14da38ef 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -15,6 +15,9 @@ const { multiplyCurrencies, addCurrencies, } = require('../../conversion-util') +const { + calcTokenAmount, +} = require('../../token-util') const { MIN_GAS_PRICE_HEX } = require('../send/send-constants') @@ -73,8 +76,7 @@ ConfirmSendToken.prototype.getAmount = function () { const { params = [] } = tokenData const { value } = params[1] || {} const { decimals } = token - const multiplier = Math.pow(10, Number(decimals || 0)) - const sendTokenAmount = Number(value / multiplier) + const sendTokenAmount = calcTokenAmount(value, decimals) return { fiat: tokenExchangeRate diff --git a/ui/app/components/send/send-utils.js b/ui/app/components/send/send-utils.js index 6ec04a223..4eb010173 100644 --- a/ui/app/components/send/send-utils.js +++ b/ui/app/components/send/send-utils.js @@ -1,11 +1,18 @@ -const { addCurrencies, conversionGreaterThan } = require('../../conversion-util') +const { + addCurrencies, + conversionGreaterThan, + conversionUtil, + conversionGTE, +} = require('../../conversion-util') +const { + calcTokenAmount, +} = require('../../token-util') -function isBalanceSufficient ({ - amount, - gasTotal, +function isBalanceSufficient({ + amount = '0x0', + gasTotal = '0x0', balance, primaryCurrency, - selectedToken, amountConversionRate, conversionRate, }) { @@ -26,13 +33,37 @@ function isBalanceSufficient ({ value: totalAmount, fromNumericBase: 'hex', conversionRate: amountConversionRate, - fromCurrency: selectedToken || primaryCurrency, + fromCurrency: primaryCurrency, }, ) return balanceIsSufficient } +function isTokenBalanceSufficient({ + amount = '0x0', + tokenBalance, + decimals, +}) { + const amountInDec = conversionUtil(amount, { + fromNumericBase: 'hex', + }) + + const tokenBalanceIsSufficient = conversionGTE( + { + value: tokenBalance, + fromNumericBase: 'dec', + }, + { + value: calcTokenAmount(amountInDec, decimals), + fromNumericBase: 'dec', + }, + ) + + return tokenBalanceIsSufficient +} + module.exports = { isBalanceSufficient, + isTokenBalanceSufficient, } diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js index 5a6e83ae6..ee18d0b4b 100644 --- a/ui/app/components/send/send-v2-container.js +++ b/ui/app/components/send/send-v2-container.js @@ -13,6 +13,7 @@ const { getSendFrom, getCurrentCurrency, getSelectedTokenToFiatRate, + getSelectedTokenContract, } = require('../../selectors') module.exports = connect(mapStateToProps, mapDispatchToProps)(SendEther) @@ -48,6 +49,7 @@ function mapStateToProps (state) { convertedCurrency: getCurrentCurrency(state), data, amountConversionRate: selectedToken ? tokenToFiatRate : conversionRate, + tokenContract: getSelectedTokenContract(state), } } @@ -64,6 +66,7 @@ function mapDispatchToProps (dispatch) { setSelectedAddress: address => dispatch(actions.setSelectedAddress(address)), addToAddressBook: address => dispatch(actions.addToAddressBook(address)), updateGasTotal: newTotal => dispatch(actions.updateGasTotal(newTotal)), + updateSendTokenBalance: tokenBalance => dispatch(actions.updateSendTokenBalance(tokenBalance)), updateSendFrom: newFrom => dispatch(actions.updateSendFrom(newFrom)), updateSendTo: newTo => dispatch(actions.updateSendTo(newTo)), updateSendAmount: newAmount => dispatch(actions.updateSendAmount(newAmount)), diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 26de19f15..4e76147a1 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -10,6 +10,7 @@ const Identicon = require('./identicon') const contractMap = require('eth-contract-metadata') const { conversionUtil, multiplyCurrencies } = require('../conversion-util') +const { calcTokenAmount } = require('../token-util') const { getCurrentCurrency } = require('../selectors') @@ -135,8 +136,7 @@ TxListItem.prototype.getSendTokenTotal = async function () { const { params = [] } = decodedData || {} const { value } = params[1] || {} const { decimals, symbol } = await this.getTokenInfo() - const multiplier = Math.pow(10, Number(decimals || 0)) - const total = Number(value / multiplier) + const total = calcTokenAmount(value, decimals) const pair = symbol && `${symbol.toLowerCase()}_eth` -- cgit v1.2.3 From 319779ab081f70343b5ef77531450878292a90d6 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 26 Oct 2017 14:13:12 -0230 Subject: Adds max amount feature for send-ether --- ui/app/components/send/send-utils.js | 2 +- ui/app/components/send/send-v2-container.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send/send-utils.js b/ui/app/components/send/send-utils.js index 4eb010173..0260c38a6 100644 --- a/ui/app/components/send/send-utils.js +++ b/ui/app/components/send/send-utils.js @@ -22,7 +22,7 @@ function isBalanceSufficient({ toNumericBase: 'hex', }) - const balanceIsSufficient = conversionGreaterThan( + const balanceIsSufficient = conversionGTE( { value: balance, fromNumericBase: 'hex', diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js index ee18d0b4b..51d5c4f89 100644 --- a/ui/app/components/send/send-v2-container.js +++ b/ui/app/components/send/send-v2-container.js @@ -66,6 +66,8 @@ function mapDispatchToProps (dispatch) { setSelectedAddress: address => dispatch(actions.setSelectedAddress(address)), addToAddressBook: address => dispatch(actions.addToAddressBook(address)), updateGasTotal: newTotal => dispatch(actions.updateGasTotal(newTotal)), + updateGasPrice: newGasPrice => dispatch(actions.updateGasPrice(newGasPrice)), + updateGasLimit: newGasLimit => dispatch(actions.updateGasLimit(newGasLimit)), updateSendTokenBalance: tokenBalance => dispatch(actions.updateSendTokenBalance(tokenBalance)), updateSendFrom: newFrom => dispatch(actions.updateSendFrom(newFrom)), updateSendTo: newTo => dispatch(actions.updateSendTo(newTo)), -- cgit v1.2.3 From b16946723f94b855ab70469dca5899ad80f129b3 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 30 Oct 2017 16:11:05 -0230 Subject: Insufficient balance warning in gas customizer works for send token --- ui/app/components/customize-gas-modal/index.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 101a19d9f..5bd6c54cb 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -107,19 +107,17 @@ CustomizeGasModal.prototype.validate = function ({ gasTotal, gasLimit }) { const { amount, balance, - primaryCurrency, selectedToken, amountConversionRate, conversionRate, } = this.props let error = null - + const balanceIsSufficient = isBalanceSufficient({ amount, gasTotal, balance, - primaryCurrency, selectedToken, amountConversionRate, conversionRate, -- cgit v1.2.3 From 716bbf67d7180ffe0f59d07484d30231ed5f5e49 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 30 Oct 2017 19:16:56 -0230 Subject: Set gas price allows for WEI precision. --- ui/app/components/customize-gas-modal/index.js | 20 ++++++++++++++++---- ui/app/components/input-number.js | 17 ++++++++++++----- ui/app/components/send/send-constants.js | 1 + 3 files changed, 29 insertions(+), 9 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 5bd6c54cb..dcb058690 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -73,6 +73,8 @@ function getOriginalState (props) { gasLimit, gasTotal, error: null, + priceSigZeros: '', + priceSigDec: '', } } @@ -167,7 +169,15 @@ CustomizeGasModal.prototype.convertAndSetGasLimit = function (newGasLimit) { } CustomizeGasModal.prototype.convertAndSetGasPrice = function (newGasPrice) { - const { gasLimit } = this.state + const { gasLimit, priceSigZeros } = this.state + const priceStrLength = newGasPrice.length + const sigZeros = String(newGasPrice).match(/^\d+[.]\d*?(0+)$/) + const sigDec = String(newGasPrice).match(/^\d+([.])0*$/) + + this.setState({ + priceSigZeros: sigZeros && sigZeros[1] || '', + priceSigDec: sigDec && sigDec[1] || '', + }) const gasPrice = conversionUtil(newGasPrice, { fromNumericBase: 'dec', @@ -189,15 +199,17 @@ CustomizeGasModal.prototype.convertAndSetGasPrice = function (newGasPrice) { CustomizeGasModal.prototype.render = function () { const { hideModal } = this.props - const { gasPrice, gasLimit, gasTotal, error } = this.state + const { gasPrice, gasLimit, gasTotal, error, priceSigZeros, priceSigDec } = this.state - const convertedGasPrice = conversionUtil(gasPrice, { + let convertedGasPrice = conversionUtil(gasPrice, { fromNumericBase: 'hex', toNumericBase: 'dec', fromDenomination: 'WEI', toDenomination: 'GWEI', }) + convertedGasPrice += convertedGasPrice.match(/[.]/) ? priceSigZeros : `${priceSigDec}${priceSigZeros}` + const convertedGasLimit = conversionUtil(gasLimit, { fromNumericBase: 'hex', toNumericBase: 'dec', @@ -222,7 +234,7 @@ CustomizeGasModal.prototype.render = function () { value: convertedGasPrice, min: MIN_GAS_PRICE_GWEI, // max: 1000, - step: MIN_GAS_PRICE_GWEI, + step: multiplyCurrencies(MIN_GAS_PRICE_GWEI, 10), onChange: value => this.convertAndSetGasPrice(value), title: 'Gas Price (GWEI)', copy: 'We calculate the suggested gas prices based on network success rates.', diff --git a/ui/app/components/input-number.js b/ui/app/components/input-number.js index e28807c13..da4d739aa 100644 --- a/ui/app/components/input-number.js +++ b/ui/app/components/input-number.js @@ -5,6 +5,7 @@ const { addCurrencies, conversionGTE, conversionLTE, + subtractCurrencies, toNegative, } = require('../conversion-util') @@ -17,18 +18,24 @@ function InputNumber () { this.setValue = this.setValue.bind(this) } +function isValidInput (text) { + const re = /^([1-9]\d*|0)(\.|\.\d*)?$/ + return re.test(text) +} + InputNumber.prototype.setValue = function (newValue) { + if (newValue && !isValidInput(newValue)) return const { fixed, min = -1, max = Infinity, onChange } = this.props - newValue = Number(fixed ? newValue.toFixed(4) : newValue) + newValue = fixed ? newValue.toFixed(4) : newValue const newValueGreaterThanMin = conversionGTE( - { value: newValue, fromNumericBase: 'dec' }, + { value: newValue || '0', fromNumericBase: 'dec' }, { value: min, fromNumericBase: 'hex' }, ) const newValueLessThanMax = conversionLTE( - { value: newValue, fromNumericBase: 'dec' }, + { value: newValue || '0', fromNumericBase: 'dec' }, { value: max, fromNumericBase: 'hex' }, ) if (newValueGreaterThanMin && newValueLessThanMax) { @@ -46,8 +53,8 @@ InputNumber.prototype.render = function () { return h('div.customize-gas-input-wrapper', {}, [ h('input.customize-gas-input', { placeholder, - type: 'number', value, + step, onChange: (e) => this.setValue(e.target.value), }), h('span.gas-tooltip-input-detail', {}, [unitLabel]), @@ -57,7 +64,7 @@ InputNumber.prototype.render = function () { }), h('i.fa.fa-angle-down', { style: { cursor: 'pointer' }, - onClick: () => this.setValue(addCurrencies(value, toNegative(step))), + onClick: () => this.setValue(subtractCurrencies(value, step)), }), ]), ]) diff --git a/ui/app/components/send/send-constants.js b/ui/app/components/send/send-constants.js index 0a4f85bc9..a961ffcd8 100644 --- a/ui/app/components/send/send-constants.js +++ b/ui/app/components/send/send-constants.js @@ -11,6 +11,7 @@ const MIN_GAS_PRICE_GWEI = ethUtil.addHexPrefix(conversionUtil(MIN_GAS_PRICE_HEX toDenomination: 'GWEI', fromNumericBase: 'hex', toNumericBase: 'hex', + numberOfDecimals: 1, })) const MIN_GAS_TOTAL = multiplyCurrencies(MIN_GAS_LIMIT_HEX, MIN_GAS_PRICE_HEX, { -- cgit v1.2.3 From 8c6e1232e417f5a2974b5aa1cc479dac4925df63 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 6 Nov 2017 16:14:46 -0330 Subject: Lint fixes. --- ui/app/components/customize-gas-modal/index.js | 3 +-- ui/app/components/input-number.js | 1 - ui/app/components/send/send-utils.js | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index dcb058690..b77e1990f 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -169,8 +169,7 @@ CustomizeGasModal.prototype.convertAndSetGasLimit = function (newGasLimit) { } CustomizeGasModal.prototype.convertAndSetGasPrice = function (newGasPrice) { - const { gasLimit, priceSigZeros } = this.state - const priceStrLength = newGasPrice.length + const { gasLimit } = this.state const sigZeros = String(newGasPrice).match(/^\d+[.]\d*?(0+)$/) const sigDec = String(newGasPrice).match(/^\d+([.])0*$/) diff --git a/ui/app/components/input-number.js b/ui/app/components/input-number.js index da4d739aa..12dec2957 100644 --- a/ui/app/components/input-number.js +++ b/ui/app/components/input-number.js @@ -6,7 +6,6 @@ const { conversionGTE, conversionLTE, subtractCurrencies, - toNegative, } = require('../conversion-util') module.exports = InputNumber diff --git a/ui/app/components/send/send-utils.js b/ui/app/components/send/send-utils.js index 0260c38a6..bd1197950 100644 --- a/ui/app/components/send/send-utils.js +++ b/ui/app/components/send/send-utils.js @@ -1,6 +1,5 @@ const { addCurrencies, - conversionGreaterThan, conversionUtil, conversionGTE, } = require('../../conversion-util') -- cgit v1.2.3 From c57d504794b6020d42dcdabe08a13ed412450fc1 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 7 Nov 2017 20:06:26 -0330 Subject: Add currency-input component to correct send amount behaviour and move currency display value state to parent component. --- ui/app/components/currency-input.js | 93 ++++++++++++++++++++++++++++++ ui/app/components/send/currency-display.js | 36 +++--------- 2 files changed, 101 insertions(+), 28 deletions(-) create mode 100644 ui/app/components/currency-input.js (limited to 'ui/app/components') diff --git a/ui/app/components/currency-input.js b/ui/app/components/currency-input.js new file mode 100644 index 000000000..5e534d87b --- /dev/null +++ b/ui/app/components/currency-input.js @@ -0,0 +1,93 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits + +module.exports = CurrencyInput + +inherits(CurrencyInput, Component) +function CurrencyInput (props) { + Component.call(this) + + this.state = { + value: sanitizeValue(props.value), + } +} + +function removeNonDigits (str) { + return str.match(/\d|$/g).join('') +} + +// Removes characters that are not digits, then removes leading zeros +function sanitizeInteger (val) { + return String(parseInt(removeNonDigits(val) || '0', 10)) +} + +function sanitizeDecimal (val) { + return removeNonDigits(val) +} + +// Take a single string param and returns a non-negative integer or float as a string. +// Breaks the input into three parts: the integer, the decimal point, and the decimal/fractional part. +// Removes leading zeros from the integer, and non-digits from the integer and decimal +// The integer is returned as '0' in cases where it would be empty. A decimal point is +// included in the returned string if one is included in the param +// Examples: +// sanitizeValue('0') -> '0' +// sanitizeValue('a') -> '0' +// sanitizeValue('010.') -> '10.' +// sanitizeValue('0.005') -> '0.005' +// sanitizeValue('22.200') -> '22.200' +// sanitizeValue('.200') -> '0.200' +// sanitizeValue('a.b.1.c,89.123') -> '0.189123' +function sanitizeValue (value) { + let [,integer, point, decimal] = (/([^.]*)([.]?)([^.]*)/).exec(value) + + integer = sanitizeInteger(integer) || '0' + decimal = sanitizeDecimal(decimal) + + return `${integer}${point}${decimal}` +} + +CurrencyInput.prototype.handleChange = function (newValue) { + const { onInputChange } = this.props + + this.setState({ value: sanitizeValue(newValue) }) + + onInputChange(sanitizeValue(newValue)) +} + +// If state.value === props.value plus a decimal point, or at least one +// zero or a decimal point and at least one zero, then this returns state.value +// after it is sanitized with getValueParts +CurrencyInput.prototype.getValueToRender = function () { + const { value } = this.props + const { value: stateValue } = this.state + + const trailingStateString = (new RegExp(`^${value}(.+)`)).exec(stateValue) + const trailingDecimalAndZeroes = trailingStateString && (/^[.0]0*/).test(trailingStateString[1]) + + return sanitizeValue(trailingDecimalAndZeroes + ? stateValue + : value) +} + +CurrencyInput.prototype.render = function () { + const { + className, + placeholder, + readOnly, + } = this.props + + const inputSizeMultiplier = readOnly ? 1 : 1.2 + + const valueToRender = this.getValueToRender() + + return h('input', { + className, + value: valueToRender, + placeholder, + size: valueToRender.length * inputSizeMultiplier, + readOnly, + onChange: e => this.handleChange(e.target.value), + }) +} diff --git a/ui/app/components/send/currency-display.js b/ui/app/components/send/currency-display.js index 45986e371..8b72b3e6d 100644 --- a/ui/app/components/send/currency-display.js +++ b/ui/app/components/send/currency-display.js @@ -1,6 +1,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits +const CurrencyInput = require('../currency-input') const { conversionUtil, multiplyCurrencies } = require('../../conversion-util') module.exports = CurrencyDisplay @@ -8,10 +9,6 @@ module.exports = CurrencyDisplay inherits(CurrencyDisplay, Component) function CurrencyDisplay () { Component.call(this) - - this.state = { - value: null, - } } function isValidInput (text) { @@ -49,13 +46,11 @@ CurrencyDisplay.prototype.render = function () { convertedCurrency, readOnly = false, inError = false, - value: initValue, + value, handleChange, - validate, } = this.props - const { value } = this.state - const initValueToRender = conversionUtil(initValue, { + const valueToRender = conversionUtil(value, { fromNumericBase: 'hex', toNumericBase: 'dec', fromDenomination: 'WEI', @@ -63,7 +58,7 @@ CurrencyDisplay.prototype.render = function () { conversionRate, }) - const convertedValue = conversionUtil(value || initValueToRender, { + const convertedValue = conversionUtil(valueToRender, { fromNumericBase: 'dec', fromCurrency: primaryCurrency, toCurrency: convertedCurrency, @@ -84,29 +79,14 @@ CurrencyDisplay.prototype.render = function () { h('div.currency-display__input-wrapper', [ - h('input', { + h(CurrencyInput, { className: primaryBalanceClassName, - value: `${value || initValueToRender}`, + value: `${valueToRender}`, placeholder: '0', - size: (value || initValueToRender).length * inputSizeMultiplier, readOnly, - onChange: (event) => { - let newValue = event.target.value - - if (newValue === '') { - newValue = '0' - } else if (newValue.match(/^0[1-9]$/)) { - newValue = newValue.match(/[1-9]/)[0] - } - - if (newValue && !isValidInput(newValue)) { - event.preventDefault() - } else { - validate(this.getAmount(newValue)) - this.setState({ value: newValue }) - } + onInputChange: newValue => { + handleChange(this.getAmount(newValue)) }, - onBlur: event => !readOnly && handleChange(this.getAmount(event.target.value)), }), h('span.currency-display__currency-symbol', primaryCurrency), -- cgit v1.2.3 From c156c85eaa064b971ce0202df0bb1681eb0e22dd Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 7 Nov 2017 21:47:14 -0330 Subject: Fix amount max for sending token. --- ui/app/components/send/currency-display.js | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send/currency-display.js b/ui/app/components/send/currency-display.js index 8b72b3e6d..49df5b0b7 100644 --- a/ui/app/components/send/currency-display.js +++ b/ui/app/components/send/currency-display.js @@ -36,6 +36,28 @@ CurrencyDisplay.prototype.getAmount = function (value) { : toHexWei(value) } +CurrencyDisplay.prototype.getValueToRender = function () { + const { selectedToken, conversionRate, value } = this.props + + const { decimals, symbol } = selectedToken || {} + const multiplier = Math.pow(10, Number(decimals || 0)) + + return selectedToken + ? conversionUtil(value, { + fromNumericBase: 'hex', + toCurrency: symbol, + conversionRate: multiplier, + invertConversionRate: true, + }) + : conversionUtil(value, { + fromNumericBase: 'hex', + toNumericBase: 'dec', + fromDenomination: 'WEI', + numberOfDecimals: 6, + conversionRate, + }) +} + CurrencyDisplay.prototype.render = function () { const { className = 'currency-display', @@ -50,13 +72,7 @@ CurrencyDisplay.prototype.render = function () { handleChange, } = this.props - const valueToRender = conversionUtil(value, { - fromNumericBase: 'hex', - toNumericBase: 'dec', - fromDenomination: 'WEI', - numberOfDecimals: 6, - conversionRate, - }) + const valueToRender = this.getValueToRender() const convertedValue = conversionUtil(valueToRender, { fromNumericBase: 'dec', -- cgit v1.2.3 From d1977225a48f381f3a6bda4a54ce9e0e0914357e Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 7 Nov 2017 21:49:14 -0330 Subject: Calculate max amount for send ether based on minimum gas total. --- ui/app/components/send/currency-display.js | 8 -------- 1 file changed, 8 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send/currency-display.js b/ui/app/components/send/currency-display.js index 49df5b0b7..870fbb42a 100644 --- a/ui/app/components/send/currency-display.js +++ b/ui/app/components/send/currency-display.js @@ -11,11 +11,6 @@ function CurrencyDisplay () { Component.call(this) } -function isValidInput (text) { - const re = /^([1-9]\d*|0)(\.|\.\d*)?$/ - return re.test(text) -} - function toHexWei (value) { return conversionUtil(value, { fromNumericBase: 'dec', @@ -68,7 +63,6 @@ CurrencyDisplay.prototype.render = function () { convertedCurrency, readOnly = false, inError = false, - value, handleChange, } = this.props @@ -82,8 +76,6 @@ CurrencyDisplay.prototype.render = function () { conversionRate, }) - const inputSizeMultiplier = readOnly ? 1 : 1.2 - return h('div', { className, style: { -- cgit v1.2.3 From 424c1f23c91b06b687ddb3a3cbc79610584dc23f Mon Sep 17 00:00:00 2001 From: cjeria Date: Wed, 8 Nov 2017 15:41:29 -0800 Subject: darker backdrop style for modal --- ui/app/components/modals/modal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 842081f40..f2909f3c3 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -189,7 +189,7 @@ const MODALS = { } const BACKDROPSTYLE = { - backgroundColor: 'rgba(245, 245, 245, 0.85)', + backgroundColor: 'rgba(0, 0, 0, 0.5)', } function mapStateToProps (state) { -- cgit v1.2.3 From 62f2aebe1d9c3efd6ace8785fc96bb43ae08afe8 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 9 Nov 2017 13:17:10 -0330 Subject: Network loading does not block network loading. --- ui/app/components/dropdowns/components/dropdown.js | 2 +- ui/app/components/dropdowns/network-dropdown.js | 3 ++- ui/app/components/loading.js | 15 +-------------- 3 files changed, 4 insertions(+), 16 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/components/dropdown.js b/ui/app/components/dropdowns/components/dropdown.js index ddcb7998f..15d064be8 100644 --- a/ui/app/components/dropdowns/components/dropdown.js +++ b/ui/app/components/dropdowns/components/dropdown.js @@ -31,7 +31,7 @@ class Dropdown extends Component { containerClassName, useCssTransition, isOpen, - zIndex: 30, + zIndex: 55, onClickOutside, style, innerStyle: innerStyleDefaults, diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js index 20dfca590..0908faf01 100644 --- a/ui/app/components/dropdowns/network-dropdown.js +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -75,11 +75,12 @@ NetworkDropdown.prototype.render = function () { } }, containerClassName: 'network-droppo', - zIndex: 11, + zIndex: 55, style: { position: 'absolute', top: '58px', minWidth: '309px', + zIndex: '55px', }, innerStyle: { padding: '18px 8px', diff --git a/ui/app/components/loading.js b/ui/app/components/loading.js index 587212015..9442121fe 100644 --- a/ui/app/components/loading.js +++ b/ui/app/components/loading.js @@ -10,20 +10,7 @@ class LoadingIndicator extends Component { render () { return ( - h('.full-flex-height', { - style: { - left: '0px', - zIndex: 50, - position: 'absolute', - flexDirection: 'column', - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - height: '100%', - width: '100%', - background: 'rgba(255, 255, 255, 0.8)', - }, - }, [ + h('.full-flex-height.loading-overlay', {}, [ h('img', { src: 'images/loading.svg', }), -- cgit v1.2.3 From 5120cfdff3047e4bf88cec544895cc713d063cdd Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Thu, 9 Nov 2017 14:23:10 -0800 Subject: Linting --- ui/app/components/currency-input.js | 2 +- ui/app/components/customize-gas-modal/index.js | 2 +- ui/app/components/send/send-utils.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/currency-input.js b/ui/app/components/currency-input.js index 5e534d87b..f192ee531 100644 --- a/ui/app/components/currency-input.js +++ b/ui/app/components/currency-input.js @@ -40,7 +40,7 @@ function sanitizeDecimal (val) { // sanitizeValue('.200') -> '0.200' // sanitizeValue('a.b.1.c,89.123') -> '0.189123' function sanitizeValue (value) { - let [,integer, point, decimal] = (/([^.]*)([.]?)([^.]*)/).exec(value) + let [integer, point, decimal] = (/([^.]*)([.]?)([^.]*)/).exec(value) integer = sanitizeInteger(integer) || '0' decimal = sanitizeDecimal(decimal) diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index b77e1990f..f01f42fe0 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -115,7 +115,7 @@ CustomizeGasModal.prototype.validate = function ({ gasTotal, gasLimit }) { } = this.props let error = null - + const balanceIsSufficient = isBalanceSufficient({ amount, gasTotal, diff --git a/ui/app/components/send/send-utils.js b/ui/app/components/send/send-utils.js index bd1197950..d8211930d 100644 --- a/ui/app/components/send/send-utils.js +++ b/ui/app/components/send/send-utils.js @@ -7,7 +7,7 @@ const { calcTokenAmount, } = require('../../token-util') -function isBalanceSufficient({ +function isBalanceSufficient ({ amount = '0x0', gasTotal = '0x0', balance, @@ -39,7 +39,7 @@ function isBalanceSufficient({ return balanceIsSufficient } -function isTokenBalanceSufficient({ +function isTokenBalanceSufficient ({ amount = '0x0', tokenBalance, decimals, -- cgit v1.2.3 From 5a0126f17b3513fa7fa1513f2c52abff19535ac0 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 10 Nov 2017 07:07:53 -0330 Subject: Rounding of vals < 0.01 in currency display consistent with master. --- ui/app/components/send/currency-display.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send/currency-display.js b/ui/app/components/send/currency-display.js index 870fbb42a..5057c413c 100644 --- a/ui/app/components/send/currency-display.js +++ b/ui/app/components/send/currency-display.js @@ -68,13 +68,14 @@ CurrencyDisplay.prototype.render = function () { const valueToRender = this.getValueToRender() - const convertedValue = conversionUtil(valueToRender, { + let convertedValue = conversionUtil(valueToRender, { fromNumericBase: 'dec', fromCurrency: primaryCurrency, toCurrency: convertedCurrency, numberOfDecimals: 2, conversionRate, }) + convertedValue = Number(convertedValue).toFixed(2) return h('div', { className, -- cgit v1.2.3 From a33ced39946c1448b56aef22ab3573b00d1faeca Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 10 Nov 2017 15:17:02 -0330 Subject: Focus amount input when click anywhere in amount field container --- ui/app/components/currency-input.js | 2 ++ ui/app/components/send/currency-display.js | 2 ++ 2 files changed, 4 insertions(+) (limited to 'ui/app/components') diff --git a/ui/app/components/currency-input.js b/ui/app/components/currency-input.js index f192ee531..016f14d3e 100644 --- a/ui/app/components/currency-input.js +++ b/ui/app/components/currency-input.js @@ -76,6 +76,7 @@ CurrencyInput.prototype.render = function () { className, placeholder, readOnly, + inputRef, } = this.props const inputSizeMultiplier = readOnly ? 1 : 1.2 @@ -89,5 +90,6 @@ CurrencyInput.prototype.render = function () { size: valueToRender.length * inputSizeMultiplier, readOnly, onChange: e => this.handleChange(e.target.value), + ref: inputRef, }) } diff --git a/ui/app/components/send/currency-display.js b/ui/app/components/send/currency-display.js index 5057c413c..5bf8d6aa0 100644 --- a/ui/app/components/send/currency-display.js +++ b/ui/app/components/send/currency-display.js @@ -82,6 +82,7 @@ CurrencyDisplay.prototype.render = function () { style: { borderColor: inError ? 'red' : null, }, + onClick: () => this.currencyInput.focus(), }, [ h('div.currency-display__primary-row', [ @@ -96,6 +97,7 @@ CurrencyDisplay.prototype.render = function () { onInputChange: newValue => { handleChange(this.getAmount(newValue)) }, + inputRef: input => { this.currencyInput = input; }, }), h('span.currency-display__currency-symbol', primaryCurrency), -- cgit v1.2.3 From 08d9ecc0454c729356f3f7a6d91156ee96c66959 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 10 Nov 2017 16:15:43 -0330 Subject: Cursor pointer and hover background on from and to dropdown items. --- ui/app/components/send/account-list-item.js | 2 ++ ui/app/components/send/from-dropdown.js | 1 + ui/app/components/send/to-autocomplete.js | 1 + 3 files changed, 4 insertions(+) (limited to 'ui/app/components') diff --git a/ui/app/components/send/account-list-item.js b/ui/app/components/send/account-list-item.js index 2378a4671..1ad3f69c1 100644 --- a/ui/app/components/send/account-list-item.js +++ b/ui/app/components/send/account-list-item.js @@ -22,6 +22,7 @@ module.exports = connect(mapStateToProps)(AccountListItem) AccountListItem.prototype.render = function () { const { + className, account, handleClick, icon = null, @@ -34,6 +35,7 @@ AccountListItem.prototype.render = function () { const { name, address, balance } = account || {} return h('div.account-list-item', { + className, onClick: () => handleClick({ name, address, balance }), }, [ diff --git a/ui/app/components/send/from-dropdown.js b/ui/app/components/send/from-dropdown.js index bcae5ede8..0686fbe73 100644 --- a/ui/app/components/send/from-dropdown.js +++ b/ui/app/components/send/from-dropdown.js @@ -35,6 +35,7 @@ FromDropdown.prototype.renderDropdown = function () { h('div.send-v2__from-dropdown__list', {}, [ ...accounts.map(account => h(AccountListItem, { + className: 'account-list-item__dropdown', account, handleClick: () => { onSelect(account) diff --git a/ui/app/components/send/to-autocomplete.js b/ui/app/components/send/to-autocomplete.js index fef8d5ccb..e0cdd0a58 100644 --- a/ui/app/components/send/to-autocomplete.js +++ b/ui/app/components/send/to-autocomplete.js @@ -38,6 +38,7 @@ ToAutoComplete.prototype.renderDropdown = function () { ...accountsToRender.map(account => h(AccountListItem, { account, + className: 'account-list-item__dropdown', handleClick: () => { onChange(account.address) closeDropdown() -- cgit v1.2.3 From 544166437a0a41ce25d3d47814409a7ce01b4e07 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 10 Nov 2017 00:02:53 -0330 Subject: Deposit button shows link to faucet on testnet networks. --- ui/app/components/modals/buy-options-modal.js | 38 ++++++++++++++++----------- 1 file changed, 23 insertions(+), 15 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/buy-options-modal.js b/ui/app/components/modals/buy-options-modal.js index 33615c483..53e40ba92 100644 --- a/ui/app/components/modals/buy-options-modal.js +++ b/ui/app/components/modals/buy-options-modal.js @@ -3,6 +3,7 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect const actions = require('../../actions') +const networkNames = require('../../../../app/scripts/config.js').networkNames function mapStateToProps (state) { return { @@ -22,6 +23,7 @@ function mapDispatchToProps (dispatch) { showAccountDetailModal: () => { dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' })) }, + toFaucet: network => dispatch(actions.buyEth({ network })), } } @@ -32,7 +34,20 @@ function BuyOptions () { module.exports = connect(mapStateToProps, mapDispatchToProps)(BuyOptions) +BuyOptions.prototype.renderModalContentOption = function (title, header, onClick) { + return h('div.buy-modal-content-option', { + onClick, + }, [ + h('div.buy-modal-content-option-title', {}, title), + h('div.buy-modal-content-option-subtitle', {}, header), + ]) +} + BuyOptions.prototype.render = function () { + const { network, toCoinbase, address, toFaucet } = this.props + const networkIsTest = ['3', '4', '42'].find(n => n === network) + const networkName = networkNames[network] + return h('div', {}, [ h('div.buy-modal-content.transfers-subview', { }, [ @@ -47,27 +62,20 @@ BuyOptions.prototype.render = function () { h('div.buy-modal-content-options.flex-column.flex-center', {}, [ - h('div.buy-modal-content-option', { - onClick: () => { - const { toCoinbase, address } = this.props - toCoinbase(address) - }, - }, [ - h('div.buy-modal-content-option-title', {}, 'Coinbase'), - h('div.buy-modal-content-option-subtitle', {}, 'Deposit with Fiat'), - ]), + networkIsTest + ? this.renderModalContentOption(networkName, 'Test Faucet', () => toFaucet(network)) + : this.renderModalContentOption('Coinbase', 'Deposit with Fiat', () => toCoinbase(address)), // h('div.buy-modal-content-option', {}, [ // h('div.buy-modal-content-option-title', {}, 'Shapeshift'), // h('div.buy-modal-content-option-subtitle', {}, 'Trade any digital asset for any other'), // ]), - h('div.buy-modal-content-option', { - onClick: () => this.goToAccountDetailsModal(), - }, [ - h('div.buy-modal-content-option-title', {}, 'Direct Deposit'), - h('div.buy-modal-content-option-subtitle', {}, 'Deposit from another account'), - ]), + this.renderModalContentOption( + 'Direct Deposit', + 'Deposit from another account', + () => this.goToAccountDetailsModal() + ), ]), -- cgit v1.2.3 From 7eb083bd9f1a8ce0e9c3e83e8b6bfb4d5a7b59cc Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 10 Nov 2017 21:06:00 -0330 Subject: Improve variable name. --- ui/app/components/modals/buy-options-modal.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/buy-options-modal.js b/ui/app/components/modals/buy-options-modal.js index 53e40ba92..d735983f9 100644 --- a/ui/app/components/modals/buy-options-modal.js +++ b/ui/app/components/modals/buy-options-modal.js @@ -45,7 +45,7 @@ BuyOptions.prototype.renderModalContentOption = function (title, header, onClick BuyOptions.prototype.render = function () { const { network, toCoinbase, address, toFaucet } = this.props - const networkIsTest = ['3', '4', '42'].find(n => n === network) + const isTestNetwork = ['3', '4', '42'].find(n => n === network) const networkName = networkNames[network] return h('div', {}, [ @@ -62,7 +62,7 @@ BuyOptions.prototype.render = function () { h('div.buy-modal-content-options.flex-column.flex-center', {}, [ - networkIsTest + isTestNetwork ? this.renderModalContentOption(networkName, 'Test Faucet', () => toFaucet(network)) : this.renderModalContentOption('Coinbase', 'Deposit with Fiat', () => toCoinbase(address)), -- cgit v1.2.3 From 34ca7290c593d6fb27faa98a660c8c0bca7e1457 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 8 Nov 2017 13:14:48 -0330 Subject: Allow editing of send ether. --- ui/app/components/pending-tx/confirm-send-ether.js | 54 +++++++++++++++++++--- ui/app/components/send/send-v2-container.js | 2 + 2 files changed, 50 insertions(+), 6 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index d12bc499b..8b5801aec 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -19,6 +19,7 @@ function mapStateToProps (state) { conversionRate, identities, currentCurrency, + send, } = state.metamask const accounts = state.metamask.accounts const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] @@ -27,12 +28,30 @@ function mapStateToProps (state) { identities, selectedAddress, currentCurrency, + send, } } function mapDispatchToProps (dispatch) { return { - backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)), + clearSend: () => dispatch(actions.clearSend()), + editTransaction: txMeta => { + const { id, txParams } = txMeta + const { + gas: gasLimit, + gasPrice, + from, + to, + value: amount + } = txParams + dispatch(actions.editTx(id)) + dispatch(actions.updateGasLimit(gasLimit)), + dispatch(actions.updateGasPrice(gasPrice)), + dispatch(actions.updateSendTo(to)), + dispatch(actions.updateSendAmount(amount)), + dispatch(actions.updateSendErrors({ to: null, amount: null })), + dispatch(actions.showSendPage()) + }, cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), } } @@ -157,7 +176,7 @@ ConfirmSendEther.prototype.getData = function () { } ConfirmSendEther.prototype.render = function () { - const { backToAccountDetail, selectedAddress, currentCurrency } = this.props + const { editTransaction, selectedAddress, currentCurrency, clearSend } = this.props const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} @@ -199,8 +218,8 @@ ConfirmSendEther.prototype.render = function () { h('div.confirm-screen-wrapper.flex-column.flex-grow', [ h('h3.flex-center.confirm-screen-header', [ h('button.confirm-screen-back-button', { - onClick: () => backToAccountDetail(selectedAddress), - }, 'BACK'), + onClick: () => editTransaction(txMeta), + }, 'EDIT'), h('div.confirm-screen-title', 'Confirm Transaction'), h('div.confirm-screen-header-tip'), ]), @@ -371,7 +390,10 @@ ConfirmSendEther.prototype.render = function () { }, [ // Cancel Button h('div.cancel.btn-light.confirm-screen-cancel-button', { - onClick: (event) => this.cancel(event, txMeta), + onClick: (event) => { + clearSend() + this.cancel(event, txMeta) + }, }, 'CANCEL'), // Accept Button @@ -419,7 +441,27 @@ ConfirmSendEther.prototype.getFormEl = function () { ConfirmSendEther.prototype.gatherTxMeta = function () { const props = this.props const state = this.state - const txData = clone(state.txData) || clone(props.txData) + let txData = clone(state.txData) || clone(props.txData) + + if (props.send.editingTransactionId) { + const { + send: { + memo, + amount: value, + gasLimit: gas, + gasPrice, + } + } = props + const { txParams: { from, to } } = txData + txData.txParams = { + from: ethUtil.addHexPrefix(from), + to: ethUtil.addHexPrefix(to), + memo: memo && ethUtil.addHexPrefix(memo), + value: ethUtil.addHexPrefix(value), + gas: ethUtil.addHexPrefix(gas), + gasPrice: ethUtil.addHexPrefix(gasPrice), + } + } // log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`) return txData diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js index 51d5c4f89..4451a6113 100644 --- a/ui/app/components/send/send-v2-container.js +++ b/ui/app/components/send/send-v2-container.js @@ -63,6 +63,7 @@ function mapDispatchToProps (dispatch) { dispatch(actions.signTokenTx(tokenAddress, toAddress, amount, txData)) ), signTx: txParams => dispatch(actions.signTx(txParams)), + updateAndApproveTx: txParams => dispatch(actions.updateAndApproveTx(txParams)), setSelectedAddress: address => dispatch(actions.setSelectedAddress(address)), addToAddressBook: address => dispatch(actions.addToAddressBook(address)), updateGasTotal: newTotal => dispatch(actions.updateGasTotal(newTotal)), @@ -76,5 +77,6 @@ function mapDispatchToProps (dispatch) { updateSendErrors: newError => dispatch(actions.updateSendErrors(newError)), goHome: () => dispatch(actions.goHome()), clearSend: () => dispatch(actions.clearSend()), + backToConfirmScreen: editingTransactionId => dispatch(actions.showConfTxPage({ id: editingTransactionId })), } } -- cgit v1.2.3 From 0a91671ff69957596abbcffb7d20c89f144d7a69 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 8 Nov 2017 15:48:27 -0330 Subject: Fix lint errors. --- ui/app/components/currency-input.js | 2 +- ui/app/components/pending-tx/confirm-send-ether.js | 19 +++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/currency-input.js b/ui/app/components/currency-input.js index 016f14d3e..66880091f 100644 --- a/ui/app/components/currency-input.js +++ b/ui/app/components/currency-input.js @@ -40,7 +40,7 @@ function sanitizeDecimal (val) { // sanitizeValue('.200') -> '0.200' // sanitizeValue('a.b.1.c,89.123') -> '0.189123' function sanitizeValue (value) { - let [integer, point, decimal] = (/([^.]*)([.]?)([^.]*)/).exec(value) + let [ , integer, point, decimal] = (/([^.]*)([.]?)([^.]*)/).exec(value) integer = sanitizeInteger(integer) || '0' decimal = sanitizeDecimal(decimal) diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 8b5801aec..b4d955b80 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -40,16 +40,15 @@ function mapDispatchToProps (dispatch) { const { gas: gasLimit, gasPrice, - from, to, - value: amount + value: amount, } = txParams dispatch(actions.editTx(id)) - dispatch(actions.updateGasLimit(gasLimit)), - dispatch(actions.updateGasPrice(gasPrice)), - dispatch(actions.updateSendTo(to)), - dispatch(actions.updateSendAmount(amount)), - dispatch(actions.updateSendErrors({ to: null, amount: null })), + dispatch(actions.updateGasLimit(gasLimit)) + dispatch(actions.updateGasPrice(gasPrice)) + dispatch(actions.updateSendTo(to)) + dispatch(actions.updateSendAmount(amount)) + dispatch(actions.updateSendErrors({ to: null, amount: null })) dispatch(actions.showSendPage()) }, cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), @@ -176,7 +175,7 @@ ConfirmSendEther.prototype.getData = function () { } ConfirmSendEther.prototype.render = function () { - const { editTransaction, selectedAddress, currentCurrency, clearSend } = this.props + const { editTransaction, currentCurrency, clearSend } = this.props const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} @@ -441,7 +440,7 @@ ConfirmSendEther.prototype.getFormEl = function () { ConfirmSendEther.prototype.gatherTxMeta = function () { const props = this.props const state = this.state - let txData = clone(state.txData) || clone(props.txData) + const txData = clone(state.txData) || clone(props.txData) if (props.send.editingTransactionId) { const { @@ -450,7 +449,7 @@ ConfirmSendEther.prototype.gatherTxMeta = function () { amount: value, gasLimit: gas, gasPrice, - } + }, } = props const { txParams: { from, to } } = txData txData.txParams = { -- cgit v1.2.3 From 4671f28476165fec43785ae23352c1e9a0776abc Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 9 Nov 2017 11:44:32 -0330 Subject: Allow editing of token transactions. --- ui/app/components/pending-tx/confirm-send-token.js | 95 ++++++++++++++++++++-- 1 file changed, 87 insertions(+), 8 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index f14da38ef..aab45f2a4 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -2,9 +2,10 @@ const Component = require('react').Component const { connect } = require('react-redux') const h = require('react-hyperscript') const inherits = require('util').inherits -const abi = require('human-standard-token-abi') +const ethAbi = require('ethereumjs-abi') +const tokenAbi = require('human-standard-token-abi') const abiDecoder = require('abi-decoder') -abiDecoder.addABI(abi) +abiDecoder.addABI(tokenAbi) const actions = require('../../actions') const clone = require('clone') const Identicon = require('../identicon') @@ -24,6 +25,7 @@ const { MIN_GAS_PRICE_HEX } = require('../send/send-constants') const { getTokenExchangeRate, getSelectedAddress, + getSelectedTokenContract, } = require('../../selectors') module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmSendToken) @@ -32,6 +34,7 @@ function mapStateToProps (state, ownProps) { const { token: { symbol }, txData } = ownProps const { txParams } = txData || {} const tokenData = txParams.data && abiDecoder.decodeMethod(txParams.data) + const { conversionRate, identities, @@ -47,6 +50,8 @@ function mapStateToProps (state, ownProps) { tokenExchangeRate, tokenData: tokenData || {}, currentCurrency: currentCurrency.toUpperCase(), + send: state.metamask.send, + tokenContract: getSelectedTokenContract(state), } } @@ -57,6 +62,30 @@ function mapDispatchToProps (dispatch, ownProps) { backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)), cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), updateTokenExchangeRate: () => dispatch(actions.updateTokenExchangeRate(symbol)), + editTransaction: txMeta => { + const { token: { address } } = ownProps + const { txParams, id } = txMeta + const tokenData = txParams.data && abiDecoder.decodeMethod(txParams.data) + const { params = [] } = tokenData + const { value } = params[1] || {} + const amount = conversionUtil(value, { + fromNumericBase: 'dec', + toNumericBase: 'hex', + }) + const { + gas: gasLimit, + gasPrice, + to, + } = txParams + dispatch(actions.editTx(id)) + dispatch(actions.updateGasLimit(gasLimit)) + dispatch(actions.updateGasPrice(gasPrice)) + dispatch(actions.updateSendTo(to)) + dispatch(actions.updateSendAmount(amount)) + dispatch(actions.updateSendErrors({ to: null, amount: null })) + dispatch(actions.setSelectedToken(address)) + dispatch(actions.showSendTokenPage()) + }, } } @@ -68,14 +97,33 @@ function ConfirmSendToken () { } ConfirmSendToken.prototype.componentWillMount = function () { + const { tokenContract, selectedAddress } = this.props + tokenContract && tokenContract + .balanceOf(selectedAddress) + .then(usersToken => { + }) this.props.updateTokenExchangeRate() } ConfirmSendToken.prototype.getAmount = function () { - const { conversionRate, tokenExchangeRate, token, tokenData } = this.props + const { + conversionRate, + tokenExchangeRate, + token, + tokenData, + send: { amount, editingTransactionId }, + } = this.props const { params = [] } = tokenData - const { value } = params[1] || {} + let { value } = params[1] || {} const { decimals } = token + + if (editingTransactionId) { + value = conversionUtil(amount, { + fromNumericBase: 'hex', + toNumericBase: 'dec', + }) + } + const sendTokenAmount = calcTokenAmount(value, decimals) return { @@ -242,9 +290,8 @@ ConfirmSendToken.prototype.renderTotalPlusGas = function () { } ConfirmSendToken.prototype.render = function () { - const { backToAccountDetail, selectedAddress } = this.props + const { editTransaction } = this.props const txMeta = this.gatherTxMeta() - const { from: { address: fromAddress, @@ -266,8 +313,8 @@ ConfirmSendToken.prototype.render = function () { h('div.confirm-screen-wrapper.flex-column.flex-grow', [ h('h3.flex-center.confirm-screen-header', [ h('button.confirm-screen-back-button', { - onClick: () => backToAccountDetail(selectedAddress), - }, 'BACK'), + onClick: () => editTransaction(txMeta), + }, 'EDIT'), h('div.confirm-screen-title', 'Confirm Transaction'), h('div.confirm-screen-header-tip'), ]), @@ -389,6 +436,38 @@ ConfirmSendToken.prototype.gatherTxMeta = function () { const state = this.state const txData = clone(state.txData) || clone(props.txData) + if (props.send.editingTransactionId) { + const { + send: { + memo, + amount, + gasLimit: gas, + gasPrice, + }, + } = props + + const { txParams: { from, to } } = txData + + const tokenParams = { + from: ethUtil.addHexPrefix(from), + value: '0', + gas: ethUtil.addHexPrefix(gas), + gasPrice: ethUtil.addHexPrefix(gasPrice), + } + + const data = '0xa9059cbb' + Array.prototype.map.call( + ethAbi.rawEncode(['address', 'uint256'], [to, ethUtil.addHexPrefix(amount)]), + x => ('00' + x.toString(16)).slice(-2) + ).join('') + + txData.txParams = { + ...tokenParams, + to: ethUtil.addHexPrefix(to), + memo: memo && ethUtil.addHexPrefix(memo), + data, + } + } + // log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`) return txData } -- cgit v1.2.3 From 9e3f921ba928a948c04b4156daa0a3f752ee2dde Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 10 Nov 2017 00:19:16 -0330 Subject: Create single action for updating all of send in redux state. --- ui/app/components/pending-tx/confirm-send-ether.js | 15 +++++++++------ ui/app/components/pending-tx/confirm-send-token.js | 15 +++++++++------ ui/app/components/send/currency-display.js | 2 +- 3 files changed, 19 insertions(+), 13 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index b4d955b80..1264da153 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -43,12 +43,15 @@ function mapDispatchToProps (dispatch) { to, value: amount, } = txParams - dispatch(actions.editTx(id)) - dispatch(actions.updateGasLimit(gasLimit)) - dispatch(actions.updateGasPrice(gasPrice)) - dispatch(actions.updateSendTo(to)) - dispatch(actions.updateSendAmount(amount)) - dispatch(actions.updateSendErrors({ to: null, amount: null })) + dispatch(actions.updateSend({ + gasLimit, + gasPrice, + gasTotal: null, + to, + amount, + errors: { to: null, amount: null }, + editingTransactionId: id, + })) dispatch(actions.showSendPage()) }, cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index aab45f2a4..cc2df8299 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -77,13 +77,16 @@ function mapDispatchToProps (dispatch, ownProps) { gasPrice, to, } = txParams - dispatch(actions.editTx(id)) - dispatch(actions.updateGasLimit(gasLimit)) - dispatch(actions.updateGasPrice(gasPrice)) - dispatch(actions.updateSendTo(to)) - dispatch(actions.updateSendAmount(amount)) - dispatch(actions.updateSendErrors({ to: null, amount: null })) dispatch(actions.setSelectedToken(address)) + dispatch(actions.updateSend({ + gasLimit, + gasPrice, + gasTotal: null, + to, + amount, + errors: { to: null, amount: null }, + editingTransactionId: id, + })) dispatch(actions.showSendTokenPage()) }, } diff --git a/ui/app/components/send/currency-display.js b/ui/app/components/send/currency-display.js index 5bf8d6aa0..819fee0a0 100644 --- a/ui/app/components/send/currency-display.js +++ b/ui/app/components/send/currency-display.js @@ -97,7 +97,7 @@ CurrencyDisplay.prototype.render = function () { onInputChange: newValue => { handleChange(this.getAmount(newValue)) }, - inputRef: input => { this.currencyInput = input; }, + inputRef: input => { this.currencyInput = input }, }), h('span.currency-display__currency-symbol', primaryCurrency), -- cgit v1.2.3 From 59e46e7cb25b7355bd969fe9ab04090f52ec67bc Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Mon, 13 Nov 2017 14:20:42 -0800 Subject: Show tokens with zero balance --- ui/app/components/token-list.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js index b6a27fd5a..8e06e0f27 100644 --- a/ui/app/components/token-list.js +++ b/ui/app/components/token-list.js @@ -151,10 +151,7 @@ TokenList.prototype.componentDidUpdate = 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 }) + this.setState({ tokens, isLoading: false }) } TokenList.prototype.componentWillUnmount = function () { -- cgit v1.2.3 From bbdb35c35a03c42eb4a950756bf280e6e15513b5 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 15 Nov 2017 15:00:35 -0330 Subject: Use currency input component in input number, to improve input behaviour in gas estimator --- ui/app/components/input-number.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/input-number.js b/ui/app/components/input-number.js index 12dec2957..fd8c5c309 100644 --- a/ui/app/components/input-number.js +++ b/ui/app/components/input-number.js @@ -1,6 +1,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits +const CurrencyInput = require('./currency-input') const { addCurrencies, conversionGTE, @@ -50,11 +51,13 @@ InputNumber.prototype.render = function () { const { unitLabel, step = 1, placeholder, value = 0 } = this.props return h('div.customize-gas-input-wrapper', {}, [ - h('input.customize-gas-input', { - placeholder, + h(CurrencyInput, { + className: 'customize-gas-input', value, - step, - onChange: (e) => this.setValue(e.target.value), + placeholder, + onInputChange: newValue => { + this.setValue(newValue) + }, }), h('span.gas-tooltip-input-detail', {}, [unitLabel]), h('div.gas-tooltip-input-arrows', {}, [ -- cgit v1.2.3 From 960cc8abcbdc82ae2b73a82f0faf1658f113a9d3 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 15 Nov 2017 15:29:57 -0330 Subject: Gas customzier does not consider amount when sending tokens. --- ui/app/components/customize-gas-modal/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index f01f42fe0..485dacf90 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -117,7 +117,7 @@ CustomizeGasModal.prototype.validate = function ({ gasTotal, gasLimit }) { let error = null const balanceIsSufficient = isBalanceSufficient({ - amount, + amount: selectedToken ? '0' : amount, gasTotal, balance, selectedToken, -- cgit v1.2.3 From c6713e93adcaeeba1ec559d44135bb62c76d2538 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 17 Nov 2017 13:23:25 -0800 Subject: Fix bug where gas param was not a string Prevented sending transactions. Fixes #2598 --- ui/app/components/customize-gas-modal/index.js | 2 +- ui/app/components/send/send-constants.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 485dacf90..6d27702e8 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -244,7 +244,7 @@ CustomizeGasModal.prototype.render = function () { min: 1, // max: 100000, step: 1, - onChange: value => this.convertAndSetGasLimit(value), + onChange: value => this.convertAndSetGasLimit(String(value)), title: 'Gas Limit', copy: 'We calculate the suggested gas limit based on network success rates.', }), diff --git a/ui/app/components/send/send-constants.js b/ui/app/components/send/send-constants.js index a961ffcd8..9c240972f 100644 --- a/ui/app/components/send/send-constants.js +++ b/ui/app/components/send/send-constants.js @@ -3,8 +3,8 @@ const { conversionUtil, multiplyCurrencies } = require('../../conversion-util') const MIN_GAS_PRICE_HEX = (100000000).toString(16) const MIN_GAS_PRICE_DEC = '100000000' -const MIN_GAS_LIMIT_HEX = (21000).toString(16) -const MIN_GAS_LIMIT_DEC = 21000 +const MIN_GAS_LIMIT_DEC = '21000' +const MIN_GAS_LIMIT_HEX = (parseInt(MIN_GAS_LIMIT_DEC)).toString(16) const MIN_GAS_PRICE_GWEI = ethUtil.addHexPrefix(conversionUtil(MIN_GAS_PRICE_HEX, { fromDenomination: 'WEI', -- cgit v1.2.3 From 28409294c3cd70ddbc9a9f3467d402c89e110261 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 20 Nov 2017 10:54:05 -0800 Subject: Remove unneeded type casting --- ui/app/components/customize-gas-modal/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 6d27702e8..485dacf90 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -244,7 +244,7 @@ CustomizeGasModal.prototype.render = function () { min: 1, // max: 100000, step: 1, - onChange: value => this.convertAndSetGasLimit(String(value)), + onChange: value => this.convertAndSetGasLimit(value), title: 'Gas Limit', copy: 'We calculate the suggested gas limit based on network success rates.', }), -- cgit v1.2.3 From 90fc4812bc75857581e56eb6d63484dbc5c48cb1 Mon Sep 17 00:00:00 2001 From: "Clark, Jason (Contractor)" Date: Thu, 23 Nov 2017 18:33:44 -0700 Subject: incremental commit --- ui/app/components/identicon.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index d30b7cd56..63f3087a4 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -4,6 +4,7 @@ const inherits = require('util').inherits const isNode = require('detect-node') const findDOMNode = require('react-dom').findDOMNode const jazzicon = require('jazzicon') +const blockies = require('blockies') const iconFactoryGen = require('../../lib/icon-factory') const iconFactory = iconFactoryGen(jazzicon) @@ -18,7 +19,7 @@ function IdenticonComponent () { IdenticonComponent.prototype.render = function () { var props = this.props - const { className = '', address } = props + const { className = '', address, useBlockie } = props var diameter = props.diameter || this.defaultDiameter return address -- cgit v1.2.3 From dc7bd3c62897edfb642f215a71fbf7dd93faa350 Mon Sep 17 00:00:00 2001 From: Jason Clark Date: Fri, 24 Nov 2017 13:48:56 -0700 Subject: incremental commit of working blockie component --- ui/app/components/blockies/blockies-component.js | 30 +++++++++++++++++ ui/app/components/identicon.js | 41 +++++++++++++++--------- 2 files changed, 56 insertions(+), 15 deletions(-) create mode 100644 ui/app/components/blockies/blockies-component.js (limited to 'ui/app/components') diff --git a/ui/app/components/blockies/blockies-component.js b/ui/app/components/blockies/blockies-component.js new file mode 100644 index 000000000..d6defda16 --- /dev/null +++ b/ui/app/components/blockies/blockies-component.js @@ -0,0 +1,30 @@ +const Component = require('react').Component +const createElement = require('react').createElement +const blockies = require("ethereum-blockies"); + +class BlockiesIdenticon extends Component { + constructor(props) { + super(props); + } + getOpts () { + return { + seed: this.props.seed || "foo", + color: this.props.color || "#dfe", + bgcolor: this.props.bgcolor || "#a71", + size: this.props.size || 15, + scale: this.props.scale || 3, + spotcolor: this.props.spotcolor || "#000" + }; + } + componentDidMount() { + this.draw(); + } + draw() { + blockies.render(this.getOpts(), this.canvas); + } + render() { + return createElement("canvas", {ref: canvas => this.canvas = canvas}); + } +} + +module.exports = BlockiesIdenticon; diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index 63f3087a4..9e9b82aae 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -1,14 +1,15 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits +const connect = require('react-redux').connect const isNode = require('detect-node') const findDOMNode = require('react-dom').findDOMNode const jazzicon = require('jazzicon') -const blockies = require('blockies') +const BlockiesIdenticon = require('./blockies/blockies-component') const iconFactoryGen = require('../../lib/icon-factory') const iconFactory = iconFactoryGen(jazzicon) -module.exports = IdenticonComponent +module.exports = connect(mapStateToProps)(IdenticonComponent) inherits(IdenticonComponent, Component) function IdenticonComponent () { @@ -17,6 +18,12 @@ function IdenticonComponent () { this.defaultDiameter = 46 } +function mapStateToProps (state) { + return { + useBlockie: state.metamask.useBlockie + } +} + IdenticonComponent.prototype.render = function () { var props = this.props const { className = '', address, useBlockie } = props @@ -24,19 +31,23 @@ IdenticonComponent.prototype.render = function () { return address ? ( - h('div', { - className: `${className} identicon`, - key: 'identicon-' + address, - style: { - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - height: diameter, - width: diameter, - borderRadius: diameter / 2, - overflow: 'hidden', - }, - }) + useBlockie + ? h(BlockiesIdenticon, { + seed: address, + }) + : h('div', { + className: `${className} identicon`, + key: 'identicon-' + address, + style: { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + height: diameter, + width: diameter, + borderRadius: diameter / 2, + overflow: 'hidden', + }, + }) ) : ( h('img.balance-icon', { -- cgit v1.2.3 From 41be4714c248870447c7593355f23023d63f24f6 Mon Sep 17 00:00:00 2001 From: Jason Clark Date: Fri, 24 Nov 2017 14:18:46 -0700 Subject: tweaking styling --- ui/app/components/blockies/blockies-component.js | 17 +++++++++++------ ui/app/components/identicon.js | 19 ++++++++++++++++--- 2 files changed, 27 insertions(+), 9 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/blockies/blockies-component.js b/ui/app/components/blockies/blockies-component.js index d6defda16..b3a97ced4 100644 --- a/ui/app/components/blockies/blockies-component.js +++ b/ui/app/components/blockies/blockies-component.js @@ -3,25 +3,30 @@ const createElement = require('react').createElement const blockies = require("ethereum-blockies"); class BlockiesIdenticon extends Component { + constructor(props) { super(props); } + getOpts () { return { - seed: this.props.seed || "foo", - color: this.props.color || "#dfe", - bgcolor: this.props.bgcolor || "#a71", - size: this.props.size || 15, - scale: this.props.scale || 3, - spotcolor: this.props.spotcolor || "#000" + seed: this.props.seed, + color: this.props.color, + bgcolor: this.props.bgcolor, + size: this.props.size, + scale: this.props.scale, + spotcolor: this.props.spotcolor, }; } + componentDidMount() { this.draw(); } + draw() { blockies.render(this.getOpts(), this.canvas); } + render() { return createElement("canvas", {ref: canvas => this.canvas = canvas}); } diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index 9e9b82aae..c1dc0fb5c 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -32,9 +32,22 @@ IdenticonComponent.prototype.render = function () { return address ? ( useBlockie - ? h(BlockiesIdenticon, { - seed: address, - }) + ? h('div', { + className: `${className} identicon`, + style: { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + height: diameter, + width: diameter, + borderRadius: diameter / 2, + overflow: 'hidden', + }, + }, [ + h(BlockiesIdenticon, { + seed: address + }) + ]) : h('div', { className: `${className} identicon`, key: 'identicon-' + address, -- cgit v1.2.3 From 1b89ceb63aa7d96912eb32c8766ef566479dde41 Mon Sep 17 00:00:00 2001 From: Jason Clark Date: Sat, 25 Nov 2017 14:33:42 -0700 Subject: swapped out ethereum-blockies lib for MEW blockies library, tightened up identicon.js code --- ui/app/components/blockies/blockies-component.js | 35 --------- ui/app/components/identicon.js | 99 ++++++++++++------------ 2 files changed, 49 insertions(+), 85 deletions(-) delete mode 100644 ui/app/components/blockies/blockies-component.js (limited to 'ui/app/components') diff --git a/ui/app/components/blockies/blockies-component.js b/ui/app/components/blockies/blockies-component.js deleted file mode 100644 index b3a97ced4..000000000 --- a/ui/app/components/blockies/blockies-component.js +++ /dev/null @@ -1,35 +0,0 @@ -const Component = require('react').Component -const createElement = require('react').createElement -const blockies = require("ethereum-blockies"); - -class BlockiesIdenticon extends Component { - - constructor(props) { - super(props); - } - - getOpts () { - return { - seed: this.props.seed, - color: this.props.color, - bgcolor: this.props.bgcolor, - size: this.props.size, - scale: this.props.scale, - spotcolor: this.props.spotcolor, - }; - } - - componentDidMount() { - this.draw(); - } - - draw() { - blockies.render(this.getOpts(), this.canvas); - } - - render() { - return createElement("canvas", {ref: canvas => this.canvas = canvas}); - } -} - -module.exports = BlockiesIdenticon; diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index c1dc0fb5c..3e2349dbe 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -5,9 +5,9 @@ const connect = require('react-redux').connect const isNode = require('detect-node') const findDOMNode = require('react-dom').findDOMNode const jazzicon = require('jazzicon') -const BlockiesIdenticon = require('./blockies/blockies-component') const iconFactoryGen = require('../../lib/icon-factory') const iconFactory = iconFactoryGen(jazzicon) +const { toDataUrl } = require('../../lib/blockies') module.exports = connect(mapStateToProps)(IdenticonComponent) @@ -31,36 +31,19 @@ IdenticonComponent.prototype.render = function () { return address ? ( - useBlockie - ? h('div', { - className: `${className} identicon`, - style: { - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - height: diameter, - width: diameter, - borderRadius: diameter / 2, - overflow: 'hidden', - }, - }, [ - h(BlockiesIdenticon, { - seed: address - }) - ]) - : h('div', { - className: `${className} identicon`, - key: 'identicon-' + address, - style: { - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - height: diameter, - width: diameter, - borderRadius: diameter / 2, - overflow: 'hidden', - }, - }) + h('div', { + className: `${className} identicon`, + key: useBlockie ? 'blockie' : 'identicon-' + address, + style: { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + height: diameter, + width: diameter, + borderRadius: diameter / 2, + overflow: 'hidden', + }, + }) ) : ( h('img.balance-icon', { @@ -76,38 +59,54 @@ IdenticonComponent.prototype.render = function () { IdenticonComponent.prototype.componentDidMount = function () { var props = this.props - const { address } = props + const { address, useBlockie } = props if (!address) return - // eslint-disable-next-line react/no-find-dom-node - var container = findDOMNode(this) - - var diameter = props.diameter || this.defaultDiameter if (!isNode) { - var img = iconFactory.iconForAddress(address, diameter) - container.appendChild(img) + // eslint-disable-next-line react/no-find-dom-node + var container = findDOMNode(this) + + if (useBlockie) { + _generateBlockie(container, address) + } else { + const diameter = props.diameter || this.defaultDiameter + _generateJazzicon(container, address, diameter) + } } } IdenticonComponent.prototype.componentDidUpdate = function () { var props = this.props - const { address } = props + const { address, useBlockie } = props if (!address) return - // eslint-disable-next-line react/no-find-dom-node - var container = findDOMNode(this) - - var children = container.children - for (var i = 0; i < children.length; i++) { - container.removeChild(children[i]) - } - - var diameter = props.diameter || this.defaultDiameter if (!isNode) { - var img = iconFactory.iconForAddress(address, diameter) - container.appendChild(img) + // eslint-disable-next-line react/no-find-dom-node + var container = findDOMNode(this) + + var children = container.children + for (var i = 0; i < children.length; i++) { + container.removeChild(children[i]) + } + + if (useBlockie) { + _generateBlockie(container, address) + } else { + const diameter = props.diameter || this.defaultDiameter + _generateJazzicon(container, address, diameter) + } } } +function _generateBlockie(container, address) { + const img = new Image() + img.src = toDataUrl(address) + container.appendChild(img) +} + +function _generateJazzicon(container, address, diameter) { + const img = iconFactory.iconForAddress(address, diameter) + container.appendChild(img) +} -- cgit v1.2.3 From bd48d858f4226da889760e259377637164f3099c Mon Sep 17 00:00:00 2001 From: Jason Clark Date: Sat, 25 Nov 2017 15:11:29 -0700 Subject: fixing blockies display issues --- ui/app/components/identicon.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index 3e2349dbe..7a3bd5394 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -67,10 +67,11 @@ IdenticonComponent.prototype.componentDidMount = function () { // eslint-disable-next-line react/no-find-dom-node var container = findDOMNode(this) + const diameter = props.diameter || this.defaultDiameter + if (useBlockie) { _generateBlockie(container, address) } else { - const diameter = props.diameter || this.defaultDiameter _generateJazzicon(container, address, diameter) } } @@ -91,18 +92,21 @@ IdenticonComponent.prototype.componentDidUpdate = function () { container.removeChild(children[i]) } + const diameter = props.diameter || this.defaultDiameter + if (useBlockie) { - _generateBlockie(container, address) + _generateBlockie(container, address, diameter) } else { - const diameter = props.diameter || this.defaultDiameter _generateJazzicon(container, address, diameter) } } } -function _generateBlockie(container, address) { +function _generateBlockie(container, address, diameter) { const img = new Image() img.src = toDataUrl(address) + const dia = !diameter || diameter < 50 ? 50 : diameter + img.height, img.width = dia * 1.25 container.appendChild(img) } -- cgit v1.2.3 From 75ef848196646e060703764e97656ab3abd8c023 Mon Sep 17 00:00:00 2001 From: Jason Clark Date: Sat, 25 Nov 2017 15:47:34 -0700 Subject: making eslint happy --- ui/app/components/identicon.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index 7a3bd5394..5b3786992 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -20,7 +20,7 @@ function IdenticonComponent () { function mapStateToProps (state) { return { - useBlockie: state.metamask.useBlockie + useBlockie: state.metamask.useBlockie, } } @@ -102,15 +102,16 @@ IdenticonComponent.prototype.componentDidUpdate = function () { } } -function _generateBlockie(container, address, diameter) { +function _generateBlockie (container, address, diameter) { const img = new Image() img.src = toDataUrl(address) const dia = !diameter || diameter < 50 ? 50 : diameter - img.height, img.width = dia * 1.25 + img.height = dia * 1.25 + img.width = dia * 1.25 container.appendChild(img) } -function _generateJazzicon(container, address, diameter) { +function _generateJazzicon (container, address, diameter) { const img = iconFactory.iconForAddress(address, diameter) container.appendChild(img) } -- cgit v1.2.3 From a34362b7765f48d24375c9953fa7c49cf3306491 Mon Sep 17 00:00:00 2001 From: Jason Clark Date: Mon, 27 Nov 2017 08:11:48 -0700 Subject: Fixes changes requested in pullrequestreview-79088534 --- ui/app/components/identicon.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index 5b3786992..ddd7e65f3 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -33,7 +33,7 @@ IdenticonComponent.prototype.render = function () { ? ( h('div', { className: `${className} identicon`, - key: useBlockie ? 'blockie' : 'identicon-' + address, + key: 'identicon-' + address, style: { display: 'flex', alignItems: 'center', @@ -70,7 +70,7 @@ IdenticonComponent.prototype.componentDidMount = function () { const diameter = props.diameter || this.defaultDiameter if (useBlockie) { - _generateBlockie(container, address) + _generateBlockie(container, address, diameter) } else { _generateJazzicon(container, address, diameter) } -- cgit v1.2.3 From f131468353aa518b8fc178cd591bfc7ab5bdc32c Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Tue, 28 Nov 2017 13:37:45 -0600 Subject: Remove useBlockie in props for render Removed unused useBlock for Lint validation. --- ui/app/components/identicon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index ddd7e65f3..b803b7ceb 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -26,7 +26,7 @@ function mapStateToProps (state) { IdenticonComponent.prototype.render = function () { var props = this.props - const { className = '', address, useBlockie } = props + const { className = '', address } = props var diameter = props.diameter || this.defaultDiameter return address -- cgit v1.2.3 From 7dba114feb428f7f2f78fee5611377b04bff5be6 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Fri, 1 Dec 2017 14:19:53 -0800 Subject: Update font weights to 300, remove animation from network dropdown, fix network dropdown not closing from certain click-areas --- ui/app/components/dropdowns/network-dropdown.js | 27 +++++++++++++++---------- ui/app/components/network.js | 14 ++++++------- 2 files changed, 23 insertions(+), 18 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js index 0908faf01..dfaa6b22c 100644 --- a/ui/app/components/dropdowns/network-dropdown.js +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -6,6 +6,16 @@ const actions = require('../../actions') const Dropdown = require('./components/dropdown').Dropdown const DropdownMenuItem = require('./components/dropdown').DropdownMenuItem const NetworkDropdownIcon = require('./components/network-dropdown-icon') +const R = require('ramda') + +// classes from nodes of the toggle element. +const notToggleElementClassnames = [ + 'menu-icon', + 'network-name', + 'network-indicator', + 'network-caret', + 'network-component', +] function mapStateToProps (state) { return { @@ -32,8 +42,8 @@ function mapDispatchToProps (dispatch) { showConfigPage: () => { dispatch(actions.showConfigPage()) }, - showNetworkDropdown: () => { dispatch(actions.showNetworkDropdown()) }, - hideNetworkDropdown: () => { dispatch(actions.hideNetworkDropdown()) }, + showNetworkDropdown: () => dispatch(actions.showNetworkDropdown()), + hideNetworkDropdown: () => dispatch(actions.hideNetworkDropdown()), } } @@ -59,18 +69,13 @@ NetworkDropdown.prototype.render = function () { } return h(Dropdown, { - useCssTransition: true, isOpen, onClickOutside: (event) => { const { classList } = event.target - const isNotToggleElement = [ - classList.contains('menu-icon'), - classList.contains('network-name'), - classList.contains('network-indicator'), - ].filter(bool => bool).length === 0 - // classes from three constituent nodes of the toggle element - - if (isNotToggleElement) { + const isInClassList = className => classList.contains(className) + const notToggleElementIndex = R.findIndex(isInClassList)(notToggleElementClassnames) + + if (notToggleElementIndex === -1) { this.props.hideNetworkDropdown() } }, diff --git a/ui/app/components/network.js b/ui/app/components/network.js index 915818009..5a8d0763d 100644 --- a/ui/app/components/network.js +++ b/ui/app/components/network.js @@ -39,7 +39,7 @@ Network.prototype.render = function () { }, src: 'images/loading.svg', }), - h('i.fa.fa-caret-down'), + h('i.fa.fa-caret-down.network-caret'), ]) } else if (providerName === 'mainnet') { hoverText = 'Main Ethereum Network' @@ -63,7 +63,7 @@ Network.prototype.render = function () { return ( h('div.network-component.pointer', { - className: classnames('network-component pointer', { + className: classnames({ 'network-component--disabled': this.props.disabled, 'ethereum-network': providerName === 'mainnet', 'ropsten-test-network': providerName === 'ropsten' || parseInt(networkNumber) === 3, @@ -90,7 +90,7 @@ Network.prototype.render = function () { color: '#039396', }}, 'Main Network'), - h('i.fa.fa-caret-down.fa-lg'), + h('i.fa.fa-caret-down.fa-lg.network-caret'), ]) case 'ropsten-test-network': return h('.network-indicator', [ @@ -103,7 +103,7 @@ Network.prototype.render = function () { color: '#ff6666', }}, 'Ropsten Test Net'), - h('i.fa.fa-caret-down.fa-lg'), + h('i.fa.fa-caret-down.fa-lg.network-caret'), ]) case 'kovan-test-network': return h('.network-indicator', [ @@ -116,7 +116,7 @@ Network.prototype.render = function () { color: '#690496', }}, 'Kovan Test Net'), - h('i.fa.fa-caret-down.fa-lg'), + h('i.fa.fa-caret-down.fa-lg.network-caret'), ]) case 'rinkeby-test-network': return h('.network-indicator', [ @@ -129,7 +129,7 @@ Network.prototype.render = function () { color: '#e7a218', }}, 'Rinkeby Test Net'), - h('i.fa.fa-caret-down.fa-lg'), + h('i.fa.fa-caret-down.fa-lg.network-caret'), ]) default: return h('.network-indicator', [ @@ -145,7 +145,7 @@ Network.prototype.render = function () { color: '#AEAEAE', }}, 'Private Network'), - h('i.fa.fa-caret-down.fa-lg'), + h('i.fa.fa-caret-down.fa-lg.network-caret'), ]) } })(), -- cgit v1.2.3 From 9db00fa507c04180f6425cc3b1e3187afa193ab8 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 4 Dec 2017 22:30:11 -0330 Subject: Show user notifications after switch between UIs --- ui/app/components/modals/modal.js | 37 +++++++++++++++++++ ui/app/components/modals/notification-modal.js | 51 ++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 ui/app/components/modals/notification-modal.js (limited to 'ui/app/components') diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index f2909f3c3..2ff6accaa 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -16,6 +16,7 @@ const NewAccountModal = require('./new-account-modal') const ShapeshiftDepositTxModal = require('./shapeshift-deposit-tx-modal.js') const HideTokenConfirmationModal = require('./hide-token-confirmation-modal') const CustomizeGasModal = require('../customize-gas-modal') +const NotifcationModal = require('./notification-modal') const accountModalStyle = { mobileModalStyle: { @@ -133,6 +134,42 @@ const MODALS = { }, }, + BETA_UI_NOTIFICATION_MODAL: { + contents: [ + h(NotifcationModal, { + header: 'Welcome to the New UI (Beta)', + message: `You are now using the new Metamask UI. Take a look around, try out new features like sending tokens, + and let us know if you have any issues.`, + }), + ], + mobileModalStyle: { + width: '95%', + top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh', + }, + laptopModalStyle: { + width: '449px', + top: 'calc(33% + 45px)', + }, + }, + + OLD_UI_NOTIFICATION_MODAL: { + contents: [ + h(NotifcationModal, { + header: 'Old UI', + message: `You have returned to the old UI. You can switch back to the New UI through the option in the top + right dropdown menu.`, + }), + ], + mobileModalStyle: { + width: '95%', + top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh', + }, + laptopModalStyle: { + width: '449px', + top: 'calc(33% + 45px)', + }, + }, + NEW_ACCOUNT: { contents: [ h(NewAccountModal, {}, []), diff --git a/ui/app/components/modals/notification-modal.js b/ui/app/components/modals/notification-modal.js new file mode 100644 index 000000000..239144b0c --- /dev/null +++ b/ui/app/components/modals/notification-modal.js @@ -0,0 +1,51 @@ +const { Component } = require('react') +const PropTypes = require('prop-types') +const h = require('react-hyperscript') +const { connect } = require('react-redux') +const actions = require('../../actions') + +class NotificationModal extends Component { + render () { + const { + header, + message, + } = this.props + + return h('div', [ + h('div.notification-modal-wrapper', { + }, [ + + h('div.notification-modal-header', {}, [ + header, + ]), + + h('div.notification-modal-message-wrapper', {}, [ + h('div.notification-modal-message', {}, [ + message, + ]), + ]), + + h('div.modal-close-x', { + onClick: this.props.hideModal, + }), + + ]), + ]) + } +} + +NotificationModal.propTypes = { + hideModal: PropTypes.func, + header: PropTypes.string, + message: PropTypes.string, +} + +const mapDispatchToProps = dispatch => { + return { + hideModal: () => { + dispatch(actions.hideModal()) + }, + } +} + +module.exports = connect(null, mapDispatchToProps)(NotificationModal) -- cgit v1.2.3 From 2e9137dddd4abd07cc45caa670f09bdc9559bbbb Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 16 Nov 2017 14:44:25 -0330 Subject: Update max amount behaviour to meet new specs. --- ui/app/components/customize-gas-modal/index.js | 22 +++++++++++++++++++++- ui/app/components/send/send-v2-container.js | 1 + 2 files changed, 22 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 485dacf90..826d2cd4b 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -5,6 +5,8 @@ const connect = require('react-redux').connect const actions = require('../../actions') const GasModalCard = require('./gas-modal-card') +const ethUtil = require('ethereumjs-util') + const { MIN_GAS_PRICE_DEC, MIN_GAS_LIMIT_DEC, @@ -19,6 +21,7 @@ const { conversionUtil, multiplyCurrencies, conversionGreaterThan, + subtractCurrencies, } = require('../../conversion-util') const { @@ -30,6 +33,7 @@ const { getSendFrom, getCurrentAccountWithSendEtherInfo, getSelectedTokenToFiatRate, + getSendMaxModeState, } = require('../../selectors') function mapStateToProps (state) { @@ -42,6 +46,7 @@ function mapStateToProps (state) { gasLimit: getGasLimit(state), conversionRate, amount: getSendAmount(state), + maxModeOn: getSendMaxModeState(state), balance: currentAccount.balance, primaryCurrency: selectedToken && selectedToken.symbol, selectedToken, @@ -55,6 +60,7 @@ function mapDispatchToProps (dispatch) { updateGasPrice: newGasPrice => dispatch(actions.updateGasPrice(newGasPrice)), updateGasLimit: newGasLimit => dispatch(actions.updateGasLimit(newGasLimit)), updateGasTotal: newGasTotal => dispatch(actions.updateGasTotal(newGasTotal)), + updateSendAmount: newAmount => dispatch(actions.updateSendAmount(newAmount)), } } @@ -93,8 +99,21 @@ CustomizeGasModal.prototype.save = function (gasPrice, gasLimit, gasTotal) { updateGasLimit, hideModal, updateGasTotal, + maxModeOn, + selectedToken, + balance, + updateSendAmount, } = this.props + if (maxModeOn && !selectedToken) { + const maxAmount = subtractCurrencies( + ethUtil.addHexPrefix(balance), + ethUtil.addHexPrefix(gasTotal), + { toNumericBase: 'hex' } + ) + updateSendAmount(maxAmount) + } + updateGasPrice(gasPrice) updateGasLimit(gasLimit) updateGasTotal(gasTotal) @@ -112,12 +131,13 @@ CustomizeGasModal.prototype.validate = function ({ gasTotal, gasLimit }) { selectedToken, amountConversionRate, conversionRate, + maxModeOn, } = this.props let error = null const balanceIsSufficient = isBalanceSufficient({ - amount: selectedToken ? '0' : amount, + amount: selectedToken || maxModeOn ? '0' : amount, gasTotal, balance, selectedToken, diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js index 4451a6113..655de8897 100644 --- a/ui/app/components/send/send-v2-container.js +++ b/ui/app/components/send/send-v2-container.js @@ -78,5 +78,6 @@ function mapDispatchToProps (dispatch) { goHome: () => dispatch(actions.goHome()), clearSend: () => dispatch(actions.clearSend()), backToConfirmScreen: editingTransactionId => dispatch(actions.showConfTxPage({ id: editingTransactionId })), + setMaxModeTo: bool => dispatch(actions.setMaxModeTo(bool)), } } -- cgit v1.2.3 From 05c6789030791bd1b46434cf89c1817db37e8f38 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 8 Dec 2017 21:18:08 -0330 Subject: Adds button for opening app in main browser window in extension. --- ui/app/components/tx-view.js | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index ebef22680..832f8e56a 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -107,6 +107,7 @@ TxView.prototype.render = function () { h('div.flex-row.phone-visible', { style: { margin: '1em 0.9em', + justifyContent: 'space-between', alignItems: 'center', }, }, [ @@ -139,6 +140,10 @@ TxView.prototype.render = function () { identity.name, ]), + h('div.open-in-browser', { + onClick: () => global.platform.openExtensionInBrowser(), + }, [h('img', { src: 'images/open.svg' })]) + ]), this.renderHeroBalance(), -- cgit v1.2.3 From 4b654669e692665aba88a14cb5804370dbfd4a80 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 8 Dec 2017 21:52:31 -0330 Subject: Hide open in browser button on mobile (but still show on extension); adds a function to detect if viewing with mobile browser. --- ui/app/components/tx-view.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 832f8e56a..bd52ac4c2 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -3,6 +3,7 @@ const connect = require('react-redux').connect const h = require('react-hyperscript') const ethUtil = require('ethereumjs-util') const inherits = require('util').inherits +const isMobileBrowser = require('../../lib/is-mobile-browser') const actions = require('../actions') const selectors = require('../selectors') @@ -140,9 +141,9 @@ TxView.prototype.render = function () { identity.name, ]), - h('div.open-in-browser', { + !isMobileBrowser() && h('div.open-in-browser', { onClick: () => global.platform.openExtensionInBrowser(), - }, [h('img', { src: 'images/open.svg' })]) + }, [h('img', { src: 'images/open.svg' })]), ]), -- cgit v1.2.3 From 57c91435a7357165441252acfffcdaff6e54e422 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 12 Dec 2017 16:21:05 -0330 Subject: Substitute isMascara check for explicit check if user is on mobile browser. --- ui/app/components/tx-view.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index bd52ac4c2..0f8a54a74 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -15,6 +15,7 @@ module.exports = connect(mapStateToProps, mapDispatchToProps)(TxView) function mapStateToProps (state) { const sidebarOpen = state.appState.sidebarOpen + const isMascara = state.appState.isMascara const identities = state.metamask.identities const accounts = state.metamask.accounts @@ -141,7 +142,7 @@ TxView.prototype.render = function () { identity.name, ]), - !isMobileBrowser() && h('div.open-in-browser', { + !isMascara && h('div.open-in-browser', { onClick: () => global.platform.openExtensionInBrowser(), }, [h('img', { src: 'images/open.svg' })]), -- cgit v1.2.3 From 515437a4c956e47a5f1d4522715a9021e08d3408 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 12 Dec 2017 12:22:22 -0800 Subject: Fix isMascara and update yarn.lock --- ui/app/components/tx-view.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 0f8a54a74..e42a20c85 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -3,7 +3,6 @@ const connect = require('react-redux').connect const h = require('react-hyperscript') const ethUtil = require('ethereumjs-util') const inherits = require('util').inherits -const isMobileBrowser = require('../../lib/is-mobile-browser') const actions = require('../actions') const selectors = require('../selectors') @@ -33,6 +32,7 @@ function mapStateToProps (state) { selectedToken: selectors.getSelectedToken(state), identity, network, + isMascara, } } @@ -100,7 +100,7 @@ TxView.prototype.renderButtons = function () { } TxView.prototype.render = function () { - const { selectedAddress, identity, network } = this.props + const { selectedAddress, identity, network, isMascara } = this.props return h('div.tx-view.flex-column', { style: {}, -- cgit v1.2.3 From 339eb7d1a687f141e822c745c568063783d44f15 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Wed, 13 Dec 2017 02:54:41 -0330 Subject: Fix edit to field bug. (#2738) --- ui/app/components/pending-tx/confirm-send-token.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index cc2df8299..727cd260b 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -67,15 +67,15 @@ function mapDispatchToProps (dispatch, ownProps) { const { txParams, id } = txMeta const tokenData = txParams.data && abiDecoder.decodeMethod(txParams.data) const { params = [] } = tokenData - const { value } = params[1] || {} - const amount = conversionUtil(value, { + const { value: to } = params[0] || {} + const { value: tokenAmountInDec } = params[1] || {} + const tokenAmountInHex = conversionUtil(tokenAmountInDec, { fromNumericBase: 'dec', toNumericBase: 'hex', }) const { gas: gasLimit, gasPrice, - to, } = txParams dispatch(actions.setSelectedToken(address)) dispatch(actions.updateSend({ @@ -83,7 +83,7 @@ function mapDispatchToProps (dispatch, ownProps) { gasPrice, gasTotal: null, to, - amount, + amount: tokenAmountInHex, errors: { to: null, amount: null }, editingTransactionId: id, })) @@ -446,10 +446,11 @@ ConfirmSendToken.prototype.gatherTxMeta = function () { amount, gasLimit: gas, gasPrice, + to, }, } = props - const { txParams: { from, to } } = txData + const { txParams: { from, to: tokenAddress } } = txData const tokenParams = { from: ethUtil.addHexPrefix(from), @@ -465,7 +466,7 @@ ConfirmSendToken.prototype.gatherTxMeta = function () { txData.txParams = { ...tokenParams, - to: ethUtil.addHexPrefix(to), + to: ethUtil.addHexPrefix(tokenAddress), memo: memo && ethUtil.addHexPrefix(memo), data, } -- cgit v1.2.3 From 0feb5b210b81533fc25c4760ce33876b4c749247 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 20 Dec 2017 14:19:13 -0330 Subject: Hides the sidebar after the an account menu actions changes the screen behind the sidebar. --- ui/app/components/account-menu/index.js | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'ui/app/components') diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index a9f075ec7..286a3b587 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -28,27 +28,33 @@ function mapDispatchToProps (dispatch) { toggleAccountMenu: () => dispatch(actions.toggleAccountMenu()), showAccountDetail: address => { dispatch(actions.showAccountDetail(address)) + dispatch(actions.hideSidebar()) dispatch(actions.toggleAccountMenu()) }, lockMetamask: () => { dispatch(actions.lockMetamask()) dispatch(actions.displayWarning(null)) + dispatch(actions.hideSidebar()) dispatch(actions.toggleAccountMenu()) }, showConfigPage: () => { dispatch(actions.showConfigPage()) + dispatch(actions.hideSidebar()) dispatch(actions.toggleAccountMenu()) }, showNewAccountModal: () => { dispatch(actions.showModal({ name: 'NEW_ACCOUNT' })) + dispatch(actions.hideSidebar()) dispatch(actions.toggleAccountMenu()) }, showImportPage: () => { dispatch(actions.showImportPage()) + dispatch(actions.hideSidebar()) dispatch(actions.toggleAccountMenu()) }, showInfoPage: () => { dispatch(actions.showInfoPage()) + dispatch(actions.hideSidebar()) dispatch(actions.toggleAccountMenu()) }, } -- cgit v1.2.3 From 109e4e5d96e31b52fcfdb22620bff113107d000c Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 19 Dec 2017 14:02:32 -0330 Subject: Hide fiat values on account details screen when eth/token value is 0. --- ui/app/components/balance-component.js | 3 ++- ui/app/components/token-cell.js | 4 +++- ui/app/components/tx-list-item.js | 4 +++- 3 files changed, 8 insertions(+), 3 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/balance-component.js b/ui/app/components/balance-component.js index d14aa675f..50007ce14 100644 --- a/ui/app/components/balance-component.js +++ b/ui/app/components/balance-component.js @@ -94,7 +94,8 @@ BalanceComponent.prototype.renderFiatValue = function (formattedBalance) { } BalanceComponent.prototype.renderFiatAmount = function (fiatDisplayNumber, fiatSuffix, fiatPrefix) { - if (fiatDisplayNumber === 'N/A') return null + const shouldNotRenderFiat = fiatDisplayNumber === 'N/A' || Number(fiatDisplayNumber) === 0 + if (shouldNotRenderFiat) return null return h('div.fiat-amount', { style: {}, diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index b40c0ec0d..677b66830 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -86,7 +86,9 @@ TokenCell.prototype.render = function () { numberOfDecimals: 2, conversionRate: currentTokenToFiatRate, }) - formattedFiat = `${currentTokenInFiat} ${currentCurrency.toUpperCase()}` + formattedFiat = currentTokenInFiat.toString() === '0' + ? '' + : `${currentTokenInFiat} ${currentCurrency.toUpperCase()}` } const showFiat = Boolean(currentTokenInFiat) && currentCurrency.toUpperCase() !== symbol diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 4e76147a1..8a9253d4d 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -170,6 +170,7 @@ TxListItem.prototype.getSendTokenTotal = async function () { TxListItem.prototype.render = function () { const { transactionStatus, + transactionAmount, onClick, transActionId, dateString, @@ -177,6 +178,7 @@ TxListItem.prototype.render = function () { className, } = this.props const { total, fiatTotal } = this.state + const showFiatTotal = transactionAmount !== '0x0' && fiatTotal return h(`div${className || ''}`, { key: transActionId, @@ -238,7 +240,7 @@ TxListItem.prototype.render = function () { }), }, total), - fiatTotal && h('span.tx-list-fiat-value', fiatTotal), + showFiatTotal && h('span.tx-list-fiat-value', fiatTotal), ]), ]), -- cgit v1.2.3 From 1f1fc2c49ecbb5c6a0a1d925d5c02cf48f795b2f Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 19 Dec 2017 11:16:11 -0330 Subject: Canceled, edited transactions show edited amount. --- ui/app/components/pending-tx/confirm-send-ether.js | 9 ++++++++- ui/app/components/pending-tx/confirm-send-token.js | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 1264da153..01195502e 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -55,6 +55,7 @@ function mapDispatchToProps (dispatch) { dispatch(actions.showSendPage()) }, cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), + updateAndCancelTx: txMeta => dispatch(actions.updateAndCancelTx(txMeta)), } } @@ -421,7 +422,13 @@ ConfirmSendEther.prototype.onSubmit = function (event) { ConfirmSendEther.prototype.cancel = function (event, txMeta) { event.preventDefault() - this.props.cancelTransaction(txMeta) + const { send, updateAndCancelTx, cancelTransaction } = this.props + + if (send.editingTransactionId) { + updateAndCancelTx(txMeta) + } else { + cancelTransaction(txMeta) + } } ConfirmSendEther.prototype.checkValidity = function () { diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index 727cd260b..e6ce3f6e6 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -89,6 +89,7 @@ function mapDispatchToProps (dispatch, ownProps) { })) dispatch(actions.showSendTokenPage()) }, + updateAndCancelTx: txMeta => dispatch(actions.updateAndCancelTx(txMeta)), } } @@ -415,7 +416,13 @@ ConfirmSendToken.prototype.onSubmit = function (event) { ConfirmSendToken.prototype.cancel = function (event, txMeta) { event.preventDefault() - this.props.cancelTransaction(txMeta) + const { send, updateAndCancelTx, cancelTransaction } = this.props + + if (send.editingTransactionId) { + updateAndCancelTx(txMeta) + } else { + cancelTransaction(txMeta) + } } ConfirmSendToken.prototype.checkValidity = function () { -- cgit v1.2.3 From bf4043c59bb67ea93599207d91cb7a4f4426e75f Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 20 Dec 2017 13:47:16 -0330 Subject: Adds updateTransaction to background and used it to update after editing in send-v2. --- ui/app/components/pending-tx/confirm-send-ether.js | 29 ++------------- ui/app/components/pending-tx/confirm-send-token.js | 42 ++-------------------- ui/app/components/send/send-v2-container.js | 2 ++ 3 files changed, 6 insertions(+), 67 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 01195502e..566224864 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -55,7 +55,6 @@ function mapDispatchToProps (dispatch) { dispatch(actions.showSendPage()) }, cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), - updateAndCancelTx: txMeta => dispatch(actions.updateAndCancelTx(txMeta)), } } @@ -422,13 +421,9 @@ ConfirmSendEther.prototype.onSubmit = function (event) { ConfirmSendEther.prototype.cancel = function (event, txMeta) { event.preventDefault() - const { send, updateAndCancelTx, cancelTransaction } = this.props + const { cancelTransaction } = this.props - if (send.editingTransactionId) { - updateAndCancelTx(txMeta) - } else { - cancelTransaction(txMeta) - } + cancelTransaction(txMeta) } ConfirmSendEther.prototype.checkValidity = function () { @@ -452,26 +447,6 @@ ConfirmSendEther.prototype.gatherTxMeta = function () { const state = this.state const txData = clone(state.txData) || clone(props.txData) - if (props.send.editingTransactionId) { - const { - send: { - memo, - amount: value, - gasLimit: gas, - gasPrice, - }, - } = props - const { txParams: { from, to } } = txData - txData.txParams = { - from: ethUtil.addHexPrefix(from), - to: ethUtil.addHexPrefix(to), - memo: memo && ethUtil.addHexPrefix(memo), - value: ethUtil.addHexPrefix(value), - gas: ethUtil.addHexPrefix(gas), - gasPrice: ethUtil.addHexPrefix(gasPrice), - } - } - // log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`) return txData } diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index e6ce3f6e6..a07835911 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -89,7 +89,6 @@ function mapDispatchToProps (dispatch, ownProps) { })) dispatch(actions.showSendTokenPage()) }, - updateAndCancelTx: txMeta => dispatch(actions.updateAndCancelTx(txMeta)), } } @@ -416,13 +415,9 @@ ConfirmSendToken.prototype.onSubmit = function (event) { ConfirmSendToken.prototype.cancel = function (event, txMeta) { event.preventDefault() - const { send, updateAndCancelTx, cancelTransaction } = this.props + const { send, cancelTransaction } = this.props - if (send.editingTransactionId) { - updateAndCancelTx(txMeta) - } else { - cancelTransaction(txMeta) - } + cancelTransaction(txMeta) } ConfirmSendToken.prototype.checkValidity = function () { @@ -446,39 +441,6 @@ ConfirmSendToken.prototype.gatherTxMeta = function () { const state = this.state const txData = clone(state.txData) || clone(props.txData) - if (props.send.editingTransactionId) { - const { - send: { - memo, - amount, - gasLimit: gas, - gasPrice, - to, - }, - } = props - - const { txParams: { from, to: tokenAddress } } = txData - - const tokenParams = { - from: ethUtil.addHexPrefix(from), - value: '0', - gas: ethUtil.addHexPrefix(gas), - gasPrice: ethUtil.addHexPrefix(gasPrice), - } - - const data = '0xa9059cbb' + Array.prototype.map.call( - ethAbi.rawEncode(['address', 'uint256'], [to, ethUtil.addHexPrefix(amount)]), - x => ('00' + x.toString(16)).slice(-2) - ).join('') - - txData.txParams = { - ...tokenParams, - to: ethUtil.addHexPrefix(tokenAddress), - memo: memo && ethUtil.addHexPrefix(memo), - data, - } - } - // log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`) return txData } diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js index 655de8897..ff7714e82 100644 --- a/ui/app/components/send/send-v2-container.js +++ b/ui/app/components/send/send-v2-container.js @@ -50,6 +50,7 @@ function mapStateToProps (state) { data, amountConversionRate: selectedToken ? tokenToFiatRate : conversionRate, tokenContract: getSelectedTokenContract(state), + unapprovedTxs: state.metamask.unapprovedTxs, } } @@ -64,6 +65,7 @@ function mapDispatchToProps (dispatch) { ), signTx: txParams => dispatch(actions.signTx(txParams)), updateAndApproveTx: txParams => dispatch(actions.updateAndApproveTx(txParams)), + updateTx: txData => dispatch(actions.updateTransaction(txData)), setSelectedAddress: address => dispatch(actions.setSelectedAddress(address)), addToAddressBook: address => dispatch(actions.addToAddressBook(address)), updateGasTotal: newTotal => dispatch(actions.updateGasTotal(newTotal)), -- cgit v1.2.3 From 5fe3c5aae6756f225edd0f8646ac0a23c264a81c Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 20 Dec 2017 15:05:41 -0330 Subject: Lint fixes. --- ui/app/components/pending-tx/confirm-send-token.js | 3 +-- ui/app/components/send/send-v2-container.js | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index a07835911..aa4f29fb0 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -2,7 +2,6 @@ const Component = require('react').Component const { connect } = require('react-redux') const h = require('react-hyperscript') const inherits = require('util').inherits -const ethAbi = require('ethereumjs-abi') const tokenAbi = require('human-standard-token-abi') const abiDecoder = require('abi-decoder') abiDecoder.addABI(tokenAbi) @@ -415,7 +414,7 @@ ConfirmSendToken.prototype.onSubmit = function (event) { ConfirmSendToken.prototype.cancel = function (event, txMeta) { event.preventDefault() - const { send, cancelTransaction } = this.props + const { cancelTransaction } = this.props cancelTransaction(txMeta) } diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js index ff7714e82..2d2ed4546 100644 --- a/ui/app/components/send/send-v2-container.js +++ b/ui/app/components/send/send-v2-container.js @@ -79,7 +79,6 @@ function mapDispatchToProps (dispatch) { updateSendErrors: newError => dispatch(actions.updateSendErrors(newError)), goHome: () => dispatch(actions.goHome()), clearSend: () => dispatch(actions.clearSend()), - backToConfirmScreen: editingTransactionId => dispatch(actions.showConfTxPage({ id: editingTransactionId })), setMaxModeTo: bool => dispatch(actions.setMaxModeTo(bool)), } } -- cgit v1.2.3 From 9ced63584bc93cf6ac82786dec0984b5022346ae Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 20 Dec 2017 19:06:58 -0330 Subject: Add constanst for token transfer function signature. --- ui/app/components/send/send-constants.js | 3 +++ 1 file changed, 3 insertions(+) (limited to 'ui/app/components') diff --git a/ui/app/components/send/send-constants.js b/ui/app/components/send/send-constants.js index 9c240972f..b3ee0899a 100644 --- a/ui/app/components/send/send-constants.js +++ b/ui/app/components/send/send-constants.js @@ -20,6 +20,8 @@ const MIN_GAS_TOTAL = multiplyCurrencies(MIN_GAS_LIMIT_HEX, MIN_GAS_PRICE_HEX, { multiplierBase: 16, }) +const TOKEN_TRANSFER_FUNCTION_SIGNATURE = '0xa9059cbb' + module.exports = { MIN_GAS_PRICE_GWEI, MIN_GAS_PRICE_HEX, @@ -27,4 +29,5 @@ module.exports = { MIN_GAS_LIMIT_HEX, MIN_GAS_LIMIT_DEC, MIN_GAS_TOTAL, + TOKEN_TRANSFER_FUNCTION_SIGNATURE, } -- cgit v1.2.3 From 208e94d3bfdaf5ab6f279fb2000f1a3d14920b1b Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Wed, 10 Jan 2018 21:09:09 -0800 Subject: Update main view styling --- ui/app/components/balance-component.js | 2 +- ui/app/components/token-cell.js | 2 +- ui/app/components/tx-view.js | 14 +++----------- 3 files changed, 5 insertions(+), 13 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/balance-component.js b/ui/app/components/balance-component.js index 50007ce14..d591ab455 100644 --- a/ui/app/components/balance-component.js +++ b/ui/app/components/balance-component.js @@ -40,7 +40,7 @@ BalanceComponent.prototype.render = function () { // style: {}, // }), h(Identicon, { - diameter: 45, + diameter: 50, address: token && token.address, network, }), diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index 677b66830..59552f4a0 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -106,7 +106,7 @@ TokenCell.prototype.render = function () { h(Identicon, { className: 'token-list-item__identicon', - diameter: 45, + diameter: 50, address, network, }), diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index e42a20c85..7bddbbef4 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -68,18 +68,14 @@ TxView.prototype.renderButtons = function () { return !selectedToken ? ( h('div.flex-row.flex-center.hero-balance-buttons', [ - h('button.btn-clear', { - style: { - textAlign: 'center', - }, + h('button.hero-balance-button', { onClick: () => showModal({ name: 'BUY', }), }, 'DEPOSIT'), - h('button.btn-clear', { + h('button.hero-balance-button', { style: { - textAlign: 'center', marginLeft: '0.8em', }, onClick: showSendPage, @@ -88,11 +84,7 @@ TxView.prototype.renderButtons = function () { ) : ( h('div.flex-row.flex-center.hero-balance-buttons', [ - h('button.btn-clear', { - style: { - textAlign: 'center', - marginLeft: '0.8em', - }, + h('button.hero-balance-button', { onClick: showSendTokenPage, }, 'SEND'), ]) -- cgit v1.2.3 From b8310ac62e358af9a6a9f3ed1e0ffa25a2a00b8d Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Thu, 11 Jan 2018 15:49:10 -0800 Subject: Fix logging out of old UI causing infinite spinner (#2914) --- ui/app/components/account-menu/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index 286a3b587..1b62b42fb 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -33,7 +33,7 @@ function mapDispatchToProps (dispatch) { }, lockMetamask: () => { dispatch(actions.lockMetamask()) - dispatch(actions.displayWarning(null)) + dispatch(actions.hideWarning()) dispatch(actions.hideSidebar()) dispatch(actions.toggleAccountMenu()) }, -- cgit v1.2.3 From 376e1365727a97344d70d627ae27e8e70830a17a Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Thu, 11 Jan 2018 16:30:07 -0800 Subject: Update styling for buttons, font weights --- ui/app/components/modals/account-details-modal.js | 4 ++-- ui/app/components/modals/export-private-key-modal.js | 10 +++++++--- ui/app/components/pending-tx/confirm-send-ether.js | 4 ++-- ui/app/components/pending-tx/confirm-send-token.js | 4 ++-- ui/app/components/tx-view.js | 6 +++--- ui/app/components/wallet-view.js | 4 ++-- 6 files changed, 18 insertions(+), 14 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/account-details-modal.js b/ui/app/components/modals/account-details-modal.js index 4bf671834..c1f7a3236 100644 --- a/ui/app/components/modals/account-details-modal.js +++ b/ui/app/components/modals/account-details-modal.js @@ -62,12 +62,12 @@ AccountDetailsModal.prototype.render = function () { h('div.account-modal-divider'), - h('button.btn-clear', { + h('button.btn-clear.account-modal__button', { onClick: () => global.platform.openWindow({ url: genAccountLink(address, network) }), }, 'View account on Etherscan'), // Holding on redesign for Export Private Key functionality - h('button.btn-clear', { + h('button.btn-clear.account-modal__button', { onClick: () => showExportPrivateKeyModal(), }, 'Export private key'), diff --git a/ui/app/components/modals/export-private-key-modal.js b/ui/app/components/modals/export-private-key-modal.js index 193755df5..422f23f44 100644 --- a/ui/app/components/modals/export-private-key-modal.js +++ b/ui/app/components/modals/export-private-key-modal.js @@ -79,11 +79,15 @@ ExportPrivateKeyModal.prototype.renderButton = function (className, onClick, lab ExportPrivateKeyModal.prototype.renderButtons = function (privateKey, password, address, hideModal) { return h('div.export-private-key-buttons', {}, [ - !privateKey && this.renderButton('btn-clear btn-cancel', () => hideModal(), 'Cancel'), + !privateKey && this.renderButton( + 'btn-cancel export-private-key__button export-private-key__button--cancel', + () => hideModal(), + 'Cancel' + ), (privateKey - ? this.renderButton('btn-clear', () => hideModal(), 'Done') - : this.renderButton('btn-clear', () => this.exportAccountAndGetPrivateKey(this.state.password, address), 'Show') + ? this.renderButton('btn-clear export-private-key__button', () => hideModal(), 'Done') + : this.renderButton('btn-clear export-private-key__button', () => this.exportAccountAndGetPrivateKey(this.state.password, address), 'Confirm') ), ]) diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 566224864..652300c94 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -219,7 +219,7 @@ ConfirmSendEther.prototype.render = function () { // Main Send token Card h('div.confirm-screen-wrapper.flex-column.flex-grow', [ h('h3.flex-center.confirm-screen-header', [ - h('button.confirm-screen-back-button', { + h('button.btn-clear.confirm-screen-back-button', { onClick: () => editTransaction(txMeta), }, 'EDIT'), h('div.confirm-screen-title', 'Confirm Transaction'), @@ -422,7 +422,7 @@ ConfirmSendEther.prototype.onSubmit = function (event) { ConfirmSendEther.prototype.cancel = function (event, txMeta) { event.preventDefault() const { cancelTransaction } = this.props - + cancelTransaction(txMeta) } diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index aa4f29fb0..ad489c3e9 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -314,7 +314,7 @@ ConfirmSendToken.prototype.render = function () { // Main Send token Card h('div.confirm-screen-wrapper.flex-column.flex-grow', [ h('h3.flex-center.confirm-screen-header', [ - h('button.confirm-screen-back-button', { + h('button.btn-clear.confirm-screen-back-button', { onClick: () => editTransaction(txMeta), }, 'EDIT'), h('div.confirm-screen-title', 'Confirm Transaction'), @@ -415,7 +415,7 @@ ConfirmSendToken.prototype.onSubmit = function (event) { ConfirmSendToken.prototype.cancel = function (event, txMeta) { event.preventDefault() const { cancelTransaction } = this.props - + cancelTransaction(txMeta) } diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 7bddbbef4..72183f0f7 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -68,13 +68,13 @@ TxView.prototype.renderButtons = function () { return !selectedToken ? ( h('div.flex-row.flex-center.hero-balance-buttons', [ - h('button.hero-balance-button', { + h('button.btn-clear.hero-balance-button', { onClick: () => showModal({ name: 'BUY', }), }, 'DEPOSIT'), - h('button.hero-balance-button', { + h('button.btn-clear.hero-balance-button', { style: { marginLeft: '0.8em', }, @@ -84,7 +84,7 @@ TxView.prototype.renderButtons = function () { ) : ( h('div.flex-row.flex-center.hero-balance-buttons', [ - h('button.hero-balance-button', { + h('button.btn-clear.hero-balance-button', { onClick: showSendTokenPage, }, 'SEND'), ]) diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index 3cb7a8b76..b1ef83cee 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -130,7 +130,7 @@ WalletView.prototype.render = function () { selectedIdentity.name, ]), - h('button.wallet-view__details-button', 'DETAILS'), + h('button.btn-clear.wallet-view__details-button', 'DETAILS'), ]), ]), @@ -151,7 +151,7 @@ WalletView.prototype.render = function () { h(TokenList), - h('button.wallet-view__add-token-button', { + h('button.btn-clear.wallet-view__add-token-button', { onClick: () => { showAddTokenPage() hideSidebar() -- cgit v1.2.3 From b0a6bfdeece8a5afb860bc47f01373d08a0895b8 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Thu, 11 Jan 2018 16:59:00 -0800 Subject: Change styling for network dropdown --- ui/app/components/network.js | 41 ++++++++++------------------------------- 1 file changed, 10 insertions(+), 31 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/network.js b/ui/app/components/network.js index 5a8d0763d..3f147159b 100644 --- a/ui/app/components/network.js +++ b/ui/app/components/network.js @@ -39,7 +39,6 @@ Network.prototype.render = function () { }, src: 'images/loading.svg', }), - h('i.fa.fa-caret-down.network-caret'), ]) } else if (providerName === 'mainnet') { hoverText = 'Main Ethereum Network' @@ -85,12 +84,8 @@ Network.prototype.render = function () { backgroundColor: '#038789', // $blue-lagoon nonSelectBackgroundColor: '#15afb2', }), - h('.network-name', { - style: { - color: '#039396', - }}, - 'Main Network'), - h('i.fa.fa-caret-down.fa-lg.network-caret'), + h('.network-name', 'Main Network'), + h('i.fa.fa-chevron-down.fa-lg.network-caret'), ]) case 'ropsten-test-network': return h('.network-indicator', [ @@ -98,12 +93,8 @@ Network.prototype.render = function () { backgroundColor: '#e91550', // $crimson nonSelectBackgroundColor: '#ec2c50', }), - h('.network-name', { - style: { - color: '#ff6666', - }}, - 'Ropsten Test Net'), - h('i.fa.fa-caret-down.fa-lg.network-caret'), + h('.network-name', 'Ropsten Test Net'), + h('i.fa.fa-chevron-down.fa-lg.network-caret'), ]) case 'kovan-test-network': return h('.network-indicator', [ @@ -111,12 +102,8 @@ Network.prototype.render = function () { backgroundColor: '#690496', // $purple nonSelectBackgroundColor: '#b039f3', }), - h('.network-name', { - style: { - color: '#690496', - }}, - 'Kovan Test Net'), - h('i.fa.fa-caret-down.fa-lg.network-caret'), + h('.network-name', 'Kovan Test Net'), + h('i.fa.fa-chevron-down.fa-lg.network-caret'), ]) case 'rinkeby-test-network': return h('.network-indicator', [ @@ -124,12 +111,8 @@ Network.prototype.render = function () { backgroundColor: '#ebb33f', // $tulip-tree nonSelectBackgroundColor: '#ecb23e', }), - h('.network-name', { - style: { - color: '#e7a218', - }}, - 'Rinkeby Test Net'), - h('i.fa.fa-caret-down.fa-lg.network-caret'), + h('.network-name', 'Rinkeby Test Net'), + h('i.fa.fa-chevron-down.fa-lg.network-caret'), ]) default: return h('.network-indicator', [ @@ -140,12 +123,8 @@ Network.prototype.render = function () { }, }), - h('.network-name', { - style: { - color: '#AEAEAE', - }}, - 'Private Network'), - h('i.fa.fa-caret-down.fa-lg.network-caret'), + h('.network-name', 'Private Network'), + h('i.fa.fa-chevron-down.fa-lg.network-caret'), ]) } })(), -- cgit v1.2.3 From 5c1dcf3e9bdb317dd8b42aadb18657eb4bfa2e0f Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Fri, 12 Jan 2018 16:18:18 -0330 Subject: [NewUI-flat] New deposit ether modal UI. (#2642) * New deposit ether modal. * New deposit modal full screen on mobile, and other style fixes. * Hide shapeshift option from deposit modal for now. * Add shapeshift form to new deposit modal. * Store recipient address for shapeshift tx in background. * Use Simpledropdown to achieve desired styling in coin selector. * Lint fix * Fix typos and remove dead code. * Remove storage of shapeshift receiving address from background. * Fix typos --- ui/app/components/modals/buy-options-modal.js | 2 +- ui/app/components/modals/deposit-ether-modal.js | 182 +++++++++ ui/app/components/modals/modal.js | 32 ++ ui/app/components/shapeshift-form.js | 468 ++++++++++-------------- ui/app/components/shift-list-item.js | 50 +-- ui/app/components/tx-list.js | 10 +- ui/app/components/tx-view.js | 2 +- 7 files changed, 451 insertions(+), 295 deletions(-) create mode 100644 ui/app/components/modals/deposit-ether-modal.js (limited to 'ui/app/components') diff --git a/ui/app/components/modals/buy-options-modal.js b/ui/app/components/modals/buy-options-modal.js index d735983f9..74a7a847e 100644 --- a/ui/app/components/modals/buy-options-modal.js +++ b/ui/app/components/modals/buy-options-modal.js @@ -69,7 +69,7 @@ BuyOptions.prototype.render = function () { // h('div.buy-modal-content-option', {}, [ // h('div.buy-modal-content-option-title', {}, 'Shapeshift'), // h('div.buy-modal-content-option-subtitle', {}, 'Trade any digital asset for any other'), - // ]), + // ]),, this.renderModalContentOption( 'Direct Deposit', diff --git a/ui/app/components/modals/deposit-ether-modal.js b/ui/app/components/modals/deposit-ether-modal.js new file mode 100644 index 000000000..3e6d3fde1 --- /dev/null +++ b/ui/app/components/modals/deposit-ether-modal.js @@ -0,0 +1,182 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const connect = require('react-redux').connect +const actions = require('../../actions') +const networkNames = require('../../../../app/scripts/config.js').networkNames +const ShapeshiftForm = require('../shapeshift-form') + +const DIRECT_DEPOSIT_ROW_TITLE = 'Directly Deposit Ether' +const DIRECT_DEPOSIT_ROW_TEXT = `If you already have some Ether, the quickest way to get Ether in +your new wallet by direct deposit.` +const COINBASE_ROW_TITLE = 'Buy on Coinbase' +const COINBASE_ROW_TEXT = `Coinbase is the world’s most popular way to buy and sell bitcoin, +ethereum, and litecoin.` +const SHAPESHIFT_ROW_TITLE = 'Deposit with ShapeShift' +const SHAPESHIFT_ROW_TEXT = `If you own other cryptocurrencies, you can trade and deposit Ether +directly into your MetaMask wallet. No Account Needed.` +const FAUCET_ROW_TITLE = 'Test Faucet' +const facuetRowText = networkName => `Get Ether from a faucet for the ${networkName}` + +function mapStateToProps (state) { + return { + network: state.metamask.network, + address: state.metamask.selectedAddress, + } +} + +function mapDispatchToProps (dispatch) { + return { + toCoinbase: (address) => { + dispatch(actions.buyEth({ network: '1', address, amount: 0 })) + }, + hideModal: () => { + dispatch(actions.hideModal()) + }, + showAccountDetailModal: () => { + dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' })) + }, + toFaucet: network => dispatch(actions.buyEth({ network })), + } +} + +inherits(DepositEtherModal, Component) +function DepositEtherModal () { + Component.call(this) + + this.state = { + buyingWithShapeshift: false, + } +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)(DepositEtherModal) + +DepositEtherModal.prototype.renderRow = function ({ + logo, + title, + text, + buttonLabel, + onButtonClick, + hide, + className, + hideButton, + hideTitle, + onBackClick, +}) { + if (hide) { + return null + } + + return h('div', { + className: className || 'deposit-ether-modal__buy-row', + }, [ + + h('div.deposit-ether-modal__buy-row__back', { + onClick: onBackClick, + }, [ + + h('i.fa.fa-arrow-left.cursor-pointer'), + + ]), + + h('div.deposit-ether-modal__buy-row__logo', [logo]), + + h('div.deposit-ether-modal__buy-row__description', [ + + !hideTitle && h('div.deposit-ether-modal__buy-row__description__title', [title]), + + h('div.deposit-ether-modal__buy-row__description__text', [text]), + + ]), + + !hideButton && h('div.deposit-ether-modal__buy-row__button', [ + h('button.deposit-ether-modal__deposit-button', { + onClick: onButtonClick, + }, [buttonLabel]), + ]), + + ]) +} + +DepositEtherModal.prototype.render = function () { + const { network, toCoinbase, address, toFaucet } = this.props + const { buyingWithShapeshift } = this.state + + const isTestNetwork = ['3', '4', '42'].find(n => n === network) + const networkName = networkNames[network] + + return h('div.deposit-ether-modal', {}, [ + + h('div.deposit-ether-modal__header', [ + + h('div.deposit-ether-modal__header__title', ['Deposit Ether']), + + h('div.deposit-ether-modal__header__description', [ + 'To interact with decentralized applications using MetaMask, you’ll need Ether in your wallet.', + ]), + + h('div.deposit-ether-modal__header__close', { + onClick: () => { + this.setState({ buyingWithShapeshift: false }) + this.props.hideModal() + }, + }), + + ]), + + h('div.deposit-ether-modal__buy-rows', [ + + this.renderRow({ + logo: h('img.deposit-ether-modal__buy-row__eth-logo', { src: '../../../images/eth_logo.svg' }), + title: DIRECT_DEPOSIT_ROW_TITLE, + text: DIRECT_DEPOSIT_ROW_TEXT, + buttonLabel: 'View Account', + onButtonClick: () => this.goToAccountDetailsModal(), + hide: buyingWithShapeshift, + }), + + this.renderRow({ + logo: h('i.fa.fa-tint.fa-2x'), + title: FAUCET_ROW_TITLE, + text: facuetRowText(networkName), + buttonLabel: 'Get Ether', + onButtonClick: () => toFaucet(network), + hide: !isTestNetwork || buyingWithShapeshift, + }), + + this.renderRow({ + logo: h('img.deposit-ether-modal__buy-row__coinbase-logo', { + src: '../../../images/coinbase logo.png', + }), + title: COINBASE_ROW_TITLE, + text: COINBASE_ROW_TEXT, + buttonLabel: 'Continue to Coinbase', + onButtonClick: () => toCoinbase(address), + hide: isTestNetwork || buyingWithShapeshift, + }), + + this.renderRow({ + logo: h('img.deposit-ether-modal__buy-row__shapeshift-logo', { + src: '../../../images/shapeshift logo.png', + }), + title: SHAPESHIFT_ROW_TITLE, + text: SHAPESHIFT_ROW_TEXT, + buttonLabel: 'Buy with Shapeshift', + onButtonClick: () => this.setState({ buyingWithShapeshift: true }), + hide: isTestNetwork, + hideButton: buyingWithShapeshift, + hideTitle: buyingWithShapeshift, + onBackClick: () => this.setState({ buyingWithShapeshift: false }), + className: buyingWithShapeshift && 'deposit-ether-modal__buy-row__shapeshift-buy', + }), + + buyingWithShapeshift && h(ShapeshiftForm), + + ]), + ]) +} + +DepositEtherModal.prototype.goToAccountDetailsModal = function () { + this.props.hideModal() + this.props.showAccountDetailModal() +} diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 2ff6accaa..afb2a2175 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -9,6 +9,7 @@ const isPopupOrNotification = require('../../../../app/scripts/lib/is-popup-or-n // Modal Components const BuyOptions = require('./buy-options-modal') +const DepositEtherModal = require('./deposit-ether-modal') const AccountDetailsModal = require('./account-details-modal') const EditAccountNameModal = require('./edit-account-name-modal') const ExportPrivateKeyModal = require('./export-private-key-modal') @@ -73,6 +74,37 @@ const MODALS = { }, }, + DEPOSIT_ETHER: { + contents: [ + h(DepositEtherModal, {}, []), + ], + mobileModalStyle: { + width: '100%', + height: '100%', + transform: 'none', + left: '0', + right: '0', + margin: '0 auto', + boxShadow: '0 0 7px 0 rgba(0,0,0,0.08)', + top: '0', + display: 'flex', + }, + laptopModalStyle: { + width: '900px', + maxWidth: '900px', + top: 'calc(10% + 10px)', + left: '0', + right: '0', + margin: '0 auto', + boxShadow: '0 0 6px 0 rgba(0,0,0,0.3)', + borderRadius: '8px', + transform: 'none', + }, + contentStyle: { + borderRadius: '8px', + }, + }, + EDIT_ACCOUNT_NAME: { contents: [ h(EditAccountNameModal, {}, []), diff --git a/ui/app/components/shapeshift-form.js b/ui/app/components/shapeshift-form.js index c5993e3d3..2270b8236 100644 --- a/ui/app/components/shapeshift-form.js +++ b/ui/app/components/shapeshift-form.js @@ -1,308 +1,242 @@ -const PersistentForm = require('../../lib/persistent-form') const h = require('react-hyperscript') const inherits = require('util').inherits +const Component = require('react').Component const connect = require('react-redux').connect -const actions = require('../actions') -const Qr = require('./qr-code') -const isValidAddress = require('../util').isValidAddress -module.exports = connect(mapStateToProps)(ShapeshiftForm) +const classnames = require('classnames') +const { qrcode } = require('qrcode-npm') +const { shapeShiftSubview, pairUpdate, buyWithShapeShift } = require('../actions') +const { isValidAddress } = require('../util') +const SimpleDropdown = require('./dropdowns/simple-dropdown') function mapStateToProps (state) { + const { + coinOptions, + tokenExchangeRates, + selectedAddress, + } = state.metamask + return { - warning: state.appState.warning, - isSubLoading: state.appState.isSubLoading, - qrRequested: state.appState.qrRequested, + coinOptions, + tokenExchangeRates, + selectedAddress, } } -inherits(ShapeshiftForm, PersistentForm) +function mapDispatchToProps (dispatch) { + return { + shapeShiftSubview: () => dispatch(shapeShiftSubview()), + pairUpdate: coin => dispatch(pairUpdate(coin)), + buyWithShapeShift: data => dispatch(buyWithShapeShift(data)), + } +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)(ShapeshiftForm) +inherits(ShapeshiftForm, Component) function ShapeshiftForm () { - PersistentForm.call(this) - this.persistentFormParentId = 'shapeshift-buy-form' + Component.call(this) + + this.state = { + depositCoin: 'btc', + refundAddress: '', + showQrCode: false, + depositAddress: '', + errorMessage: '', + isLoading: false, + bought: false, + } } -ShapeshiftForm.prototype.render = function () { - return this.props.qrRequested ? h(Qr, {key: 'qr'}) : this.renderMain() +ShapeshiftForm.prototype.componentWillMount = function () { + this.props.shapeShiftSubview() } -ShapeshiftForm.prototype.renderMain = function () { - const marketinfo = this.props.buyView.formView.marketinfo - const coinOptions = this.props.buyView.formView.coinOptions - var coin = marketinfo.pair.split('_')[0].toUpperCase() - - return h('.flex-column', { - style: { - position: 'relative', - padding: '25px', - paddingTop: '5px', - width: '90%', - minHeight: '215px', - alignItems: 'center', - overflowY: 'auto', - }, - }, [ - h('.flex-row', { - style: { - justifyContent: 'center', - alignItems: 'baseline', - height: '42px', - }, - }, [ - h('img', { - src: coinOptions[coin].image, - width: '25px', - height: '25px', - style: { - marginRight: '5px', - }, - }), - - h('.input-container', { - position: 'relative', - }, [ - h('input#fromCoin.buy-inputs.ex-coins', { - type: 'text', - list: 'coinList', - autoFocus: true, - dataset: { - persistentFormId: 'input-coin', - }, - style: { - boxSizing: 'border-box', - }, - onChange: this.handleLiveInput.bind(this), - defaultValue: 'BTC', - }), +ShapeshiftForm.prototype.onCoinChange = function (e) { + const coin = e.target.value + this.setState({ + depositCoin: coin, + errorMessage: '', + }) + this.props.pairUpdate(coin) +} - this.renderCoinList(), +ShapeshiftForm.prototype.onBuyWithShapeShift = function () { + this.setState({ + isLoading: true, + showQrCode: true, + }) - h('i.fa.fa-pencil-square-o.edit-text', { - style: { - fontSize: '12px', - color: '#F7861C', - position: 'absolute', - }, - }), - ]), + const { + buyWithShapeShift, + selectedAddress: withdrawal, + } = this.props + const { + refundAddress: returnAddress, + depositCoin, + } = this.state + const pair = `${depositCoin}_eth` + const data = { + withdrawal, + pair, + returnAddress, + // Public api key + 'apiKey': '803d1f5df2ed1b1476e4b9e6bcd089e34d8874595dda6a23b67d93c56ea9cc2445e98a6748b219b2b6ad654d9f075f1f1db139abfa93158c04e825db122c14b6', + } - h('.icon-control', { - style: { - position: 'relative', - }, - }, [ - // Not visible on the screen, can't see it on master. - - // h('i.fa.fa-refresh.fa-4.orange', { - // style: { - // bottom: '5px', - // left: '5px', - // color: '#F7861C', - // }, - // onClick: this.updateCoin.bind(this), - // }), - h('i.fa.fa-chevron-right.fa-4.orange', { - style: { - position: 'absolute', - bottom: '35%', - left: '0%', - color: '#F7861C', - }, - onClick: this.updateCoin.bind(this), - }), - ]), + if (isValidAddress(withdrawal)) { + buyWithShapeShift(data) + .then(d => this.setState({ + showQrCode: true, + depositAddress: d.deposit, + isLoading: false, + })) + .catch(() => this.setState({ + showQrCode: false, + errorMessage: 'Invalid Request', + isLoading: false, + })) + } +} - h('#toCoin.ex-coins', marketinfo.pair.split('_')[1].toUpperCase()), +ShapeshiftForm.prototype.renderMetadata = function (label, value) { + return h('div', {className: 'shapeshift-form__metadata-wrapper'}, [ - h('img', { - src: coinOptions[marketinfo.pair.split('_')[1].toUpperCase()].image, - width: '25px', - height: '25px', - style: { - marginLeft: '5px', - }, - }), + h('div.shapeshift-form__metadata-label', {}, [ + h('span', `${label}:`), ]), - h('.flex-column', { - style: { - marginTop: '1%', - alignItems: 'flex-start', - }, - }, [ - this.props.warning ? - this.props.warning && - h('span.error.flex-center', { - style: { - textAlign: 'center', - width: '229px', - height: '82px', - }, - }, this.props.warning) - : this.renderInfo(), - - this.renderRefundAddressForCoin(coin), + h('div.shapeshift-form__metadata-value', {}, [ + h('span', value), ]), ]) } -ShapeshiftForm.prototype.renderRefundAddressForCoin = function (coin) { - return h(this.activeToggle('.input-container'), { - style: { - marginTop: '1%', - }, - }, [ - - h('div', `${coin} Address:`), - - h('input#fromCoinAddress.buy-inputs', { - type: 'text', - placeholder: `Your ${coin} Refund Address`, - dataset: { - persistentFormId: 'refund-address', - - }, - style: { - boxSizing: 'border-box', - width: '227px', - height: '30px', - padding: ' 5px ', - }, - }), - - h('i.fa.fa-pencil-square-o.edit-text', { - style: { - fontSize: '12px', - color: '#F7861C', - position: 'absolute', - }, - }), - h('div.flex-row', { - style: { - justifyContent: 'flex-start', - }, - }, [ - h('button', { - onClick: this.shift.bind(this), - style: { - marginTop: '1%', - }, - }, - 'Submit'), - ]), +ShapeshiftForm.prototype.renderMarketInfo = function () { + const { depositCoin } = this.state + const coinPair = `${depositCoin}_eth` + const { tokenExchangeRates } = this.props + const { + limit, + rate, + minimum, + } = tokenExchangeRates[coinPair] || {} + + return h('div.shapeshift-form__metadata', {}, [ + + this.renderMetadata('Status', limit ? 'Available' : 'Unavailable'), + this.renderMetadata('Limit', limit), + this.renderMetadata('Exchange Rate', rate), + this.renderMetadata('Minimum', minimum), + ]) } -ShapeshiftForm.prototype.shift = function () { - var props = this.props - var withdrawal = this.props.buyView.buyAddress - var returnAddress = document.getElementById('fromCoinAddress').value - var pair = this.props.buyView.formView.marketinfo.pair - var data = { - 'withdrawal': withdrawal, - 'pair': pair, - 'returnAddress': returnAddress, - // Public api key - 'apiKey': '803d1f5df2ed1b1476e4b9e6bcd089e34d8874595dda6a23b67d93c56ea9cc2445e98a6748b219b2b6ad654d9f075f1f1db139abfa93158c04e825db122c14b6', - } - var message = [ - `Deposit Limit: ${props.buyView.formView.marketinfo.limit}`, - `Deposit Minimum:${props.buyView.formView.marketinfo.minimum}`, - ] - if (isValidAddress(withdrawal)) { - this.props.dispatch(actions.coinShiftRquest(data, message)) - } -} +ShapeshiftForm.prototype.renderQrCode = function () { + const { depositAddress, isLoading } = this.state + const qrImage = qrcode(4, 'M') + qrImage.addData(depositAddress) + qrImage.make() -ShapeshiftForm.prototype.renderCoinList = function () { - var list = Object.keys(this.props.buyView.formView.coinOptions).map((item) => { - return h('option', { - value: item, - }, item) - }) + return h('div.shapeshift-form', {}, [ - return h('datalist#coinList', { - onClick: (event) => { - event.preventDefault() - }, - }, list) -} + h('div.shapeshift-form__deposit-instruction', [ + 'Deposit your BTC to the address below:', + ]), -ShapeshiftForm.prototype.updateCoin = function (event) { - event.preventDefault() - const props = this.props - var coinOptions = this.props.buyView.formView.coinOptions - var coin = document.getElementById('fromCoin').value - - if (!coinOptions[coin.toUpperCase()] || coin.toUpperCase() === 'ETH') { - var message = 'Not a valid coin' - return props.dispatch(actions.displayWarning(message)) - } else { - return props.dispatch(actions.pairUpdate(coin)) - } -} + h('div', depositAddress), -ShapeshiftForm.prototype.handleLiveInput = function () { - const props = this.props - var coinOptions = this.props.buyView.formView.coinOptions - var coin = document.getElementById('fromCoin').value + h('div.shapeshift-form__qr-code', [ + isLoading + ? h('img', { + src: 'images/loading.svg', + style: { width: '60px'}, + }) + : h('div', { + dangerouslySetInnerHTML: { __html: qrImage.createTableTag(4) }, + }), + ]), - if (!coinOptions[coin.toUpperCase()] || coin.toUpperCase() === 'ETH') { - return null - } else { - return props.dispatch(actions.pairUpdate(coin)) - } -} + this.renderMarketInfo(), -ShapeshiftForm.prototype.renderInfo = function () { - const marketinfo = this.props.buyView.formView.marketinfo - const coinOptions = this.props.buyView.formView.coinOptions - var coin = marketinfo.pair.split('_')[0].toUpperCase() - - return h('span', { - style: { - }, - }, [ - h('h3.flex-row.text-transform-uppercase', { - style: { - color: '#868686', - paddingTop: '4px', - justifyContent: 'space-around', - textAlign: 'center', - fontSize: '17px', - }, - }, `Market Info for ${marketinfo.pair.replace('_', ' to ').toUpperCase()}:`), - h('.marketinfo', ['Status : ', `${coinOptions[coin].status}`]), - h('.marketinfo', ['Exchange Rate: ', `${marketinfo.rate}`]), - h('.marketinfo', ['Limit: ', `${marketinfo.limit}`]), - h('.marketinfo', ['Minimum : ', `${marketinfo.minimum}`]), ]) } -ShapeshiftForm.prototype.activeToggle = function (elementType) { - if (!this.props.buyView.formView.response || this.props.warning) return elementType - return `${elementType}.inactive` -} -ShapeshiftForm.prototype.renderLoading = function () { - return h('span', { - style: { - position: 'absolute', - left: '70px', - bottom: '194px', - background: 'transparent', - width: '229px', - height: '82px', - display: 'flex', - justifyContent: 'center', - }, - }, [ - h('img', { - style: { - width: '60px', - }, - src: 'images/loading.svg', - }), - ]) +ShapeshiftForm.prototype.render = function () { + const { coinOptions, btnClass } = this.props + const { depositCoin, errorMessage, showQrCode, depositAddress } = this.state + const coinPair = `${depositCoin}_eth` + const { tokenExchangeRates } = this.props + const token = tokenExchangeRates[coinPair] + + return h('div.shapeshift-form-wrapper', [ + showQrCode + ? this.renderQrCode() + : h('div.shapeshift-form', [ + h('div.shapeshift-form__selectors', [ + + h('div.shapeshift-form__selector', [ + + h('div.shapeshift-form__selector-label', 'Deposit'), + + h(SimpleDropdown, { + selectedOption: this.state.depositCoin, + onSelect: this.onCoinChange, + options: Object.entries(coinOptions).map(([coin]) => ({ + value: coin.toLowerCase(), + displayValue: coin, + })), + }), + + ]), + + h('div.icon.shapeshift-form__caret', { + style: { backgroundImage: 'url(images/caret-right.svg)'}, + }), + + h('div.shapeshift-form__selector', [ + + h('div.shapeshift-form__selector-label', [ + 'Receive', + ]), + + h('div.shapeshift-form__selector-input', ['ETH']), + + ]), + + ]), + + h('div', { + className: classnames('shapeshift-form__address-input-wrapper', { + 'shapeshift-form__address-input-wrapper--error': errorMessage, + }), + }, [ + + h('div.shapeshift-form__address-input-label', [ + 'Your Refund Address', + ]), + + h('input.shapeshift-form__address-input', { + type: 'text', + onChange: e => this.setState({ + refundAddress: e.target.value, + errorMessage: '', + }), + }), + + h('divshapeshift-form__address-input-error-message', [errorMessage]), + ]), + + this.renderMarketInfo(), + + ]), + + !depositAddress && h('button.shapeshift-form__shapeshift-buy-btn', { + className: btnClass, + disabled: !token, + onClick: () => this.onBuyWithShapeShift(), + }, ['Buy']), + + ]) } diff --git a/ui/app/components/shift-list-item.js b/ui/app/components/shift-list-item.js index 43973de63..111a77df4 100644 --- a/ui/app/components/shift-list-item.js +++ b/ui/app/components/shift-list-item.js @@ -16,6 +16,7 @@ module.exports = connect(mapStateToProps)(ShiftListItem) function mapStateToProps (state) { return { + selectedAddress: state.metamask.selectedAddress, conversionRate: state.metamask.conversionRate, currentCurrency: state.metamask.currentCurrency, } @@ -28,36 +29,39 @@ function ShiftListItem () { } ShiftListItem.prototype.render = function () { + const { selectedAddress, receivingAddress } = this.props return ( - h('div.tx-list-item.tx-list-clickable', { - style: { - paddingTop: '20px', - paddingBottom: '20px', - justifyContent: 'space-around', - alignItems: 'center', - }, - }, [ - h('div', { + selectedAddress === receivingAddress + ? h('div.tx-list-item.tx-list-clickable', { style: { - width: '0px', - position: 'relative', - bottom: '19px', + paddingTop: '20px', + paddingBottom: '20px', + justifyContent: 'space-around', + alignItems: 'center', }, }, [ - h('img', { - src: 'https://info.shapeshift.io/sites/default/files/logo.png', + h('div', { style: { - height: '35px', - width: '132px', - position: 'absolute', - clip: 'rect(0px,23px,34px,0px)', + width: '0px', + position: 'relative', + bottom: '19px', }, - }), - ]), + }, [ + h('img', { + src: 'https://info.shapeshift.io/sites/default/files/logo.png', + style: { + height: '35px', + width: '132px', + position: 'absolute', + clip: 'rect(0px,23px,34px,0px)', + }, + }), + ]), - this.renderInfo(), - this.renderUtilComponents(), - ]) + this.renderInfo(), + this.renderUtilComponents(), + ]) + : null ) } diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 70722f43e..50e328dac 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -52,7 +52,7 @@ TxList.prototype.render = function () { TxList.prototype.renderTransaction = function () { const { txsToRender, conversionRate } = this.props return txsToRender.length - ? txsToRender.map((transaction, i) => this.renderTransactionListItem(transaction, conversionRate)) + ? txsToRender.map((transaction, i) => this.renderTransactionListItem(transaction, conversionRate, i)) : [h( 'div.tx-list-item.tx-list-item--empty', { key: 'tx-list-none' }, @@ -61,12 +61,16 @@ TxList.prototype.renderTransaction = function () { } // TODO: Consider moving TxListItem into a separate component -TxList.prototype.renderTransactionListItem = function (transaction, conversionRate) { +TxList.prototype.renderTransactionListItem = function (transaction, conversionRate, index) { // console.log({transaction}) // refer to transaction-list.js:line 58 if (transaction.key === 'shapeshift') { - return h(ShiftListItem, transaction) + return h('div', { + key: `shapeshift${index}`, + }, [ + h(ShiftListItem, transaction), + ]) } const props = { diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index e42a20c85..949d91f6f 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -73,7 +73,7 @@ TxView.prototype.renderButtons = function () { textAlign: 'center', }, onClick: () => showModal({ - name: 'BUY', + name: 'DEPOSIT_ETHER', }), }, 'DEPOSIT'), -- cgit v1.2.3 From 980e1bfcf82361185f6d1b22abd9593ba166825e Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 10 Jan 2018 14:55:38 -0330 Subject: New add account page with create and import options. --- ui/app/components/account-menu/index.js | 16 +++++----------- .../components/dropdowns/components/account-dropdowns.js | 10 ++++------ 2 files changed, 9 insertions(+), 17 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index 1b62b42fb..aeb8a0b38 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -42,13 +42,8 @@ function mapDispatchToProps (dispatch) { dispatch(actions.hideSidebar()) dispatch(actions.toggleAccountMenu()) }, - showNewAccountModal: () => { - dispatch(actions.showModal({ name: 'NEW_ACCOUNT' })) - dispatch(actions.hideSidebar()) - dispatch(actions.toggleAccountMenu()) - }, - showImportPage: () => { - dispatch(actions.showImportPage()) + showNewAccountPage: (formToSelect) => { + dispatch(actions.showNewAccountPage(formToSelect)) dispatch(actions.hideSidebar()) dispatch(actions.toggleAccountMenu()) }, @@ -64,8 +59,7 @@ AccountMenu.prototype.render = function () { const { isAccountMenuOpen, toggleAccountMenu, - showNewAccountModal, - showImportPage, + showNewAccountPage, lockMetamask, showConfigPage, showInfoPage, @@ -85,12 +79,12 @@ AccountMenu.prototype.render = function () { h('div.account-menu__accounts', this.renderAccounts()), h(Divider), h(Item, { - onClick: showNewAccountModal, + onClick: () => showNewAccountPage('CREATE'), icon: h('img', { src: 'images/plus-btn-white.svg' }), text: 'Create Account', }), h(Item, { - onClick: showImportPage, + onClick: () => showNewAccountPage('IMPORT'), icon: h('img', { src: 'images/import-account.svg' }), text: 'Import Account', }), diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index 58326b13c..f97ac0691 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -199,7 +199,7 @@ class AccountDropdowns extends Component { {}, menuItemStyles, ), - onClick: () => actions.showNewAccountModal(), + onClick: () => actions.showNewAccountPageCreateForm(), }, [ h( @@ -228,7 +228,7 @@ class AccountDropdowns extends Component { actions.hideSidebar() } }, - onClick: () => actions.showImportPage(), + onClick: () => actions.showNewAccountPageImportForm(), style: Object.assign( {}, menuItemStyles, @@ -457,9 +457,7 @@ const mapDispatchToProps = (dispatch) => { identity, })) }, - showNewAccountModal: () => { - dispatch(actions.showModal({ name: 'NEW_ACCOUNT' })) - }, + showNewAccountPageCreateForm: () => dispatch(actions.showNewAccountPage({ form: 'CREATE' })), showExportPrivateKeyModal: () => { dispatch(actions.showModal({ name: 'EXPORT_PRIVATE_KEY' })) }, @@ -467,7 +465,7 @@ const mapDispatchToProps = (dispatch) => { dispatch(actions.showAddTokenPage()) }, addNewAccount: () => dispatch(actions.addNewAccount()), - showImportPage: () => dispatch(actions.showImportPage()), + showNewAccountPageImportForm: () => dispatch(actions.showNewAccountPage({ form: 'IMPORT' })), showQrView: (selected, identity) => dispatch(actions.showQrView(selected, identity)), }, } -- cgit v1.2.3 From 644adeccf6b5365ef2c8c9a5ba69b90fdaa1f2ec Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Sat, 13 Jan 2018 14:59:16 -0800 Subject: Fix Hide Token modal styling, popup positioning --- ui/app/components/modals/hide-token-confirmation-modal.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/hide-token-confirmation-modal.js b/ui/app/components/modals/hide-token-confirmation-modal.js index fa3ad0b1e..56c7ba299 100644 --- a/ui/app/components/modals/hide-token-confirmation-modal.js +++ b/ui/app/components/modals/hide-token-confirmation-modal.js @@ -58,12 +58,12 @@ HideTokenConfirmationModal.prototype.render = function () { ]), h('div.hide-token-confirmation__buttons', {}, [ - h('button.btn-clear', { + h('button.btn-cancel.hide-token-confirmation__button', { onClick: () => hideModal(), }, [ 'CANCEL', ]), - h('button.btn-clear', { + h('button.btn-clear.hide-token-confirmation__button', { onClick: () => hideToken(address), }, [ 'HIDE', -- cgit v1.2.3 From baebf64afd594316a4e160ff1d046ea68bfc5c70 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Mon, 15 Jan 2018 14:37:59 -0800 Subject: Fix send screen value input --- ui/app/components/currency-input.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/currency-input.js b/ui/app/components/currency-input.js index 66880091f..6f7862e51 100644 --- a/ui/app/components/currency-input.js +++ b/ui/app/components/currency-input.js @@ -50,10 +50,18 @@ function sanitizeValue (value) { CurrencyInput.prototype.handleChange = function (newValue) { const { onInputChange } = this.props + const { value } = this.state - this.setState({ value: sanitizeValue(newValue) }) + let parsedValue = newValue + const newValueLastIndex = newValue.length - 1 - onInputChange(sanitizeValue(newValue)) + if (value === '0' && newValue[newValueLastIndex] === '0') { + parsedValue = parsedValue.slice(0, newValueLastIndex) + } + + const sanitizedValue = sanitizeValue(parsedValue) + this.setState({ value: sanitizedValue }) + onInputChange(sanitizedValue) } // If state.value === props.value plus a decimal point, or at least one @@ -90,6 +98,6 @@ CurrencyInput.prototype.render = function () { size: valueToRender.length * inputSizeMultiplier, readOnly, onChange: e => this.handleChange(e.target.value), - ref: inputRef, + ref: inputRef, }) } -- cgit v1.2.3 From ccb80594be3000488b7c73f9fd5e56168e0d5042 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Tue, 16 Jan 2018 16:08:42 -0800 Subject: Readjust gas fees when switching networks on the send screen --- ui/app/components/send/send-v2-container.js | 1 + 1 file changed, 1 insertion(+) (limited to 'ui/app/components') diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js index 2d2ed4546..1106902b7 100644 --- a/ui/app/components/send/send-v2-container.js +++ b/ui/app/components/send/send-v2-container.js @@ -51,6 +51,7 @@ function mapStateToProps (state) { amountConversionRate: selectedToken ? tokenToFiatRate : conversionRate, tokenContract: getSelectedTokenContract(state), unapprovedTxs: state.metamask.unapprovedTxs, + network: state.metamask.network, } } -- cgit v1.2.3 From 65e9d9efc56a99ecd3a46b98ed58af9604374f68 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Tue, 16 Jan 2018 17:41:42 -0800 Subject: Fix rendering QR code in old UI, hide unnecessary back button --- ui/app/components/modals/deposit-ether-modal.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/modals/deposit-ether-modal.js b/ui/app/components/modals/deposit-ether-modal.js index 3e6d3fde1..532d66653 100644 --- a/ui/app/components/modals/deposit-ether-modal.js +++ b/ui/app/components/modals/deposit-ether-modal.js @@ -62,6 +62,7 @@ DepositEtherModal.prototype.renderRow = function ({ hideButton, hideTitle, onBackClick, + showBackButton, }) { if (hide) { return null @@ -71,7 +72,7 @@ DepositEtherModal.prototype.renderRow = function ({ className: className || 'deposit-ether-modal__buy-row', }, [ - h('div.deposit-ether-modal__buy-row__back', { + onBackClick && showBackButton && h('div.deposit-ether-modal__buy-row__back', { onClick: onBackClick, }, [ @@ -167,6 +168,7 @@ DepositEtherModal.prototype.render = function () { hideButton: buyingWithShapeshift, hideTitle: buyingWithShapeshift, onBackClick: () => this.setState({ buyingWithShapeshift: false }), + showBackButton: this.state.buyingWithShapeshift, className: buyingWithShapeshift && 'deposit-ether-modal__buy-row__shapeshift-buy', }), -- cgit v1.2.3 From 40e58d31326cc4e759991d15e7e84140e483a791 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Tue, 16 Jan 2018 11:58:02 -0800 Subject: Fix tx-list, confirmation screen styling --- ui/app/components/tx-list.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 50e328dac..84cd0f093 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -36,16 +36,15 @@ TxList.prototype.componentWillMount = function () { } TxList.prototype.render = function () { - return h('div.flex-column.tx-list-container', {}, [ - + return h('div.flex-column', [ h('div.flex-row.tx-list-header-wrapper', [ h('div.flex-row.tx-list-header', [ h('div', 'transactions'), ]), ]), - - this.renderTransaction(), - + h('div.flex-column.tx-list-container', {}, [ + this.renderTransaction(), + ]), ]) } -- cgit v1.2.3 From f8bf8cb527ae0e24ccf9d1c9f2f6baa457f2e659 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Wed, 17 Jan 2018 17:37:18 -0800 Subject: Update popout to fullscreen icon --- ui/app/components/tx-view.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 0148b32a5..b25d8e0f9 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -100,7 +100,7 @@ TxView.prototype.render = function () { h('div.flex-row.phone-visible', { style: { - margin: '1em 0.9em', + margin: '1.5em 1.2em 0', justifyContent: 'space-between', alignItems: 'center', }, @@ -136,7 +136,7 @@ TxView.prototype.render = function () { !isMascara && h('div.open-in-browser', { onClick: () => global.platform.openExtensionInBrowser(), - }, [h('img', { src: 'images/open.svg' })]), + }, [h('img', { src: 'images/popout.svg' })]), ]), -- cgit v1.2.3 From 4fae461a672b89a16c496d09321f11f86b873e32 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Thu, 18 Jan 2018 01:17:01 -0330 Subject: [NewUI] Send screen gas loading fixes (#3027) * Allow entering amount, but disable validation of amount, opening of gas customizer or clicking of next, when gas loading in send. * Fix variable name. --- ui/app/components/send/gas-fee-display-v2.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/send/gas-fee-display-v2.js b/ui/app/components/send/gas-fee-display-v2.js index 806c33f0a..0c4c3f7a9 100644 --- a/ui/app/components/send/gas-fee-display-v2.js +++ b/ui/app/components/send/gas-fee-display-v2.js @@ -32,8 +32,9 @@ GasFeeDisplay.prototype.render = function () { }) : h('div.currency-display', 'Loading...'), - h('div.send-v2__sliders-icon-container', { + h('button.send-v2__sliders-icon-container', { onClick, + disabled: !gasTotal, }, [ h('i.fa.fa-sliders.send-v2__sliders-icon'), ]), -- cgit v1.2.3 From b05d21b1ba308bdb5b758d53dd79593a7a2bf26e Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Wed, 17 Jan 2018 20:08:29 -0800 Subject: Fix transaction list font sizes, padding --- ui/app/components/tx-list-item.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 8a9253d4d..7ccc5c315 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -234,11 +234,7 @@ TxListItem.prototype.render = function () { style: {}, }, [ - h('span', { - className: classnames('tx-list-value', { - 'tx-list-value--confirmed': transactionStatus === 'confirmed', - }), - }, total), + h('span.tx-list-value', total), showFiatTotal && h('span.tx-list-fiat-value', fiatTotal), -- cgit v1.2.3 From 78bce55858916ba9d3189f76db440768e6ae95b1 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Wed, 31 Jan 2018 20:57:35 -0330 Subject: [NewUI] Use tooltip for copy to clipboard helper text on main screen. (#3120) * Use tooltip for display of helper text in wallet views copy to clipboard feature. * Use react-tippy in wallet-view.js; center arrow tooltip throughout tooltip text change. * Remove unnecessary tabIndex attribute from wallet view address element. --- ui/app/components/tooltip-v2.js | 31 +++++++++++++++++++++++++++++++ ui/app/components/wallet-view.js | 36 ++++++++++++++++++++++++++---------- 2 files changed, 57 insertions(+), 10 deletions(-) create mode 100644 ui/app/components/tooltip-v2.js (limited to 'ui/app/components') diff --git a/ui/app/components/tooltip-v2.js b/ui/app/components/tooltip-v2.js new file mode 100644 index 000000000..133a0f16a --- /dev/null +++ b/ui/app/components/tooltip-v2.js @@ -0,0 +1,31 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const ReactTippy = require('react-tippy').Tooltip + +module.exports = Tooltip + +inherits(Tooltip, Component) +function Tooltip () { + Component.call(this) +} + +Tooltip.prototype.render = function () { + const props = this.props + const { position, title, children, wrapperClassName } = props + + return h('div', { + className: wrapperClassName, + }, [ + + h(ReactTippy, { + title, + position: position || 'left', + trigger: 'mouseenter', + hideOnClick: false, + size: 'small', + arrow: true, + }, children), + + ]) +} diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index b1ef83cee..34f27ca2a 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -2,8 +2,10 @@ const Component = require('react').Component const connect = require('react-redux').connect const h = require('react-hyperscript') const inherits = require('util').inherits +const classnames = require('classnames') const Identicon = require('./identicon') // const AccountDropdowns = require('./dropdowns/index.js').AccountDropdowns +const Tooltip = require('./tooltip-v2.js') const copyToClipboard = require('copy-to-clipboard') const actions = require('../actions') const BalanceComponent = require('./balance-component') @@ -45,6 +47,7 @@ function WalletView () { Component.call(this) this.state = { hasCopied: false, + copyToClipboardPressed: false, } } @@ -134,17 +137,30 @@ WalletView.prototype.render = function () { ]), ]), - - h('div.wallet-view__address', { - onClick: () => { - copyToClipboard(selectedAddress) - this.setState({ hasCopied: true }) - setTimeout(() => this.setState({ hasCopied: false }), 3000) - }, + h(Tooltip, { + position: 'bottom', + title: this.state.hasCopied ? 'Copied!' : 'Copy to clipboard', + wrapperClassName: 'wallet-view__tooltip', }, [ - this.state.hasCopied && 'Copied to Clipboard', - !this.state.hasCopied && `${selectedAddress.slice(0, 4)}...${selectedAddress.slice(-4)}`, - h('i.fa.fa-clipboard', { style: { marginLeft: '8px' } }), + h('button.wallet-view__address', { + className: classnames({ + 'wallet-view__address__pressed': this.state.copyToClipboardPressed, + }), + onClick: () => { + copyToClipboard(selectedAddress) + this.setState({ hasCopied: true }) + setTimeout(() => this.setState({ hasCopied: false }), 3000) + }, + onMouseDown: () => { + this.setState({ copyToClipboardPressed: true }) + }, + onMouseUp: () => { + this.setState({ copyToClipboardPressed: false }) + }, + }, [ + `${selectedAddress.slice(0, 4)}...${selectedAddress.slice(-4)}`, + h('i.fa.fa-clipboard', { style: { marginLeft: '8px' } }), + ]), ]), this.renderWalletBalance(), -- cgit v1.2.3 From d4da419c5befdbee77cb30f6113ea50fc572625c Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Mon, 5 Feb 2018 23:01:21 -0330 Subject: Wallet view supports screen sizes between 576px and 667px (#3193) --- ui/app/components/token-cell.js | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index 59552f4a0..a5d032a0d 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -111,20 +111,25 @@ TokenCell.prototype.render = function () { network, }), - h('h.token-list-item__balance-wrapper', null, [ - h('h3.token-list-item__token-balance', `${string || 0} ${symbol}`), + h('div.token-list-item__balance-ellipsis', [ - showFiat && h('div.token-list-item__fiat-amount', { - style: {}, - }, formattedFiat), - ]), + h('h.token-list-item__balance-wrapper', null, [ + h('h3.token-list-item__token-balance', `${string || 0} ${symbol}`), - h('i.fa.fa-ellipsis-h.fa-lg.token-list-item__ellipsis.cursor-pointer', { - onClick: (e) => { - e.stopPropagation() - this.setState({ tokenMenuOpen: true }) - }, - }), + showFiat && h('div.token-list-item__fiat-amount', { + style: {}, + }, formattedFiat), + ]), + + h('i.fa.fa-ellipsis-h.fa-lg.token-list-item__ellipsis.cursor-pointer', { + onClick: (e) => { + e.stopPropagation() + this.setState({ tokenMenuOpen: true }) + }, + }), + + ]), + tokenMenuOpen && h(TokenMenuDropdown, { onClose: () => this.setState({ tokenMenuOpen: false }), -- cgit v1.2.3 From d452403322c517eee4fc6120de1ead68ed65ee6a Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Mon, 5 Feb 2018 18:47:46 -0800 Subject: Add functional integration testing to Add Token flow (#3189) --- ui/app/components/token-cell.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index a5d032a0d..5c1c36465 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -111,9 +111,10 @@ TokenCell.prototype.render = function () { network, }), - h('div.token-list-item__balance-ellipsis', [ + h('div.token-list-item__balance-wrapper', null, [ + h('h3.token-list-item__token-balance', `${string || 0} ${symbol}`), - h('h.token-list-item__balance-wrapper', null, [ + h('div.token-list-item__balance-wrapper', null, [ h('h3.token-list-item__token-balance', `${string || 0} ${symbol}`), showFiat && h('div.token-list-item__fiat-amount', { @@ -129,7 +130,7 @@ TokenCell.prototype.render = function () { }), ]), - + tokenMenuOpen && h(TokenMenuDropdown, { onClose: () => this.setState({ tokenMenuOpen: false }), -- cgit v1.2.3 From d84dc5da4249cd6737d892b044534f7f83c91979 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Tue, 6 Feb 2018 14:51:21 -0330 Subject: Remove duplicate token balance on uat next. (#3195) --- ui/app/components/token-cell.js | 2 -- 1 file changed, 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index 5c1c36465..677f22a75 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -112,8 +112,6 @@ TokenCell.prototype.render = function () { }), h('div.token-list-item__balance-wrapper', null, [ - h('h3.token-list-item__token-balance', `${string || 0} ${symbol}`), - h('div.token-list-item__balance-wrapper', null, [ h('h3.token-list-item__token-balance', `${string || 0} ${symbol}`), -- cgit v1.2.3 From 9ed3a5512efed033efae1a5e3d414598f74b6bd7 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Tue, 6 Feb 2018 21:21:32 -0330 Subject: Fix alignment of ellipsis and address in wallet view. (#3198) --- ui/app/components/token-cell.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index 677f22a75..0332fde88 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -111,7 +111,7 @@ TokenCell.prototype.render = function () { network, }), - h('div.token-list-item__balance-wrapper', null, [ + h('div.token-list-item__balance-ellipsis', null, [ h('div.token-list-item__balance-wrapper', null, [ h('h3.token-list-item__token-balance', `${string || 0} ${symbol}`), -- cgit v1.2.3 From 8b90b1d1b12bdae4f1fa06caec5cd5619dc83437 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Tue, 6 Feb 2018 22:03:37 -0800 Subject: Remove accessing PropTypes from main React package --- ui/app/components/account-dropdowns.js | 2 +- ui/app/components/dropdowns/components/account-dropdowns.js | 2 +- ui/app/components/dropdowns/components/dropdown.js | 2 +- ui/app/components/dropdowns/simple-dropdown.js | 2 +- ui/app/components/loading.js | 2 +- ui/app/components/tab-bar.js | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/account-dropdowns.js b/ui/app/components/account-dropdowns.js index 0c34a5154..f69a6ca68 100644 --- a/ui/app/components/account-dropdowns.js +++ b/ui/app/components/account-dropdowns.js @@ -1,5 +1,5 @@ const Component = require('react').Component -const PropTypes = require('react').PropTypes +const PropTypes = require('prop-types') const h = require('react-hyperscript') const actions = require('../actions') const genAccountLink = require('etherscan-link').createAccountLink diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index f97ac0691..d3a549884 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -1,5 +1,5 @@ const Component = require('react').Component -const PropTypes = require('react').PropTypes +const PropTypes = require('prop-types') const h = require('react-hyperscript') const actions = require('../../../actions') const genAccountLink = require('../../../../lib/account-link.js') diff --git a/ui/app/components/dropdowns/components/dropdown.js b/ui/app/components/dropdowns/components/dropdown.js index 15d064be8..0336dbb8b 100644 --- a/ui/app/components/dropdowns/components/dropdown.js +++ b/ui/app/components/dropdowns/components/dropdown.js @@ -1,5 +1,5 @@ const Component = require('react').Component -const PropTypes = require('react').PropTypes +const PropTypes = require('prop-types') const h = require('react-hyperscript') const MenuDroppo = require('../../menu-droppo') const extend = require('xtend') diff --git a/ui/app/components/dropdowns/simple-dropdown.js b/ui/app/components/dropdowns/simple-dropdown.js index 7bb48e57b..bba088ed1 100644 --- a/ui/app/components/dropdowns/simple-dropdown.js +++ b/ui/app/components/dropdowns/simple-dropdown.js @@ -1,5 +1,5 @@ const { Component } = require('react') -const PropTypes = require('react').PropTypes +const PropTypes = require('prop-types') const h = require('react-hyperscript') const classnames = require('classnames') const R = require('ramda') diff --git a/ui/app/components/loading.js b/ui/app/components/loading.js index 9442121fe..cb6fa51fb 100644 --- a/ui/app/components/loading.js +++ b/ui/app/components/loading.js @@ -1,6 +1,6 @@ const { Component } = require('react') const h = require('react-hyperscript') -const PropTypes = require('react').PropTypes +const PropTypes = require('prop-types') class LoadingIndicator extends Component { renderMessage () { diff --git a/ui/app/components/tab-bar.js b/ui/app/components/tab-bar.js index 0edced119..a80640116 100644 --- a/ui/app/components/tab-bar.js +++ b/ui/app/components/tab-bar.js @@ -1,6 +1,6 @@ const { Component } = require('react') const h = require('react-hyperscript') -const PropTypes = require('react').PropTypes +const PropTypes = require('prop-types') const classnames = require('classnames') class TabBar extends Component { -- cgit v1.2.3 From e9c2c0eec19514468fd53087f974709d5df9c35b Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Wed, 7 Feb 2018 18:46:27 -0800 Subject: Make blockies icon round to match identicons (#3205) --- ui/app/components/account-menu/index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index aeb8a0b38..1a0103d4f 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -80,23 +80,23 @@ AccountMenu.prototype.render = function () { h(Divider), h(Item, { onClick: () => showNewAccountPage('CREATE'), - icon: h('img', { src: 'images/plus-btn-white.svg' }), + icon: h('img.account-menu__item-icon', { src: 'images/plus-btn-white.svg' }), text: 'Create Account', }), h(Item, { onClick: () => showNewAccountPage('IMPORT'), - icon: h('img', { src: 'images/import-account.svg' }), + icon: h('img.account-menu__item-icon', { src: 'images/import-account.svg' }), text: 'Import Account', }), h(Divider), h(Item, { onClick: showInfoPage, - icon: h('img', { src: 'images/mm-info-icon.svg' }), + icon: h('img.account-menu__item-icon', { src: 'images/mm-info-icon.svg' }), text: 'Info & Help', }), h(Item, { onClick: showConfigPage, - icon: h('img', { src: 'images/settings.svg' }), + icon: h('img.account-menu__item-icon', { src: 'images/settings.svg' }), text: 'Settings', }), ]) -- cgit v1.2.3 From cd976a2765b9e442642faec8a985c049f8cb393b Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 8 Feb 2018 13:48:25 -0330 Subject: Add reset account button to new UI. --- ui/app/components/modals/modal.js | 13 ++++++ ui/app/components/modals/notification-modal.js | 36 ++++++++++++++--- .../notification-modals/confirm-reset-account.js | 46 ++++++++++++++++++++++ 3 files changed, 89 insertions(+), 6 deletions(-) create mode 100644 ui/app/components/modals/notification-modals/confirm-reset-account.js (limited to 'ui/app/components') diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index afb2a2175..97fe38292 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -18,6 +18,7 @@ const ShapeshiftDepositTxModal = require('./shapeshift-deposit-tx-modal.js') const HideTokenConfirmationModal = require('./hide-token-confirmation-modal') const CustomizeGasModal = require('../customize-gas-modal') const NotifcationModal = require('./notification-modal') +const ConfirmResetAccount = require('./notification-modals/confirm-reset-account') const accountModalStyle = { mobileModalStyle: { @@ -202,6 +203,18 @@ const MODALS = { }, }, + CONFIRM_RESET_ACCOUNT: { + contents: h(ConfirmResetAccount), + mobileModalStyle: { + width: '95%', + top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh', + }, + laptopModalStyle: { + width: '473px', + top: 'calc(33% + 45px)', + }, + }, + NEW_ACCOUNT: { contents: [ h(NewAccountModal, {}, []), diff --git a/ui/app/components/modals/notification-modal.js b/ui/app/components/modals/notification-modal.js index 239144b0c..621a974d0 100644 --- a/ui/app/components/modals/notification-modal.js +++ b/ui/app/components/modals/notification-modal.js @@ -9,26 +9,47 @@ class NotificationModal extends Component { const { header, message, + showCancelButton = false, + showConfirmButton = false, + hideModal, + onConfirm, } = this.props + const showButtons = showCancelButton || showConfirmButton + return h('div', [ - h('div.notification-modal-wrapper', { + h('div.notification-modal__wrapper', { }, [ - h('div.notification-modal-header', {}, [ + h('div.notification-modal__header', {}, [ header, ]), - h('div.notification-modal-message-wrapper', {}, [ - h('div.notification-modal-message', {}, [ + h('div.notification-modal__message-wrapper', {}, [ + h('div.notification-modal__message', {}, [ message, ]), ]), h('div.modal-close-x', { - onClick: this.props.hideModal, + onClick: hideModal, }), + showButtons && h('div.notification-modal__buttons', [ + + showCancelButton && h('div.btn-cancel.notification-modal__buttons__btn', { + onClick: hideModal, + }, 'Cancel'), + + showConfirmButton && h('div.btn-clear.notification-modal__buttons__btn', { + onClick: () => { + onConfirm() + hideModal() + }, + }, 'Confirm'), + + ]), + ]), ]) } @@ -37,7 +58,10 @@ class NotificationModal extends Component { NotificationModal.propTypes = { hideModal: PropTypes.func, header: PropTypes.string, - message: PropTypes.string, + message: PropTypes.node, + showCancelButton: PropTypes.bool, + showConfirmButton: PropTypes.bool, + onConfirm: PropTypes.func, } const mapDispatchToProps = dispatch => { diff --git a/ui/app/components/modals/notification-modals/confirm-reset-account.js b/ui/app/components/modals/notification-modals/confirm-reset-account.js new file mode 100644 index 000000000..e1bc91b24 --- /dev/null +++ b/ui/app/components/modals/notification-modals/confirm-reset-account.js @@ -0,0 +1,46 @@ +const { Component } = require('react') +const PropTypes = require('prop-types') +const h = require('react-hyperscript') +const { connect } = require('react-redux') +const actions = require('../../../actions') +const NotifcationModal = require('../notification-modal') + +class ConfirmResetAccount extends Component { + render () { + const { resetAccount } = this.props + + return h(NotifcationModal, { + header: 'Are you sure you want to reset account?', + message: h('div', [ + + h('span', `Resetting is for developer use only. This button wipes the current account's transaction history, + which is used to calculate the current account nonce. `), + + h('a.notification-modal__link', { + href: 'http://metamask.helpscoutdocs.com/article/36-resetting-an-account', + target: '_blank', + onClick (event) { global.platform.openWindow({ url: event.target.href }) }, + }, 'Read more.'), + + ]), + showCancelButton: true, + showConfirmButton: true, + onConfirm: resetAccount, + + }) + } +} + +ConfirmResetAccount.propTypes = { + resetAccount: PropTypes.func, +} + +const mapDispatchToProps = dispatch => { + return { + resetAccount: () => { + dispatch(actions.resetAccount()) + }, + } +} + +module.exports = connect(null, mapDispatchToProps)(ConfirmResetAccount) -- cgit v1.2.3 From c8c2dfdc0f5d3cf68b5bd3b3ebf8bf6799c640c2 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Thu, 8 Feb 2018 21:10:15 -0330 Subject: Fixes shapeshift txs so that they render in tx list. (#3208) --- ui/app/components/shift-list-item.js | 57 ++++++++++++++++-------------------- ui/app/components/tx-list.js | 7 ++--- 2 files changed, 28 insertions(+), 36 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/shift-list-item.js b/ui/app/components/shift-list-item.js index 111a77df4..017bf9f0c 100644 --- a/ui/app/components/shift-list-item.js +++ b/ui/app/components/shift-list-item.js @@ -29,40 +29,35 @@ function ShiftListItem () { } ShiftListItem.prototype.render = function () { - const { selectedAddress, receivingAddress } = this.props - return ( - selectedAddress === receivingAddress - ? h('div.tx-list-item.tx-list-clickable', { + return h('div.tx-list-item.tx-list-clickable', { + style: { + paddingTop: '20px', + paddingBottom: '20px', + justifyContent: 'space-around', + alignItems: 'center', + }, + }, [ + h('div', { + style: { + width: '0px', + position: 'relative', + bottom: '19px', + }, + }, [ + h('img', { + src: 'https://info.shapeshift.io/sites/default/files/logo.png', style: { - paddingTop: '20px', - paddingBottom: '20px', - justifyContent: 'space-around', - alignItems: 'center', + height: '35px', + width: '132px', + position: 'absolute', + clip: 'rect(0px,23px,34px,0px)', }, - }, [ - h('div', { - style: { - width: '0px', - position: 'relative', - bottom: '19px', - }, - }, [ - h('img', { - src: 'https://info.shapeshift.io/sites/default/files/logo.png', - style: { - height: '35px', - width: '132px', - position: 'absolute', - clip: 'rect(0px,23px,34px,0px)', - }, - }), - ]), + }), + ]), - this.renderInfo(), - this.renderUtilComponents(), - ]) - : null - ) + this.renderInfo(), + this.renderUtilComponents(), + ]) } function formatDate (date) { diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 84cd0f093..1729e6a6f 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -50,6 +50,7 @@ TxList.prototype.render = function () { TxList.prototype.renderTransaction = function () { const { txsToRender, conversionRate } = this.props + return txsToRender.length ? txsToRender.map((transaction, i) => this.renderTransactionListItem(transaction, conversionRate, i)) : [h( @@ -65,11 +66,7 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa // refer to transaction-list.js:line 58 if (transaction.key === 'shapeshift') { - return h('div', { - key: `shapeshift${index}`, - }, [ - h(ShiftListItem, transaction), - ]) + return h(ShiftListItem, { ...transaction, key: `shapeshift${index}` }) } const props = { -- cgit v1.2.3 From 35c762da47c4b604f44e903940245f87eb7a3d3a Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Tue, 13 Feb 2018 03:21:05 -0330 Subject: Updates the styling of confirm send ether and token screens. (#3235) --- ui/app/components/pending-tx/confirm-send-ether.js | 16 +++++++--------- ui/app/components/pending-tx/confirm-send-token.js | 16 +++++++--------- 2 files changed, 14 insertions(+), 18 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 652300c94..3f8d9c28f 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -213,17 +213,15 @@ ConfirmSendEther.prototype.render = function () { this.inputs = [] return ( - h('div.confirm-screen-container.confirm-send-ether', { - style: { minWidth: '355px' }, - }, [ + h('div.confirm-screen-container.confirm-send-ether', [ // Main Send token Card - h('div.confirm-screen-wrapper.flex-column.flex-grow', [ - h('h3.flex-center.confirm-screen-header', [ - h('button.btn-clear.confirm-screen-back-button', { + h('div.page-container', [ + h('div.page-container__header', [ + h('button.confirm-screen-back-button', { onClick: () => editTransaction(txMeta), - }, 'EDIT'), - h('div.confirm-screen-title', 'Confirm Transaction'), - h('div.confirm-screen-header-tip'), + }, 'Edit'), + h('div.page-container__title', 'Confirm'), + h('div.page-container__subtitle', `Please review your transaction.`), ]), h('div.flex-row.flex-center.confirm-screen-identicons', [ h('div.confirm-screen-account-wrapper', [ diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index ad489c3e9..e4b0c186a 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -308,17 +308,15 @@ ConfirmSendToken.prototype.render = function () { this.inputs = [] return ( - h('div.confirm-screen-container.confirm-send-token', { - style: { minWidth: '355px' }, - }, [ + h('div.confirm-screen-container.confirm-send-token', [ // Main Send token Card - h('div.confirm-screen-wrapper.flex-column.flex-grow', [ - h('h3.flex-center.confirm-screen-header', [ - h('button.btn-clear.confirm-screen-back-button', { + h('div.page-container', [ + h('div.page-container__header', [ + h('button.confirm-screen-back-button', { onClick: () => editTransaction(txMeta), - }, 'EDIT'), - h('div.confirm-screen-title', 'Confirm Transaction'), - h('div.confirm-screen-header-tip'), + }, 'Edit'), + h('div.page-container__title', 'Confirm'), + h('div.page-container__subtitle', `Please review your transaction.`), ]), h('div.flex-row.flex-center.confirm-screen-identicons', [ h('div.confirm-screen-account-wrapper', [ -- cgit v1.2.3 From a1b72e5252e15113c98180194cfa7f1640bde08e Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 20 Feb 2018 13:51:06 -0800 Subject: Try fixing notice screen synchronous state call --- ui/app/components/notice.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/notice.js b/ui/app/components/notice.js index 941ac33e6..9d2e89cb0 100644 --- a/ui/app/components/notice.js +++ b/ui/app/components/notice.js @@ -105,8 +105,7 @@ Notice.prototype.render = function () { h('button.primary', { disabled, onClick: () => { - this.setState({disclaimerDisabled: true}) - onConfirm() + this.setState({disclaimerDisabled: true}, () => onConfirm()) }, style: { marginTop: '18px', -- cgit v1.2.3 From 2b9af0734b6127349ed4f1ed535dee858633776b Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 27 Feb 2018 20:05:54 -0330 Subject: Replace 'Contract Published' with 'Contract Deployment' for clearer indication of contract tx state. --- ui/app/components/transaction-list-item.js | 2 +- ui/app/components/tx-list-item.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/transaction-list-item.js b/ui/app/components/transaction-list-item.js index 4e3d2cb93..a45cd441a 100644 --- a/ui/app/components/transaction-list-item.js +++ b/ui/app/components/transaction-list-item.js @@ -180,7 +180,7 @@ function recipientField (txParams, transaction, isTx, isMsg) { } else if (txParams.to) { message = addressSummary(txParams.to) } else { - message = 'Contract Published' + message = 'Contract Deployment' } return h('div', { diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 7ccc5c315..1a13070c8 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -63,7 +63,7 @@ TxListItem.prototype.getAddressText = function () { default: return address ? `${address.slice(0, 10)}...${address.slice(-4)}` - : 'Contract Published' + : 'Contract Deployment' } } -- cgit v1.2.3 From 78f6a4866425ca9fd7795d91ea5dacd47599c1ab Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 28 Feb 2018 13:12:06 -0330 Subject: Define event locally in onClickOutside method in account-dropdowns.js --- ui/app/components/account-dropdowns.js | 2 +- ui/app/components/dropdowns/components/account-dropdowns.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/account-dropdowns.js b/ui/app/components/account-dropdowns.js index f69a6ca68..1cd7a0847 100644 --- a/ui/app/components/account-dropdowns.js +++ b/ui/app/components/account-dropdowns.js @@ -173,7 +173,7 @@ class AccountDropdowns extends Component { minWidth: '180px', }, isOpen: optionsMenuActive, - onClickOutside: () => { + onClickOutside: (event) => { const { classList } = event.target const isNotToggleElement = !classList.contains(this.optionsMenuToggleClassName) if (optionsMenuActive && isNotToggleElement) { diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index d3a549884..fa9ffc632 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -281,7 +281,7 @@ class AccountDropdowns extends Component { dropdownWrapperStyle, ), isOpen: optionsMenuActive, - onClickOutside: () => { + onClickOutside: (event) => { const { classList } = event.target const isNotToggleElement = !classList.contains(this.optionsMenuToggleClassName) if (optionsMenuActive && isNotToggleElement) { -- cgit v1.2.3 From ace4f0d998d75e9df8c31641a292abc4f703582f Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Thu, 1 Mar 2018 13:11:35 -0800 Subject: Fix exception thrown when styleOverride is not present (#3364) --- ui/app/components/eth-balance.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components') diff --git a/ui/app/components/eth-balance.js b/ui/app/components/eth-balance.js index 1be8c9731..c3d084bdc 100644 --- a/ui/app/components/eth-balance.js +++ b/ui/app/components/eth-balance.js @@ -46,7 +46,7 @@ EthBalanceComponent.prototype.renderBalance = function (value) { incoming, currentCurrency, hideTooltip, - styleOveride, + styleOveride = {}, showFiat = true, } = this.props const { fontSize, color, fontFamily, lineHeight } = styleOveride -- cgit v1.2.3 From f22dfd4ae8031e3f7b4972a1cc8f119b99007717 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Thu, 1 Mar 2018 13:12:10 -0800 Subject: Fix network menu for custom URLs (#3366) --- ui/app/components/dropdowns/network-dropdown.js | 40 +++++++++++++++++-------- 1 file changed, 27 insertions(+), 13 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js index dfaa6b22c..9be5cc5d1 100644 --- a/ui/app/components/dropdowns/network-dropdown.js +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -84,7 +84,7 @@ NetworkDropdown.prototype.render = function () { style: { position: 'absolute', top: '58px', - minWidth: '309px', + width: '309px', zIndex: '55px', }, innerStyle: { @@ -276,11 +276,21 @@ NetworkDropdown.prototype.renderCommonRpc = function (rpcList, provider) { key: `common${rpc}`, closeMenu: () => this.props.hideNetworkDropdown(), onClick: () => props.setRpcTarget(rpc), + style: { + fontFamily: 'DIN OT', + fontSize: '16px', + lineHeight: '20px', + padding: '12px 0', + }, }, [ - h('i.fa.fa-question-circle.fa-lg.menu-icon'), - rpc, - rpcTarget === rpc ? h('.check', '✓') : null, + rpcTarget === rpc ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'), + h('i.fa.fa-question-circle.fa-med.menu-icon-circle'), + h('span.network-name-item', { + style: { + color: rpcTarget === rpc ? '#ffffff' : '#9b9b9b', + }, + }, rpc), ] ) } @@ -293,12 +303,6 @@ NetworkDropdown.prototype.renderCustomOption = function (provider) { if (type !== 'rpc') return null - // Concatenate long URLs - let label = rpcTarget - if (rpcTarget.length > 31) { - label = label.substr(0, 34) + '...' - } - switch (rpcTarget) { case 'http://localhost:8545': @@ -311,11 +315,21 @@ NetworkDropdown.prototype.renderCustomOption = function (provider) { key: rpcTarget, onClick: () => props.setRpcTarget(rpcTarget), closeMenu: () => this.props.hideNetworkDropdown(), + style: { + fontFamily: 'DIN OT', + fontSize: '16px', + lineHeight: '20px', + padding: '12px 0', + }, }, [ - h('i.fa.fa-question-circle.fa-lg.menu-icon'), - label, - h('.check', '✓'), + h('i.fa.fa-check'), + h('i.fa.fa-question-circle.fa-med.menu-icon-circle'), + h('span.network-name-item', { + style: { + color: '#ffffff', + }, + }, rpcTarget), ] ) } -- cgit v1.2.3 From 1bd18cebd7e08edbbcf35407b962e71dcd2c3399 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Mon, 5 Mar 2018 13:33:46 -0330 Subject: Fixes shapeshift coin selection dropdown. (#3416) --- ui/app/components/shapeshift-form.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/shapeshift-form.js b/ui/app/components/shapeshift-form.js index 2270b8236..648b05049 100644 --- a/ui/app/components/shapeshift-form.js +++ b/ui/app/components/shapeshift-form.js @@ -51,8 +51,7 @@ ShapeshiftForm.prototype.componentWillMount = function () { this.props.shapeShiftSubview() } -ShapeshiftForm.prototype.onCoinChange = function (e) { - const coin = e.target.value +ShapeshiftForm.prototype.onCoinChange = function (coin) { this.setState({ depositCoin: coin, errorMessage: '', @@ -133,7 +132,7 @@ ShapeshiftForm.prototype.renderMarketInfo = function () { } ShapeshiftForm.prototype.renderQrCode = function () { - const { depositAddress, isLoading } = this.state + const { depositAddress, isLoading, depositCoin } = this.state const qrImage = qrcode(4, 'M') qrImage.addData(depositAddress) qrImage.make() @@ -141,7 +140,7 @@ ShapeshiftForm.prototype.renderQrCode = function () { return h('div.shapeshift-form', {}, [ h('div.shapeshift-form__deposit-instruction', [ - 'Deposit your BTC to the address below:', + `Deposit your ${depositCoin.toUpperCase()} to the address below:`, ]), h('div', depositAddress), @@ -182,7 +181,7 @@ ShapeshiftForm.prototype.render = function () { h(SimpleDropdown, { selectedOption: this.state.depositCoin, - onSelect: this.onCoinChange, + onSelect: (coin) => this.onCoinChange(coin), options: Object.entries(coinOptions).map(([coin]) => ({ value: coin.toLowerCase(), displayValue: coin, -- cgit v1.2.3