Compact table markup (#2514)
* Compact table markup * Motions tweak * Small fixes
This commit is contained in:
parent
491ec94801
commit
b8df3dc8f4
@ -116,8 +116,9 @@ function Overview ({ className, onStatusChange }: Props): React.ReactElement<Pro
|
||||
</>
|
||||
)}
|
||||
</Button.Group>
|
||||
<Table>
|
||||
<Table.Head filter={
|
||||
<Table
|
||||
empty={t('no accounts yet, create or import an existing')}
|
||||
filter={
|
||||
<div className='filter--tags'>
|
||||
<Input
|
||||
autoFocus
|
||||
@ -127,30 +128,25 @@ function Overview ({ className, onStatusChange }: Props): React.ReactElement<Pro
|
||||
value={filter}
|
||||
/>
|
||||
</div>
|
||||
}>
|
||||
<th
|
||||
className='start'
|
||||
colSpan={3}
|
||||
>
|
||||
<h1>{t('accounts')}</h1>
|
||||
</th>
|
||||
<th>{t('type')}</th>
|
||||
<th className='start'>{t('tags')}</th>
|
||||
<th>{t('transactions')}</th>
|
||||
<th>{t('balances')}</th>
|
||||
<th colSpan={2}> </th>
|
||||
</Table.Head>
|
||||
<Table.Body empty={t('no accounts yet, create or import an existing')}>
|
||||
{sortedAccounts.map(({ address, isFavorite }): React.ReactNode => (
|
||||
<Account
|
||||
address={address}
|
||||
filter={filter}
|
||||
isFavorite={isFavorite}
|
||||
key={address}
|
||||
toggleFavorite={toggleFavorite}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
}
|
||||
header={[
|
||||
[t('accounts'), 'start', 3],
|
||||
[t('type')],
|
||||
[t('tags'), 'start'],
|
||||
[t('transactions')],
|
||||
[t('balances')],
|
||||
[undefined, undefined, 2]
|
||||
]}
|
||||
>
|
||||
{sortedAccounts.map(({ address, isFavorite }): React.ReactNode => (
|
||||
<Account
|
||||
address={address}
|
||||
filter={filter}
|
||||
isFavorite={isFavorite}
|
||||
key={address}
|
||||
toggleFavorite={toggleFavorite}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -54,8 +54,9 @@ function Overview ({ className, onStatusChange }: Props): React.ReactElement<Pro
|
||||
onStatusChange={onStatusChange}
|
||||
/>
|
||||
)}
|
||||
<Table>
|
||||
<Table.Head filter={
|
||||
<Table
|
||||
empty={t('no addresses saved yet, add any existing address')}
|
||||
filter={
|
||||
<div className='filter--tags'>
|
||||
<Input
|
||||
autoFocus
|
||||
@ -65,29 +66,24 @@ function Overview ({ className, onStatusChange }: Props): React.ReactElement<Pro
|
||||
value={filter}
|
||||
/>
|
||||
</div>
|
||||
}>
|
||||
<th
|
||||
className='start'
|
||||
colSpan={2}
|
||||
>
|
||||
<h1>{t('contacts')}</h1>
|
||||
</th>
|
||||
<th className='start'>{t('tags')}</th>
|
||||
<th>{t('transactions')}</th>
|
||||
<th>{t('balances')}</th>
|
||||
<th colSpan={2}> </th>
|
||||
</Table.Head>
|
||||
<Table.Body empty={t('no addresses saved yet, add any existing address')}>
|
||||
{sortedAddresses.map(({ address, isFavorite }): React.ReactNode => (
|
||||
<Address
|
||||
address={address}
|
||||
filter={filter}
|
||||
isFavorite={isFavorite}
|
||||
key={address}
|
||||
toggleFavorite={toggleFavorite}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
}
|
||||
header={[
|
||||
[t('contacts'), 'start', 2],
|
||||
[t('tags'), 'start'],
|
||||
[t('transactions')],
|
||||
[t('balances')],
|
||||
[undefined, undefined, 2]
|
||||
]}
|
||||
>
|
||||
{sortedAddresses.map(({ address, isFavorite }): React.ReactNode => (
|
||||
<Address
|
||||
address={address}
|
||||
filter={filter}
|
||||
isFavorite={isFavorite}
|
||||
key={address}
|
||||
toggleFavorite={toggleFavorite}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -44,26 +44,26 @@ function Proposals ({ className, motions, prime }: Props): React.ReactElement<Pr
|
||||
members={members}
|
||||
/>
|
||||
</Button.Group>
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th colSpan={2}> </th>
|
||||
<th>{t('threshold')}</th>
|
||||
<th>{t('voting end')}</th>
|
||||
<th className='address'>{t('aye')}</th>
|
||||
<th className='address'>{t('nay')}</th>
|
||||
<th colSpan={2}> </th>
|
||||
</Table.Head>
|
||||
<Table.Body empty={motions && t('No council motions')}>
|
||||
{motions?.map((motion: DeriveCollectiveProposal): React.ReactNode => (
|
||||
<Motion
|
||||
isMember={isMember}
|
||||
key={motion.hash.toHex()}
|
||||
members={members}
|
||||
motion={motion}
|
||||
prime={prime}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
<Table
|
||||
empty={motions && t('No council motions')}
|
||||
header={[
|
||||
[t('motions'), 'start', 2],
|
||||
[t('threshold')],
|
||||
[t('voting end')],
|
||||
[t('aye'), 'address'],
|
||||
[t('nay'), 'address'],
|
||||
[undefined, undefined, 2]
|
||||
]}
|
||||
>
|
||||
{motions?.map((motion: DeriveCollectiveProposal): React.ReactNode => (
|
||||
<Motion
|
||||
isMember={isMember}
|
||||
key={motion.hash.toHex()}
|
||||
members={members}
|
||||
motion={motion}
|
||||
prime={prime}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -21,46 +21,36 @@ function Candidates ({ allVotes = {}, electionsInfo }: Props): React.ReactElemen
|
||||
|
||||
return (
|
||||
<>
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th
|
||||
className='start'
|
||||
colSpan={2}
|
||||
>
|
||||
<h1>{t('runners up')}</h1>
|
||||
</th>
|
||||
<th>{t('backing')}</th>
|
||||
</Table.Head>
|
||||
<Table.Body empty={electionsInfo && t('No runners up found')}>
|
||||
{electionsInfo?.runnersUp.map(([accountId, balance]): React.ReactNode => (
|
||||
<Candidate
|
||||
address={accountId}
|
||||
balance={balance}
|
||||
key={accountId.toString()}
|
||||
voters={allVotes[accountId.toString()]}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
<Table
|
||||
empty={electionsInfo && t('No runners up found')}
|
||||
header={[
|
||||
[t('runners up'), 'start', 2],
|
||||
[t('backing')]
|
||||
]}
|
||||
>
|
||||
{electionsInfo?.runnersUp.map(([accountId, balance]): React.ReactNode => (
|
||||
<Candidate
|
||||
address={accountId}
|
||||
balance={balance}
|
||||
key={accountId.toString()}
|
||||
voters={allVotes[accountId.toString()]}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th
|
||||
className='start'
|
||||
colSpan={2}
|
||||
>
|
||||
<h1>{t('candidates')}</h1>
|
||||
</th>
|
||||
<th>{t('backing')}</th>
|
||||
</Table.Head>
|
||||
<Table.Body empty={electionsInfo && t('No candidates found')}>
|
||||
{electionsInfo?.candidates.map((accountId): React.ReactNode => (
|
||||
<Candidate
|
||||
address={accountId}
|
||||
key={accountId.toString()}
|
||||
voters={allVotes[accountId.toString()]}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
<Table
|
||||
empty={electionsInfo && t('No candidates found')}
|
||||
header={[
|
||||
[t('candidates'), 'start', 2],
|
||||
[t('backing')]
|
||||
]}
|
||||
>
|
||||
{electionsInfo?.candidates.map((accountId): React.ReactNode => (
|
||||
<Candidate
|
||||
address={accountId}
|
||||
key={accountId.toString()}
|
||||
voters={allVotes[accountId.toString()]}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
</>
|
||||
);
|
||||
|
||||
@ -21,27 +21,23 @@ function Members ({ allVotes = {}, className, electionsInfo, prime }: Props): Re
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Table className={className}>
|
||||
<Table.Head>
|
||||
<th
|
||||
className='start'
|
||||
colSpan={2}
|
||||
>
|
||||
<h1>{t('members')}</h1>
|
||||
</th>
|
||||
<th>{t('backing')}</th>
|
||||
</Table.Head>
|
||||
<Table.Body empty={electionsInfo && t('No members found')}>
|
||||
{electionsInfo?.members.map(([accountId, balance]): React.ReactNode => (
|
||||
<Candidate
|
||||
address={accountId}
|
||||
balance={balance}
|
||||
isPrime={prime?.eq(accountId)}
|
||||
key={accountId.toString()}
|
||||
voters={allVotes[accountId.toString()]}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
<Table
|
||||
className={className}
|
||||
empty={electionsInfo && t('No members found')}
|
||||
header={[
|
||||
[t('members'), 'start', 2],
|
||||
[t('backing')]
|
||||
]}
|
||||
>
|
||||
{electionsInfo?.members.map(([accountId, balance]): React.ReactNode => (
|
||||
<Candidate
|
||||
address={accountId}
|
||||
balance={balance}
|
||||
isPrime={prime?.eq(accountId)}
|
||||
key={accountId.toString()}
|
||||
voters={allVotes[accountId.toString()]}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
@ -21,25 +21,21 @@ function DispatchQueue ({ className }: Props): React.ReactElement<Props> | null
|
||||
const queued = useCall<DeriveDispatch[]>(api.derive.democracy.dispatchQueue as any, []);
|
||||
|
||||
return (
|
||||
<Table className={className}>
|
||||
<Table.Head>
|
||||
<th
|
||||
className='start'
|
||||
colSpan={2}
|
||||
>
|
||||
<h1>{t('dispatch queue')}</h1>
|
||||
</th>
|
||||
<th>{t('enact')}</th>
|
||||
<th colSpan={2}> </th>
|
||||
</Table.Head>
|
||||
<Table.Body empty={queued && t('Nothing queued for execution')}>
|
||||
{queued?.map((entry): React.ReactNode => (
|
||||
<DispatchEntry
|
||||
key={entry.index.toString()}
|
||||
value={entry}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
<Table
|
||||
className={className}
|
||||
empty={queued && t('Nothing queued for execution')}
|
||||
header={[
|
||||
[t('dispatch queue'), 'start', 2],
|
||||
[t('enact')],
|
||||
[undefined, undefined, 2]
|
||||
]}
|
||||
>
|
||||
{queued?.map((entry): React.ReactNode => (
|
||||
<DispatchEntry
|
||||
key={entry.index.toString()}
|
||||
value={entry}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
@ -21,19 +21,18 @@ function Externals ({ className }: Props): React.ReactElement<Props> | null {
|
||||
const external = useCall<DeriveProposalExternal | null>(api.derive.democracy.nextExternal, []);
|
||||
|
||||
return (
|
||||
<div className={`proposalSection ${className}`}>
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th className='start'><h1>{t('external')}</h1></th>
|
||||
<th className='address'>{t('proposer')}</th>
|
||||
<th>{t('locked')}</th>
|
||||
<th> </th>
|
||||
</Table.Head>
|
||||
<Table.Body empty={external === null && t('No external proposal')}>
|
||||
{external && <External value={external} />}
|
||||
</Table.Body>
|
||||
</Table>
|
||||
</div>
|
||||
<Table
|
||||
className={className}
|
||||
empty={external === null && t('No external proposal')}
|
||||
header={[
|
||||
[t('external'), 'start'],
|
||||
[t('proposer'), 'address'],
|
||||
[t('locked')],
|
||||
[]
|
||||
]}
|
||||
>
|
||||
{external && <External value={external} />}
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -21,26 +21,22 @@ function Proposals ({ className }: Props): React.ReactElement<Props> {
|
||||
const proposals = useCall<DeriveProposal[]>(api.derive.democracy.proposals, []);
|
||||
|
||||
return (
|
||||
<Table className={className}>
|
||||
<Table.Head>
|
||||
<th
|
||||
className='start'
|
||||
colSpan={2}
|
||||
>
|
||||
<h1>{t('proposals')}</h1>
|
||||
</th>
|
||||
<th className='address'>{t('proposer')}</th>
|
||||
<th>{t('locked')}</th>
|
||||
<th colSpan={3}> </th>
|
||||
</Table.Head>
|
||||
<Table.Body empty={proposals && t('No active proposals')}>
|
||||
{proposals?.map((proposal): React.ReactNode => (
|
||||
<ProposalDisplay
|
||||
key={proposal.index.toString()}
|
||||
value={proposal}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
<Table
|
||||
className={className}
|
||||
empty={proposals && t('No active proposals')}
|
||||
header={[
|
||||
[t('proposals'), 'start', 2],
|
||||
[t('proposer'), 'address'],
|
||||
[t('locked')],
|
||||
[undefined, undefined, 3]
|
||||
]}
|
||||
>
|
||||
{proposals?.map((proposal): React.ReactNode => (
|
||||
<ProposalDisplay
|
||||
key={proposal.index.toString()}
|
||||
value={proposal}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
@ -21,28 +21,24 @@ function Referendums ({ className }: Props): React.ReactElement<Props> {
|
||||
const referendums = useCall<DeriveReferendumExt[]>(api.derive.democracy.referendums, []);
|
||||
|
||||
return (
|
||||
<Table className={className}>
|
||||
<Table.Head>
|
||||
<th
|
||||
className='start'
|
||||
colSpan={2}
|
||||
>
|
||||
<h1>{t('referenda')}</h1>
|
||||
</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 empty={referendums && t('No active referendums')}>
|
||||
{referendums?.map((referendum): React.ReactNode => (
|
||||
<Referendum
|
||||
key={referendum.index.toString()}
|
||||
value={referendum}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
<Table
|
||||
className={className}
|
||||
empty={referendums && t('No active referendums')}
|
||||
header={[
|
||||
[t('referenda'), 'start', 2],
|
||||
[t('remaining')],
|
||||
[t('activate')],
|
||||
[t('aye')],
|
||||
[t('nay')],
|
||||
[undefined, undefined, 3]
|
||||
]}
|
||||
>
|
||||
{referendums?.map((referendum): React.ReactNode => (
|
||||
<Referendum
|
||||
key={referendum.index.toString()}
|
||||
value={referendum}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
@ -17,25 +17,20 @@ function BlockHeaders ({ headers }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th
|
||||
className='start'
|
||||
colSpan={3}
|
||||
>
|
||||
<h1>{t('recent blocks')}</h1>
|
||||
</th>
|
||||
</Table.Head>
|
||||
<Table.Body empty={t('No blocks available')}>
|
||||
{headers
|
||||
.filter((header) => !!header)
|
||||
.map((header): React.ReactNode => (
|
||||
<BlockHeader
|
||||
key={header.number.toString()}
|
||||
value={header}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
<Table
|
||||
empty={t('No blocks available')}
|
||||
header={[
|
||||
[t('recent blocks'), 'start', 3]
|
||||
]}
|
||||
>
|
||||
{headers
|
||||
.filter((header) => !!header)
|
||||
.map((header): React.ReactNode => (
|
||||
<BlockHeader
|
||||
key={header.number.toString()}
|
||||
value={header}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
@ -33,41 +33,36 @@ function BlockByHash ({ className, value }: Props): React.ReactElement<Props> {
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<Table isFixed>
|
||||
<Table.Head>
|
||||
<th
|
||||
className='start'
|
||||
colSpan={getHeader ? 1 : 6}
|
||||
>
|
||||
<h1>{blockNumber ? formatNumber(blockNumber) : '...'}</h1>
|
||||
</th>
|
||||
{getHeader && (
|
||||
<>
|
||||
<th className='start'>{t('hash')}</th>
|
||||
<th className='start'>{t('parent')}</th>
|
||||
<th className='start'>{t('extrinsics')}</th>
|
||||
<th className='start'>{t('state')}</th>
|
||||
<th> </th>
|
||||
</>
|
||||
)}
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
{getBlock && !getBlock.isEmpty && getHeader && !getHeader.isEmpty && (
|
||||
<tr>
|
||||
<td className='address'>{getHeader.author && <AddressMini value={getHeader.author} />}</td>
|
||||
<td className='hash overflow'>{getHeader.hash.toHex()}</td>
|
||||
<td className='hash overflow'><Link to={`/explorer/query/${parentHash}`}>{parentHash}</Link></td>
|
||||
<td className='hash overflow'>{getHeader.extrinsicsRoot.toHex()}</td>
|
||||
<td className='hash overflow'>{getHeader.stateRoot.toHex()}</td>
|
||||
<td>
|
||||
<LinkExternal
|
||||
data={value}
|
||||
type='block'
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</Table.Body>
|
||||
<Table
|
||||
header={
|
||||
getHeader
|
||||
? [
|
||||
[formatNumber(blockNumber), 'start', 1],
|
||||
[t('hash'), 'start'],
|
||||
[t('parent'), 'start'],
|
||||
[t('extrinsics'), 'start'],
|
||||
[t('state'), 'start'],
|
||||
[]
|
||||
]
|
||||
: [['...', 'start', 6]]
|
||||
}
|
||||
isFixed
|
||||
>
|
||||
{getBlock && !getBlock.isEmpty && getHeader && !getHeader.isEmpty && (
|
||||
<tr>
|
||||
<td className='address'>{getHeader.author && <AddressMini value={getHeader.author} />}</td>
|
||||
<td className='hash overflow'>{getHeader.hash.toHex()}</td>
|
||||
<td className='hash overflow'><Link to={`/explorer/query/${parentHash}`}>{parentHash}</Link></td>
|
||||
<td className='hash overflow'>{getHeader.extrinsicsRoot.toHex()}</td>
|
||||
<td className='hash overflow'>{getHeader.stateRoot.toHex()}</td>
|
||||
<td>
|
||||
<LinkExternal
|
||||
data={value}
|
||||
type='block'
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</Table>
|
||||
{getBlock && getHeader && (
|
||||
<>
|
||||
|
||||
@ -24,34 +24,23 @@ function Extrinsics ({ blockNumber, className, events, label, value }: Props): R
|
||||
return (
|
||||
<Table
|
||||
className={className}
|
||||
empty={t('No pending extrinsics are in the queue')}
|
||||
header={[
|
||||
[label || t('extrinsics'), 'start', 2],
|
||||
[t('events'), 'start', 2],
|
||||
[t('signer'), 'address']
|
||||
]}
|
||||
isFixed
|
||||
>
|
||||
<Table.Head>
|
||||
<th
|
||||
className='start'
|
||||
colSpan={2}
|
||||
>
|
||||
<h1>{label || t('extrinsics')}</h1>
|
||||
</th>
|
||||
<th
|
||||
className='start'
|
||||
colSpan={2}
|
||||
>
|
||||
{t('events')}
|
||||
</th>
|
||||
<th className='address'>{t('signer')}</th>
|
||||
</Table.Head>
|
||||
<Table.Body empty={t('No pending extrinsics are in the queue')}>
|
||||
{value?.map((extrinsic, index): React.ReactNode =>
|
||||
<ExtrinsicDisplay
|
||||
blockNumber={blockNumber}
|
||||
events={events}
|
||||
index={index}
|
||||
key={`extrinsic:${index}`}
|
||||
value={extrinsic}
|
||||
/>
|
||||
)}
|
||||
</Table.Body>
|
||||
{value?.map((extrinsic, index): React.ReactNode =>
|
||||
<ExtrinsicDisplay
|
||||
blockNumber={blockNumber}
|
||||
events={events}
|
||||
index={index}
|
||||
key={`extrinsic:${index}`}
|
||||
value={extrinsic}
|
||||
/>
|
||||
)}
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
@ -104,21 +104,19 @@ function Logs (props: Props): React.ReactElement<Props> | null {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th className='start'><h1>{t('logs')}</h1></th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
{value?.map((log, index) => (
|
||||
<tr key={`log:${index}`}>
|
||||
<td className='overflow'>
|
||||
<Expander summary={log.type.toString()}>
|
||||
{formatItem(log)}
|
||||
</Expander>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</Table.Body>
|
||||
<Table
|
||||
empty={t('No logs available')}
|
||||
header={[[t('logs'), 'start']]}
|
||||
>
|
||||
{value?.map((log, index) => (
|
||||
<tr key={`log:${index}`}>
|
||||
<td className='overflow'>
|
||||
<Expander summary={log.type.toString()}>
|
||||
{formatItem(log)}
|
||||
</Expander>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
@ -21,25 +21,25 @@ function Events ({ emptyLabel, eventClassName, events, label }: Props): React.Re
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th className='start'><h1>{label || t('recent events')}</h1></th>
|
||||
</Table.Head>
|
||||
<Table.Body empty={emptyLabel || t('No events available')}>
|
||||
{events
|
||||
.filter(({ event: { method, section } }): boolean => !!method && !!section)
|
||||
.map((event: EventRecord, index): React.ReactNode => (
|
||||
<tr
|
||||
className={eventClassName}
|
||||
key={`event:${index}`}
|
||||
>
|
||||
<td className='overflow'>
|
||||
<Event value={event} />
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
}
|
||||
</Table.Body>
|
||||
<Table
|
||||
empty={emptyLabel || t('No events available')}
|
||||
header={[
|
||||
[label || t('recent events'), 'start']
|
||||
]}
|
||||
>
|
||||
{events
|
||||
.filter(({ event: { method, section } }): boolean => !!method && !!section)
|
||||
.map((event: EventRecord, index): React.ReactNode => (
|
||||
<tr
|
||||
className={eventClassName}
|
||||
key={`event:${index}`}
|
||||
>
|
||||
<td className='overflow'>
|
||||
<Event value={event} />
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
}
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
@ -19,23 +19,24 @@ function Peers ({ className, peers }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Table className={className}>
|
||||
<Table.Head>
|
||||
<th className='start'><h1>{t('connected peers')}</h1></th>
|
||||
<th className='start'>{t('role')}</th>
|
||||
<th className='number'>{t('best #')}</th>
|
||||
<th className='start'>{t('best hash')}</th>
|
||||
</Table.Head>
|
||||
<Table.Body empty={t('no peers connected')}>
|
||||
{peers?.sort((a, b): number => b.bestNumber.cmp(a.bestNumber)).map((peer) => (
|
||||
<tr key={peer.peerId.toString()}>
|
||||
<td className='hash'>{peer.peerId.toString()}</td>
|
||||
<td>{peer.roles.toString().toLowerCase()}</td>
|
||||
<td className='number all'>{formatNumber(peer.bestNumber)}</td>
|
||||
<td className='hash'>{peer.bestHash.toHex()}</td>
|
||||
</tr>
|
||||
))}
|
||||
</Table.Body>
|
||||
<Table
|
||||
className={className}
|
||||
empty={t('no peers connected')}
|
||||
header={[
|
||||
[t('connected peers'), 'start'],
|
||||
[t('role'), 'start'],
|
||||
[t('best #'), 'number'],
|
||||
[t('best hash'), 'hash']
|
||||
]}
|
||||
>
|
||||
{peers?.sort((a, b): number => b.bestNumber.cmp(a.bestNumber)).map((peer) => (
|
||||
<tr key={peer.peerId.toString()}>
|
||||
<td className='hash'>{peer.peerId.toString()}</td>
|
||||
<td>{peer.roles.toString().toLowerCase()}</td>
|
||||
<td className='number all'>{formatNumber(peer.bestNumber)}</td>
|
||||
<td className='hash'>{peer.bestHash.toHex()}</td>
|
||||
</tr>
|
||||
))}
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
@ -19,28 +19,25 @@ 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
|
||||
key={parachain.id.toString()}
|
||||
parachain={parachain}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
<Table
|
||||
header={[
|
||||
[t('parachains'), 'start', 4],
|
||||
[t('swap to id')],
|
||||
[t('scheduling')]
|
||||
]}
|
||||
>
|
||||
{parachains.map((parachain): React.ReactNode => (
|
||||
<Parachain
|
||||
key={parachain.id.toString()}
|
||||
parachain={parachain}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(styled(Parachains)`
|
||||
tbody {
|
||||
tr {
|
||||
cursor: pointer;
|
||||
}
|
||||
tbody tr {
|
||||
cursor: pointer;
|
||||
}
|
||||
`);
|
||||
|
||||
@ -21,20 +21,21 @@ function Bids ({ className }: Props): React.ReactElement<Props> {
|
||||
const bids = useCall<Bid[]>(api.query.society.bids, []);
|
||||
|
||||
return (
|
||||
<Table className={className}>
|
||||
<Table.Head>
|
||||
<th className='start'><h1>{t('bids')}</h1></th>
|
||||
<th>{t('kind')}</th>
|
||||
<th>{t('value')}</th>
|
||||
</Table.Head>
|
||||
<Table.Body empty={bids && t('No bids')}>
|
||||
{bids?.map((bid): React.ReactNode => (
|
||||
<BidRow
|
||||
key={bid.who.toString()}
|
||||
value={bid}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
<Table
|
||||
className={className}
|
||||
empty={bids && t('No bids')}
|
||||
header={[
|
||||
[t('bids'), 'start'],
|
||||
[t('kind')],
|
||||
[t('value')]
|
||||
]}
|
||||
>
|
||||
{bids?.map((bid): React.ReactNode => (
|
||||
<BidRow
|
||||
key={bid.who.toString()}
|
||||
value={bid}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
@ -22,25 +22,25 @@ function Candidates ({ allMembers, className, isMember, ownMembers }: Props): Re
|
||||
const candidates = useCall<DeriveSocietyCandidate[]>(api.derive.society.candidates, []);
|
||||
|
||||
return (
|
||||
<Table className={className}>
|
||||
<Table.Head>
|
||||
<th className='start'><h1>{t('candidates')}</h1></th>
|
||||
<th>{t('kind')}</th>
|
||||
<th>{t('value')}</th>
|
||||
<th className='start'>{t('votes')}</th>
|
||||
<th> </th>
|
||||
</Table.Head>
|
||||
<Table.Body empty={candidates && t('No candidates')}>
|
||||
{candidates?.map((candidate): React.ReactNode => (
|
||||
<Candidate
|
||||
allMembers={allMembers}
|
||||
isMember={isMember}
|
||||
key={candidate.accountId.toString()}
|
||||
ownMembers={ownMembers}
|
||||
value={candidate}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
<Table
|
||||
className={className}
|
||||
empty={candidates && t('No candidates')}
|
||||
header={[
|
||||
[t('candidates'), 'start'],
|
||||
[t('kind')],
|
||||
[t('value')],
|
||||
[t('votes'), 'start']
|
||||
]}
|
||||
>
|
||||
{candidates?.map((candidate): React.ReactNode => (
|
||||
<Candidate
|
||||
allMembers={allMembers}
|
||||
isMember={isMember}
|
||||
key={candidate.accountId.toString()}
|
||||
ownMembers={ownMembers}
|
||||
value={candidate}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
@ -34,26 +34,26 @@ function Defender ({ className, info, isMember, ownMembers }: Props): React.Reac
|
||||
}
|
||||
|
||||
return (
|
||||
<Table className={className}>
|
||||
<Table.Head>
|
||||
<th className='start'><h1>{t('defender')}</h1></th>
|
||||
<th className='start'>{t('votes')}</th>
|
||||
<th> </th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
<tr>
|
||||
<td className='address all'>
|
||||
<AddressSmall value={info.defender} />
|
||||
</td>
|
||||
<Votes votes={votes} />
|
||||
<td className='button'>
|
||||
<DefenderVoting
|
||||
isMember={isMember}
|
||||
ownMembers={ownMembers}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</Table.Body>
|
||||
<Table
|
||||
className={className}
|
||||
header={[
|
||||
[t('defender'), 'start'],
|
||||
[t('votes'), 'start'],
|
||||
[]
|
||||
]}
|
||||
>
|
||||
<tr>
|
||||
<td className='address all'>
|
||||
<AddressSmall value={info.defender} />
|
||||
</td>
|
||||
<Votes votes={votes} />
|
||||
<td className='button'>
|
||||
<DefenderVoting
|
||||
isMember={isMember}
|
||||
ownMembers={ownMembers}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
@ -29,25 +29,21 @@ function Members ({ className, info }: Props): React.ReactElement<Props> {
|
||||
}, [info, members]);
|
||||
|
||||
return (
|
||||
<Table className={className}>
|
||||
<Table.Head>
|
||||
<th
|
||||
className='start'
|
||||
colSpan={3}
|
||||
>
|
||||
<h1>{t('members')}</h1>
|
||||
</th>
|
||||
<th>{t('strikes')}</th>
|
||||
</Table.Head>
|
||||
<Table.Body empty={info && t('No active members')}>
|
||||
{filtered.map((member): React.ReactNode => (
|
||||
<Member
|
||||
isHead={info?.head?.eq(member.accountId)}
|
||||
key={member.accountId.toString()}
|
||||
value={member}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
<Table
|
||||
className={className}
|
||||
empty={info && t('No active members')}
|
||||
header={[
|
||||
[t('members'), 'start', 3],
|
||||
[t('strikes')]
|
||||
]}
|
||||
>
|
||||
{filtered.map((member): React.ReactNode => (
|
||||
<Member
|
||||
isHead={info?.head?.eq(member.accountId)}
|
||||
key={member.accountId.toString()}
|
||||
value={member}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
@ -77,35 +77,30 @@ function Actions ({ allRewards, allStashes, className, isVisible, next, stakingO
|
||||
{isNewStakeOpen && (
|
||||
<StartStaking onClose={_toggleNewStake} />
|
||||
)}
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th
|
||||
className='start'
|
||||
colSpan={2}
|
||||
>
|
||||
<h1>{t('stashes')}</h1>
|
||||
</th>
|
||||
<th className='address'>{t('controller')}</th>
|
||||
<th className='number'>{t('rewards')}</th>
|
||||
<th className='number'>{t('bonded')}</th>
|
||||
<th colSpan={2}> </th>
|
||||
</Table.Head>
|
||||
<Table.Body empty={t('No funds staked yet. Bond funds to validate or nominate a validator.')}>
|
||||
{foundStashes?.map(([stashId, isOwnStash]): React.ReactNode => (
|
||||
<Account
|
||||
activeEra={activeEra}
|
||||
allStashes={allStashes}
|
||||
isOwnStash={isOwnStash}
|
||||
isVisible={isVisible}
|
||||
key={stashId}
|
||||
next={next}
|
||||
onUpdateType={_onUpdateType}
|
||||
rewards={allRewards && allRewards[stashId]}
|
||||
stakingOverview={stakingOverview}
|
||||
stashId={stashId}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
<Table
|
||||
empty={t('No funds staked yet. Bond funds to validate or nominate a validator')}
|
||||
header={[
|
||||
[t('stashes'), 'start', 2],
|
||||
[t('controller'), 'address'],
|
||||
[t('rewards'), 'number'],
|
||||
[t('bonded'), 'number'],
|
||||
[undefined, undefined, 2]
|
||||
]}
|
||||
>
|
||||
{foundStashes?.map(([stashId, isOwnStash]): React.ReactNode => (
|
||||
<Account
|
||||
activeEra={activeEra}
|
||||
allStashes={allStashes}
|
||||
isOwnStash={isOwnStash}
|
||||
isVisible={isVisible}
|
||||
key={stashId}
|
||||
next={next}
|
||||
onUpdateType={_onUpdateType}
|
||||
rewards={allRewards && allRewards[stashId]}
|
||||
stakingOverview={stakingOverview}
|
||||
stashId={stashId}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -136,24 +136,19 @@ function CurrentList ({ authorsMap, hasQueries, isIntentions, lastAuthors, next,
|
||||
|
||||
return isIntentions
|
||||
? (
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th
|
||||
className='start'
|
||||
colSpan={9}
|
||||
>
|
||||
<h1>{t('intentions')}</h1>
|
||||
</th>
|
||||
</Table.Head>
|
||||
<Table.Body empty={waiting && t('No waiting validators found')}>
|
||||
{_renderRows(elected, false).concat(..._renderRows(waiting, false))}
|
||||
{}
|
||||
</Table.Body>
|
||||
<Table
|
||||
empty={waiting && t('No waiting validators found')}
|
||||
header={[
|
||||
[t('intentions'), 'start', 9]
|
||||
]}
|
||||
>
|
||||
{_renderRows(elected, false).concat(..._renderRows(waiting, false))}
|
||||
</Table>
|
||||
)
|
||||
: (
|
||||
<Table>
|
||||
<Table.Head filter={
|
||||
<Table
|
||||
empty={validators && t('No active validators found')}
|
||||
filter={
|
||||
<Input
|
||||
autoFocus
|
||||
isFull
|
||||
@ -161,23 +156,18 @@ function CurrentList ({ authorsMap, hasQueries, isIntentions, lastAuthors, next,
|
||||
onChange={setNameFilter}
|
||||
value={nameFilter}
|
||||
/>
|
||||
}>
|
||||
<th
|
||||
className='start'
|
||||
colSpan={3}
|
||||
>
|
||||
<h1>{t('validators')}</h1>
|
||||
</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 empty={validators && t('No active validators found')}>
|
||||
{_renderRows(validators, true)}
|
||||
</Table.Body>
|
||||
}
|
||||
header={[
|
||||
[t('validators'), 'start', 3],
|
||||
[t('other stake')],
|
||||
[t('own stake')],
|
||||
[t('commission')],
|
||||
[t('points')],
|
||||
[t('last #')],
|
||||
[]
|
||||
]}
|
||||
>
|
||||
{_renderRows(validators, true)}
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
@ -219,8 +219,9 @@ function Targets ({ className }: Props): React.ReactElement<Props> {
|
||||
numValidators={validators.length}
|
||||
totalStaked={totalStaked}
|
||||
/>
|
||||
<Table>
|
||||
<Table.Head filter={
|
||||
<Table
|
||||
empty={sorted && t('No active validators to check for rewards available')}
|
||||
filter={
|
||||
<InputBalance
|
||||
className='balanceInput'
|
||||
help={t('The amount that will be used on a per-validator basis to calculate rewards for that validator.')}
|
||||
@ -229,31 +230,25 @@ function Targets ({ className }: Props): React.ReactElement<Props> {
|
||||
onChange={setAmount}
|
||||
value={_amount}
|
||||
/>
|
||||
}>
|
||||
<th
|
||||
className='start'
|
||||
colSpan={3}
|
||||
>
|
||||
<h1>{t('validators')}</h1>
|
||||
</th>
|
||||
{['rankComm', 'rankBondTotal', 'rankBondOwn', 'rankBondOther', 'rankOverall'].map((header): React.ReactNode => (
|
||||
<th
|
||||
className={`isClickable ${sortBy === header && 'ui--highlight--border'} number`}
|
||||
key={header}
|
||||
onClick={(): void => _sort(header as 'rankComm')}
|
||||
>{labels[header]}<Icon name={sortBy === header ? (sortFromMax ? 'chevron down' : 'chevron up') : 'minus'} /></th>
|
||||
))}
|
||||
<th> </th>
|
||||
</Table.Head>
|
||||
<Table.Body empty={sorted && t('No active validators to check for rewards available')}>
|
||||
{sorted?.map((info): React.ReactNode =>
|
||||
<Validator
|
||||
info={info}
|
||||
key={info.key}
|
||||
toggleFavorite={toggleFavorite}
|
||||
/>
|
||||
)}
|
||||
</Table.Body>
|
||||
}
|
||||
header={[
|
||||
[t('validators'), 'start', 3],
|
||||
...['rankComm', 'rankBondTotal', 'rankBondOwn', 'rankBondOther', 'rankOverall'].map((header) => [
|
||||
<>{labels[header]}<Icon name={sortBy === header ? (sortFromMax ? 'chevron down' : 'chevron up') : 'minus'} /></>,
|
||||
`isClickable ${sortBy === header && 'ui--highlight--border'} number`,
|
||||
1,
|
||||
(): void => _sort(header as 'rankComm')
|
||||
]),
|
||||
[]
|
||||
]}
|
||||
>
|
||||
{sorted?.map((info): React.ReactNode =>
|
||||
<Validator
|
||||
info={info}
|
||||
key={info.key}
|
||||
toggleFavorite={toggleFavorite}
|
||||
/>
|
||||
)}
|
||||
</Table>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -19,34 +19,30 @@ function Members ({ className, members, prime }: Props): React.ReactElement<Prop
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Table className={className}>
|
||||
<Table.Head>
|
||||
<th
|
||||
className='start'
|
||||
colSpan={3}
|
||||
>
|
||||
<h1>{t('members')}</h1>
|
||||
</th>
|
||||
</Table.Head>
|
||||
<Table.Body empty={members && t('No members found')}>
|
||||
{members?.map((accountId): React.ReactNode => (
|
||||
<tr key={accountId.toString()}>
|
||||
<td className='address'>
|
||||
<AddressSmall value={accountId} />
|
||||
</td>
|
||||
<td>
|
||||
{prime?.eq(accountId) && (
|
||||
<Tag
|
||||
color='green'
|
||||
hover={t('Committee prime member, default voting')}
|
||||
label={t('prime member')}
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td className='all'> </td>
|
||||
</tr>
|
||||
))}
|
||||
</Table.Body>
|
||||
<Table
|
||||
className={className}
|
||||
empty={members && t('No members found')}
|
||||
header={[
|
||||
[t('members'), 'start', 3]
|
||||
]}
|
||||
>
|
||||
{members?.map((accountId): React.ReactNode => (
|
||||
<tr key={accountId.toString()}>
|
||||
<td className='address'>
|
||||
<AddressSmall value={accountId} />
|
||||
</td>
|
||||
<td>
|
||||
{prime?.eq(accountId) && (
|
||||
<Tag
|
||||
color='green'
|
||||
hover={t('Committee prime member, default voting')}
|
||||
label={t('prime member')}
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td className='all'> </td>
|
||||
</tr>
|
||||
))}
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
@ -23,28 +23,23 @@ function Proposals ({ className, isMember, members, prime, proposals }: Props):
|
||||
members={members}
|
||||
/>
|
||||
</Button.Group>
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th
|
||||
className='start'
|
||||
colSpan={2}
|
||||
>
|
||||
<h1>{t('proposals')}</h1>
|
||||
</th>
|
||||
<th>{t('threshold')}</th>
|
||||
<th className='address'>{t('aye')}</th>
|
||||
<th className='address'>{t('nay')}</th>
|
||||
<th> </th>
|
||||
</Table.Head>
|
||||
<Table.Body empty={proposals && t('No committee proposals')}>
|
||||
{proposals?.map((hash: Hash): React.ReactNode => (
|
||||
<Proposal
|
||||
imageHash={hash.toHex()}
|
||||
key={hash.toHex()}
|
||||
prime={prime}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
<Table
|
||||
empty={proposals && t('No committee proposals')}
|
||||
header={[
|
||||
[t('proposals'), 'start', 2],
|
||||
[t('threshold')],
|
||||
[t('aye'), 'address'],
|
||||
[t('nay'), 'address'],
|
||||
[]
|
||||
]}
|
||||
>
|
||||
{proposals?.map((hash: Hash): React.ReactNode => (
|
||||
<Proposal
|
||||
imageHash={hash.toHex()}
|
||||
key={hash.toHex()}
|
||||
prime={prime}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -40,30 +40,26 @@ function ProposalsBase ({ className, isApprovals, proposals }: Props): React.Rea
|
||||
};
|
||||
|
||||
return (
|
||||
<Table className={className}>
|
||||
<Table.Head>
|
||||
<th
|
||||
className='start'
|
||||
colSpan={2}
|
||||
>
|
||||
<h1>{isApprovals ? t('Approved') : t('Proposals')}</h1>
|
||||
</th>
|
||||
<th className='address'>{t('beneficiary')}</th>
|
||||
<th>{t('payment')}</th>
|
||||
<th>{t('bond')}</th>
|
||||
<th colSpan={2}> </th>
|
||||
</Table.Head>
|
||||
<Table.Body empty={proposals && (isApprovals ? t('No approved proposals') : t('No pending proposals'))}>
|
||||
{proposals?.map((proposal): React.ReactNode => (
|
||||
<Proposal
|
||||
isMember={isMember}
|
||||
key={proposal.id.toString()}
|
||||
onRespond={_onRespond}
|
||||
proposal={proposal}
|
||||
withSend={!isApprovals}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
<Table
|
||||
className={className}
|
||||
empty={proposals && (isApprovals ? t('No approved proposals') : t('No pending proposals'))}
|
||||
header={[
|
||||
[isApprovals ? t('Approved') : t('Proposals'), 'start', 2],
|
||||
[t('beneficiary'), 'address'],
|
||||
[t('payment')],
|
||||
[t('bond')],
|
||||
[undefined, undefined, 2]
|
||||
]}
|
||||
>
|
||||
{proposals?.map((proposal): React.ReactNode => (
|
||||
<Proposal
|
||||
isMember={isMember}
|
||||
key={proposal.id.toString()}
|
||||
onRespond={_onRespond}
|
||||
proposal={proposal}
|
||||
withSend={!isApprovals}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
34
packages/react-components/src/Table/Body.tsx
Normal file
34
packages/react-components/src/Table/Body.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2017-2020 @polkadot/react-components authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import React from 'react';
|
||||
import { isString } from '@polkadot/util';
|
||||
|
||||
import Spinner from '../Spinner';
|
||||
|
||||
interface Props {
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
empty?: React.ReactNode;
|
||||
isEmpty?: boolean;
|
||||
}
|
||||
|
||||
function Body ({ children, className, empty, isEmpty }: Props): React.ReactElement<Props> {
|
||||
return (
|
||||
<tbody className={className}>
|
||||
{isEmpty
|
||||
? (
|
||||
<tr><td colSpan={100}>{
|
||||
isString(empty)
|
||||
? <div className='empty'>{empty}</div>
|
||||
: empty || <Spinner />
|
||||
}</td></tr>
|
||||
)
|
||||
: children
|
||||
}
|
||||
</tbody>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(Body);
|
||||
44
packages/react-components/src/Table/Head.tsx
Normal file
44
packages/react-components/src/Table/Head.tsx
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright 2017-2020 @polkadot/react-components authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import React from 'react';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
filter?: React.ReactNode;
|
||||
header: [React.ReactNode?, string?, number?, (() => void)?][];
|
||||
isEmpty: boolean;
|
||||
}
|
||||
|
||||
function Head ({ className, filter, header, isEmpty }: Props): React.ReactElement<Props> {
|
||||
return (
|
||||
<thead className={className}>
|
||||
{filter && (
|
||||
<tr className='filter'>
|
||||
<th colSpan={100}>{filter}</th>
|
||||
</tr>
|
||||
)}
|
||||
<tr>
|
||||
{header.map(([label, className = 'default', colSpan = 1, onClick], index) =>
|
||||
<th
|
||||
className={className}
|
||||
colSpan={colSpan}
|
||||
key={index}
|
||||
onClick={onClick}
|
||||
>
|
||||
{
|
||||
index === 0
|
||||
? <h1>{label}</h1>
|
||||
: isEmpty
|
||||
? ''
|
||||
: label
|
||||
}
|
||||
</th>
|
||||
)}
|
||||
</tr>
|
||||
</thead>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(Head);
|
||||
@ -4,77 +4,42 @@
|
||||
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { isString } from '@polkadot/util';
|
||||
|
||||
import Spinner from './Spinner';
|
||||
import Body from './Body';
|
||||
import Head from './Head';
|
||||
|
||||
interface BaseProps {
|
||||
interface TableProps {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
interface BodyProps extends BaseProps {
|
||||
empty?: React.ReactNode;
|
||||
}
|
||||
|
||||
interface HeadProps extends BaseProps {
|
||||
filter?: React.ReactNode;
|
||||
}
|
||||
|
||||
interface TableProps extends BaseProps {
|
||||
header: [React.ReactNode?, string?, number?, (() => void)?][];
|
||||
isFixed?: boolean;
|
||||
}
|
||||
|
||||
type TableImpl = React.FC<TableProps> & {
|
||||
Body: React.FC<BodyProps>;
|
||||
Head: React.FC<HeadProps>;
|
||||
}
|
||||
|
||||
function Head ({ children, className, filter }: HeadProps): React.ReactElement<HeadProps> {
|
||||
return (
|
||||
<thead className={className}>
|
||||
{filter && (
|
||||
<tr className='filter'>
|
||||
<th colSpan={100}>{filter}</th>
|
||||
</tr>
|
||||
)}
|
||||
<tr>
|
||||
{children}
|
||||
</tr>
|
||||
</thead>
|
||||
);
|
||||
}
|
||||
|
||||
function Body ({ children, className, empty }: BodyProps): React.ReactElement<BodyProps> {
|
||||
function Table ({ children, className, empty, filter, header, isFixed }: TableProps): React.ReactElement<TableProps> {
|
||||
const isEmpty = !children || (Array.isArray(children) && children.length === 0);
|
||||
|
||||
return (
|
||||
<tbody className={className}>
|
||||
{isEmpty
|
||||
? (
|
||||
<tr><td colSpan={100}>{
|
||||
isString(empty)
|
||||
? <div className='empty'>{empty}</div>
|
||||
: empty || <Spinner />
|
||||
}</td></tr>
|
||||
)
|
||||
: children
|
||||
}
|
||||
</tbody>
|
||||
);
|
||||
}
|
||||
|
||||
function Table ({ children, className, isFixed }: TableProps): React.ReactElement<TableProps> {
|
||||
return (
|
||||
<div className={`ui--Table ${isFixed && 'isFixed'} ${className}`}>
|
||||
<table>
|
||||
{children}
|
||||
<Head
|
||||
filter={filter}
|
||||
header={header}
|
||||
isEmpty={isEmpty}
|
||||
/>
|
||||
<Body
|
||||
empty={empty}
|
||||
isEmpty={isEmpty}
|
||||
>
|
||||
{children}
|
||||
</Body>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const Memo = React.memo(styled(Table)`
|
||||
export default React.memo(styled(Table)`
|
||||
margin-bottom: 1.5rem;
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
@ -293,9 +258,4 @@ const Memo = React.memo(styled(Table)`
|
||||
}
|
||||
}
|
||||
}
|
||||
`) as unknown as TableImpl;
|
||||
|
||||
Memo.Body = React.memo(Body);
|
||||
Memo.Head = React.memo(Head);
|
||||
|
||||
export default Memo;
|
||||
`);
|
||||
Loading…
Reference in New Issue
Block a user