Display turnout for poll (#3223)

This commit is contained in:
Jaco Greeff 2020-07-17 22:43:00 +02:00 committed by GitHub
parent c00ab64628
commit 826598c1b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 45 additions and 8 deletions

View File

@ -8,7 +8,7 @@ A Portal into the Polkadot and Substrate networks. Provides a view and interacti
This can be accessed as a hosted application via https://polkadot.js.org/apps/ or you can access the IPFS hosted version via https://polkadot.js.org/apps/ipfs (via hash) or https://dotapps.io (via ipns) to explore any of the supported Polkadot and Substrate chains.
If you run one or more IPFS node(s), pinning the UI (which only getes updated on releases) will make it faster for you and others. You can find details about that below in the IPFS chapter below.
If you run one or more IPFS node(s), pinning the UI (which only gets updated on releases) will make it faster for you and others. You can find details about that below in the IPFS chapter below.
**Important** If you are a chain developer and would like to add support for your chain to the UI, all the local configuration (API types, settings, logos) can be customized in [the apps-config package](packages/apps-config#README.md), complete with instructions of what goes where.

View File

@ -51,6 +51,7 @@ function QrModal ({ className = '', onClose, onStatusChange }: Props): React.Rea
const _onScan = useCallback(
(scanned: Scanned): void => {
setScanned(scanned);
const { content, genesisHash } = scanned;
setIsAddress(scanned.isAddress);

View File

@ -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 { Balance, BlockNumber } from '@polkadot/types/interfaces';
import { Approvals, Balance, BlockNumber } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import BN from 'bn.js';
@ -12,7 +12,7 @@ import styled from 'styled-components';
import { Button, Columar, InputAddress, Progress, Spinner, Toggle, TxButton } from '@polkadot/react-components';
import { useApi, useCall } from '@polkadot/react-hooks';
import { FormatBalance, BlockToTime } from '@polkadot/react-query';
import { BN_ONE, BN_ZERO, bnMax, formatNumber } from '@polkadot/util';
import { BN_ONE, BN_ZERO, bnMax, formatBalance, formatNumber } from '@polkadot/util';
import { useTranslation } from './translate';
@ -20,6 +20,11 @@ interface Props {
className?: string;
}
interface Turnout {
percentage: number;
voted: BN;
}
const DIV = new BN(1_000_000);
function PollApp ({ className }: Props): React.ReactElement<Props> {
@ -27,7 +32,9 @@ function PollApp ({ className }: Props): React.ReactElement<Props> {
const { api } = useApi();
const totals = useCall<ITuple<[Balance, Balance, Balance, Balance]>>(api.query.poll.totals, []);
const bestNumber = useCall<BlockNumber>(api.derive.chain.bestNumber, []);
const totalIssuance = useCall<Balance>(api.query.balances.totalIssuance, []);
const [accountId, setAccountId] = useState<string | null>(null);
const [turnout, setTurnout] = useState<Turnout | null>(null);
const [opt10m, setOpt10m] = useState(false);
const [opt100m, setOpt100m] = useState(false);
const [opt1b, setOpt1b] = useState(false);
@ -35,12 +42,22 @@ function PollApp ({ className }: Props): React.ReactElement<Props> {
const [progress, setProgress] = useState<BN[] | undefined>();
useEffect((): void => {
if (totals) {
if (totalIssuance && totals) {
const max = bnMax(BN_ONE, ...totals);
setProgress(totals.map((total) => total.mul(DIV).div(max)));
api.query.poll.voteOf
.entries<ITuple<[Approvals, Balance]>>()
.then((entries): void => {
const voted = entries.reduce((voted: BN, [, [, balance]]) => voted.iadd(balance), new BN(0));
const percentage = voted.muln(10_000).div(totalIssuance).toNumber() / 100;
setTurnout({ percentage, voted });
})
.catch(console.log);
}
}, [totals]);
}, [api, totalIssuance, totals]);
if (!totals || !progress || !bestNumber) {
return (
@ -52,6 +69,8 @@ function PollApp ({ className }: Props): React.ReactElement<Props> {
);
}
console.error(turnout);
const blocksLeft = (api.consts.poll.end as BlockNumber).sub(bestNumber);
const canVote = blocksLeft.gt(BN_ZERO);
const options: [string, string, boolean, (value: boolean) => void][] = [
@ -70,8 +89,16 @@ function PollApp ({ className }: Props): React.ReactElement<Props> {
<div className='pollHeader'>
<h1>{t('denomination vote')}</h1>
<div className='pollBlocksRight'>
{canVote && <BlockToTime blocks={blocksLeft} />}
<div>#{formatNumber(api.consts.poll.end as BlockNumber)}</div>
{turnout && (
<div>
<div>{t('{{balance}} voted', { replace: { balance: formatBalance(turnout.voted) } })}</div>
<div>{t('{{percentage}}% turnout', { replace: { percentage: turnout.percentage.toFixed(2) } })}</div>
</div>
)}
<div>
{canVote && <BlockToTime blocks={blocksLeft} />}
<div>#{formatNumber(api.consts.poll.end as BlockNumber)}</div>
</div>
</div>
</div>
<article className='keepAlive'>
@ -169,10 +196,19 @@ export default React.memo(styled(PollApp)`
.pollBlocksRight {
position: absolute;
right: 0.5rem;
right: 0;
text-align: right;
opacity: 0.75;
bottom: 0;
> div {
display: inline-block;
padding: 0 0.75rem;
&+div {
border-left: 1px solid #bbb;
}
}
}
.pollContainer {