diff options
author | Dan <danjm.com@gmail.com> | 2017-10-18 04:13:20 +0800 |
---|---|---|
committer | Chi Kei Chan <chikeichan@gmail.com> | 2017-10-19 11:21:46 +0800 |
commit | 60eda592b5979ac1fdbfb6d5b3418a4924abc14d (patch) | |
tree | c688881be17265045f5b0afa61c1802669643388 /ui | |
parent | f81226fbe9f98d5a6c408e289fa0ea61a467e7dc (diff) | |
download | tangerine-wallet-browser-60eda592b5979ac1fdbfb6d5b3418a4924abc14d.tar tangerine-wallet-browser-60eda592b5979ac1fdbfb6d5b3418a4924abc14d.tar.gz tangerine-wallet-browser-60eda592b5979ac1fdbfb6d5b3418a4924abc14d.tar.bz2 tangerine-wallet-browser-60eda592b5979ac1fdbfb6d5b3418a4924abc14d.tar.lz tangerine-wallet-browser-60eda592b5979ac1fdbfb6d5b3418a4924abc14d.tar.xz tangerine-wallet-browser-60eda592b5979ac1fdbfb6d5b3418a4924abc14d.tar.zst tangerine-wallet-browser-60eda592b5979ac1fdbfb6d5b3418a4924abc14d.zip |
Handling to and amount errors.
Diffstat (limited to 'ui')
-rw-r--r-- | ui/app/actions.js | 10 | ||||
-rw-r--r-- | ui/app/components/send/currency-display.js | 23 | ||||
-rw-r--r-- | ui/app/components/send/send-v2-container.js | 1 | ||||
-rw-r--r-- | ui/app/components/send/to-autocomplete.js | 10 | ||||
-rw-r--r-- | ui/app/conversion-util.js | 11 | ||||
-rw-r--r-- | ui/app/css/itcss/components/send.scss | 11 | ||||
-rw-r--r-- | ui/app/reducers/metamask.js | 16 | ||||
-rw-r--r-- | ui/app/send-v2.js | 97 |
8 files changed, 151 insertions, 28 deletions
diff --git a/ui/app/actions.js b/ui/app/actions.js index ed1ff75e5..25a4abda6 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -140,6 +140,7 @@ var actions = { UPDATE_SEND_TO: 'UPDATE_SEND_TO', UPDATE_SEND_AMOUNT: 'UPDATE_SEND_AMOUNT', UPDATE_SEND_MEMO: 'UPDATE_SEND_MEMO', + UPDATE_SEND_ERRORS: 'UPDATE_SEND_ERRORS', updateGasLimit, updateGasPrice, updateGasTotal, @@ -147,6 +148,7 @@ var actions = { updateSendTo, updateSendAmount, updateSendMemo, + updateSendErrors, setSelectedAddress, // app messages confirmSeedWords: confirmSeedWords, @@ -553,6 +555,14 @@ function updateSendMemo (memo) { } } +function updateSendErrors (error) { + console.log(`updateSendErrors error`, error); + return { + type: actions.UPDATE_SEND_ERRORS, + value: error, + } +} + function sendTx (txData) { log.info(`actions - sendTx: ${JSON.stringify(txData.txParams)}`) 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', [ diff --git a/ui/app/conversion-util.js b/ui/app/conversion-util.js index 3a9e9ad0f..1ef276a39 100644 --- a/ui/app/conversion-util.js +++ b/ui/app/conversion-util.js @@ -157,14 +157,11 @@ const multiplyCurrencies = (a, b, options = {}) => { } const conversionGreaterThan = ( - { value, fromNumericBase }, - { value: compareToValue, fromNumericBase: compareToBase }, + { ...firstProps }, + { ...secondProps }, ) => { - const firstValue = converter({ value, fromNumericBase }) - const secondValue = converter({ - value: compareToValue, - fromNumericBase: compareToBase, - }) + const firstValue = converter({ ...firstProps }) + const secondValue = converter({ ...secondProps }) return firstValue.gt(secondValue) } diff --git a/ui/app/css/itcss/components/send.scss b/ui/app/css/itcss/components/send.scss index ddabdee2e..7e72e8399 100644 --- a/ui/app/css/itcss/components/send.scss +++ b/ui/app/css/itcss/components/send.scss @@ -497,6 +497,17 @@ width: 287px; } + &__error { + font-size: 12px; + line-height: 12px; + left: 8px; + color: $red; + } + + &__error-border { + color: $red; + } + &__form { display: flex; flex-direction: column; diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js index 6915dbb0f..fb2b2e674 100644 --- a/ui/app/reducers/metamask.js +++ b/ui/app/reducers/metamask.js @@ -29,6 +29,7 @@ function reduceMetamask (state, action) { to: '', amount: '0x0', memo: '', + errors: {}, }, }, state.metamask) @@ -224,6 +225,21 @@ function reduceMetamask (state, action) { }, }) + case actions.UPDATE_SEND_ERRORS: + console.log(123, { + ...metamaskState.send.errors, + ...action.value, + }) + return extend(metamaskState, { + send: { + ...metamaskState.send, + errors: { + ...metamaskState.send.errors, + ...action.value, + } + }, + }) + default: return metamaskState diff --git a/ui/app/send-v2.js b/ui/app/send-v2.js index e3182689d..8d368044a 100644 --- a/ui/app/send-v2.js +++ b/ui/app/send-v2.js @@ -12,7 +12,8 @@ const GasFeeDisplay = require('./components/send/gas-fee-display-v2') const { showModal } = require('./actions') -const { multiplyCurrencies } = require('./conversion-util') +const { multiplyCurrencies, conversionGreaterThan } = require('./conversion-util') +const { isValidAddress } = require('./util') module.exports = SendTransactionScreen @@ -22,10 +23,15 @@ function SendTransactionScreen () { this.state = { dropdownOpen: false, + errors: { + to: null, + amount: null, + }, } this.handleToChange = this.handleToChange.bind(this) this.handleAmountChange = this.handleAmountChange.bind(this) + this.validateAmount = this.validateAmount.bind(this) } SendTransactionScreen.prototype.componentWillMount = function () { @@ -126,6 +132,16 @@ SendTransactionScreen.prototype.renderHeader = function () { ]) } +SendTransactionScreen.prototype.renderErrorMessage = function(errorType) { + const { errors } = this.props + console.log(`! errors`, errors); + const errorMessage = errors[errorType]; + console.log(`errorMessage`, errorMessage); + return errorMessage + ? h('div.send-v2__error', [ errorMessage ] ) + : null +} + SendTransactionScreen.prototype.renderFromRow = function () { const { from, @@ -155,57 +171,122 @@ SendTransactionScreen.prototype.renderFromRow = function () { } SendTransactionScreen.prototype.handleToChange = function (event) { - const { updateSendTo } = this.props + const { updateSendTo, updateSendErrors } = this.props const to = event.target.value + let toError = null + + if (!to) { + toError = 'Required' + } else if (!isValidAddress(to)) { + toError = 'Recipient address is invalid.' + } updateSendTo(to) + updateSendErrors({ to: toError }) } SendTransactionScreen.prototype.renderToRow = function () { - const { toAccounts } = this.props + const { toAccounts, errors } = this.props const { to } = this.state return h('div.send-v2__form-row', [ - h('div.send-v2__form-label', 'To:'), + h('div.send-v2__form-label', [ + + 'To:', + + this.renderErrorMessage('to'), + + ]), h(ToAutoComplete, { to, accounts: toAccounts, onChange: this.handleToChange, + inError: Boolean(errors.to), }), ]) } SendTransactionScreen.prototype.handleAmountChange = function (value) { - const { updateSendAmount } = this.props const amount = value + const { updateSendAmount } = this.props updateSendAmount(amount) } +SendTransactionScreen.prototype.validateAmount = function (value) { + const { + from: { balance }, + updateSendErrors, + amountConversionRate, + conversionRate, + primaryCurrency, + toCurrency, + selectedToken + } = this.props + const amount = value + + let amountError = null + + const sufficientBalance = conversionGreaterThan( + { + value: balance, + fromNumericBase: 'hex', + fromCurrency: primaryCurrency, + conversionRate, + }, + { + value: amount, + fromNumericBase: 'hex', + conversionRate: amountConversionRate, + fromCurrency: selectedToken || primaryCurrency, + conversionRate: amountConversionRate, + }, + ) + console.log(`sufficientBalance`, sufficientBalance); + const amountLessThanZero = conversionGreaterThan( + { value: 0, fromNumericBase: 'dec' }, + { value: amount, fromNumericBase: 'hex' }, + ) + + if (!sufficientBalance) { + amountError = 'Insufficient funds.' + } else if (amountLessThanZero) { + amountError = 'Can not send negative amounts of ETH.' + } + + updateSendErrors({ amount: amountError }) +} + SendTransactionScreen.prototype.renderAmountRow = function () { const { selectedToken, primaryCurrency = 'ETH', amountConversionRate, + errors, } = this.props const { amount } = this.state return h('div.send-v2__form-row', [ - h('div.send-v2__form-label', 'Amount:'), + h('div.send-v2__form-label', [ + 'Amount:', + this.renderErrorMessage('amount'), + ]), h(CurrencyDisplay, { + inError: Boolean(errors.amount), primaryCurrency, convertedCurrency: 'USD', value: amount, conversionRate: amountConversionRate, convertedPrefix: '$', - handleChange: this.handleAmountChange - }), + handleChange: this.handleAmountChange, + validate: this.validateAmount, + }), ]) } |