Rewok council voting display (#3067)
This commit is contained in:
parent
cd0e1a3040
commit
dc8a77e1e4
@ -5,10 +5,10 @@
|
||||
import { AccountId } from '@polkadot/types/interfaces';
|
||||
import { DeriveCollectiveProposal } from '@polkadot/api-derive/types';
|
||||
|
||||
import React from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import ProposalCell from '@polkadot/app-democracy/Overview/ProposalCell';
|
||||
import { LinkExternal } from '@polkadot/react-components';
|
||||
import { useVotingStatus } from '@polkadot/react-hooks';
|
||||
import { Icon, LinkExternal } from '@polkadot/react-components';
|
||||
import { useAccounts, useVotingStatus } from '@polkadot/react-hooks';
|
||||
import { BlockToTime } from '@polkadot/react-query';
|
||||
import { formatNumber } from '@polkadot/util';
|
||||
|
||||
@ -24,8 +24,26 @@ interface Props {
|
||||
prime: AccountId | null;
|
||||
}
|
||||
|
||||
interface VoterState {
|
||||
hasVoted: boolean;
|
||||
hasVotedAye: boolean;
|
||||
}
|
||||
|
||||
function Motion ({ className = '', isMember, members, motion: { hash, proposal, votes }, prime }: Props): React.ReactElement<Props> | null {
|
||||
const { allAccounts } = useAccounts();
|
||||
const { hasFailed, isCloseable, isVoteable, remainingBlocks } = useVotingStatus(votes, members.length, 'council');
|
||||
const [{ hasVoted, hasVotedAye }, setIsVoter] = useState<VoterState>({ hasVoted: false, hasVotedAye: false });
|
||||
|
||||
useEffect((): void => {
|
||||
if (votes) {
|
||||
const hasVotedAye = allAccounts.some((address) => votes.ayes.some((accountId) => accountId.eq(address)));
|
||||
|
||||
setIsVoter({
|
||||
hasVoted: hasVotedAye || allAccounts.some((address) => votes.nays.some((accountId) => accountId.eq(address))),
|
||||
hasVotedAye
|
||||
});
|
||||
}
|
||||
}, [allAccounts, votes]);
|
||||
|
||||
if (!votes) {
|
||||
return null;
|
||||
@ -41,7 +59,7 @@ function Motion ({ className = '', isMember, members, motion: { hash, proposal,
|
||||
proposal={proposal}
|
||||
/>
|
||||
<td className='number together'>
|
||||
{formatNumber(ayes.length)}/{formatNumber(threshold)}
|
||||
{formatNumber(threshold)}
|
||||
</td>
|
||||
<td className='number together'>
|
||||
{remainingBlocks && end && (
|
||||
@ -51,8 +69,17 @@ function Motion ({ className = '', isMember, members, motion: { hash, proposal,
|
||||
</>
|
||||
)}
|
||||
</td>
|
||||
<Voters votes={ayes} />
|
||||
<Voters votes={nays} />
|
||||
<Voters
|
||||
isAye
|
||||
members={members}
|
||||
threshold={threshold}
|
||||
votes={ayes}
|
||||
/>
|
||||
<Voters
|
||||
members={members}
|
||||
threshold={threshold}
|
||||
votes={nays}
|
||||
/>
|
||||
<td className='button'>
|
||||
{isVoteable && !isCloseable && (
|
||||
<Voting
|
||||
@ -75,6 +102,14 @@ function Motion ({ className = '', isMember, members, motion: { hash, proposal,
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td className='badge'>
|
||||
{isVoteable && (
|
||||
<Icon
|
||||
color={hasVoted ? (hasVotedAye ? 'green' : 'red') : 'gray'}
|
||||
icon='asterisk'
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td className='mini'>
|
||||
<LinkExternal
|
||||
data={index}
|
||||
|
||||
@ -2,25 +2,51 @@
|
||||
// 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, MemberCount } from '@polkadot/types/interfaces';
|
||||
|
||||
import React from 'react';
|
||||
import { AddressMini } from '@polkadot/react-components';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { AddressMini, Expander } from '@polkadot/react-components';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
|
||||
interface Props {
|
||||
isAye?: boolean;
|
||||
members: string[];
|
||||
votes: AccountId[];
|
||||
threshold: MemberCount;
|
||||
}
|
||||
|
||||
function Votes ({ votes }: Props): React.ReactElement<Props> {
|
||||
function Votes ({ isAye, members, threshold, votes }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const [counter, setCounter] = useState('');
|
||||
|
||||
useEffect((): void => {
|
||||
const max = isAye
|
||||
? threshold.toNumber()
|
||||
: members.length - threshold.toNumber();
|
||||
|
||||
setCounter(`${votes.length}/${max}`);
|
||||
}, [isAye, members, threshold, votes]);
|
||||
|
||||
return (
|
||||
<td className='address'>
|
||||
{votes.map((address): React.ReactNode => (
|
||||
<AddressMini
|
||||
key={address.toString()}
|
||||
value={address}
|
||||
withBalance={false}
|
||||
/>
|
||||
))}
|
||||
{counter && votes.length !== 0 && (
|
||||
<Expander
|
||||
summary={
|
||||
isAye
|
||||
? t<string>('Aye {{counter}}', { replace: { counter } })
|
||||
: t<string>('Nay {{counter}}', { replace: { counter } })
|
||||
}
|
||||
>
|
||||
{votes.map((address): React.ReactNode => (
|
||||
<AddressMini
|
||||
key={address.toString()}
|
||||
value={address}
|
||||
withBalance={false}
|
||||
/>
|
||||
))}
|
||||
</Expander>
|
||||
)}
|
||||
</td>
|
||||
);
|
||||
}
|
||||
|
||||
@ -29,9 +29,10 @@ function Proposals ({ className = '', motions, prime }: Props): React.ReactEleme
|
||||
[t('motions'), 'start', 2],
|
||||
[t('threshold')],
|
||||
[t('voting end')],
|
||||
[t('aye'), 'address'],
|
||||
[t('nay'), 'address'],
|
||||
[undefined, 'address'],
|
||||
[undefined, 'address'],
|
||||
[],
|
||||
[undefined, 'badge'],
|
||||
[undefined, 'mini']
|
||||
], [t]);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user