Small init changes (static state) (#663)
* Small init changes (static state) * Hide vanity on empty accounts * Require accounts for apps, cleanup needsApi/needsCalls * Display InputAddress when disable (but no options) * Filter toolbox based on accounts * Accounts gated via app, don't display add * Cleanup linting * Validation display & clear on settings types * Split save for developer & general * Add Reset button to dev settings
This commit is contained in:
parent
15cc5190f0
commit
a8ed300dc4
@ -27,7 +27,7 @@ export default class Transfer extends React.PureComponent<Props> {
|
|||||||
<section>
|
<section>
|
||||||
<h1>transfer</h1>
|
<h1>transfer</h1>
|
||||||
<div className='ui--row'>
|
<div className='ui--row'>
|
||||||
<article className='medium'>
|
<div className='large'>
|
||||||
<InputAddress
|
<InputAddress
|
||||||
label='recipient address for this transfer'
|
label='recipient address for this transfer'
|
||||||
onChange={this.onChangeRecipient}
|
onChange={this.onChangeRecipient}
|
||||||
@ -45,7 +45,7 @@ export default class Transfer extends React.PureComponent<Props> {
|
|||||||
tx='balances.transfer'
|
tx='balances.transfer'
|
||||||
/>
|
/>
|
||||||
</Button.Group>
|
</Button.Group>
|
||||||
</article>
|
</div>
|
||||||
<div className='template--summary small'>Make a transfer from any account you control to another account. Transfer fees and per-transaction fees apply and will be calculated upon submission.</div>
|
<div className='template--summary small'>Make a transfer from any account you control to another account. Transfer fees and per-transaction fees apply and will be calculated upon submission.</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@ -25,16 +25,10 @@ type State = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Backup extends React.PureComponent<Props, State> {
|
class Backup extends React.PureComponent<Props, State> {
|
||||||
state: State;
|
state: State = {
|
||||||
|
isPassValid: false,
|
||||||
constructor (props: Props) {
|
password: ''
|
||||||
super(props);
|
};
|
||||||
|
|
||||||
this.state = {
|
|
||||||
isPassValid: false,
|
|
||||||
password: ''
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -26,18 +26,12 @@ type State = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class ChangePass extends React.PureComponent<Props, State> {
|
class ChangePass extends React.PureComponent<Props, State> {
|
||||||
state: State;
|
state: State = {
|
||||||
|
isNewValid: false,
|
||||||
constructor (props: Props) {
|
isOldValid: false,
|
||||||
super(props);
|
newPass: '',
|
||||||
|
oldPass: ''
|
||||||
this.state = {
|
};
|
||||||
isNewValid: false,
|
|
||||||
isOldValid: false,
|
|
||||||
newPass: '',
|
|
||||||
oldPass: ''
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -25,18 +25,12 @@ type State = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Restore extends React.PureComponent<Props, State> {
|
class Restore extends React.PureComponent<Props, State> {
|
||||||
state: State;
|
state: State = {
|
||||||
|
isFileValid: false,
|
||||||
constructor (props: Props) {
|
isPassValid: false,
|
||||||
super(props);
|
json: null,
|
||||||
|
password: ''
|
||||||
this.state = {
|
};
|
||||||
isFileValid: false,
|
|
||||||
isPassValid: false,
|
|
||||||
json: null,
|
|
||||||
password: ''
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { t } = this.props;
|
const { t } = this.props;
|
||||||
|
|||||||
@ -27,7 +27,7 @@ type Props = AppProps & I18nProps & {
|
|||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
hidden: Array<string>,
|
hidden: Array<string>,
|
||||||
items: Array<TabItem>
|
tabs: Array<TabItem>
|
||||||
};
|
};
|
||||||
|
|
||||||
class AccountsApp extends React.PureComponent<Props, State> {
|
class AccountsApp extends React.PureComponent<Props, State> {
|
||||||
@ -43,7 +43,7 @@ class AccountsApp extends React.PureComponent<Props, State> {
|
|||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
...baseState,
|
...baseState,
|
||||||
items: [
|
tabs: [
|
||||||
{
|
{
|
||||||
name: 'edit',
|
name: 'edit',
|
||||||
text: t('Edit account')
|
text: t('Edit account')
|
||||||
@ -72,8 +72,10 @@ class AccountsApp extends React.PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static hideEditState () {
|
static hideEditState () {
|
||||||
|
// Hide vanity as well - since the route order and matching changes, the
|
||||||
|
// /create/:seed route become problematic, so don't allow that option
|
||||||
return {
|
return {
|
||||||
hidden: ['edit']
|
hidden: ['edit', 'vanity']
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +95,7 @@ class AccountsApp extends React.PureComponent<Props, State> {
|
|||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { basePath } = this.props;
|
const { basePath } = this.props;
|
||||||
const { hidden, items } = this.state;
|
const { hidden, tabs } = this.state;
|
||||||
const renderCreator = this.renderComponent(Creator);
|
const renderCreator = this.renderComponent(Creator);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -102,7 +104,7 @@ class AccountsApp extends React.PureComponent<Props, State> {
|
|||||||
<Tabs
|
<Tabs
|
||||||
basePath={basePath}
|
basePath={basePath}
|
||||||
hidden={hidden}
|
hidden={hidden}
|
||||||
items={items}
|
items={tabs}
|
||||||
/>
|
/>
|
||||||
</header>
|
</header>
|
||||||
<Switch>
|
<Switch>
|
||||||
@ -122,13 +124,14 @@ class AccountsApp extends React.PureComponent<Props, State> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderComponent = (Component: React.ComponentType<ComponentProps>) => {
|
private renderComponent (Component: React.ComponentType<ComponentProps>) {
|
||||||
return ({ match }: LocationProps) => {
|
return ({ match }: LocationProps) => {
|
||||||
const { basePath, onStatusChange } = this.props;
|
const { basePath, location, onStatusChange } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Component
|
<Component
|
||||||
basePath={basePath}
|
basePath={basePath}
|
||||||
|
location={location}
|
||||||
match={match}
|
match={match}
|
||||||
onStatusChange={onStatusChange}
|
onStatusChange={onStatusChange}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -107,13 +107,14 @@ class AddressesApp extends React.PureComponent<Props, State> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderComponent = (Component: React.ComponentType<ComponentProps>) => {
|
private renderComponent (Component: React.ComponentType<ComponentProps>) {
|
||||||
return () => {
|
return () => {
|
||||||
const { basePath, onStatusChange } = this.props;
|
const { basePath, location, onStatusChange } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Component
|
<Component
|
||||||
basePath={basePath}
|
basePath={basePath}
|
||||||
|
location={location}
|
||||||
onStatusChange={onStatusChange}
|
onStatusChange={onStatusChange}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -44,20 +44,14 @@ type State = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Referendum extends React.PureComponent<Props, State> {
|
class Referendum extends React.PureComponent<Props, State> {
|
||||||
state: State;
|
state: State = {
|
||||||
|
voteCount: 0,
|
||||||
constructor (props: Props) {
|
voteCountYay: 0,
|
||||||
super(props);
|
voteCountNay: 0,
|
||||||
|
votedTotal: new BN(0),
|
||||||
this.state = {
|
votedYay: new BN(0),
|
||||||
voteCount: 0,
|
votedNay: new BN(0)
|
||||||
voteCountYay: 0,
|
};
|
||||||
voteCountNay: 0,
|
|
||||||
votedTotal: new BN(0),
|
|
||||||
votedYay: new BN(0),
|
|
||||||
votedNay: new BN(0)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static getDerivedStateFromProps ({ democracy_referendumVotesFor }: Props, prevState: State): State | null {
|
static getDerivedStateFromProps ({ democracy_referendumVotesFor }: Props, prevState: State): State | null {
|
||||||
if (!democracy_referendumVotesFor) {
|
if (!democracy_referendumVotesFor) {
|
||||||
|
|||||||
@ -24,14 +24,10 @@ type State = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class EventsRecent extends React.PureComponent<Props, State> {
|
class EventsRecent extends React.PureComponent<Props, State> {
|
||||||
constructor (props: Props) {
|
state: State = {
|
||||||
super(props);
|
prevEventHash: '',
|
||||||
|
recentEvents: []
|
||||||
this.state = {
|
};
|
||||||
prevEventHash: '',
|
|
||||||
recentEvents: []
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static getDerivedStateFromProps ({ system_events = [] }: Props, prevState: State): State | null {
|
static getDerivedStateFromProps ({ system_events = [] }: Props, prevState: State): State | null {
|
||||||
const prevEventHash = xxhashAsHex(stringToU8a(JSON.stringify(system_events)));
|
const prevEventHash = xxhashAsHex(stringToU8a(JSON.stringify(system_events)));
|
||||||
|
|||||||
@ -8,33 +8,17 @@ import { AppProps, I18nProps } from '@polkadot/ui-app/types';
|
|||||||
import './index.css';
|
import './index.css';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { QueueConsumer } from '@polkadot/ui-app/Status/Context';
|
import { QueueConsumer } from '@polkadot/ui-app/Status/Context';
|
||||||
import { Tabs } from '@polkadot/ui-app/index';
|
import { Tabs } from '@polkadot/ui-app/index';
|
||||||
import accountsObservable from '@polkadot/ui-keyring/observable/accounts';
|
|
||||||
import { withMulti, withObservable } from '@polkadot/ui-api/index';
|
|
||||||
|
|
||||||
import Selection from './Selection';
|
import Selection from './Selection';
|
||||||
import translate from './translate';
|
import translate from './translate';
|
||||||
|
|
||||||
type Props = AppProps & I18nProps & {
|
type Props = AppProps & I18nProps;
|
||||||
accountAll?: Array<any>
|
|
||||||
};
|
|
||||||
|
|
||||||
class ExtrinsicsApp extends React.PureComponent<Props> {
|
class ExtrinsicsApp extends React.PureComponent<Props> {
|
||||||
render () {
|
render () {
|
||||||
const { accountAll, basePath, t } = this.props;
|
const { basePath, t } = this.props;
|
||||||
|
|
||||||
if (!accountAll || !Object.keys(accountAll).length) {
|
|
||||||
return (
|
|
||||||
<main className='extrinsics--App'>
|
|
||||||
{t('There are no saved accounts. ')}
|
|
||||||
<Link to='/accounts'>
|
|
||||||
{t('Add Accounts.')}
|
|
||||||
</Link>
|
|
||||||
</main>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className='extrinsics--App'>
|
<main className='extrinsics--App'>
|
||||||
@ -59,8 +43,4 @@ class ExtrinsicsApp extends React.PureComponent<Props> {
|
|||||||
|
|
||||||
export { ExtrinsicsApp };
|
export { ExtrinsicsApp };
|
||||||
|
|
||||||
export default withMulti(
|
export default translate(ExtrinsicsApp);
|
||||||
ExtrinsicsApp,
|
|
||||||
translate,
|
|
||||||
withObservable(accountsObservable.subject, { propName: 'accountAll' })
|
|
||||||
);
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
/* of the Apache-2.0 license. See the LICENSE file for details. */
|
/* of the Apache-2.0 license. See the LICENSE file for details. */
|
||||||
|
|
||||||
.sub-label {
|
.sub-label {
|
||||||
|
cursor: pointer;
|
||||||
padding: 0rem .5833rem;
|
padding: 0rem .5833rem;
|
||||||
font-size: .85rem;
|
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,12 +3,14 @@
|
|||||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||||
|
|
||||||
import { AppProps, I18nProps } from '@polkadot/ui-app/types';
|
import { AppProps, I18nProps } from '@polkadot/ui-app/types';
|
||||||
|
import { TabItem } from '@polkadot/ui-app/Tabs';
|
||||||
import { SettingsStruct } from '@polkadot/ui-settings/types';
|
import { SettingsStruct } from '@polkadot/ui-settings/types';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { Route, Switch } from 'react-router';
|
||||||
import store from 'store';
|
import store from 'store';
|
||||||
import typeRegistry from '@polkadot/types/codec/typeRegistry';
|
import typeRegistry from '@polkadot/types/codec/typeRegistry';
|
||||||
import { Button, Dropdown, Input, InputFile } from '@polkadot/ui-app/index';
|
import { Button, Dropdown, Input, InputFile, Tabs } from '@polkadot/ui-app/index';
|
||||||
import uiSettings from '@polkadot/ui-settings';
|
import uiSettings from '@polkadot/ui-settings';
|
||||||
import { u8aToString } from '@polkadot/util';
|
import { u8aToString } from '@polkadot/util';
|
||||||
|
|
||||||
@ -19,130 +21,193 @@ import translate from './translate';
|
|||||||
type Props = AppProps & I18nProps;
|
type Props = AppProps & I18nProps;
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
settings: SettingsStruct & {
|
isCustomNode: boolean,
|
||||||
types?: { [index: string]: any } | null,
|
isTypesValid: boolean,
|
||||||
typesError?: boolean,
|
isUrlValid: boolean,
|
||||||
typesPlaceholder?: string,
|
settings: SettingsStruct,
|
||||||
customNode: boolean
|
tabs: Array<TabItem>,
|
||||||
}
|
types?: { [index: string]: any } | null,
|
||||||
|
typesPlaceholder?: string
|
||||||
};
|
};
|
||||||
|
|
||||||
class App extends React.PureComponent<Props, State> {
|
class App extends React.PureComponent<Props, State> {
|
||||||
constructor (props: Props) {
|
constructor (props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
|
const { t } = props;
|
||||||
const types = store.get('types') || {};
|
const types = store.get('types') || {};
|
||||||
const names = Object.keys(types);
|
const names = Object.keys(types);
|
||||||
const presets = uiSettings.get();
|
const settings = uiSettings.get();
|
||||||
|
let isCustomNode = true;
|
||||||
|
|
||||||
// check to see if user has saved a custom node by seeing if their URL is equal to any preset
|
// check to see if user has saved a custom node by seeing if their URL is equal to any preset
|
||||||
let customNode = true;
|
|
||||||
for (let i = 0; i < uiSettings.availableNodes.length; i++) {
|
for (let i = 0; i < uiSettings.availableNodes.length; i++) {
|
||||||
if (uiSettings.availableNodes[i].value === presets.apiUrl) {
|
if (uiSettings.availableNodes[i].value === settings.apiUrl) {
|
||||||
customNode = false;
|
isCustomNode = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
settings: {
|
isCustomNode,
|
||||||
...presets,
|
isTypesValid: true,
|
||||||
typesPlaceholder: names.length
|
isUrlValid: this.isValidUrl(settings.apiUrl),
|
||||||
? names.join(', ')
|
tabs: [
|
||||||
: undefined,
|
{
|
||||||
customNode: customNode
|
name: 'general',
|
||||||
}
|
text: t('General')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'developer',
|
||||||
|
text: t('Developer')
|
||||||
|
}
|
||||||
|
],
|
||||||
|
typesPlaceholder: names.length
|
||||||
|
? names.join(', ')
|
||||||
|
: undefined,
|
||||||
|
settings
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { t } = this.props;
|
const { basePath } = this.props;
|
||||||
const { settings: { apiUrl, i18nLang, typesPlaceholder, typesError, uiMode, uiTheme, customNode } } = this.state;
|
const { tabs } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className='settings--App'>
|
<main className='settings--App'>
|
||||||
<section>
|
<header>
|
||||||
<h1>{t('general')}</h1>
|
<Tabs
|
||||||
<div className='ui--row'>
|
basePath={basePath}
|
||||||
<div className='full'>
|
items={tabs}
|
||||||
<div className='sub-label'>
|
|
||||||
{
|
|
||||||
customNode
|
|
||||||
? <><a onClick={this.toggleCustomNode}>{t('pre-set')}</a> | <b>{t('custom')}</b></>
|
|
||||||
: <><b>{t('pre-set')}</b> | <a onClick={this.toggleCustomNode}>{t('custom')}</a></>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
{
|
|
||||||
customNode
|
|
||||||
? <Input
|
|
||||||
defaultValue={apiUrl}
|
|
||||||
label={t('remote node/endpoint to connect to')}
|
|
||||||
onChange={this.onChangeApiUrl}
|
|
||||||
/>
|
|
||||||
: <Dropdown
|
|
||||||
defaultValue={apiUrl}
|
|
||||||
label={t('remote node/endpoint to connect to')}
|
|
||||||
onChange={this.onChangeApiUrl}
|
|
||||||
options={uiSettings.availableNodes}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className='ui--row'>
|
|
||||||
<div className='medium'>
|
|
||||||
<Dropdown
|
|
||||||
defaultValue={uiTheme}
|
|
||||||
label={t('default interface theme')}
|
|
||||||
onChange={this.onChangeUiTheme}
|
|
||||||
options={uiSettings.availableUIThemes}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className='medium'>
|
|
||||||
<Dropdown
|
|
||||||
defaultValue={uiMode}
|
|
||||||
label={t('interface operation mode')}
|
|
||||||
onChange={this.onChangeUiMode}
|
|
||||||
options={uiSettings.availableUIModes}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className='ui--row'>
|
|
||||||
<div className='full'>
|
|
||||||
<Dropdown
|
|
||||||
defaultValue={i18nLang}
|
|
||||||
isDisabled
|
|
||||||
label={t('default interface language')}
|
|
||||||
onChange={this.onChangeLang}
|
|
||||||
options={uiSettings.availableLanguages}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h1>{t('developer')}</h1>
|
|
||||||
<div className='ui--row'>
|
|
||||||
<div className='full'>
|
|
||||||
<InputFile
|
|
||||||
isError={typesError}
|
|
||||||
label={t('additional type definitions (JSON)')}
|
|
||||||
onChange={this.onChangeTypes}
|
|
||||||
placeholder={typesPlaceholder}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<Button.Group>
|
|
||||||
<Button
|
|
||||||
isPrimary
|
|
||||||
onClick={this.save}
|
|
||||||
label={t('Save & Reload')}
|
|
||||||
/>
|
/>
|
||||||
</Button.Group>
|
</header>
|
||||||
|
<Switch>
|
||||||
|
<Route path={`${basePath}/developer`} render={this.renderDeveloper} />
|
||||||
|
<Route render={this.renderGeneral} />
|
||||||
|
</Switch>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private renderDeveloper = () => {
|
||||||
|
const { t } = this.props;
|
||||||
|
const { isTypesValid, types, typesPlaceholder } = this.state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className='ui--row'>
|
||||||
|
<div className='full'>
|
||||||
|
<InputFile
|
||||||
|
clearContent={!types && isTypesValid}
|
||||||
|
isError={!isTypesValid}
|
||||||
|
label={t('additional type definitions (JSON)')}
|
||||||
|
onChange={this.onChangeTypes}
|
||||||
|
placeholder={typesPlaceholder}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Button.Group>
|
||||||
|
<Button
|
||||||
|
isDisabled={!types}
|
||||||
|
isNegative
|
||||||
|
onClick={this.clearTypes}
|
||||||
|
label={t('Reset')}
|
||||||
|
/>
|
||||||
|
<Button.Or />
|
||||||
|
<Button
|
||||||
|
isDisabled={!isTypesValid}
|
||||||
|
isPrimary
|
||||||
|
onClick={this.saveDeveloper}
|
||||||
|
label={t('Save')}
|
||||||
|
/>
|
||||||
|
</Button.Group>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderGeneral = () => {
|
||||||
|
const { t } = this.props;
|
||||||
|
const { isCustomNode, isUrlValid, settings: { apiUrl, i18nLang, uiMode, uiTheme } } = this.state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className='ui--row'>
|
||||||
|
<div className='full'>
|
||||||
|
<div className='sub-label'>
|
||||||
|
{
|
||||||
|
isCustomNode
|
||||||
|
? <><a onClick={this.toggleCustomNode}>{t('pre-set')}</a> | <b>{t('custom')}</b></>
|
||||||
|
: <><b>{t('pre-set')}</b> | <a onClick={this.toggleCustomNode}>{t('custom')}</a></>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
{
|
||||||
|
isCustomNode
|
||||||
|
? <Input
|
||||||
|
defaultValue={apiUrl}
|
||||||
|
isError={!isUrlValid}
|
||||||
|
label={t('remote node/endpoint to connect to')}
|
||||||
|
onChange={this.onChangeApiUrl}
|
||||||
|
/>
|
||||||
|
: <Dropdown
|
||||||
|
defaultValue={apiUrl}
|
||||||
|
label={t('remote node/endpoint to connect to')}
|
||||||
|
onChange={this.onChangeApiUrl}
|
||||||
|
options={uiSettings.availableNodes}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='ui--row'>
|
||||||
|
<div className='medium'>
|
||||||
|
<Dropdown
|
||||||
|
defaultValue={uiTheme}
|
||||||
|
label={t('default interface theme')}
|
||||||
|
onChange={this.onChangeUiTheme}
|
||||||
|
options={uiSettings.availableUIThemes}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='medium'>
|
||||||
|
<Dropdown
|
||||||
|
defaultValue={uiMode}
|
||||||
|
label={t('interface operation mode')}
|
||||||
|
onChange={this.onChangeUiMode}
|
||||||
|
options={uiSettings.availableUIModes}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='ui--row'>
|
||||||
|
<div className='full'>
|
||||||
|
<Dropdown
|
||||||
|
defaultValue={i18nLang}
|
||||||
|
isDisabled
|
||||||
|
label={t('default interface language')}
|
||||||
|
onChange={this.onChangeLang}
|
||||||
|
options={uiSettings.availableLanguages}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Button.Group>
|
||||||
|
<Button
|
||||||
|
isDisabled={!isUrlValid}
|
||||||
|
isPrimary
|
||||||
|
onClick={this.saveAndReload}
|
||||||
|
label={t('Save & Reload')}
|
||||||
|
/>
|
||||||
|
</Button.Group>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private clearTypes = (): void => {
|
||||||
|
this.setState({
|
||||||
|
isTypesValid: true,
|
||||||
|
types: null,
|
||||||
|
typesPlaceholder: ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private onChangeApiUrl = (apiUrl: string): void => {
|
private onChangeApiUrl = (apiUrl: string): void => {
|
||||||
this.setState(({ settings }: State) => ({
|
this.setState(({ settings }: State) => ({
|
||||||
|
isUrlValid: this.isValidUrl(apiUrl),
|
||||||
settings: {
|
settings: {
|
||||||
...settings,
|
...settings,
|
||||||
apiUrl
|
apiUrl
|
||||||
@ -163,25 +228,19 @@ class App extends React.PureComponent<Props, State> {
|
|||||||
|
|
||||||
typeRegistry.register(types);
|
typeRegistry.register(types);
|
||||||
|
|
||||||
this.setState(({ settings }: State) => ({
|
this.setState({
|
||||||
settings: {
|
isTypesValid: true,
|
||||||
...settings,
|
types,
|
||||||
types,
|
typesPlaceholder
|
||||||
typesError: false,
|
});
|
||||||
typesPlaceholder
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Registering types:', error);
|
console.error('Registering types:', error);
|
||||||
|
|
||||||
this.setState(({ settings }: State) => ({
|
this.setState({
|
||||||
settings: {
|
isTypesValid: false,
|
||||||
...settings,
|
types: null,
|
||||||
types: null,
|
typesPlaceholder: error.message
|
||||||
typesError: true,
|
});
|
||||||
typesPlaceholder: error.message
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,49 +263,44 @@ class App extends React.PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private toggleCustomNode = (): void => {
|
private toggleCustomNode = (): void => {
|
||||||
this.setState(({ settings }: State) => {
|
this.setState(({ isCustomNode, settings }: State) => {
|
||||||
const customNode = !settings.customNode;
|
|
||||||
// reset URL to a preset when toggled to preset
|
// reset URL to a preset when toggled to preset
|
||||||
const apiUrl = customNode
|
const apiUrl = isCustomNode
|
||||||
? settings.apiUrl
|
? uiSettings.availableNodes[0].value
|
||||||
: uiSettings.availableNodes[0].value;
|
: settings.apiUrl;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
isCustomNode: !isCustomNode,
|
||||||
|
isUrlValid: true,
|
||||||
settings: {
|
settings: {
|
||||||
...settings,
|
...settings,
|
||||||
apiUrl,
|
apiUrl
|
||||||
customNode
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private save = (): void => {
|
private isValidUrl (apiUrl: string): boolean {
|
||||||
const { onStatusChange, t } = this.props;
|
return (
|
||||||
const { settings: { types, typesError } } = this.state;
|
// some random length... we probably want to parse via some lib
|
||||||
|
(apiUrl.length >= 7) &&
|
||||||
|
// check that it starts with a valid ws identifier
|
||||||
|
(apiUrl.startsWith('ws://') || apiUrl.startsWith('wss://'))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// validate custom node url
|
private saveDeveloper = (): void => {
|
||||||
const apiUrl = this.state.settings.apiUrl;
|
const { isTypesValid, types } = this.state;
|
||||||
|
|
||||||
if (this.state.settings.customNode) {
|
if (isTypesValid) {
|
||||||
if (!(apiUrl.startsWith('ws://localhost') ||
|
|
||||||
apiUrl.startsWith('ws://127.0.0.1') ||
|
|
||||||
apiUrl.startsWith('wss://'))) {
|
|
||||||
onStatusChange({
|
|
||||||
action: '',
|
|
||||||
status: 'error',
|
|
||||||
message: t('Custom node URL is not valid')
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uiSettings.set(this.state.settings);
|
|
||||||
|
|
||||||
if (types && !typesError) {
|
|
||||||
store.set('types', types);
|
store.set('types', types);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private saveAndReload = (): void => {
|
||||||
|
const { settings } = this.state;
|
||||||
|
|
||||||
|
uiSettings.set(settings);
|
||||||
|
|
||||||
// HACK This is terribe, but since the API needs to re-connect, but since
|
// HACK This is terribe, but since the API needs to re-connect, but since
|
||||||
// the API does not yet handle re-connections properly, it is what it is
|
// the API does not yet handle re-connections properly, it is what it is
|
||||||
|
|||||||
@ -37,15 +37,11 @@ type State = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Account extends React.PureComponent<Props, State> {
|
class Account extends React.PureComponent<Props, State> {
|
||||||
constructor (props: Props) {
|
state: State = {
|
||||||
super(props);
|
isNominateOpen: false,
|
||||||
|
isNominating: false,
|
||||||
this.state = {
|
isPrefsOpen: false
|
||||||
isNominateOpen: false,
|
};
|
||||||
isNominating: false,
|
|
||||||
isPrefsOpen: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static getDerivedStateFromProps ({ staking_nominating }: Props) {
|
static getDerivedStateFromProps ({ staking_nominating }: Props) {
|
||||||
const isNominating = !!staking_nominating && !staking_nominating.isEmpty;
|
const isNominating = !!staking_nominating && !staking_nominating.isEmpty;
|
||||||
|
|||||||
@ -24,17 +24,11 @@ type State = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Nominating extends React.PureComponent<Props, State> {
|
class Nominating extends React.PureComponent<Props, State> {
|
||||||
state: State;
|
state: State = {
|
||||||
|
isNomineeValid: false,
|
||||||
constructor (props: Props) {
|
isAddressFormatValid: false,
|
||||||
super(props);
|
nominee: ''
|
||||||
|
};
|
||||||
this.state = {
|
|
||||||
isNomineeValid: false,
|
|
||||||
isAddressFormatValid: false,
|
|
||||||
nominee: ''
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { isOpen, style } = this.props;
|
const { isOpen, style } = this.props;
|
||||||
|
|||||||
@ -86,7 +86,7 @@ class App extends React.PureComponent<Props, State> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderComponent = (Component: React.ComponentType<ComponentProps>) => {
|
private renderComponent (Component: React.ComponentType<ComponentProps>) {
|
||||||
return (): React.ReactNode => {
|
return (): React.ReactNode => {
|
||||||
const { intentions, validators } = this.state;
|
const { intentions, validators } = this.state;
|
||||||
const { balances = {} } = this.props;
|
const { balances = {} } = this.props;
|
||||||
|
|||||||
@ -20,16 +20,10 @@ type State = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Raw extends React.PureComponent<Props, State> {
|
class Raw extends React.PureComponent<Props, State> {
|
||||||
state: State;
|
state: State = {
|
||||||
|
isValid: false,
|
||||||
constructor (props: Props) {
|
key: new Uint8Array([])
|
||||||
super(props);
|
};
|
||||||
|
|
||||||
this.state = {
|
|
||||||
isValid: false,
|
|
||||||
key: new Uint8Array([])
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { t } = this.props;
|
const { t } = this.props;
|
||||||
|
|||||||
@ -65,7 +65,7 @@ class Selection extends React.PureComponent<Props, State> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderComponent = (Component: React.ComponentType<ComponentProps>) => {
|
private renderComponent (Component: React.ComponentType<ComponentProps>) {
|
||||||
return (): React.ReactNode => {
|
return (): React.ReactNode => {
|
||||||
return (
|
return (
|
||||||
<Component onAdd={this.onAdd} />
|
<Component onAdd={this.onAdd} />
|
||||||
|
|||||||
@ -3,12 +3,15 @@
|
|||||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||||
|
|
||||||
import { AppProps, I18nProps } from '@polkadot/ui-app/types';
|
import { AppProps, I18nProps } from '@polkadot/ui-app/types';
|
||||||
|
import { SubjectInfo } from '@polkadot/ui-keyring/observable/types';
|
||||||
|
|
||||||
import './index.css';
|
import './index.css';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Route, Switch } from 'react-router';
|
import { Route, Switch } from 'react-router';
|
||||||
import Tabs, { TabItem } from '@polkadot/ui-app/Tabs';
|
import Tabs, { TabItem } from '@polkadot/ui-app/Tabs';
|
||||||
|
import accountObservable from '@polkadot/ui-keyring/observable/accounts';
|
||||||
|
import { withMulti, withObservable } from '@polkadot/ui-api/index';
|
||||||
|
|
||||||
import Hash from './Hash';
|
import Hash from './Hash';
|
||||||
import Rpc from './Rpc';
|
import Rpc from './Rpc';
|
||||||
@ -16,7 +19,9 @@ import Sign from './Sign';
|
|||||||
import Verify from './Verify';
|
import Verify from './Verify';
|
||||||
import translate from './translate';
|
import translate from './translate';
|
||||||
|
|
||||||
type Props = AppProps & I18nProps;
|
type Props = AppProps & I18nProps & {
|
||||||
|
allAccounts?: SubjectInfo
|
||||||
|
};
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
tabs: Array<TabItem>
|
tabs: Array<TabItem>
|
||||||
@ -32,7 +37,7 @@ class ToolboxApp extends React.PureComponent<Props, State> {
|
|||||||
tabs: [
|
tabs: [
|
||||||
{
|
{
|
||||||
name: 'rpc',
|
name: 'rpc',
|
||||||
text: 'RPC calls'
|
text: t('RPC calls')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'hash',
|
name: 'hash',
|
||||||
@ -50,15 +55,21 @@ class ToolboxApp extends React.PureComponent<Props, State> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
render () {
|
render () {
|
||||||
const { basePath } = this.props;
|
const { allAccounts = {}, basePath } = this.props;
|
||||||
const { tabs } = this.state;
|
const { tabs } = this.state;
|
||||||
|
const hasAccounts = Object.keys(allAccounts).length !== 0;
|
||||||
|
const filteredTabs = hasAccounts
|
||||||
|
? tabs
|
||||||
|
: tabs.filter(({ name }) =>
|
||||||
|
!['sign', 'verify'].includes(name)
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className='toolbox--App'>
|
<main className='toolbox--App'>
|
||||||
<header>
|
<header>
|
||||||
<Tabs
|
<Tabs
|
||||||
basePath={basePath}
|
basePath={basePath}
|
||||||
items={tabs}
|
items={filteredTabs}
|
||||||
/>
|
/>
|
||||||
</header>
|
</header>
|
||||||
<Switch>
|
<Switch>
|
||||||
@ -72,4 +83,8 @@ class ToolboxApp extends React.PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default translate(ToolboxApp);
|
export default withMulti(
|
||||||
|
ToolboxApp,
|
||||||
|
translate,
|
||||||
|
withObservable(accountObservable.subject, { propName: 'allAccounts' })
|
||||||
|
);
|
||||||
|
|||||||
@ -31,19 +31,13 @@ type State = {
|
|||||||
const ZERO = new BN(0);
|
const ZERO = new BN(0);
|
||||||
|
|
||||||
class Transfer extends React.PureComponent<Props, State> {
|
class Transfer extends React.PureComponent<Props, State> {
|
||||||
state: State;
|
state: State = {
|
||||||
|
accountId: null,
|
||||||
constructor (props: Props) {
|
amount: ZERO,
|
||||||
super(props);
|
extrinsic: null,
|
||||||
|
hasAvailable: true,
|
||||||
this.state = {
|
recipientId: null
|
||||||
accountId: null,
|
};
|
||||||
amount: ZERO,
|
|
||||||
extrinsic: null,
|
|
||||||
hasAvailable: true,
|
|
||||||
recipientId: null
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { t } = this.props;
|
const { t } = this.props;
|
||||||
|
|||||||
@ -3,12 +3,8 @@
|
|||||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||||
|
|
||||||
import { AppProps, I18nProps } from '@polkadot/ui-app/types';
|
import { AppProps, I18nProps } from '@polkadot/ui-app/types';
|
||||||
import { SubjectInfo } from '@polkadot/ui-keyring/observable/types';
|
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Trans } from 'react-i18next';
|
|
||||||
import accountObservable from '@polkadot/ui-keyring/observable/accounts';
|
|
||||||
import { withMulti, withObservable } from '@polkadot/ui-api/index';
|
|
||||||
import { Tabs } from '@polkadot/ui-app/index';
|
import { Tabs } from '@polkadot/ui-app/index';
|
||||||
|
|
||||||
import './index.css';
|
import './index.css';
|
||||||
@ -16,34 +12,14 @@ import './index.css';
|
|||||||
import Transfer from './Transfer';
|
import Transfer from './Transfer';
|
||||||
import translate from './translate';
|
import translate from './translate';
|
||||||
|
|
||||||
type Props = AppProps & I18nProps & {
|
type Props = AppProps & I18nProps;
|
||||||
allAccounts?: SubjectInfo
|
|
||||||
};
|
|
||||||
|
|
||||||
class App extends React.PureComponent<Props> {
|
class App extends React.PureComponent<Props> {
|
||||||
render () {
|
render () {
|
||||||
|
const { basePath, t } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className='transfer--App'>
|
<main className='transfer--App'>
|
||||||
{this.renderBody()}
|
|
||||||
</main>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private renderBody () {
|
|
||||||
const { allAccounts, basePath, t } = this.props;
|
|
||||||
|
|
||||||
if (!allAccounts || !Object.keys(allAccounts).length) {
|
|
||||||
return (
|
|
||||||
<div className='transfer--App-no-accounts'>
|
|
||||||
<Trans i18nKey='no-accounts'>
|
|
||||||
You currently have no active accounts. Before you are able to transfer, add <a href='#/accounts'>an account</a>.
|
|
||||||
</Trans>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<header>
|
<header>
|
||||||
<Tabs
|
<Tabs
|
||||||
basePath={basePath}
|
basePath={basePath}
|
||||||
@ -54,13 +30,9 @@ class App extends React.PureComponent<Props> {
|
|||||||
/>
|
/>
|
||||||
</header>
|
</header>
|
||||||
<Transfer />
|
<Transfer />
|
||||||
</>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withMulti(
|
export default translate(App);
|
||||||
App,
|
|
||||||
translate,
|
|
||||||
withObservable(accountObservable.subject, { propName: 'allAccounts' })
|
|
||||||
);
|
|
||||||
|
|||||||
@ -23,7 +23,9 @@ type Props = I18nProps & ApiProps & {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const unknown = {
|
const unknown = {
|
||||||
isApiGated: false,
|
display: {
|
||||||
|
needsApi: undefined
|
||||||
|
},
|
||||||
Component: NotFound,
|
Component: NotFound,
|
||||||
name: ''
|
name: ''
|
||||||
};
|
};
|
||||||
@ -32,11 +34,11 @@ class Content extends React.Component<Props> {
|
|||||||
render () {
|
render () {
|
||||||
const { isApiConnected, isApiReady, location, t } = this.props;
|
const { isApiConnected, isApiReady, location, t } = this.props;
|
||||||
const app = location.pathname.slice(1) || '';
|
const app = location.pathname.slice(1) || '';
|
||||||
const { Component, isApiGated, name } = routing.routes.find((route) =>
|
const { Component, display: { needsApi }, name } = routing.routes.find((route) =>
|
||||||
!!(route && app.indexOf(route.name) === 0)
|
!!(route && app.indexOf(route.name) === 0)
|
||||||
) || unknown;
|
) || unknown;
|
||||||
|
|
||||||
if (isApiGated && (!isApiReady || !isApiConnected)) {
|
if (needsApi && (!isApiReady || !isApiConnected)) {
|
||||||
return (
|
return (
|
||||||
<div className='apps--Content-body'>
|
<div className='apps--Content-body'>
|
||||||
<main>{t('Waiting for API to be connected and ready.')}</main>
|
<main>{t('Waiting for API to be connected and ready.')}</main>
|
||||||
@ -51,6 +53,7 @@ class Content extends React.Component<Props> {
|
|||||||
<Component
|
<Component
|
||||||
key='content-content'
|
key='content-content'
|
||||||
basePath={`/${name}`}
|
basePath={`/${name}`}
|
||||||
|
location={location}
|
||||||
onStatusChange={queueAction}
|
onStatusChange={queueAction}
|
||||||
/>,
|
/>,
|
||||||
<Status
|
<Status
|
||||||
@ -67,12 +70,12 @@ class Content extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// React-router needs to be first, otherwise we have blocked updates
|
// 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(
|
export default withMulti(
|
||||||
Content,
|
Content,
|
||||||
withRouter,
|
withRouter,
|
||||||
translate,
|
translate,
|
||||||
|
// These API queries are used in a number of places, warm them up
|
||||||
|
// to avoid constant un-/re-subscribe on these
|
||||||
withCalls<Props>(
|
withCalls<Props>(
|
||||||
'query.session.validators',
|
'query.session.validators',
|
||||||
'derive.accounts.indexes',
|
'derive.accounts.indexes',
|
||||||
|
|||||||
@ -4,16 +4,19 @@
|
|||||||
|
|
||||||
import { I18nProps } from '@polkadot/ui-app/types';
|
import { I18nProps } from '@polkadot/ui-app/types';
|
||||||
import { ApiProps } from '@polkadot/ui-api/types';
|
import { ApiProps } from '@polkadot/ui-api/types';
|
||||||
|
import { SubjectInfo } from '@polkadot/ui-keyring/observable/types';
|
||||||
import { Route } from '../types';
|
import { Route } from '../types';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { withRouter } from 'react-router';
|
import { withRouter } from 'react-router';
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
import { Icon, Menu } from '@polkadot/ui-app/index';
|
import { Icon, Menu } from '@polkadot/ui-app/index';
|
||||||
import { withApi, withMulti } from '@polkadot/ui-api/index';
|
import accountObservable from '@polkadot/ui-keyring/observable/accounts';
|
||||||
|
import { withApi, withMulti, withObservable } from '@polkadot/ui-api/index';
|
||||||
import { isFunction } from '@polkadot/util';
|
import { isFunction } from '@polkadot/util';
|
||||||
|
|
||||||
type Props = I18nProps & ApiProps & {
|
type Props = I18nProps & ApiProps & {
|
||||||
|
allAccounts?: SubjectInfo,
|
||||||
route: Route
|
route: Route
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -21,7 +24,7 @@ class Item extends React.PureComponent<Props> {
|
|||||||
render () {
|
render () {
|
||||||
const { route: { i18n, icon, name }, t } = this.props;
|
const { route: { i18n, icon, name }, t } = this.props;
|
||||||
|
|
||||||
if (!this.isApiAvailable()) {
|
if (!this.isVisible()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,13 +41,18 @@ class Item extends React.PureComponent<Props> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private isApiAvailable () {
|
private isVisible () {
|
||||||
const { api, isApiConnected, isApiReady, route: { isApiGated, name, needsApi } } = this.props;
|
const { allAccounts = {}, api, isApiConnected, isApiReady, route: { display: { isHidden, needsAccounts, needsApi }, name } } = this.props;
|
||||||
|
const hasAccounts = Object.keys(allAccounts).length !== 0;
|
||||||
|
|
||||||
if (isApiGated && (!isApiReady || !isApiConnected)) {
|
if (isHidden) {
|
||||||
return false;
|
return false;
|
||||||
} else if (!needsApi || !needsApi.length) {
|
} else if (needsAccounts && !hasAccounts) {
|
||||||
|
return false;
|
||||||
|
} else if (!needsApi) {
|
||||||
return true;
|
return true;
|
||||||
|
} else if (!isApiReady || !isApiConnected) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const notFound = needsApi.filter((endpoint) => {
|
const notFound = needsApi.filter((endpoint) => {
|
||||||
@ -68,5 +76,6 @@ class Item extends React.PureComponent<Props> {
|
|||||||
export default withMulti(
|
export default withMulti(
|
||||||
Item,
|
Item,
|
||||||
withRouter,
|
withRouter,
|
||||||
withApi
|
withApi,
|
||||||
|
withObservable(accountObservable.subject, { propName: 'allAccounts' })
|
||||||
);
|
);
|
||||||
|
|||||||
@ -62,26 +62,22 @@ class SideBar extends React.PureComponent<Props> {
|
|||||||
private renderRoutes () {
|
private renderRoutes () {
|
||||||
const { t } = this.props;
|
const { t } = this.props;
|
||||||
|
|
||||||
return routing.routes
|
return routing.routes.map((route, index) => (
|
||||||
.filter((route) =>
|
route
|
||||||
!route || !route.isHidden
|
? (
|
||||||
)
|
<Item
|
||||||
.map((route, index) => (
|
key={route.name}
|
||||||
route
|
t={t}
|
||||||
? (
|
route={route}
|
||||||
<Item
|
/>
|
||||||
key={route.name}
|
)
|
||||||
t={t}
|
: (
|
||||||
route={route}
|
<Menu.Divider
|
||||||
/>
|
hidden
|
||||||
)
|
key={index}
|
||||||
: (
|
/>
|
||||||
<Menu.Divider
|
)
|
||||||
hidden
|
));
|
||||||
key={index}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderGithub () {
|
private renderGithub () {
|
||||||
|
|||||||
@ -9,12 +9,17 @@ import Template from '@polkadot/app-123code/index';
|
|||||||
export default ([
|
export default ([
|
||||||
{
|
{
|
||||||
Component: Template,
|
Component: Template,
|
||||||
|
display: {
|
||||||
|
isHidden: true,
|
||||||
|
needsAccounts: true,
|
||||||
|
needsApi: [
|
||||||
|
'tx.balances.transfer'
|
||||||
|
]
|
||||||
|
},
|
||||||
i18n: {
|
i18n: {
|
||||||
defaultValue: 'Template'
|
defaultValue: 'Template'
|
||||||
},
|
},
|
||||||
icon: 'th',
|
icon: 'th',
|
||||||
isApiGated: true,
|
|
||||||
isHidden: true,
|
|
||||||
name: '123code'
|
name: '123code'
|
||||||
}
|
}
|
||||||
] as Routes);
|
] as Routes);
|
||||||
|
|||||||
@ -9,12 +9,13 @@ import Accounts from '@polkadot/app-accounts/index';
|
|||||||
export default ([
|
export default ([
|
||||||
{
|
{
|
||||||
Component: Accounts,
|
Component: Accounts,
|
||||||
|
display: {
|
||||||
|
needsApi: []
|
||||||
|
},
|
||||||
i18n: {
|
i18n: {
|
||||||
defaultValue: 'Accounts'
|
defaultValue: 'Accounts'
|
||||||
},
|
},
|
||||||
icon: 'users',
|
icon: 'users',
|
||||||
isApiGated: true,
|
|
||||||
isHidden: false,
|
|
||||||
name: 'accounts'
|
name: 'accounts'
|
||||||
}
|
}
|
||||||
] as Routes);
|
] as Routes);
|
||||||
|
|||||||
@ -9,12 +9,13 @@ import Addresses from '@polkadot/app-addresses/index';
|
|||||||
export default ([
|
export default ([
|
||||||
{
|
{
|
||||||
Component: Addresses,
|
Component: Addresses,
|
||||||
|
display: {
|
||||||
|
needsApi: []
|
||||||
|
},
|
||||||
i18n: {
|
i18n: {
|
||||||
defaultValue: 'Addresses'
|
defaultValue: 'Addresses'
|
||||||
},
|
},
|
||||||
icon: 'address book',
|
icon: 'address book',
|
||||||
isApiGated: true,
|
|
||||||
isHidden: false,
|
|
||||||
name: 'addresses'
|
name: 'addresses'
|
||||||
}
|
}
|
||||||
] as Routes);
|
] as Routes);
|
||||||
|
|||||||
@ -9,15 +9,16 @@ import Democracy from '@polkadot/app-democracy/index';
|
|||||||
export default ([
|
export default ([
|
||||||
{
|
{
|
||||||
Component: Democracy,
|
Component: Democracy,
|
||||||
|
display: {
|
||||||
|
needsAccounts: true,
|
||||||
|
needsApi: [
|
||||||
|
'query.democracy.nextTally'
|
||||||
|
]
|
||||||
|
},
|
||||||
i18n: {
|
i18n: {
|
||||||
defaultValue: 'Democracy'
|
defaultValue: 'Democracy'
|
||||||
},
|
},
|
||||||
icon: 'calendar check',
|
icon: 'calendar check',
|
||||||
isApiGated: true,
|
name: 'democracy'
|
||||||
isHidden: false,
|
|
||||||
name: 'democracy',
|
|
||||||
needsApi: [
|
|
||||||
'query.democracy.nextTally'
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
] as Routes);
|
] as Routes);
|
||||||
|
|||||||
@ -9,12 +9,13 @@ import Explorer from '@polkadot/app-explorer/index';
|
|||||||
export default ([
|
export default ([
|
||||||
{
|
{
|
||||||
Component: Explorer,
|
Component: Explorer,
|
||||||
|
display: {
|
||||||
|
needsApi: []
|
||||||
|
},
|
||||||
i18n: {
|
i18n: {
|
||||||
defaultValue: 'Explorer'
|
defaultValue: 'Explorer'
|
||||||
},
|
},
|
||||||
icon: 'braille',
|
icon: 'braille',
|
||||||
isApiGated: true,
|
|
||||||
isHidden: false,
|
|
||||||
name: 'explorer'
|
name: 'explorer'
|
||||||
}
|
}
|
||||||
] as Routes);
|
] as Routes);
|
||||||
|
|||||||
@ -9,12 +9,14 @@ import Extrinsics from '@polkadot/app-extrinsics/index';
|
|||||||
export default ([
|
export default ([
|
||||||
{
|
{
|
||||||
Component: Extrinsics,
|
Component: Extrinsics,
|
||||||
|
display: {
|
||||||
|
needsAccounts: true,
|
||||||
|
needsApi: []
|
||||||
|
},
|
||||||
i18n: {
|
i18n: {
|
||||||
defaultValue: 'Extrinsics'
|
defaultValue: 'Extrinsics'
|
||||||
},
|
},
|
||||||
icon: 'send',
|
icon: 'send',
|
||||||
isApiGated: true,
|
|
||||||
isHidden: false,
|
|
||||||
name: 'extrinsics'
|
name: 'extrinsics'
|
||||||
}
|
}
|
||||||
] as Routes);
|
] as Routes);
|
||||||
|
|||||||
@ -9,12 +9,13 @@ import Nodeinfo from '@polkadot/app-nodeinfo/index';
|
|||||||
export default ([
|
export default ([
|
||||||
{
|
{
|
||||||
Component: Nodeinfo,
|
Component: Nodeinfo,
|
||||||
|
display: {
|
||||||
|
needsApi: []
|
||||||
|
},
|
||||||
i18n: {
|
i18n: {
|
||||||
defaultValue: 'Node info'
|
defaultValue: 'Node info'
|
||||||
},
|
},
|
||||||
icon: 'tty',
|
icon: 'tty',
|
||||||
isApiGated: true,
|
|
||||||
isHidden: false,
|
|
||||||
name: 'nodeinfo'
|
name: 'nodeinfo'
|
||||||
}
|
}
|
||||||
] as Routes);
|
] as Routes);
|
||||||
|
|||||||
@ -9,12 +9,13 @@ import Settings from '@polkadot/app-settings/index';
|
|||||||
export default ([
|
export default ([
|
||||||
{
|
{
|
||||||
Component: Settings,
|
Component: Settings,
|
||||||
|
display: {
|
||||||
|
needsApi: []
|
||||||
|
},
|
||||||
i18n: {
|
i18n: {
|
||||||
defaultValue: 'Settings'
|
defaultValue: 'Settings'
|
||||||
},
|
},
|
||||||
icon: 'settings',
|
icon: 'settings',
|
||||||
isApiGated: false,
|
|
||||||
isHidden: false,
|
|
||||||
name: 'settings'
|
name: 'settings'
|
||||||
}
|
}
|
||||||
] as Routes);
|
] as Routes);
|
||||||
|
|||||||
@ -9,15 +9,16 @@ import Staking from '@polkadot/app-staking/index';
|
|||||||
export default ([
|
export default ([
|
||||||
{
|
{
|
||||||
Component: Staking,
|
Component: Staking,
|
||||||
|
display: {
|
||||||
|
needsAccounts: true,
|
||||||
|
needsApi: [
|
||||||
|
'tx.staking.stake'
|
||||||
|
]
|
||||||
|
},
|
||||||
i18n: {
|
i18n: {
|
||||||
defaultValue: 'Staking'
|
defaultValue: 'Staking'
|
||||||
},
|
},
|
||||||
icon: 'certificate',
|
icon: 'certificate',
|
||||||
isApiGated: true,
|
name: 'staking'
|
||||||
isHidden: false,
|
|
||||||
name: 'staking',
|
|
||||||
needsApi: [
|
|
||||||
'tx.staking.stake'
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
] as Routes);
|
] as Routes);
|
||||||
|
|||||||
@ -9,12 +9,13 @@ import Storage from '@polkadot/app-storage/index';
|
|||||||
export default ([
|
export default ([
|
||||||
{
|
{
|
||||||
Component: Storage,
|
Component: Storage,
|
||||||
|
display: {
|
||||||
|
needsApi: []
|
||||||
|
},
|
||||||
i18n: {
|
i18n: {
|
||||||
defaultValue: 'Chain state'
|
defaultValue: 'Chain state'
|
||||||
},
|
},
|
||||||
icon: 'database',
|
icon: 'database',
|
||||||
isApiGated: true,
|
|
||||||
isHidden: false,
|
|
||||||
name: 'chainstate'
|
name: 'chainstate'
|
||||||
}
|
}
|
||||||
] as Routes);
|
] as Routes);
|
||||||
|
|||||||
@ -9,12 +9,13 @@ import Toolbox from '@polkadot/app-toolbox/index';
|
|||||||
export default ([
|
export default ([
|
||||||
{
|
{
|
||||||
Component: Toolbox,
|
Component: Toolbox,
|
||||||
|
display: {
|
||||||
|
needsApi: []
|
||||||
|
},
|
||||||
i18n: {
|
i18n: {
|
||||||
defaultValue: 'Toolbox'
|
defaultValue: 'Toolbox'
|
||||||
},
|
},
|
||||||
icon: 'configure',
|
icon: 'configure',
|
||||||
isApiGated: true,
|
|
||||||
isHidden: false,
|
|
||||||
name: 'toolbox'
|
name: 'toolbox'
|
||||||
}
|
}
|
||||||
] as Routes);
|
] as Routes);
|
||||||
|
|||||||
@ -9,15 +9,16 @@ import Transfer from '@polkadot/app-transfer/index';
|
|||||||
export default ([
|
export default ([
|
||||||
{
|
{
|
||||||
Component: Transfer,
|
Component: Transfer,
|
||||||
|
display: {
|
||||||
|
needsAccounts: true,
|
||||||
|
needsApi: [
|
||||||
|
'tx.balances.transfer'
|
||||||
|
]
|
||||||
|
},
|
||||||
i18n: {
|
i18n: {
|
||||||
defaultValue: 'Transfer'
|
defaultValue: 'Transfer'
|
||||||
},
|
},
|
||||||
icon: 'angle double right',
|
icon: 'angle double right',
|
||||||
isApiGated: true,
|
name: 'transfer'
|
||||||
isHidden: false,
|
|
||||||
name: 'transfer',
|
|
||||||
needsApi: [
|
|
||||||
'tx.balances.transfer'
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
] as Routes);
|
] as Routes);
|
||||||
|
|||||||
@ -9,12 +9,14 @@ export type RouteProps = AppProps & BareProps;
|
|||||||
|
|
||||||
export type Route = {
|
export type Route = {
|
||||||
Component: React.ComponentType<RouteProps>,
|
Component: React.ComponentType<RouteProps>,
|
||||||
i18n: any, // I18Next$Translate$Config,
|
display: {
|
||||||
|
isHidden?: boolean,
|
||||||
|
needsAccounts?: boolean,
|
||||||
|
needsApi?: Array<string>
|
||||||
|
},
|
||||||
|
i18n: { defaultValue: string },
|
||||||
icon: SemanticICONS,
|
icon: SemanticICONS,
|
||||||
isApiGated: boolean,
|
name: string
|
||||||
isHidden: boolean,
|
|
||||||
name: string,
|
|
||||||
needsApi?: Array<string>
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Routes = Array<Route | null>;
|
export type Routes = Array<Route | null>;
|
||||||
|
|||||||
@ -26,7 +26,11 @@ const NOOP = () => {
|
|||||||
export default function withCall<P extends ApiProps> (endpoint: string, { at, atProp, callOnResult, params = [], paramName = 'params', propName, transform = echoTransform }: Options = {}): (Inner: React.ComponentType<ApiProps>) => React.ComponentType<any> {
|
export default function withCall<P extends ApiProps> (endpoint: string, { at, atProp, callOnResult, params = [], paramName = 'params', propName, transform = echoTransform }: Options = {}): (Inner: React.ComponentType<ApiProps>) => React.ComponentType<any> {
|
||||||
return (Inner: React.ComponentType<ApiProps>): React.ComponentType<Subtract<P, ApiProps>> => {
|
return (Inner: React.ComponentType<ApiProps>): React.ComponentType<Subtract<P, ApiProps>> => {
|
||||||
class WithPromise extends React.Component<P, State> {
|
class WithPromise extends React.Component<P, State> {
|
||||||
state: State;
|
state: State = {
|
||||||
|
callResult: void 0,
|
||||||
|
callUpdated: false,
|
||||||
|
callUpdatedAt: 0
|
||||||
|
};
|
||||||
private destroy?: () => void;
|
private destroy?: () => void;
|
||||||
private isActive: boolean = false;
|
private isActive: boolean = false;
|
||||||
private propName: string;
|
private propName: string;
|
||||||
@ -38,11 +42,6 @@ export default function withCall<P extends ApiProps> (endpoint: string, { at, at
|
|||||||
const [, section, method] = endpoint.split('.');
|
const [, section, method] = endpoint.split('.');
|
||||||
|
|
||||||
this.propName = `${section}_${method}`;
|
this.propName = `${section}_${method}`;
|
||||||
this.state = {
|
|
||||||
callResult: void 0,
|
|
||||||
callUpdated: false,
|
|
||||||
callUpdatedAt: 0
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate (prevProps: any) {
|
componentDidUpdate (prevProps: any) {
|
||||||
|
|||||||
@ -23,18 +23,12 @@ type State = CallState & {
|
|||||||
export default function withObservable<T, P> (observable: Observable<P>, { callOnResult, propName = 'value', transform = echoTransform }: Options = {}): HOC {
|
export default function withObservable<T, P> (observable: Observable<P>, { callOnResult, propName = 'value', transform = echoTransform }: Options = {}): HOC {
|
||||||
return (Inner: React.ComponentType<any>, defaultProps: DefaultProps = {}, render?: RenderFn): React.ComponentType<any> => {
|
return (Inner: React.ComponentType<any>, defaultProps: DefaultProps = {}, render?: RenderFn): React.ComponentType<any> => {
|
||||||
return class WithObservable extends React.Component<any, State> {
|
return class WithObservable extends React.Component<any, State> {
|
||||||
state: State;
|
state: State = {
|
||||||
|
callResult: void 0,
|
||||||
constructor (props: any) {
|
callUpdated: false,
|
||||||
super(props);
|
callUpdatedAt: 0,
|
||||||
|
subscriptions: []
|
||||||
this.state = {
|
};
|
||||||
callResult: void 0,
|
|
||||||
callUpdated: false,
|
|
||||||
callUpdatedAt: 0,
|
|
||||||
subscriptions: []
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
this.setState({
|
this.setState({
|
||||||
|
|||||||
@ -76,11 +76,7 @@ const createOption = (address: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class InputAddress extends React.PureComponent<Props, State> {
|
class InputAddress extends React.PureComponent<Props, State> {
|
||||||
constructor (props: Props) {
|
state: State = {};
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.state = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
static getDerivedStateFromProps ({ value }: Props): State | null {
|
static getDerivedStateFromProps ({ value }: Props): State | null {
|
||||||
try {
|
try {
|
||||||
@ -112,8 +108,9 @@ class InputAddress extends React.PureComponent<Props, State> {
|
|||||||
render () {
|
render () {
|
||||||
const { className, defaultValue, hideAddress = false, isDisabled = false, isError, label, optionsAll, type = DEFAULT_TYPE, style, withLabel } = this.props;
|
const { className, defaultValue, hideAddress = false, isDisabled = false, isError, label, optionsAll, type = DEFAULT_TYPE, style, withLabel } = this.props;
|
||||||
const { value } = this.state;
|
const { value } = this.state;
|
||||||
|
const hasOptions = optionsAll && Object.keys(optionsAll[type]).length !== 0;
|
||||||
|
|
||||||
if (!optionsAll || !Object.keys(optionsAll[type]).length) {
|
if (!hasOptions && !isDisabled) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +140,7 @@ class InputAddress extends React.PureComponent<Props, State> {
|
|||||||
options={
|
options={
|
||||||
isDisabled && actualValue
|
isDisabled && actualValue
|
||||||
? [createOption(actualValue)]
|
? [createOption(actualValue)]
|
||||||
: optionsAll[type]
|
: (optionsAll ? optionsAll[type] : [])
|
||||||
}
|
}
|
||||||
style={style}
|
style={style}
|
||||||
value={value}
|
value={value}
|
||||||
|
|||||||
@ -16,6 +16,7 @@ type Props = BareProps & WithNamespaces & {
|
|||||||
// Reference Example Usage: https://github.com/react-dropzone/react-dropzone/tree/master/examples/Accept
|
// Reference Example Usage: https://github.com/react-dropzone/react-dropzone/tree/master/examples/Accept
|
||||||
// i.e. MIME types: 'application/json, text/plain', or '.json, .txt'
|
// i.e. MIME types: 'application/json, text/plain', or '.json, .txt'
|
||||||
accept?: string,
|
accept?: string,
|
||||||
|
clearContent?: boolean,
|
||||||
isDisabled?: boolean,
|
isDisabled?: boolean,
|
||||||
isError?: boolean,
|
isError?: boolean,
|
||||||
label: string,
|
label: string,
|
||||||
@ -41,7 +42,7 @@ class InputFile extends React.PureComponent<Props, State> {
|
|||||||
state: State = {};
|
state: State = {};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { accept, className, isDisabled, isError = false, label, placeholder, t, withLabel } = this.props;
|
const { accept, className, clearContent, isDisabled, isError = false, label, placeholder, t, withLabel } = this.props;
|
||||||
const { file } = this.state;
|
const { file } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -58,7 +59,7 @@ class InputFile extends React.PureComponent<Props, State> {
|
|||||||
>
|
>
|
||||||
<div className='label'>
|
<div className='label'>
|
||||||
{
|
{
|
||||||
!file
|
!file || clearContent
|
||||||
? placeholder || t('drag and drop the file here')
|
? placeholder || t('drag and drop the file here')
|
||||||
: placeholder || t('{{name}} ({{size}} bytes)', {
|
: placeholder || t('{{name}} ({{size}} bytes)', {
|
||||||
replace: file
|
replace: file
|
||||||
|
|||||||
@ -45,14 +45,17 @@ class Tabs extends React.PureComponent<Props> {
|
|||||||
const to = index === 0
|
const to = index === 0
|
||||||
? basePath
|
? basePath
|
||||||
: `${basePath}/${name}`;
|
: `${basePath}/${name}`;
|
||||||
|
// only do exact matching when not the fallback (first position tab),
|
||||||
|
// params are problematic for dynamic hidden such as app-accounts
|
||||||
|
const isExact = !hasParams || index === 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NavLink
|
<NavLink
|
||||||
activeClassName='active'
|
activeClassName='active'
|
||||||
className='item'
|
className='item'
|
||||||
exact={!hasParams}
|
exact={isExact}
|
||||||
key={to}
|
key={to}
|
||||||
strict={!hasParams}
|
strict={isExact}
|
||||||
to={to}
|
to={to}
|
||||||
>
|
>
|
||||||
{text}
|
{text}
|
||||||
|
|||||||
@ -15,6 +15,7 @@ export type BareProps = {
|
|||||||
|
|
||||||
export type AppProps = {
|
export type AppProps = {
|
||||||
basePath: string,
|
basePath: string,
|
||||||
|
location: Location,
|
||||||
onStatusChange: (status: ActionStatus) => void
|
onStatusChange: (status: ActionStatus) => void
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -16,13 +16,9 @@ type State = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default class Bytes extends React.PureComponent<Props, State> {
|
export default class Bytes extends React.PureComponent<Props, State> {
|
||||||
constructor (props: Props) {
|
state: State = {
|
||||||
super(props);
|
isFileDrop: false
|
||||||
|
};
|
||||||
this.state = {
|
|
||||||
isFileDrop: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { isDisabled } = this.props;
|
const { isDisabled } = this.props;
|
||||||
|
|||||||
@ -20,16 +20,12 @@ type State = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default class Tuple extends React.PureComponent<Props, State> {
|
export default class Tuple extends React.PureComponent<Props, State> {
|
||||||
constructor (props: Props) {
|
state: State = {
|
||||||
super(props);
|
Components: [],
|
||||||
|
sub: [],
|
||||||
this.state = {
|
subTypes: [],
|
||||||
Components: [],
|
values: []
|
||||||
sub: [],
|
};
|
||||||
subTypes: [],
|
|
||||||
values: []
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static getDerivedStateFromProps ({ defaultValue: { value }, type: { sub, type } }: Props, prevState: State): Partial<State> | null {
|
static getDerivedStateFromProps ({ defaultValue: { value }, type: { sub, type } }: Props, prevState: State): Partial<State> | null {
|
||||||
if (type === prevState.type) {
|
if (type === prevState.type) {
|
||||||
|
|||||||
@ -24,14 +24,10 @@ type State = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Vector extends React.PureComponent<Props, State> {
|
class Vector extends React.PureComponent<Props, State> {
|
||||||
constructor (props: Props) {
|
state: State = {
|
||||||
super(props);
|
Component: null,
|
||||||
|
values: []
|
||||||
this.state = {
|
};
|
||||||
Component: null,
|
|
||||||
values: []
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static getDerivedStateFromProps ({ defaultValue: { value = [] }, isDisabled, type: { sub, type } }: Props, prevState: State): Partial<State> | null {
|
static getDerivedStateFromProps ({ defaultValue: { value = [] }, isDisabled, type: { sub, type } }: Props, prevState: State): Partial<State> | null {
|
||||||
if (type === prevState.type) {
|
if (type === prevState.type) {
|
||||||
|
|||||||
@ -26,16 +26,12 @@ type State = ExtraFees & {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Proposal extends React.PureComponent<Props, State> {
|
class Proposal extends React.PureComponent<Props, State> {
|
||||||
constructor (props: Props) {
|
state: State = {
|
||||||
super(props);
|
extraFees: new BN(0),
|
||||||
|
extraAmount: new BN(0),
|
||||||
this.state = {
|
extraWarn: false,
|
||||||
extraFees: new BN(0),
|
isBelowMinimum: false
|
||||||
extraAmount: new BN(0),
|
};
|
||||||
extraWarn: false,
|
|
||||||
isBelowMinimum: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static getDerivedStateFromProps ({ deposit, democracy_minimumDeposit = new BN(0), onChange }: Props): State {
|
static getDerivedStateFromProps ({ deposit, democracy_minimumDeposit = new BN(0), onChange }: Props): State {
|
||||||
const extraAmount = deposit instanceof Compact
|
const extraAmount = deposit instanceof Compact
|
||||||
|
|||||||
@ -30,17 +30,13 @@ type State = ExtraFees & {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Transfer extends React.PureComponent<Props, State> {
|
class Transfer extends React.PureComponent<Props, State> {
|
||||||
constructor (props: Props) {
|
state: State = {
|
||||||
super(props);
|
extraFees: new BN(0),
|
||||||
|
extraAmount: new BN(0),
|
||||||
this.state = {
|
extraWarn: false,
|
||||||
extraFees: new BN(0),
|
isCreation: false,
|
||||||
extraAmount: new BN(0),
|
isNoEffect: false
|
||||||
extraWarn: false,
|
};
|
||||||
isCreation: false,
|
|
||||||
isNoEffect: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static getDerivedStateFromProps ({ amount, balances_votingBalance = ZERO_BALANCE, fees, onChange }: Props): State {
|
static getDerivedStateFromProps ({ amount, balances_votingBalance = ZERO_BALANCE, fees, onChange }: Props): State {
|
||||||
let extraFees = fees.transferFee;
|
let extraFees = fees.transferFee;
|
||||||
|
|||||||
@ -39,16 +39,10 @@ type State = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Signer extends React.PureComponent<Props, State> {
|
class Signer extends React.PureComponent<Props, State> {
|
||||||
state: State;
|
state: State = {
|
||||||
|
password: '',
|
||||||
constructor (props: Props) {
|
unlockError: null
|
||||||
super(props);
|
};
|
||||||
|
|
||||||
this.state = {
|
|
||||||
password: '',
|
|
||||||
unlockError: null
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static getDerivedStateFromProps ({ queue }: Props, { currentItem, password, unlockError }: State): State {
|
static getDerivedStateFromProps ({ queue }: Props, { currentItem, password, unlockError }: State): State {
|
||||||
const nextItem = queue.find(({ status }) =>
|
const nextItem = queue.find(({ status }) =>
|
||||||
|
|||||||
@ -11,5 +11,6 @@
|
|||||||
"Transaction": {
|
"Transaction": {
|
||||||
"inputs": "Vec<TransactionInput>",
|
"inputs": "Vec<TransactionInput>",
|
||||||
"outputs": "Vec<TransactionOutput>"
|
"outputs": "Vec<TransactionOutput>"
|
||||||
}
|
},
|
||||||
|
"blah": "u32"
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user