Basic info display for 123-code (#641)

* Add withCalls

* withCalls operational

* Basic header display & cleanups

* Global account selector for app

* Remove errant debug log

* Simple transfer applet working

* Update Upgrade.tsx

* Update InputNumber.tsx

* Update Transfer.tsx

* Move TxButton back to 123code (for the time being)

* Good enough for a v1
This commit is contained in:
Jaco Greeff 2019-01-27 12:50:47 +01:00 committed by GitHub
parent e1a17a86c1
commit 653c2a505f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
95 changed files with 859 additions and 315 deletions

View File

@ -0,0 +1,53 @@
// Copyright 2017-2019 @polkadot/app-123code 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 React from 'react';
import { Bubble, InputAddress } from '@polkadot/ui-app/index';
import { AccountIndex, Balance, Nonce } from '@polkadot/ui-reactive/index';
type Props = {
onChange: (accountId?: string) => void
};
type State = {
accountId?: string
};
export default class AccountSelector extends React.PureComponent<Props, State> {
state: State = {};
render () {
const { accountId } = this.state;
return (
<section className='template--AccountSelector template--2-columns'>
<InputAddress
className='template--column'
label='my default account to transact from'
onChange={this.onChange}
type='account'
/>
<div className='template--column'>
<Bubble color='teal' icon='address card' label='index'>
<AccountIndex value={accountId} />
</Bubble>
<Bubble color='yellow' icon='adjust' label='balance'>
<Balance value={accountId} />
</Bubble>
<Bubble color='yellow' icon='target' label='transactions'>
<Nonce value={accountId} />
</Bubble>
</div>
</section>
);
}
private onChange = (accountId?: string): void => {
const { onChange } = this.props;
this.setState({ accountId }, () =>
onChange(accountId)
);
}
}

View File

@ -0,0 +1,102 @@
// Copyright 2017-2019 @polkadot/app-123code 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 { ApiProps } from '@polkadot/ui-api/types';
import { BareProps, I18nProps } from '@polkadot/ui-app/types';
import BN from 'bn.js';
import React from 'react';
import { AccountId, RuntimeVersion } from '@polkadot/types';
import { withCalls } from '@polkadot/ui-api/with';
import { Bubble, IdentityIcon } from '@polkadot/ui-app/index';
import { formatBalance, formatNumber } from '@polkadot/ui-app/util';
import translate from './translate';
type Props = ApiProps & BareProps & I18nProps & {
balances_totalIssuance?: BN,
chain_bestNumber?: BN,
chain_bestNumberLag?: BN,
chain_getRuntimeVersion?: RuntimeVersion,
session_validators?: Array<AccountId>,
staking_intentions?: Array<AccountId>,
system_chain?: string,
system_name?: string,
system_version?: string
};
type State = {
nextUp: Array<AccountId>
};
class SummaryBar extends React.PureComponent<Props, State> {
state: State = {
nextUp: []
};
static getDerivedStateFromProps ({ staking_intentions, session_validators }: Props): State | null {
if (!staking_intentions || !session_validators) {
return null;
}
return {
nextUp: staking_intentions.filter((accountId) =>
!session_validators.find((validatorId) => validatorId.eq(accountId))
)
};
}
render () {
const { balances_totalIssuance, chain_bestNumber, chain_bestNumberLag, chain_getRuntimeVersion, session_validators = [], system_chain, system_name, system_version } = this.props;
const { nextUp } = this.state;
return (
<summary>
<div>
<Bubble icon='tty' label='node'>
{system_name} v{system_version}
</Bubble>
<Bubble icon='chain' label='chain'>
{system_chain}
</Bubble>
<Bubble icon='code' label='runtime'>{
chain_getRuntimeVersion
? `${chain_getRuntimeVersion.implName} v${chain_getRuntimeVersion.implVersion}`
: undefined
}</Bubble>
<Bubble icon='bullseye' label='best #'>
{formatNumber(chain_bestNumber)} ({formatNumber(chain_bestNumberLag)} lag)
</Bubble>
<Bubble icon='chess queen' label='validators'>{
session_validators.map((accountId, index) => (
<IdentityIcon key={index} value={accountId} size={20} />
))
}</Bubble>
<Bubble icon='chess bishop' label='next up'>{
nextUp.map((accountId, index) => (
<IdentityIcon key={index} value={accountId} size={20} />
))
}</Bubble>
<Bubble icon='circle' label='total tokens'>
{formatBalance(balances_totalIssuance)}
</Bubble>
</div>
</summary>
);
}
}
// inject the actual API calls automatically into props
export default translate(
withCalls<Props>(
'derive.chain.bestNumber',
'derive.chain.bestNumberLag',
'query.balances.totalIssuance',
'query.session.validators',
'query.staking.intentions',
'rpc.chain.getRuntimeVersion',
'rpc.system.chain',
'rpc.system.name',
'rpc.system.version'
)(SummaryBar)
);

View File

@ -0,0 +1,62 @@
// Copyright 2017-2019 @polkadot/app-123code 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 BN from 'bn.js';
import React from 'react';
import { Button, InputAddress, InputBalance } from '@polkadot/ui-app/index';
import TxButton from './TxButton';
type Props = {
accountId?: string
};
type State = {
amount?: BN;
recipientId?: string;
};
export default class Transfer extends React.PureComponent<Props> {
state: State = {};
render () {
const { accountId } = this.props;
const { amount, recipientId } = this.state;
return (
<section>
<h1>transfer</h1>
<div className='template--2-columns'>
<article className='template--column'>
<InputAddress
label='recipient address for this transfer'
onChange={this.onChangeRecipient}
type='all'
/>
<InputBalance
label='amount to transfer'
onChange={this.onChangeAmount}
/>
<Button.Group>
<TxButton
accountId={accountId}
label='make transfer'
params={[recipientId, amount]}
tx='balances.transfer'
/>
</Button.Group>
</article>
<div className='template--column template--summary'>Make a transfer from any account you control to another account. Transfer fees and per-transaction feed apply.</div>
</div>
</section>
);
}
private onChangeAmount = (amount?: BN): void => {
this.setState({ amount });
}
private onChangeRecipient = (recipientId?: string): void => {
this.setState({ recipientId });
}
}

View File

@ -0,0 +1,68 @@
// Copyright 2017-2019 @polkadot/app-123code 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 { ApiProps } from '@polkadot/ui-api/types';
import { QueueTx$ExtrinsicAdd } from '@polkadot/ui-app/Status/types';
import React from 'react';
import { Button } from '@polkadot/ui-app/index';
import { QueueConsumer } from '@polkadot/ui-app/Status/Context';
import { withApi } from '@polkadot/ui-api/index';
import { assert } from '@polkadot/util';
type InjectedProps = {
queueExtrinsic: QueueTx$ExtrinsicAdd;
};
type Props = ApiProps & {
accountId?: string,
isDisabled?: boolean,
label: React.ReactNode,
params: Array<any>,
tx: string
};
class TxButtonInner extends React.PureComponent<Props & InjectedProps> {
render () {
const { accountId, isDisabled, label } = this.props;
return (
<Button
isDisabled={isDisabled || !accountId}
isPrimary
label={label}
onClick={this.send}
/>
);
}
private send = (): void => {
const { accountId, api, params, queueExtrinsic, tx } = this.props;
const [section, method] = tx.split('.');
assert(api.tx[section] && api.tx[section][method], `Unable to find api.tx.${section}.${method}`);
queueExtrinsic({
accountId,
extrinsic: api.tx[section][method](...params)
});
}
}
class TxButton extends React.PureComponent<Props> {
render () {
return (
<QueueConsumer>
{({ queueExtrinsic }) => (
<TxButtonInner
{...this.props}
queueExtrinsic={queueExtrinsic}
/>
)}
</QueueConsumer>
);
}
}
export default withApi(TxButton);

View File

@ -1,3 +1,25 @@
/* Copyright 2017-2019 @polkadot/app-123code authors & contributors
/* This software may be modified and distributed under the terms
/* of the Apache-2.0 license. See the LICENSE file for details. */
.template--2-columns {
display: flex;
.template--column {
box-sizing: border-box;
flex: 1 1;
}
}
.template--summary {
opacity: 0.5;
padding: 1rem 1.5rem;
}
.template--AccountSelector {
align-items: flex-end;
.ui.dropdown {
margin-bottom: 0.25rem;
}
}

View File

@ -2,24 +2,51 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
// some types, AppProps for the app and I18nProps to indicate
// translatable strings. Generally the latter is quite "light",
// `t` is inject into props (see the HOC export) and `t('any text')
// does the translation
import { AppProps, I18nProps } from '@polkadot/ui-app/types';
// external imports (including those found in the packages/*
// of this repo)
import React from 'react';
// our app-specific styles
import './index.css';
// local imports and components
import AccountSelector from './AccountSelector';
import SummaryBar from './SummaryBar';
import Transfer from './Transfer';
import translate from './translate';
// define out internal types
type Props = AppProps & I18nProps;
type State = {};
type State = {
accountId?: string
};
class App extends React.PureComponent<Props, State> {
state: State = {};
render () {
const { accountId } = this.state;
return (
<main className='template--App'>empty</main>
// in all apps, the main wrapper is setup to allow the padding
// and margins inside the application. (Just from a consistent pov)
<main>
<SummaryBar />
<AccountSelector onChange={this.onAccountChange} />
<Transfer accountId={accountId} />
</main>
);
}
private onAccountChange = (accountId?: string): void => {
this.setState({ accountId });
}
}
export default translate(App);

View File

@ -4,4 +4,4 @@
import { withNamespaces } from 'react-i18next';
export default withNamespaces(['template', 'ui']);
export default withNamespaces(['123code', 'ui']);

View File

@ -59,15 +59,15 @@ class Backup extends React.PureComponent<Props, State> {
<Button.Group>
<Button
isNegative
label={t('Cancel')}
onClick={onClose}
text={t('Cancel')}
/>
<Button.Or />
<Button
isDisabled={!isPassValid}
isPrimary
label={t('Download')}
onClick={this.doBackup}
text={t('Download')}
/>
</Button.Group>
</Modal.Actions>

View File

@ -62,15 +62,15 @@ class ChangePass extends React.PureComponent<Props, State> {
<Button.Group>
<Button
isNegative
label={t('Cancel')}
onClick={onClose}
text={t('Cancel')}
/>
<Button.Or />
<Button
isDisabled={!isNewValid || !isOldValid}
isPrimary
label={t('Change')}
onClick={this.doChange}
text={t('Change')}
/>
</Button.Group>
</Modal.Actions>

View File

@ -122,15 +122,15 @@ class Creator extends React.PureComponent<Props, State> {
return (
<Button.Group>
<Button
label={t('Reset')}
onClick={this.onDiscard}
text={t('Reset')}
/>
<Button.Or />
<Button
isDisabled={!isValid}
isPrimary
label={t('Save')}
onClick={this.onShowWarning}
text={t('Save')}
/>
</Button.Group>
);
@ -209,14 +209,14 @@ class Creator extends React.PureComponent<Props, State> {
<Button.Group>
<Button
isNegative
label={t('Cancel')}
onClick={this.onHideWarning}
text={t('Cancel')}
/>
<Button.Or />
<Button
isPrimary
label={t('Create and backup account')}
onClick={this.onCommit}
text={t('Create and backup account')}
/>
</Button.Group>
</Modal.Actions>

View File

@ -62,32 +62,32 @@ class Editor extends React.PureComponent<Props, State> {
<Button
isNegative
onClick={this.toggleForget}
text={t('Forget')}
label={t('Forget')}
/>
<Button.Group.Divider />
<Button
isDisabled={isEdited}
onClick={this.toggleBackup}
text={t('Backup')}
label={t('Backup')}
/>
<Button.Or />
<Button
isDisabled={isEdited}
onClick={this.togglePass}
text={t('Change Password')}
label={t('Change Password')}
/>
<Button.Group.Divider />
<Button
isDisabled={!isEdited}
onClick={this.onDiscard}
text={t('Reset')}
label={t('Reset')}
/>
<Button.Or />
<Button
isDisabled={!isEdited}
isPrimary
onClick={this.onCommit}
text={t('Save')}
label={t('Save')}
/>
</Button.Group>
);

View File

@ -39,13 +39,13 @@ class Forgetting extends React.PureComponent<Props> {
<Button
isNegative
onClick={onClose}
text={t('Cancel')}
label={t('Cancel')}
/>
<Button.Or />
<Button
isPrimary
onClick={doForget}
text={t('Forget')}
label={t('Forget')}
/>
</Button.Group>
</Modal.Actions>

View File

@ -62,7 +62,7 @@ class Restore extends React.PureComponent<Props, State> {
isDisabled={!isFileValid || !isPassValid}
isPrimary
onClick={this.onSave}
text={t('Restore')}
label={t('Restore')}
/>
</Button.Group>
</div>

View File

@ -79,7 +79,7 @@ class VanityApp extends React.PureComponent<Props, State> {
isDisabled={!isMatchValid}
isPrimary={!isRunning}
onClick={this.toggleStart}
text={
label={
isRunning
? t('Stop generation')
: t('Start generation')

View File

@ -61,14 +61,14 @@ class Creator extends React.PureComponent<Props, State> {
<Button.Group>
<Button
onClick={this.onDiscard}
text={t('Reset')}
label={t('Reset')}
/>
<Button.Or />
<Button
isDisabled={!isValid}
isPrimary
onClick={this.onCommit}
text={t('Save')}
label={t('Save')}
/>
</Button.Group>
);

View File

@ -62,20 +62,20 @@ class Editor extends React.PureComponent<Props, State> {
<Button
isNegative
onClick={this.toggleForget}
text={t('Forget')}
label={t('Forget')}
/>
<Button.Group.Divider />
<Button
isDisabled={!isEdited}
onClick={this.onDiscard}
text={t('Reset')}
label={t('Reset')}
/>
<Button.Or />
<Button
isDisabled={!isEdited}
isPrimary
onClick={this.onCommit}
text={t('Save')}
label={t('Save')}
/>
</Button.Group>
);

View File

@ -51,13 +51,13 @@ class Forgetting extends React.PureComponent<Props> {
<Button
isNegative
onClick={onClose}
text={t('Cancel')}
label={t('Cancel')}
/>
<Button.Or />
<Button
isPrimary
onClick={doForget}
text={t('Forget')}
label={t('Forget')}
/>
</Button.Group>
</Modal.Actions>

View File

@ -8,7 +8,7 @@ import BN from 'bn.js';
import React from 'react';
import { Method, Proposal } from '@polkadot/types';
import { Call } from '@polkadot/ui-app/index';
import numberFormat from '@polkadot/ui-reactive/util/numberFormat';
import { formatNumber } from '@polkadot/ui-app/util';
import translate from './translate';
@ -16,7 +16,7 @@ type Props = I18nProps & {
children?: React.ReactNode,
proposal: Proposal,
proposalExtra?: React.ReactNode,
idNumber: BN
idNumber: BN | number
};
class Item extends React.PureComponent<Props> {
@ -39,7 +39,7 @@ class Item extends React.PureComponent<Props> {
}</div>
</div>
<div className='democracy--Item-header-id'>
#{numberFormat(idNumber)}
#{formatNumber(idNumber)}
</div>
</div>
<div className='democracy--Item-body'>

View File

@ -10,7 +10,7 @@ import { AccountId, Balance, Proposal } from '@polkadot/types';
import { Tuple, Vector } from '@polkadot/types/codec';
import { AddressMini, Labelled, Static } from '@polkadot/ui-app/index';
import { withCall, withMulti } from '@polkadot/ui-api/index';
import { balanceFormat } from '@polkadot/ui-reactive/util/index';
import { formatBalance } from '@polkadot/ui-app/util/index';
import Item from './Item';
import translate from './translate';
@ -58,7 +58,7 @@ class ProposalDisplay extends React.PureComponent<Props> {
</div>
</Labelled>
<Static label={t('balance')}>
{balanceFormat(balance)}
{formatBalance(balance)}
</Static>
</div>
);

View File

@ -11,8 +11,8 @@ import React from 'react';
import { ReferendumInfo } from '@polkadot/types';
import { Chart, Static } from '@polkadot/ui-app/index';
import VoteThreshold from '@polkadot/ui-params/Param/VoteThreshold';
import { withCall, withMulti } from '@polkadot/ui-api/index';
import { balanceFormat, numberFormat } from '@polkadot/ui-reactive/util/index';
import { withCalls } from '@polkadot/ui-api/index';
import { formatBalance, formatNumber } from '@polkadot/ui-app/util/index';
import settings from '@polkadot/ui-settings';
import Item from './Item';
@ -30,7 +30,7 @@ type Props = I18nProps & {
chain_bestNumber?: BN,
democracy_referendumVotesFor?: Array<DerivedReferendumVote>,
democracy_publicDelay?: BN,
idNumber: BN,
idNumber: BN | number,
value: ReferendumInfo
};
@ -126,15 +126,15 @@ class Referendum extends React.PureComponent<Props, State> {
<Static label={t('ending at')}>
{t('block #{{blockNumber}}, {{remaining}} blocks remaining', {
replace: {
blockNumber: numberFormat(end),
remaining: numberFormat(end.sub(chain_bestNumber).subn(1))
blockNumber: formatNumber(end),
remaining: formatNumber(end.sub(chain_bestNumber).subn(1))
}
})}
</Static>
<Static label={t('activate at (if passed)')}>
{t('block #{{blockNumber}}', {
replace: {
blockNumber: numberFormat(enactBlock)
blockNumber: formatNumber(enactBlock)
}
})}
</Static>
@ -165,12 +165,12 @@ class Referendum extends React.PureComponent<Props, State> {
values={[
{
colors: COLORS_YAY,
label: `${balanceFormat(votedYay)} (${numberFormat(voteCountYay)})`,
label: `${formatBalance(votedYay)} (${formatNumber(voteCountYay)})`,
value: votedYay.muln(10000).div(votedTotal).toNumber() / 100
},
{
colors: COLORS_NAY,
label: `${balanceFormat(votedNay)} (${numberFormat(voteCountNay)})`,
label: `${formatBalance(votedNay)} (${formatNumber(voteCountNay)})`,
value: votedNay.muln(10000).div(votedTotal).toNumber() / 100
}
]}
@ -180,10 +180,10 @@ class Referendum extends React.PureComponent<Props, State> {
}
}
export default withMulti(
Referendum,
translate,
withCall('derive.chain.bestNumber'),
withCall('derive.democracy.referendumVotesFor', { paramName: 'idNumber' }),
withCall('query.democracy.publicDelay')
export default translate(
withCalls<Props>(
'derive.chain.bestNumber',
['derive.democracy.referendumVotesFor', { paramName: 'idNumber' }],
'query.democracy.publicDelay'
)(Referendum)
);

View File

@ -7,7 +7,7 @@ import { I18nProps } from '@polkadot/ui-app/types';
import BN from 'bn.js';
import React from 'react';
import { ReferendumInfo } from '@polkadot/types';
import { withCall, withMulti } from '@polkadot/ui-api/index';
import { withCalls } from '@polkadot/ui-api/index';
import Referendum from './Referendum';
import translate from './translate';
@ -54,10 +54,10 @@ class Referendums extends React.PureComponent<Props> {
}
}
export default withMulti(
Referendums,
translate,
withCall('query.democracy.nextTally'),
withCall('query.democracy.referendumCount'),
withCall('derive.democracy.referendums')
export default translate(
withCalls<Props>(
'query.democracy.nextTally',
'query.democracy.referendumCount',
'derive.democracy.referendums'
)(Referendums)
);

View File

@ -7,8 +7,8 @@ import { I18nProps } from '@polkadot/ui-app/types';
import BN from 'bn.js';
import React from 'react';
import { CardSummary } from '@polkadot/ui-app/index';
import { withCall, withMulti } from '@polkadot/ui-api/index';
import { numberFormat } from '@polkadot/ui-reactive/util/index';
import { formatNumber } from '@polkadot/ui-app/util/index';
import { withCalls } from '@polkadot/ui-api/index';
import translate from './translate';
@ -30,13 +30,13 @@ class Summary extends React.PureComponent<Props> {
<summary>
<section>
<CardSummary label={t('proposals')}>
{numberFormat(democracy_publicPropCount)}
{formatNumber(democracy_publicPropCount)}
</CardSummary>
<CardSummary label={t('referendums')}>
{numberFormat(democracy_referendumCount)}
{formatNumber(democracy_referendumCount)}
</CardSummary>
<CardSummary label={t('active')}>
{numberFormat(democracy_referendumCount.sub(democracy_nextTally))}
{formatNumber(democracy_referendumCount.sub(democracy_nextTally))}
</CardSummary>
</section>
<section>
@ -60,13 +60,13 @@ class Summary extends React.PureComponent<Props> {
}
}
export default withMulti(
Summary,
translate,
withCall('query.democracy.launchPeriod'),
withCall('query.democracy.nextTally'),
withCall('query.democracy.publicPropCount'),
withCall('query.democracy.referendumCount'),
withCall('query.democracy.votingPeriod'),
withCall('derive.chain.bestNumber')
export default translate(
withCalls<Props>(
'query.democracy.launchPeriod',
'query.democracy.nextTally',
'query.democracy.publicPropCount',
'query.democracy.referendumCount',
'query.democracy.votingPeriod',
'derive.chain.bestNumber'
)(Summary)
);

View File

@ -14,7 +14,7 @@ import VotingButtons from './VotingButtons';
import translate from './translate';
type Props = I18nProps & {
referendumId: BN
referendumId: BN | number
};
type State = {

View File

@ -28,14 +28,14 @@ class VotingButton extends React.PureComponent<Props> {
<Button
isDisabled={!accountId}
isNegative
text={t('Nay')}
label={t('Nay')}
onClick={this.onClickNo}
/>
<Button.Or />
<Button
isDisabled={!accountId}
isPositive
text={t('Aye')}
label={t('Aye')}
onClick={this.onClickYes}
/>
</Button.Group>

View File

@ -8,7 +8,7 @@ import { ApiProps } from '@polkadot/ui-api/types';
import React from 'react';
import { EventRecord, SignedBlock } from '@polkadot/types';
import { HeaderExtended } from '@polkadot/types/Header';
import { withCall, withMulti } from '@polkadot/ui-api/index';
import { withCalls } from '@polkadot/ui-api/index';
import BlockHeader from '../BlockHeader';
import translate from '../translate';
@ -44,10 +44,10 @@ class BlockByHash extends React.PureComponent<Props> {
}
}
export default withMulti(
BlockByHash,
translate,
withCall('rpc.chain.getBlock', { paramName: 'value' }),
withCall('derive.chain.getHeader', { paramName: 'value' }),
withCall('query.system.events', { atProp: 'value' })
export default translate(
withCalls<Props>(
['rpc.chain.getBlock', { paramName: 'value' }],
['derive.chain.getHeader', { paramName: 'value' }],
['query.system.events', { atProp: 'value' }]
)(BlockByHash)
);

View File

@ -6,8 +6,8 @@ import { I18nProps } from '@polkadot/ui-app/types';
import React from 'react';
import { AddressMini, Call } from '@polkadot/ui-app/index';
import { formatNumber } from '@polkadot/ui-app/util';
import { Extrinsic, Method } from '@polkadot/types';
import { numberFormat } from '@polkadot/ui-reactive/util/index';
import translate from '../translate';
@ -58,7 +58,7 @@ class Extrinsics extends React.PureComponent<Props> {
<article className='ui--hoverable explorer--Container'>
<div className='header'>
<h3>
{section}.{method}&nbsp;(#{numberFormat(index)})
{section}.{method}&nbsp;(#{formatNumber(index)})
</h3>
{this.renderSigner(extrinsic)}
</div>
@ -93,7 +93,7 @@ class Extrinsics extends React.PureComponent<Props> {
<AddressMini value={extrinsic.signature.signer} />
</div>
<div className='explorer--BlockByHash-accountIndex'>
{t('index')} {numberFormat(extrinsic.signature.nonce)}
{t('index')} {formatNumber(extrinsic.signature.nonce)}
</div>
</div>
);

View File

@ -10,7 +10,7 @@ import React from 'react';
import { Link } from 'react-router-dom';
import { HeaderExtended } from '@polkadot/types/Header';
import { AddressMini } from '@polkadot/ui-app/index';
import numberFormat from '@polkadot/ui-reactive/util/numberFormat';
import { formatNumber } from '@polkadot/ui-app/util';
type Props = BareProps & {
isSummary?: boolean,
@ -29,7 +29,7 @@ export default class BlockHeader extends React.PureComponent<Props> {
const { author, blockNumber, extrinsicsRoot, parentHash, stateRoot } = value;
const parentHex = parentHash.toHex();
const hashHex = value.hash.toHex();
const textNumber = numberFormat(blockNumber);
const textNumber = formatNumber(blockNumber);
return (
<article className={['explorer--BlockHeader', isSummary ? 'ui--hoverable summary' : ''].join(' ')}>

View File

@ -7,7 +7,7 @@ import { I18nProps } from '@polkadot/ui-app/types';
import React from 'react';
import { EventRecord } from '@polkadot/types';
import { Event as EventDisplay } from '@polkadot/ui-app/index';
import { numberFormat } from '@polkadot/ui-reactive/util/index';
import { formatNumber } from '@polkadot/ui-app/util';
import translate from './translate';
@ -59,7 +59,7 @@ class Events extends React.PureComponent<Props> {
<h3>
{event.section}.{event.method}&nbsp;{
extIndex !== -1
? `(#${numberFormat(extIndex)})`
? `(#${formatNumber(extIndex)})`
: ''
}
</h3>

View File

@ -8,7 +8,7 @@ import BN from 'bn.js';
import React from 'react';
import { BlockNumber } from '@polkadot/types';
import { CardSummary } from '@polkadot/ui-app/index';
import { withCall, withMulti } from '@polkadot/ui-api/index';
import { withCalls } from '@polkadot/ui-api/index';
import translate from './translate';
@ -92,11 +92,11 @@ class SummarySession extends React.PureComponent<Props> {
}
}
export default withMulti(
SummarySession,
translate,
withCall('derive.session.eraLength'),
withCall('derive.session.eraProgress'),
withCall('derive.session.sessionProgress'),
withCall('query.session.sessionLength')
export default translate(
withCalls<Props>(
'derive.session.eraLength',
'derive.session.eraProgress',
'derive.session.sessionProgress',
'query.session.sessionLength'
)(SummarySession)
);

View File

@ -69,14 +69,14 @@ class Selection extends React.PureComponent<Props, State> {
<Button
isDisabled={!isValid}
onClick={this.onQueueInherent}
text={t('Submit Inherent')}
label={t('Submit Inherent')}
/>
<Button.Or />
<Button
isDisabled={!isValid}
isPrimary
onClick={this.onQueueExtrinsic}
text={t('Submit Transaction')}
label={t('Submit Transaction')}
/>
</Button.Group>
</div>

View File

@ -6,7 +6,7 @@ import { I18nProps } from '@polkadot/ui-app/types';
import React from 'react';
import { PeerInfo } from '@polkadot/types';
import { numberFormat } from '@polkadot/ui-reactive/util/index';
import { formatNumber } from '@polkadot/ui-app/util';
import translate from './translate';
@ -63,7 +63,7 @@ class Peers extends React.PureComponent<Props> {
<td className='number'>{peer.index.toNumber()}</td>
<td className='roles'>{peer.roles.toString().toLowerCase()}</td>
<td className='peerid'>{peer.peerId.toString()}</td>
<td className='number'>{numberFormat(peer.bestNumber)}</td>
<td className='number'>{formatNumber(peer.bestNumber)}</td>
<td className='hash'>{peer.bestHash.toHex()}</td>
</tr>
);

View File

@ -8,8 +8,8 @@ import { Info } from './types';
import BN from 'bn.js';
import React from 'react';
import { CardSummary } from '@polkadot/ui-app/index';
import { formatNumber } from '@polkadot/ui-app/util';
import { BestNumber, Elapsed } from '@polkadot/ui-reactive/index';
import { numberFormat } from '@polkadot/ui-reactive/util';
import translate from './translate';
@ -79,7 +79,7 @@ class Summary extends React.PureComponent<Props, State> {
</section>
<section>
<CardSummary label={t('peer best')}>
{numberFormat(peerBest)}
{formatNumber(peerBest)}
</CardSummary>
<CardSummary label={t('our best')}>
<BestNumber />

View File

@ -109,7 +109,7 @@ class App extends React.PureComponent<Props, State> {
<Button
isPrimary
onClick={this.save}
text={t('Save & Reload')}
label={t('Save & Reload')}
/>
</Button.Group>
</main>

View File

@ -10,10 +10,10 @@ import { AccountId, Balance } from '@polkadot/types';
import { HeaderExtended } from '@polkadot/types/Header';
import { withCall, withMulti } from '@polkadot/ui-api/with';
import { AddressMini, AddressRow } from '@polkadot/ui-app/index';
import { formatNumber } from '@polkadot/ui-app/util';
import keyring from '@polkadot/ui-keyring';
import translate from '../translate';
import { numberFormat } from '@polkadot/ui-reactive/util';
type Props = I18nProps & {
balances: DerivedBalancesMap,
@ -88,7 +88,7 @@ class CurrentList extends React.PureComponent<Props> {
let lastAuthor: string;
if (chain_subscribeNewHead) {
lastBlock = `#${numberFormat(chain_subscribeNewHead.blockNumber)}`;
lastBlock = `#${formatNumber(chain_subscribeNewHead.blockNumber)}`;
lastAuthor = (chain_subscribeNewHead.author || '').toString();
}

View File

@ -7,10 +7,10 @@ import { I18nProps } from '@polkadot/ui-app/types';
import BN from 'bn.js';
import React from 'react';
import { CardSummary } from '@polkadot/ui-app/index';
import SummarySession from '@polkadot/app-explorer/SummarySession';
import { CardSummary } from '@polkadot/ui-app/index';
import { formatBalance } from '@polkadot/ui-app/util';
import { withCall, withMulti } from '@polkadot/ui-api/index';
import { balanceFormat } from '@polkadot/ui-reactive/util/index';
import translate from '../translate';
@ -56,10 +56,10 @@ class Summary extends React.PureComponent<Props> {
const intentionHigh = this.calcIntentionsHigh();
const validatorLow = this.calcValidatorLow();
const nominatedLow = validatorLow && validatorLow.nominatedBalance.gtn(0)
? `(+${balanceFormat(validatorLow.nominatedBalance)})`
? `(+${formatBalance(validatorLow.nominatedBalance)})`
: '';
const nominatedHigh = intentionHigh && intentionHigh.nominatedBalance.gtn(0)
? `(+${balanceFormat(intentionHigh.nominatedBalance)})`
? `(+${formatBalance(intentionHigh.nominatedBalance)})`
: '';
return (
@ -67,14 +67,14 @@ class Summary extends React.PureComponent<Props> {
<div>{t('lowest validator {{validatorLow}}', {
replace: {
validatorLow: validatorLow && validatorLow.stakingBalance
? `${balanceFormat(validatorLow.stakingBalance)} ${nominatedLow}`
? `${formatBalance(validatorLow.stakingBalance)} ${nominatedLow}`
: '-'
}
})}</div>
<div>{t('highest intention {{intentionHigh}}', {
replace: {
intentionHigh: intentionHigh
? `${balanceFormat(intentionHigh.stakingBalance)} ${nominatedHigh}`
? `${formatBalance(intentionHigh.stakingBalance)} ${nominatedHigh}`
: '-'
}
})}</div>

View File

@ -11,7 +11,7 @@ import { ApiProps } from '@polkadot/ui-api/types';
import React from 'react';
import { AccountId, Balance, ValidatorPrefs } from '@polkadot/types';
import { AddressMini, AddressSummary, Button } from '@polkadot/ui-app/index';
import { withCall, withMulti } from '@polkadot/ui-api/index';
import { withCalls } from '@polkadot/ui-api/index';
import Nominating from './Nominating';
import Preferences from './Preferences';
@ -27,8 +27,7 @@ type Props = ApiProps & I18nProps & {
staking_nominatorsFor?: Array<string>,
intentions: Array<string>,
isValidator: boolean,
queueExtrinsic: QueueTx$ExtrinsicAdd,
validators: Array<string>
queueExtrinsic: QueueTx$ExtrinsicAdd
};
type State = {
@ -140,13 +139,13 @@ class Account extends React.PureComponent<Props, State> {
<Button
isPrimary
onClick={this.stake}
text={t('Stake')}
label={t('Stake')}
/>
<Button.Or />
<Button
isPrimary
onClick={this.toggleNominate}
text={t('Nominate')}
label={t('Nominate')}
/>
</Button.Group>
);
@ -169,13 +168,13 @@ class Account extends React.PureComponent<Props, State> {
<Button
isNegative
onClick={this.unstake}
text={t('Unstake')}
label={t('Unstake')}
/>
<Button.Or />
<Button
isPrimary
onClick={this.togglePrefs}
text={t('Set Prefs')}
label={t('Set Prefs')}
/>
</Button.Group>
);
@ -247,9 +246,9 @@ class Account extends React.PureComponent<Props, State> {
}
}
export default withMulti(
Account,
translate,
withCall('query.staking.nominatorsFor', { paramName: 'accountId' }),
withCall('query.staking.nominating', { paramName: 'accountId' })
export default translate(
withCalls<Props>(
['query.staking.nominatorsFor', { paramName: 'accountId' }],
['query.staking.nominating', { paramName: 'accountId' }]
)(Account)
);

View File

@ -67,14 +67,14 @@ class Nominating extends React.PureComponent<Props, State> {
<Button
isNegative
onClick={onClose}
text={t('Cancel')}
label={t('Cancel')}
/>
<Button.Or />
<Button
isDisabled={!isNomineeValid}
isPrimary
onClick={this.nominate}
text={t('Nominate')}
label={t('Nominate')}
/>
</Button.Group>
</Modal.Actions>

View File

@ -73,13 +73,13 @@ class Preferences extends React.PureComponent<Props, State> {
<Button
isNegative
onClick={onClose}
text={t('Cancel')}
label={t('Cancel')}
/>
<Button.Or />
<Button
isPrimary
onClick={this.setPrefs}
text={t('Set Prefs')}
label={t('Set Prefs')}
/>
</Button.Group>
</Modal.Actions>

View File

@ -31,7 +31,7 @@ class UnnominateButton extends React.Component<Props> {
style={style}
isNegative
onClick={this.onClick}
text={t('Unnominate')}
label={t('Unnominate')}
/>
);
}

View File

@ -4,11 +4,12 @@
import { DerivedBalancesMap } from '@polkadot/api-derive/types';
import { AppProps, I18nProps } from '@polkadot/ui-app/types';
import { ApiProps } from '@polkadot/ui-api/types';
import React from 'react';
import { AccountId, Balance } from '@polkadot/types';
import { Tabs } from '@polkadot/ui-app/index';
import { withCall, withMulti } from '@polkadot/ui-api/index';
import { withCalls } from '@polkadot/ui-api/index';
import './index.css';
@ -18,7 +19,7 @@ import translate from './translate';
type Actions = 'actions' | 'overview';
type Props = AppProps & I18nProps & {
type Props = AppProps & ApiProps & I18nProps & {
balances?: DerivedBalancesMap,
intentions?: Array<AccountId>,
session_validators?: Array<AccountId>
@ -115,10 +116,10 @@ class App extends React.PureComponent<Props, State> {
}
}
export default withMulti(
App,
translate,
withCall('query.session.validators'),
withCall('query.staking.intentions', { propName: 'intentions' }),
withCall('derive.staking.intentionsBalances', { propName: 'balances' })
export default translate(
withCalls<Props>(
'query.session.validators',
['query.staking.intentions', { propName: 'intentions' }],
['derive.staking.intentionsBalances', { propName: 'balances' }]
)(App)
);

View File

@ -63,7 +63,7 @@ class Selection extends React.PureComponent<Props, State> {
isDisabled={!isValid}
isPrimary
onClick={this.onSubmit}
text={t('Submit RPC call')}
label={t('Submit RPC call')}
/>
</Button.Group>
</section>

View File

@ -90,7 +90,7 @@ class Sign extends React.PureComponent<Props, State> {
<Button
isPrimary
onClick={this.toggleUnlock}
text={t('Unlock account')}
label={t('Unlock account')}
/>
</Button.Group>
);

View File

@ -67,13 +67,13 @@ class Unlock extends React.PureComponent<Props, State> {
<Button
isNegative
onClick={this.onCancel}
text={t('Cancel')}
label={t('Cancel')}
/>
<Button.Or />
<Button
isPrimary
onClick={this.onUnlock}
text={t('Unlock')}
label={t('Unlock')}
/>
</Button.Group>
);

View File

@ -31,7 +31,7 @@ class Submit extends React.PureComponent<Props> {
isDisabled={isDisabled || !extrinsic}
isPrimary
onClick={this.onMakeTransfer}
text={t('Make Transfer')}
label={t('Make Transfer')}
/>
</Button.Group>
);

View File

@ -2,15 +2,14 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { BitLength, I18nProps } from '@polkadot/ui-app/types';
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';
import React from 'react';
import { Extrinsic } from '@polkadot/types';
import { BitLengthOption } from '@polkadot/ui-app/constants';
import { AddressSummary, InputAddress, InputNumber } from '@polkadot/ui-app/index';
import { AddressSummary, InputAddress, InputBalance } from '@polkadot/ui-app/index';
import { withApi, withMulti } from '@polkadot/ui-api/index';
import { QueueConsumer } from '@polkadot/ui-app/Status/Context';
import keyring from '@polkadot/ui-keyring';
@ -29,8 +28,6 @@ type State = {
recipientId: string | null
};
const DEFAULT_BITLENGTH = BitLengthOption.CHAIN_SPEC as BitLength;
const ZERO = new BN(0);
class Transfer extends React.PureComponent<Props, State> {
@ -73,11 +70,9 @@ class Transfer extends React.PureComponent<Props, State> {
<div className='transfer--Transfer-info'>
{this.renderAddress(accountId)}
<div className='transfer--Transfer-data'>
<InputNumber
<InputBalance
autoFocus
bitLength={DEFAULT_BITLENGTH}
isError={!hasAvailable}
isSi
label={t('send a value of')}
onChange={this.onChangeAmount}
/>

View File

@ -10,7 +10,7 @@ import './Content.css';
import React from 'react';
import { withRouter } from 'react-router';
import { withCall, withMulti } from '@polkadot/ui-api/index';
import { withCalls, withMulti } from '@polkadot/ui-api/index';
import { QueueConsumer } from '@polkadot/ui-app/Status/Context';
import Status from '../Status';
@ -66,14 +66,16 @@ class Content extends React.Component<Props> {
}
}
// React-router needs to be first, otherwise we have blocked updates
// These API queries are used in a number of places, warm them up as
// to avoid constant un/resubscriptions on these
export default withMulti(
Content,
// React-router needs to be first, otherwise we have blocked updates
withRouter,
translate,
// these queries are used in a number of places, warm them up as to avoid
// constant un/resubscriptions on these
withCall('query.session.validators'),
withCall('derive.accounts.indexes'),
withCall('derive.balances.fees')
withCalls<Props>(
'query.session.validators',
'derive.accounts.indexes',
'derive.balances.fees'
)
);

View File

@ -10,8 +10,8 @@ import React from 'react';
import store from 'store';
import typeRegistry from '@polkadot/types/codec/typeRegistry';
import createApp from '@polkadot/ui-app/index';
import { classes } from '@polkadot/ui-app/util';
import Signer from '@polkadot/ui-signer/index';
import classes from '@polkadot/ui-app/util/classes';
import settings from '@polkadot/ui-settings';
import Connecting from './Connecting';

View File

@ -10,8 +10,8 @@ import ApiPromise from '@polkadot/api/promise';
import defaults from '@polkadot/rpc-provider/defaults';
import WsProvider from '@polkadot/rpc-provider/ws';
import { InputNumber } from '@polkadot/ui-app/InputNumber';
import { formatBalance } from '@polkadot/ui-app/util';
import keyring from '@polkadot/ui-keyring';
import { balanceFormat } from '@polkadot/ui-reactive/util/index';
import settings from '@polkadot/ui-settings';
import { ChainProperties } from '@polkadot/types';
@ -92,7 +92,7 @@ export default class ApiWrapper extends React.PureComponent<Props, State> {
console.log('api: found chain', chain, [...properties.entries()]);
// first setup the UI helpers
balanceFormat.setDefaultDecimals(properties.get('tokenDecimals') || found.tokenDecimals || 0);
formatBalance.setDefaultDecimals(properties.get('tokenDecimals') || found.tokenDecimals || 0);
InputNumber.setUnit(properties.get('tokenSymbol') || found.tokenSymbol);
// setup keyring (loadAll) only after prefix has been set

View File

@ -77,7 +77,9 @@ export default function withCall<P extends ApiProps> (endpoint: string, { at, at
componentWillUnmount () {
this.isActive = false;
this.unsubscribe();
this.unsubscribe()
.then(NOOP)
.catch(NOOP);
if (this.timerId !== -1) {
clearInterval(this.timerId);
@ -154,7 +156,7 @@ export default function withCall<P extends ApiProps> (endpoint: string, { at, at
assert(at || !atProp, 'Unable to perform query on non-existent at hash');
this.unsubscribe();
await this.unsubscribe();
if (isSubscription) {
this.destroy = await apiMethod(...params, (value?: any) =>
@ -172,7 +174,7 @@ export default function withCall<P extends ApiProps> (endpoint: string, { at, at
}
}
private unsubscribe () {
private async unsubscribe () {
if (this.destroy) {
this.destroy();
this.destroy = undefined;

View File

@ -0,0 +1,25 @@
// Copyright 2017-2019 @polkadot/ui-api 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 { ApiProps, Subtract } from '../types';
import { Options } from './types';
import React from 'react';
import withCall from './call';
type Call = string | [string, Options];
export default function withCalls <P> (...calls: Array<Call>): (Component: React.ComponentType<P>) => React.ComponentType<Subtract<P, ApiProps>> {
return (Component: React.ComponentType<P>): React.ComponentType<any> => {
// NOTE: Order is reversed so it makes sense in the props, i.e. component
// after something can use the value of the preceding version
return calls
.reverse()
.reduce((Component, call) => {
return Array.isArray(call)
? withCall(...call)(Component as any)
: withCall(call)(Component as any);
}, Component);
};
}

View File

@ -2,16 +2,9 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import withApi from './api';
import withCall from './call';
import withCallDiv from './callDiv';
import withMulti from './multi';
import withObservable from './observable';
export {
withApi,
withCall,
withCallDiv,
withMulti,
withObservable
};
export { default as withApi } from './api';
export { default as withCall } from './call';
export { default as withCalls } from './calls';
export { default as withCallDiv } from './callDiv';
export { default as withMulti } from './multi';
export { default as withObservable } from './observable';

View File

@ -21,12 +21,13 @@ type Props = BareProps & {
isShort?: boolean,
session_validators?: Array<AccountId>,
value?: AccountId | AccountIndex | Address | string,
withAddress?: boolean,
withBalance?: boolean
};
class AddressMini extends React.PureComponent<Props> {
render () {
const { children, className, isPadded = true, isShort = true, session_validators, style, value } = this.props;
const { children, className, isPadded = true, session_validators, style, value } = this.props;
if (!value) {
return null;
@ -48,7 +49,7 @@ class AddressMini extends React.PureComponent<Props> {
size={24}
value={address}
/>
<div className='ui--AddressMini-address'>{isShort ? toShortAddress(address) : address}</div>
{this.renderAddress(address)}
{children}
</div>
{this.renderBalance()}
@ -56,6 +57,18 @@ class AddressMini extends React.PureComponent<Props> {
);
}
private renderAddress (address: string) {
const { isShort = true, withAddress = true } = this.props;
if (!withAddress) {
return null;
}
return (
<div className='ui--AddressMini-address'>{isShort ? toShortAddress(address) : address}</div>
);
}
private renderBalance () {
const { balance, value, withBalance = false } = this.props;

View File

@ -3,10 +3,10 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import React from 'react';
import { withCall, withMulti } from '@polkadot/ui-api/index';
import { withCalls } from '@polkadot/ui-api/index';
import classes from './util/classes';
import { AddressSummary } from './AddressSummary';
import { AddressSummary, Props } from './AddressSummary';
import translate from './translate';
class AddressRow extends AddressSummary {
@ -32,9 +32,9 @@ class AddressRow extends AddressSummary {
}
}
export default withMulti(
AddressRow,
translate,
withCall('derive.accounts.idAndIndex', { paramName: 'value' }),
withCall('query.session.validators')
export default translate(
withCalls<Props>(
['derive.accounts.idAndIndex', { paramName: 'value' }],
'query.session.validators'
)(AddressRow)
);

View File

@ -7,7 +7,7 @@ import { I18nProps } from './types';
import React from 'react';
import { AccountId, AccountIndex, Address, Balance } from '@polkadot/types';
import { Nonce } from '@polkadot/ui-reactive/index';
import { withCall, withMulti } from '@polkadot/ui-api/index';
import { withCalls } from '@polkadot/ui-api/index';
import classes from './util/classes';
import toShortAddress from './util/toShortAddress';
@ -210,9 +210,9 @@ export {
AddressSummary
};
export default withMulti(
AddressSummary,
translate,
withCall('derive.accounts.idAndIndex', { paramName: 'value' }),
withCall('query.session.validators')
export default translate(
withCalls<Props>(
['derive.accounts.idAndIndex', { paramName: 'value' }],
'query.session.validators'
)(AddressSummary)
);

View File

@ -7,8 +7,8 @@ import { BareProps } from './types';
import BN from 'bn.js';
import React from 'react';
import { AccountId, AccountIndex, Address, Balance } from '@polkadot/types';
import { formatBalance } from '@polkadot/ui-app/util';
import RxBalance from '@polkadot/ui-reactive/Balance';
import { balanceFormat } from '@polkadot/ui-reactive/util/index';
import classes from './util/classes';
@ -46,12 +46,12 @@ export default class BalanceDisplay extends React.PureComponent<Props> {
return null;
}
let value = `${balanceFormat(Array.isArray(balance) ? balance[0] : balance)}`;
let value = `${formatBalance(Array.isArray(balance) ? balance[0] : balance)}`;
if (Array.isArray(balance)) {
const totals = balance.filter((value, index) => index !== 0);
const total = totals.reduce((total, value) => total.add(value), new BN(0)).gtn(0)
? `(+${totals.map((balance) => balanceFormat(balance)).join(', ')})`
? `(+${totals.map((balance) => formatBalance(balance)).join(', ')})`
: '';
value = `${value} ${total}`;

View File

@ -0,0 +1,49 @@
// Copyright 2017-2019 @polkadot/ui-app 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 { BareProps } from './types';
import { SemanticCOLORS, SemanticICONS } from 'semantic-ui-react/dist/commonjs/generic';
import React from 'react';
import SUILabel from 'semantic-ui-react/dist/commonjs/elements/Label/Label';
import settings from '@polkadot/ui-settings';
import classes from './util/classes';
import Icon from './Icon';
type Props = BareProps & {
children: React.ReactNode,
color?: SemanticCOLORS,
icon?: SemanticICONS,
label?: React.ReactNode
};
export default class Bubble extends React.PureComponent<Props> {
render () {
const { color, children, className, icon, label } = this.props;
return (
<SUILabel
className={classes(`theme--${settings.uiTheme}`, 'ui--Bubble', className)}
color={color}
>
<div className='ui--Bubble-header'>
{
icon
? <Icon name={icon} size='large' />
: undefined
}
{
label
? <div className='text'>{label}</div>
: undefined
}
</div>
<div className='ui--Bubble-children'>
{children}
</div>
</SUILabel>
);
}
}

View File

@ -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, onClick, size, style, tabIndex, text } = this.props;
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 props = {
basic: isBasic || false,
@ -30,13 +30,13 @@ export default class Button extends React.PureComponent<ButtonProps> {
tabIndex
};
return isUndefined(text) && isUndefined(children)
return isUndefined(label) && isUndefined(children)
? (
<SUIButton {...props} />
)
: (
<SUIButton {...props}>
{text}{children}
{label}{children}
</SUIButton>
);
}

View File

@ -22,7 +22,7 @@ class ButtonOr extends React.PureComponent<Props> {
<SUIButton.Or
className={className}
style={style}
text={
label={
isUndefined(text)
? t('or')
: text

View File

@ -16,10 +16,10 @@ export type ButtonProps = BareProps & {
isNegative?: boolean,
isPositive?: boolean,
isPrimary?: boolean,
label?: React.ReactNode,
onClick?: () => void | Promise<void>,
size?: Button$Sizes,
tabIndex?: number,
text?: any
tabIndex?: number
};
export type DividerProps = BareProps;

View File

@ -18,7 +18,7 @@ type Props<Option> = BareProps & {
isDisabled?: boolean,
isError?: boolean,
label?: React.ReactNode,
onChange: (value: any) => void,
onChange?: (value: any) => void,
onSearch?: (filteredOptions: Array<any>, query: string) => Array<Option>,
options: Array<Option>,
placeholder?: string,
@ -96,7 +96,7 @@ export default class Dropdown<Option> extends React.PureComponent<Props<Option>>
private onChange = (event: React.SyntheticEvent<HTMLElement>, { value }: DropdownProps): void => {
const { onChange, transform } = this.props;
onChange(
onChange && onChange(
transform
? transform(value)
: value

View File

@ -2,11 +2,14 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiProps } from '@polkadot/ui-api/types';
import { IdentityProps } from '@polkadot/ui-identicon/types';
import { QueueProps, QueueAction$Add } from './Status/types';
import { I18nProps } from './types';
import React from 'react';
import { AccountId } from '@polkadot/types';
import { withCall } from '@polkadot/ui-api/with';
import BaseIdentityIcon from '@polkadot/ui-identicon';
import { QueueConsumer } from './Status/Context';
@ -16,6 +19,10 @@ type CopyProps = IdentityProps & I18nProps & {
queueAction?: QueueAction$Add
};
type IconProps = ApiProps & IdentityProps & {
session_validators?: Array<AccountId>
};
class CopyIcon extends React.PureComponent<CopyProps> {
render () {
return (
@ -46,12 +53,20 @@ class CopyIcon extends React.PureComponent<CopyProps> {
const CopyIconI18N = translate(CopyIcon);
export default class IdentityIcon extends React.PureComponent<IdentityProps> {
class IdentityIcon extends React.PureComponent<IconProps & IdentityProps> {
render () {
const { session_validators = [], value } = this.props;
const address = (value || '').toString();
const isValidator = (session_validators || []).find((validator) =>
validator.toString() === address
);
return (
<QueueConsumer>
{({ queueAction }: QueueProps) =>
<CopyIconI18N
isHighlight={!!isValidator}
{...this.props}
queueAction={queueAction}
/>
@ -60,3 +75,5 @@ export default class IdentityIcon extends React.PureComponent<IdentityProps> {
);
}
}
export default withCall('query.session.validators')(IdentityIcon);

View File

@ -27,7 +27,7 @@ type Props = BareProps & {
maxLength?: number,
min?: any,
name?: string,
onChange: (value: string) => void,
onChange?: (value: string) => void,
onKeyDown?: (event: React.KeyboardEvent<Element>) => void,
onKeyUp?: (event: React.KeyboardEvent<Element>) => void,
placeholder?: string,
@ -148,7 +148,7 @@ export default class Input extends React.PureComponent<Props, State> {
const { onChange } = this.props;
const { value } = event.target as HTMLInputElement;
onChange(value);
onChange && onChange(value);
}
private onKeyDown = (event: React.KeyboardEvent<Element>): void => {

View File

@ -0,0 +1,48 @@
// Copyright 2017-2019 @polkadot/ui-app 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 { BareProps, BitLength } from './types';
import BN from 'bn.js';
import React from 'react';
import { BitLengthOption } from '@polkadot/ui-app/constants';
import { InputNumber } from '@polkadot/ui-app/index';
type Props = BareProps & {
autoFocus?: boolean,
defaultValue?: string,
isDisabled?: boolean,
isError?: boolean,
label?: any,
onChange?: (value?: BN) => void,
placeholder?: string,
value?: BN | string,
withLabel?: boolean
};
const DEFAULT_BITLENGTH = BitLengthOption.CHAIN_SPEC as BitLength;
export default class InputBalance extends React.PureComponent<Props> {
render () {
const { autoFocus, className, defaultValue, isDisabled, isError, label, onChange, placeholder, style, value, withLabel } = this.props;
return (
<InputNumber
autoFocus={autoFocus}
className={className}
bitLength={DEFAULT_BITLENGTH}
defaultValue={defaultValue || '0'}
isDisabled={isDisabled}
isError={isError}
isSi
label={label}
onChange={onChange}
placeholder={placeholder}
style={style}
value={value}
withLabel={withLabel}
/>
);
}
}

View File

@ -6,7 +6,7 @@ import { BareProps, BitLength, I18nProps } from './types';
import BN from 'bn.js';
import React from 'react';
import { balanceFormat, calcSi } from '@polkadot/ui-reactive/util/index';
import { formatBalance, calcSi } from '@polkadot/ui-app/util';
import { isUndefined } from '@polkadot/util';
import classes from './util/classes';
@ -24,7 +24,7 @@ type Props = BareProps & I18nProps & {
isSi?: boolean,
label?: any,
maxLength?: number,
onChange: (value?: BN) => void,
onChange?: (value?: BN) => void,
placeholder?: string,
value?: BN | string,
withLabel?: boolean
@ -55,7 +55,7 @@ class InputNumber extends React.PureComponent<Props, State> {
this.state = {
isPreKeyDown: false,
isValid: !isUndefined(this.props.value),
siOptions: balanceFormat.getOptions().map(({ power, text, value }) => ({
siOptions: formatBalance.getOptions().map(({ power, text, value }) => ({
value,
text: power === 0
? InputNumber.units
@ -77,7 +77,7 @@ class InputNumber extends React.PureComponent<Props, State> {
}
return {
defaultValue: balanceFormat(defaultValue, false),
defaultValue: formatBalance(defaultValue, false),
siUnit: calcSi(defaultValue).value
};
}
@ -186,7 +186,7 @@ class InputNumber extends React.PureComponent<Props, State> {
this.setState({ isValid, valueBN });
onChange(
onChange && onChange(
isValid
? valueBN
: undefined
@ -236,15 +236,15 @@ class InputNumber extends React.PureComponent<Props, State> {
}
private applySi (siUnit: string, value: BN): BN {
const si = balanceFormat.findSi(siUnit);
const power = new BN(balanceFormat.getDefaultDecimals() + si.power);
const si = formatBalance.findSi(siUnit);
const power = new BN(formatBalance.getDefaultDecimals() + si.power);
return value.mul(new BN(10).pow(power));
}
private applyNewSi (oldSi: string, newSi: string, value: BN): BN {
const si = balanceFormat.findSi(oldSi);
const power = new BN(balanceFormat.getDefaultDecimals() + si.power);
const si = formatBalance.findSi(oldSi);
const power = new BN(formatBalance.getDefaultDecimals() + si.power);
return this.applySi(newSi, value.div(new BN(10).pow(power)));
}
@ -255,7 +255,7 @@ class InputNumber extends React.PureComponent<Props, State> {
const valueBN = this.applyNewSi(prevState.siUnit, siUnit, prevState.valueBN);
const isValid = this.isValidNumber(valueBN, bitLength);
onChange(
onChange && onChange(
isValid
? valueBN
: undefined

View File

@ -25,7 +25,7 @@ type Props = I18nProps & {
isError?: boolean,
labelMethod?: string,
labelSection?: string,
onChange: (value: RpcMethod) => void,
onChange?: (value: RpcMethod) => void,
withLabel?: boolean
};
@ -88,7 +88,7 @@ class InputRpc extends React.PureComponent<Props, State> {
}
this.setState({ value: newValue }, () =>
onChange(newValue)
onChange && onChange(newValue)
);
}

View File

@ -26,7 +26,7 @@ type Props = ApiProps & I18nProps & {
isError?: boolean,
labelMethod?: string,
labelSection?: string,
onChange: (value: StorageFunction) => void,
onChange?: (value: StorageFunction) => void,
withLabel?: boolean
};
@ -89,7 +89,7 @@ class InputStorage extends React.PureComponent<Props, State> {
}
this.setState({ value: newValue }, () =>
onChange(newValue)
onChange && onChange(newValue)
);
}

View File

@ -17,7 +17,7 @@ type Props = BareProps & {
activeItem: string,
hidden?: Array<string>,
items: Array<TabItem>,
onChange: (name: any) => void
onChange?: (name: any) => void
};
type State = {
@ -76,7 +76,7 @@ export default class Tabs extends React.PureComponent<Props, State> {
const { onChange } = this.props;
this.setState({ active: name }, () => {
onChange(name);
onChange && onChange(name);
});
};
}

View File

@ -17,6 +17,7 @@ export { default as AddressMini } from './AddressMini';
export { default as AddressRow } from './AddressRow';
export { default as AddressSummary } from './AddressSummary';
export { default as Balance } from './Balance';
export { default as Bubble } from './Bubble';
export { default as Button } from './Button';
export { default as Call } from './Call';
export { default as CardSummary } from './CardSummary';
@ -31,6 +32,7 @@ export { default as InputAddress } from './InputAddress';
export { default as InputError } from './InputError';
export { default as InputExtrinsic } from './InputExtrinsic';
export { default as InputFile } from './InputFile';
export { default as InputBalance } from './InputBalance';
export { default as InputNumber } from './InputNumber';
export { default as InputRpc } from './InputRpc';
export { default as InputStorage } from './InputStorage';

View File

@ -155,6 +155,47 @@ header .ui--Button-Group {
font-style: italic;
}
.ui--Bubble.ui.label {
font-weight: normal;
margin: 0.25rem;
padding: 0;
* {
vertical-align: middle;
}
.ui--Bubble-children,
.ui--Bubble-header {
display: inline-block;
vertical-align: middle;
}
.ui--Bubble-children {
padding: 0 0.75rem 0 0;
}
.ui--Bubble-header {
background: rgba(0, 0, 0, 0.05);
box-sizing: border-box;
border-radius: .28571429rem 0 0 .28571429rem;
height: 2.75rem;
margin-right: 0.75rem;
padding: 0 0.75rem;
text-align: center;
vertical-align: middle;
> div {
display: inline-block;
line-height: 2.75rem !important;
vertical-align: middle;
}
> .text {
padding: 0 0 0 0.25rem;
}
}
}
.ui--CardSummary .ui.label {
padding-left: 0;
padding-right: 0;

View File

@ -49,7 +49,7 @@
background-color: rgba(255, 255, 255, 0.75);
}
.ui.label {
.ui.label:not(.ui--Bubble) {
background: transparent;
font-weight: normal;
position: relative;

View File

@ -4,79 +4,79 @@
import BN from 'bn.js';
import { balanceFormat } from './';
import { formatBalance } from './';
describe('balanceFormat', () => {
describe('formatBalance', () => {
const TESTVAL = new BN('123456789000');
it('formats 123,456,789,000 (decimals=15)', () => {
expect(
balanceFormat(TESTVAL, true, 15)
formatBalance(TESTVAL, true, 15)
).toEqual('123.456µ');
});
it('formats 123,456,789,000 (decimals=12)', () => {
expect(
balanceFormat(TESTVAL, true, 12)
formatBalance(TESTVAL, true, 12)
).toEqual('123.456m');
});
it('formats 123,456,789,000 (decimals=12, no SI)', () => {
expect(
balanceFormat(TESTVAL, false, 12)
formatBalance(TESTVAL, false, 12)
).toEqual('123.456');
});
it('formats 123,456,789,000 (decimals=9)', () => {
expect(
balanceFormat(TESTVAL, true, 9)
formatBalance(TESTVAL, true, 9)
).toEqual('123.456');
});
it('formats 123,456,789,000 (decimals=6)', () => {
expect(
balanceFormat(TESTVAL, true, 6)
formatBalance(TESTVAL, true, 6)
).toEqual('123.456k');
});
it('formats 123,456,789,000 * 10 (decimals=12)', () => {
expect(
balanceFormat(TESTVAL.muln(10), true, 12)
formatBalance(TESTVAL.muln(10), true, 12)
).toEqual('1.234');
});
it('formats 123,456,789,000 * 100 (decimals=12)', () => {
expect(
balanceFormat(TESTVAL.muln(100), true, 12)
formatBalance(TESTVAL.muln(100), true, 12)
).toEqual('12.345');
});
it('formats 123,456,789,000 * 1000 (decimals=12)', () => {
expect(
balanceFormat(TESTVAL.muln(1000), true, 12)
formatBalance(TESTVAL.muln(1000), true, 12)
).toEqual('123.456');
});
describe('findSi', () => {
it('finds the SI value', () => {
expect(
balanceFormat.findSi('k')
formatBalance.findSi('k')
).toEqual({ power: 3, value: 'k', text: 'Kilo' });
});
it('returns default on not found', () => {
expect(
balanceFormat.findSi('blah')
formatBalance.findSi('blah')
).toEqual({ power: 0, value: '-', text: '----' });
});
});
describe('setDefaultDecimals', () => {
it('formats 123,456,789,000 (defaultDecimals=15)', () => {
balanceFormat.setDefaultDecimals(15);
formatBalance.setDefaultDecimals(15);
expect(
balanceFormat(TESTVAL)
formatBalance(TESTVAL)
).toEqual('123.456µ');
});
});

View File

@ -4,7 +4,7 @@
import BN from 'bn.js';
import decimalFormat from './decimalFormat';
import formatDecimal from './formatDecimal';
type SiDef = {
power: number,
@ -13,7 +13,7 @@ type SiDef = {
};
interface BalanceFormatter {
(input: string | BN, withSi?: boolean, decimals?: number): string;
(input?: number | string | BN, withSi?: boolean, decimals?: number): string;
findSi (type: string): SiDef;
getDefaultDecimals (): number;
getOptions (decimals?: number): Array<SiDef>;
@ -49,7 +49,7 @@ export function calcSi (text: string, decimals: number = defaultDecimals): SiDef
}
// Formats a string/number with <prefix>.<postfix><type> notation
function _balanceFormat (input: string | BN, withSi: boolean = true, decimals: number = defaultDecimals): string {
function _formatBalance (input?: number | string | BN, withSi: boolean = true, decimals: number = defaultDecimals): string {
const text = (input || '').toString();
if (text.length === 0 || text === '0') {
@ -64,22 +64,22 @@ function _balanceFormat (input: string | BN, withSi: boolean = true, decimals: n
const prefix = text.substr(0, mid);
const postfix = `${text.substr(mid)}000`.substr(0, 3);
return `${decimalFormat(prefix || '0')}.${postfix}${withSi ? (si.value === '-' ? '' : si.value) : ''}`;
return `${formatDecimal(prefix || '0')}.${postfix}${withSi ? (si.value === '-' ? '' : si.value) : ''}`;
}
const balanceFormat = _balanceFormat as BalanceFormatter;
const formatBalance = _formatBalance as BalanceFormatter;
// Given a SI type (e.g. k, m, Y) find the SI definition
balanceFormat.findSi = (type: string): SiDef => {
formatBalance.findSi = (type: string): SiDef => {
return SI.find(({ value }) => value === type) || SI[SI_MID];
};
balanceFormat.getDefaultDecimals = (): number => {
formatBalance.getDefaultDecimals = (): number => {
return defaultDecimals;
};
// get allowable options to display in a dropdown
balanceFormat.getOptions = (decimals: number = defaultDecimals): Array<SiDef> => {
formatBalance.getOptions = (decimals: number = defaultDecimals): Array<SiDef> => {
return SI.filter(({ power }) =>
power < 0
? (decimals + power) >= 0
@ -88,8 +88,8 @@ balanceFormat.getOptions = (decimals: number = defaultDecimals): Array<SiDef> =>
};
// Sets the default decimals to use for formatting (chain-wide)
balanceFormat.setDefaultDecimals = (decimals: number = 0): void => {
formatBalance.setDefaultDecimals = (decimals: number = 0): void => {
defaultDecimals = decimals;
};
export default balanceFormat;
export default formatBalance;

View File

@ -4,6 +4,6 @@
const NUMBER_REGEX = new RegExp('(\\d+?)(?=(\\d{3})+(?!\\d)|$)', 'g');
export default function decimalFormat (value: string): string {
export default function formatDecimal (value: string): string {
return (value.match(NUMBER_REGEX) || []).join(',');
}

View File

@ -6,9 +6,9 @@ import BN from 'bn.js';
import { Compact } from '@polkadot/types/codec';
import { bnToBn } from '@polkadot/util';
import decimalFormat from './decimalFormat';
import formatDecimal from './formatDecimal';
export default function numberFormat (_value?: Compact | BN | number | null): string {
export default function formatNumber (_value?: Compact | BN | number | null): string {
if (!_value) {
return '0';
}
@ -17,5 +17,5 @@ export default function numberFormat (_value?: Compact | BN | number | null): st
? _value.toBn()
: bnToBn(_value);
return decimalFormat(value.toString());
return formatDecimal(value.toString());
}

View File

@ -0,0 +1,10 @@
// Copyright 2017-2019 @polkadot/ui-app authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
export { default as classes } from './classes';
export { default as formatBalance, calcSi } from './formatBalance';
export { default as formatDecimal } from './formatDecimal';
export { default as formatNumber } from './formatNumber';
export { default as toAddress } from './toAddress';
export { default as toShortAddress } from './toShortAddress';

View File

@ -8,7 +8,7 @@ import BN from 'bn.js';
import React from 'react';
import { AccountIndex } from '@polkadot/types';
import { Input } from '@polkadot/ui-app/index';
import numberFormat from '@polkadot/ui-reactive/util/numberFormat';
import { formatNumber } from '@polkadot/ui-app/util';
import { bnToBn } from '@polkadot/util';
import Bare from './Bare';
@ -20,7 +20,7 @@ export default class Amount extends React.PureComponent<Props> {
? (
value instanceof AccountIndex
? value.toString()
: numberFormat(value)
: formatNumber(value)
)
: bnToBn((value as number) || 0).toString();

View File

@ -2,20 +2,16 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { BitLength } from '@polkadot/ui-app/types';
import { Props as BareProps } from '../types';
import BN from 'bn.js';
import React from 'react';
import { BitLengthOption } from '@polkadot/ui-app/constants';
import { InputNumber } from '@polkadot/ui-app/index';
import { InputBalance } from '@polkadot/ui-app/index';
import Bare from './Bare';
type Props = BareProps;
const DEFAULT_BITLENGTH = BitLengthOption.CHAIN_SPEC as BitLength;
class Balance extends React.PureComponent<Props> {
render () {
const { className, defaultValue: { value }, isDisabled, isError, label, style, withLabel } = this.props;
@ -26,13 +22,11 @@ class Balance extends React.PureComponent<Props> {
className={className}
style={style}
>
<InputNumber
bitLength={DEFAULT_BITLENGTH}
<InputBalance
className='large'
defaultValue={defaultValue || '0'}
defaultValue={defaultValue}
isDisabled={isDisabled}
isError={isError}
isSi
label={label}
onChange={this.onChange}
withLabel={withLabel}

View File

@ -5,7 +5,7 @@
import { BareProps } from '@polkadot/ui-app/types';
import React from 'react';
import classes from '@polkadot/ui-app/util/classes';
import { classes } from '@polkadot/ui-app/util';
type Props = BareProps & {
children: React.ReactNode

View File

@ -7,7 +7,7 @@ import { Props } from '../types';
import React from 'react';
import { Extrinsic, Method } from '@polkadot/types';
import { Call, Static } from '@polkadot/ui-app/index';
import classes from '@polkadot/ui-app/util/classes';
import { classes } from '@polkadot/ui-app/util';
import Bare from './Bare';
import Unknown from './Unknown';

View File

@ -99,13 +99,13 @@ class Vector extends React.PureComponent<Props, State> {
<Button
isPrimary
onClick={this.rowAdd}
text={t('Add item')}
label={t('Add item')}
/>
<Button
isDisabled={values.length === 1}
isNegative
onClick={this.rowRemove}
text={t('Remove item')}
label={t('Remove item')}
/>
</div>
);

View File

@ -6,7 +6,7 @@ import { I18nProps } from '@polkadot/ui-app/types';
import { BaseProps, Props as ComponentProps, ComponentMap } from '../types';
import React from 'react';
import classes from '@polkadot/ui-app/util/classes';
import { classes } from '@polkadot/ui-app/util';
import translate from '@polkadot/ui-app/translate';
import { isUndefined } from '@polkadot/util';

View File

@ -9,7 +9,7 @@ import { ComponentMap, RawParams, RawParam$OnChange, RawParam$OnChange$Value } f
import './Params.css';
import React from 'react';
import classes from '@polkadot/ui-app/util/classes';
import { classes } from '@polkadot/ui-app/util';
import translate from '@polkadot/ui-app/translate';
import Param from './Param';

View File

@ -5,11 +5,11 @@
import './Params.css';
import React from 'react';
import classes from '@polkadot/ui-app/util/classes';
import { classes } from '@polkadot/ui-app/util';
import { isNull, isUndefined, u8aToHex } from '@polkadot/util';
// import IdentityIcon from '@polkadot/ui-react/IdentityIcon';
// import numberFormat from '@polkadot/ui-reactive/util/numberFormat';
// import formatNumber from '@polkadot/ui-app/util/formatNumber';
// import keyring from '@polkadot/ui-keyring';
// import u8aToHex from '@polkadot/util/u8a/toHex';
// import isBn from '@polkadot/util/is/bn';
@ -140,7 +140,7 @@ function valueToText (type: string, value: any, swallowError: boolean = true, co
// }
// if (isBn(value)) {
// return div({}, numberFormat(value));
// return div({}, formatNumber(value));
// }
// } catch (error) {
// if (!swallowError) {

View File

@ -0,0 +1,37 @@
// Copyright 2017-2019 @polkadot/ui-reactive 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 { BareProps, CallProps } from '@polkadot/ui-api/types';
import React from 'react';
import { AccountId, AccountIndex } from '@polkadot/types';
import { withCall } from '@polkadot/ui-api/index';
type Props = BareProps & CallProps & {
children?: React.ReactNode,
label?: string,
accounts_idAndIndex?: [AccountId?, AccountIndex?]
};
class AccountIndexDisplay extends React.PureComponent<Props> {
render () {
const { children, className, label = '', style, accounts_idAndIndex = [] } = this.props;
const [, accountIndex] = accounts_idAndIndex;
return (
<div
className={className}
style={style}
>
{label}{
accountIndex
? accountIndex.toString()
: '-'
}{children}
</div>
);
}
}
export default withCall('derive.accounts.idAndIndex', { paramName: 'value' })(AccountIndexDisplay);

View File

@ -7,8 +7,7 @@ import { BareProps, CallProps } from '@polkadot/ui-api/types';
import React from 'react';
import { Balance } from '@polkadot/types';
import { withCall } from '@polkadot/ui-api/index';
import { balanceFormat } from './util/index';
import { formatBalance } from '@polkadot/ui-app/util/index';
type Props = BareProps & CallProps & {
children?: React.ReactNode,
@ -27,7 +26,7 @@ class BalanceDisplay extends React.PureComponent<Props> {
>
{label}{
balances_freeBalance
? balanceFormat(balances_freeBalance)
? formatBalance(balances_freeBalance)
: '0'
}{children}
</div>
@ -35,4 +34,4 @@ class BalanceDisplay extends React.PureComponent<Props> {
}
}
export default withCall('query.balances.freeBalance')(BalanceDisplay);
export default withCall('query.balances.freeBalance', { paramName: 'value' })(BalanceDisplay);

View File

@ -7,8 +7,7 @@ import { BareProps, CallProps } from '@polkadot/ui-api/types';
import React from 'react';
import { BlockNumber } from '@polkadot/types';
import { withCall } from '@polkadot/ui-api/index';
import { numberFormat } from './util/index';
import { formatNumber } from '@polkadot/ui-app/util/index';
type Props = BareProps & CallProps & {
children?: React.ReactNode,
@ -27,7 +26,7 @@ class BestFinalised extends React.PureComponent<Props> {
>
{label}{
chain_bestNumberFinalised
? numberFormat(chain_bestNumberFinalised)
? formatNumber(chain_bestNumberFinalised)
: '-'
}{children}
</div>

View File

@ -7,8 +7,7 @@ import { BareProps, CallProps } from '@polkadot/ui-api/types';
import React from 'react';
import { BlockNumber } from '@polkadot/types';
import { withCall } from '@polkadot/ui-api/index';
import { numberFormat } from './util/index';
import { formatNumber } from '@polkadot/ui-app/util/index';
type Props = BareProps & CallProps & {
children?: React.ReactNode,
@ -27,7 +26,7 @@ class BestNumber extends React.PureComponent<Props> {
>
{label}{
chain_bestNumber
? numberFormat(chain_bestNumber)
? formatNumber(chain_bestNumber)
: '-'
}{children}
</div>

View File

@ -7,8 +7,7 @@ import { BareProps, CallProps } from '@polkadot/ui-api/types';
import React from 'react';
import { Index } from '@polkadot/types';
import { withCall } from '@polkadot/ui-api/index';
import { numberFormat } from './util/index';
import { formatNumber } from '@polkadot/ui-app/util/index';
type Props = BareProps & CallProps & {
children?: React.ReactNode,
@ -27,7 +26,7 @@ class Nonce extends React.PureComponent<Props> {
>
{label}{
system_accountNonce
? numberFormat(system_accountNonce)
? formatNumber(system_accountNonce)
: '0'
}{children}
</div>
@ -35,4 +34,4 @@ class Nonce extends React.PureComponent<Props> {
}
}
export default withCall('query.system.accountNonce')(Nonce);
export default withCall('query.system.accountNonce', { paramName: 'value' })(Nonce);

View File

@ -7,8 +7,7 @@ import { BareProps, CallProps } from '@polkadot/ui-api/types';
import React from 'react';
import { Moment } from '@polkadot/types';
import { withCall } from '@polkadot/ui-api/index';
import { numberFormat } from './util/index';
import { formatNumber } from '@polkadot/ui-app/util/index';
type Props = BareProps & CallProps & {
children?: React.ReactNode,
@ -27,7 +26,7 @@ class TimePeriod extends React.PureComponent<Props> {
>
{label}{
timestamp_blockPeriod
? `${numberFormat(timestamp_blockPeriod.toNumber() * 2)}s`
? `${formatNumber(timestamp_blockPeriod.toNumber() * 2)}s`
: '-'
}{children}
</div>

View File

@ -2,6 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
export { default as AccountIndex } from './AccountIndex';
export { default as Balance } from './Balance';
export { default as BestFinalised } from './BestFinalised';
export { default as BestNumber } from './BestNumber';

View File

@ -1,14 +0,0 @@
// Copyright 2017-2019 @polkadot/ui-reactive 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 balanceFormat, { calcSi } from './balanceFormat';
import decimalFormat from './decimalFormat';
import numberFormat from './numberFormat';
export {
balanceFormat,
calcSi,
decimalFormat,
numberFormat
};

View File

@ -11,7 +11,7 @@ import React from 'react';
import { Compact } from '@polkadot/types/codec';
import { withCall, withMulti } from '@polkadot/ui-api/index';
import { Icon } from '@polkadot/ui-app/index';
import { balanceFormat } from '@polkadot/ui-reactive/util/index';
import { formatBalance } from '@polkadot/ui-app/util';
import translate from '../translate';
@ -67,7 +67,7 @@ class Proposal extends React.PureComponent<Props, State> {
isBelowMinimum
? <div><Icon name='warning sign' />{t('The deposit is below the {{minimum}} minimum required for the proposal to be evaluated', {
replace: {
minimum: balanceFormat(democracy_minimumDeposit)
minimum: formatBalance(democracy_minimumDeposit)
}
})}</div>
: undefined
@ -77,7 +77,7 @@ class Proposal extends React.PureComponent<Props, State> {
? undefined
: <div><Icon name='arrow right' />{t('The deposit of {{deposit}} will be reserved until the proposal is completed', {
replace: {
deposit: balanceFormat(extraAmount)
deposit: formatBalance(extraAmount)
}
})}</div>
}

View File

@ -11,7 +11,7 @@ import React from 'react';
import { Compact } from '@polkadot/types/codec';
import { withCall, withMulti } from '@polkadot/ui-api/index';
import { Icon } from '@polkadot/ui-app/index';
import { balanceFormat } from '@polkadot/ui-reactive/util/index';
import { formatBalance } from '@polkadot/ui-app/util';
import translate from '../translate';
import { ZERO_BALANCE } from './constants';
@ -83,7 +83,7 @@ class Transfer extends React.PureComponent<Props, State> {
isCreation
? <div><Icon name='warning sign' />{t('A fee of {{creationFee}} will be deducted from the sender since the destination account does not exist', {
replace: {
creationFee: balanceFormat(fees.creationFee)
creationFee: formatBalance(fees.creationFee)
}
})}</div>
: undefined

View File

@ -9,9 +9,9 @@ import { ExtraFees } from './types';
import BN from 'bn.js';
import React from 'react';
import { Extrinsic, Method } from '@polkadot/types';
import { withCall, withMulti } from '@polkadot/ui-api/index';
import { withCalls } from '@polkadot/ui-api/index';
import { Icon } from '@polkadot/ui-app/index';
import { balanceFormat } from '@polkadot/ui-reactive/util/index';
import { formatBalance } from '@polkadot/ui-app/util';
import { compactToU8a } from '@polkadot/util';
import translate from '../translate';
@ -34,7 +34,7 @@ type Props = I18nProps & {
balances_fees?: DerivedFees,
balances_votingBalance?: DerivedBalances,
accountId?: string | null,
extrinsic: Extrinsic | null,
extrinsic?: Extrinsic | null,
onChange?: (hasAvailble: boolean) => void,
system_accountNonce?: BN
};
@ -157,12 +157,12 @@ class FeeDisplay extends React.PureComponent<Props, State> {
<div><Icon name='arrow right' />{t('Fees includes the transaction fee and the per-byte fee')}</div>
<div><Icon name='arrow right' />{t('Fees totalling {{fees}} will be applied to the submission', {
replace: {
fees: balanceFormat(allFees)
fees: formatBalance(allFees)
}
})}</div>
<div><Icon name='arrow right' />{t('{{total}} total transaction amount (fees + value)', {
replace: {
total: balanceFormat(allTotal)
total: formatBalance(allTotal)
}
})}</div>
</article>
@ -213,10 +213,10 @@ class FeeDisplay extends React.PureComponent<Props, State> {
}
}
export default withMulti(
FeeDisplay,
translate,
withCall('derive.balances.fees'),
withCall('derive.balances.votingBalance', { paramName: 'accountId' }),
withCall('query.system.accountNonce', { paramName: 'accountId' })
export default translate(
withCalls<Props>(
'derive.balances.fees',
['derive.balances.votingBalance', { paramName: 'accountId' }],
['query.system.accountNonce', { paramName: 'accountId' }]
)(FeeDisplay)
);

View File

@ -113,7 +113,7 @@ class Signer extends React.PureComponent<Props, State> {
isNegative
onClick={this.onCancel}
tabIndex={3}
text={t('Cancel')}
label={t('Cancel')}
/>
<Button.Or />
<Button
@ -121,7 +121,7 @@ class Signer extends React.PureComponent<Props, State> {
isPrimary
onClick={this.onSend}
tabIndex={2}
text={
label={
currentItem.isUnsigned
? t('Submit (no signature)')
: t('Sign and Submit')