Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'development' into 2466-reolve-ux-issues-voting
- Loading branch information
Showing
21 changed files
with
523 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import React from 'react'; | ||
import MonitorHeader from '../header'; | ||
import AccountsTable from './accountsTable'; | ||
|
||
const MonitorAccounts = ({ t, accounts, networkStatus }) => ( | ||
<div> | ||
<MonitorHeader /> | ||
<AccountsTable | ||
isLoadMoreEnabled | ||
title={t('Accounts')} | ||
accounts={accounts} | ||
networkStatus={networkStatus} | ||
t={t} | ||
/> | ||
</div> | ||
); | ||
|
||
export default MonitorAccounts; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import React from 'react'; | ||
import { mount } from 'enzyme'; | ||
import Delegates from './accounts'; | ||
import accounts from '../../../../../test/constants/accounts'; | ||
|
||
jest.mock('../../../../constants/monitor', () => ({ DEFAULT_LIMIT: 4 })); | ||
|
||
const accountsApiResponse = Object.values(accounts); | ||
|
||
describe('Top Accounts Monitor Page', () => { | ||
let props; | ||
let accountsWithData; | ||
let wrapper; | ||
|
||
const setup = properties => mount(<Delegates {...properties} />); | ||
|
||
beforeEach(() => { | ||
props = { | ||
t: key => key, | ||
accounts: { | ||
isLoading: true, | ||
data: [], | ||
loadData: jest.fn(), | ||
clearData: jest.fn(), | ||
urlSearchParams: {}, | ||
}, | ||
networkStatus: { | ||
data: { | ||
supply: 9999999999999, | ||
}, | ||
}, | ||
}; | ||
|
||
accountsWithData = { | ||
...props.accounts, | ||
isLoading: false, | ||
data: [ | ||
{ | ||
address: '1234567L', | ||
delegate: { | ||
username: 'geenesis', | ||
}, | ||
knowledge: { | ||
owner: 'Lisk', | ||
description: 'assetes', | ||
}, | ||
}, | ||
...accountsApiResponse, | ||
], | ||
}; | ||
|
||
wrapper = setup(props); | ||
}); | ||
|
||
it('renders a page with header', () => { | ||
expect(wrapper.find('Box header')).toIncludeText('Accounts'); | ||
}); | ||
|
||
it('renders table with accounts', () => { | ||
expect(wrapper.find('.accounts-row')).toHaveLength(0); | ||
wrapper.setProps({ accounts: accountsWithData }); | ||
expect(wrapper.find('.accounts-row').hostNodes()).toHaveLength(accountsApiResponse.length + 1); | ||
}); | ||
|
||
it('shows error if API failed', () => { | ||
const error = 'Loading failed'; | ||
wrapper.setProps({ | ||
accounts: { | ||
...props.accounts, | ||
isLoading: false, | ||
error, | ||
}, | ||
}); | ||
expect(wrapper).toIncludeText(error); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
@import '../../../../app/variables.css'; | ||
|
||
.content { | ||
padding: 0 !important; | ||
counter-reset: section; | ||
} | ||
|
||
.counter::before { | ||
counter-increment: section; | ||
content: "#" counter(section); | ||
} |
134 changes: 134 additions & 0 deletions
134
src/components/screens/monitor/accounts/accountsTable.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
import React from 'react'; | ||
import { BigNumber } from 'bignumber.js'; | ||
import grid from 'flexboxgrid/dist/flexboxgrid.css'; | ||
import { tokenMap } from '../../../../constants/tokens'; | ||
import Box from '../../../toolbox/box'; | ||
import BoxHeader from '../../../toolbox/box/header'; | ||
import BoxContent from '../../../toolbox/box/content'; | ||
import BoxFooterButton from '../../../toolbox/box/footerButton'; | ||
import BoxEmptyState from '../../../toolbox/box/emptyState'; | ||
import LiskAmount from '../../../shared/liskAmount'; | ||
import Illustration from '../../../toolbox/illustration'; | ||
import withResizeValues from '../../../../utils/withResizeValues'; | ||
import routes from '../../../../constants/routes'; | ||
import Table from '../../../toolbox/table'; | ||
import AccountVisualWithAddress from '../../../shared/accountVisualWithAddress'; | ||
import { DEFAULT_LIMIT } from '../../../../constants/monitor'; | ||
import { formatAmountBasedOnLocale } from '../../../../utils/formattedNumber'; | ||
import styles from './accountsTable.css'; | ||
|
||
class AccountsTable extends React.Component { | ||
handleLoadMore = () => { | ||
const { accounts } = this.props; | ||
accounts.loadData({ offset: accounts.data.length }); | ||
} | ||
|
||
render() { | ||
const { | ||
accounts, | ||
isMediumViewPort, | ||
networkStatus, | ||
t, | ||
title, | ||
} = this.props; | ||
const supply = networkStatus.data.supply; | ||
|
||
return ( | ||
<Box main isLoading={accounts.isLoading} className="accounts-box"> | ||
<BoxHeader> | ||
<h1>{title}</h1> | ||
</BoxHeader> | ||
{ | ||
accounts.error | ||
? ( | ||
<BoxContent> | ||
<BoxEmptyState> | ||
<Illustration name="emptyWallet" /> | ||
<h3>{`${accounts.error}`}</h3> | ||
</BoxEmptyState> | ||
</BoxContent> | ||
) | ||
: ( | ||
<React.Fragment> | ||
<BoxContent className={styles.content}> | ||
<Table | ||
getRowLink={account => `${routes.accounts.path}/${account.address}`} | ||
data={accounts.data} | ||
columns={[ | ||
{ | ||
header: t('Rank'), | ||
className: `${grid['col-xs-1']} ${grid['col-md-1']}`, | ||
id: 'rank', | ||
getValue: () => (<span className={styles.counter} />), | ||
}, | ||
{ | ||
header: t('Address'), | ||
className: `${grid['col-xs-3']} ${grid['col-md-5']}`, | ||
id: 'address', | ||
getValue: account => ( | ||
<AccountVisualWithAddress | ||
address={account.address} | ||
isMediumViewPort={isMediumViewPort} | ||
transactionSubject="address" | ||
showBookmarkedAddress | ||
/> | ||
), | ||
}, | ||
{ | ||
header: t('Balance'), | ||
className: `${grid['col-xs-3']} ${grid['col-md-3']}`, | ||
id: 'balance', | ||
getValue: account => ( | ||
<LiskAmount val={account.balance} roundTo={0} token={tokenMap.LSK.key} /> | ||
), | ||
}, | ||
{ | ||
header: t('Supply'), | ||
className: `${grid['col-xs-2']} ${grid['col-md-1']}`, | ||
id: 'supply', | ||
getValue: (account) => { | ||
const amount = new BigNumber(account.balance / supply * 100); | ||
return <span>{`${formatAmountBasedOnLocale({ value: amount.toFormat(2) })} %`}</span>; | ||
}, | ||
}, | ||
{ | ||
header: t('Owner'), | ||
className: `${grid['col-xs-3']} ${grid['col-md-2']}`, | ||
id: 'owner', | ||
getValue: (account) => { | ||
const delegateUsername = account.delegate ? account.delegate.username : ''; | ||
const text = account.knowledge | ||
&& account.knowledge.owner && account.knowledge.description | ||
? `${account.knowledge.owner} ${account.knowledge.description}` | ||
: delegateUsername; | ||
return text; | ||
}, | ||
}, | ||
]} | ||
rowClassName="accounts-row" | ||
rowKey="address" | ||
/> | ||
</BoxContent> | ||
{ | ||
!!accounts.data.length | ||
&& accounts.data.length % DEFAULT_LIMIT === 0 | ||
? ( | ||
<BoxFooterButton className="load-more" onClick={this.handleLoadMore}> | ||
{t('Load more')} | ||
</BoxFooterButton> | ||
) | ||
: null | ||
} | ||
</React.Fragment> | ||
) | ||
} | ||
</Box> | ||
); | ||
} | ||
} | ||
|
||
AccountsTable.defaultProps = { | ||
title: '', | ||
}; | ||
|
||
export default withResizeValues(AccountsTable); |
Oops, something went wrong.