Propose.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. // Copyright 2017-2019 @polkadot/ui-staking authors & contributors
  2. // This software may be modified and distributed under the terms
  3. // of the Apache-2.0 license. See the LICENSE file for details.
  4. import { Call } from '@polkadot/types/interfaces';
  5. import { I18nProps } from '@polkadot/react-components/types';
  6. import { ApiProps } from '@polkadot/react-api/types';
  7. import BN from 'bn.js';
  8. import React from 'react';
  9. import { RouteComponentProps } from 'react-router';
  10. import { withRouter } from 'react-router-dom';
  11. import { createType } from '@polkadot/types';
  12. import { Button, Extrinsic, InputAddress, InputBalance, TxButton, TxComponent } from '@polkadot/react-components';
  13. import { withApi, withMulti } from '@polkadot/react-api';
  14. import translate from './translate';
  15. type Props = I18nProps & ApiProps & RouteComponentProps & {
  16. basePath: string;
  17. };
  18. interface State {
  19. accountId?: string;
  20. method: Call | null;
  21. value: BN;
  22. isValid: boolean;
  23. }
  24. class Propose extends TxComponent<Props, State> {
  25. public state: State = {
  26. method: null,
  27. value: new BN(0),
  28. isValid: false
  29. };
  30. public render (): React.ReactNode {
  31. const { apiDefaultTxSudo, t } = this.props;
  32. const { isValid, accountId, method, value } = this.state;
  33. const hasValue = !!value && value.gtn(0);
  34. return (
  35. <section>
  36. <InputAddress
  37. className='medium'
  38. label={t('account')}
  39. help={t('The account used to make the new proposal')}
  40. type='account'
  41. onChange={this.onChangeAccount}
  42. />
  43. <Extrinsic
  44. defaultValue={apiDefaultTxSudo}
  45. label={t('propose')}
  46. onChange={this.onChangeExtrinsic}
  47. onEnter={this.sendTx}
  48. />
  49. <InputBalance
  50. className='medium'
  51. isError={!hasValue}
  52. help={t('The amount that will be bonded to submit the proposal')}
  53. label={t('value')}
  54. onChange={this.onChangeValue}
  55. onEnter={this.sendTx}
  56. />
  57. <Button.Group>
  58. <TxButton
  59. accountId={accountId}
  60. label={t('Submit')}
  61. tx='democracy.propose'
  62. isDisabled={!isValid}
  63. params={[
  64. ...(method ? [createType('Proposal', method)] : []),
  65. ...(hasValue ? [value] : [])
  66. ]}
  67. onSuccess={this.onSubmitProposal}
  68. ref={this.button}
  69. />
  70. </Button.Group>
  71. </section>
  72. );
  73. }
  74. private nextState (newState: Partial<State>): void {
  75. this.setState(
  76. (prevState: State): State => {
  77. const { accountId = prevState.accountId, method = prevState.method, value = prevState.value } = newState;
  78. const isValid = !!method && !!value && value.gt(new BN(0)) && !!accountId && accountId.length > 0;
  79. return {
  80. accountId,
  81. method,
  82. value,
  83. isValid
  84. };
  85. }
  86. );
  87. }
  88. private onChangeAccount = (accountId: string): void => {
  89. this.nextState({ accountId });
  90. }
  91. private onChangeExtrinsic = (method: Call): void => {
  92. if (!method) {
  93. return;
  94. }
  95. this.nextState({ method });
  96. }
  97. private onChangeValue = (value?: BN): void => {
  98. this.nextState({ value });
  99. }
  100. private onSubmitProposal = (): void => {
  101. const { history, basePath } = this.props;
  102. history.push(basePath);
  103. }
  104. }
  105. export default withMulti(
  106. Propose,
  107. translate,
  108. withRouter,
  109. withApi
  110. );