mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
restore status tooltip (#8745)
initially set out to add the failed tooltip back to the transaction list, but in the process rediscovered the transaction-status component which illuminated a fair number of statuses that were not properly handled by the refactor of the list. These statuses were discussed with UX and engineering team members to come up with a definitive list of statuses that should be reflected in the UI Changes: 1. normalized the color of status labels to use Red-500 and Orange-500 where applicable 2. added a new color of icon for pending transactions -- grey 3. added support for dropped and rejected labels 4. failed, dropped, rejected and cancelled all have red icons now. 5. cancelled transactions will reflect a change in the user's balance 6. tooltip displayed for failed transactions 7. Icon logic isolated to a new component.
This commit is contained in:
parent
1f8a7a72c9
commit
a4e5fc934d
@ -1090,7 +1090,7 @@
|
|||||||
"description": "For importing an account from a private key"
|
"description": "For importing an account from a private key"
|
||||||
},
|
},
|
||||||
"pending": {
|
"pending": {
|
||||||
"message": "pending"
|
"message": "Pending"
|
||||||
},
|
},
|
||||||
"permissionCheckedIconDescription": {
|
"permissionCheckedIconDescription": {
|
||||||
"message": "You have approved this permission"
|
"message": "You have approved this permission"
|
||||||
|
1
ui/app/components/app/transaction-icon/index.js
Normal file
1
ui/app/components/app/transaction-icon/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from './transaction-icon'
|
58
ui/app/components/app/transaction-icon/transaction-icon.js
Normal file
58
ui/app/components/app/transaction-icon/transaction-icon.js
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import Approve from '../../ui/icon/approve-icon.component'
|
||||||
|
import Interaction from '../../ui/icon/interaction-icon.component'
|
||||||
|
import Receive from '../../ui/icon/receive-icon.component'
|
||||||
|
import Send from '../../ui/icon/send-icon.component'
|
||||||
|
import Sign from '../../ui/icon/sign-icon.component'
|
||||||
|
import {
|
||||||
|
TRANSACTION_CATEGORY_APPROVAL,
|
||||||
|
TRANSACTION_CATEGORY_SIGNATURE_REQUEST,
|
||||||
|
TRANSACTION_CATEGORY_INTERACTION,
|
||||||
|
TRANSACTION_CATEGORY_SEND,
|
||||||
|
TRANSACTION_CATEGORY_RECEIVE,
|
||||||
|
UNAPPROVED_STATUS,
|
||||||
|
FAILED_STATUS,
|
||||||
|
REJECTED_STATUS,
|
||||||
|
CANCELLED_STATUS,
|
||||||
|
DROPPED_STATUS,
|
||||||
|
SUBMITTED_STATUS,
|
||||||
|
APPROVED_STATUS,
|
||||||
|
} from '../../../helpers/constants/transactions'
|
||||||
|
|
||||||
|
|
||||||
|
const ICON_MAP = {
|
||||||
|
[TRANSACTION_CATEGORY_APPROVAL]: Approve,
|
||||||
|
[TRANSACTION_CATEGORY_INTERACTION]: Interaction,
|
||||||
|
[TRANSACTION_CATEGORY_SEND]: Send,
|
||||||
|
[TRANSACTION_CATEGORY_SIGNATURE_REQUEST]: Sign,
|
||||||
|
[TRANSACTION_CATEGORY_RECEIVE]: Receive,
|
||||||
|
}
|
||||||
|
|
||||||
|
const FAIL_COLOR = '#D73A49'
|
||||||
|
const PENDING_COLOR = '#6A737D'
|
||||||
|
const OK_COLOR = '#2F80ED'
|
||||||
|
|
||||||
|
const COLOR_MAP = {
|
||||||
|
[SUBMITTED_STATUS]: PENDING_COLOR,
|
||||||
|
[UNAPPROVED_STATUS]: PENDING_COLOR,
|
||||||
|
[APPROVED_STATUS]: PENDING_COLOR,
|
||||||
|
[FAILED_STATUS]: FAIL_COLOR,
|
||||||
|
[REJECTED_STATUS]: FAIL_COLOR,
|
||||||
|
[CANCELLED_STATUS]: FAIL_COLOR,
|
||||||
|
[DROPPED_STATUS]: FAIL_COLOR,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function TransactionIcon ({ status, category }) {
|
||||||
|
|
||||||
|
const color = COLOR_MAP[status] || OK_COLOR
|
||||||
|
|
||||||
|
const Icon = ICON_MAP[category]
|
||||||
|
|
||||||
|
return <Icon color={color} size={28} />
|
||||||
|
}
|
||||||
|
|
||||||
|
TransactionIcon.propTypes = {
|
||||||
|
status: PropTypes.string.isRequired,
|
||||||
|
category: PropTypes.string.isRequired,
|
||||||
|
}
|
@ -15,29 +15,14 @@
|
|||||||
color: $Grey-500;
|
color: $Grey-500;
|
||||||
}
|
}
|
||||||
|
|
||||||
&--pending {
|
&--unconfirmed {
|
||||||
color: $Grey-500;
|
color: $Grey-500;
|
||||||
}
|
}
|
||||||
|
|
||||||
&--pending &__primary-currency {
|
&--unconfirmed &__primary-currency {
|
||||||
color: $Grey-500;
|
color: $Grey-500;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__status {
|
|
||||||
&--unapproved {
|
|
||||||
color: $flamingo;
|
|
||||||
}
|
|
||||||
&--failed {
|
|
||||||
color: $valencia;
|
|
||||||
}
|
|
||||||
&--cancelled {
|
|
||||||
color: $valencia;
|
|
||||||
}
|
|
||||||
&--queued {
|
|
||||||
color: $Grey-500;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__pending-actions {
|
&__pending-actions {
|
||||||
padding-top: 12px;
|
padding-top: 12px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -3,11 +3,7 @@ import PropTypes from 'prop-types'
|
|||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import ListItem from '../../ui/list-item'
|
import ListItem from '../../ui/list-item'
|
||||||
import { useTransactionDisplayData } from '../../../hooks/useTransactionDisplayData'
|
import { useTransactionDisplayData } from '../../../hooks/useTransactionDisplayData'
|
||||||
import Approve from '../../ui/icon/approve-icon.component'
|
|
||||||
import Interaction from '../../ui/icon/interaction-icon.component'
|
|
||||||
import Receive from '../../ui/icon/receive-icon.component'
|
|
||||||
import Preloader from '../../ui/icon/preloader'
|
import Preloader from '../../ui/icon/preloader'
|
||||||
import Send from '../../ui/icon/send-icon.component'
|
|
||||||
import { useI18nContext } from '../../../hooks/useI18nContext'
|
import { useI18nContext } from '../../../hooks/useI18nContext'
|
||||||
import { useCancelTransaction } from '../../../hooks/useCancelTransaction'
|
import { useCancelTransaction } from '../../../hooks/useCancelTransaction'
|
||||||
import { useRetryTransaction } from '../../../hooks/useRetryTransaction'
|
import { useRetryTransaction } from '../../../hooks/useRetryTransaction'
|
||||||
@ -17,17 +13,15 @@ import TransactionListItemDetails from '../transaction-list-item-details'
|
|||||||
import { useHistory } from 'react-router-dom'
|
import { useHistory } from 'react-router-dom'
|
||||||
import { CONFIRM_TRANSACTION_ROUTE } from '../../../helpers/constants/routes'
|
import { CONFIRM_TRANSACTION_ROUTE } from '../../../helpers/constants/routes'
|
||||||
import {
|
import {
|
||||||
TRANSACTION_CATEGORY_APPROVAL,
|
|
||||||
TRANSACTION_CATEGORY_SIGNATURE_REQUEST,
|
TRANSACTION_CATEGORY_SIGNATURE_REQUEST,
|
||||||
TRANSACTION_CATEGORY_INTERACTION,
|
|
||||||
TRANSACTION_CATEGORY_SEND,
|
|
||||||
TRANSACTION_CATEGORY_RECEIVE,
|
|
||||||
UNAPPROVED_STATUS,
|
UNAPPROVED_STATUS,
|
||||||
FAILED_STATUS,
|
FAILED_STATUS,
|
||||||
CANCELLED_STATUS,
|
DROPPED_STATUS,
|
||||||
|
REJECTED_STATUS,
|
||||||
} from '../../../helpers/constants/transactions'
|
} from '../../../helpers/constants/transactions'
|
||||||
import { useShouldShowSpeedUp } from '../../../hooks/useShouldShowSpeedUp'
|
import { useShouldShowSpeedUp } from '../../../hooks/useShouldShowSpeedUp'
|
||||||
import Sign from '../../ui/icon/sign-icon.component'
|
import TransactionStatus from '../transaction-status/transaction-status.component'
|
||||||
|
import TransactionIcon from '../transaction-icon'
|
||||||
|
|
||||||
|
|
||||||
export default function TransactionListItem ({ transactionGroup, isEarliestNonce = false }) {
|
export default function TransactionListItem ({ transactionGroup, isEarliestNonce = false }) {
|
||||||
@ -36,7 +30,7 @@ export default function TransactionListItem ({ transactionGroup, isEarliestNonce
|
|||||||
const { hasCancelled } = transactionGroup
|
const { hasCancelled } = transactionGroup
|
||||||
const [showDetails, setShowDetails] = useState(false)
|
const [showDetails, setShowDetails] = useState(false)
|
||||||
|
|
||||||
const { initialTransaction: { id } } = transactionGroup
|
const { initialTransaction: { id }, primaryTransaction } = transactionGroup
|
||||||
|
|
||||||
const [cancelEnabled, cancelTransaction] = useCancelTransaction(transactionGroup)
|
const [cancelEnabled, cancelTransaction] = useCancelTransaction(transactionGroup)
|
||||||
const retryTransaction = useRetryTransaction(transactionGroup)
|
const retryTransaction = useRetryTransaction(transactionGroup)
|
||||||
@ -55,50 +49,12 @@ export default function TransactionListItem ({ transactionGroup, isEarliestNonce
|
|||||||
senderAddress,
|
senderAddress,
|
||||||
} = useTransactionDisplayData(transactionGroup)
|
} = useTransactionDisplayData(transactionGroup)
|
||||||
|
|
||||||
const isApprove = category === TRANSACTION_CATEGORY_APPROVAL
|
|
||||||
const isSignatureReq = category === TRANSACTION_CATEGORY_SIGNATURE_REQUEST
|
const isSignatureReq = category === TRANSACTION_CATEGORY_SIGNATURE_REQUEST
|
||||||
const isInteraction = category === TRANSACTION_CATEGORY_INTERACTION
|
|
||||||
const isSend = category === TRANSACTION_CATEGORY_SEND
|
|
||||||
const isReceive = category === TRANSACTION_CATEGORY_RECEIVE
|
|
||||||
const isUnapproved = status === UNAPPROVED_STATUS
|
const isUnapproved = status === UNAPPROVED_STATUS
|
||||||
const isFailed = status === FAILED_STATUS
|
|
||||||
const isCancelled = status === CANCELLED_STATUS
|
|
||||||
|
|
||||||
const color = isFailed ? '#D73A49' : '#2F80ED'
|
const className = classnames('transaction-list-item', {
|
||||||
|
'transaction-list-item--unconfirmed': isPending || [FAILED_STATUS, DROPPED_STATUS, REJECTED_STATUS].includes(status),
|
||||||
let Icon
|
})
|
||||||
if (isApprove) {
|
|
||||||
Icon = Approve
|
|
||||||
} else if (isSend) {
|
|
||||||
Icon = Send
|
|
||||||
} else if (isReceive) {
|
|
||||||
Icon = Receive
|
|
||||||
} else if (isInteraction) {
|
|
||||||
Icon = Interaction
|
|
||||||
} else if (isSignatureReq) {
|
|
||||||
Icon = Sign
|
|
||||||
}
|
|
||||||
|
|
||||||
let subtitleStatus = <span><span className="transaction-list-item__date">{date}</span> · </span>
|
|
||||||
if (isUnapproved) {
|
|
||||||
subtitleStatus = (
|
|
||||||
<span><span className="transaction-list-item__status--unapproved">{t('unapproved')}</span> · </span>
|
|
||||||
)
|
|
||||||
} else if (isFailed) {
|
|
||||||
subtitleStatus = (
|
|
||||||
<span><span className="transaction-list-item__status--failed">{t('failed')}</span> · </span>
|
|
||||||
)
|
|
||||||
} else if (isCancelled) {
|
|
||||||
subtitleStatus = (
|
|
||||||
<span><span className="transaction-list-item__status--cancelled">{t('cancelled')}</span> · </span>
|
|
||||||
)
|
|
||||||
} else if (isPending && !isEarliestNonce) {
|
|
||||||
subtitleStatus = (
|
|
||||||
<span><span className="transaction-list-item__status--queued">{t('queued')}</span> · </span>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const className = classnames('transaction-list-item', { 'transaction-list-item--pending': isPending })
|
|
||||||
|
|
||||||
const toggleShowDetails = useCallback(() => {
|
const toggleShowDetails = useCallback(() => {
|
||||||
if (isUnapproved) {
|
if (isUnapproved) {
|
||||||
@ -161,9 +117,17 @@ export default function TransactionListItem ({ transactionGroup, isEarliestNonce
|
|||||||
color="#D73A49"
|
color="#D73A49"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
icon={<Icon color={color} size={28} />}
|
icon={<TransactionIcon category={category} status={status} />}
|
||||||
subtitle={subtitle}
|
subtitle={subtitle}
|
||||||
subtitleStatus={subtitleStatus}
|
subtitleStatus={(
|
||||||
|
<TransactionStatus
|
||||||
|
isPending={isPending}
|
||||||
|
isEarliestNonce={isEarliestNonce}
|
||||||
|
error={primaryTransaction.err}
|
||||||
|
date={date}
|
||||||
|
status={status}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
rightContent={!isSignatureReq && (
|
rightContent={!isSignatureReq && (
|
||||||
<>
|
<>
|
||||||
<h2 className="transaction-list-item__primary-currency">{primaryCurrency}</h2>
|
<h2 className="transaction-list-item__primary-currency">{primaryCurrency}</h2>
|
||||||
@ -184,7 +148,7 @@ export default function TransactionListItem ({ transactionGroup, isEarliestNonce
|
|||||||
senderAddress={senderAddress}
|
senderAddress={senderAddress}
|
||||||
recipientAddress={recipientAddress}
|
recipientAddress={recipientAddress}
|
||||||
onRetry={retryTransaction}
|
onRetry={retryTransaction}
|
||||||
showRetry={isFailed}
|
showRetry={status === FAILED_STATUS}
|
||||||
showSpeedUp={shouldShowSpeedUp}
|
showSpeedUp={shouldShowSpeedUp}
|
||||||
isEarliestNonce={isEarliestNonce}
|
isEarliestNonce={isEarliestNonce}
|
||||||
onCancel={cancelTransaction}
|
onCancel={cancelTransaction}
|
||||||
|
@ -1,52 +1,24 @@
|
|||||||
.transaction-status {
|
.transaction-status {
|
||||||
height: 26px;
|
display: inline;
|
||||||
width: 84px;
|
&--unapproved {
|
||||||
border-radius: 4px;
|
color: $Orange-500;
|
||||||
background-color: #f0f0f0;
|
|
||||||
color: #5e6064;
|
|
||||||
font-size: .625rem;
|
|
||||||
text-transform: uppercase;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
@media screen and (max-width: $break-small) {
|
|
||||||
height: 16px;
|
|
||||||
min-width: 72px;
|
|
||||||
font-size: 10px;
|
|
||||||
padding: 0 12px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&--confirmed {
|
|
||||||
background-color: #eafad7;
|
|
||||||
color: #609a1c;
|
|
||||||
|
|
||||||
.transaction-status__transaction-count {
|
|
||||||
border: 1px solid #609a1c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&--approved, &--submitted {
|
|
||||||
background-color: #FFF2DB;
|
|
||||||
color: #CA810A;
|
|
||||||
|
|
||||||
.transaction-status__transaction-count {
|
|
||||||
border: 1px solid #CA810A;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&--failed {
|
&--failed {
|
||||||
background: lighten($monzo, 56%);
|
color: $Red-500;
|
||||||
color: $monzo;
|
|
||||||
|
|
||||||
.transaction-status__transaction-count {
|
|
||||||
border: 1px solid $monzo;
|
|
||||||
}
|
}
|
||||||
|
&--cancelled {
|
||||||
|
color: $Red-500;
|
||||||
}
|
}
|
||||||
|
&--dropped {
|
||||||
&__pending-spinner {
|
color: $Red-500;
|
||||||
height: 16px;
|
}
|
||||||
width: 16px;
|
&--rejected {
|
||||||
margin-right: 6px;
|
color: $Red-500;
|
||||||
|
}
|
||||||
|
&--pending {
|
||||||
|
color: $Orange-500;
|
||||||
|
}
|
||||||
|
&--queued {
|
||||||
|
color: $Grey-500;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,33 +1,80 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import assert from 'assert'
|
import assert from 'assert'
|
||||||
import { mount } from 'enzyme'
|
import { mount } from 'enzyme'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import * as i18nHook from '../../../../hooks/useI18nContext'
|
||||||
import TransactionStatus from '../transaction-status.component'
|
import TransactionStatus from '../transaction-status.component'
|
||||||
import Tooltip from '../../../ui/tooltip-v2'
|
import Tooltip from '../../../ui/tooltip-v2'
|
||||||
|
|
||||||
describe('TransactionStatus Component', function () {
|
describe('TransactionStatus Component', function () {
|
||||||
it('should render APPROVED properly', function () {
|
before(function () {
|
||||||
|
sinon.stub(i18nHook, 'useI18nContext').returns((str) => str.toUpperCase())
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should render CONFIRMED properly', function () {
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<TransactionStatus
|
<TransactionStatus
|
||||||
statusKey="approved"
|
status="confirmed"
|
||||||
title="test-title"
|
date="June 1"
|
||||||
/>,
|
/>
|
||||||
{ context: { t: (str) => str.toUpperCase() } }
|
|
||||||
)
|
)
|
||||||
|
|
||||||
assert.ok(wrapper)
|
assert.ok(wrapper)
|
||||||
assert.equal(wrapper.text(), 'APPROVED')
|
assert.equal(wrapper.text(), 'June 1 · ')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should render PENDING properly when status is APPROVED', function () {
|
||||||
|
const wrapper = mount(
|
||||||
|
<TransactionStatus
|
||||||
|
status="approved"
|
||||||
|
isEarliestNonce
|
||||||
|
error={{ message: 'test-title' }}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.ok(wrapper)
|
||||||
|
assert.equal(wrapper.text(), 'PENDING · ')
|
||||||
assert.equal(wrapper.find(Tooltip).props().title, 'test-title')
|
assert.equal(wrapper.find(Tooltip).props().title, 'test-title')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should render SUBMITTED properly', function () {
|
it('should render PENDING properly', function () {
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<TransactionStatus
|
<TransactionStatus
|
||||||
statusKey="submitted"
|
date="June 1"
|
||||||
/>,
|
status="submitted"
|
||||||
{ context: { t: (str) => str.toUpperCase() } }
|
isEarliestNonce
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
assert.ok(wrapper)
|
assert.ok(wrapper)
|
||||||
assert.equal(wrapper.text(), 'PENDING')
|
assert.equal(wrapper.text(), 'PENDING · ')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should render QUEUED properly', function () {
|
||||||
|
const wrapper = mount(
|
||||||
|
<TransactionStatus
|
||||||
|
status="queued"
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.ok(wrapper)
|
||||||
|
assert.ok(wrapper.find('.transaction-status--queued').length, 'queued className not found')
|
||||||
|
assert.equal(wrapper.text(), 'QUEUED · ')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should render UNAPPROVED properly', function () {
|
||||||
|
const wrapper = mount(
|
||||||
|
<TransactionStatus
|
||||||
|
status="unapproved"
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.ok(wrapper)
|
||||||
|
assert.ok(wrapper.find('.transaction-status--unapproved').length, 'unapproved className not found')
|
||||||
|
assert.equal(wrapper.text(), 'UNAPPROVED · ')
|
||||||
|
})
|
||||||
|
|
||||||
|
after(function () {
|
||||||
|
sinon.restore()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,66 +1,78 @@
|
|||||||
import React, { PureComponent } from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import Tooltip from '../../ui/tooltip-v2'
|
import Tooltip from '../../ui/tooltip-v2'
|
||||||
import Spinner from '../../ui/spinner'
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
UNAPPROVED_STATUS,
|
UNAPPROVED_STATUS,
|
||||||
REJECTED_STATUS,
|
REJECTED_STATUS,
|
||||||
APPROVED_STATUS,
|
|
||||||
SIGNED_STATUS,
|
|
||||||
SUBMITTED_STATUS,
|
SUBMITTED_STATUS,
|
||||||
CONFIRMED_STATUS,
|
CONFIRMED_STATUS,
|
||||||
FAILED_STATUS,
|
FAILED_STATUS,
|
||||||
DROPPED_STATUS,
|
DROPPED_STATUS,
|
||||||
CANCELLED_STATUS,
|
CANCELLED_STATUS,
|
||||||
|
APPROVED_STATUS,
|
||||||
|
SIGNED_STATUS,
|
||||||
} from '../../../helpers/constants/transactions'
|
} from '../../../helpers/constants/transactions'
|
||||||
|
import { useI18nContext } from '../../../hooks/useI18nContext'
|
||||||
|
|
||||||
|
const QUEUED_PSEUDO_STATUS = 'queued'
|
||||||
|
const PENDING_PSEUDO_STATUS = 'pending'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A note about status logic for this component:
|
||||||
|
* Approved, Signed and Submitted statuses are all treated, effectively
|
||||||
|
* as pending. Transactions are only approved or signed for less than a
|
||||||
|
* second, usually, and ultimately should be rendered in the UI no
|
||||||
|
* differently than a pending transaction.
|
||||||
|
*
|
||||||
|
* Confirmed transactions are not especially highlighted except that their
|
||||||
|
* status label will be the date the transaction was finalized.
|
||||||
|
*/
|
||||||
|
const pendingStatusHash = {
|
||||||
|
[SUBMITTED_STATUS]: PENDING_PSEUDO_STATUS,
|
||||||
|
[APPROVED_STATUS]: PENDING_PSEUDO_STATUS,
|
||||||
|
[SIGNED_STATUS]: PENDING_PSEUDO_STATUS,
|
||||||
|
}
|
||||||
|
|
||||||
const statusToClassNameHash = {
|
const statusToClassNameHash = {
|
||||||
[UNAPPROVED_STATUS]: 'transaction-status--unapproved',
|
[UNAPPROVED_STATUS]: 'transaction-status--unapproved',
|
||||||
[REJECTED_STATUS]: 'transaction-status--rejected',
|
[REJECTED_STATUS]: 'transaction-status--rejected',
|
||||||
[APPROVED_STATUS]: 'transaction-status--approved',
|
|
||||||
[SIGNED_STATUS]: 'transaction-status--signed',
|
|
||||||
[SUBMITTED_STATUS]: 'transaction-status--submitted',
|
|
||||||
[CONFIRMED_STATUS]: 'transaction-status--confirmed',
|
|
||||||
[FAILED_STATUS]: 'transaction-status--failed',
|
[FAILED_STATUS]: 'transaction-status--failed',
|
||||||
[DROPPED_STATUS]: 'transaction-status--dropped',
|
[DROPPED_STATUS]: 'transaction-status--dropped',
|
||||||
[CANCELLED_STATUS]: 'transaction-status--failed',
|
[CANCELLED_STATUS]: 'transaction-status--cancelled',
|
||||||
|
[QUEUED_PSEUDO_STATUS]: 'transaction-status--queued',
|
||||||
|
[PENDING_PSEUDO_STATUS]: 'transaction-status--pending',
|
||||||
}
|
}
|
||||||
|
|
||||||
const statusToTextHash = {
|
export default function TransactionStatus ({ status, date, error, isEarliestNonce, className }) {
|
||||||
[SUBMITTED_STATUS]: 'pending',
|
const t = useI18nContext()
|
||||||
}
|
const tooltipText = error?.rpc?.message || error?.message
|
||||||
|
let statusKey = status
|
||||||
export default class TransactionStatus extends PureComponent {
|
if (pendingStatusHash[status]) {
|
||||||
static defaultProps = {
|
statusKey = isEarliestNonce ? PENDING_PSEUDO_STATUS : QUEUED_PSEUDO_STATUS
|
||||||
title: null,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static contextTypes = {
|
const statusText = statusKey === CONFIRMED_STATUS ? date : t(statusKey)
|
||||||
t: PropTypes.func,
|
|
||||||
}
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
statusKey: PropTypes.string,
|
|
||||||
className: PropTypes.string,
|
|
||||||
title: PropTypes.string,
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const { className, statusKey, title } = this.props
|
|
||||||
const statusText = this.context.t(statusToTextHash[statusKey] || statusKey)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classnames('transaction-status', className, statusToClassNameHash[statusKey])}>
|
<span>
|
||||||
{ statusToTextHash[statusKey] === 'pending' ? <Spinner className="transaction-status__pending-spinner" /> : null }
|
|
||||||
<Tooltip
|
<Tooltip
|
||||||
position="top"
|
position="top"
|
||||||
title={title}
|
title={tooltipText}
|
||||||
|
wrapperClassName={classnames('transaction-status', className, statusToClassNameHash[statusKey])}
|
||||||
>
|
>
|
||||||
{ statusText }
|
{ statusText }
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
{' · '}
|
||||||
|
</span>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TransactionStatus.propTypes = {
|
||||||
|
status: PropTypes.string,
|
||||||
|
className: PropTypes.string,
|
||||||
|
date: PropTypes.string,
|
||||||
|
error: PropTypes.object,
|
||||||
|
isEarliestNonce: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user