Optimise components (#39)
* ui-react-app -> ui-app
* CopyButton, Input & Password components
* Convert all to use ui-app/{Input, Label}
* Change to PureComponent where we have onChange listeners
* Cleanup layouts
* Swap dropdown components, remove uselexx constructors
* Allow address/account forget
* Bump
* Searching with headers operational
* flex grow/shrink for icon + account add
* Fix balance & transaction display (account/address management)
* Adjust balance layout
* Equalise padding
This commit is contained in:
parent
da4807b63c
commit
b11a6981a2
@ -14,4 +14,4 @@ all=warn
|
||||
include_warnings=true
|
||||
module.name_mapper='^@polkadot/app-\(accounts\|addresses\|explorer\|extrinsics\|home\|rpc\|settings\|storage\|vanitygen\)\(.*\)$' -> '<PROJECT_ROOT>/packages/app-\1/src\2'
|
||||
module.name_mapper='^@polkadot/apps\(.*\)$' -> '<PROJECT_ROOT>/packages/apps/src\1'
|
||||
module.name_mapper='^@polkadot/ui-\(keyring\|react-app\)\(.*\)$' -> '<PROJECT_ROOT>/packages/ui-\1/src\2'
|
||||
module.name_mapper='^@polkadot/ui-\(app\|keyring\)\(.*\)$' -> '<PROJECT_ROOT>/packages/ui-\1/src\2'
|
||||
|
||||
2
flow-typed/react-copy-to-clipboard.js
vendored
2
flow-typed/react-copy-to-clipboard.js
vendored
@ -1,5 +1,5 @@
|
||||
// @flow
|
||||
|
||||
declare module 'react-copy-to-clipboard' {
|
||||
declare module.exports: React$ComponentType<{ text: string }>;
|
||||
declare module.exports: React$ComponentType<{ text?: string }>;
|
||||
}
|
||||
|
||||
1
flow-typed/store.js
vendored
1
flow-typed/store.js
vendored
@ -4,6 +4,7 @@ declare module 'store' {
|
||||
declare module.exports: {
|
||||
each: (fn: (value: any, key: string) => void) => void,
|
||||
get: (key: string) => any,
|
||||
remove: (key: string) => any,
|
||||
set: (key: string, value: any) => void,
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,5 +10,5 @@
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"version": "0.3.4"
|
||||
"version": "0.4.0"
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/app-accounts",
|
||||
"version": "0.3.4",
|
||||
"version": "0.4.0",
|
||||
"main": "index.js",
|
||||
"repository": "https://github.com/polkadot-js/apps.git",
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
@ -11,6 +11,6 @@
|
||||
"test": "jest --coverage"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@polkadot/ui-react-app": "^0.3.4"
|
||||
"@polkadot/ui-app": "^0.4.0"
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,63 +3,97 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BareProps } from '@polkadot/ui-react-app/types';
|
||||
import type { BareProps } from '@polkadot/ui-app/types';
|
||||
|
||||
import React from 'react';
|
||||
import CopyToClipboard from 'react-copy-to-clipboard';
|
||||
import Button from 'semantic-ui-react/dist/es/elements/Button';
|
||||
|
||||
import CopyButton from '@polkadot/ui-app/src/CopyButton';
|
||||
import IdentityIcon from '@polkadot/ui-react/IdentityIcon';
|
||||
import Balance from '@polkadot/ui-react-rx/Balance';
|
||||
import Nonce from '@polkadot/ui-react-rx/Nonce';
|
||||
import addressDecode from '@polkadot/util-keyring/address/decode';
|
||||
|
||||
type Props = BareProps & {
|
||||
value: null | {
|
||||
address: string,
|
||||
publicKey: Uint8Array
|
||||
};
|
||||
value: string | null;
|
||||
}
|
||||
|
||||
export default function Address ({ className, style, value }: Props): React$Node {
|
||||
if (!value) {
|
||||
return null;
|
||||
type State = {
|
||||
address: string,
|
||||
isValid: boolean,
|
||||
publicKey: Uint8Array | null,
|
||||
shortValue: string
|
||||
}
|
||||
|
||||
const DEFAULT_ADDR = '5'.padEnd(16, 'x');
|
||||
const DEFAULT_SHORT = `${DEFAULT_ADDR.slice(0, 7)}…${DEFAULT_ADDR.slice(-7)}`;
|
||||
|
||||
export default class Address extends React.PureComponent<Props, State> {
|
||||
state: State = ({}: $Shape<State>);
|
||||
|
||||
static getDerivedStateFromProps ({ value }: Props, { publicKey, shortValue }: State): State {
|
||||
// flowlint-next-line sketchy-null-string:off
|
||||
const address = value || DEFAULT_ADDR;
|
||||
|
||||
try {
|
||||
// $FlowFixMe yes, we expect a throw when invalid
|
||||
publicKey = addressDecode(value);
|
||||
shortValue = `${address.slice(0, 7)}…${address.slice(-7)}`;
|
||||
} catch (error) {
|
||||
publicKey = null;
|
||||
}
|
||||
|
||||
const isValid = !!publicKey && publicKey.length === 32;
|
||||
|
||||
console.log('publicKey', publicKey);
|
||||
|
||||
return {
|
||||
address: isValid ? address : DEFAULT_ADDR,
|
||||
isValid,
|
||||
publicKey,
|
||||
shortValue: isValid ? shortValue : DEFAULT_SHORT
|
||||
};
|
||||
}
|
||||
|
||||
const { address, publicKey } = value;
|
||||
const short = `${address.slice(0, 7)}…${address.slice(-7)}`;
|
||||
render (): React$Node {
|
||||
const { className, style } = this.props;
|
||||
const { address, isValid, publicKey, shortValue } = this.state;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['accounts--Address', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<IdentityIcon
|
||||
className='accounts--Address-icon'
|
||||
size={96}
|
||||
value={address}
|
||||
/>
|
||||
<div className='accounts--Address-data'>
|
||||
<div className='accounts--Address-address'>
|
||||
{short}
|
||||
</div>
|
||||
<CopyToClipboard text={address}>
|
||||
<Button
|
||||
icon='copy'
|
||||
primary
|
||||
size='tiny'
|
||||
/>
|
||||
</CopyToClipboard>
|
||||
</div>
|
||||
<Balance
|
||||
className='accounts--Address-balance'
|
||||
label='balance '
|
||||
value={publicKey}
|
||||
/>
|
||||
<Nonce
|
||||
className='accounts--Address-nonce'
|
||||
value={publicKey}
|
||||
return (
|
||||
<div
|
||||
className={['accounts--Address', isValid ? '' : 'invalid', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
{' transactions'}
|
||||
</Nonce>
|
||||
</div>
|
||||
);
|
||||
<IdentityIcon
|
||||
className='accounts--Address-icon'
|
||||
size={96}
|
||||
value={address}
|
||||
/>
|
||||
<div className='accounts--Address-data'>
|
||||
<div className='accounts--Address-address'>
|
||||
{shortValue}
|
||||
</div>
|
||||
<CopyButton value={address} />
|
||||
</div>
|
||||
{
|
||||
!isValid
|
||||
? null
|
||||
: [
|
||||
<Balance
|
||||
className='accounts--Address-balance'
|
||||
key='balance'
|
||||
label='balance '
|
||||
params={publicKey}
|
||||
/>,
|
||||
<Nonce
|
||||
className='accounts--Address-nonce'
|
||||
key='nonce'
|
||||
params={publicKey}
|
||||
>
|
||||
{' transactions'}
|
||||
</Nonce>
|
||||
]
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,12 +3,13 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
|
||||
import React from 'react';
|
||||
import Button from 'semantic-ui-react/dist/es/elements/Button';
|
||||
import Input from 'semantic-ui-react/dist/es/elements/Input';
|
||||
import Label from 'semantic-ui-react/dist/es/elements/Label';
|
||||
|
||||
import Input from '@polkadot/ui-app/src/Input';
|
||||
import Password from '@polkadot/ui-app/src/Password';
|
||||
import keyring from '@polkadot/ui-keyring/src';
|
||||
import isHex from '@polkadot/util/is/hex';
|
||||
import hexToU8a from '@polkadot/util/hex/toU8a';
|
||||
@ -26,13 +27,11 @@ type Props = I18nProps & {
|
||||
};
|
||||
|
||||
type State = {
|
||||
address: string | null,
|
||||
publicKey: Uint8Array | null,
|
||||
address: string,
|
||||
fieldName: string,
|
||||
isNameValid: boolean,
|
||||
isSeedValid: boolean,
|
||||
isPassValid: boolean,
|
||||
isPassVisible: boolean,
|
||||
isValid: boolean,
|
||||
name: string,
|
||||
password: string,
|
||||
@ -45,14 +44,12 @@ function formatSeed (seed: string): Uint8Array {
|
||||
: u8aFromString(seed.padEnd(32, ' '));
|
||||
}
|
||||
|
||||
function infoFromSeed (seed: string): { address: string, publicKey: Uint8Array } {
|
||||
const { publicKey } = keypairFromSeed(formatSeed(seed));
|
||||
const address = addressEncode(publicKey);
|
||||
|
||||
return {
|
||||
address,
|
||||
publicKey
|
||||
};
|
||||
function addressFromSeed (seed: string): string {
|
||||
return addressEncode(
|
||||
keypairFromSeed(
|
||||
formatSeed(seed)
|
||||
).publicKey
|
||||
);
|
||||
}
|
||||
|
||||
class Creator extends React.PureComponent<Props, State> {
|
||||
@ -66,7 +63,7 @@ class Creator extends React.PureComponent<Props, State> {
|
||||
|
||||
render (): React$Node {
|
||||
const { className, style, t } = this.props;
|
||||
const { address, fieldName, isNameValid, isPassValid, isPassVisible, isSeedValid, isValid, name, password, publicKey, seed } = this.state;
|
||||
const { address, fieldName, isNameValid, isPassValid, isSeedValid, isValid, name, password, seed } = this.state;
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -74,68 +71,52 @@ class Creator extends React.PureComponent<Props, State> {
|
||||
style={style}
|
||||
>
|
||||
<div className='ui--grid'>
|
||||
<div className='medium'>
|
||||
<div className='ui--row'>
|
||||
<div className='full'>
|
||||
<Label>{t('creator.seed', {
|
||||
defaultValue: 'create from the following seed (hex or string)'
|
||||
})}</Label>
|
||||
<Input
|
||||
error={!isSeedValid}
|
||||
name={`${fieldName}_seed`}
|
||||
onChange={this.onChangeSeed}
|
||||
value={seed}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className='ui--row'>
|
||||
<div className='full'>
|
||||
<Label>{t('creator.name', {
|
||||
defaultValue: 'name the account'
|
||||
})}</Label>
|
||||
<Input
|
||||
error={!isNameValid}
|
||||
name={`${fieldName}_name`}
|
||||
onChange={this.onChangeName}
|
||||
value={name}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className='ui--row'>
|
||||
<div className='full'>
|
||||
<Label>{t('creator.pass1', {
|
||||
defaultValue: 'encrypt it using the password'
|
||||
})}</Label>
|
||||
<Input
|
||||
action
|
||||
error={!isPassValid}
|
||||
name={`${fieldName}_pass`}
|
||||
onChange={this.onChangePass}
|
||||
type={isPassVisible ? 'text' : 'password'}
|
||||
value={password}
|
||||
>
|
||||
<input />
|
||||
<Button
|
||||
icon='eye'
|
||||
primary
|
||||
onClick={this.togglePassword}
|
||||
/>
|
||||
</Input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Address
|
||||
className='medium'
|
||||
className='shrink'
|
||||
value={
|
||||
// flowlint-next-line sketchy-null-string:off
|
||||
!address || !publicKey
|
||||
? null
|
||||
: {
|
||||
address,
|
||||
publicKey
|
||||
}
|
||||
isSeedValid
|
||||
? address
|
||||
: null
|
||||
}
|
||||
/>
|
||||
<div className='grow'>
|
||||
<div className='ui--row'>
|
||||
<Input
|
||||
className='full'
|
||||
isError={!isSeedValid}
|
||||
label={t('creator.seed', {
|
||||
defaultValue: 'create from the following seed (hex or string)'
|
||||
})}
|
||||
name={`${fieldName}_seed`}
|
||||
onChange={this.onChangeSeed}
|
||||
value={seed}
|
||||
/>
|
||||
</div>
|
||||
<div className='ui--row'>
|
||||
<Input
|
||||
className='full'
|
||||
isError={!isNameValid}
|
||||
label={t('creator.name', {
|
||||
defaultValue: 'name the account'
|
||||
})}
|
||||
name={`${fieldName}_name`}
|
||||
onChange={this.onChangeName}
|
||||
value={name}
|
||||
/>
|
||||
</div>
|
||||
<div className='ui--row'>
|
||||
<Password
|
||||
className='full'
|
||||
isError={!isPassValid}
|
||||
label={t('creator.password', {
|
||||
defaultValue: 'encrypt it using the password'
|
||||
})}
|
||||
name={`${fieldName}_pass`}
|
||||
onChange={this.onChangePass}
|
||||
value={password}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='ui--row-buttons'>
|
||||
<Button
|
||||
@ -161,19 +142,17 @@ class Creator extends React.PureComponent<Props, State> {
|
||||
|
||||
emptyState (): State {
|
||||
const seed = u8aToHex(randomBytes());
|
||||
const { address, publicKey } = infoFromSeed(seed);
|
||||
const address = addressFromSeed(seed);
|
||||
|
||||
return {
|
||||
address,
|
||||
fieldName: `field_${Date.now()}`,
|
||||
isNameValid: true,
|
||||
isPassValid: false,
|
||||
isPassVisible: false,
|
||||
isSeedValid: true,
|
||||
isValid: false,
|
||||
name: 'new keypair',
|
||||
password: '',
|
||||
publicKey,
|
||||
seed
|
||||
};
|
||||
}
|
||||
@ -183,7 +162,6 @@ class Creator extends React.PureComponent<Props, State> {
|
||||
(prevState: State, props: Props): $Shape<State> => {
|
||||
const { name = prevState.name, password = prevState.password, seed = prevState.seed } = newState;
|
||||
let address = prevState.address;
|
||||
let publicKey = prevState.publicKey;
|
||||
const isNameValid = !!name;
|
||||
const isSeedValid = isHex(seed)
|
||||
? seed.length === 66
|
||||
@ -191,10 +169,7 @@ class Creator extends React.PureComponent<Props, State> {
|
||||
const isPassValid = password.length > 0 && password.length <= 32;
|
||||
|
||||
if (isSeedValid && seed !== prevState.seed) {
|
||||
const info = infoFromSeed(seed);
|
||||
|
||||
address = info.address;
|
||||
publicKey = info.publicKey;
|
||||
address = addressFromSeed(seed);
|
||||
}
|
||||
|
||||
return {
|
||||
@ -205,25 +180,22 @@ class Creator extends React.PureComponent<Props, State> {
|
||||
isValid: isNameValid && isPassValid && isSeedValid,
|
||||
name,
|
||||
password,
|
||||
publicKey,
|
||||
seed
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
onChangeSeed = (event: SyntheticEvent<*>, { value }): void => {
|
||||
this.nextState({ seed: value });
|
||||
onChangeSeed = (seed: string): void => {
|
||||
this.nextState({ seed });
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
onChangeName = (event: SyntheticEvent<*>, { value }): void => {
|
||||
this.nextState({ name: value });
|
||||
onChangeName = (name: string): void => {
|
||||
this.nextState({ name });
|
||||
}
|
||||
|
||||
onChangePass = (event: SyntheticEvent<*>, { value }): void => {
|
||||
this.nextState({ password: value });
|
||||
onChangePass = (password: string): void => {
|
||||
this.nextState({ password });
|
||||
}
|
||||
|
||||
onCommit = (): void => {
|
||||
@ -240,10 +212,6 @@ class Creator extends React.PureComponent<Props, State> {
|
||||
onDiscard = (): void => {
|
||||
this.setState(this.emptyState());
|
||||
}
|
||||
|
||||
togglePassword = (): void => {
|
||||
this.setState({ isPassVisible: !this.state.isPassVisible });
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(Creator);
|
||||
|
||||
@ -4,14 +4,14 @@
|
||||
// @flow
|
||||
|
||||
import type { KeyringPair } from '@polkadot/util-keyring/types';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
|
||||
import React from 'react';
|
||||
import Button from 'semantic-ui-react/dist/es/elements/Button';
|
||||
import Input from 'semantic-ui-react/dist/es/elements/Input';
|
||||
import Label from 'semantic-ui-react/dist/es/elements/Label';
|
||||
|
||||
import Input from '@polkadot/ui-app/src/Input';
|
||||
import InputAddress from '@polkadot/ui-app/src/InputAddress';
|
||||
import keyring from '@polkadot/ui-keyring/src';
|
||||
import InputAddress from '@polkadot/ui-react-app/src/InputAddress';
|
||||
|
||||
import Address from './Address';
|
||||
import translate from './translate';
|
||||
@ -21,8 +21,8 @@ type Props = I18nProps & {
|
||||
};
|
||||
|
||||
type State = {
|
||||
currentPair: KeyringPair,
|
||||
defaultPublicKey: Uint8Array,
|
||||
currentPair: KeyringPair | null,
|
||||
defaultPublicKey?: Uint8Array,
|
||||
editedName: string,
|
||||
isEdited: boolean
|
||||
}
|
||||
@ -34,55 +34,69 @@ class Editor extends React.PureComponent<Props, State> {
|
||||
super(props);
|
||||
|
||||
const pairs = keyring.getPairs();
|
||||
const currentPair = pairs[pairs.length - 1];
|
||||
const currentPair = pairs[pairs.length - 1] || null;
|
||||
|
||||
this.state = this.createState(currentPair);
|
||||
this.state.defaultPublicKey = currentPair.publicKey();
|
||||
this.state.defaultPublicKey = currentPair
|
||||
? currentPair.publicKey()
|
||||
: void 0;
|
||||
}
|
||||
|
||||
render (): React$Node {
|
||||
const { className, style, t } = this.props;
|
||||
const { defaultPublicKey, currentPair, editedName, isEdited } = this.state;
|
||||
|
||||
if (!currentPair) {
|
||||
return (
|
||||
<div
|
||||
className={['accounts--Editor', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
{t('editor.none', {
|
||||
defaultValue: 'There are no saved accounts. Add some first.'
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const address = currentPair.address();
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['accounts--Editor', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='ui--grid'>
|
||||
<div className='medium'>
|
||||
<Address
|
||||
className='shrink'
|
||||
value={address}
|
||||
/>
|
||||
<div className='grow'>
|
||||
<div className='ui--row'>
|
||||
<InputAddress
|
||||
className='full'
|
||||
defaultValue={defaultPublicKey}
|
||||
hideAddress
|
||||
isInput={false}
|
||||
isSUIInput={false}
|
||||
label={t('editor.select', {
|
||||
defaultValue: 'using my account'
|
||||
})}
|
||||
onChange={this.onChangeAccount}
|
||||
type='account'
|
||||
value={address}
|
||||
/>
|
||||
</div>
|
||||
<div className='ui--row'>
|
||||
<div className='full'>
|
||||
<Label>{t('editor.name', {
|
||||
<Input
|
||||
className='full'
|
||||
label={t('editor.name', {
|
||||
defaultValue: 'identified by the name'
|
||||
})}</Label>
|
||||
<Input
|
||||
onChange={this.onChangeName}
|
||||
value={editedName}
|
||||
/>
|
||||
</div>
|
||||
})}
|
||||
onChange={this.onChangeName}
|
||||
value={editedName}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Address
|
||||
className='medium'
|
||||
value={{
|
||||
address: currentPair.address(),
|
||||
publicKey: currentPair.publicKey()
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className='ui--row-buttons'>
|
||||
<Button
|
||||
@ -102,17 +116,26 @@ class Editor extends React.PureComponent<Props, State> {
|
||||
defaultValue: 'Save'
|
||||
})}
|
||||
</Button>
|
||||
<Button
|
||||
negative
|
||||
onClick={this.onForget}
|
||||
primary
|
||||
>
|
||||
{t('editor.forget', {
|
||||
defaultValue: 'Forget'
|
||||
})}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
createState (currentPair: KeyringPair): $Shape<State> {
|
||||
const { name = '' } = currentPair.getMeta();
|
||||
|
||||
createState (currentPair: KeyringPair | null): $Shape<State> {
|
||||
return {
|
||||
currentPair,
|
||||
editedName: name,
|
||||
editedName: currentPair
|
||||
? currentPair.getMeta().name || ''
|
||||
: '',
|
||||
isEdited: false
|
||||
};
|
||||
}
|
||||
@ -121,13 +144,19 @@ class Editor extends React.PureComponent<Props, State> {
|
||||
this.setState(
|
||||
(prevState: State): $Shape<State> => {
|
||||
let { currentPair = prevState.currentPair, editedName = prevState.editedName } = newState;
|
||||
const previous = prevState.currentPair || { address: () => null };
|
||||
let isEdited = false;
|
||||
|
||||
if (currentPair.address() !== prevState.currentPair.address()) {
|
||||
editedName = currentPair.getMeta().name || '';
|
||||
if (currentPair) {
|
||||
if (currentPair.address() !== previous.address()) {
|
||||
editedName = currentPair.getMeta().name || '';
|
||||
} else if (editedName !== currentPair.getMeta().name) {
|
||||
isEdited = true;
|
||||
}
|
||||
} else {
|
||||
editedName = '';
|
||||
}
|
||||
|
||||
const isEdited = editedName !== currentPair.getMeta().name;
|
||||
|
||||
return {
|
||||
currentPair,
|
||||
editedName,
|
||||
@ -145,14 +174,17 @@ class Editor extends React.PureComponent<Props, State> {
|
||||
});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
onChangeName = (event: SyntheticEvent<*>, { value }): void => {
|
||||
this.nextState({ editedName: value });
|
||||
onChangeName = (editedName: string): void => {
|
||||
this.nextState({ editedName });
|
||||
}
|
||||
|
||||
onCommit = (): void => {
|
||||
const { currentPair, editedName } = this.state;
|
||||
|
||||
if (!currentPair) {
|
||||
return;
|
||||
}
|
||||
|
||||
keyring.saveAccountMeta(currentPair, {
|
||||
name: editedName,
|
||||
whenEdited: Date.now()
|
||||
@ -164,10 +196,38 @@ class Editor extends React.PureComponent<Props, State> {
|
||||
onDiscard = (): void => {
|
||||
const { currentPair } = this.state;
|
||||
|
||||
if (!currentPair) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.nextState({
|
||||
editedName: currentPair.getMeta().name
|
||||
});
|
||||
}
|
||||
|
||||
onForget = (): void => {
|
||||
const { currentPair } = this.state;
|
||||
|
||||
if (!currentPair) {
|
||||
return;
|
||||
}
|
||||
|
||||
const address = currentPair.address();
|
||||
const pairs = keyring.getPairs().filter((item) =>
|
||||
item.address() !== address
|
||||
);
|
||||
const nextPair = pairs[pairs.length - 1] || null;
|
||||
const defaultPublicKey = nextPair
|
||||
? nextPair.publicKey()
|
||||
: void 0;
|
||||
|
||||
keyring.forgetAccount(address);
|
||||
|
||||
this.nextState({
|
||||
currentPair: nextPair,
|
||||
defaultPublicKey
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(Editor);
|
||||
|
||||
@ -15,6 +15,15 @@
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.accounts--Address .rx--updated {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.accounts--Address.invalid {
|
||||
filter: grayscale(100);
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
.accounts--Address-icon {
|
||||
display: block
|
||||
}
|
||||
@ -24,7 +33,14 @@
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
.accounts--Address-data {}
|
||||
.accounts--Address-balance.rx--updated,
|
||||
.accounts--Address-nonce.rx--updated {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.accounts--Address-data {
|
||||
padding: 0.5em 2em;
|
||||
}
|
||||
|
||||
.accounts--Address-data * {
|
||||
margin: 0 0.25rem !important;
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
|
||||
import './index.css';
|
||||
|
||||
@ -19,8 +19,7 @@ type Props = I18nProps & {};
|
||||
type Actions = 'create' | 'edit';
|
||||
|
||||
type State = {
|
||||
currentAction: Actions,
|
||||
currentAddress: string | null
|
||||
action: Actions
|
||||
}
|
||||
|
||||
// FIXME React-router would probably be the best route, not home-grown
|
||||
@ -30,19 +29,12 @@ const Components: { [Actions]: React$ComponentType<*> } = {
|
||||
};
|
||||
|
||||
class App extends React.PureComponent<Props, State> {
|
||||
constructor (props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
currentAction: 'edit',
|
||||
currentAddress: null
|
||||
};
|
||||
}
|
||||
state: State = { action: 'edit' };
|
||||
|
||||
render (): React$Node {
|
||||
const { className, style, t } = this.props;
|
||||
const { currentAction } = this.state;
|
||||
const Component = Components[currentAction];
|
||||
const { action } = this.state;
|
||||
const Component = Components[action];
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -53,7 +45,7 @@ class App extends React.PureComponent<Props, State> {
|
||||
<Button.Group>
|
||||
<Button
|
||||
onClick={this.selectEdit}
|
||||
primary={currentAction === 'edit'}
|
||||
primary={action === 'edit'}
|
||||
>
|
||||
{t('app.edit', {
|
||||
defaultValue: 'Edit account'
|
||||
@ -66,7 +58,7 @@ class App extends React.PureComponent<Props, State> {
|
||||
/>
|
||||
<Button
|
||||
onClick={this.selectCreate}
|
||||
primary={currentAction === 'create'}
|
||||
primary={action === 'create'}
|
||||
>
|
||||
{t('app.create', {
|
||||
defaultValue: 'Create account'
|
||||
@ -79,16 +71,12 @@ class App extends React.PureComponent<Props, State> {
|
||||
);
|
||||
}
|
||||
|
||||
setCurrentAction (currentAction: Actions): void {
|
||||
this.setState({ currentAction });
|
||||
}
|
||||
|
||||
selectCreate = (): void => {
|
||||
this.setCurrentAction('create');
|
||||
this.setState({ action: 'create' });
|
||||
}
|
||||
|
||||
selectEdit = (): void => {
|
||||
this.setCurrentAction('edit');
|
||||
this.setState({ action: 'edit' });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/app-addresses",
|
||||
"version": "0.3.4",
|
||||
"version": "0.4.0",
|
||||
"main": "index.js",
|
||||
"repository": "https://github.com/polkadot-js/apps.git",
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
@ -11,7 +11,7 @@
|
||||
"test": "jest --coverage"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@polkadot/app-accounts": "^0.3.4",
|
||||
"@polkadot/ui-react-app": "^0.3.4"
|
||||
"@polkadot/app-accounts": "^0.4.0",
|
||||
"@polkadot/ui-app": "^0.4.0"
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,12 +3,12 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
|
||||
import React from 'react';
|
||||
import Button from 'semantic-ui-react/dist/es/elements/Button';
|
||||
import Input from 'semantic-ui-react/dist/es/elements/Input';
|
||||
import Label from 'semantic-ui-react/dist/es/elements/Label';
|
||||
|
||||
import Input from '@polkadot/ui-app/src/Input';
|
||||
import keyring from '@polkadot/ui-keyring/src';
|
||||
import addressDecode from '@polkadot/util-keyring/address/decode';
|
||||
import addressEncode from '@polkadot/util-keyring/address/encode';
|
||||
@ -21,8 +21,7 @@ type Props = I18nProps & {
|
||||
};
|
||||
|
||||
type State = {
|
||||
address: string | null,
|
||||
publicKey: Uint8Array | null,
|
||||
address: string,
|
||||
fieldName: string,
|
||||
isAddressValid: boolean,
|
||||
isNameValid: boolean,
|
||||
@ -41,7 +40,7 @@ class Creator extends React.PureComponent<Props, State> {
|
||||
|
||||
render (): React$Node {
|
||||
const { className, style, t } = this.props;
|
||||
const { address, fieldName, isAddressValid, isNameValid, isValid, name, publicKey } = this.state;
|
||||
const { address, fieldName, isAddressValid, isNameValid, isValid, name } = this.state;
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -49,46 +48,36 @@ class Creator extends React.PureComponent<Props, State> {
|
||||
style={style}
|
||||
>
|
||||
<div className='ui--grid'>
|
||||
<div className='medium'>
|
||||
<Address
|
||||
className='shrink'
|
||||
value={address}
|
||||
/>
|
||||
<div className='grow'>
|
||||
<div className='ui--row'>
|
||||
<div className='full'>
|
||||
<Label>{t('creator.address', {
|
||||
<Input
|
||||
className='full'
|
||||
isError={!isAddressValid}
|
||||
label={t('creator.address', {
|
||||
defaultValue: 'add the following address'
|
||||
})}</Label>
|
||||
<Input
|
||||
error={!isAddressValid}
|
||||
name={`${fieldName}_address`}
|
||||
onChange={this.onChangeAddress}
|
||||
value={address}
|
||||
/>
|
||||
</div>
|
||||
})}
|
||||
name={`${fieldName}_address`}
|
||||
onChange={this.onChangeAddress}
|
||||
value={address}
|
||||
/>
|
||||
</div>
|
||||
<div className='ui--row'>
|
||||
<div className='full'>
|
||||
<Label>{t('creator.name', {
|
||||
<Input
|
||||
className='full'
|
||||
isError={!isNameValid}
|
||||
label={t('creator.name', {
|
||||
defaultValue: 'name the entry'
|
||||
})}</Label>
|
||||
<Input
|
||||
error={!isNameValid}
|
||||
name={`${fieldName}_name`}
|
||||
onChange={this.onChangeName}
|
||||
value={name}
|
||||
/>
|
||||
</div>
|
||||
})}
|
||||
name={`${fieldName}_name`}
|
||||
onChange={this.onChangeName}
|
||||
value={name}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Address
|
||||
className='medium'
|
||||
value={
|
||||
// flowlint-next-line sketchy-null-string:off
|
||||
!address || !publicKey
|
||||
? null
|
||||
: {
|
||||
address,
|
||||
publicKey
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className='ui--row-buttons'>
|
||||
<Button
|
||||
@ -119,8 +108,7 @@ class Creator extends React.PureComponent<Props, State> {
|
||||
isAddressValid: false,
|
||||
isNameValid: true,
|
||||
isValid: false,
|
||||
name: 'new address',
|
||||
publicKey: null
|
||||
name: 'new address'
|
||||
};
|
||||
}
|
||||
|
||||
@ -129,51 +117,42 @@ class Creator extends React.PureComponent<Props, State> {
|
||||
(prevState: State, props: Props): $Shape<State> => {
|
||||
const { address = prevState.address, name = prevState.name } = newState;
|
||||
|
||||
let nextAddress;
|
||||
let publicKey;
|
||||
let isAddressValid = true;
|
||||
|
||||
try {
|
||||
// $FlowFixMe we do expect failures... sometimes
|
||||
publicKey = addressDecode(address);
|
||||
nextAddress = addressEncode(publicKey);
|
||||
addressEncode(
|
||||
addressDecode(address)
|
||||
);
|
||||
} catch (error) {
|
||||
nextAddress = void 0;
|
||||
publicKey = void 0;
|
||||
isAddressValid = false;
|
||||
}
|
||||
|
||||
const isNameValid = !!name;
|
||||
const isAddressValid = !!nextAddress;
|
||||
|
||||
return {
|
||||
address: nextAddress,
|
||||
address,
|
||||
isAddressValid,
|
||||
isNameValid,
|
||||
isValid: isAddressValid && isNameValid,
|
||||
name,
|
||||
publicKey
|
||||
name
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
onChangeAddress = (event: SyntheticEvent<*>, { value }): void => {
|
||||
this.nextState({ address: value });
|
||||
onChangeAddress = (address: string): void => {
|
||||
this.nextState({ address });
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
onChangeName = (event: SyntheticEvent<*>, { value }): void => {
|
||||
this.nextState({ name: value });
|
||||
onChangeName = (name: string): void => {
|
||||
this.nextState({ name });
|
||||
}
|
||||
|
||||
onCommit = (): void => {
|
||||
const { onBack } = this.props;
|
||||
const { address, name } = this.state;
|
||||
|
||||
// flowlint-next-line sketchy-null-string:off
|
||||
if (address) {
|
||||
keyring.saveAddress(address, { name });
|
||||
}
|
||||
keyring.saveAddress(address, { name });
|
||||
|
||||
onBack();
|
||||
}
|
||||
|
||||
@ -4,14 +4,14 @@
|
||||
// @flow
|
||||
|
||||
import type { KeyringAddress } from '@polkadot/ui-keyring/types';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
|
||||
import React from 'react';
|
||||
import Button from 'semantic-ui-react/dist/es/elements/Button';
|
||||
import Input from 'semantic-ui-react/dist/es/elements/Input';
|
||||
import Label from 'semantic-ui-react/dist/es/elements/Label';
|
||||
|
||||
import Input from '@polkadot/ui-app/src/Input';
|
||||
import InputAddress from '@polkadot/ui-app/src/InputAddress';
|
||||
import keyring from '@polkadot/ui-keyring/src';
|
||||
import InputAddress from '@polkadot/ui-react-app/src/InputAddress';
|
||||
|
||||
import Address from '@polkadot/app-accounts/src/Address';
|
||||
import translate from './translate';
|
||||
@ -21,7 +21,7 @@ type Props = I18nProps & {
|
||||
};
|
||||
|
||||
type State = {
|
||||
currentAddress?: KeyringAddress,
|
||||
currentAddress: KeyringAddress | null,
|
||||
defaultPublicKey?: Uint8Array,
|
||||
editedName: string,
|
||||
isEdited: boolean,
|
||||
@ -35,7 +35,7 @@ class Editor extends React.PureComponent<Props, State> {
|
||||
super(props);
|
||||
|
||||
const addresses = keyring.getAddresses();
|
||||
const currentAddress = addresses[addresses.length - 1];
|
||||
const currentAddress = addresses[addresses.length - 1] || null;
|
||||
|
||||
this.state = this.createState(currentAddress);
|
||||
this.state.defaultPublicKey = currentAddress
|
||||
@ -60,13 +60,19 @@ class Editor extends React.PureComponent<Props, State> {
|
||||
);
|
||||
}
|
||||
|
||||
const address = currentAddress.address();
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['addresses--Editor', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='ui--grid'>
|
||||
<div className='medium'>
|
||||
<Address
|
||||
className='shrink'
|
||||
value={address}
|
||||
/>
|
||||
<div className='grow'>
|
||||
<div className='ui--row'>
|
||||
<InputAddress
|
||||
className='full'
|
||||
@ -78,27 +84,20 @@ class Editor extends React.PureComponent<Props, State> {
|
||||
})}
|
||||
onChange={this.onChangeAddress}
|
||||
type='address'
|
||||
value={address}
|
||||
/>
|
||||
</div>
|
||||
<div className='ui--row'>
|
||||
<div className='full'>
|
||||
<Label>{t('editor.name', {
|
||||
<Input
|
||||
className='full'
|
||||
label={t('editor.name', {
|
||||
defaultValue: 'identified by the name'
|
||||
})}</Label>
|
||||
<Input
|
||||
onChange={this.onChangeName}
|
||||
value={editedName}
|
||||
/>
|
||||
</div>
|
||||
})}
|
||||
onChange={this.onChangeName}
|
||||
value={editedName}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Address
|
||||
className='medium'
|
||||
value={{
|
||||
address: currentAddress.address(),
|
||||
publicKey: currentAddress.publicKey()
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className='ui--row-buttons'>
|
||||
<Button
|
||||
@ -118,12 +117,21 @@ class Editor extends React.PureComponent<Props, State> {
|
||||
defaultValue: 'Save'
|
||||
})}
|
||||
</Button>
|
||||
<Button
|
||||
negative
|
||||
onClick={this.onForget}
|
||||
primary
|
||||
>
|
||||
{t('editor.forget', {
|
||||
defaultValue: 'Forget'
|
||||
})}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
createState (currentAddress?: KeyringAddress): $Shape<State> {
|
||||
createState (currentAddress: KeyringAddress | null): $Shape<State> {
|
||||
const { name = '' } = currentAddress
|
||||
? currentAddress.getMeta()
|
||||
: {};
|
||||
@ -140,13 +148,18 @@ class Editor extends React.PureComponent<Props, State> {
|
||||
(prevState: State): $Shape<State> => {
|
||||
let { currentAddress = prevState.currentAddress, editedName = prevState.editedName } = newState;
|
||||
const previous = prevState.currentAddress || { address: () => null };
|
||||
let isEdited = false;
|
||||
|
||||
if (currentAddress && currentAddress.address() !== previous.address()) {
|
||||
editedName = currentAddress.getMeta().name || '';
|
||||
if (currentAddress && currentAddress.isValid()) {
|
||||
if (currentAddress.address() !== previous.address()) {
|
||||
editedName = currentAddress.getMeta().name || '';
|
||||
} else if (editedName !== currentAddress.getMeta().name) {
|
||||
isEdited = true;
|
||||
}
|
||||
} else {
|
||||
editedName = '';
|
||||
}
|
||||
|
||||
const isEdited = !!currentAddress && editedName !== currentAddress.getMeta().name;
|
||||
|
||||
return {
|
||||
currentAddress,
|
||||
editedName,
|
||||
@ -157,16 +170,15 @@ class Editor extends React.PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
onChangeAddress = (publicKey: Uint8Array): void => {
|
||||
const currentAddress = keyring.getAddress(publicKey);
|
||||
const currentAddress = keyring.getAddress(publicKey) || null;
|
||||
|
||||
this.nextState({
|
||||
currentAddress
|
||||
});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
onChangeName = (event: SyntheticEvent<*>, { value }): void => {
|
||||
this.nextState({ editedName: value });
|
||||
onChangeName = (editedName: string): void => {
|
||||
this.nextState({ editedName });
|
||||
}
|
||||
|
||||
onCommit = (): void => {
|
||||
@ -195,6 +207,30 @@ class Editor extends React.PureComponent<Props, State> {
|
||||
editedName: currentAddress.getMeta().name
|
||||
});
|
||||
}
|
||||
|
||||
onForget = (): void => {
|
||||
const { currentAddress } = this.state;
|
||||
|
||||
if (!currentAddress) {
|
||||
return;
|
||||
}
|
||||
|
||||
const address = currentAddress.address();
|
||||
const addresses = keyring.getAddresses().filter((item) =>
|
||||
item.address() !== address
|
||||
);
|
||||
const nextAddress = addresses[0] || null;
|
||||
const defaultPublicKey = nextAddress
|
||||
? nextAddress.publicKey()
|
||||
: void 0;
|
||||
|
||||
keyring.forgetAddress(address);
|
||||
|
||||
this.nextState({
|
||||
currentAddress: nextAddress,
|
||||
defaultPublicKey
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(Editor);
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
|
||||
import './index.css';
|
||||
|
||||
@ -19,8 +19,7 @@ type Props = I18nProps & {};
|
||||
type Actions = 'create' | 'edit';
|
||||
|
||||
type State = {
|
||||
currentAction: Actions,
|
||||
currentAddress: string | null
|
||||
action: Actions
|
||||
}
|
||||
|
||||
// FIXME React-router would probably be the best route, not home-grown
|
||||
@ -30,19 +29,12 @@ const Components: { [Actions]: React$ComponentType<*> } = {
|
||||
};
|
||||
|
||||
class App extends React.PureComponent<Props, State> {
|
||||
constructor (props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
currentAction: 'edit',
|
||||
currentAddress: null
|
||||
};
|
||||
}
|
||||
state: State = { action: 'edit' };
|
||||
|
||||
render (): React$Node {
|
||||
const { className, style, t } = this.props;
|
||||
const { currentAction } = this.state;
|
||||
const Component = Components[currentAction];
|
||||
const { action } = this.state;
|
||||
const Component = Components[action];
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -53,7 +45,7 @@ class App extends React.PureComponent<Props, State> {
|
||||
<Button.Group>
|
||||
<Button
|
||||
onClick={this.selectEdit}
|
||||
primary={currentAction === 'edit'}
|
||||
primary={action === 'edit'}
|
||||
>
|
||||
{t('app.edit', {
|
||||
defaultValue: 'Edit address'
|
||||
@ -66,7 +58,7 @@ class App extends React.PureComponent<Props, State> {
|
||||
/>
|
||||
<Button
|
||||
onClick={this.selectCreate}
|
||||
primary={currentAction === 'create'}
|
||||
primary={action === 'create'}
|
||||
>
|
||||
{t('app.create', {
|
||||
defaultValue: 'Add address'
|
||||
@ -79,16 +71,12 @@ class App extends React.PureComponent<Props, State> {
|
||||
);
|
||||
}
|
||||
|
||||
setCurrentAction (currentAction: Actions): void {
|
||||
this.setState({ currentAction });
|
||||
}
|
||||
|
||||
selectCreate = (): void => {
|
||||
this.setCurrentAction('create');
|
||||
this.setState({ action: 'create' });
|
||||
}
|
||||
|
||||
selectEdit = (): void => {
|
||||
this.setCurrentAction('edit');
|
||||
this.setState({ action: 'edit' });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/app-explorer",
|
||||
"version": "0.3.4",
|
||||
"version": "0.4.0",
|
||||
"main": "index.js",
|
||||
"repository": "https://github.com/polkadot-js/apps.git",
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
@ -14,7 +14,7 @@
|
||||
"@polkadot/primitives": "^0.12.9",
|
||||
"@polkadot/primitives-codec": "^0.12.9",
|
||||
"@polkadot/primitives-json": "^0.12.9",
|
||||
"@polkadot/ui-react-app": "^0.3.4",
|
||||
"@polkadot/ui-app": "^0.4.0",
|
||||
"@polkadot/util-crypto": "^0.19.6"
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,11 +4,12 @@
|
||||
// @flow
|
||||
|
||||
import type { Header } from '@polkadot/primitives/header';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
|
||||
import './BlockHeader.css';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import headerHash from '@polkadot/primitives-codec/header/hash';
|
||||
import u8aToHex from '@polkadot/util/u8a/toHex';
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
import type { Header } from '@polkadot/primitives/header';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import withApiDiv from '@polkadot/ui-react-rx/with/apiDiv';
|
||||
|
||||
import BlockHeader from './BlockHeader';
|
||||
|
||||
@ -3,11 +3,12 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
|
||||
import './index.css';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import BestNumber from '@polkadot/ui-react-rx/BestNumber';
|
||||
|
||||
import BestHash from './BestHash';
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/app-extrinsics",
|
||||
"version": "0.3.4",
|
||||
"version": "0.4.0",
|
||||
"main": "index.js",
|
||||
"repository": "https://github.com/polkadot-js/apps.git",
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
@ -13,7 +13,7 @@
|
||||
"devDependencies": {
|
||||
"@polkadot/extrinsics": "^0.12.9",
|
||||
"@polkadot/extrinsics-codec": "^0.12.9",
|
||||
"@polkadot/ui-react-app": "^0.3.4",
|
||||
"@polkadot/ui-app": "^0.4.0",
|
||||
"react-dropzone": "^4.2.9"
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,12 +4,13 @@
|
||||
// @flow
|
||||
|
||||
import type { KeyringOption$Type } from '@polkadot/ui-keyring/types';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
|
||||
import React from 'react';
|
||||
import Label from 'semantic-ui-react/dist/es/elements/Label';
|
||||
|
||||
import InputAddress from '@polkadot/ui-app/src/InputAddress';
|
||||
import Labelled from '@polkadot/ui-app/src/Labelled';
|
||||
import Balance from '@polkadot/ui-react-rx/Balance';
|
||||
import InputAddress from '@polkadot/ui-react-app/src/InputAddress';
|
||||
|
||||
import translate from './translate';
|
||||
|
||||
@ -57,17 +58,17 @@ class Account extends React.PureComponent<Props, State> {
|
||||
type={type}
|
||||
/>
|
||||
</div>
|
||||
<div className='small'>
|
||||
<Label>
|
||||
{t('account.balance', {
|
||||
defaultValue: 'with an available balance of'
|
||||
})}
|
||||
</Label>
|
||||
<Labelled
|
||||
className='small'
|
||||
label={t('account.balance', {
|
||||
defaultValue: 'with an available balance of'
|
||||
})}
|
||||
>
|
||||
<Balance
|
||||
className='ui disabled dropdown selection'
|
||||
params={publicKey}
|
||||
/>
|
||||
</div>
|
||||
</Labelled>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -4,14 +4,15 @@
|
||||
// @flow
|
||||
|
||||
import type { Extrinsic } from '@polkadot/extrinsics/types';
|
||||
import type { BareProps } from '@polkadot/ui-react-app/types';
|
||||
import type { RawParam } from '@polkadot/ui-react-app/Params/types';
|
||||
import type { BareProps } from '@polkadot/ui-app/types';
|
||||
import type { RawParam } from '@polkadot/ui-app/Params/types';
|
||||
import type { EncodedMessage } from './types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import encode from '@polkadot/extrinsics-codec/encode/extrinsic';
|
||||
import InputExtrinsic from '@polkadot/ui-react-app/src/InputExtrinsic';
|
||||
import Params from '@polkadot/ui-react-app/src/Params';
|
||||
import InputExtrinsic from '@polkadot/ui-app/src/InputExtrinsic';
|
||||
import Params from '@polkadot/ui-app/src/Params';
|
||||
import isUndefined from '@polkadot/util/is/undefined';
|
||||
|
||||
import paramComponents from './Params';
|
||||
|
||||
@ -4,10 +4,11 @@
|
||||
// @flow
|
||||
|
||||
import type BN from 'bn.js';
|
||||
import type { BareProps } from '@polkadot/ui-react-app/types';
|
||||
import type { BareProps } from '@polkadot/ui-app/types';
|
||||
|
||||
import React from 'react';
|
||||
import Label from 'semantic-ui-react/dist/es/elements/Label';
|
||||
|
||||
import Labelled from '@polkadot/ui-app/src/Labelled';
|
||||
import RxNonce from '@polkadot/ui-react-rx/Nonce';
|
||||
|
||||
type Props = BareProps & {
|
||||
@ -22,14 +23,16 @@ export default function Nonce ({ className, label, style, onChange, value }: Pro
|
||||
className={['ui--row', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='small'>
|
||||
<Label>{label}</Label>
|
||||
<Labelled
|
||||
className='small'
|
||||
label={label}
|
||||
>
|
||||
<RxNonce
|
||||
className='ui disabled dropdown selection'
|
||||
onChange={onChange}
|
||||
params={value}
|
||||
/>
|
||||
</div>
|
||||
</Labelled>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { Props as BaseProps } from '@polkadot/ui-react-app/Params/types';
|
||||
import type { Props as BaseProps } from '@polkadot/ui-app/Params/types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
@ -13,22 +13,29 @@ type Props = BaseProps & {
|
||||
defaultValue?: Uint8Array
|
||||
};
|
||||
|
||||
export default function Account ({ className, defaultValue, index, isError, onChange, label, style }: Props): React$Node {
|
||||
const _onChange = (value?: Uint8Array): void =>
|
||||
export default class Account extends React.PureComponent<Props> {
|
||||
render (): React$Node {
|
||||
const { className, defaultValue, isError, label, style } = this.props;
|
||||
|
||||
return (
|
||||
<BaseAccount
|
||||
className={className}
|
||||
defaultValue={defaultValue}
|
||||
isError={isError}
|
||||
isInput
|
||||
label={label}
|
||||
onChange={this.onChange}
|
||||
style={style}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
onChange = (value?: Uint8Array): void => {
|
||||
const { index, onChange } = this.props;
|
||||
|
||||
onChange(index, {
|
||||
isValid: !!value && value.length === 32,
|
||||
value
|
||||
});
|
||||
|
||||
return (
|
||||
<BaseAccount
|
||||
className={className}
|
||||
defaultValue={defaultValue}
|
||||
isError={isError}
|
||||
isInput
|
||||
label={label}
|
||||
onChange={_onChange}
|
||||
style={style}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,11 +3,12 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { Props as BaseProps } from '@polkadot/ui-react-app/Params/types';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { Props as BaseProps } from '@polkadot/ui-app/Params/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
import type { EncodedMessage } from '../types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import extrinsics from '@polkadot/extrinsics-substrate';
|
||||
|
||||
import Extrinsic from '../Extrinsic';
|
||||
@ -17,35 +18,42 @@ type Props = BaseProps & I18nProps;
|
||||
|
||||
const defaultValue = extrinsics.consensus.methods.private.setCode;
|
||||
|
||||
function Proposal ({ className, index, isError, onChange, label, style, t }: Props): React$Node {
|
||||
const _onChange = ({ isValid, value }: EncodedMessage): void =>
|
||||
class Proposal extends React.PureComponent<Props> {
|
||||
render (): React$Node {
|
||||
const { className, isError, label, style, t } = this.props;
|
||||
|
||||
return (
|
||||
<Extrinsic
|
||||
className={className}
|
||||
defaultValue={defaultValue}
|
||||
isError={isError}
|
||||
isPrivate
|
||||
labelMethod={t('proposal.method', {
|
||||
defaultValue: '{{label}} (extrinsic)',
|
||||
replace: {
|
||||
label
|
||||
}
|
||||
})}
|
||||
labelSection={t('proposal.method', {
|
||||
defaultValue: '{{label}} (section)',
|
||||
replace: {
|
||||
label
|
||||
}
|
||||
})}
|
||||
onChange={this.onChange}
|
||||
style={style}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
onChange = ({ isValid, value }: EncodedMessage): void => {
|
||||
const { index, onChange } = this.props;
|
||||
|
||||
onChange(index, {
|
||||
isValid,
|
||||
value
|
||||
});
|
||||
|
||||
return (
|
||||
<Extrinsic
|
||||
className={className}
|
||||
defaultValue={defaultValue}
|
||||
isError={isError}
|
||||
isPrivate
|
||||
labelMethod={t('proposal.method', {
|
||||
defaultValue: '{{label}} (extrinsic)',
|
||||
replace: {
|
||||
label
|
||||
}
|
||||
})}
|
||||
labelSection={t('proposal.method', {
|
||||
defaultValue: '{{label}} (section)',
|
||||
replace: {
|
||||
label
|
||||
}
|
||||
})}
|
||||
onChange={_onChange}
|
||||
style={style}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(Proposal);
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { ComponentMap } from '@polkadot/ui-react-app/Params/types';
|
||||
import type { ComponentMap } from '@polkadot/ui-app/Params/types';
|
||||
|
||||
import Account from './Account';
|
||||
import Proposal from './Proposal';
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
// @flow
|
||||
|
||||
import type BN from 'bn.js';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
import type { EncodedMessage, QueueTx } from './types';
|
||||
|
||||
import React from 'react';
|
||||
@ -32,15 +32,9 @@ const defaultExtrinsic = extrinsics.staking.methods.public.transfer;
|
||||
let id = 0;
|
||||
|
||||
class Selection extends React.PureComponent<Props, State> {
|
||||
state: State;
|
||||
|
||||
constructor (props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = ({
|
||||
isValid: false
|
||||
}: $Shape<State>);
|
||||
}
|
||||
state: State = ({
|
||||
isValid: false
|
||||
}: $Shape<State>);
|
||||
|
||||
render () {
|
||||
const { className, style, t } = this.props;
|
||||
|
||||
@ -3,12 +3,13 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
import type { QueueTx } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import React from 'react';
|
||||
import { Trans } from 'react-i18next';
|
||||
|
||||
import IdentityIcon from '@polkadot/ui-react/IdentityIcon';
|
||||
import u8aToHexShort from '@polkadot/util/u8a/toHexShort';
|
||||
import addressEncode from '@polkadot/util-keyring/address/encode';
|
||||
|
||||
@ -11,8 +11,16 @@
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.extrinsics--Signer-Decoded {
|
||||
padding-top: 2rem;
|
||||
}
|
||||
|
||||
.extrinsics--Signer-Unlock {
|
||||
padding-top: 1.5em;
|
||||
padding-top: 1.5rem;
|
||||
}
|
||||
|
||||
.extrinsics--Signer-Content {
|
||||
padding: 1.5rem 3rem !important;
|
||||
}
|
||||
|
||||
.extrinsics--Signer-Content .expanded {
|
||||
|
||||
@ -3,13 +3,12 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
import type { KeyringPair } from '@polkadot/util-keyring/types';
|
||||
|
||||
import React from 'react';
|
||||
import Button from 'semantic-ui-react/dist/es/elements/Button';
|
||||
import Input from 'semantic-ui-react/dist/es/elements/Input';
|
||||
import Label from 'semantic-ui-react/dist/es/elements/Label';
|
||||
|
||||
import Password from '@polkadot/ui-app/src/Password';
|
||||
import keyring from '@polkadot/ui-keyring/src';
|
||||
|
||||
import translate from '../translate';
|
||||
@ -26,20 +25,13 @@ type State = {
|
||||
fieldName: string,
|
||||
isError: boolean,
|
||||
isLocked: boolean,
|
||||
isVisible: boolean,
|
||||
pair: KeyringPair
|
||||
}
|
||||
|
||||
class Unlock extends React.PureComponent<Props, State> {
|
||||
constructor (props: Props) {
|
||||
super(props);
|
||||
state: State = ({}: $Shape<State>);
|
||||
|
||||
this.state = ({
|
||||
isVisible: false
|
||||
}: $Shape<State>);
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps ({ error, password, value }: Props, { isVisible }: State): $Shape<State> {
|
||||
static getDerivedStateFromProps ({ error, password, value }: Props): $Shape<State> {
|
||||
const pair = keyring.getPair(value);
|
||||
const isLocked = !pair.hasSecretKey();
|
||||
|
||||
@ -47,16 +39,13 @@ class Unlock extends React.PureComponent<Props, State> {
|
||||
fieldName: `pass_${Date.now()}`,
|
||||
isError: !!error,
|
||||
isLocked,
|
||||
isVisible: password.length === 0
|
||||
? false
|
||||
: isVisible,
|
||||
pair
|
||||
};
|
||||
}
|
||||
|
||||
render (): React$Node {
|
||||
const { className, password, style, t } = this.props;
|
||||
const { fieldName, isError, isLocked, isVisible } = this.state;
|
||||
const { className, onChange, password, style, t } = this.props;
|
||||
const { fieldName, isError, isLocked } = this.state;
|
||||
|
||||
if (!isLocked) {
|
||||
return null;
|
||||
@ -67,42 +56,21 @@ class Unlock extends React.PureComponent<Props, State> {
|
||||
className={['extrinsics--Signer-Unlock', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='expanded ui--row'>
|
||||
<div className='medium'>
|
||||
<Label>{t('unlock.password', {
|
||||
<div className='ui--row'>
|
||||
<Password
|
||||
className='medium'
|
||||
isError={isError}
|
||||
label={t('unlock.password', {
|
||||
defaultValue: 'unlock account using'
|
||||
})}</Label>
|
||||
<Input
|
||||
action
|
||||
error={isError}
|
||||
name={fieldName}
|
||||
onChange={this.onChange}
|
||||
type={isVisible ? 'text' : 'password'}
|
||||
value={password}
|
||||
>
|
||||
<input />
|
||||
<Button
|
||||
icon='eye'
|
||||
primary
|
||||
onClick={this.togglePassword}
|
||||
/>
|
||||
</Input>
|
||||
</div>
|
||||
})}
|
||||
name={fieldName}
|
||||
onChange={onChange}
|
||||
value={password}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
onChange = (event: SyntheticEvent<*>, { value }): void => {
|
||||
this.props.onChange(value);
|
||||
}
|
||||
|
||||
togglePassword = (): void => {
|
||||
this.setState({
|
||||
isVisible: !this.state.isVisible
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(Unlock);
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
// @flow
|
||||
|
||||
import type { ApiProps } from '@polkadot/ui-react-rx/types';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
import type { QueueTx } from '../types';
|
||||
|
||||
import './Signer.css';
|
||||
@ -12,6 +12,7 @@ import './Signer.css';
|
||||
import React from 'react';
|
||||
import Button from 'semantic-ui-react/dist/es/elements/Button';
|
||||
import Modal from 'semantic-ui-react/dist/es/modules/Modal';
|
||||
|
||||
import keyring from '@polkadot/ui-keyring/src';
|
||||
import withApi from '@polkadot/ui-react-rx/with/api';
|
||||
|
||||
@ -37,14 +38,10 @@ type State = {
|
||||
};
|
||||
|
||||
class Signer extends React.PureComponent<Props, State> {
|
||||
constructor (props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
password: '',
|
||||
unlockError: null
|
||||
};
|
||||
}
|
||||
state: State = {
|
||||
password: '',
|
||||
unlockError: null
|
||||
};
|
||||
|
||||
static getDerivedStateFromProps ({ queue }: Props, { currentItem, password, unlockError }: State): $Shape<State> {
|
||||
const nextItem = queue.find(({ status }) =>
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BareProps } from '@polkadot/ui-react-app/types';
|
||||
import type { BareProps } from '@polkadot/ui-app/types';
|
||||
import type { QueueTx } from './types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
@ -7,16 +7,16 @@
|
||||
}
|
||||
|
||||
.extrinsics--Status {
|
||||
bottom: 0;
|
||||
display: inline-block;
|
||||
position: fixed;
|
||||
right: 0.125rem;
|
||||
right: 0.25rem;
|
||||
top: 0.125rem;
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
.extrinsics--Status-Item {
|
||||
background: #bcdaf0;
|
||||
margin-bottom: 0.125rem;
|
||||
margin: 0.125rem;
|
||||
padding: 0.5rem 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BareProps } from '@polkadot/ui-react-app/types';
|
||||
import type { BareProps } from '@polkadot/ui-app/types';
|
||||
import type { QueueTx, QueueTx$Status } from './types';
|
||||
|
||||
import './index.css';
|
||||
@ -21,15 +21,9 @@ type State = {
|
||||
};
|
||||
|
||||
export default class App extends React.PureComponent<Props, State> {
|
||||
state: State;
|
||||
|
||||
constructor (props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
queue: []
|
||||
};
|
||||
}
|
||||
state: State = {
|
||||
queue: []
|
||||
};
|
||||
|
||||
render (): React$Node {
|
||||
const { className, style } = this.props;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/app-storage",
|
||||
"version": "0.3.4",
|
||||
"version": "0.4.0",
|
||||
"main": "index.js",
|
||||
"repository": "https://github.com/polkadot-js/apps.git",
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
@ -11,6 +11,6 @@
|
||||
"test": "jest --coverage"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@polkadot/ui-react-app": "^0.3.4"
|
||||
"@polkadot/ui-app": "^0.4.0"
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
import type { StorageQuery } from './types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
import type { Param$Type, Param$TypeArray } from '@polkadot/primitives/param';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
// import IdentityIcon from '@polkadot/ui-react/IdentityIcon';
|
||||
import addressEncode from '@polkadot/util-keyring/address/encode';
|
||||
import u8aToBn from '@polkadot/util/u8a/toBn';
|
||||
|
||||
@ -3,13 +3,14 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
import type { StorageQuery } from '../types';
|
||||
|
||||
import React from 'react';
|
||||
import Button from 'semantic-ui-react/dist/es/elements/Button';
|
||||
import Label from 'semantic-ui-react/dist/es/elements/Label';
|
||||
import typeToText from '@polkadot/ui-react-app/src/Params/typeToText';
|
||||
|
||||
import Labelled from '@polkadot/ui-app/src/Labelled';
|
||||
import typeToText from '@polkadot/ui-app/src/Params/typeToText';
|
||||
import withStorageDiv from '@polkadot/ui-react-rx/with/storageDiv';
|
||||
|
||||
import translate from '../translate';
|
||||
@ -20,61 +21,82 @@ type Props = I18nProps & {
|
||||
value: StorageQuery
|
||||
};
|
||||
|
||||
type State = {
|
||||
inputs: Array<React$Node>,
|
||||
Component: React$ComponentType<*>;
|
||||
};
|
||||
|
||||
const cache = [];
|
||||
|
||||
function Query ({ className, onRemove, style, value: { id, key, params } }: Props): React$Node {
|
||||
const CachedQuery = (() => {
|
||||
if (!cache[id]) {
|
||||
const values = params.map(({ value }) => value);
|
||||
class Query extends React.PureComponent<Props, State> {
|
||||
state: State = ({}: $Shape<State>);
|
||||
|
||||
cache[id] = withStorageDiv(key, { params: values })(
|
||||
(value) =>
|
||||
format(key.type, value),
|
||||
{ className: 'ui disabled dropdown selection' }
|
||||
);
|
||||
}
|
||||
static getDerivedStateFromProps ({ value: { id, key, params } }: Props, prevState: State): State | null {
|
||||
const Component = ((): React$ComponentType<*> => {
|
||||
if (!cache[id]) {
|
||||
const values = params.map(({ value }) => value);
|
||||
|
||||
return cache[id];
|
||||
})();
|
||||
cache[id] = withStorageDiv(key, { params: values })(
|
||||
(value) =>
|
||||
format(key.type, value),
|
||||
{ className: 'ui disabled dropdown selection' }
|
||||
);
|
||||
}
|
||||
|
||||
return cache[id];
|
||||
})();
|
||||
const inputs = Object
|
||||
.keys(key.params || {})
|
||||
.map((name, index) => {
|
||||
// $FlowFixMe key.params exists
|
||||
const formatted = format(key.params[name].type, params[index].value, 12);
|
||||
|
||||
return (
|
||||
<span key={`param_${name}_${index}`}>{name}={formatted}</span>
|
||||
);
|
||||
});
|
||||
|
||||
return {
|
||||
Component,
|
||||
inputs
|
||||
};
|
||||
}
|
||||
|
||||
render (): React$Node {
|
||||
const { className, style, value: { key } } = this.props;
|
||||
const { Component, inputs } = this.state;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['storage--Query', 'storage--actionrow', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<Labelled
|
||||
className='storage--actionrow-value'
|
||||
label={
|
||||
<div>{key.section}.{key.name}({inputs}): {typeToText(key.type)}</div>
|
||||
}
|
||||
>
|
||||
<Component />
|
||||
</Labelled>
|
||||
<Labelled className='storage--actionrow-button'>
|
||||
<Button
|
||||
icon='close'
|
||||
negative
|
||||
onClick={this.onRemove}
|
||||
/>
|
||||
</Labelled>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
onRemove = (): void => {
|
||||
const { onRemove, value: { id } } = this.props;
|
||||
|
||||
const _onRemove = (): void => {
|
||||
delete cache[id];
|
||||
|
||||
onRemove(id);
|
||||
};
|
||||
|
||||
const inputs = Object
|
||||
.keys(key.params || {})
|
||||
.map((name, index) => {
|
||||
// $FlowFixMe key.params exists
|
||||
const formatted = format(key.params[name].type, params[index].value, 12);
|
||||
|
||||
return (
|
||||
<span>{name}={formatted}</span>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['storage--Query', 'storage--actionrow', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='storage--actionrow-value'>
|
||||
<Label>
|
||||
{key.section}.{key.name}({inputs}): {typeToText(key.type)}
|
||||
</Label>
|
||||
<CachedQuery />
|
||||
</div>
|
||||
<div className='storage--actionrow-button'>
|
||||
<Label> </Label>
|
||||
<Button
|
||||
icon='close'
|
||||
negative
|
||||
onClick={_onRemove}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(Query);
|
||||
|
||||
@ -4,17 +4,17 @@
|
||||
// @flow
|
||||
|
||||
import type { StorageDef$Key } from '@polkadot/storage/types';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { RawParams } from '@polkadot/ui-react-app/Params/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
import type { RawParams } from '@polkadot/ui-app/Params/types';
|
||||
import type { StorageQuery } from './types';
|
||||
|
||||
import React from 'react';
|
||||
import Button from 'semantic-ui-react/dist/es/elements/Button';
|
||||
import Label from 'semantic-ui-react/dist/es/elements/Label';
|
||||
// import encode from '@polkadot/extrinsics-codec/encode/params';
|
||||
|
||||
import storage from '@polkadot/storage-substrate/keys';
|
||||
import InputStorage from '@polkadot/ui-react-app/src/InputStorage';
|
||||
import Params from '@polkadot/ui-react-app/src/Params';
|
||||
import InputStorage from '@polkadot/ui-app/src/InputStorage';
|
||||
import Labelled from '@polkadot/ui-app/src/Labelled';
|
||||
import Params from '@polkadot/ui-app/src/Params';
|
||||
import isUndefined from '@polkadot/util/is/undefined';
|
||||
|
||||
import translate from './translate';
|
||||
@ -33,13 +33,9 @@ const defaultValue = storage.timestamp.keys.current;
|
||||
let id = -1;
|
||||
|
||||
class Selection extends React.PureComponent<Props, State> {
|
||||
constructor (props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = ({
|
||||
key: defaultValue
|
||||
}: $Shape<State>);
|
||||
}
|
||||
state: State = ({
|
||||
key: defaultValue
|
||||
}: $Shape<State>);
|
||||
|
||||
render (): React$Node {
|
||||
const { className, style, t } = this.props;
|
||||
@ -63,15 +59,14 @@ class Selection extends React.PureComponent<Props, State> {
|
||||
onChange={this.onChangeParams}
|
||||
/>
|
||||
</div>
|
||||
<div className='storage--actionrow-button'>
|
||||
<Label> </Label>
|
||||
<Labelled className='storage--actionrow-button'>
|
||||
<Button
|
||||
disabled={!isValid}
|
||||
icon='plus'
|
||||
onClick={this.onAdd}
|
||||
primary
|
||||
/>
|
||||
</div>
|
||||
</Labelled>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
import type { StorageQuery } from './types';
|
||||
|
||||
import './index.css';
|
||||
@ -21,15 +21,9 @@ type State = {
|
||||
}
|
||||
|
||||
class App extends React.PureComponent<Props, State> {
|
||||
state: State;
|
||||
|
||||
constructor (props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
queue: []
|
||||
};
|
||||
}
|
||||
state: State = {
|
||||
queue: []
|
||||
};
|
||||
|
||||
render (): React$Node {
|
||||
const { className, style } = this.props;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/app-vanitygen",
|
||||
"version": "0.3.4",
|
||||
"version": "0.4.0",
|
||||
"main": "index.js",
|
||||
"repository": "https://github.com/polkadot-js/apps.git",
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
@ -11,9 +11,8 @@
|
||||
"test": "jest --coverage"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@polkadot/ui-react-app": "^0.3.4",
|
||||
"@polkadot/ui-app": "^0.4.0",
|
||||
"chalk": "^2.4.1",
|
||||
"react-copy-to-clipboard": "^5.0.1",
|
||||
"yargs": "10.1.2"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
|
||||
@ -3,11 +3,12 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BareProps } from '@polkadot/ui-react-app/types';
|
||||
import type { BareProps } from '@polkadot/ui-app/types';
|
||||
|
||||
import React from 'react';
|
||||
import CopyToClipboard from 'react-copy-to-clipboard';
|
||||
import Button from 'semantic-ui-react/dist/es/elements/Button';
|
||||
|
||||
import CopyButton from '@polkadot/ui-app/src/CopyButton';
|
||||
import IdentityIcon from '@polkadot/ui-react/IdentityIcon';
|
||||
import u8aToHex from '@polkadot/util/u8a/toHex';
|
||||
|
||||
@ -19,46 +20,59 @@ type Props = BareProps & {
|
||||
seed: Uint8Array;
|
||||
}
|
||||
|
||||
export default function Match ({ address, className, count, offset, onRemove, seed, style }: Props): React$Node {
|
||||
const _onRemove = (): void =>
|
||||
onRemove(address);
|
||||
const hexSeed = u8aToHex(seed);
|
||||
type State = {
|
||||
hexSeed: string
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['vanity--Match', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='vanity--Match-item'>
|
||||
<IdentityIcon
|
||||
className='vanity--Match-icon'
|
||||
size={48}
|
||||
value={address}
|
||||
/>
|
||||
<div className='vanity--Match-data'>
|
||||
<div className='vanity--Match-addr'>
|
||||
<span className='no'>{address.slice(0, offset)}</span><span className='yes'>{address.slice(offset, count + offset)}</span><span className='no'>{address.slice(count + offset)}</span>
|
||||
export default class Match extends React.PureComponent<Props, State> {
|
||||
state: State = ({}: $Shape<State>);
|
||||
|
||||
static getDerivedStateFromProps ({ seed }: Props): State {
|
||||
return {
|
||||
hexSeed: u8aToHex(seed)
|
||||
};
|
||||
}
|
||||
|
||||
render (): React$Node {
|
||||
const { address, className, count, offset, style } = this.props;
|
||||
const { hexSeed } = this.state;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['vanity--Match', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='vanity--Match-item'>
|
||||
<IdentityIcon
|
||||
className='vanity--Match-icon'
|
||||
size={48}
|
||||
value={address}
|
||||
/>
|
||||
<div className='vanity--Match-data'>
|
||||
<div className='vanity--Match-addr'>
|
||||
<span className='no'>{address.slice(0, offset)}</span><span className='yes'>{address.slice(offset, count + offset)}</span><span className='no'>{address.slice(count + offset)}</span>
|
||||
</div>
|
||||
<div className='vanity--Match-seed'>
|
||||
{hexSeed}
|
||||
</div>
|
||||
</div>
|
||||
<div className='vanity--Match-seed'>
|
||||
{hexSeed}
|
||||
</div>
|
||||
</div>
|
||||
<div className='vanity--Match-buttons'>
|
||||
<CopyToClipboard text={hexSeed}>
|
||||
<div className='vanity--Match-buttons'>
|
||||
<CopyButton value={hexSeed} />
|
||||
<Button
|
||||
icon='copy'
|
||||
primary
|
||||
icon='close'
|
||||
negative
|
||||
onClick={this.onRemove}
|
||||
size='tiny'
|
||||
/>
|
||||
</CopyToClipboard>
|
||||
<Button
|
||||
icon='close'
|
||||
negative
|
||||
onClick={_onRemove}
|
||||
size='tiny'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
onRemove = (): void => {
|
||||
const { address, onRemove } = this.props;
|
||||
|
||||
onRemove(address);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,16 +3,17 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
import type { Generator$Matches, Generator$Result } from './generator/types';
|
||||
|
||||
import './index.css';
|
||||
|
||||
import React from 'react';
|
||||
import Button from 'semantic-ui-react/dist/es/elements/Button';
|
||||
import Input from 'semantic-ui-react/dist/es/elements/Input';
|
||||
import Label from 'semantic-ui-react/dist/es/elements/Label';
|
||||
import Dropdown from 'semantic-ui-react/dist/es/modules/Dropdown';
|
||||
|
||||
import Dropdown from '@polkadot/ui-app/src/Dropdown';
|
||||
import Input from '@polkadot/ui-app/src/Input';
|
||||
import Labelled from '@polkadot/ui-app/src/Labelled';
|
||||
|
||||
import Match from './Match';
|
||||
import generator from './generator';
|
||||
@ -41,25 +42,18 @@ const BOOL_OPTIONS = [
|
||||
];
|
||||
|
||||
class App extends React.PureComponent<Props, State> {
|
||||
results: Array<Generator$Result>;
|
||||
state: State;
|
||||
|
||||
constructor (props: Props) {
|
||||
super(props);
|
||||
|
||||
this.results = [];
|
||||
this.state = {
|
||||
elapsed: 0,
|
||||
isMatchValid: true,
|
||||
isRunning: false,
|
||||
keyCount: 0,
|
||||
keyTime: 0,
|
||||
match: DEFAULT_MATCH,
|
||||
matches: [],
|
||||
startAt: 0,
|
||||
withCase: true
|
||||
};
|
||||
}
|
||||
results: Array<Generator$Result> = [];
|
||||
state: State = {
|
||||
elapsed: 0,
|
||||
isMatchValid: true,
|
||||
isRunning: false,
|
||||
keyCount: 0,
|
||||
keyTime: 0,
|
||||
match: DEFAULT_MATCH,
|
||||
matches: [],
|
||||
startAt: 0,
|
||||
withCase: true
|
||||
};
|
||||
|
||||
render (): React$Node {
|
||||
const { className, style, t } = this.props;
|
||||
@ -71,38 +65,37 @@ class App extends React.PureComponent<Props, State> {
|
||||
style={style}
|
||||
>
|
||||
<div className='ui--row'>
|
||||
<div className='medium'>
|
||||
<Label>{t('vanity.matching', {
|
||||
<Input
|
||||
className='medium'
|
||||
isDisable={isRunning}
|
||||
isError={!isMatchValid}
|
||||
label={t('vanity.matching', {
|
||||
defaultValue: 'generate address containing (? wildcard)'
|
||||
})}</Label>
|
||||
<Input
|
||||
disabled={isRunning}
|
||||
error={!isMatchValid}
|
||||
onChange={this.onChangeMatch}
|
||||
value={match}
|
||||
/>
|
||||
</div>
|
||||
<div className='small'>
|
||||
<Label>{t('vanity.case', {
|
||||
})}
|
||||
onChange={this.onChangeMatch}
|
||||
value={match}
|
||||
/>
|
||||
<Dropdown
|
||||
className='small'
|
||||
label={t('vanity.case', {
|
||||
defaultValue: 'case sensitive match'
|
||||
})}</Label>
|
||||
<Dropdown
|
||||
selection
|
||||
options={BOOL_OPTIONS}
|
||||
onChange={this.onChangeCase}
|
||||
value={withCase}
|
||||
/>
|
||||
</div>
|
||||
<div className='small'>
|
||||
<Label>{t('vanity.offset', {
|
||||
})}
|
||||
options={BOOL_OPTIONS}
|
||||
onChange={this.onChangeCase}
|
||||
value={withCase}
|
||||
/>
|
||||
<Labelled
|
||||
className='small'
|
||||
label={t('vanity.offset', {
|
||||
defaultValue: 'exact offset'
|
||||
})}</Label>
|
||||
})}
|
||||
>
|
||||
<div className='ui dropdown selection disabled'>
|
||||
{t('vanity.offset.off', {
|
||||
defaultValue: 'No'
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</Labelled>
|
||||
</div>
|
||||
<div className='ui--row-buttons'>
|
||||
<Button
|
||||
@ -205,21 +198,17 @@ class App extends React.PureComponent<Props, State> {
|
||||
}, 0);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
onChangeCase = (event: SyntheticEvent<*>, { value }): void => {
|
||||
this.setState({
|
||||
withCase: value
|
||||
});
|
||||
onChangeCase = (withCase: boolean): void => {
|
||||
this.setState({ withCase });
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
onChangeMatch = (event: SyntheticEvent<*>, { value }): void => {
|
||||
onChangeMatch = (match: string): void => {
|
||||
this.setState({
|
||||
isMatchValid:
|
||||
matchRegex.test(value) &&
|
||||
(value.length !== 0) &&
|
||||
(value.length < 31),
|
||||
match: value
|
||||
matchRegex.test(match) &&
|
||||
(match.length !== 0) &&
|
||||
(match.length < 31),
|
||||
match
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/apps",
|
||||
"version": "0.3.4",
|
||||
"version": "0.4.0",
|
||||
"description": "An Apps portal into the Polkadot network",
|
||||
"main": "index.js",
|
||||
"homepage": ".",
|
||||
@ -14,12 +14,12 @@
|
||||
"test": "react-scripts test --env=jsdom --coverage"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@polkadot/app-accounts": "^0.3.4",
|
||||
"@polkadot/app-addresses": "^0.3.4",
|
||||
"@polkadot/app-explorer": "^0.3.4",
|
||||
"@polkadot/app-extrinsics": "^0.3.4",
|
||||
"@polkadot/app-storage": "^0.3.4",
|
||||
"@polkadot/ui-react-app": "^0.3.4",
|
||||
"@polkadot/app-accounts": "^0.4.0",
|
||||
"@polkadot/app-addresses": "^0.4.0",
|
||||
"@polkadot/app-explorer": "^0.4.0",
|
||||
"@polkadot/app-extrinsics": "^0.4.0",
|
||||
"@polkadot/app-storage": "^0.4.0",
|
||||
"@polkadot/ui-app": "^0.4.0",
|
||||
"react-remarkable": "^1.1.3"
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
|
||||
import './App.css';
|
||||
|
||||
|
||||
@ -3,11 +3,12 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
|
||||
import './Connecting.css';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import withApiCall from '@polkadot/ui-react-rx/with/apiCall';
|
||||
|
||||
import translate from '../translate';
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
// @flow
|
||||
|
||||
import type { Location } from 'react-router-dom';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
|
||||
import './Content.css';
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
|
||||
import './NotFound.css';
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
import type { Route } from '../types';
|
||||
|
||||
import './Item.css';
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { I18nProps } from '@polkadot/ui-app/types';
|
||||
|
||||
import './SideBar.css';
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import createApp from '@polkadot/ui-react-app/src';
|
||||
import createApp from '@polkadot/ui-app/src';
|
||||
|
||||
import App from './App';
|
||||
import NotFound from './NotFound';
|
||||
|
||||
1
packages/ui-app/README.md
Normal file
1
packages/ui-app/README.md
Normal file
@ -0,0 +1 @@
|
||||
# @polkadot/ui-app
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/ui-react-app",
|
||||
"version": "0.3.4",
|
||||
"name": "@polkadot/ui-app",
|
||||
"version": "0.4.0",
|
||||
"main": "index.js",
|
||||
"repository": "https://github.com/polkadot-js/apps.git",
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
@ -13,7 +13,7 @@
|
||||
"dependencies": {
|
||||
"@polkadot/extrinsics-substrate": "^0.12.9",
|
||||
"@polkadot/storage-substrate": "^0.12.9",
|
||||
"@polkadot/ui-keyring": "^0.3.4",
|
||||
"@polkadot/ui-keyring": "^0.4.0",
|
||||
"@polkadot/ui-react": "^0.11.3",
|
||||
"@polkadot/ui-react-rx": "^0.11.3",
|
||||
"@polkadot/util": "^0.19.6",
|
||||
@ -21,6 +21,7 @@
|
||||
"i18next-browser-languagedetector": "^2.2.0",
|
||||
"i18next-xhr-backend": "^1.5.1",
|
||||
"react": "^16.3.1",
|
||||
"react-copy-to-clipboard": "^5.0.1",
|
||||
"react-dom": "^16.3.1",
|
||||
"react-i18next": "^7.5.1",
|
||||
"react-router-dom": "^4.2.2",
|
||||
28
packages/ui-app/src/CopyButton.js
Normal file
28
packages/ui-app/src/CopyButton.js
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BareProps } from './types';
|
||||
|
||||
import React from 'react';
|
||||
import CopyToClipboard from 'react-copy-to-clipboard';
|
||||
import Button from 'semantic-ui-react/dist/es/elements/Button';
|
||||
|
||||
type Props = BareProps & {
|
||||
value?: string
|
||||
}
|
||||
|
||||
export default function CopyButton ({ className, style, value }: Props): React$Node {
|
||||
return (
|
||||
<CopyToClipboard text={value}>
|
||||
<Button
|
||||
className={className}
|
||||
icon='copy'
|
||||
primary
|
||||
size='tiny'
|
||||
style={style}
|
||||
/>
|
||||
</CopyToClipboard>
|
||||
);
|
||||
}
|
||||
66
packages/ui-app/src/Dropdown.js
Normal file
66
packages/ui-app/src/Dropdown.js
Normal file
@ -0,0 +1,66 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BareProps } from './types';
|
||||
|
||||
import React from 'react';
|
||||
import SUIDropdown from 'semantic-ui-react/dist/es/modules/Dropdown';
|
||||
|
||||
import Labelled from './Labelled';
|
||||
|
||||
type Props = BareProps & {
|
||||
defaultValue?: mixed,
|
||||
isError?: boolean,
|
||||
label?: string,
|
||||
// flowlint-next-line unclear-type:off
|
||||
onChange: (value: any) => void,
|
||||
// flowlint-next-line unclear-type:off
|
||||
transform?: (value: any) => any
|
||||
};
|
||||
|
||||
type SUIEvent = {
|
||||
// flowlint-next-line unclear-type:off
|
||||
value: any
|
||||
};
|
||||
|
||||
export default class Dropdown extends React.PureComponent<Props> {
|
||||
render (): React$Node {
|
||||
const { className, isError, label, style } = this.props;
|
||||
const _props = {...this.props};
|
||||
|
||||
delete _props.className;
|
||||
delete _props.isError;
|
||||
delete _props.label;
|
||||
delete _props.onChange;
|
||||
delete _props.style;
|
||||
delete _props.transform;
|
||||
|
||||
return (
|
||||
<Labelled
|
||||
className={['ui--Dropdown', className].join(' ')}
|
||||
label={label}
|
||||
style={style}
|
||||
>
|
||||
<SUIDropdown
|
||||
key='dropdown'
|
||||
selection
|
||||
{..._props}
|
||||
error={isError}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
</Labelled>
|
||||
);
|
||||
}
|
||||
|
||||
onChange = (event: SyntheticEvent<*>, { value }: SUIEvent): void => {
|
||||
const { onChange, transform } = this.props;
|
||||
|
||||
onChange(
|
||||
transform
|
||||
? transform(value)
|
||||
: value
|
||||
);
|
||||
}
|
||||
}
|
||||
69
packages/ui-app/src/Input.js
Normal file
69
packages/ui-app/src/Input.js
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BareProps } from './types';
|
||||
|
||||
import React from 'react';
|
||||
import SUIInput from 'semantic-ui-react/dist/es/elements/Input';
|
||||
|
||||
import Labelled from './Labelled';
|
||||
|
||||
type Props = BareProps & {
|
||||
children?: React$Node,
|
||||
defaultValue?: mixed,
|
||||
isAction?: boolean,
|
||||
isDisabled?: boolean,
|
||||
isError?: boolean,
|
||||
label?: string,
|
||||
max?: mixed,
|
||||
min?: mixed,
|
||||
name?: string,
|
||||
// flowlint-next-line unclear-type:off
|
||||
onChange: (value: any) => void,
|
||||
placeholder?: string,
|
||||
type?: string,
|
||||
value?: mixed
|
||||
};
|
||||
|
||||
type SUIEvent = {
|
||||
// flowlint-next-line unclear-type:off
|
||||
value: any
|
||||
};
|
||||
|
||||
export default class Input extends React.PureComponent<Props> {
|
||||
render (): React$Node {
|
||||
const { children, className, defaultValue, isAction = false, isDisabled = false, isError = false, label, max, min, name, placeholder, style, type = 'text', value } = this.props;
|
||||
|
||||
return (
|
||||
<Labelled
|
||||
className={className}
|
||||
label={label}
|
||||
style={style}
|
||||
>
|
||||
<SUIInput
|
||||
action={isAction}
|
||||
defaultValue={defaultValue}
|
||||
disabled={isDisabled}
|
||||
error={isError}
|
||||
max={max}
|
||||
min={min}
|
||||
name={name}
|
||||
onChange={this.onChange}
|
||||
placeholder={placeholder}
|
||||
type={type}
|
||||
value={value}
|
||||
>
|
||||
<input />
|
||||
{children}
|
||||
</SUIInput>
|
||||
</Labelled>
|
||||
);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-var
|
||||
onChange = (event: SyntheticEvent<*>, { value }: SUIEvent): void => {
|
||||
this.props.onChange(value);
|
||||
}
|
||||
}
|
||||
20
packages/ui-app/src/InputAddress/addressToAddress.js
Normal file
20
packages/ui-app/src/InputAddress/addressToAddress.js
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import addressDecode from '@polkadot/util-keyring/address/decode';
|
||||
import addressEncode from '@polkadot/util-keyring/address/encode';
|
||||
|
||||
export default function addressToAddress (value?: string | Uint8Array): ?string {
|
||||
// flowlint-next-line sketchy-null-string:off
|
||||
if (value) {
|
||||
try {
|
||||
return addressEncode(
|
||||
addressDecode(value)
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Unable to encode address', value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -9,26 +9,32 @@ import type { BareProps } from '../types';
|
||||
import './InputAddress.css';
|
||||
|
||||
import React from 'react';
|
||||
import keyring from '@polkadot/ui-keyring/src';
|
||||
import addressDecode from '@polkadot/util-keyring/address/decode';
|
||||
import addressEncode from '@polkadot/util-keyring/address/encode';
|
||||
|
||||
import RxDropdown from '../RxDropdown';
|
||||
import keyring from '@polkadot/ui-keyring/src';
|
||||
import createOptionHeader from '@polkadot/ui-keyring/src/options/header';
|
||||
import addressDecode from '@polkadot/util-keyring/address/decode';
|
||||
|
||||
import Dropdown from '../Dropdown';
|
||||
import addressToAddress from './addressToAddress';
|
||||
|
||||
type Props = BareProps & {
|
||||
defaultValue?: Uint8Array,
|
||||
defaultValue?: string | Uint8Array,
|
||||
hideAddress?: boolean;
|
||||
isError?: boolean,
|
||||
isInput?: boolean,
|
||||
label?: string,
|
||||
onChange: (value: Uint8Array) => void,
|
||||
type?: KeyringOption$Type
|
||||
type?: KeyringOption$Type,
|
||||
value?: string | Uint8Array
|
||||
};
|
||||
|
||||
type State = {
|
||||
defaultValue?: string;
|
||||
defaultValue: ?string;
|
||||
value: ?string;
|
||||
}
|
||||
|
||||
const RECENT_KEY = 'header-recent';
|
||||
|
||||
const transform = (value: string): Uint8Array => {
|
||||
try {
|
||||
return addressDecode(value);
|
||||
@ -42,28 +48,25 @@ export default class InputAddress extends React.Component<Props, State> {
|
||||
constructor (props: Props) {
|
||||
super(props);
|
||||
|
||||
let defaultValue;
|
||||
|
||||
if (props.defaultValue) {
|
||||
try {
|
||||
defaultValue = addressEncode(props.defaultValue);
|
||||
} catch (error) {
|
||||
console.error('Unable to encode defaultValue address', props.defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
this.state = {
|
||||
defaultValue
|
||||
defaultValue: addressToAddress(props.defaultValue),
|
||||
value: addressToAddress(props.value)
|
||||
};
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps ({ value }: Props): $Shape<State> {
|
||||
return {
|
||||
value: addressToAddress(value)
|
||||
};
|
||||
}
|
||||
|
||||
render (): React$Node {
|
||||
const { className, hideAddress = false, isError, label, onChange, style, type = 'all' } = this.props;
|
||||
const { defaultValue } = this.state;
|
||||
const { defaultValue, value } = this.state;
|
||||
const options = keyring.getOptions(type);
|
||||
|
||||
return (
|
||||
<RxDropdown
|
||||
<Dropdown
|
||||
className={['ui--InputAddress', hideAddress ? 'flag--hideAddress' : '', className].join(' ')}
|
||||
defaultValue={defaultValue}
|
||||
isError={isError}
|
||||
@ -73,6 +76,7 @@ export default class InputAddress extends React.Component<Props, State> {
|
||||
search={this.onSearch}
|
||||
style={style}
|
||||
transform={transform}
|
||||
value={value}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -81,9 +85,8 @@ export default class InputAddress extends React.Component<Props, State> {
|
||||
const { isInput = true } = this.props;
|
||||
const queryLower = query.toLowerCase();
|
||||
const matches = filteredOptions.filter((item) => {
|
||||
// flowlint-next-line sketchy-null-string:off
|
||||
if (!item.key) {
|
||||
return false;
|
||||
if (!item.value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const { name, value } = item;
|
||||
@ -93,17 +96,32 @@ export default class InputAddress extends React.Component<Props, State> {
|
||||
return hasMatch;
|
||||
});
|
||||
|
||||
// see if we should add a new item, i.e. valid address found
|
||||
if (isInput && matches.length === 0) {
|
||||
const valueMatches = matches.filter((item) => item.value);
|
||||
|
||||
// see if we should add a new item, i.e. no valid address found
|
||||
if (isInput && valueMatches.length === 0) {
|
||||
const publicKey = transform(query);
|
||||
|
||||
if (publicKey.length === 32) {
|
||||
if (!matches.find((item) => item.key === RECENT_KEY)) {
|
||||
matches.push(
|
||||
createOptionHeader('Recent')
|
||||
);
|
||||
}
|
||||
|
||||
matches.push(
|
||||
keyring.saveRecent(query)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
return matches.filter((item, index) => {
|
||||
// it is a value entry or header followed by a value entry
|
||||
if (item.value || (index !== matches.length - 1 && matches[index + 1].value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
};
|
||||
}
|
||||
@ -2,11 +2,11 @@
|
||||
/* This software may be modified and distributed under the terms
|
||||
/* of the ISC license. See the LICENSE file for details. */
|
||||
|
||||
.ui--RxDropdownLinked {}
|
||||
.ui--DropdownLinked {}
|
||||
|
||||
.ui--RxDropdownLinked-Items {}
|
||||
.ui--DropdownLinked-Items {}
|
||||
|
||||
.ui--RxDropdownLinked-Items .text {
|
||||
.ui--DropdownLinked-Items .text {
|
||||
box-sizing: border-box;
|
||||
display: flex !important;
|
||||
flex-wrap: nowrap;
|
||||
@ -16,16 +16,16 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.ui--RxDropdownLinked-Item > .text {
|
||||
.ui--DropdownLinked-Item > .text {
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.ui--RxDropdownLinked-Item-text,
|
||||
.ui--RxDropdownLinked-Item-call {
|
||||
.ui--DropdownLinked-Item-text,
|
||||
.ui--DropdownLinked-Item-call {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.ui--RxDropdownLinked-Item-call {
|
||||
.ui--DropdownLinked-Item-call {
|
||||
flex: 1;
|
||||
font-family: monospace;
|
||||
margin-left: 1rem;
|
||||
@ -35,8 +35,8 @@
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.ui--RxDropdownLinked-Item-text {
|
||||
.ui--DropdownLinked-Item-text {
|
||||
flex: 1 0;
|
||||
}
|
||||
|
||||
.ui--RxDropdownLinked-Sections {}
|
||||
.ui--DropdownLinked-Sections {}
|
||||
@ -7,9 +7,10 @@ import type { Extrinsic } from '@polkadot/extrinsics/types';
|
||||
import type { I18nProps } from '../types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import extrinsics from '@polkadot/extrinsics-substrate';
|
||||
|
||||
import RxDropdown from '../RxDropdown';
|
||||
import Dropdown from '../Dropdown';
|
||||
import translate from '../translate';
|
||||
import createOptions from './options/method';
|
||||
|
||||
@ -33,8 +34,8 @@ function SelectMethod ({ className, isError, label = '', onChange, style, t, typ
|
||||
const options = createOptions(section, type);
|
||||
|
||||
return (
|
||||
<RxDropdown
|
||||
className={['ui--RxDropdownLinked-Items', className].join(' ')}
|
||||
<Dropdown
|
||||
className={['ui--DropdownLinked-Items', className].join(' ')}
|
||||
isError={isError}
|
||||
label={label || t('input.extrinsic.method', {
|
||||
defaultValue: 'with the extrinsic'
|
||||
@ -8,7 +8,7 @@ import type { I18nProps } from '../types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import RxDropdown from '../RxDropdown';
|
||||
import Dropdown from '../Dropdown';
|
||||
import translate from '../translate';
|
||||
import createOptions from './options/section';
|
||||
|
||||
@ -25,8 +25,8 @@ function SelectSection ({ className, defaultValue, isError, label = '', onChange
|
||||
const options = createOptions(type);
|
||||
|
||||
return (
|
||||
<RxDropdown
|
||||
className={['ui--RxDropdownLinked-Sections', className].join(' ')}
|
||||
<Dropdown
|
||||
className={['ui--DropdownLinked-Sections', className].join(' ')}
|
||||
defaultValue={defaultValue}
|
||||
isError={isError}
|
||||
label={label || t('input.extrinsic.section', {
|
||||
@ -49,25 +49,23 @@ class InputExtrinsic extends React.PureComponent<Props, State> {
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['ui--RxDropdownLinked', 'ui--row', className].join(' ')}
|
||||
className={['ui--DropdownLinked', 'ui--row', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='small'>
|
||||
<SelectSection
|
||||
label={labelSection}
|
||||
onChange={this.onSectionChange}
|
||||
type={type}
|
||||
value={value}
|
||||
/>
|
||||
</div>
|
||||
<div className='large'>
|
||||
<SelectMethod
|
||||
label={labelMethod}
|
||||
onChange={this.onKeyChange}
|
||||
value={value}
|
||||
type={type}
|
||||
/>
|
||||
</div>
|
||||
<SelectSection
|
||||
className='small'
|
||||
label={labelSection}
|
||||
onChange={this.onSectionChange}
|
||||
type={type}
|
||||
value={value}
|
||||
/>
|
||||
<SelectMethod
|
||||
className='large'
|
||||
label={labelMethod}
|
||||
onChange={this.onKeyChange}
|
||||
value={value}
|
||||
type={type}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -6,6 +6,7 @@
|
||||
import type { ExtrinsicSectionName } from '@polkadot/extrinsics/types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import map from '@polkadot/extrinsics-substrate';
|
||||
|
||||
// flowlint-next-line unclear-type:off
|
||||
@ -26,17 +27,17 @@ export default function createOptions (sectionName: any, type: 'private' | 'publ
|
||||
const inputs = Object.keys(params).join(', ');
|
||||
|
||||
return {
|
||||
className: 'ui--RxDropdownLinked-Item',
|
||||
className: 'ui--DropdownLinked-Item',
|
||||
key: `${sectionName}_${name}`,
|
||||
text: [
|
||||
<div
|
||||
className='ui--RxDropdownLinked-Item-text'
|
||||
className='ui--DropdownLinked-Item-text'
|
||||
key={`${sectionName}_${name}:text`}
|
||||
>
|
||||
{description || name}
|
||||
</div>,
|
||||
<div
|
||||
className='ui--RxDropdownLinked-Item-call'
|
||||
className='ui--DropdownLinked-Item-call'
|
||||
key={`${sectionName}_${name}:call`}
|
||||
>
|
||||
{name}({inputs})
|
||||
@ -7,9 +7,10 @@ import type { StorageDef$Key } from '@polkadot/storage/types';
|
||||
import type { I18nProps } from '../types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import map from '@polkadot/storage-substrate/keys';
|
||||
|
||||
import RxDropdown from '../RxDropdown';
|
||||
import Dropdown from '../Dropdown';
|
||||
import translate from '../translate';
|
||||
import createOptions from './options/key';
|
||||
|
||||
@ -32,8 +33,8 @@ function SelectKey ({ className, isError, label = '', onChange, style, t, value:
|
||||
const options = createOptions(section);
|
||||
|
||||
return (
|
||||
<RxDropdown
|
||||
className={['ui--RxDropdownLinked-Items', className].join(' ')}
|
||||
<Dropdown
|
||||
className={['ui--DropdownLinked-Items', className].join(' ')}
|
||||
isError={isError}
|
||||
label={label || t('input.storage.key', {
|
||||
defaultValue: 'with storage key'
|
||||
@ -8,7 +8,7 @@ import type { I18nProps } from '../types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import RxDropdown from '../RxDropdown';
|
||||
import Dropdown from '../Dropdown';
|
||||
import translate from '../translate';
|
||||
import createOptions from './options/section';
|
||||
|
||||
@ -24,8 +24,8 @@ const options = createOptions();
|
||||
|
||||
function SelectSection ({ className, defaultValue, isError, label, onChange, style, t, value: { section } }: Props): React$Node {
|
||||
return (
|
||||
<RxDropdown
|
||||
className={['ui--RxDropdownLinked-Sections', className].join(' ')}
|
||||
<Dropdown
|
||||
className={['ui--DropdownLinked-Sections', className].join(' ')}
|
||||
defaultValue={defaultValue}
|
||||
isError={isError}
|
||||
label={label || t('input.storage.section', {
|
||||
@ -47,23 +47,21 @@ class InputStorage extends React.PureComponent<Props, State> {
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['ui--RxDropdownLinked', 'ui--row', className].join(' ')}
|
||||
className={['ui--DropdownLinked', 'ui--row', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='small'>
|
||||
<SelectSection
|
||||
label={labelSection}
|
||||
onChange={this.onSectionChange}
|
||||
value={value}
|
||||
/>
|
||||
</div>
|
||||
<div className='large'>
|
||||
<SelectKey
|
||||
label={labelMethod}
|
||||
onChange={this.onKeyChange}
|
||||
value={value}
|
||||
/>
|
||||
</div>
|
||||
<SelectSection
|
||||
className='small'
|
||||
label={labelSection}
|
||||
onChange={this.onSectionChange}
|
||||
value={value}
|
||||
/>
|
||||
<SelectKey
|
||||
className='large'
|
||||
label={labelMethod}
|
||||
onChange={this.onKeyChange}
|
||||
value={value}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -6,6 +6,7 @@
|
||||
import type { StateDb$SectionNames } from '@polkadot/storage/types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import map from '@polkadot/storage-substrate/keys';
|
||||
|
||||
// flowlint-next-line unclear-type:off
|
||||
@ -29,17 +30,17 @@ export default function createOptions (sectionName: any): Array<*> {
|
||||
const inputs = Object.keys(params).join(', ');
|
||||
|
||||
return {
|
||||
className: 'ui--RxDropdownLinked-Item',
|
||||
className: 'ui--DropdownLinked-Item',
|
||||
key: `${sectionName}_${name}`,
|
||||
text: [
|
||||
<div
|
||||
className='ui--RxDropdownLinked-Item-text'
|
||||
className='ui--DropdownLinked-Item-text'
|
||||
key={`${sectionName}_${name}:text`}
|
||||
>
|
||||
{description || name}
|
||||
</div>,
|
||||
<div
|
||||
className='ui--RxDropdownLinked-Item-call'
|
||||
className='ui--DropdownLinked-Item-call'
|
||||
key={`${sectionName}_${name}:call`}
|
||||
>
|
||||
{name}({inputs})
|
||||
32
packages/ui-app/src/Labelled.js
Normal file
32
packages/ui-app/src/Labelled.js
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BareProps } from './types';
|
||||
|
||||
import React from 'react';
|
||||
import Label from 'semantic-ui-react/dist/es/elements/Label';
|
||||
|
||||
type Props = BareProps & {
|
||||
label?: React$Node,
|
||||
children: React$Node
|
||||
};
|
||||
|
||||
export default function Labelled ({ className, children, label, style }: Props): React$Node {
|
||||
console.log('label', label);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
<Label>{
|
||||
typeof label === 'undefined'
|
||||
? <div> </div>
|
||||
: label
|
||||
}</Label>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
46
packages/ui-app/src/Params/Param/Account.js
Normal file
46
packages/ui-app/src/Params/Param/Account.js
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { Props } from '../types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import InputAddress from '../../InputAddress';
|
||||
import Bare from './Bare';
|
||||
|
||||
export default class Account extends React.PureComponent<Props> {
|
||||
render (): React$Node {
|
||||
const { className, isError, label, style, value: { options: { initValue } = {} } } = this.props;
|
||||
|
||||
// flowlint-next-line unclear-type:off
|
||||
const defaultValue = ((initValue: any): Uint8Array);
|
||||
|
||||
return (
|
||||
<Bare
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
<InputAddress
|
||||
className='large'
|
||||
defaultValue={defaultValue}
|
||||
isError={isError}
|
||||
isInput
|
||||
label={label}
|
||||
onChange={this.onChange}
|
||||
placeholder='5...'
|
||||
/>
|
||||
</Bare>
|
||||
);
|
||||
}
|
||||
|
||||
onChange = (value?: Uint8Array): void => {
|
||||
const { index, onChange } = this.props;
|
||||
|
||||
onChange(index, {
|
||||
isValid: !!value && value.length === 32,
|
||||
value
|
||||
});
|
||||
}
|
||||
}
|
||||
46
packages/ui-app/src/Params/Param/Amount.js
Normal file
46
packages/ui-app/src/Params/Param/Amount.js
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
// flowlint sketchy-null-mixed:off,sketchy-null-number:off
|
||||
|
||||
import type { Props } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import React from 'react';
|
||||
|
||||
import Input from '../../Input';
|
||||
import Bare from './Bare';
|
||||
|
||||
export default class Amount extends React.PureComponent<Props> {
|
||||
render (): React$Node {
|
||||
const { className, isError, label, style, value: { options: { initValue = 0, maxValue, minValue = 0 } = {} } } = this.props;
|
||||
|
||||
return (
|
||||
<Bare
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
<Input
|
||||
className='small'
|
||||
defaultValue={initValue || minValue}
|
||||
isError={isError}
|
||||
label={label}
|
||||
max={maxValue}
|
||||
min={minValue}
|
||||
onChange={this.onChange}
|
||||
type='number'
|
||||
/>
|
||||
</Bare>
|
||||
);
|
||||
}
|
||||
|
||||
onChange = (value: number): void => {
|
||||
const { index, onChange, value: { options: { minValue = 0 } = {} } } = this.props;
|
||||
|
||||
onChange(index, {
|
||||
isValid: true,
|
||||
value: new BN(value || minValue || 0)
|
||||
});
|
||||
}
|
||||
}
|
||||
23
packages/ui-app/src/Params/Param/Bare.js
Normal file
23
packages/ui-app/src/Params/Param/Bare.js
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BareProps } from '../../types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
type Props = BareProps & {
|
||||
children: React$Node
|
||||
};
|
||||
|
||||
export default function Bare ({ children, className, style }: Props): React$Node {
|
||||
return (
|
||||
<div
|
||||
className={['ui--row', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -7,7 +7,9 @@ import type { BareProps } from '../../types';
|
||||
import type { Size } from '../types';
|
||||
|
||||
import React from 'react';
|
||||
import Label from 'semantic-ui-react/dist/es/elements/Label';
|
||||
|
||||
import Labelled from '../../Labelled';
|
||||
import Bare from './Bare';
|
||||
|
||||
type Props = BareProps & {
|
||||
children: React$Node,
|
||||
@ -17,14 +19,16 @@ type Props = BareProps & {
|
||||
|
||||
export default function Base ({ children, className, label, size = 'medium', style }: Props): React$Node {
|
||||
return (
|
||||
<div
|
||||
className={['ui--row', className].join(' ')}
|
||||
<Bare
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
<div className={size}>
|
||||
<Label>{label}</Label>
|
||||
<Labelled
|
||||
className={size}
|
||||
label={label}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</Labelled>
|
||||
</Bare>
|
||||
);
|
||||
}
|
||||
47
packages/ui-app/src/Params/Param/Bool.js
Normal file
47
packages/ui-app/src/Params/Param/Bool.js
Normal file
@ -0,0 +1,47 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { Props } from '../types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import Dropdown from '../../Dropdown';
|
||||
import Bare from './Bare';
|
||||
|
||||
const options = [
|
||||
{ text: 'No', value: false },
|
||||
{ text: 'Yes', value: true }
|
||||
];
|
||||
|
||||
export default class Bool extends React.PureComponent<Props> {
|
||||
render (): React$Node {
|
||||
const { className, isError, label, style, value: { options: { initValue = false } = {} } } = this.props;
|
||||
|
||||
return (
|
||||
<Bare
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
<Dropdown
|
||||
className='small'
|
||||
isError={isError}
|
||||
defaultValue={initValue}
|
||||
label={label}
|
||||
options={options}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
</Bare>
|
||||
);
|
||||
}
|
||||
|
||||
onChange = (value: boolean): void => {
|
||||
const { index, onChange } = this.props;
|
||||
|
||||
onChange(index, {
|
||||
isValid: true,
|
||||
value
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -6,10 +6,11 @@
|
||||
import type { Props as BaseProps, Size } from '../types';
|
||||
|
||||
import React from 'react';
|
||||
import Input from 'semantic-ui-react/dist/es/elements/Input';
|
||||
|
||||
import hexToU8a from '@polkadot/util/hex/toU8a';
|
||||
|
||||
import Base from './Base';
|
||||
import Input from '../../Input';
|
||||
import Bare from './Bare';
|
||||
|
||||
type Props = BaseProps & {
|
||||
length?: number,
|
||||
@ -20,13 +21,34 @@ type Props = BaseProps & {
|
||||
const defaultValidate = (u8a: Uint8Array): boolean =>
|
||||
true;
|
||||
|
||||
export default function Bytes ({ index, isError, length = -1, label, onChange, size = 'full', validate = defaultValidate }: Props): React$Node {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const _onChange = (event: SyntheticEvent<*>, { value }) => {
|
||||
export default class Bytes extends React.PureComponent<Props> {
|
||||
render (): React$Node {
|
||||
const { className, isError, label, size = 'full', style } = this.props;
|
||||
|
||||
return (
|
||||
<Bare
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
<Input
|
||||
className={size}
|
||||
isError={isError}
|
||||
label={label}
|
||||
onChange={this.onChange}
|
||||
placeholder='0x...'
|
||||
type='text'
|
||||
/>
|
||||
</Bare>
|
||||
);
|
||||
}
|
||||
|
||||
onChange = (hex: string): void => {
|
||||
const { index, length = -1, onChange, validate = defaultValidate } = this.props;
|
||||
|
||||
let u8a;
|
||||
|
||||
try {
|
||||
u8a = hexToU8a(value);
|
||||
u8a = hexToU8a(hex);
|
||||
} catch (error) {
|
||||
u8a = new Uint8Array([]);
|
||||
}
|
||||
@ -40,18 +62,4 @@ export default function Bytes ({ index, isError, length = -1, label, onChange, s
|
||||
value: u8a
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Base
|
||||
label={label}
|
||||
size={size}
|
||||
>
|
||||
<Input
|
||||
error={isError}
|
||||
onChange={_onChange}
|
||||
placeholder='0x...'
|
||||
type='text'
|
||||
/>
|
||||
</Base>
|
||||
);
|
||||
}
|
||||
@ -3,7 +3,7 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BareProps } from '@polkadot/ui-react-app/types';
|
||||
import type { BareProps } from '@polkadot/ui-app/types';
|
||||
|
||||
import React from 'react';
|
||||
import Dropzone from 'react-dropzone';
|
||||
@ -26,13 +26,7 @@ type State = {
|
||||
};
|
||||
|
||||
class BytesFile extends React.PureComponent<Props, State> {
|
||||
state: State;
|
||||
|
||||
constructor (props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {};
|
||||
}
|
||||
state: State = {};
|
||||
|
||||
render (): React$Node {
|
||||
const { className, isError = false, label, t } = this.props;
|
||||
49
packages/ui-app/src/Params/Param/VoteThreshold.js
Normal file
49
packages/ui-app/src/Params/Param/VoteThreshold.js
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
// flowlint sketchy-null-mixed:off
|
||||
|
||||
import type { Props } from '../types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import Dropdown from '../../Dropdown';
|
||||
import Bare from './Bare';
|
||||
|
||||
const options = [
|
||||
{ text: 'Super majority approval', value: 0 },
|
||||
{ text: 'Super majority rejection', value: 1 },
|
||||
{ text: 'Simple majority', value: 2 }
|
||||
];
|
||||
|
||||
export default class VoteThreshold extends React.PureComponent<Props> {
|
||||
render (): React$Node {
|
||||
const { className, label, style, value: { options: { initValue = 0 } = {} } } = this.props;
|
||||
const defaultValue = initValue || 0;
|
||||
|
||||
return (
|
||||
<Bare
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
<Dropdown
|
||||
className='small'
|
||||
defaultValue={defaultValue}
|
||||
label={label}
|
||||
options={options}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
</Bare>
|
||||
);
|
||||
}
|
||||
|
||||
onChange = (value: number): void => {
|
||||
const { index, onChange } = this.props;
|
||||
|
||||
onChange(index, {
|
||||
isValid: true,
|
||||
value
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -6,24 +6,34 @@
|
||||
import type { Props } from '../types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import bnToU8a from '@polkadot/util/bn/toU8a';
|
||||
import u8aConcat from '@polkadot/util/u8a/concat';
|
||||
|
||||
import BytesFile from './File';
|
||||
|
||||
export default function Wasm ({ index, isError, label, onChange }: Props): React$Node {
|
||||
export default class Wasm extends React.PureComponent<Props> {
|
||||
render (): React$Node {
|
||||
const { className, isError, label, style } = this.props;
|
||||
|
||||
return (
|
||||
<BytesFile
|
||||
className={className}
|
||||
isError={isError}
|
||||
label={label}
|
||||
onChange={this.onChange}
|
||||
style={style}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: Validate that we have actual proper WASM code
|
||||
const _onChange = (value: Uint8Array) =>
|
||||
onChange = (value: Uint8Array): void => {
|
||||
const { index, onChange } = this.props;
|
||||
|
||||
onChange(index, {
|
||||
isValid: value.length !== 0,
|
||||
value: u8aConcat(bnToU8a(value.length, 32, true), value)
|
||||
});
|
||||
|
||||
return (
|
||||
<BytesFile
|
||||
isError={isError}
|
||||
label={label}
|
||||
onChange={_onChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -22,13 +22,37 @@ type Props = I18nProps & {
|
||||
};
|
||||
};
|
||||
|
||||
function ParamComponent ({ className, index, onChange, overrides, style, value: { name, type, options = {} } = {} }: Props): React$Node {
|
||||
if (!type) {
|
||||
return null;
|
||||
type State = {
|
||||
Component: React$ComponentType<*> | Array<React$ComponentType<*>> | null
|
||||
}
|
||||
|
||||
class ParamComponent extends React.PureComponent<Props, State> {
|
||||
state: State = {
|
||||
Component: null
|
||||
};
|
||||
|
||||
static getDerivedStateFromProps ({ overrides, value: { type } = {} }: Props): State {
|
||||
return {
|
||||
Component: !type
|
||||
? null
|
||||
: findComponent(type, overrides)
|
||||
};
|
||||
}
|
||||
|
||||
const Component = findComponent(type, overrides);
|
||||
const renderComponent = (Component: React$ComponentType<*>, sub: number = -1) => {
|
||||
render (): React$Node {
|
||||
const { Component } = this.state;
|
||||
|
||||
if (!Component) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Array.isArray(Component)
|
||||
? Component.map(this.renderComponent)
|
||||
: this.renderComponent(Component);
|
||||
}
|
||||
|
||||
renderComponent = (Component: React$ComponentType<*>, sub: number = -1): React$Node => {
|
||||
const { className, index, onChange, style, value: { name, type, options = {} } = {} } = this.props;
|
||||
const _type: Param$Type = Array.isArray(type)
|
||||
? type[sub]
|
||||
: type;
|
||||
@ -39,23 +63,20 @@ function ParamComponent ({ className, index, onChange, overrides, style, value:
|
||||
|
||||
return (
|
||||
<Component
|
||||
className='ui--Param'
|
||||
className={['ui--Param', className].join(' ')}
|
||||
index={index}
|
||||
key={`${name}:${text}:${index}}`}
|
||||
label={`${name}: ${text}${labelExtra}`}
|
||||
// FIXME subjects are not for array components (as defined here)
|
||||
onChange={onChange}
|
||||
style={style}
|
||||
value={{
|
||||
options,
|
||||
type: _type
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
return Array.isArray(Component)
|
||||
? Component.map(renderComponent)
|
||||
: renderComponent(Component);
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(ParamComponent);
|
||||
@ -27,14 +27,7 @@ type State = {
|
||||
};
|
||||
|
||||
class Params extends React.PureComponent<Props, State> {
|
||||
state: State;
|
||||
|
||||
constructor (props: Props) {
|
||||
super(props);
|
||||
|
||||
// wed ont' set anything, getDerivedStateFromProps will update
|
||||
this.state = ({}: $Shape<State>);
|
||||
}
|
||||
state: State = ({}: $Shape<State>);
|
||||
|
||||
static getDerivedStateFromProps ({ item, onChange }: Props, { item: { name, section } = {} }: State): $Shape<State> | null {
|
||||
if (name === item.name && section === item.section) {
|
||||
@ -7,6 +7,7 @@
|
||||
import type { Param } from '@polkadot/primitives/param';
|
||||
|
||||
import BN from 'bn.js';
|
||||
|
||||
import isUndefined from '@polkadot/util/is/undefined';
|
||||
|
||||
export default function getInitValue ({ options: { initValue, minValue } = {}, type }: Param): mixed {
|
||||
69
packages/ui-app/src/Password.js
Normal file
69
packages/ui-app/src/Password.js
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BareProps } from './types';
|
||||
|
||||
import React from 'react';
|
||||
import Button from 'semantic-ui-react/dist/es/elements/Button';
|
||||
|
||||
import Input from './Input';
|
||||
|
||||
type Props = BareProps & {
|
||||
defaultValue?: mixed,
|
||||
children?: React$Node,
|
||||
isDisabled?: boolean,
|
||||
isError?: boolean,
|
||||
label?: string,
|
||||
name?: string,
|
||||
onChange: (value: string) => void,
|
||||
value: mixed
|
||||
};
|
||||
|
||||
type State = {
|
||||
isVisible: boolean
|
||||
}
|
||||
|
||||
export default class Password extends React.PureComponent<Props, State> {
|
||||
state: State = {
|
||||
isVisible: false
|
||||
};
|
||||
|
||||
render (): React$Node {
|
||||
const { children, className, defaultValue, isDisabled, isError, label, name, onChange, style, value } = this.props;
|
||||
const { isVisible } = this.state;
|
||||
const type = isVisible
|
||||
? 'text'
|
||||
: 'password';
|
||||
|
||||
return (
|
||||
<Input
|
||||
className={className}
|
||||
defaultValue={defaultValue}
|
||||
isAction
|
||||
isDisabled={isDisabled}
|
||||
isError={isError}
|
||||
label={label}
|
||||
name={name}
|
||||
onChange={onChange}
|
||||
style={style}
|
||||
type={type}
|
||||
value={value}
|
||||
>
|
||||
<Button
|
||||
icon='eye'
|
||||
primary
|
||||
onClick={this.onToggleVisible}
|
||||
/>
|
||||
{children}
|
||||
</Input>
|
||||
);
|
||||
}
|
||||
|
||||
onToggleVisible = (): void => {
|
||||
this.setState({
|
||||
isVisible: !this.state.isVisible
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -13,6 +13,7 @@ import './styles';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { HashRouter } from 'react-router-dom';
|
||||
|
||||
import Api from '@polkadot/ui-react-rx/Api';
|
||||
|
||||
type Props = BareProps & {
|
||||
@ -20,15 +20,29 @@
|
||||
.ui--row > div {
|
||||
box-sizing: border-box;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.ui--grid > div:not(.grow):not(.shrink),
|
||||
.ui--row > div:not(.grow):not(.shrink) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ui--grid > div,
|
||||
.ui--grid > div:not(.shrink),
|
||||
.ui--grid > div.full,
|
||||
.ui--row > div.full {
|
||||
flex: 0 100%;
|
||||
}
|
||||
|
||||
.ui--grid > div.shrink,
|
||||
.ui--row > div.shrink {
|
||||
flex: 0 1 auto;
|
||||
}
|
||||
|
||||
.ui--grid > div.grow,
|
||||
.ui--row > div.grow {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.ui--grid > div.large,
|
||||
.ui--row > div.large {
|
||||
flex: 0 75%;
|
||||
@ -65,7 +79,7 @@
|
||||
|
||||
.ui--row-buttons {
|
||||
margin: 1em 0;
|
||||
text-align: center;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.ui--row-buttons .button {
|
||||
@ -43,7 +43,7 @@
|
||||
.ui.modal > .actions {
|
||||
background: transparent;
|
||||
border-top: none;
|
||||
text-align: center;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.ui.modal > .actions .button {
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user