Add ability to second proposals (#1150)
This commit is contained in:
parent
539e0fded5
commit
bc15fa8d79
@ -7,55 +7,61 @@ import { I18nProps } from '@polkadot/ui-app/types';
|
||||
import BN from 'bn.js';
|
||||
import React from 'react';
|
||||
import { AccountId, Balance, Option, Proposal, Tuple, Vector } from '@polkadot/types';
|
||||
import { AddressMini, Labelled, Static } from '@polkadot/ui-app';
|
||||
import { InputAddress, Labelled, Static } from '@polkadot/ui-app';
|
||||
import { withCalls, withMulti } from '@polkadot/ui-api';
|
||||
import { formatBalance } from '@polkadot/util';
|
||||
|
||||
import Item from './Item';
|
||||
import translate from '../translate';
|
||||
import Item from './Item';
|
||||
import Seconding from './Seconding';
|
||||
|
||||
type Props = I18nProps & {
|
||||
democracy_depositOf?: Option<Tuple>,
|
||||
democracy_depositOf?: [Balance, Vector<AccountId>] | null,
|
||||
idNumber: BN,
|
||||
value: Tuple
|
||||
value: Proposal
|
||||
};
|
||||
|
||||
class ProposalDisplay extends React.PureComponent<Props> {
|
||||
render () {
|
||||
const { idNumber, value } = this.props;
|
||||
const { democracy_depositOf, idNumber, value } = this.props;
|
||||
const depositors = democracy_depositOf
|
||||
? democracy_depositOf[1]
|
||||
: [];
|
||||
|
||||
return (
|
||||
<Item
|
||||
idNumber={idNumber}
|
||||
proposal={value[1] as Proposal}
|
||||
proposal={value}
|
||||
proposalExtra={this.renderExtra()}
|
||||
/>
|
||||
>
|
||||
<Seconding
|
||||
depositors={depositors}
|
||||
proposalId={idNumber}
|
||||
/>
|
||||
</Item>
|
||||
);
|
||||
}
|
||||
|
||||
private renderExtra () {
|
||||
const { democracy_depositOf, t } = this.props;
|
||||
|
||||
if (!democracy_depositOf || democracy_depositOf.isNone) {
|
||||
if (!democracy_depositOf) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const value = democracy_depositOf.unwrap();
|
||||
const balance = value[0] as Balance;
|
||||
const addresses = value[1] as Vector<AccountId>;
|
||||
const [balance, addresses] = democracy_depositOf;
|
||||
|
||||
return (
|
||||
<div className='democracy--Proposal-info'>
|
||||
<Labelled label={t('depositors')}>
|
||||
<div>
|
||||
{addresses.map((address, index) => (
|
||||
<AddressMini
|
||||
isPadded={false}
|
||||
key={`${index}:${address}`}
|
||||
value={address}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
{addresses.map((address, index) => (
|
||||
<InputAddress
|
||||
isDisabled
|
||||
key={`${index}:${address}`}
|
||||
value={address}
|
||||
withLabel={false}
|
||||
/>
|
||||
))}
|
||||
</Labelled>
|
||||
<Static label={t('balance')}>
|
||||
{formatBalance(balance)}
|
||||
@ -69,6 +75,10 @@ export default withMulti(
|
||||
ProposalDisplay,
|
||||
translate,
|
||||
withCalls<Props>(
|
||||
['query.democracy.depositOf', { paramName: 'idNumber' }]
|
||||
['query.democracy.depositOf', {
|
||||
paramName: 'idNumber',
|
||||
transform: (value: Option<Tuple>) =>
|
||||
value.unwrapOr(null)
|
||||
}]
|
||||
)
|
||||
);
|
||||
|
||||
@ -4,15 +4,16 @@
|
||||
|
||||
import { I18nProps } from '@polkadot/ui-app/types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import React from 'react';
|
||||
import { Tuple } from '@polkadot/types';
|
||||
import { Proposal } from '@polkadot/types';
|
||||
import { withCalls, withMulti } from '@polkadot/ui-api';
|
||||
|
||||
import Proposal from './Proposal';
|
||||
import ProposalDisplay from './Proposal';
|
||||
import translate from '../translate';
|
||||
|
||||
type Props = I18nProps & {
|
||||
democracy_publicProps?: Array<Tuple>
|
||||
democracy_publicProps?: Array<[BN, Proposal]>
|
||||
};
|
||||
|
||||
type State = {
|
||||
@ -48,10 +49,10 @@ class Proposals extends React.PureComponent<Props> {
|
||||
);
|
||||
}
|
||||
|
||||
return democracy_publicProps.map((proposal) => (
|
||||
<Proposal
|
||||
idNumber={proposal[0]}
|
||||
key={proposal[0].toString()}
|
||||
return democracy_publicProps.map(([idNumber, proposal]) => (
|
||||
<ProposalDisplay
|
||||
idNumber={idNumber}
|
||||
key={idNumber.toString()}
|
||||
value={proposal}
|
||||
/>
|
||||
));
|
||||
|
||||
73
packages/app-democracy/src/Overview/Seconding.tsx
Normal file
73
packages/app-democracy/src/Overview/Seconding.tsx
Normal file
@ -0,0 +1,73 @@
|
||||
// Copyright 2017-2019 @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 { I18nProps } from '@polkadot/ui-app/types';
|
||||
import { SubjectInfo } from '@polkadot/ui-keyring/observable/types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import React from 'react';
|
||||
import { AccountId } from '@polkadot/types';
|
||||
import { Button, InputAddress, TxButton } from '@polkadot/ui-app';
|
||||
import accountObservable from '@polkadot/ui-keyring/observable/accounts';
|
||||
import { withMulti, withObservable } from '@polkadot/ui-api';
|
||||
|
||||
import translate from '../translate';
|
||||
|
||||
type Props = I18nProps & {
|
||||
allAccounts?: SubjectInfo,
|
||||
depositors: Array<AccountId>,
|
||||
proposalId: BN | number
|
||||
};
|
||||
|
||||
type State = {
|
||||
accountId?: string
|
||||
};
|
||||
|
||||
class Seconding extends React.PureComponent<Props, State> {
|
||||
state: State = {};
|
||||
|
||||
render () {
|
||||
const { allAccounts, depositors, proposalId, t } = this.props;
|
||||
const { accountId } = this.state;
|
||||
const hasAccounts = allAccounts && Object.keys(allAccounts).length !== 0;
|
||||
|
||||
if (!hasAccounts) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const isDepositor = !!depositors.find((depositor) => depositor.eq(accountId));
|
||||
|
||||
return (
|
||||
<div className='democarcy--Proposal-second'>
|
||||
<InputAddress
|
||||
help={t('Select the account you wish to second with. This will lock your funds until the proposal is either approved or rejected')}
|
||||
label={t('using my account')}
|
||||
onChange={this.onChangeAccount}
|
||||
type='account'
|
||||
withLabel
|
||||
/>
|
||||
<Button.Group>
|
||||
<TxButton
|
||||
accountId={accountId}
|
||||
isDisabled={!accountId || isDepositor}
|
||||
isPrimary
|
||||
label={t('Second')}
|
||||
params={[proposalId]}
|
||||
tx='democracy.second'
|
||||
/>
|
||||
</Button.Group>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private onChangeAccount = (accountId?: string) => {
|
||||
this.setState({ accountId });
|
||||
}
|
||||
}
|
||||
|
||||
export default withMulti(
|
||||
Seconding,
|
||||
translate,
|
||||
withObservable(accountObservable.subject, { propName: 'allAccounts' })
|
||||
);
|
||||
@ -7,11 +7,10 @@ import { SubjectInfo } from '@polkadot/ui-keyring/observable/types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import React from 'react';
|
||||
import { InputAddress } from '@polkadot/ui-app';
|
||||
import { Button, InputAddress, TxButton } from '@polkadot/ui-app';
|
||||
import accountObservable from '@polkadot/ui-keyring/observable/accounts';
|
||||
import { withMulti, withObservable } from '@polkadot/ui-api';
|
||||
|
||||
import VotingButtons from './VotingButtons';
|
||||
import translate from '../translate';
|
||||
|
||||
type Props = I18nProps & {
|
||||
@ -23,11 +22,15 @@ type State = {
|
||||
accountId?: string
|
||||
};
|
||||
|
||||
const VOTE_NAY = 0;
|
||||
const VOTE_YAY = -1; // Yes, this is weird, but voting works on i8 with the high bit set
|
||||
|
||||
class Voting extends React.PureComponent<Props, State> {
|
||||
state: State = {};
|
||||
|
||||
render () {
|
||||
const { allAccounts, t } = this.props;
|
||||
const { allAccounts, referendumId, t } = this.props;
|
||||
const { accountId } = this.state;
|
||||
const hasAccounts = allAccounts && Object.keys(allAccounts).length !== 0;
|
||||
|
||||
if (!hasAccounts) {
|
||||
@ -38,33 +41,34 @@ class Voting extends React.PureComponent<Props, State> {
|
||||
<div className='democracy--Referendum-vote'>
|
||||
<InputAddress
|
||||
help={t('Select the account you wish to vote with. You can approve "yay" or deny "nay" the proposal.')}
|
||||
label={t('vote using my account')}
|
||||
label={t('using my account')}
|
||||
onChange={this.onChangeAccount}
|
||||
placeholder='0x...'
|
||||
type='account'
|
||||
withLabel
|
||||
/>
|
||||
{this.renderButtons()}
|
||||
<Button.Group>
|
||||
<TxButton
|
||||
accountId={accountId}
|
||||
isDisabled={!accountId}
|
||||
isNegative
|
||||
label={t('Nay')}
|
||||
params={[referendumId, VOTE_NAY]}
|
||||
tx='democracy.vote'
|
||||
/>
|
||||
<Button.Or />
|
||||
<TxButton
|
||||
accountId={accountId}
|
||||
isDisabled={!accountId}
|
||||
isPositive
|
||||
label={t('Aye')}
|
||||
params={[referendumId, VOTE_YAY]}
|
||||
tx='democracy.vote'
|
||||
/>
|
||||
</Button.Group>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private renderButtons () {
|
||||
const { referendumId } = this.props;
|
||||
const { accountId } = this.state;
|
||||
|
||||
if (!accountId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<VotingButtons
|
||||
accountId={accountId}
|
||||
referendumId={referendumId}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
private onChangeAccount = (accountId?: string) => {
|
||||
this.setState({ accountId });
|
||||
}
|
||||
|
||||
@ -1,55 +0,0 @@
|
||||
// Copyright 2017-2019 @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 { I18nProps } from '@polkadot/ui-app/types';
|
||||
import { ApiProps } from '@polkadot/ui-api/types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import React from 'react';
|
||||
import { Button, TxButton } from '@polkadot/ui-app';
|
||||
import { withApi, withMulti } from '@polkadot/ui-api';
|
||||
|
||||
import translate from '../translate';
|
||||
|
||||
type Props = ApiProps & I18nProps & {
|
||||
accountId?: string,
|
||||
referendumId: BN
|
||||
};
|
||||
|
||||
const NAY = 0;
|
||||
const YAY = -1; // Yes, this is weird, but works on i8 with the high bit set
|
||||
|
||||
class VotingButton extends React.PureComponent<Props> {
|
||||
render () {
|
||||
const { accountId, referendumId, t } = this.props;
|
||||
|
||||
return (
|
||||
<Button.Group>
|
||||
<TxButton
|
||||
accountId={accountId}
|
||||
isDisabled={!accountId}
|
||||
isNegative
|
||||
label={t('Nay')}
|
||||
params={[referendumId, NAY]}
|
||||
tx='democracy.vote'
|
||||
/>
|
||||
<Button.Or />
|
||||
<TxButton
|
||||
accountId={accountId}
|
||||
isDisabled={!accountId}
|
||||
isPositive
|
||||
label={t('Aye')}
|
||||
params={[referendumId, YAY]}
|
||||
tx='democracy.vote'
|
||||
/>
|
||||
</Button.Group>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withMulti(
|
||||
VotingButton,
|
||||
translate,
|
||||
withApi
|
||||
);
|
||||
Loading…
Reference in New Issue
Block a user