Add create proposal option to app-democracy (#1046)
* new proposal flow * fixes * separate concerns * basePath
This commit is contained in:
parent
00ffa44b79
commit
7d899bfc9a
@ -10,7 +10,7 @@ import { Method, Proposal } from '@polkadot/types';
|
||||
import { Call } from '@polkadot/ui-app';
|
||||
import { formatNumber } from '@polkadot/util';
|
||||
|
||||
import translate from './translate';
|
||||
import translate from '../translate';
|
||||
|
||||
type Props = I18nProps & {
|
||||
children?: React.ReactNode,
|
||||
@ -12,7 +12,7 @@ import { withCalls, withMulti } from '@polkadot/ui-api';
|
||||
import { formatBalance } from '@polkadot/util';
|
||||
|
||||
import Item from './Item';
|
||||
import translate from './translate';
|
||||
import translate from '../translate';
|
||||
|
||||
type Props = I18nProps & {
|
||||
democracy_depositOf?: Option<Tuple>,
|
||||
@ -9,19 +9,29 @@ import { Tuple } from '@polkadot/types';
|
||||
import { withCalls, withMulti } from '@polkadot/ui-api';
|
||||
|
||||
import Proposal from './Proposal';
|
||||
import translate from './translate';
|
||||
import translate from '../translate';
|
||||
|
||||
type Props = I18nProps & {
|
||||
democracy_publicProps?: Array<Tuple>
|
||||
};
|
||||
|
||||
type State = {
|
||||
isProposeOpen: boolean
|
||||
};
|
||||
|
||||
class Proposals extends React.PureComponent<Props> {
|
||||
state: State = {
|
||||
isProposeOpen: false
|
||||
};
|
||||
|
||||
render () {
|
||||
const { t } = this.props;
|
||||
|
||||
return (
|
||||
<section className='democracy--Proposals'>
|
||||
<h1>{t('proposals')}</h1>
|
||||
<h1>
|
||||
{t('proposals')}
|
||||
</h1>
|
||||
{this.renderProposals()}
|
||||
</section>
|
||||
);
|
||||
@ -17,7 +17,7 @@ import { formatBalance, formatNumber } from '@polkadot/util';
|
||||
|
||||
import Item from './Item';
|
||||
import Voting from './Voting';
|
||||
import translate from './translate';
|
||||
import translate from '../translate';
|
||||
|
||||
const COLORS_YAY = settings.uiTheme === 'substrate'
|
||||
? ['#4d4', '#4e4']
|
||||
@ -10,7 +10,7 @@ import { Option } from '@polkadot/types';
|
||||
import { withCalls } from '@polkadot/ui-api';
|
||||
|
||||
import Referendum from './Referendum';
|
||||
import translate from './translate';
|
||||
import translate from '../translate';
|
||||
|
||||
type Props = I18nProps & {
|
||||
democracy_referendums?: Array<Option<ReferendumInfoExtended>>
|
||||
@ -10,7 +10,7 @@ import { SummaryBox, CardSummary } from '@polkadot/ui-app';
|
||||
import { withCalls } from '@polkadot/ui-api';
|
||||
import { formatNumber } from '@polkadot/util';
|
||||
|
||||
import translate from './translate';
|
||||
import translate from '../translate';
|
||||
|
||||
type Props = I18nProps & {
|
||||
chain_bestNumber?: BN,
|
||||
@ -12,7 +12,7 @@ import accountObservable from '@polkadot/ui-keyring/observable/accounts';
|
||||
import { withMulti, withObservable } from '@polkadot/ui-api';
|
||||
|
||||
import VotingButtons from './VotingButtons';
|
||||
import translate from './translate';
|
||||
import translate from '../translate';
|
||||
|
||||
type Props = I18nProps & {
|
||||
allAccounts?: SubjectInfo,
|
||||
@ -10,7 +10,7 @@ import React from 'react';
|
||||
import { Button, TxButton } from '@polkadot/ui-app';
|
||||
import { withApi, withMulti } from '@polkadot/ui-api';
|
||||
|
||||
import translate from './translate';
|
||||
import translate from '../translate';
|
||||
|
||||
type Props = ApiProps & I18nProps & {
|
||||
accountId?: string,
|
||||
27
packages/app-democracy/src/Overview/index.tsx
Normal file
27
packages/app-democracy/src/Overview/index.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
// 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 { AppProps, BareProps, I18nProps } from '@polkadot/ui-app/types';
|
||||
|
||||
import '../index.css';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import Proposals from './Proposals';
|
||||
import Referendums from './Referendums';
|
||||
import Summary from './Summary';
|
||||
|
||||
type Props = AppProps & BareProps & I18nProps;
|
||||
|
||||
export default class Overview extends React.PureComponent<Props> {
|
||||
render () {
|
||||
return (
|
||||
<>
|
||||
<Summary />
|
||||
<Referendums />
|
||||
<Proposals />
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
132
packages/app-democracy/src/Propose.tsx
Normal file
132
packages/app-democracy/src/Propose.tsx
Normal file
@ -0,0 +1,132 @@
|
||||
// Copyright 2017-2019 @polkadot/ui-staking 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 { RouteComponentProps } from 'react-router';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { Method, Proposal } from '@polkadot/types';
|
||||
|
||||
import { Button, Extrinsic, InputAddress, InputBalance, TxButton } from '@polkadot/ui-app';
|
||||
import { withApi, withMulti } from '@polkadot/ui-api';
|
||||
|
||||
import translate from './translate';
|
||||
|
||||
type Props = I18nProps & ApiProps & RouteComponentProps & {
|
||||
basePath: string
|
||||
};
|
||||
|
||||
type State = {
|
||||
accountId?: string,
|
||||
method: Method | null,
|
||||
value: BN,
|
||||
isValid: boolean
|
||||
};
|
||||
|
||||
class Propose extends React.PureComponent<Props, State> {
|
||||
state: State = {
|
||||
method: null,
|
||||
value: new BN(0),
|
||||
isValid: false
|
||||
};
|
||||
|
||||
render () {
|
||||
const { api, apiDefaultTx, t } = this.props;
|
||||
const { isValid, accountId, method, value } = this.state;
|
||||
const hasValue = !!value && value.gtn(0);
|
||||
|
||||
const defaultExtrinsic = (() => {
|
||||
try {
|
||||
return api.tx.consensus.setCode;
|
||||
} catch (error) {
|
||||
return apiDefaultTx;
|
||||
}
|
||||
})();
|
||||
|
||||
return (
|
||||
<section>
|
||||
<InputAddress
|
||||
className='medium'
|
||||
label={t('account')}
|
||||
help={t('The account used to make the new proposal')}
|
||||
type='account'
|
||||
onChange={this.onChangeAccount}
|
||||
/>
|
||||
<Extrinsic
|
||||
defaultValue={defaultExtrinsic}
|
||||
label={t('propose')}
|
||||
onChange={this.onChangeExtrinsic}
|
||||
/>
|
||||
<InputBalance
|
||||
className='medium'
|
||||
isError={!hasValue}
|
||||
help={t('The amount that will be bonded to submit the proposal')}
|
||||
label={t('value')}
|
||||
onChange={this.onChangeValue}
|
||||
/>
|
||||
<Button.Group>
|
||||
<TxButton
|
||||
accountId={accountId}
|
||||
label={t('Submit')}
|
||||
tx='democracy.propose'
|
||||
isDisabled={!isValid}
|
||||
params={[
|
||||
...(method ? [new Proposal(method)] : []),
|
||||
...(hasValue ? [value] : [])
|
||||
]}
|
||||
onSuccess={this.onSubmitProposal}
|
||||
/>
|
||||
</Button.Group>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
private nextState (newState: State): void {
|
||||
this.setState(
|
||||
(prevState: State): State => {
|
||||
const { accountId = prevState.accountId, method = prevState.method, value = prevState.value } = newState;
|
||||
const isValid = !!method && !!value && value.gt(new BN(0)) && !!accountId && accountId.length > 0;
|
||||
|
||||
return {
|
||||
accountId,
|
||||
method,
|
||||
value,
|
||||
isValid
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private onChangeAccount = (accountId: string): void => {
|
||||
this.nextState({ accountId } as State);
|
||||
}
|
||||
|
||||
private onChangeExtrinsic = (method: Method): void => {
|
||||
if (!method) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.nextState({ method } as State);
|
||||
}
|
||||
|
||||
private onChangeValue = (value?: BN): void => {
|
||||
this.nextState({ value } as State);
|
||||
}
|
||||
|
||||
private onSubmitProposal = () => {
|
||||
const { history, basePath } = this.props;
|
||||
|
||||
history.push(basePath);
|
||||
}
|
||||
}
|
||||
|
||||
export default withMulti(
|
||||
Propose,
|
||||
translate,
|
||||
withApi,
|
||||
withRouter
|
||||
);
|
||||
@ -55,6 +55,10 @@
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.democracy--Proposal-new {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.democracy--Referendum-results {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
@ -7,12 +7,12 @@ import { AppProps, BareProps, I18nProps } from '@polkadot/ui-app/types';
|
||||
import './index.css';
|
||||
|
||||
import React from 'react';
|
||||
import { Route, Switch } from 'react-router';
|
||||
import { HelpOverlay,Tabs } from '@polkadot/ui-app';
|
||||
|
||||
import basicMd from './md/basic.md';
|
||||
import Proposals from './Proposals';
|
||||
import Referendums from './Referendums';
|
||||
import Summary from './Summary';
|
||||
import Overview from './Overview';
|
||||
import Propose from './Propose';
|
||||
import translate from './translate';
|
||||
|
||||
type Props = AppProps & BareProps & I18nProps;
|
||||
@ -27,15 +27,22 @@ class App extends React.PureComponent<Props> {
|
||||
<header>
|
||||
<Tabs
|
||||
basePath={basePath}
|
||||
items={[{
|
||||
name: 'overview',
|
||||
text: t('Democracy overview')
|
||||
}]}
|
||||
items={[
|
||||
{
|
||||
name: 'overview',
|
||||
text: t('Democracy overview')
|
||||
},
|
||||
{
|
||||
name: 'propose',
|
||||
text: t('Submit proposal')
|
||||
}
|
||||
]}
|
||||
/>
|
||||
</header>
|
||||
<Summary />
|
||||
<Referendums />
|
||||
<Proposals />
|
||||
<Switch>
|
||||
<Route path={`${basePath}/propose`} render={() => <Propose basePath={basePath} />} />
|
||||
<Route component={Overview} />
|
||||
</Switch>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user