Rework table layouts (#2472)
* Rework table layouts * Additional * Additional * Accounts & Contacts * Cleanup alignment * Mini links * Ordering adjustments * Empty indicators
This commit is contained in:
parent
dc5f79a37e
commit
5126dbff93
@ -2,13 +2,13 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { DeriveAccountInfo } from '@polkadot/api-derive/types';
|
||||
import { DeriveAccountInfo, DeriveBalancesAll } from '@polkadot/api-derive/types';
|
||||
import { ActionStatus } from '@polkadot/react-components/Status/types';
|
||||
import { RecoveryConfig } from '@polkadot/types/interfaces';
|
||||
|
||||
import React, { useCallback, useState, useEffect } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { AddressInfo, AddressSmall, Badge, Button, ChainLock, Forget, Icon, IdentityIcon, Input, InputTags, LinkExternal, Menu, Popup, Tag } from '@polkadot/react-components';
|
||||
import { AddressInfo, AddressSmall, Badge, Button, ChainLock, CryptoType, Forget, Icon, IdentityIcon, Input, InputTags, LinkExternal, Menu, Popup, Tag } from '@polkadot/react-components';
|
||||
import { useApi, useCall, useToggle } from '@polkadot/react-hooks';
|
||||
import { Option } from '@polkadot/types';
|
||||
import keyring from '@polkadot/ui-keyring';
|
||||
@ -35,6 +35,7 @@ function Account ({ address, className, filter, isFavorite, toggleFavorite }: Pr
|
||||
const { t } = useTranslation();
|
||||
const api = useApi();
|
||||
const info = useCall<DeriveAccountInfo>(api.api.derive.accounts.info as any, [address]);
|
||||
const balancesAll = useCall<DeriveBalancesAll>(api.api.derive.balances.all as any, [address]);
|
||||
const recoveryInfo = useCall<RecoveryConfig | null>(api.api.query.recovery?.recoverable, [address], {
|
||||
transform: (opt: Option<RecoveryConfig>): RecoveryConfig | null =>
|
||||
opt.unwrapOr(null)
|
||||
@ -305,7 +306,7 @@ function Account ({ address, className, filter, isFavorite, toggleFavorite }: Pr
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
<td className='all'>
|
||||
{isEditingTags
|
||||
? (
|
||||
<InputTags
|
||||
@ -331,7 +332,10 @@ function Account ({ address, className, filter, isFavorite, toggleFavorite }: Pr
|
||||
)
|
||||
}
|
||||
</td>
|
||||
<td className='top'>
|
||||
<td className='number'>
|
||||
{balancesAll && formatNumber(balancesAll.accountNonce)}
|
||||
</td>
|
||||
<td className='number'>
|
||||
<AddressInfo
|
||||
address={address}
|
||||
withBalance
|
||||
@ -339,14 +343,10 @@ function Account ({ address, className, filter, isFavorite, toggleFavorite }: Pr
|
||||
withExtended={false}
|
||||
/>
|
||||
</td>
|
||||
<td className='top'>
|
||||
<AddressInfo
|
||||
address={address}
|
||||
withBalance={false}
|
||||
withExtended
|
||||
/>
|
||||
<td className='number'>
|
||||
<CryptoType accountId={address} />
|
||||
</td>
|
||||
<td className='number top'>
|
||||
<td className='button'>
|
||||
<Button
|
||||
icon='paper plane'
|
||||
label={t('send')}
|
||||
@ -429,7 +429,7 @@ function Account ({ address, className, filter, isFavorite, toggleFavorite }: Pr
|
||||
</Menu>
|
||||
</Popup>
|
||||
</td>
|
||||
<td className='mini top'>
|
||||
<td className='mini'>
|
||||
<LinkExternal
|
||||
className='ui--AddressCard-exporer-link'
|
||||
data={address}
|
||||
|
||||
@ -129,6 +129,13 @@ function Overview ({ className, onStatusChange }: Props): React.ReactElement<Pro
|
||||
/>
|
||||
</div>
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th colSpan={4}> </th>
|
||||
<th>{t('transactions')}</th>
|
||||
<th>{t('balances')}</th>
|
||||
<th>{t('type')}</th>
|
||||
<th colSpan={2}> </th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
{sortedAccounts.map(({ address, isFavorite }): React.ReactNode => (
|
||||
<Account
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { DeriveAccountInfo } from '@polkadot/api-derive/types';
|
||||
import { DeriveAccountInfo, DeriveBalancesAll } from '@polkadot/api-derive/types';
|
||||
import { KeyringAddress } from '@polkadot/ui-keyring/types';
|
||||
import { ActionStatus } from '@polkadot/react-components/Status/types';
|
||||
|
||||
@ -11,6 +11,7 @@ import styled from 'styled-components';
|
||||
import { AddressSmall, AddressInfo, Button, ChainLock, Icon, InputTags, Input, LinkExternal, Forget, Menu, Popup, Tag } from '@polkadot/react-components';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import keyring from '@polkadot/ui-keyring';
|
||||
import { formatNumber } from '@polkadot/util';
|
||||
|
||||
import Transfer from '../Accounts/modals/Transfer';
|
||||
import { useTranslation } from '../translate';
|
||||
@ -24,7 +25,6 @@ interface Props {
|
||||
}
|
||||
|
||||
const WITH_BALANCE = { available: true, bonded: true, free: true, locked: true, reserved: true, total: true };
|
||||
const WITH_EXTENDED = { nonce: true };
|
||||
|
||||
const isEditable = true;
|
||||
|
||||
@ -32,6 +32,7 @@ function Address ({ address, className, filter, isFavorite, toggleFavorite }: Pr
|
||||
const { t } = useTranslation();
|
||||
const api = useApi();
|
||||
const info = useCall<DeriveAccountInfo>(api.api.derive.accounts.info as any, [address]);
|
||||
const balancesAll = useCall<DeriveBalancesAll>(api.api.derive.balances.all as any, [address]);
|
||||
const [tags, setTags] = useState<string[]>([]);
|
||||
const [accName, setAccName] = useState('');
|
||||
const [current, setCurrent] = useState<KeyringAddress | null>(null);
|
||||
@ -204,7 +205,7 @@ function Address ({ address, className, filter, isFavorite, toggleFavorite }: Pr
|
||||
</>
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
<td className='all'>
|
||||
{isEditingTags
|
||||
? (
|
||||
<InputTags
|
||||
@ -230,7 +231,10 @@ function Address ({ address, className, filter, isFavorite, toggleFavorite }: Pr
|
||||
)
|
||||
}
|
||||
</td>
|
||||
<td className='top'>
|
||||
<td className='number'>
|
||||
{balancesAll && formatNumber(balancesAll.accountNonce)}
|
||||
</td>
|
||||
<td className='number'>
|
||||
<AddressInfo
|
||||
address={address}
|
||||
withBalance={WITH_BALANCE}
|
||||
@ -238,14 +242,7 @@ function Address ({ address, className, filter, isFavorite, toggleFavorite }: Pr
|
||||
withExtended={false}
|
||||
/>
|
||||
</td>
|
||||
<td className='top'>
|
||||
<AddressInfo
|
||||
address={address}
|
||||
withBalance={false}
|
||||
withExtended={WITH_EXTENDED}
|
||||
/>
|
||||
</td>
|
||||
<td className='number top'>
|
||||
<td className='button'>
|
||||
<Button
|
||||
icon='paper plane'
|
||||
key='deposit'
|
||||
@ -293,7 +290,7 @@ function Address ({ address, className, filter, isFavorite, toggleFavorite }: Pr
|
||||
</Menu>
|
||||
</Popup>
|
||||
</td>
|
||||
<td className='mini top'>
|
||||
<td className='mini'>
|
||||
<LinkExternal
|
||||
className='ui--AddressCard-exporer-link'
|
||||
data={address}
|
||||
|
||||
@ -67,6 +67,12 @@ function Overview ({ className, onStatusChange }: Props): React.ReactElement<Pro
|
||||
/>
|
||||
</div>
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th colSpan={3}> </th>
|
||||
<th>{t('transactions')}</th>
|
||||
<th>{t('balances')}</th>
|
||||
<th colSpan={2}> </th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
{sortedAddresses.map(({ address, isFavorite }): React.ReactNode => (
|
||||
<Address
|
||||
|
||||
@ -13,7 +13,6 @@ import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import { BlockToTime } from '@polkadot/react-query';
|
||||
import { formatNumber } from '@polkadot/util';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
import Voting from './Voting';
|
||||
|
||||
interface Props {
|
||||
@ -25,7 +24,6 @@ interface Props {
|
||||
}
|
||||
|
||||
function Motion ({ className, isMember, members, motion: { hash, proposal, votes }, prime }: Props): React.ReactElement<Props> | null {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const bestNumber = useCall<BlockNumber>(api.derive.chain.bestNumber, []) || new BN(0);
|
||||
|
||||
@ -37,46 +35,41 @@ function Motion ({ className, isMember, members, motion: { hash, proposal, votes
|
||||
|
||||
return (
|
||||
<tr className={className}>
|
||||
<td className='number top'><h1>{formatNumber(index)}</h1></td>
|
||||
<td className='number'><h1>{formatNumber(index)}</h1></td>
|
||||
<ProposalCell
|
||||
className='top'
|
||||
imageHash={hash}
|
||||
proposal={proposal}
|
||||
/>
|
||||
<td className='number top'>
|
||||
<label>{t('threshold')}</label>
|
||||
<td className='number'>
|
||||
{formatNumber(ayes.length)}/{formatNumber(threshold)}
|
||||
</td>
|
||||
<td className='number together top'>
|
||||
<td className='number together'>
|
||||
{end && (
|
||||
<>
|
||||
<label>{t('voting end')}</label>
|
||||
<BlockToTime blocks={end.sub(bestNumber)} />
|
||||
#{formatNumber(end)}
|
||||
</>
|
||||
)}
|
||||
</td>
|
||||
<td className='top'>
|
||||
<td className='number'>
|
||||
{ayes.map((address, index): React.ReactNode => (
|
||||
<AddressMini
|
||||
key={`${index}:${address}`}
|
||||
label={index === 0 ? t('Aye') : undefined}
|
||||
value={address}
|
||||
withBalance={false}
|
||||
/>
|
||||
))}
|
||||
</td>
|
||||
<td className='top'>
|
||||
<td className='number'>
|
||||
{nays.map((address, index): React.ReactNode => (
|
||||
<AddressMini
|
||||
key={`${index}:${address}`}
|
||||
label={index === 0 ? t('Nay') : undefined}
|
||||
value={address}
|
||||
withBalance={false}
|
||||
/>
|
||||
))}
|
||||
</td>
|
||||
<td className='number top together'>
|
||||
<td className='button'>
|
||||
<Voting
|
||||
hash={hash}
|
||||
idNumber={index}
|
||||
|
||||
@ -47,6 +47,14 @@ function Proposals ({ className, motions, prime }: Props): React.ReactElement<Pr
|
||||
{motions?.length
|
||||
? (
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th colSpan={2}> </th>
|
||||
<th>{t('threshold')}</th>
|
||||
<th>{t('voting end')}</th>
|
||||
<th>{t('aye')}</th>
|
||||
<th>{t('nay')}</th>
|
||||
<th> </th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
{motions?.map((motion: DeriveCollectiveProposal): React.ReactNode => (
|
||||
<Motion
|
||||
@ -60,7 +68,7 @@ function Proposals ({ className, motions, prime }: Props): React.ReactElement<Pr
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
: t('No council motions')
|
||||
: <div>{t('No council motions')}</div>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -6,7 +6,6 @@ import { AccountId, Balance } from '@polkadot/types/interfaces';
|
||||
|
||||
import React from 'react';
|
||||
import { AddressSmall, Tag } from '@polkadot/react-components';
|
||||
import { FormatBalance } from '@polkadot/react-query';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
import Voters from './Voters';
|
||||
@ -27,7 +26,7 @@ function Candidate ({ className, address, balance, isPrime, voters }: Props): Re
|
||||
<td className='address'>
|
||||
<AddressSmall value={address} />
|
||||
</td>
|
||||
<td className='together top padtop'>
|
||||
<td>
|
||||
{isPrime && (
|
||||
<Tag
|
||||
color='green'
|
||||
@ -36,15 +35,11 @@ function Candidate ({ className, address, balance, isPrime, voters }: Props): Re
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td className='top together right'>
|
||||
{balance && balance.gtn(0) && (
|
||||
<FormatBalance label={<label>{t('backing')}</label>} value={balance} />
|
||||
)}
|
||||
</td>
|
||||
<td className='all'>
|
||||
{voters && voters.length !== 0 && (
|
||||
<Voters voters={voters} />
|
||||
)}
|
||||
<td className='all number'>
|
||||
<Voters
|
||||
balance={balance}
|
||||
voters={voters}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
|
||||
@ -27,6 +27,10 @@ function Candidates ({ allVotes = {}, className, electionsInfo }: Props): React.
|
||||
? electionsInfo.runnersUp.length
|
||||
? (
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th colSpan={2}> </th>
|
||||
<th>{t('backing')}</th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
{electionsInfo.runnersUp.map(([accountId, balance]): React.ReactNode => (
|
||||
<Candidate
|
||||
@ -39,7 +43,7 @@ function Candidates ({ allVotes = {}, className, electionsInfo }: Props): React.
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
: t('No runners up found')
|
||||
: <div>{t('No runners up found')}</div>
|
||||
: <Spinner />
|
||||
}
|
||||
<h1>{t('candidates')}</h1>
|
||||
@ -47,6 +51,10 @@ function Candidates ({ allVotes = {}, className, electionsInfo }: Props): React.
|
||||
? electionsInfo.candidates.length
|
||||
? (
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th colSpan={2}> </th>
|
||||
<th>{t('backing')}</th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
{electionsInfo.candidates.map((accountId): React.ReactNode => (
|
||||
<Candidate
|
||||
@ -58,7 +66,7 @@ function Candidates ({ allVotes = {}, className, electionsInfo }: Props): React.
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
: t('No candidates found')
|
||||
: <div>{t('No candidates found')}</div>
|
||||
: <Spinner />
|
||||
}
|
||||
</div>
|
||||
|
||||
@ -27,6 +27,10 @@ function Members ({ allVotes = {}, className, electionsInfo, prime }: Props): Re
|
||||
? electionsInfo.members.length
|
||||
? (
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th colSpan={2}> </th>
|
||||
<th>{t('backing')}</th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
{electionsInfo.members.map(([accountId, balance]): React.ReactNode => (
|
||||
<Candidate
|
||||
@ -40,7 +44,7 @@ function Members ({ allVotes = {}, className, electionsInfo, prime }: Props): Re
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
: t('No members found')
|
||||
: <div>{t('No members found')}</div>
|
||||
: <Spinner />
|
||||
}
|
||||
</div>
|
||||
|
||||
@ -2,22 +2,24 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId } from '@polkadot/types/interfaces';
|
||||
import { AccountId, Balance } from '@polkadot/types/interfaces';
|
||||
|
||||
import React from 'react';
|
||||
import { AddressMini, Expander } from '@polkadot/react-components';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
import { FormatBalance } from '@polkadot/react-query';
|
||||
|
||||
interface Props {
|
||||
voters: AccountId[];
|
||||
balance?: Balance;
|
||||
voters?: AccountId[];
|
||||
}
|
||||
|
||||
function Voters ({ voters }: Props): React.ReactElement<Props> | null {
|
||||
const { t } = useTranslation();
|
||||
function Voters ({ balance, voters }: Props): React.ReactElement<Props> | null {
|
||||
if (!balance || !voters || !voters.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Expander summary={t('Voters ({{count}})', { replace: { count: voters.length } })}>
|
||||
<Expander summary={<><FormatBalance value={balance} /> ({voters.length})</>}>
|
||||
{voters.map((who): React.ReactNode =>
|
||||
<AddressMini
|
||||
key={who.toString()}
|
||||
|
||||
@ -12,7 +12,6 @@ import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import { BlockToTime } from '@polkadot/react-query';
|
||||
import { formatNumber } from '@polkadot/util';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
import ProposalCell from './ProposalCell';
|
||||
import PreImageButton from './PreImageButton';
|
||||
|
||||
@ -21,36 +20,37 @@ interface Props {
|
||||
}
|
||||
|
||||
function DispatchEntry ({ value: { at, image, imageHash, index } }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const bestNumber = useCall<BlockNumber>(api.derive.chain.bestNumber, []) || new BN(0);
|
||||
|
||||
return (
|
||||
<tr>
|
||||
<td className='number top'><h1>{formatNumber(index)}</h1></td>
|
||||
<td className='number'><h1>{formatNumber(index)}</h1></td>
|
||||
<ProposalCell
|
||||
imageHash={imageHash}
|
||||
proposal={image?.proposal}
|
||||
/>
|
||||
<td className='number together top'>
|
||||
<td className='number together'>
|
||||
{bestNumber && (
|
||||
<>
|
||||
<label>{t('enact')}</label>
|
||||
<BlockToTime blocks={at.sub(bestNumber)} />
|
||||
#{formatNumber(at)}
|
||||
</>
|
||||
)}
|
||||
</td>
|
||||
<td className='together number top'>
|
||||
<td className='button'>
|
||||
{!image?.proposal && (
|
||||
<PreImageButton
|
||||
imageHash={imageHash}
|
||||
isImminent
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td className='mini'>
|
||||
<LinkExternal
|
||||
data={index}
|
||||
type='referendum'
|
||||
withShort
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@ -27,6 +27,11 @@ function DispatchQueue ({ className }: Props): React.ReactElement<Props> | null
|
||||
? queued.length
|
||||
? (
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th colSpan={2}> </th>
|
||||
<th>{t('enact')}</th>
|
||||
<th colSpan={2}> </th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
{queued.map((entry): React.ReactNode => (
|
||||
<DispatchEntry
|
||||
@ -37,7 +42,7 @@ function DispatchQueue ({ className }: Props): React.ReactElement<Props> | null
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
: t('Nothing queued for execution')
|
||||
: <div>{t('Nothing queued for execution')}</div>
|
||||
: <Spinner />
|
||||
}
|
||||
</div>
|
||||
|
||||
@ -8,7 +8,6 @@ import React from 'react';
|
||||
import { AddressMini, Button } from '@polkadot/react-components';
|
||||
import { FormatBalance } from '@polkadot/react-query';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
import PreImageButton from './PreImageButton';
|
||||
import ProposalCell from './ProposalCell';
|
||||
import Fasttrack from './Fasttrack';
|
||||
@ -19,8 +18,6 @@ interface Props {
|
||||
}
|
||||
|
||||
function External ({ className, value: { image, imageHash, threshold } }: Props): React.ReactElement<Props> | null {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<tr className={className}>
|
||||
<ProposalCell
|
||||
@ -28,12 +25,12 @@ function External ({ className, value: { image, imageHash, threshold } }: Props)
|
||||
proposal={image?.proposal}
|
||||
/>
|
||||
<td className='address'>
|
||||
{image && <AddressMini label={t('proposer')} value={image.proposer} />}
|
||||
{image && <AddressMini value={image.proposer} />}
|
||||
</td>
|
||||
<td className='number together top'>
|
||||
{image && <FormatBalance label={<label>{t('locked')}</label>} value={image.balance} />}
|
||||
{image && <FormatBalance value={image.balance} />}
|
||||
</td>
|
||||
<td className='together number top'>
|
||||
<td className='button'>
|
||||
<Button.Group>
|
||||
{!image?.proposal && (
|
||||
<PreImageButton
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
import { DeriveProposalExternal } from '@polkadot/api-derive/types';
|
||||
|
||||
import React from 'react';
|
||||
import { Spinner } from '@polkadot/react-components';
|
||||
import { Spinner, Table } from '@polkadot/react-components';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
@ -23,11 +23,23 @@ function Externals ({ className }: Props): React.ReactElement<Props> | null {
|
||||
return (
|
||||
<div className={`proposalSection ${className}`}>
|
||||
<h1>{t('external')}</h1>
|
||||
{!external
|
||||
? external === null
|
||||
? t('No external proposal')
|
||||
{external
|
||||
? (
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th> </th>
|
||||
<th>{t('proposer')}</th>
|
||||
<th>{t('locked')}</th>
|
||||
<th> </th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
<External value={external} />
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
: external === null
|
||||
? <div>{t('No external proposal')}</div>
|
||||
: <Spinner />
|
||||
: <External value={external} />
|
||||
}
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -26,18 +26,18 @@ function Proposal ({ className, value: { balance, index, image, imageHash, propo
|
||||
|
||||
return (
|
||||
<tr className={className}>
|
||||
<td className='number top'><h1>{formatNumber(index)}</h1></td>
|
||||
<td className='number'><h1>{formatNumber(index)}</h1></td>
|
||||
<ProposalCell
|
||||
imageHash={imageHash}
|
||||
proposal={image?.proposal}
|
||||
/>
|
||||
<td className='address'>
|
||||
<AddressMini label={t('proposer')} value={proposer} />
|
||||
<AddressMini value={proposer} />
|
||||
</td>
|
||||
<td className='number together top'>
|
||||
<FormatBalance label={<label>{t('locked')}</label>} value={balance} />
|
||||
<td className='number together'>
|
||||
<FormatBalance value={balance} />
|
||||
</td>
|
||||
<td className='top padtop'>
|
||||
<td>
|
||||
{seconding.length !== 0 && (
|
||||
<Expander summary={t('Seconds ({{count}})', { replace: { count: seconding.length } })}>
|
||||
{seconding.map((address, count): React.ReactNode => (
|
||||
@ -52,7 +52,7 @@ function Proposal ({ className, value: { balance, index, image, imageHash, propo
|
||||
</Expander>
|
||||
)}
|
||||
</td>
|
||||
<td className='together number top'>
|
||||
<td className='button'>
|
||||
<Button.Group>
|
||||
<Seconding
|
||||
depositors={seconds || []}
|
||||
@ -63,9 +63,12 @@ function Proposal ({ className, value: { balance, index, image, imageHash, propo
|
||||
<PreImageButton imageHash={imageHash} />
|
||||
)}
|
||||
</Button.Group>
|
||||
</td>
|
||||
<td className='mini'>
|
||||
<LinkExternal
|
||||
data={index}
|
||||
type='proposal'
|
||||
withShort
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@ -21,7 +21,7 @@ function ProposalCell ({ className, imageHash, proposal }: Props): React.ReactEl
|
||||
|
||||
if (!proposal) {
|
||||
return (
|
||||
<td className={`${className} all top`}>
|
||||
<td className={`${className} all`}>
|
||||
<label>{t('preimage hash')}</label>
|
||||
{imageHash.toString()}
|
||||
</td>
|
||||
@ -31,7 +31,7 @@ function ProposalCell ({ className, imageHash, proposal }: Props): React.ReactEl
|
||||
const { meta, method, section } = registry.findMetaCall(proposal.callIndex);
|
||||
|
||||
return (
|
||||
<td className={`${className} all top`}>
|
||||
<td className={`${className} all`}>
|
||||
<div>{section}.{method}</div>
|
||||
<Expander summaryMeta={meta}>
|
||||
<Call
|
||||
|
||||
@ -27,6 +27,12 @@ function Proposals ({ className }: Props): React.ReactElement<Props> {
|
||||
? proposals.length
|
||||
? (
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th colSpan={2}> </th>
|
||||
<th>{t('proposer')}</th>
|
||||
<th>{t('locked')}</th>
|
||||
<th colSpan={3}> </th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
{proposals.map((proposal): React.ReactNode => (
|
||||
<ProposalDisplay
|
||||
@ -37,7 +43,7 @@ function Proposals ({ className }: Props): React.ReactElement<Props> {
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
: t('No active proposals')
|
||||
: <div>{t('No active proposals')}</div>
|
||||
: <Spinner />
|
||||
}
|
||||
</div>
|
||||
|
||||
@ -40,25 +40,21 @@ function Referendum ({ className, value: { allAye, allNay, image, imageHash, ind
|
||||
|
||||
return (
|
||||
<tr className={className}>
|
||||
<td className='number top'><h1>{formatNumber(index)}</h1></td>
|
||||
<td className='number'><h1>{formatNumber(index)}</h1></td>
|
||||
<ProposalCell
|
||||
className='top'
|
||||
imageHash={imageHash}
|
||||
proposal={image?.proposal}
|
||||
/>
|
||||
<td className='number together top'>
|
||||
<label>{t('remaining')}</label>
|
||||
<td className='number together'>
|
||||
<BlockToTime blocks={remainBlock} />
|
||||
{t('{{blocks}} blocks', { replace: { blocks: formatNumber(remainBlock) } })}
|
||||
</td>
|
||||
<td className='number together top'>
|
||||
<label>{t('activate')}</label>
|
||||
<td className='number together'>
|
||||
<BlockToTime blocks={enactBlock.sub(bestNumber)} />
|
||||
#{formatNumber(enactBlock)}
|
||||
</td>
|
||||
<td className='top'>
|
||||
<label>{t('Aye {{count}}', { replace: { count: voteCountAye ? `(${formatNumber(voteCountAye)})` : '' } })}</label>
|
||||
<Expander summary={<FormatBalance value={votedAye} />}>
|
||||
<td className='number'>
|
||||
<Expander summary={<><FormatBalance value={votedAye} />{voteCountAye ? ` (${formatNumber(voteCountAye)})` : '' }</>}>
|
||||
{allAye.map(({ accountId }) =>
|
||||
<AddressMini
|
||||
key={accountId.toString()}
|
||||
@ -67,9 +63,8 @@ function Referendum ({ className, value: { allAye, allNay, image, imageHash, ind
|
||||
)}
|
||||
</Expander>
|
||||
</td>
|
||||
<td className='top'>
|
||||
<label>{t('Nay {{count}}', { replace: { count: voteCountNay ? `(${formatNumber(voteCountNay)})` : '' } })}</label>
|
||||
<Expander summary={<FormatBalance value={votedNay} />}>
|
||||
<td className='number'>
|
||||
<Expander summary={<><FormatBalance value={votedNay} />{voteCountNay ? ` (${formatNumber(voteCountNay)})` : '' }</>}>
|
||||
{allNay.map(({ accountId }) =>
|
||||
<AddressMini
|
||||
key={accountId.toString()}
|
||||
@ -78,7 +73,7 @@ function Referendum ({ className, value: { allAye, allNay, image, imageHash, ind
|
||||
)}
|
||||
</Expander>
|
||||
</td>
|
||||
<td className='together top padtop'>
|
||||
<td>
|
||||
{isBoolean(isPassing) && (
|
||||
<Tag
|
||||
color={isPassing ? 'green' : 'red'}
|
||||
@ -87,7 +82,7 @@ function Referendum ({ className, value: { allAye, allNay, image, imageHash, ind
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td className='number together top'>
|
||||
<td className='button'>
|
||||
<Button.Group>
|
||||
<Voting
|
||||
proposal={image?.proposal}
|
||||
@ -97,9 +92,12 @@ function Referendum ({ className, value: { allAye, allNay, image, imageHash, ind
|
||||
<PreImageButton imageHash={imageHash} />
|
||||
)}
|
||||
</Button.Group>
|
||||
</td>
|
||||
<td className='mini'>
|
||||
<LinkExternal
|
||||
data={index}
|
||||
type='referendum'
|
||||
withShort
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@ -27,6 +27,14 @@ function Referendums ({ className }: Props): React.ReactElement<Props> {
|
||||
? referendums.length
|
||||
? (
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th colSpan={2}> </th>
|
||||
<th>{t('remaining')}</th>
|
||||
<th>{t('activate')}</th>
|
||||
<th>{t('aye')}</th>
|
||||
<th>{t('nay')}</th>
|
||||
<th colSpan={3}> </th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
{referendums.map((referendum): React.ReactNode => (
|
||||
<Referendum
|
||||
@ -37,7 +45,7 @@ function Referendums ({ className }: Props): React.ReactElement<Props> {
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
: t('No active referendums')
|
||||
: <div>{t('No active referendums')}</div>
|
||||
: <Spinner />
|
||||
}
|
||||
</div>
|
||||
|
||||
@ -42,7 +42,7 @@ function Peers ({ className, peers }: Props): React.ReactElement<Props> {
|
||||
<tr>
|
||||
<th className='roles'>{t('role')}</th>
|
||||
<th className='peerid ui--media-medium'>{t('peer id')}</th>
|
||||
<th className='number'>{t('best #')}</th>
|
||||
<th>{t('best #')}</th>
|
||||
<th className='hash'>{t('best hash')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@ -63,21 +63,13 @@ function Parachain ({ className, parachain: { didUpdate, id, info, pendingSwapId
|
||||
</div>
|
||||
</td>
|
||||
<td className='all info'>
|
||||
<div>
|
||||
<ParachainInfo info={info} />
|
||||
</div>
|
||||
<ParachainInfo info={info} />
|
||||
</td>
|
||||
<td className='all'></td>
|
||||
<td className='top number pending-swap-id ui--media-small'>
|
||||
{pendingSwapId && (
|
||||
<>
|
||||
<label>{t('will swap to id')}</label>
|
||||
<b>{pendingSwapId.toString()}</b>
|
||||
</>
|
||||
)}
|
||||
<td className='number pending-swap-id ui--media-small'>
|
||||
{pendingSwapId?.toString()}
|
||||
</td>
|
||||
<td className='top ui--media-small'>
|
||||
<label>{t('scheduling')}</label>
|
||||
<td className='number ui--media-small'>
|
||||
{info?.scheduling?.toString() || t('<unknown>')}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@ -8,6 +8,7 @@ import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { Table } from '@polkadot/react-components';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
import Parachain from './Parachain';
|
||||
|
||||
interface Props {
|
||||
@ -15,8 +16,15 @@ interface Props {
|
||||
}
|
||||
|
||||
function Parachains ({ parachains }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th colSpan={4}> </th>
|
||||
<th>{t('swap to id')}</th>
|
||||
<th>{t('scheduling')}</th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
{parachains.map((parachain): React.ReactNode => (
|
||||
<Parachain
|
||||
|
||||
@ -61,7 +61,7 @@ function Extensions ({ chainInfo, className }: Props): React.ReactElement<Props>
|
||||
</Button.Group>
|
||||
</>
|
||||
)
|
||||
: t('No upgradable extensions found')
|
||||
: <div>{t('No upgradable extensions found')}</div>
|
||||
: <Spinner />
|
||||
}
|
||||
</div>
|
||||
|
||||
@ -8,29 +8,21 @@ import React from 'react';
|
||||
import { AddressSmall } from '@polkadot/react-components';
|
||||
import { FormatBalance } from '@polkadot/react-query';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
|
||||
interface Props {
|
||||
value: Bid;
|
||||
}
|
||||
|
||||
function BidRow ({ value: { who, kind, value } }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<tr>
|
||||
<td className='top'>
|
||||
<td className='all top'>
|
||||
<AddressSmall value={who} />
|
||||
</td>
|
||||
<td className='number top'>
|
||||
<label>{t('kind')}</label>
|
||||
{kind.type}
|
||||
</td>
|
||||
<td className='number top'>
|
||||
<FormatBalance
|
||||
label={<label>{t('value')}</label>}
|
||||
value={value}
|
||||
/>
|
||||
<FormatBalance value={value} />
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
|
||||
@ -27,6 +27,11 @@ function Bids ({ className }: Props): React.ReactElement<Props> {
|
||||
? bids.length
|
||||
? (
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th> </th>
|
||||
<th>{t('kind')}</th>
|
||||
<th>{t('value')}</th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
{bids.map((bid): React.ReactNode => (
|
||||
<BidRow
|
||||
@ -37,7 +42,7 @@ function Bids ({ className }: Props): React.ReactElement<Props> {
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
: t('No bids')
|
||||
: <div>{t('No bids')}</div>
|
||||
: <Spinner />
|
||||
}
|
||||
</div>
|
||||
|
||||
@ -12,7 +12,6 @@ import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import { FormatBalance } from '@polkadot/react-query';
|
||||
import { Option } from '@polkadot/types';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
import CandidateVoting from './CandidateVoting';
|
||||
import VoteDisplay from './VoteDisplay';
|
||||
|
||||
@ -24,7 +23,6 @@ interface Props {
|
||||
}
|
||||
|
||||
function Candidate ({ allMembers, isMember, ownMembers, value: { accountId, kind, value } }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const votes = useCall<VoteType[]>(api.query.society.votes.multi as any, [allMembers.map((memberId): [AccountId, string] => [accountId, memberId])] as any, {
|
||||
transform: (voteOpts: Option<SocietyVote>[]): VoteType[] =>
|
||||
@ -36,21 +34,17 @@ function Candidate ({ allMembers, isMember, ownMembers, value: { accountId, kind
|
||||
|
||||
return (
|
||||
<tr>
|
||||
<td className='address'>
|
||||
<td className='address all'>
|
||||
<AddressSmall value={accountId} />
|
||||
</td>
|
||||
<td className='number top'>
|
||||
<label>{t('kind')}</label>
|
||||
<td className='number'>
|
||||
{kind.type}
|
||||
</td>
|
||||
<td className='number top'>
|
||||
<FormatBalance
|
||||
label={<label>{t('value')}</label>}
|
||||
value={value}
|
||||
/>
|
||||
<td className='number'>
|
||||
<FormatBalance value={value} />
|
||||
</td>
|
||||
<VoteDisplay votes={votes} />
|
||||
<td className='number together top'>
|
||||
<td className='button'>
|
||||
<CandidateVoting
|
||||
candidateId={accountId.toString()}
|
||||
isMember={isMember}
|
||||
|
||||
@ -28,6 +28,13 @@ function Candidates ({ allMembers, className, isMember, ownMembers }: Props): Re
|
||||
? candidates.length
|
||||
? (
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th> </th>
|
||||
<th>{t('kind')}</th>
|
||||
<th>{t('value')}</th>
|
||||
<th colSpan={3}>{t('votes')}</th>
|
||||
<th> </th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
{candidates.map((candidate): React.ReactNode => (
|
||||
<Candidate
|
||||
@ -41,7 +48,7 @@ function Candidates ({ allMembers, className, isMember, ownMembers }: Props): Re
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
: t('No candidates')
|
||||
: <div>{t('No candidates')}</div>
|
||||
: <Spinner />
|
||||
}
|
||||
</div>
|
||||
|
||||
@ -37,13 +37,18 @@ function Defender ({ className, info, isMember, ownMembers }: Props): React.Reac
|
||||
<div className={`overviewSection ${className}`}>
|
||||
<h1>{t('defender')}</h1>
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th> </th>
|
||||
<th colSpan={3}>{t('votes')}</th>
|
||||
<th> </th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
<tr>
|
||||
<td className='address'>
|
||||
<td className='address all'>
|
||||
<AddressSmall value={info.defender} />
|
||||
</td>
|
||||
<VoteDisplay votes={votes} />
|
||||
<td className='top together number'>
|
||||
<td className='button'>
|
||||
<DefenderVoting
|
||||
isMember={isMember}
|
||||
ownMembers={ownMembers}
|
||||
|
||||
@ -23,7 +23,7 @@ function Member ({ className, isHead, value: { accountId, strikes } }: Props): R
|
||||
<td className='address'>
|
||||
<AddressSmall value={accountId} />
|
||||
</td>
|
||||
<td className='together top padtop'>
|
||||
<td>
|
||||
{isHead && (
|
||||
<Tag
|
||||
color='green'
|
||||
@ -34,7 +34,6 @@ function Member ({ className, isHead, value: { accountId, strikes } }: Props): R
|
||||
</td>
|
||||
<td className='all'> </td>
|
||||
<td className='number top'>
|
||||
<label>{t('strikes')}</label>
|
||||
{strikes.toString()}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@ -35,6 +35,10 @@ function Members ({ className, info }: Props): React.ReactElement<Props> {
|
||||
? filtered.length
|
||||
? (
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th colSpan={3}> </th>
|
||||
<th>{t('strikes')}</th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
{filtered.map((member): React.ReactNode => (
|
||||
<Member
|
||||
@ -46,7 +50,7 @@ function Members ({ className, info }: Props): React.ReactElement<Props> {
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
: t('No active members')
|
||||
: <div>{t('No active members')}</div>
|
||||
: <Spinner />
|
||||
}
|
||||
</div>
|
||||
|
||||
@ -27,7 +27,7 @@ function VoteDisplay ({ votes }: Props): React.ReactElement<Props> {
|
||||
|
||||
return (
|
||||
<>
|
||||
<td className='top padtop'>
|
||||
<td>
|
||||
{allSkeptic.length !== 0 && (
|
||||
<Expander summary={t('Skeptics ({{count}})', { replace: { count: allSkeptic.length } })}>
|
||||
{allSkeptic.map(([who]): React.ReactNode =>
|
||||
@ -39,7 +39,7 @@ function VoteDisplay ({ votes }: Props): React.ReactElement<Props> {
|
||||
</Expander>
|
||||
)}
|
||||
</td>
|
||||
<td className='top padtop'>
|
||||
<td>
|
||||
{allAye.length !== 0 && (
|
||||
<Expander summary={t('Approvals ({{count}})', { replace: { count: allAye.length } })}>
|
||||
{allAye.map(([who]): React.ReactNode =>
|
||||
@ -51,7 +51,7 @@ function VoteDisplay ({ votes }: Props): React.ReactElement<Props> {
|
||||
</Expander>
|
||||
)}
|
||||
</td>
|
||||
<td className='top padtop'>
|
||||
<td>
|
||||
{allNay.length !== 0 && (
|
||||
<Expander summary={t('Rejections ({{count}})', { replace: { count: allNay.length } })}>
|
||||
{allNay.map(([who]): React.ReactNode =>
|
||||
|
||||
@ -257,12 +257,9 @@ function Account ({ allStashes, className, isOwnStash, next, onUpdateType, rewar
|
||||
<AddressSmall value={stashId} />
|
||||
</td>
|
||||
<td className='address'>
|
||||
<AddressMini
|
||||
label={t('controller')}
|
||||
value={controllerId}
|
||||
/>
|
||||
<AddressMini value={controllerId} />
|
||||
</td>
|
||||
<td className='top'>
|
||||
<td>
|
||||
<AddressInfo
|
||||
address={stashId}
|
||||
withBalance={{
|
||||
@ -277,7 +274,7 @@ function Account ({ allStashes, className, isOwnStash, next, onUpdateType, rewar
|
||||
</td>
|
||||
{isStashValidating
|
||||
? (
|
||||
<td className='top'>
|
||||
<td>
|
||||
<AddressInfo
|
||||
address={stashId}
|
||||
withBalance={false}
|
||||
@ -319,7 +316,7 @@ function Account ({ allStashes, className, isOwnStash, next, onUpdateType, rewar
|
||||
</td>
|
||||
)
|
||||
}
|
||||
<td className='top number together'>
|
||||
<td className='button'>
|
||||
{isLoading
|
||||
? null
|
||||
: (
|
||||
|
||||
@ -80,6 +80,11 @@ function Actions ({ allRewards, allStashes, className, isVisible, next, stakingO
|
||||
{foundStashes?.length
|
||||
? (
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th colSpan={2}> </th>
|
||||
<th className='start'>{t('controller')}</th>
|
||||
<th colSpan={3}> </th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
{foundStashes.map(([stashId, isOwnStash]): React.ReactNode => (
|
||||
<Account
|
||||
@ -98,7 +103,7 @@ function Actions ({ allRewards, allStashes, className, isVisible, next, stakingO
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
: t('No funds staked yet. Bond funds to validate or nominate a validator.')
|
||||
: <div>{t('No funds staked yet. Bond funds to validate or nominate a validator.')}</div>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -10,21 +10,16 @@ import { AddressMini, Expander } from '@polkadot/react-components';
|
||||
import { FormatBalance } from '@polkadot/react-query';
|
||||
import { formatNumber } from '@polkadot/util';
|
||||
|
||||
import { useTranslation } from '../../translate';
|
||||
|
||||
interface Props {
|
||||
stakeOther?: BN;
|
||||
nominators: [string, Balance][];
|
||||
}
|
||||
|
||||
function StakeOther ({ nominators, stakeOther }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<td className='top'>
|
||||
<td className='number all'>
|
||||
{stakeOther?.gtn(0) && (
|
||||
<>
|
||||
<label>{t('other stake')}</label>
|
||||
<Expander summary={
|
||||
<FormatBalance value={stakeOther}>
|
||||
({formatNumber(nominators.length)})
|
||||
|
||||
@ -14,7 +14,6 @@ import { FormatBalance } from '@polkadot/react-query';
|
||||
import keyring from '@polkadot/ui-keyring';
|
||||
import { formatNumber } from '@polkadot/util';
|
||||
|
||||
import { useTranslation } from '../../translate';
|
||||
import Favorite from './Favorite';
|
||||
import Status from './Status';
|
||||
import StakeOther from './StakeOther';
|
||||
@ -102,7 +101,6 @@ function checkVisibility (api: ApiPromise, address: string, filterName: string,
|
||||
}
|
||||
|
||||
function Address ({ address, className, filterName, hasQueries, isAuthor, isElected, isFavorite, isMain, lastBlock, onlineCount, onlineMessage, points, setNominators, toggleFavorite }: Props): React.ReactElement<Props> | null {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const info = useCall<DeriveAccountInfo>(api.derive.accounts.info as any, [address]);
|
||||
const stakingInfo = useCall<DeriveStakingQuery>(isMain && api.derive.staking.query as any, [address]);
|
||||
@ -146,32 +144,23 @@ function Address ({ address, className, filterName, hasQueries, isAuthor, isElec
|
||||
<td className='address'>
|
||||
<AddressSmall value={address} />
|
||||
</td>
|
||||
<td className='top'>
|
||||
{stakeOwn && (
|
||||
<FormatBalance
|
||||
label={<label>{t('own stake')}</label>}
|
||||
value={stakeOwn}
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<StakeOther
|
||||
nominators={nominators}
|
||||
stakeOther={stakeOther}
|
||||
/>
|
||||
<td className='number top'>
|
||||
{commission && (
|
||||
<><label>{t('commission')}</label>{commission}</>
|
||||
<td className='number'>
|
||||
{stakeOwn && (
|
||||
<FormatBalance value={stakeOwn} />
|
||||
)}
|
||||
</td>
|
||||
<td className='number top'>
|
||||
{points && (
|
||||
<><label>{t('points')}</label>{formatNumber(points)}</>
|
||||
)}
|
||||
<td className='number'>
|
||||
{commission}
|
||||
</td>
|
||||
<td className='number top'>
|
||||
{lastBlock && (
|
||||
<><label>{t('last #')}</label>{lastBlock}</>
|
||||
)}
|
||||
<td className='number'>
|
||||
{points && formatNumber(points)}
|
||||
</td>
|
||||
<td className='number'>
|
||||
{lastBlock}
|
||||
</td>
|
||||
<td>
|
||||
{hasQueries && (
|
||||
|
||||
@ -150,6 +150,15 @@ function CurrentList ({ authorsMap, hasQueries, isIntentions, isVisible, lastAut
|
||||
value={nameFilter}
|
||||
/>
|
||||
<Table className={isIntentions ? 'staking--hidden' : ''}>
|
||||
<Table.Head>
|
||||
<th colSpan={3}> </th>
|
||||
<th>{t('other stake')}</th>
|
||||
<th>{t('own stake')}</th>
|
||||
<th>{t('commission')}</th>
|
||||
<th>{t('points')}</th>
|
||||
<th>{t('last #')}</th>
|
||||
<th> </th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
{_renderRows(validators, true)}
|
||||
</Table.Body>
|
||||
@ -158,6 +167,9 @@ function CurrentList ({ authorsMap, hasQueries, isIntentions, isVisible, lastAut
|
||||
waiting
|
||||
? (
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th colSpan={9}> </th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
{_renderRows(elected, false)}
|
||||
{_renderRows(waiting, false)}
|
||||
|
||||
@ -9,7 +9,6 @@ import { AddressSmall, Icon } from '@polkadot/react-components';
|
||||
import { FormatBalance } from '@polkadot/react-query';
|
||||
import { formatNumber } from '@polkadot/util';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
import Favorite from '../Overview/Address/Favorite';
|
||||
|
||||
interface Props {
|
||||
@ -18,8 +17,6 @@ interface Props {
|
||||
}
|
||||
|
||||
function Validator ({ info: { accountId, bondOther, bondOwn, bondTotal, commissionPer, isCommission, isFavorite, isNominating, key, numNominators, rankOverall, rewardPayout, validatorPayment }, toggleFavorite }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const _onQueryStats = useCallback(
|
||||
(): void => {
|
||||
window.location.hash = `/staking/query/${key}`;
|
||||
@ -41,14 +38,14 @@ function Validator ({ info: { accountId, bondOther, bondOwn, bondTotal, commissi
|
||||
<td className='number'>
|
||||
{
|
||||
isCommission
|
||||
? <><label>{t('commission')}</label>{`${commissionPer.toFixed(2)}%`}</>
|
||||
: <FormatBalance label={<label>{t('commission')}</label>} value={validatorPayment} />
|
||||
? `${commissionPer.toFixed(2)}%`
|
||||
: <FormatBalance value={validatorPayment} />
|
||||
}
|
||||
</td>
|
||||
<td className='number together'><FormatBalance label={<label>{t('total stake')}</label>} value={bondTotal} /></td>
|
||||
<td className='number together'><FormatBalance label={<label>{t('own stake')}</label>} value={bondOwn} /></td>
|
||||
<td className='number together'><FormatBalance label={<label>{t('other stake')}</label>} value={bondOther} > ({formatNumber(numNominators)})</FormatBalance></td>
|
||||
<td className='number together'><FormatBalance label={<label>{t('profit/era est.')}</label>} value={rewardPayout} /></td>
|
||||
<td className='number together'><FormatBalance value={bondTotal} /></td>
|
||||
<td className='number together'><FormatBalance value={bondOwn} /></td>
|
||||
<td className='number together'><FormatBalance value={bondOther} > ({formatNumber(numNominators)})</FormatBalance></td>
|
||||
<td className='number together'><FormatBalance value={rewardPayout} /></td>
|
||||
<td>
|
||||
<Icon
|
||||
className='staking--stats'
|
||||
|
||||
@ -7,7 +7,7 @@ import { Balance, ValidatorPrefs, ValidatorPrefsTo196 } from '@polkadot/types/in
|
||||
import { ValidatorInfo } from './types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { registry } from '@polkadot/react-api';
|
||||
import { Icon, InputBalance, Spinner, Table } from '@polkadot/react-components';
|
||||
@ -186,6 +186,10 @@ function Targets ({ className }: Props): React.ReactElement<Props> {
|
||||
const [{ nominators, validators, sorted, totalStaked }, setWorkable] = useState<AllInfo>({ nominators: [], validators: [] });
|
||||
const [{ sortBy, sortFromMax }, setSortBy] = useState<{ sortBy: SortBy; sortFromMax: boolean }>({ sortBy: 'rankOverall', sortFromMax: true });
|
||||
const amount = useDebounce(_amount);
|
||||
const labels = useMemo(
|
||||
(): Record<string, string> => ({ rankComm: t('commission'), rankBondTotal: t('total stake'), rankBondOwn: t('own stake'), rankBondOther: t('other stake'), rankOverall: t('profit/era est') }),
|
||||
[t]
|
||||
);
|
||||
|
||||
const _sort = useCallback(
|
||||
(newSortBy: SortBy): void =>
|
||||
@ -232,15 +236,13 @@ function Targets ({ className }: Props): React.ReactElement<Props> {
|
||||
/>
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
<th colSpan={3}> </th>
|
||||
{['rankComm', 'rankBondTotal', 'rankBondOwn', 'rankBondOther', 'rankOverall'].map((header): React.ReactNode => (
|
||||
<th
|
||||
className={`isClickable ${sortBy === header && 'isSelected'}`}
|
||||
className={`isClickable ${sortBy === header && 'ui--highlight--border'} number`}
|
||||
key={header}
|
||||
onClick={(): void => _sort(header as 'rankComm')}
|
||||
><Icon name={sortBy === header ? (sortFromMax ? 'chevron down' : 'chevron up') : 'minus'} /></th>
|
||||
>{labels[header]}<Icon name={sortBy === header ? (sortFromMax ? 'chevron down' : 'chevron up') : 'minus'} /></th>
|
||||
))}
|
||||
<th> </th>
|
||||
</Table.Head>
|
||||
@ -264,4 +266,10 @@ function Targets ({ className }: Props): React.ReactElement<Props> {
|
||||
|
||||
export default React.memo(styled(Targets)`
|
||||
text-align: center;
|
||||
|
||||
th {
|
||||
i.icon {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
@ -23,13 +23,16 @@ function Members ({ className, members, prime }: Props): React.ReactElement<Prop
|
||||
{members.length
|
||||
? (
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th colSpan={3}> </th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
{members.map((accountId): React.ReactNode => (
|
||||
<tr key={accountId.toString()}>
|
||||
<td className='all address'>
|
||||
<td className='address'>
|
||||
<AddressSmall value={accountId} />
|
||||
</td>
|
||||
<td className='together top padtop'>
|
||||
<td>
|
||||
{prime?.eq(accountId) && (
|
||||
<Tag
|
||||
color='green'
|
||||
@ -44,7 +47,7 @@ function Members ({ className, members, prime }: Props): React.ReactElement<Prop
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
: t('No members found')
|
||||
: <div>{t('No members found')}</div>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -11,7 +11,6 @@ import ProposalCell from '@polkadot/app-democracy/Overview/ProposalCell';
|
||||
import { Option } from '@polkadot/types';
|
||||
import { formatNumber } from '@polkadot/util';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
import Voting from './Voting';
|
||||
|
||||
interface Props {
|
||||
@ -21,7 +20,6 @@ interface Props {
|
||||
}
|
||||
|
||||
function Proposal ({ className, imageHash, prime }: Props): React.ReactElement<Props> | null {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const optProposal = useCall<Option<ProposalType>>(api.query.technicalCommittee.proposalOf, [imageHash]);
|
||||
const votes = useCall<Option<Votes>>(api.query.technicalCommittee.voting, [imageHash]);
|
||||
@ -35,37 +33,33 @@ function Proposal ({ className, imageHash, prime }: Props): React.ReactElement<P
|
||||
|
||||
return (
|
||||
<tr className={className}>
|
||||
<td className='number top'><h1>{formatNumber(index)}</h1></td>
|
||||
<td className='number'><h1>{formatNumber(index)}</h1></td>
|
||||
<ProposalCell
|
||||
className='top'
|
||||
imageHash={imageHash}
|
||||
proposal={proposal}
|
||||
/>
|
||||
<td className='number top'>
|
||||
<label>{t('threshold')}</label>
|
||||
<td className='number'>
|
||||
{formatNumber(ayes.length)}/{formatNumber(threshold)}
|
||||
</td>
|
||||
<td className='top'>
|
||||
<td className='number'>
|
||||
{ayes.map((address, index): React.ReactNode => (
|
||||
<AddressMini
|
||||
key={`${index}:${address}`}
|
||||
label={index === 0 ? t('Aye') : undefined}
|
||||
value={address}
|
||||
withBalance={false}
|
||||
/>
|
||||
))}
|
||||
</td>
|
||||
<td className='top'>
|
||||
<td className='number'>
|
||||
{nays.map((address, index): React.ReactNode => (
|
||||
<AddressMini
|
||||
key={`${index}:${address}`}
|
||||
label={t('Nay')}
|
||||
value={address}
|
||||
withBalance={false}
|
||||
/>
|
||||
))}
|
||||
</td>
|
||||
<td className='number top together'>
|
||||
<td className='button'>
|
||||
<Voting
|
||||
hash={imageHash}
|
||||
prime={prime}
|
||||
|
||||
@ -27,6 +27,13 @@ function Proposals ({ className, isMember, members, prime, proposals }: Props):
|
||||
? proposals.length
|
||||
? (
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th colSpan={2}> </th>
|
||||
<td>{t('threshold')}</td>
|
||||
<td>{t('aye')}</td>
|
||||
<td>{t('nay')}</td>
|
||||
<th> </th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
{proposals?.map((hash: Hash): React.ReactNode => (
|
||||
<Proposal
|
||||
@ -38,7 +45,7 @@ function Proposals ({ className, isMember, members, prime, proposals }: Props):
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
: t('No committee proposals')
|
||||
: <div>{t('No committee proposals')}</div>
|
||||
: <Spinner />
|
||||
}
|
||||
</div>
|
||||
|
||||
@ -9,7 +9,6 @@ import { AddressMini, AddressSmall, LinkExternal } from '@polkadot/react-compone
|
||||
import { FormatBalance } from '@polkadot/react-query';
|
||||
import { formatNumber } from '@polkadot/util';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
import Submission from './Submission';
|
||||
import Voting from './Voting';
|
||||
|
||||
@ -22,35 +21,24 @@ interface Props {
|
||||
}
|
||||
|
||||
function ProposalDisplay ({ className, isMember, proposal: { council, id, proposal }, withSend }: Props): React.ReactElement<Props> | null {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<tr className={className}>
|
||||
<td className='number top'>
|
||||
<td className='number'>
|
||||
<h1>{formatNumber(id)}</h1>
|
||||
</td>
|
||||
<td className='address'>
|
||||
<AddressSmall value={proposal.proposer} />
|
||||
</td>
|
||||
<td className='top'>
|
||||
<FormatBalance
|
||||
label={<label>{t('bond')}</label>}
|
||||
value={proposal.bond}
|
||||
/>
|
||||
<td className='number'>
|
||||
<FormatBalance value={proposal.bond} />
|
||||
</td>
|
||||
<td className='address'>
|
||||
<AddressMini
|
||||
label={t('beneficiary')}
|
||||
value={proposal.beneficiary}
|
||||
/>
|
||||
<AddressMini value={proposal.beneficiary} />
|
||||
</td>
|
||||
<td className='top'>
|
||||
<FormatBalance
|
||||
label={<label>{t('value')}</label>}
|
||||
value={proposal.value}
|
||||
/>
|
||||
<td>
|
||||
<FormatBalance value={proposal.value} />
|
||||
</td>
|
||||
<td className='top number together'>
|
||||
<td className='button'>
|
||||
{withSend && (
|
||||
<>
|
||||
<Submission
|
||||
|
||||
@ -7,7 +7,7 @@ import { AccountId, Balance } from '@polkadot/types/interfaces';
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { Table } from '@polkadot/react-components';
|
||||
import { Spinner, Table } from '@polkadot/react-components';
|
||||
import { useApi, useAccounts, useCall } from '@polkadot/react-hooks';
|
||||
|
||||
import Proposal from './Proposal';
|
||||
@ -42,22 +42,35 @@ function ProposalsBase ({ className, isApprovals, proposals }: Props): React.Rea
|
||||
return (
|
||||
<div className={className}>
|
||||
<h1>{isApprovals ? t('Approved') : t('Proposals')}</h1>
|
||||
{!(proposals?.length) && (
|
||||
isApprovals ? t('No approved proposals') : t('No pending proposals')
|
||||
)}
|
||||
<Table>
|
||||
<Table.Body>
|
||||
{proposals?.map((proposal): React.ReactNode => (
|
||||
<Proposal
|
||||
isMember={isMember}
|
||||
onRespond={_onRespond}
|
||||
proposal={proposal}
|
||||
key={proposal.id.toString()}
|
||||
withSend={!isApprovals}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
</Table>
|
||||
{proposals
|
||||
? proposals.length
|
||||
? (
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th colSpan={2}> </th>
|
||||
<td>{t('bond')}</td>
|
||||
<td className='start'>{t('beneficiary')}</td>
|
||||
<td>{t('value')}</td>
|
||||
<th> </th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
{proposals.map((proposal): React.ReactNode => (
|
||||
<Proposal
|
||||
isMember={isMember}
|
||||
onRespond={_onRespond}
|
||||
proposal={proposal}
|
||||
key={proposal.id.toString()}
|
||||
withSend={!isApprovals}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
: isApprovals
|
||||
? <div>{t('No approved proposals')}</div>
|
||||
: <div>{t('No pending proposals')}</div>
|
||||
: <Spinner />
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -365,7 +365,6 @@ function renderBalances (props: Props, allAccounts: string[], t: (key: string) =
|
||||
if (withBalanceToggle) {
|
||||
return (
|
||||
<>
|
||||
<label>{t('balances')}</label>
|
||||
<Expander summary={<FormatBalance className='summary' value={balancesAll?.votingBalance} />}>
|
||||
<div className='body column'>
|
||||
{allItems}
|
||||
@ -449,7 +448,6 @@ export default withMulti(
|
||||
justify-content: start;
|
||||
|
||||
&.column--expander {
|
||||
text-align: left;
|
||||
width: 15rem;
|
||||
|
||||
.ui--Expander.isExpanded {
|
||||
|
||||
@ -79,9 +79,12 @@ function LinkExternal ({ className, data, hash, type, withShort }: Props): React
|
||||
}
|
||||
|
||||
export default React.memo(styled(LinkExternal)`
|
||||
margin-top: 0.75rem;
|
||||
text-align: right;
|
||||
|
||||
&:not(.withShort) {
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
|
||||
> div {
|
||||
display: block;
|
||||
whitespace: nowrap;
|
||||
|
||||
@ -53,10 +53,28 @@ const Memo = React.memo(styled(Table)`
|
||||
margin-bottom: 1.5rem;
|
||||
|
||||
table {
|
||||
border-collapse: separate;
|
||||
border-spacing: 0 0.25rem;
|
||||
border: 1px solid #f2f2f2;
|
||||
border-radius: 0.25rem;
|
||||
border-spacing: 0;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
|
||||
tr+tr td {
|
||||
border-top: 1px solid #f2f2f2;
|
||||
}
|
||||
|
||||
thead tr {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
tbody tr {
|
||||
background: white;
|
||||
|
||||
&:first-child td {
|
||||
border-top: 1px solid #e6e6e6;
|
||||
}
|
||||
}
|
||||
|
||||
tr {
|
||||
width: 100%;
|
||||
|
||||
@ -94,6 +112,7 @@ const Memo = React.memo(styled(Table)`
|
||||
|
||||
td, th {
|
||||
padding: 0.5rem 0.75rem;
|
||||
vertical-align: middle;
|
||||
|
||||
&.all {
|
||||
width: 100%;
|
||||
@ -105,7 +124,6 @@ const Memo = React.memo(styled(Table)`
|
||||
|
||||
&.address {
|
||||
padding: 0.85rem 1rem;
|
||||
vertical-align: top;
|
||||
|
||||
> .ui--AddressMini,
|
||||
> .ui--AddressMini.padded {
|
||||
@ -119,6 +137,12 @@ const Memo = React.memo(styled(Table)`
|
||||
}
|
||||
}
|
||||
|
||||
&.button {
|
||||
text-align: right;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&.number {
|
||||
text-align: right;
|
||||
}
|
||||
@ -130,30 +154,9 @@ const Memo = React.memo(styled(Table)`
|
||||
&.toggle {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.top {
|
||||
vertical-align: top;
|
||||
|
||||
>.ui--AddressMini.padded:first-child {
|
||||
margin-top: -0.25rem;
|
||||
|
||||
.ui--AddressMini-label {
|
||||
margin-bottom: 0rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.padtop {
|
||||
padding-top: 1.1rem;
|
||||
}
|
||||
}
|
||||
|
||||
td {
|
||||
background: white;
|
||||
border: 1px solid #f2f2f2;
|
||||
border-left-width: 0;
|
||||
border-right-width: 0;
|
||||
|
||||
text-align: left;
|
||||
|
||||
label {
|
||||
@ -161,27 +164,13 @@ const Memo = React.memo(styled(Table)`
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
details > summary,
|
||||
details[open] > summary {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
i.icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.mini {
|
||||
padding: 0 0.75rem 0 0;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
border-left-width: 1px;
|
||||
border-radius: 0.25rem 0 0 0.25rem;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-right-width: 1px;
|
||||
border-radius: 0 0.25rem 0.25rem 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&.favorite i.icon.isSelected {
|
||||
@ -190,11 +179,11 @@ const Memo = React.memo(styled(Table)`
|
||||
}
|
||||
|
||||
th {
|
||||
background: #666;
|
||||
color: #eee;
|
||||
color: #888;
|
||||
font-family: sans-serif;
|
||||
font-weight: normal;
|
||||
font-weight: 600;
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
|
||||
&:first-child {
|
||||
border-top-left-radius: 0.25rem;
|
||||
@ -206,10 +195,11 @@ const Memo = React.memo(styled(Table)`
|
||||
|
||||
&.isClickable {
|
||||
cursor: pointer;
|
||||
border-bottom: 2px solid transparent;
|
||||
}
|
||||
|
||||
&.isSelected {
|
||||
background: #888;
|
||||
&.start {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { Label } from 'semantic-ui-react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import Tooltip from './Tooltip';
|
||||
|
||||
@ -39,4 +40,6 @@ function Tag ({ className, color, hover, label }: Props): React.ReactElement<Pro
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(Tag);
|
||||
export default React.memo(styled(Tag)`
|
||||
white-space: nowrap;
|
||||
`);
|
||||
|
||||
@ -205,7 +205,7 @@ export default createGlobalStyle<Props>`
|
||||
}
|
||||
}
|
||||
|
||||
h3, h4, h5 {
|
||||
h1, h2, h3, h4, h5 {
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user