Rewok council voting display (#3067)

This commit is contained in:
Jaco Greeff 2020-06-27 14:33:59 +02:00 committed by GitHub
parent cd0e1a3040
commit dc8a77e1e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 81 additions and 19 deletions

View File

@ -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}

View File

@ -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>
);
}

View File

@ -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]);