balance table sorting fix wip

This commit is contained in:
Mikhail Mikheev 2019-06-04 18:32:58 +04:00
parent 02fbb74f72
commit 998ec2e687
8 changed files with 85 additions and 59 deletions

View File

@ -15,6 +15,7 @@ export type Column = {
label: string,
custom: boolean, // If content will be rendered by user manually
width?: number,
static?: boolean, // If content can't be sorted by values in the column
}
export const cellWidth = (width: number | typeof undefined) => {
@ -57,7 +58,7 @@ class GnoTableHead extends React.PureComponent<Props> {
<TableSortLabel
active={orderBy === column.id}
direction={order}
onClick={this.changeSort(column.id, column.order)}
onClick={!column.static && this.changeSort(column.id, column.order)}
>
{column.label}
</TableSortLabel>

View File

@ -23,7 +23,7 @@ const desc = (a: Object, b: Object, orderBy: string, orderProp: boolean) => {
}
// eslint-disable-next-line
export const stableSort = <SortRow>(array: Array<SortRow>, cmp: any, fixed: boolean): Array<SortRow> => {
export const stableSort = (array: Array<SortRow>, cmp: any, fixed: boolean): Array<SortRow> => {
const fixedElems: Array<SortRow> = fixed ? array.filter((elem: any) => elem.fixed) : []
const data: Array<SortRow> = fixed ? array.filter((elem: any) => !elem[FIXED]) : array
const stabilizedThis = data.map((el, index) => [el, index])

View File

@ -4,6 +4,7 @@ import { type Token } from '~/logic/tokens/store/model/token'
import { buildOrderFieldFrom, FIXED, type SortRow } from '~/components/Table/sorting'
import { type Column } from '~/components/Table/TableHead'
export const BALANCE_TABLE_IMAGE_ID = 'image'
export const BALANCE_TABLE_ASSET_ID = 'asset'
export const BALANCE_TABLE_BALANCE_ID = 'balance'
export const BALANCE_TABLE_VALUE_ID = 'value'
@ -17,7 +18,8 @@ export type BalanceRow = SortRow<BalanceData>
export const getBalanceData = (activeTokens: List<Token>): List<BalanceRow> => {
const rows = activeTokens.map((token: Token) => ({
[BALANCE_TABLE_ASSET_ID]: { name: token.name, logoUri: token.logoUri },
[BALANCE_TABLE_IMAGE_ID]: token.logoUri,
[BALANCE_TABLE_ASSET_ID]: token.name,
[BALANCE_TABLE_BALANCE_ID]: `${token.balance} ${token.symbol}`,
[buildOrderFieldFrom(BALANCE_TABLE_BALANCE_ID)]: Number(token.balance),
[FIXED]: token.get('symbol') === 'ETH',
@ -27,7 +29,17 @@ export const getBalanceData = (activeTokens: List<Token>): List<BalanceRow> => {
}
export const generateColumns = () => {
const assetRow: Column = {
const imageColumn: Column = {
id: BALANCE_TABLE_IMAGE_ID,
order: false,
static: true,
label: '',
custom: false,
disablePadding: true,
width: 30,
}
const assetColumn: Column = {
id: BALANCE_TABLE_ASSET_ID,
order: false,
disablePadding: false,
@ -36,7 +48,7 @@ export const generateColumns = () => {
width: 250,
}
const balanceRow: Column = {
const balanceColumn: Column = {
id: BALANCE_TABLE_BALANCE_ID,
align: 'right',
order: true,
@ -53,7 +65,7 @@ export const generateColumns = () => {
custom: true,
}
return List([assetRow, balanceRow, actions])
return List([imageColumn, assetColumn, balanceColumn, actions])
}
export const filterByZero = (data: List<BalanceRow>, hideZero: boolean): List<BalanceRow> => data.filter((row: BalanceRow) => (hideZero ? row[buildOrderFieldFrom(BALANCE_TABLE_BALANCE_ID)] !== 0 : true))

View File

@ -12,14 +12,16 @@ import TableCell from '@material-ui/core/TableCell'
import { withStyles } from '@material-ui/core/styles'
import Col from '~/components/layout/Col'
import Row from '~/components/layout/Row'
import Img from '~/components/layout/Img'
import ButtonLink from '~/components/layout/ButtonLink'
import Paragraph from '~/components/layout/Paragraph'
import Modal from '~/components/Modal'
import { type Column, cellWidth } from '~/components/Table/TableHead'
import Table from '~/components/Table'
import {
getBalanceData, generateColumns, BALANCE_TABLE_ASSET_ID, type BalanceRow, filterByZero,
getBalanceData, generateColumns, BALANCE_TABLE_IMAGE_ID, BALANCE_TABLE_BALANCE_ID, type BalanceRow, filterByZero,
} from './dataFetcher'
import AssetTableCell from './AssetTableCell'
import { setImageToPlaceholder } from '~/routes/safe/components/Balances/utils'
import Tokens from './Tokens'
import SendModal from './SendModal'
import Receive from './Receive'
@ -127,9 +129,7 @@ class Balances extends React.Component<Props, State> {
<Paragraph className={classes.zero}>Hide zero balances</Paragraph>
</Col>
<Col xs={6} end="sm">
<Paragraph noMargin size="md" color="secondary" className={classes.links} onClick={this.onShow('Token')}>
Manage Tokens
</Paragraph>
<ButtonLink onClick={this.onShow('Token')}>Manage Tokens</ButtonLink>
<Modal
title="Manage Tokens"
description="Enable and disable tokens to be listed"
@ -147,7 +147,7 @@ class Balances extends React.Component<Props, State> {
</Row>
<Table
label="Balances"
defaultOrderBy={BALANCE_TABLE_ASSET_ID}
defaultOrderBy={BALANCE_TABLE_BALANCE_ID}
columns={columns}
data={filteredData}
size={filteredData.size}
@ -157,7 +157,7 @@ class Balances extends React.Component<Props, State> {
<TableRow tabIndex={-1} key={index} className={classes.hide} data-testid="balance-row">
{autoColumns.map((column: Column) => (
<TableCell key={column.id} style={cellWidth(column.width)} align={column.align} component="td">
{column.id === BALANCE_TABLE_ASSET_ID ? <AssetTableCell asset={row[column.id]} /> : row[column.id]}
{column.id === BALANCE_TABLE_IMAGE_ID ? <Img src={row[column.id]} height={26} alt="Logo" onError={setImageToPlaceholder} /> : row[column.id]}
</TableCell>
))}
<TableCell component="td">

View File

@ -25,6 +25,9 @@ export const styles = (theme: Object) => ({
'&:hover $actions': {
visibility: 'initial',
},
'&:focus $actions': {
visibility: 'initial',
},
},
actions: {
justifyContent: 'flex-end',

View File

@ -1,5 +1,4 @@
// @flow
import * as TestUtils from 'react-dom/test-utils'
import { getWeb3 } from '~/logic/wallets/getWeb3'
import { type Match } from 'react-router-dom'
import { getFirstTokenContract, getSecondTokenContract } from '~/test/utils/tokenMovements'
@ -7,60 +6,60 @@ import { aNewStore } from '~/store'
import { aMinedSafe } from '~/test/builder/safe.redux.builder'
import { travelToTokens } from '~/test/builder/safe.dom.utils'
import { sleep } from '~/utils/timer'
import { buildMathPropsFrom } from '~/test/utils/buildReactRouterProps'
import { buildMatchPropsFrom } from '~/test/utils/buildReactRouterProps'
import { tokenListSelector } from '~/logic/tokens/store/selectors'
import { testToken } from '~/test/builder/tokens.dom.utils'
import * as fetchTokensModule from '~/logic/tokens/store/actions/fetchTokens'
import * as enhancedFetchModule from '~/utils/fetch'
describe('DOM > Feature > Add new ERC 20 Tokens', () => {
// let web3
// let accounts
// let firstErc20Token
// let secondErc20Token
let web3
let accounts
let firstErc20Token
let secondErc20Token
// beforeAll(async () => {
// web3 = getWeb3()
// accounts = await web3.eth.getAccounts()
// firstErc20Token = await getFirstTokenContract(web3, accounts[0])
// secondErc20Token = await getSecondTokenContract(web3, accounts[0])
beforeAll(async () => {
web3 = getWeb3()
accounts = await web3.eth.getAccounts()
firstErc20Token = await getFirstTokenContract(web3, accounts[0])
secondErc20Token = await getSecondTokenContract(web3, accounts[0])
// // $FlowFixMe
// enhancedFetchModule.enhancedFetch = jest.fn()
// enhancedFetchModule.enhancedFetch.mockImplementation(() => Promise.resolve({
// results: [
// {
// address: firstErc20Token.address,
// name: 'First Token Example',
// symbol: 'FTE',
// decimals: 18,
// logoUri: 'https://upload.wikimedia.org/wikipedia/commons/c/c0/Earth_simple_icon.png',
// },
// ],
// }))
// })
// $FlowFixMe
enhancedFetchModule.enhancedFetch = jest.fn()
enhancedFetchModule.enhancedFetch.mockImplementation(() => Promise.resolve({
results: [
{
address: firstErc20Token.address,
name: 'First Token Example',
symbol: 'FTE',
decimals: 18,
logoUri: 'https://upload.wikimedia.org/wikipedia/commons/c/c0/Earth_simple_icon.png',
},
],
}))
})
it('adds a second erc 20 token filling the form', async () => {
// // GIVEN
// const store = aNewStore()
// const safeAddress = await aMinedSafe(store)
// await store.dispatch(fetchTokensModule.fetchTokens(safeAddress))
// const TokensDom = await travelToTokens(store, safeAddress)
// await sleep(400)
// const tokens = TestUtils.scryRenderedComponentsWithType(TokensDom, TokenComponent)
// expect(tokens.length).toBe(2)
// testToken(tokens[0].props.token, 'FTE', false)
// testToken(tokens[1].props.token, 'ETH', true)
// // WHEN
// await clickOnAddToken(TokensDom)
// await fillAddress(TokensDom, secondErc20Token)
// await fillHumanReadableInfo(TokensDom)
// // THEN
// const match: Match = buildMathPropsFrom(safeAddress)
// const tokenList = tokenListSelector(store.getState(), { match })
// expect(tokenList.count()).toBe(3)
// testToken(tokenList.get(0), 'FTE', false)
// testToken(tokenList.get(1), 'ETH', true)
// testToken(tokenList.get(2), 'TKN', true)
// GIVEN
const store = aNewStore()
const safeAddress = await aMinedSafe(store)
await store.dispatch(fetchTokensModule.fetchTokens(safeAddress))
const TokensDom = await travelToTokens(store, safeAddress)
await sleep(400)
const tokens = TestUtils.scryRenderedComponentsWithType(TokensDom, TokenComponent)
expect(tokens.length).toBe(2)
testToken(tokens[0].props.token, 'FTE', false)
testToken(tokens[1].props.token, 'ETH', true)
// WHEN
await clickOnAddToken(TokensDom)
await fillAddress(TokensDom, secondErc20Token)
await fillHumanReadableInfo(TokensDom)
// THEN
const match: Match = buildMathPropsFrom(safeAddress)
const tokenList = tokenListSelector(store.getState(), { match })
expect(tokenList.count()).toBe(3)
testToken(tokenList.get(0), 'FTE', false)
testToken(tokenList.get(1), 'ETH', true)
testToken(tokenList.get(2), 'TKN', true)
})
})

View File

@ -0,0 +1,3 @@
// @flow
export * from './tokens'

View File

@ -0,0 +1,8 @@
// @flow
import { fireEvent } from '@testing-library/reactß'
const clickOnManageTokens = (dom) => {
const btn = dom.findByTestId()
}