Refactor TxButton and expand use (#1023)
* Refactor TxButton and expand use * Set button to loading while broadcasting * Travis CI * add extrinsic prop, req changes * restore loading indicator
This commit is contained in:
parent
347632af2b
commit
6435293ff4
@ -3,13 +3,11 @@
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { I18nProps } from '@polkadot/ui-app/types';
|
||||
import { QueueProps } from '@polkadot/ui-app/Status/types';
|
||||
import { SubjectInfo } from '@polkadot/ui-keyring/observable/types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import React from 'react';
|
||||
import { InputAddress } from '@polkadot/ui-app';
|
||||
import { QueueConsumer } from '@polkadot/ui-app/Status/Context';
|
||||
import accountObservable from '@polkadot/ui-keyring/observable/accounts';
|
||||
import { withMulti, withObservable } from '@polkadot/ui-api';
|
||||
|
||||
@ -60,15 +58,10 @@ class Voting extends React.PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
return (
|
||||
<QueueConsumer>
|
||||
{({ queueExtrinsic }: QueueProps) => (
|
||||
<VotingButtons
|
||||
accountId={accountId}
|
||||
queueExtrinsic={queueExtrinsic}
|
||||
referendumId={referendumId}
|
||||
/>
|
||||
)}
|
||||
</QueueConsumer>
|
||||
<VotingButtons
|
||||
accountId={accountId}
|
||||
referendumId={referendumId}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -3,65 +3,46 @@
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { I18nProps } from '@polkadot/ui-app/types';
|
||||
import { QueueTx$ExtrinsicAdd } from '@polkadot/ui-app/Status/types';
|
||||
import { ApiProps } from '@polkadot/ui-api/types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import React from 'react';
|
||||
import { Button } from '@polkadot/ui-app';
|
||||
import { Button, TxButton } from '@polkadot/ui-app';
|
||||
import { withApi, withMulti } from '@polkadot/ui-api';
|
||||
|
||||
import translate from './translate';
|
||||
|
||||
type Props = ApiProps & I18nProps & {
|
||||
accountId?: string,
|
||||
queueExtrinsic: QueueTx$ExtrinsicAdd,
|
||||
referendumId: BN
|
||||
};
|
||||
|
||||
class VotingButton extends React.PureComponent<Props> {
|
||||
render () {
|
||||
const { accountId, t } = this.props;
|
||||
const { accountId, referendumId, t } = this.props;
|
||||
|
||||
return (
|
||||
<Button.Group>
|
||||
<Button
|
||||
<TxButton
|
||||
accountId={accountId}
|
||||
isDisabled={!accountId}
|
||||
isNegative
|
||||
label={t('Nay')}
|
||||
onClick={this.onClickNo}
|
||||
params={[referendumId, -1]}
|
||||
tx='democracy.vote'
|
||||
/>
|
||||
<Button.Or />
|
||||
<Button
|
||||
<TxButton
|
||||
accountId={accountId}
|
||||
isDisabled={!accountId}
|
||||
isPositive
|
||||
label={t('Aye')}
|
||||
onClick={this.onClickYes}
|
||||
params={[referendumId, 0]}
|
||||
tx='democracy.vote'
|
||||
/>
|
||||
</Button.Group>
|
||||
);
|
||||
}
|
||||
|
||||
private doVote (vote: boolean) {
|
||||
const { accountId, api, queueExtrinsic, referendumId } = this.props;
|
||||
|
||||
if (!accountId) {
|
||||
return;
|
||||
}
|
||||
|
||||
queueExtrinsic({
|
||||
extrinsic: api.tx.democracy.vote(referendumId, vote ? -1 : 0),
|
||||
accountId
|
||||
});
|
||||
}
|
||||
|
||||
private onClickYes = () => {
|
||||
this.doVote(true);
|
||||
}
|
||||
|
||||
private onClickNo = () => {
|
||||
this.doVote(false);
|
||||
}
|
||||
}
|
||||
|
||||
export default withMulti(
|
||||
|
||||
@ -6,10 +6,11 @@ import BN from 'bn.js';
|
||||
import { I18nProps } from '@polkadot/ui-app/types';
|
||||
import { QueueTx$ExtrinsicAdd } from '@polkadot/ui-app/Status/types';
|
||||
import { ApiProps } from '@polkadot/ui-api/types';
|
||||
import { SubmittableExtrinsic } from '@polkadot/api/promise/types';
|
||||
|
||||
import React from 'react';
|
||||
import { Method } from '@polkadot/types';
|
||||
import { Button, Extrinsic, InputAddress, Labelled } from '@polkadot/ui-app';
|
||||
import { Button, Extrinsic, InputAddress, Labelled, TxButton } from '@polkadot/ui-app';
|
||||
import { withApi, withMulti } from '@polkadot/ui-api';
|
||||
import { Nonce } from '@polkadot/ui-reactive';
|
||||
|
||||
@ -42,6 +43,7 @@ class Selection extends React.PureComponent<Props, State> {
|
||||
return apiDefaultTx;
|
||||
}
|
||||
})();
|
||||
const extrinsic = this.getExtrinsic() || defaultExtrinsic;
|
||||
|
||||
return (
|
||||
<div className='extrinsics--Selection'>
|
||||
@ -75,17 +77,18 @@ class Selection extends React.PureComponent<Props, State> {
|
||||
/>
|
||||
<br></br>
|
||||
<Button.Group>
|
||||
<Button
|
||||
<TxButton
|
||||
isDisabled={!isValid}
|
||||
onClick={this.onQueueInherent}
|
||||
label={t('Submit Inherent')}
|
||||
extrinsic={extrinsic}
|
||||
/>
|
||||
<Button.Or />
|
||||
<Button
|
||||
<TxButton
|
||||
accountId={accountId}
|
||||
isDisabled={!isValid}
|
||||
isPrimary
|
||||
onClick={this.onQueueExtrinsic}
|
||||
label={t('Submit Transaction')}
|
||||
extrinsic={extrinsic}
|
||||
/>
|
||||
</Button.Group>
|
||||
</div>
|
||||
@ -124,32 +127,16 @@ class Selection extends React.PureComponent<Props, State> {
|
||||
this.nextState({ accountId, accountNonce: new BN(0) } as State);
|
||||
}
|
||||
|
||||
private onQueue (isUnsigned: boolean): void {
|
||||
const { api, queueExtrinsic } = this.props;
|
||||
const { method, isValid, accountId } = this.state;
|
||||
private getExtrinsic (): SubmittableExtrinsic | null {
|
||||
const { api } = this.props;
|
||||
const { method, isValid } = this.state;
|
||||
|
||||
if (!isValid || !method) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
const fn = Method.findFunction(method.callIndex);
|
||||
const extrinsic = api.tx[fn.section][fn.method](...method.args);
|
||||
|
||||
queueExtrinsic({
|
||||
accountId: isUnsigned
|
||||
? undefined
|
||||
: accountId,
|
||||
extrinsic,
|
||||
isUnsigned
|
||||
});
|
||||
}
|
||||
|
||||
private onQueueExtrinsic = (): void => {
|
||||
this.onQueue(false);
|
||||
}
|
||||
|
||||
private onQueueInherent = (): void => {
|
||||
this.onQueue(true);
|
||||
return api.tx[fn.section][fn.method](...method.args);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,13 +2,11 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { QueueProps } from '@polkadot/ui-app/Status/types';
|
||||
import { AppProps, I18nProps } from '@polkadot/ui-app/types';
|
||||
|
||||
import './index.css';
|
||||
|
||||
import React from 'react';
|
||||
import { QueueConsumer } from '@polkadot/ui-app/Status/Context';
|
||||
import { Tabs } from '@polkadot/ui-app';
|
||||
|
||||
import Selection from './Selection';
|
||||
@ -31,11 +29,7 @@ class ExtrinsicsApp extends React.PureComponent<Props> {
|
||||
}]}
|
||||
/>
|
||||
</header>
|
||||
<QueueConsumer>
|
||||
{({ queueExtrinsic }: QueueProps) => (
|
||||
<Selection queueExtrinsic={queueExtrinsic} />
|
||||
)}
|
||||
</QueueConsumer>
|
||||
<Selection />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@ -2,13 +2,12 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { SubmittableExtrinsic } from '@polkadot/api/promise/types';
|
||||
import { IExtrinsic } from '@polkadot/types/types';
|
||||
import { I18nProps } from '@polkadot/ui-app/types';
|
||||
import { QueueTx$Extrinsic, QueueTx$ExtrinsicAdd } from '@polkadot/ui-app/Status/types';
|
||||
|
||||
import React from 'react';
|
||||
import { Index } from '@polkadot/types';
|
||||
import Button from '@polkadot/ui-app/Button';
|
||||
import { Button, TxButton } from '@polkadot/ui-app';
|
||||
import { withCalls, withMulti } from '@polkadot/ui-api';
|
||||
|
||||
import translate from './translate';
|
||||
@ -17,39 +16,26 @@ type Props = I18nProps & {
|
||||
isDisabled: boolean,
|
||||
accountId?: string,
|
||||
system_accountNonce?: Index,
|
||||
extrinsic: SubmittableExtrinsic | null,
|
||||
queueExtrinsic: QueueTx$ExtrinsicAdd
|
||||
extrinsic: IExtrinsic | null
|
||||
};
|
||||
|
||||
class Submit extends React.PureComponent<Props> {
|
||||
render () {
|
||||
const { extrinsic, isDisabled, t } = this.props;
|
||||
const { accountId, system_accountNonce, extrinsic, isDisabled, t } = this.props;
|
||||
|
||||
return (
|
||||
<Button.Group>
|
||||
<Button
|
||||
isDisabled={isDisabled || !extrinsic}
|
||||
<TxButton
|
||||
accountId={accountId}
|
||||
accountNonce={system_accountNonce}
|
||||
isDisabled={isDisabled}
|
||||
isPrimary
|
||||
onClick={this.onMakeTransfer}
|
||||
label={t('Make Transfer')}
|
||||
extrinsic={extrinsic}
|
||||
/>
|
||||
</Button.Group>
|
||||
);
|
||||
}
|
||||
|
||||
private onMakeTransfer = () => {
|
||||
const { accountId, system_accountNonce, extrinsic, queueExtrinsic } = this.props;
|
||||
|
||||
if (!extrinsic) {
|
||||
return;
|
||||
}
|
||||
|
||||
queueExtrinsic({
|
||||
extrinsic,
|
||||
accountId,
|
||||
accountNonce: system_accountNonce
|
||||
} as QueueTx$Extrinsic);
|
||||
}
|
||||
}
|
||||
|
||||
export default withMulti(
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { I18nProps } from '@polkadot/ui-app/types';
|
||||
import { QueueProps } from '@polkadot/ui-app/Status/types';
|
||||
import { ApiProps } from '@polkadot/ui-api/types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
@ -11,7 +10,6 @@ import React from 'react';
|
||||
import { IExtrinsic } from '@polkadot/types/types';
|
||||
import { AddressSummary, InputAddress, InputBalance } from '@polkadot/ui-app';
|
||||
import { withApi, withMulti } from '@polkadot/ui-api';
|
||||
import { QueueConsumer } from '@polkadot/ui-app/Status/Context';
|
||||
import keyring from '@polkadot/ui-keyring';
|
||||
import Checks from '@polkadot/ui-signer/Checks';
|
||||
|
||||
@ -73,16 +71,11 @@ class Transfer extends React.PureComponent<Props, State> {
|
||||
isSendable
|
||||
onChange={this.onChangeFees}
|
||||
/>
|
||||
<QueueConsumer>
|
||||
{({ queueExtrinsic }: QueueProps) => (
|
||||
<Submit
|
||||
accountId={accountId}
|
||||
isDisabled={!hasAvailable}
|
||||
extrinsic={extrinsic}
|
||||
queueExtrinsic={queueExtrinsic}
|
||||
/>
|
||||
)}
|
||||
</QueueConsumer>
|
||||
<Submit
|
||||
accountId={accountId}
|
||||
isDisabled={!hasAvailable}
|
||||
extrinsic={extrinsic}
|
||||
/>
|
||||
</div>
|
||||
{this.renderAddress(recipientId, 'large')}
|
||||
</div>
|
||||
|
||||
@ -11,7 +11,7 @@ import { isUndefined } from '@polkadot/util';
|
||||
|
||||
export default class Button extends React.PureComponent<ButtonProps> {
|
||||
render () {
|
||||
const { children, className, floated, icon, isBasic = false, isCircular = false, isDisabled = false, isNegative = false, isPositive = false, isPrimary = false, label, onClick, size, style, tabIndex } = this.props;
|
||||
const { children, className, floated, icon, isBasic = false, isCircular = false, isDisabled = false, isLoading = false, isNegative = false, isPositive = false, isPrimary = false, label, onClick, size, style, tabIndex } = this.props;
|
||||
|
||||
const props = {
|
||||
basic: isBasic,
|
||||
@ -20,6 +20,7 @@ export default class Button extends React.PureComponent<ButtonProps> {
|
||||
disabled: isDisabled,
|
||||
floated,
|
||||
icon,
|
||||
loading: isLoading,
|
||||
negative: isNegative,
|
||||
onClick,
|
||||
positive: isPositive,
|
||||
|
||||
@ -13,6 +13,7 @@ export type ButtonProps = BareProps & {
|
||||
isBasic?: boolean,
|
||||
isCircular?: boolean,
|
||||
isDisabled?: boolean,
|
||||
isLoading?: boolean,
|
||||
isNegative?: boolean,
|
||||
isPositive?: boolean,
|
||||
isPrimary?: boolean,
|
||||
|
||||
@ -2,8 +2,11 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { Index } from '@polkadot/types';
|
||||
import { IExtrinsic } from '@polkadot/types/types';
|
||||
import { ApiProps } from '@polkadot/ui-api/types';
|
||||
import { QueueTx$ExtrinsicAdd, TxCallback } from './Status/types';
|
||||
import { SubmittableExtrinsic } from '@polkadot/api/promise/types';
|
||||
import { QueueTx, QueueTx$ExtrinsicAdd, TxCallback } from './Status/types';
|
||||
|
||||
import React from 'react';
|
||||
import { withApi } from '@polkadot/ui-api';
|
||||
@ -16,10 +19,12 @@ type ConstructFn = () => Array<any>;
|
||||
|
||||
type InjectedProps = {
|
||||
queueExtrinsic: QueueTx$ExtrinsicAdd;
|
||||
txqueue: Array<QueueTx>;
|
||||
};
|
||||
|
||||
type Props = ApiProps & {
|
||||
accountId?: string,
|
||||
accountNonce?: Index,
|
||||
isPrimary?: boolean,
|
||||
isDisabled?: boolean,
|
||||
isNegative?: boolean,
|
||||
@ -29,16 +34,60 @@ type Props = ApiProps & {
|
||||
onSuccess?: TxCallback,
|
||||
onUpdate?: TxCallback,
|
||||
params?: Array<any> | ConstructFn,
|
||||
tx: string
|
||||
tx?: string,
|
||||
extrinsic?: IExtrinsic | SubmittableExtrinsic
|
||||
};
|
||||
|
||||
class TxButtonInner extends React.PureComponent<Props & InjectedProps> {
|
||||
type InnerProps = Props & InjectedProps;
|
||||
|
||||
type State = {
|
||||
extrinsic: SubmittableExtrinsic,
|
||||
isSending: boolean
|
||||
};
|
||||
|
||||
class TxButtonInner extends React.PureComponent<InnerProps> {
|
||||
state = {
|
||||
isSending: false
|
||||
} as State;
|
||||
|
||||
static getDerivedStateFromProps ({ api, params = [], txqueue = [], tx = '', extrinsic: propsExtrinsic }: InnerProps): State | null {
|
||||
if (!propsExtrinsic && (!tx || tx.length === 0)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let extrinsic: any;
|
||||
if (propsExtrinsic) {
|
||||
extrinsic = propsExtrinsic;
|
||||
} else {
|
||||
const [section, method] = tx.split('.');
|
||||
|
||||
assert(api.tx[section] && api.tx[section][method], `Unable to find api.tx.${section}.${method}`);
|
||||
|
||||
extrinsic = api.tx[section][method](
|
||||
...(isFunction(params) ? params() : params)
|
||||
);
|
||||
}
|
||||
|
||||
let isSending = false;
|
||||
const queuedTx = txqueue.find(({ extrinsic: ex }) => ex === extrinsic);
|
||||
if (queuedTx) {
|
||||
isSending = ['broadcast', 'sending'].includes(queuedTx.status);
|
||||
}
|
||||
|
||||
return {
|
||||
extrinsic,
|
||||
isSending
|
||||
};
|
||||
}
|
||||
|
||||
render () {
|
||||
const { accountId, isDisabled, isNegative, isPrimary, label } = this.props;
|
||||
const { isSending } = this.state;
|
||||
|
||||
return (
|
||||
<Button
|
||||
isDisabled={isDisabled || !accountId}
|
||||
isDisabled={isSending || isDisabled || !accountId}
|
||||
isLoading={isSending}
|
||||
isNegative={isNegative}
|
||||
isPrimary={isUndefined(isPrimary) ? !isNegative : isPrimary}
|
||||
label={label}
|
||||
@ -48,17 +97,10 @@ class TxButtonInner extends React.PureComponent<Props & InjectedProps> {
|
||||
}
|
||||
|
||||
private send = (): void => {
|
||||
const { accountId, api, onClick, onFailed, onSuccess, onUpdate, params = [], queueExtrinsic, tx } = this.props;
|
||||
const { accountId, onClick, onFailed, onSuccess, onUpdate, queueExtrinsic } = this.props;
|
||||
const { extrinsic } = this.state;
|
||||
|
||||
assert(tx, 'Expected tx param passed to TxButton');
|
||||
|
||||
const [section, method] = tx.split('.');
|
||||
|
||||
assert(api.tx[section] && api.tx[section][method], `Unable to find api.tx.${section}.${method}`);
|
||||
|
||||
const extrinsic: any = api.tx[section][method](
|
||||
...(isFunction(params) ? params() : params)
|
||||
);
|
||||
assert(extrinsic, 'Expected generated extrinsic passed to TxButton');
|
||||
|
||||
queueExtrinsic({
|
||||
accountId,
|
||||
@ -76,10 +118,11 @@ class TxButton extends React.PureComponent<Props> {
|
||||
render () {
|
||||
return (
|
||||
<QueueConsumer>
|
||||
{({ queueExtrinsic }) => (
|
||||
{({ queueExtrinsic, txqueue }) => (
|
||||
<TxButtonInner
|
||||
{...this.props}
|
||||
queueExtrinsic={queueExtrinsic}
|
||||
txqueue={txqueue}
|
||||
/>
|
||||
)}
|
||||
</QueueConsumer>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user