Add create proposal option to app-democracy (#1046)

* new proposal flow

* fixes

* separate concerns

* basePath
This commit is contained in:
kwingram25 2019-05-02 03:08:56 -07:00 committed by Jaco Greeff
parent 00ffa44b79
commit 7d899bfc9a
12 changed files with 199 additions and 19 deletions

View File

@ -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,

View File

@ -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>,

View File

@ -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>
);

View File

@ -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']

View File

@ -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>>

View File

@ -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,

View File

@ -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,

View File

@ -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,

View 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 />
</>
);
}
}

View 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
);

View File

@ -55,6 +55,10 @@
margin-bottom: 0;
}
.democracy--Proposal-new {
float: right;
}
.democracy--Referendum-results {
margin-bottom: 1em;
}

View File

@ -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>
);
}