refactoring ownersList column, move it to separate component to decrease complexity of ExpandedTx component

This commit is contained in:
mmv 2019-07-09 15:59:57 +04:00
parent 7cd59d918f
commit d768fcbdae
5 changed files with 133 additions and 76 deletions

View File

@ -0,0 +1,120 @@
// @flow
import React, { useState } from 'react'
import { List } from 'immutable'
import { withStyles } from '@material-ui/core/styles'
import Tabs from '@material-ui/core/Tabs'
import Tab from '@material-ui/core/Tab'
import Col from '~/components/layout/Col'
import Row from '~/components/layout/Row'
import Hairline from '~/components/layout/Hairline'
import { type Owner } from '~/routes/safe/store/models/owner'
import { type Transaction } from '~/routes/safe/store/models/transaction'
import { TX_TYPE_CONFIRMATION } from '~/logic/safe/transactions/send'
import { EMPTY_DATA } from '~/logic/wallets/ethTransactions'
import OwnersList from './List'
import ButtonRow from './ButtonRow'
import { styles } from './style'
type Props = {
tx: Transaction,
owners: List<Owner>,
classes: Object,
granted: boolean,
threshold: number,
userAddress: string,
thresholdReached: boolean,
safeAddress: string,
onTxConfirm: Function,
onTxCancel: Function,
onTxExecute: Function,
}
const isCancellationTransaction = (tx: Transaction, safeAddress: string) => !tx.value && tx.data === EMPTY_DATA && tx.recipient === safeAddress
const OwnersColumn = ({
tx,
owners,
classes,
granted,
threshold,
userAddress,
thresholdReached,
safeAddress,
onTxConfirm,
onTxCancel,
onTxExecute,
}: Props) => {
const [tabIndex, setTabIndex] = useState(0)
const handleTabChange = (event, tabClicked) => {
setTabIndex(tabClicked)
}
const cancellationTx = isCancellationTransaction(tx, safeAddress)
const confirmedLabel = `Confirmed [${
tx.confirmations.filter(conf => conf.type === TX_TYPE_CONFIRMATION).size
}/${threshold}]`
const unconfirmedLabel = `Unconfirmed [${owners.size - tx.confirmations.size}]`
const ownersWhoConfirmed = []
const ownersUnconfirmed = []
let currentUserAlreadyConfirmed = false
let executionConfirmation
owners.forEach((owner) => {
const ownerConfirmation = tx.confirmations.find(conf => conf.owner.address === owner.address)
if (ownerConfirmation) {
if (ownerConfirmation.type === TX_TYPE_CONFIRMATION) {
ownersWhoConfirmed.push(owner)
} else {
executionConfirmation = owner
}
if (owner.address === userAddress) {
currentUserAlreadyConfirmed = true
}
} else {
ownersUnconfirmed.push(owner)
}
})
let displayButtonRow = true
if (tx.isExecuted) {
// already executed, can't do any actions
displayButtonRow = false
} else if (tx.status === 'cancelled') {
// tx is cancelled (replaced) by another one
displayButtonRow = false
} else if (cancellationTx && currentUserAlreadyConfirmed && !thresholdReached) {
// the TX is the cancellation (replacement) transaction for previous TX,
// current user has already confirmed it and threshold is not reached (so he can't execute/cancel it)
displayButtonRow = false
}
return (
<Col xs={6} className={classes.rightCol} layout="block">
<Row>
<Tabs value={tabIndex} onChange={handleTabChange} indicatorColor="secondary" textColor="secondary">
<Tab label={confirmedLabel} />
<Tab label={unconfirmedLabel} />
</Tabs>
<Hairline color="#c8ced4" />
</Row>
<Row>
{tabIndex === 0 && <OwnersList owners={ownersWhoConfirmed} executionConfirmation={executionConfirmation} />}
</Row>
<Row>{tabIndex === 1 && <OwnersList owners={ownersUnconfirmed} />}</Row>
{granted && displayButtonRow && (
<ButtonRow
onTxConfirm={onTxConfirm}
onTxCancel={onTxCancel}
showConfirmBtn={!currentUserAlreadyConfirmed}
showCancelBtn={!cancellationTx}
showExecuteBtn={thresholdReached}
onTxExecute={onTxExecute}
/>
)}
</Col>
)
}
export default withStyles(styles)(OwnersColumn)

View File

@ -17,10 +17,8 @@ import { type Owner } from '~/routes/safe/store/models/owner'
import { getEtherScanLink, openTxInEtherScan, getWeb3 } from '~/logic/wallets/getWeb3' import { getEtherScanLink, openTxInEtherScan, getWeb3 } from '~/logic/wallets/getWeb3'
import { shortVersionOf } from '~/logic/wallets/ethAddresses' import { shortVersionOf } from '~/logic/wallets/ethAddresses'
import { TX_TYPE_CONFIRMATION } from '~/logic/safe/transactions' import { TX_TYPE_CONFIRMATION } from '~/logic/safe/transactions'
import { EMPTY_DATA } from '~/logic/wallets/ethTransactions'
import { secondary } from '~/theme/variables' import { secondary } from '~/theme/variables'
import OwnersList from './OwnersList' import OwnersColumn from './OwnersColumn'
import ButtonRow from './ButtonRow'
import CancelTxModal from './CancelTxModal' import CancelTxModal from './CancelTxModal'
import ApproveTxModal from './ApproveTxModal' import ApproveTxModal from './ApproveTxModal'
import { styles } from './style' import { styles } from './style'
@ -55,8 +53,6 @@ const txStatusToLabel = {
awaiting_execution: 'Awaiting execution', awaiting_execution: 'Awaiting execution',
} }
const isCancellationTransaction = (tx: Transaction, safeAddress: string) => !tx.value && tx.data === EMPTY_DATA && tx.recipient === safeAddress
const ExpandedTx = ({ const ExpandedTx = ({
classes, classes,
tx, tx,
@ -68,57 +64,12 @@ const ExpandedTx = ({
createTransaction, createTransaction,
processTransaction, processTransaction,
}: Props) => { }: Props) => {
const [tabIndex, setTabIndex] = useState<number>(0)
const [openModal, setOpenModal] = useState<OpenModal>(null) const [openModal, setOpenModal] = useState<OpenModal>(null)
const openApproveModal = () => setOpenModal('approveTx') const openApproveModal = () => setOpenModal('approveTx')
const openCancelModal = () => setOpenModal('cancelTx') const openCancelModal = () => setOpenModal('cancelTx')
const closeModal = () => setOpenModal(null) const closeModal = () => setOpenModal(null)
const cancellationTx = isCancellationTransaction(tx, safeAddress)
const confirmedLabel = `Confirmed [${
tx.confirmations.filter(conf => conf.type === TX_TYPE_CONFIRMATION).size
}/${threshold}]`
const unconfirmedLabel = `Unconfirmed [${owners.size - tx.confirmations.size}]`
const thresholdReached = threshold <= tx.confirmations.size const thresholdReached = threshold <= tx.confirmations.size
const ownersWhoConfirmed = []
const ownersUnconfirmed = []
let currentUserAlreadyConfirmed = false
let executionConfirmation
owners.forEach((owner) => {
const ownerConfirmation = tx.confirmations.find(conf => conf.owner.address === owner.address)
if (ownerConfirmation) {
if (ownerConfirmation.type === TX_TYPE_CONFIRMATION) {
ownersWhoConfirmed.push(owner)
} else {
executionConfirmation = owner
}
if (owner.address === userAddress) {
currentUserAlreadyConfirmed = true
}
} else {
ownersUnconfirmed.push(owner)
}
})
let displayButtonRow = true
if (tx.isExecuted) {
// already executed, can't do any actions
displayButtonRow = false
} else if (tx.status === 'cancelled') {
// tx is cancelled (replaced) by another one
displayButtonRow = false
} else if (cancellationTx && currentUserAlreadyConfirmed && !thresholdReached) {
// the TX is the cancellation (replacement) transaction for previous TX,
// current user has already confirmed it and threshold is not reached (so he can't execute/cancel it)
displayButtonRow = false
}
const handleTabChange = (event, tabClicked) => {
setTabIndex(tabClicked)
}
return ( return (
<> <>
<Block> <Block>
@ -173,31 +124,18 @@ to:
</Paragraph> </Paragraph>
</Block> </Block>
</Col> </Col>
<Col xs={6} className={classes.rightCol} layout="block"> <OwnersColumn
<Row> tx={tx}
<Tabs value={tabIndex} onChange={handleTabChange} indicatorColor="secondary" textColor="secondary"> owners={owners}
<Tab label={confirmedLabel} /> granted={granted}
<Tab label={unconfirmedLabel} /> threshold={threshold}
</Tabs> userAddress={userAddress}
<Hairline color="#c8ced4" /> thresholdReached={thresholdReached}
</Row> safeAddress={safeAddress}
<Row> onTxConfirm={openApproveModal}
{tabIndex === 0 && ( onTxCancel={openCancelModal}
<OwnersList owners={ownersWhoConfirmed} executionConfirmation={executionConfirmation} /> onTxExecute={openApproveModal}
)} />
</Row>
<Row>{tabIndex === 1 && <OwnersList owners={ownersUnconfirmed} />}</Row>
{granted && displayButtonRow && (
<ButtonRow
onTxConfirm={openApproveModal}
onTxCancel={openCancelModal}
showConfirmBtn={!currentUserAlreadyConfirmed}
showCancelBtn={!cancellationTx}
showExecuteBtn={thresholdReached}
onTxExecute={openApproveModal}
/>
)}
</Col>
</Row> </Row>
</Block> </Block>
<CancelTxModal <CancelTxModal
@ -215,7 +153,6 @@ to:
safeAddress={safeAddress} safeAddress={safeAddress}
threshold={threshold} threshold={threshold}
thresholdReached={thresholdReached} thresholdReached={thresholdReached}
currentUserAlreadyConfirmed={currentUserAlreadyConfirmed}
/> />
</> </>
) )