Close on proposal failing (#2808)
This commit is contained in:
parent
332b076c8d
commit
c385a8afad
@ -2,20 +2,19 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId, BlockNumber, Votes } from '@polkadot/types/interfaces';
|
||||
import { AccountId } from '@polkadot/types/interfaces';
|
||||
import { DeriveCollectiveProposal } from '@polkadot/api-derive/types';
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { ApiPromise } from '@polkadot/api';
|
||||
import React from 'react';
|
||||
import ProposalCell from '@polkadot/app-democracy/Overview/ProposalCell';
|
||||
import { LinkExternal } from '@polkadot/react-components';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import { BlockToTime } from '@polkadot/react-query';
|
||||
import { formatNumber } from '@polkadot/util';
|
||||
|
||||
import Close from './Close';
|
||||
import Voters from './Votes';
|
||||
import Voting from './Voting';
|
||||
import useVotingStatus from './useVotingStatus';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
@ -25,44 +24,8 @@ interface Props {
|
||||
prime: AccountId | null;
|
||||
}
|
||||
|
||||
interface Status {
|
||||
isCloseable: boolean;
|
||||
isVotable: boolean;
|
||||
}
|
||||
|
||||
function getStatus (api: ApiPromise, bestNumber: BlockNumber, votes: Votes): Status {
|
||||
if (!votes.end) {
|
||||
return {
|
||||
isCloseable: false,
|
||||
isVotable: true
|
||||
};
|
||||
}
|
||||
|
||||
const isEnd = bestNumber.gte(votes.end);
|
||||
|
||||
if (api.tx.council.close.meta.args.length === 2) {
|
||||
return {
|
||||
isCloseable: isEnd,
|
||||
isVotable: !isEnd
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
isCloseable: isEnd || votes.threshold.eq(votes.ayes.length),
|
||||
isVotable: !isEnd
|
||||
};
|
||||
}
|
||||
|
||||
function Motion ({ className = '', isMember, members, motion: { hash, proposal, votes }, prime }: Props): React.ReactElement<Props> | null {
|
||||
const { api } = useApi();
|
||||
const bestNumber = useCall<BlockNumber>(api.derive.chain.bestNumber, []);
|
||||
const [{ isCloseable, isVotable }, setStatus] = useState<Status>({ isCloseable: false, isVotable: false });
|
||||
|
||||
useEffect((): void => {
|
||||
bestNumber && votes && setStatus(
|
||||
getStatus(api, bestNumber, votes)
|
||||
);
|
||||
}, [api, bestNumber, votes]);
|
||||
const { isCloseable, isVoteable, remainingBlocks } = useVotingStatus(votes, members.length);
|
||||
|
||||
if (!votes) {
|
||||
return null;
|
||||
@ -81,9 +44,9 @@ function Motion ({ className = '', isMember, members, motion: { hash, proposal,
|
||||
{formatNumber(ayes.length)}/{formatNumber(threshold)}
|
||||
</td>
|
||||
<td className='number together'>
|
||||
{bestNumber && end && (
|
||||
{remainingBlocks && end && (
|
||||
<>
|
||||
<BlockToTime blocks={end.sub(bestNumber)} />
|
||||
<BlockToTime blocks={remainingBlocks} />
|
||||
#{formatNumber(end)}
|
||||
</>
|
||||
)}
|
||||
@ -91,7 +54,7 @@ function Motion ({ className = '', isMember, members, motion: { hash, proposal,
|
||||
<Voters votes={ayes} />
|
||||
<Voters votes={nays} />
|
||||
<td className='button'>
|
||||
{isVotable && (
|
||||
{isVoteable && (
|
||||
<Voting
|
||||
hash={hash}
|
||||
idNumber={index}
|
||||
|
||||
54
packages/page-council/src/Motions/useVotingStatus.ts
Normal file
54
packages/page-council/src/Motions/useVotingStatus.ts
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2017-2020 @polkadot/app-democracy 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 { BlockNumber, Votes } from '@polkadot/types/interfaces';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { ApiPromise } from '@polkadot/api';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
|
||||
interface State {
|
||||
isCloseable: boolean;
|
||||
isVoteable: boolean;
|
||||
remainingBlocks: BN | null;
|
||||
}
|
||||
|
||||
function getStatus (api: ApiPromise, bestNumber: BlockNumber, votes: Votes, numMembers: number): State {
|
||||
if (!votes.end) {
|
||||
return {
|
||||
isCloseable: false,
|
||||
isVoteable: true,
|
||||
remainingBlocks: null
|
||||
};
|
||||
}
|
||||
|
||||
const isEnd = bestNumber.gte(votes.end);
|
||||
const isPassing = votes.threshold.lten(votes.ayes.length);
|
||||
const isFailing = votes.threshold.gtn(Math.abs(numMembers - votes.nays.length));
|
||||
|
||||
return {
|
||||
isCloseable: api.tx.council.close.meta.args.length === 2
|
||||
? isEnd
|
||||
: isEnd || isPassing || isFailing,
|
||||
isVoteable: !isEnd,
|
||||
remainingBlocks: isEnd
|
||||
? null
|
||||
: votes.end.sub(bestNumber)
|
||||
};
|
||||
}
|
||||
|
||||
export default function useVotingStatus (votes: Votes | null, numMembers: number): State {
|
||||
const { api } = useApi();
|
||||
const bestNumber = useCall<BlockNumber>(api.derive.chain.bestNumber, []);
|
||||
const [state, setState] = useState<State>({ isCloseable: false, isVoteable: false, remainingBlocks: null });
|
||||
|
||||
useEffect((): void => {
|
||||
bestNumber && votes && setState(
|
||||
getStatus(api, bestNumber, votes, numMembers)
|
||||
);
|
||||
}, [api, bestNumber, numMembers, votes]);
|
||||
|
||||
return state;
|
||||
}
|
||||
@ -22,14 +22,16 @@ interface Props {
|
||||
function Proposal ({ className = '', imageHash, prime }: Props): React.ReactElement<Props> | null {
|
||||
const { api } = useApi();
|
||||
const optProposal = useCall<Option<ProposalType>>(api.query.technicalCommittee.proposalOf, [imageHash]);
|
||||
const votes = useCall<Option<Votes>>(api.query.technicalCommittee.voting, [imageHash]);
|
||||
const votes = useCall<Votes | null>(api.query.technicalCommittee.voting, [imageHash], {
|
||||
transform: (optVotes: Option<Votes>) => optVotes.unwrapOr(null)
|
||||
});
|
||||
|
||||
if (!optProposal?.isSome || !votes?.isSome) {
|
||||
if (!optProposal?.isSome || !votes) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const proposal = optProposal.unwrap();
|
||||
const { ayes, index, nays, threshold } = votes.unwrap();
|
||||
const { ayes, index, nays, threshold } = votes;
|
||||
|
||||
return (
|
||||
<tr className={className}>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user