Remove ote duplication on treasury (#3488)

This commit is contained in:
Jaco Greeff 2020-08-23 17:41:31 +02:00 committed by GitHub
parent 02c8a8b37f
commit 926aa6e1f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 23 additions and 182 deletions

View File

@ -3,7 +3,6 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { SubmittableExtrinsic } from '@polkadot/api/types';
import { DeriveCollectiveProposal } from '@polkadot/api-derive/types';
import { ProposalIndex } from '@polkadot/types/interfaces';
import React, { useEffect, useRef, useState } from 'react';
@ -14,7 +13,6 @@ import { useApi, useToggle } from '@polkadot/react-hooks';
import { useTranslation } from '../translate';
interface Props {
councilProposals: DeriveCollectiveProposal[];
id: ProposalIndex;
isDisabled: boolean;
members: string[];
@ -25,14 +23,13 @@ interface ProposalState {
proposalLength: number;
}
function Submission ({ councilProposals, id, isDisabled, members }: Props): React.ReactElement<Props> | null {
function Council ({ id, isDisabled, members }: Props): React.ReactElement<Props> | null {
const { t } = useTranslation();
const { api } = useApi();
const [isOpen, toggleOpen] = useToggle();
const [accountId, setAccountId] = useState<string | null>(null);
const [councilType, setCouncilType] = useState('reject');
const [{ proposal, proposalLength }, setProposal] = useState<ProposalState>({ proposalLength: 0 });
const [hasProposals, setHasProposals] = useState(true);
const threshold = Math.ceil((members?.length || 0) * getTreasuryThreshold(api));
@ -41,15 +38,6 @@ function Submission ({ councilProposals, id, isDisabled, members }: Props): Reac
{ text: t<string>('Rejection proposal to council'), value: 'reject' }
]);
useEffect((): void => {
setHasProposals(
!!councilProposals
.map(({ votes }) => votes ? votes.index.toNumber() : -1)
.filter((index) => index !== -1)
.length
);
}, [councilProposals]);
useEffect((): void => {
const proposal = councilType === 'reject'
? api.tx.treasury.rejectProposal(id)
@ -58,10 +46,6 @@ function Submission ({ councilProposals, id, isDisabled, members }: Props): Reac
setProposal({ proposal, proposalLength: proposal.length });
}, [api, councilType, id]);
if (hasProposals) {
return null;
}
return (
<>
{isOpen && (
@ -127,4 +111,4 @@ function Submission ({ councilProposals, id, isDisabled, members }: Props): Reac
);
}
export default React.memo(Submission);
export default React.memo(Council);

View File

@ -4,13 +4,13 @@
import { DeriveTreasuryProposal } from '@polkadot/api-derive/types';
import React from 'react';
import React, { useMemo } from 'react';
import { AddressMini, AddressSmall, LinkExternal } from '@polkadot/react-components';
import { FormatBalance } from '@polkadot/react-query';
import { formatNumber } from '@polkadot/util';
import Submission from './Submission';
import Voting from './Voting';
import { useTranslation } from '../translate';
import Council from './Council';
interface Props {
className?: string;
@ -21,7 +21,17 @@ interface Props {
withSend: boolean;
}
function ProposalDisplay ({ className = '', isMember, members, proposal: { council, id, proposal }, withSend }: Props): React.ReactElement<Props> | null {
function ProposalDisplay ({ className = '', isMember, members, proposal: { council, id, proposal }, withSend }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const hasProposals = useMemo(
() => !!council
.map(({ votes }) => votes ? votes.index.toNumber() : -1)
.filter((index) => index !== -1)
.length,
[council]
);
return (
<tr className={className}>
<td className='number'>
@ -39,22 +49,17 @@ function ProposalDisplay ({ className = '', isMember, members, proposal: { counc
<td className='number'>
<FormatBalance value={proposal.bond} />
</td>
<td className='button'>
{withSend && (
<>
<Submission
councilProposals={council}
<td className={hasProposals ? 'middle' : 'button'}>
{hasProposals
? <a href='#/council/motions'>{t('Voting')}</a>
: withSend && (
<Council
id={id}
isDisabled={!isMember}
members={members}
/>
<Voting
councilProposals={council}
isDisabled={!isMember}
members={members}
/>
</>
)}
)
}
</td>
<td className='mini'>
<LinkExternal

View File

@ -1,148 +0,0 @@
// Copyright 2017-2020 @polkadot/app-treasury 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 { DeriveCollectiveProposal } from '@polkadot/api-derive/types';
import { BlockNumber, Hash, ProposalIndex } from '@polkadot/types/interfaces';
import React, { useCallback, useEffect, useState } from 'react';
import { Button, Dropdown, Input, Modal, VoteAccount, VoteActions, VoteToggle } from '@polkadot/react-components';
import { useAccounts, useApi, useCall, useToggle } from '@polkadot/react-hooks';
import { isBoolean } from '@polkadot/util';
import { useTranslation } from '../translate';
interface CouncilInfo {
councilHash: Hash | null;
councilId: ProposalIndex | null;
}
interface Props {
councilProposals: DeriveCollectiveProposal[];
isDisabled?: boolean;
members: string[];
}
interface Option {
text: React.ReactNode;
value: number;
}
function Voting ({ councilProposals, isDisabled, members }: Props): React.ReactElement<Props> | null {
const { t } = useTranslation();
const { hasAccounts } = useAccounts();
const { api } = useApi();
const bestNumber = useCall<BlockNumber>(api.derive.chain.bestNumber);
const [councilOpts, setCouncilOpts] = useState<Option[]>([]);
const [councilOptId, setCouncilOptId] = useState<number>(0);
const [accountId, setAccountId] = useState<string | null>(null);
const [{ councilHash, councilId }, setCouncilInfo] = useState<CouncilInfo>({ councilHash: null, councilId: null });
const [isOpen, toggleOpen] = useToggle();
const [voteValue, setVoteValue] = useState(true);
useEffect((): void => {
isOpen && setVoteValue(true);
}, [isOpen]);
useEffect((): void => {
const available = councilProposals
.filter(({ votes }) => bestNumber && votes && (!votes.end || votes.end.gt(bestNumber)))
.map(({ proposal: { methodName, sectionName }, votes }): Option => ({
text: `Council #${votes?.index.toNumber() || '-'}: ${sectionName}.${methodName} `,
value: votes ? votes?.index.toNumber() : -1
}))
.filter(({ value }) => value !== -1);
setCouncilOptId(available.length ? available[0].value : 0);
setCouncilOpts(available);
}, [bestNumber, councilProposals]);
const _onChangeVote = useCallback(
(vote?: boolean) => setVoteValue(isBoolean(vote) ? vote : true),
[]
);
const _onChangeProposal = useCallback(
(optionId: number): void => {
const councilProp = councilProposals.find(({ votes }) => votes?.index.eq(optionId));
if (councilProp && councilProp.votes) {
setCouncilInfo({ councilHash: councilProp.hash, councilId: councilProp.votes.index });
setCouncilOptId(councilOptId);
} else {
setCouncilInfo({ councilHash: null, councilId: null });
}
},
[councilOptId, councilProposals]
);
if (!hasAccounts || !councilOpts.length) {
return null;
}
return (
<>
{isOpen && (
<Modal
header={t<string>('Vote on proposal')}
size='small'
>
<Modal.Content>
<Modal.Columns>
<Modal.Column>
<VoteAccount
filter={members}
onChange={setAccountId}
/>
</Modal.Column>
</Modal.Columns>
<Modal.Columns>
<Modal.Column>
<Dropdown
help={t<string>('The council proposal to make the vote on')}
label={t<string>('council proposal')}
onChange={_onChangeProposal}
options={councilOpts}
value={councilOptId}
/>
<Input
help={t<string>('The hash for the proposal this vote applies to')}
isDisabled
label={t<string>('proposal hash')}
value={councilHash?.toString()}
/>
</Modal.Column>
<Modal.Column>
<p>{t<string>('Multiple council proposals could exist, both approval and rejection. Apply your vote to the correct council proposal (also available on council motions page)')}</p>
</Modal.Column>
</Modal.Columns>
<Modal.Columns>
<Modal.Column>
<VoteToggle
onChange={_onChangeVote}
value={voteValue}
/>
</Modal.Column>
</Modal.Columns>
</Modal.Content>
<VoteActions
accountId={accountId}
aye={voteValue}
isDisabled={!councilHash}
onClick={toggleOpen}
params={[councilHash, councilId, voteValue]}
tx='council.vote'
/>
</Modal>
)}
<Button
icon='check'
isDisabled={isDisabled}
label={t<string>('Vote')}
onClick={toggleOpen}
/>
</>
);
}
export default React.memo(Voting);