aboutsummaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorAlexander Tseung <alextsg@gmail.com>2018-08-03 11:20:15 +0800
committerAlexander Tseung <alextsg@gmail.com>2018-08-24 07:44:44 +0800
commit5ddd9b55be0d8bd778822b4b401cbd22a7b57c54 (patch)
tree607cb4747aba68d7f6127e5f1bfb6d732f735acf /ui
parentfa8313f9036882e1a558d871f4e520da71ffaa03 (diff)
downloadtangerine-wallet-browser-5ddd9b55be0d8bd778822b4b401cbd22a7b57c54.tar
tangerine-wallet-browser-5ddd9b55be0d8bd778822b4b401cbd22a7b57c54.tar.gz
tangerine-wallet-browser-5ddd9b55be0d8bd778822b4b401cbd22a7b57c54.tar.bz2
tangerine-wallet-browser-5ddd9b55be0d8bd778822b4b401cbd22a7b57c54.tar.lz
tangerine-wallet-browser-5ddd9b55be0d8bd778822b4b401cbd22a7b57c54.tar.xz
tangerine-wallet-browser-5ddd9b55be0d8bd778822b4b401cbd22a7b57c54.tar.zst
tangerine-wallet-browser-5ddd9b55be0d8bd778822b4b401cbd22a7b57c54.zip
Add retry button to TransactionListItem
Diffstat (limited to 'ui')
-rw-r--r--ui/app/components/token-view-balance/index.scss10
-rw-r--r--ui/app/components/token-view-balance/token-view-balance.component.js2
-rw-r--r--ui/app/components/transaction-action/index.js2
-rw-r--r--ui/app/components/transaction-action/transaction-action.container.js4
-rw-r--r--ui/app/components/transaction-list-item/index.scss45
-rw-r--r--ui/app/components/transaction-list-item/transaction-list-item.component.js110
-rw-r--r--ui/app/components/transaction-list-item/transaction-list-item.container.js12
-rw-r--r--ui/app/components/transaction-list/transaction-list.component.js11
-rw-r--r--ui/app/components/transaction-list/transaction-list.container.js6
-rw-r--r--ui/app/helpers/transactions.util.js21
-rw-r--r--ui/app/util.js2
11 files changed, 175 insertions, 50 deletions
diff --git a/ui/app/components/token-view-balance/index.scss b/ui/app/components/token-view-balance/index.scss
index 6a89e125b..b522a10f9 100644
--- a/ui/app/components/token-view-balance/index.scss
+++ b/ui/app/components/token-view-balance/index.scss
@@ -16,6 +16,16 @@
}
}
+ &__token-balance {
+ margin-left: 12px;
+ font-size: 1.5rem;
+
+ @media screen and (max-width: $break-small) {
+ margin-bottom: 12px;
+ font-size: 1.75rem;
+ }
+ }
+
&__primary-balance {
font-size: 1.5rem;
diff --git a/ui/app/components/token-view-balance/token-view-balance.component.js b/ui/app/components/token-view-balance/token-view-balance.component.js
index 6b8140a22..f74cc4926 100644
--- a/ui/app/components/token-view-balance/token-view-balance.component.js
+++ b/ui/app/components/token-view-balance/token-view-balance.component.js
@@ -30,7 +30,7 @@ export default class TokenViewBalance extends PureComponent {
<TokenBalance
token={selectedToken}
withSymbol
- className="token-view-balance__primary-balance"
+ className="token-view-balance__token-balance"
/>
) : (
<div className="token-view-balance__balance">
diff --git a/ui/app/components/transaction-action/index.js b/ui/app/components/transaction-action/index.js
index 5882443b6..a6e9097f1 100644
--- a/ui/app/components/transaction-action/index.js
+++ b/ui/app/components/transaction-action/index.js
@@ -1 +1 @@
-export { default } from './transaction-action.container'
+export { default } from './transaction-action.component'
diff --git a/ui/app/components/transaction-action/transaction-action.container.js b/ui/app/components/transaction-action/transaction-action.container.js
deleted file mode 100644
index 56efbdc26..000000000
--- a/ui/app/components/transaction-action/transaction-action.container.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import withMethodData from '../../higher-order-components/with-method-data'
-import TransactionAction from './transaction-action.component'
-
-export default withMethodData(TransactionAction)
diff --git a/ui/app/components/transaction-list-item/index.scss b/ui/app/components/transaction-list-item/index.scss
index b93edebcc..9c53c8960 100644
--- a/ui/app/components/transaction-list-item/index.scss
+++ b/ui/app/components/transaction-list-item/index.scss
@@ -2,21 +2,36 @@
box-sizing: border-box;
min-height: 74px;
padding: 8px 20px;
- display: grid;
- grid-template-columns: 45px 1fr 1fr 1fr;
- grid-template-areas:
- "identicon action status primary-amount"
- "identicon nonce status secondary-amount";
border-bottom: 1px solid $geyser;
cursor: pointer;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-direction: column;
@media screen and (max-width: $break-small) {
padding: 8px 20px 12px;
- grid-template-columns: 45px 5fr 3fr;
+ }
+
+ &:hover {
+ background: rgba($alto, .2);
+ }
+
+ &__grid {
+ width: 100%;
+ display: grid;
+ grid-template-columns: 45px 1fr 1fr 1fr;
grid-template-areas:
- "nonce nonce nonce"
- "identicon action primary-amount"
- "identicon status secondary-amount";
+ "identicon action status primary-amount"
+ "identicon nonce status secondary-amount";
+
+ @media screen and (max-width: $break-small) {
+ grid-template-columns: 45px 5fr 3fr;
+ grid-template-areas:
+ "nonce nonce nonce"
+ "identicon action primary-amount"
+ "identicon status secondary-amount";
+ }
}
&__identicon {
@@ -87,8 +102,16 @@
}
}
+ &__retry {
+ background: #d1edff;
+ border-radius: 12px;
+ font-size: .75rem;
+ padding: 4px 12px;
+ cursor: pointer;
+ margin-top: 8px;
- &:hover {
- background: rgba($alto, .2);
+ @media screen and (max-width: $break-small) {
+ font-size: .5rem;
+ }
}
}
diff --git a/ui/app/components/transaction-list-item/transaction-list-item.component.js b/ui/app/components/transaction-list-item/transaction-list-item.component.js
index 928d531f0..bf3f09d28 100644
--- a/ui/app/components/transaction-list-item/transaction-list-item.component.js
+++ b/ui/app/components/transaction-list-item/transaction-list-item.component.js
@@ -6,7 +6,7 @@ import TransactionAction from '../transaction-action'
import { formatDate } from '../../util'
import prefixForNetwork from '../../../lib/etherscan-prefix-for-network'
import { CONFIRM_TRANSACTION_ROUTE } from '../../routes'
-import { UNAPPROVED_STATUS } from '../../constants/transactions'
+import { UNAPPROVED_STATUS, TOKEN_METHOD_TRANSFER } from '../../constants/transactions'
import { hexToDecimal } from '../../helpers/conversions.util'
export default class TransactionListItem extends PureComponent {
@@ -15,6 +15,10 @@ export default class TransactionListItem extends PureComponent {
transaction: PropTypes.object,
ethTransactionAmount: PropTypes.string,
fiatDisplayValue: PropTypes.string,
+ methodData: PropTypes.object,
+ showRetry: PropTypes.bool,
+ retryTransaction: PropTypes.func,
+ setSelectedToken: PropTypes.func,
}
handleClick = () => {
@@ -30,44 +34,92 @@ export default class TransactionListItem extends PureComponent {
}
}
+ handleRetryClick = event => {
+ event.stopPropagation()
+
+ const {
+ transaction: { txParams: { to } = {} },
+ methodData: { name } = {},
+ setSelectedToken,
+ } = this.props
+
+ if (name === TOKEN_METHOD_TRANSFER) {
+ setSelectedToken(to)
+ }
+
+ this.resubmit()
+ }
+
+ resubmit () {
+ const { transaction: { id }, retryTransaction, history } = this.props
+ retryTransaction(id)
+ .then(id => history.push(`${CONFIRM_TRANSACTION_ROUTE}/${id}`))
+ }
+
render () {
- const { transaction, ethTransactionAmount, fiatDisplayValue } = this.props
+ const {
+ transaction,
+ ethTransactionAmount,
+ fiatDisplayValue,
+ methodData,
+ showRetry,
+ } = this.props
const { txParams = {} } = transaction
const nonce = hexToDecimal(txParams.nonce)
+ const nonceAndDateText = `#${nonce} - ${formatDate(transaction.time)}`
+ const fiatDisplayText = `-${fiatDisplayValue}`
+ const ethDisplayText = `-${ethTransactionAmount} ETH`
+
return (
<div
className="transaction-list-item"
onClick={this.handleClick}
>
- <Identicon
- className="transaction-list-item__identicon"
- address={txParams.to}
- diameter={34}
- />
- <TransactionAction
- transaction={transaction}
- className="transaction-list-item__action"
- />
- <div className="transaction-list-item__nonce">
- { `#${nonce} - ${formatDate(transaction.time)}` }
- </div>
- <TransactionStatus
- className="transaction-list-item__status"
- status={transaction.status}
- />
- <div
- className="transaction-list-item__amount transaction-list-item__amount--primary"
- title={`-${fiatDisplayValue}`}
- >
- { `-${fiatDisplayValue}` }
- </div>
- <div
- className="transaction-list-item__amount transaction-list-item__amount--secondary"
- title={`-${ethTransactionAmount} ETH`}
- >
- { `-${ethTransactionAmount} ETH` }
+ <div className="transaction-list-item__grid">
+ <Identicon
+ className="transaction-list-item__identicon"
+ address={txParams.to}
+ diameter={34}
+ />
+ <TransactionAction
+ transaction={transaction}
+ methodData={methodData}
+ className="transaction-list-item__action"
+ />
+ <div
+ className="transaction-list-item__nonce"
+ title={nonceAndDateText}
+ >
+ { nonceAndDateText }
+ </div>
+ <TransactionStatus
+ className="transaction-list-item__status"
+ status={transaction.status}
+ />
+ <div
+ className="transaction-list-item__amount transaction-list-item__amount--primary"
+ title={fiatDisplayText}
+ >
+ { fiatDisplayText }
+ </div>
+ <div
+ className="transaction-list-item__amount transaction-list-item__amount--secondary"
+ title={ethDisplayText}
+ >
+ { ethDisplayText }
+ </div>
</div>
+ {
+ showRetry && !methodData.isFetching && (
+ <div
+ className="transaction-list-item__retry"
+ onClick={this.handleRetryClick}
+ >
+ <span>Taking too long? Increase the gas price on your transaction</span>
+ </div>
+ )
+ }
</div>
)
}
diff --git a/ui/app/components/transaction-list-item/transaction-list-item.container.js b/ui/app/components/transaction-list-item/transaction-list-item.container.js
index bc47f20aa..d6e57028e 100644
--- a/ui/app/components/transaction-list-item/transaction-list-item.container.js
+++ b/ui/app/components/transaction-list-item/transaction-list-item.container.js
@@ -1,7 +1,9 @@
import { connect } from 'react-redux'
import { withRouter } from 'react-router-dom'
import { compose } from 'recompose'
+import withMethodData from '../../higher-order-components/with-method-data'
import TransactionListItem from './transaction-list-item.component'
+import { setSelectedToken, retryTransaction } from '../../actions'
import { getEthFromWeiHex, getValueFromWeiHex } from '../../helpers/conversions.util'
import { formatCurrency } from '../../helpers/confirm-transaction/util'
@@ -22,7 +24,15 @@ const mapStateToProps = (state, ownProps) => {
}
}
+const mapDispatchToProps = dispatch => {
+ return {
+ setSelectedToken: tokenAddress => dispatch(setSelectedToken(tokenAddress)),
+ retryTransaction: transactionId => dispatch(retryTransaction(transactionId)),
+ }
+}
+
export default compose(
withRouter,
- connect(mapStateToProps),
+ connect(mapStateToProps, mapDispatchToProps),
+ withMethodData,
)(TransactionListItem)
diff --git a/ui/app/components/transaction-list/transaction-list.component.js b/ui/app/components/transaction-list/transaction-list.component.js
index d9b8e3cf8..fb23ece7a 100644
--- a/ui/app/components/transaction-list/transaction-list.component.js
+++ b/ui/app/components/transaction-list/transaction-list.component.js
@@ -10,16 +10,24 @@ export default class TransactionList extends PureComponent {
static defaultProps = {
pendingTransactions: [],
completedTransactions: [],
+ transactionToRetry: {},
}
static propTypes = {
pendingTransactions: PropTypes.array,
completedTransactions: PropTypes.array,
+ transactionToRetry: PropTypes.object,
+ }
+
+ shouldShowRetry = transaction => {
+ const { transactionToRetry } = this.props
+ const { id, submittedTime } = transaction
+ return id === transactionToRetry.id && Date.now() - submittedTime > 30000
}
renderTransactions () {
const { t } = this.context
- const { pendingTransactions, completedTransactions } = this.props
+ const { pendingTransactions = [], completedTransactions = [] } = this.props
return (
<div className="transaction-list__transactions">
@@ -34,6 +42,7 @@ export default class TransactionList extends PureComponent {
<TransactionListItem
transaction={transaction}
key={transaction.id}
+ showRetry={this.shouldShowRetry(transaction)}
/>
))
}
diff --git a/ui/app/components/transaction-list/transaction-list.container.js b/ui/app/components/transaction-list/transaction-list.container.js
index b1c2c04c9..97a94b981 100644
--- a/ui/app/components/transaction-list/transaction-list.container.js
+++ b/ui/app/components/transaction-list/transaction-list.container.js
@@ -6,11 +6,15 @@ import {
pendingTransactionsSelector,
completedTransactionsSelector,
} from '../../selectors/transactions'
+import { getLatestSubmittedTxWithEarliestNonce } from '../../helpers/transactions.util'
const mapStateToProps = state => {
+ const pendingTransactions = pendingTransactionsSelector(state)
+
return {
- pendingTransactions: pendingTransactionsSelector(state),
completedTransactions: completedTransactionsSelector(state),
+ pendingTransactions,
+ transactionToRetry: getLatestSubmittedTxWithEarliestNonce(pendingTransactions),
}
}
diff --git a/ui/app/helpers/transactions.util.js b/ui/app/helpers/transactions.util.js
index 04cef150f..68e935702 100644
--- a/ui/app/helpers/transactions.util.js
+++ b/ui/app/helpers/transactions.util.js
@@ -2,6 +2,8 @@ import ethUtil from 'ethereumjs-util'
import MethodRegistry from 'eth-method-registry'
const registry = new MethodRegistry({ provider: global.ethereumProvider })
+import { hexToDecimal } from './conversions.util'
+
import {
TOKEN_METHOD_TRANSFER,
TOKEN_METHOD_APPROVE,
@@ -55,3 +57,22 @@ export async function getMethodData (data = {}) {
params: parsedResult.args,
}
}
+
+export function getLatestSubmittedTxWithEarliestNonce (transactions = []) {
+ if (!transactions.length) {
+ return {}
+ }
+
+ return transactions.reduce((acc, current) => {
+ const accNonce = hexToDecimal(acc.nonce)
+ const currentNonce = hexToDecimal(current.nonce)
+
+ if (currentNonce < accNonce) {
+ return current
+ } else if (currentNonce === accNonce) {
+ return current.submittedTime > acc.submittedTime ? current : acc
+ } else {
+ return acc
+ }
+ })
+}
diff --git a/ui/app/util.js b/ui/app/util.js
index d5558c04e..37c0fb698 100644
--- a/ui/app/util.js
+++ b/ui/app/util.js
@@ -9,7 +9,7 @@ const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR)
// formatData :: ( date: <Unix Timestamp> ) -> String
function formatDate (date) {
- return vreme.format(new Date(date), 'March 16 2014, at 14:30')
+ return vreme.format(new Date(date), '3/16/2014 at 14:30')
}
var valueTable = {