Browse Source

Merge pull request #172 from meriadec/master

Display confirmation check on TransactionsList, and ability to adjust min confirmations
master
Loëck Vézien 7 years ago
committed by GitHub
parent
commit
9b77426b83
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      src/components/AccountPage.js
  2. 3
      src/components/SelectAccount/stories.js
  3. 41
      src/components/TransactionsList/ConfirmationCheck.js
  4. 31
      src/components/TransactionsList/index.js
  5. 33
      src/components/modals/SettingsAccount.js
  6. 1
      src/helpers/btc.js
  7. 10
      src/icons/Check.js
  8. 10
      src/icons/Clock.js
  9. 11
      src/reducers/accounts.js
  10. 6
      src/types/common.js

2
src/components/AccountPage.js

@ -25,7 +25,7 @@ import TransactionsList from 'components/TransactionsList'
type Props = {
t: T,
account: Account,
account?: Account,
openModal: Function,
}

3
src/components/SelectAccount/stories.js

@ -22,6 +22,9 @@ const accounts = [...Array(20)].map(() => ({
path: '',
transactions: [],
unit: getDefaultUnitByCoinType(0),
settings: {
minConfirmations: 2,
},
}))
type State = {

41
src/components/TransactionsList/ConfirmationCheck.js

@ -0,0 +1,41 @@
// @flow
import React from 'react'
import styled from 'styled-components'
import { rgba } from 'styles/helpers'
import Box from 'components/base/Box'
import Tooltip from 'components/base/Tooltip'
import IconCheck from 'icons/Check'
import IconClock from 'icons/Clock'
const Container = styled(Box).attrs({
bg: p => rgba(p.isConfirmed ? p.theme.colors.positiveGreen : p.theme.colors.grey, 0.1),
color: p => (p.isConfirmed ? p.theme.colors.positiveGreen : p.theme.colors.grey),
align: 'center',
justify: 'center',
})`
width: 24px;
height: 24px;
border-radius: 50%;
`
const ConfirmationCheck = ({
confirmations,
minConfirmations,
}: {
confirmations: number,
minConfirmations: number,
}) => {
const isConfirmed = confirmations >= minConfirmations
return (
<Tooltip render={() => (isConfirmed ? 'Confirmed' : 'Not confirmed')}>
<Container isConfirmed={isConfirmed}>
{isConfirmed ? <IconCheck width={12} /> : <IconClock width={12} />}
</Container>
</Tooltip>
)
}
export default ConfirmationCheck

31
src/components/TransactionsList/index.js

@ -15,10 +15,12 @@ import Box from 'components/base/Box'
import Defer from 'components/base/Defer'
import FormattedVal from 'components/base/FormattedVal'
import Text from 'components/base/Text'
import ConfirmationCheck from './ConfirmationCheck'
const DATE_COL_SIZE = 80
const ACCOUNT_COL_SIZE = 150
const AMOUNT_COL_SIZE = 150
const CONFIRMATION_COL_SIZE = 30
const Cap = styled(Text).attrs({
fontSize: 2,
@ -41,7 +43,7 @@ const Hour = styled(Day).attrs({
color: 'graphite',
})``
const HeaderCol = ({ size, children, ...props }: { size?: number, children: any }) => (
const HeaderCol = ({ size, children, ...props }: { size?: number, children?: any }) => (
<Cell size={size} {...props}>
<Cap>{children}</Cap>
</Cell>
@ -49,6 +51,7 @@ const HeaderCol = ({ size, children, ...props }: { size?: number, children: any
HeaderCol.defaultProps = {
size: undefined,
children: undefined,
}
const TransactionRaw = styled(Box).attrs({
@ -76,11 +79,13 @@ const Transaction = ({
onAccountClick,
tx,
withAccounts,
minConfirmations,
}: {
t: T,
onAccountClick?: Function,
tx: TransactionType,
withAccounts?: boolean,
minConfirmations: number,
}) => {
const time = moment(tx.receivedAt)
const Icon = getIconByCoinType(get(tx, 'account.currency.coinType'))
@ -117,16 +122,23 @@ const Transaction = ({
grow
shrink
style={{
overflow: 'hidden',
whiteSpace: 'nowrap',
textOverflow: 'ellipsis',
display: 'block',
}}
>
<Box ff="Open Sans" fontSize={3} color="graphite">
{tx.balance > 0 ? t('transactionsList.from') : t('transactionsList.to')}
</Box>
<Box color="dark" ff="Open Sans" fontSize={3}>
<Box
color="dark"
ff="Open Sans"
fontSize={3}
style={{
overflow: 'hidden',
whiteSpace: 'nowrap',
textOverflow: 'ellipsis',
display: 'block',
}}
>
{tx.address}
</Box>
</Cell>
@ -139,6 +151,9 @@ const Transaction = ({
alwaysShowSign
/>
</Cell>
<Cell size={CONFIRMATION_COL_SIZE} px={0} align="center" justify="center">
<ConfirmationCheck minConfirmations={minConfirmations} confirmations={tx.confirmations} />
</Cell>
</TransactionRaw>
)
}
@ -153,12 +168,14 @@ type Props = {
onAccountClick?: Function,
transactions: Array<TransactionType>,
withAccounts?: boolean,
minConfirmations: number,
}
class TransactionsList extends Component<Props> {
static defaultProps = {
onAccountClick: noop,
withAccounts: false,
minConfirmations: 2,
}
shouldComponentUpdate(nextProps: Props) {
@ -174,7 +191,7 @@ class TransactionsList extends Component<Props> {
_hashCache = null
render() {
const { transactions, withAccounts, onAccountClick, t } = this.props
const { transactions, withAccounts, onAccountClick, minConfirmations, t } = this.props
this._hashCache = this.getHashCache(transactions)
@ -189,6 +206,7 @@ class TransactionsList extends Component<Props> {
<HeaderCol size={AMOUNT_COL_SIZE} justifyContent="flex-end">
{t('transactionsList.amount')}
</HeaderCol>
<HeaderCol size={CONFIRMATION_COL_SIZE} px={0} />
</Box>
<Defer>
<Box>
@ -198,6 +216,7 @@ class TransactionsList extends Component<Props> {
key={`{${trans.hash}-${trans.account ? trans.account.id : ''}`}
withAccounts={withAccounts}
onAccountClick={onAccountClick}
minConfirmations={minConfirmations}
tx={trans}
/>
))}

33
src/components/modals/SettingsAccount.js

@ -18,9 +18,11 @@ import Input from 'components/base/Input'
import Modal, { ModalBody } from 'components/base/Modal'
import Text from 'components/base/Text'
import Icon from 'components/base/Icon'
import Label from 'components/base/Label'
type State = {
accountName: string | null,
minConfirmations: number | null,
editName: boolean,
nameHovered: boolean,
}
@ -44,6 +46,7 @@ const mapDispatchToProps = {
const defaultState = {
editName: false,
accountName: null,
minConfirmations: null,
nameHovered: false,
}
@ -57,7 +60,7 @@ class SettingsAccount extends PureComponent<Props, State> {
}
getAccount(data: Object) {
const { accountName } = this.state
const { accountName, minConfirmations } = this.state
const account = get(data, 'account', {})
@ -68,6 +71,10 @@ class SettingsAccount extends PureComponent<Props, State> {
name: accountName,
}
: {}),
settings: {
...account.settings,
minConfirmations: minConfirmations || account.settings.minConfirmations,
},
}
}
@ -76,6 +83,20 @@ class SettingsAccount extends PureComponent<Props, State> {
nameHovered: state,
})
handleChangeMinConfirmations = account => minConfirmations => {
const { updateAccount } = this.props
this.setState({ minConfirmations })
window.requestAnimationFrame(() => {
updateAccount({
...account,
settings: {
...account.settings,
minConfirmations,
},
})
})
}
handleEditName = (state: boolean) => () =>
this.setState({
nameHovered: false,
@ -179,6 +200,16 @@ class SettingsAccount extends PureComponent<Props, State> {
</Box>
)}
</Box>
<Box>
<Label>{'Minimum confirmations'}</Label>
<Input
type="number"
min={1}
max={100}
value={account.settings.minConfirmations}
onChange={this.handleChangeMinConfirmations(account)}
/>
</Box>
<Box horizontal grow alignItems="flex-end" flow={2}>
<Box grow>
<Button onClick={this.handleArchiveAccount(account)}>

1
src/helpers/btc.js

@ -145,6 +145,7 @@ export async function getAccount({
index: currentAddress.index,
path: `${path}/${getPath('external', currentAddress.index + 1)}`,
transactions: transactions.map(t => ({
confirmations: t.confirmations,
address: t.balance > 0 ? t.inputs[0].address : t.outputs[0].address,
balance: t.balance,
hash: t.hash,

10
src/icons/Check.js

@ -0,0 +1,10 @@
import React from 'react'
export default props => (
<svg viewBox="0 0 16 16" {...props}>
<path
fill="currentColor"
d="M13.62 2.608l-8.22 8.22-3.02-3.02a.375.375 0 0 0-.53 0l-.884.884a.375.375 0 0 0 0 .53l4.169 4.17a.375.375 0 0 0 .53 0l9.37-9.37a.375.375 0 0 0 0-.53l-.884-.884a.375.375 0 0 0-.53 0z"
/>
</svg>
)

10
src/icons/Clock.js

@ -0,0 +1,10 @@
import React from 'react'
export default props => (
<svg viewBox="0 0 16 16" {...props}>
<path
fill="currentColor"
d="M8 .583a7.417 7.417 0 1 1 0 14.834A7.417 7.417 0 0 1 8 .583zm0 1.5a5.917 5.917 0 1 0 0 11.834A5.917 5.917 0 0 0 8 2.083zm.75 5.606l1.78 1.78a.75.75 0 0 1-1.06 1.061l-2-2A.75.75 0 0 1 7.25 8V4a.75.75 0 0 1 1.5 0v3.69z"
/>
</svg>
)

11
src/reducers/accounts.js

@ -5,6 +5,7 @@ import { handleActions } from 'redux-actions'
import every from 'lodash/every'
import get from 'lodash/get'
import reduce from 'lodash/reduce'
import defaultsDeep from 'lodash/defaultsDeep'
import { getDefaultUnitByCoinType, getCurrencyByCoinType } from '@ledgerhq/currencies'
@ -24,11 +25,19 @@ function orderAccountsTransactions(account: Account) {
}
}
function applyDefaults(account) {
return defaultsDeep(account, {
settings: {
minConfirmations: 2,
},
})
}
const handlers: Object = {
SET_ACCOUNTS: (
state: AccountsState,
{ payload: accounts }: { payload: Accounts },
): AccountsState => accounts,
): AccountsState => accounts.map(applyDefaults),
ADD_ACCOUNT: (
state: AccountsState,

6
src/types/common.js

@ -18,10 +18,15 @@ export type Transaction = {
balance: number,
hash: string,
receivedAt: string,
confirmations: number,
}
// -------------------- Accounts
export type AccountSettings = {
minConfirmations: number,
}
export type Account = {
address: string,
addresses: Array<string>,
@ -35,6 +40,7 @@ export type Account = {
path: string,
transactions: Array<Transaction>,
unit: Unit,
settings: AccountSettings,
}
export type Accounts = Array<Account>

Loading…
Cancel
Save