Add utility/toolbox app (#51)

* Upgrades

* Add & use Output component

* Render app in content

* Use update @polkadot/dev-react

* Add app-toolbox

* DRY className concat

* Hashing in place

* Verify signature operational

* Entry updates

* Verification operational

* Final cleanups before PR

* Bump version
This commit is contained in:
Jaco Greeff 2018-05-15 16:58:32 +02:00 committed by GitHub
parent e1f1ca5153
commit 5f884c4b65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
111 changed files with 1439 additions and 487 deletions

View File

@ -1,4 +1,3 @@
{ {
"extends": "@polkadot/dev/config/babel", "extends": "@polkadot/dev-react/config/babel"
"presets": ["react"]
} }

View File

@ -1,5 +1,5 @@
{ {
"extends": [ "extends": [
"./node_modules/@polkadot/dev/config/eslint.js" "./node_modules/@polkadot/dev-react/config/eslint.js"
] ]
} }

View File

@ -6,12 +6,13 @@
[libs] [libs]
node_modules/@polkadot/dev/flow-typed node_modules/@polkadot/dev/flow-typed
node_modules/@polkadot/dev-react/flow-typed
[lints] [lints]
all=warn all=warn
[options] [options]
include_warnings=true 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/app-\(accounts\|addresses\|explorer\|extrinsics\|home\|rpc\|settings\|storage\|toolbox\|vanitygen\)\(.*\)$' -> '<PROJECT_ROOT>/packages/app-\1/src\2'
module.name_mapper='^@polkadot/apps\(.*\)$' -> '<PROJECT_ROOT>/packages/apps/src\1' module.name_mapper='^@polkadot/apps\(.*\)$' -> '<PROJECT_ROOT>/packages/apps/src\1'
module.name_mapper='^@polkadot/ui-\(app\|keyring\)\(.*\)$' -> '<PROJECT_ROOT>/packages/ui-\1/src\2' module.name_mapper='^@polkadot/ui-\(app\|keyring\)\(.*\)$' -> '<PROJECT_ROOT>/packages/ui-\1/src\2'

View File

@ -1,3 +1,3 @@
{ {
"extends": "@polkadot/dev/config/stylelint" "extends": "@polkadot/dev-react/config/stylelint"
} }

View File

@ -1,5 +0,0 @@
// @flow
declare module 'i18next-browser-languagedetector' {
declare module.exports: {}
}

View File

@ -1,5 +0,0 @@
// @flow
declare module 'i18next-xhr-backend' {
declare module.exports: {}
}

23
flow-typed/i18next.js vendored
View File

@ -1,23 +0,0 @@
// @flow
declare type I18Next$Config = {
fallbackLng?: string,
ns?: Array<string>,
defaultNS?: string,
debug?: boolean,
interpolation?: {
escapeValue: boolean
},
react?: {
wait: boolean
}
};
declare module 'i18next' {
declare type I18Next = {
use: (any) => I18Next,
init: (I18Next$Config) => I18Next
};
declare module.exports: I18Next
}

View File

@ -1,5 +0,0 @@
// @flow
declare module 'react-copy-to-clipboard' {
declare module.exports: React$ComponentType<{ text?: string }>;
}

View File

@ -1,6 +0,0 @@
// @flow
declare module 'react-dropzone' {
declare type Dropzone = React$StatelessFunctionalComponent<*>;
declare module.exports: Dropzone;
}

View File

@ -1,19 +0,0 @@
// @flow
declare type I18Next$Translate$Config = {
defaultValue: string,
replace?: {
[string]: any
}
};
declare type I18Next$Translate = (key: string, config: I18Next$Translate$Config) => string;
declare module 'react-i18next' {
declare module.exports: {
I18nextProvider: React$StatelessFunctionalComponent<*>,
Trans: React$StatelessFunctionalComponent<*>,
reactI18nextModule: {},
translate: (context: string | Array<string>) => (Component: React$ComponentType<*>) => React$StatelessFunctionalComponent<*>
}
}

View File

@ -1,5 +0,0 @@
// @flow
declare module 'react-remarkable' {
declare module.exports: React$StatelessFunctionalComponent<*>
}

View File

@ -1,7 +0,0 @@
// @flow
declare module 'react-router' {
declare module.exports: {
withRouter: (Component: React$ComponentType<*>) => React$StatelessFunctionalComponent<*>;
}
}

View File

@ -1 +1 @@
module.exports = require('@polkadot/dev/config/jest'); module.exports = require('@polkadot/dev-react/config/jest');

View File

@ -1,5 +1,5 @@
{ {
"lerna": "2.5.1", "lerna": "2.11.0",
"npmClient": "yarn", "npmClient": "yarn",
"useWorkspaces": true, "useWorkspaces": true,
"command": { "command": {
@ -10,5 +10,5 @@
"packages": [ "packages": [
"packages/*" "packages/*"
], ],
"version": "0.4.12" "version": "0.5.0"
} }

View File

@ -9,16 +9,15 @@
"build": "polkadot-dev-build-babel && yarn run build:apps", "build": "polkadot-dev-build-babel && yarn run build:apps",
"build:apps": "cd packages/apps && react-scripts build", "build:apps": "cd packages/apps && react-scripts build",
"check": "eslint packages && flow check", "check": "eslint packages && flow check",
"clean": "polkadot-dev-clean-build",
"deploy:ghpages": "gh-pages -d packages/apps/build", "deploy:ghpages": "gh-pages -d packages/apps/build",
"vanitygen": "polkadot-dev-build-babel && node packages/app-vanitygen/build/generator/cli.js", "vanitygen": "polkadot-dev-build-babel && node packages/app-vanitygen/build/generator/cli.js",
"start": "cd packages/apps && react-scripts start", "start": "cd packages/apps && react-scripts start",
"test": "echo 'no tests executed'" "test": "echo 'no tests executed'"
}, },
"devDependencies": { "devDependencies": {
"@polkadot/dev": "^0.17.13", "@polkadot/dev-react": "^0.18.3",
"babel-preset-react": "^6.24.1",
"gh-pages": "^1.1.0", "gh-pages": "^1.1.0",
"lerna": "^2.5.1",
"react-scripts": "2.0.0-next.66cc7a90" "react-scripts": "2.0.0-next.66cc7a90"
}, },
"browserslist": { "browserslist": {

View File

@ -1,6 +1,6 @@
{ {
"name": "@polkadot/app-accounts", "name": "@polkadot/app-accounts",
"version": "0.4.12", "version": "0.5.0",
"main": "index.js", "main": "index.js",
"repository": "https://github.com/polkadot-js/apps.git", "repository": "https://github.com/polkadot-js/apps.git",
"author": "Jaco Greeff <jacogr@gmail.com>", "author": "Jaco Greeff <jacogr@gmail.com>",
@ -11,6 +11,6 @@
"test": "jest --coverage" "test": "jest --coverage"
}, },
"devDependencies": { "devDependencies": {
"@polkadot/ui-app": "^0.4.12" "@polkadot/ui-app": "^0.5.0"
} }
} }

View File

@ -8,6 +8,7 @@ import type { BareProps } from '@polkadot/ui-app/types';
import React from 'react'; import React from 'react';
import CopyButton from '@polkadot/ui-app/src/CopyButton'; import CopyButton from '@polkadot/ui-app/src/CopyButton';
import classes from '@polkadot/ui-app/src/util/classes';
import IdentityIcon from '@polkadot/ui-react/IdentityIcon'; import IdentityIcon from '@polkadot/ui-react/IdentityIcon';
import Balance from '@polkadot/ui-react-rx/Balance'; import Balance from '@polkadot/ui-react-rx/Balance';
import Nonce from '@polkadot/ui-react-rx/Nonce'; import Nonce from '@polkadot/ui-react-rx/Nonce';
@ -58,7 +59,7 @@ export default class Address extends React.PureComponent<Props, State> {
return ( return (
<div <div
className={['accounts--Address', isValid ? '' : 'invalid', className].join(' ')} className={classes('accounts--Address', isValid && 'invalid', className)}
style={style} style={style}
> >
<IdentityIcon <IdentityIcon

View File

@ -10,6 +10,7 @@ import React from 'react';
import Button from '@polkadot/ui-app/src/Button'; import Button from '@polkadot/ui-app/src/Button';
import Input from '@polkadot/ui-app/src/Input'; import Input from '@polkadot/ui-app/src/Input';
import Password from '@polkadot/ui-app/src/Password'; import Password from '@polkadot/ui-app/src/Password';
import classes from '@polkadot/ui-app/src/util/classes';
import keyring from '@polkadot/ui-keyring/src'; import keyring from '@polkadot/ui-keyring/src';
import isHex from '@polkadot/util/is/hex'; import isHex from '@polkadot/util/is/hex';
import hexToU8a from '@polkadot/util/hex/toU8a'; import hexToU8a from '@polkadot/util/hex/toU8a';
@ -66,7 +67,7 @@ class Creator extends React.PureComponent<Props, State> {
return ( return (
<div <div
className={['accounts--Creator', className].join(' ')} className={classes('accounts--Creator', className)}
style={style} style={style}
> >
<div className='ui--grid'> <div className='ui--grid'>

View File

@ -11,6 +11,7 @@ import React from 'react';
import Button from '@polkadot/ui-app/src/Button'; import Button from '@polkadot/ui-app/src/Button';
import Input from '@polkadot/ui-app/src/Input'; import Input from '@polkadot/ui-app/src/Input';
import InputAddress from '@polkadot/ui-app/src/InputAddress'; import InputAddress from '@polkadot/ui-app/src/InputAddress';
import classes from '@polkadot/ui-app/src/util/classes';
import keyring from '@polkadot/ui-keyring/src'; import keyring from '@polkadot/ui-keyring/src';
import Address from './Address'; import Address from './Address';
@ -49,7 +50,7 @@ class Editor extends React.PureComponent<Props, State> {
if (!currentPair) { if (!currentPair) {
return ( return (
<div <div
className={['accounts--Editor', className].join(' ')} className={classes('accounts--Editor', className)}
style={style} style={style}
> >
{t('editor.none', { {t('editor.none', {
@ -63,7 +64,7 @@ class Editor extends React.PureComponent<Props, State> {
return ( return (
<div <div
className={['accounts--Editor', className].join(' ')} className={classes('accounts--Editor', className)}
style={style} style={style}
> >
<div className='ui--grid'> <div className='ui--grid'>
@ -77,7 +78,7 @@ class Editor extends React.PureComponent<Props, State> {
className='full' className='full'
defaultValue={defaultPublicKey} defaultValue={defaultPublicKey}
hideAddress hideAddress
isSUIInput={false} isInput={false}
label={t('editor.select', { label={t('editor.select', {
defaultValue: 'using my account' defaultValue: 'using my account'
})} })}

View File

@ -12,6 +12,7 @@
} }
.accounts--Address { .accounts--Address {
padding: 0 2em;
text-align: center; text-align: center;
} }
@ -39,7 +40,7 @@
} }
.accounts--Address-data { .accounts--Address-data {
padding: 0.5em 2em; padding: 0.5em 0;
} }
.accounts--Address-data * { .accounts--Address-data * {

View File

@ -10,6 +10,7 @@ import './index.css';
import React from 'react'; import React from 'react';
import Button from '@polkadot/ui-app/src/Button'; import Button from '@polkadot/ui-app/src/Button';
import classes from '@polkadot/ui-app/src/util/classes';
import Creator from './Creator'; import Creator from './Creator';
import Editor from './Editor'; import Editor from './Editor';
@ -24,7 +25,8 @@ type State = {
} }
// FIXME React-router would probably be the best route, not home-grown // FIXME React-router would probably be the best route, not home-grown
const Components: { [Actions]: React$ComponentType<*> } = { // flowlint-next-line unclear-type:off
const Components: { [Actions]: React$ComponentType<any> } = {
'create': Creator, 'create': Creator,
'edit': Editor 'edit': Editor
}; };
@ -39,7 +41,7 @@ class App extends React.PureComponent<Props, State> {
return ( return (
<div <div
className={['accounts--App', className].join(' ')} className={classes('accounts--App', className)}
style={style} style={style}
> >
<Button.Group className='accounts--App-navigation'> <Button.Group className='accounts--App-navigation'>

View File

@ -1,6 +1,6 @@
{ {
"name": "@polkadot/app-addresses", "name": "@polkadot/app-addresses",
"version": "0.4.12", "version": "0.5.0",
"main": "index.js", "main": "index.js",
"repository": "https://github.com/polkadot-js/apps.git", "repository": "https://github.com/polkadot-js/apps.git",
"author": "Jaco Greeff <jacogr@gmail.com>", "author": "Jaco Greeff <jacogr@gmail.com>",
@ -11,7 +11,7 @@
"test": "jest --coverage" "test": "jest --coverage"
}, },
"devDependencies": { "devDependencies": {
"@polkadot/app-accounts": "^0.4.12", "@polkadot/app-accounts": "^0.5.0",
"@polkadot/ui-app": "^0.4.12" "@polkadot/ui-app": "^0.5.0"
} }
} }

View File

@ -9,6 +9,7 @@ import React from 'react';
import Button from '@polkadot/ui-app/src/Button'; import Button from '@polkadot/ui-app/src/Button';
import Input from '@polkadot/ui-app/src/Input'; import Input from '@polkadot/ui-app/src/Input';
import classes from '@polkadot/ui-app/src/util/classes';
import keyring from '@polkadot/ui-keyring/src'; import keyring from '@polkadot/ui-keyring/src';
import addressDecode from '@polkadot/util-keyring/address/decode'; import addressDecode from '@polkadot/util-keyring/address/decode';
import addressEncode from '@polkadot/util-keyring/address/encode'; import addressEncode from '@polkadot/util-keyring/address/encode';
@ -43,7 +44,7 @@ class Creator extends React.PureComponent<Props, State> {
return ( return (
<div <div
className={['addresses--Creator', className].join(' ')} className={classes('addresses--Creator', className)}
style={style} style={style}
> >
<div className='ui--grid'> <div className='ui--grid'>

View File

@ -11,6 +11,7 @@ import React from 'react';
import Button from '@polkadot/ui-app/src/Button'; import Button from '@polkadot/ui-app/src/Button';
import Input from '@polkadot/ui-app/src/Input'; import Input from '@polkadot/ui-app/src/Input';
import InputAddress from '@polkadot/ui-app/src/InputAddress'; import InputAddress from '@polkadot/ui-app/src/InputAddress';
import classes from '@polkadot/ui-app/src/util/classes';
import keyring from '@polkadot/ui-keyring/src'; import keyring from '@polkadot/ui-keyring/src';
import Address from '@polkadot/app-accounts/src/Address'; import Address from '@polkadot/app-accounts/src/Address';
@ -50,7 +51,7 @@ class Editor extends React.PureComponent<Props, State> {
if (!currentAddress) { if (!currentAddress) {
return ( return (
<div <div
className={['addresses--Editor', className].join(' ')} className={classes('addresses--Editor', className)}
style={style} style={style}
> >
{t('editor.none', { {t('editor.none', {
@ -64,7 +65,7 @@ class Editor extends React.PureComponent<Props, State> {
return ( return (
<div <div
className={['addresses--Editor', className].join(' ')} className={classes('addresses--Editor', className)}
style={style} style={style}
> >
<div className='ui--grid'> <div className='ui--grid'>

View File

@ -10,6 +10,7 @@ import './index.css';
import React from 'react'; import React from 'react';
import Button from '@polkadot/ui-app/src/Button'; import Button from '@polkadot/ui-app/src/Button';
import classes from '@polkadot/ui-app/src/util/classes';
import Creator from './Creator'; import Creator from './Creator';
import Editor from './Editor'; import Editor from './Editor';
@ -24,7 +25,8 @@ type State = {
} }
// FIXME React-router would probably be the best route, not home-grown // FIXME React-router would probably be the best route, not home-grown
const Components: { [Actions]: React$ComponentType<*> } = { // flowlint-next-line unclear-type:off
const Components: { [Actions]: React$ComponentType<any> } = {
'create': Creator, 'create': Creator,
'edit': Editor 'edit': Editor
}; };
@ -39,7 +41,7 @@ class App extends React.PureComponent<Props, State> {
return ( return (
<div <div
className={['addresses--App', className].join(' ')} className={classes('addresses--App', className)}
style={style} style={style}
> >
<Button.Group className='addresses--App-navigation'> <Button.Group className='addresses--App-navigation'>

View File

@ -1,6 +1,6 @@
{ {
"name": "@polkadot/app-explorer", "name": "@polkadot/app-explorer",
"version": "0.4.12", "version": "0.5.0",
"main": "index.js", "main": "index.js",
"repository": "https://github.com/polkadot-js/apps.git", "repository": "https://github.com/polkadot-js/apps.git",
"author": "Jaco Greeff <jacogr@gmail.com>", "author": "Jaco Greeff <jacogr@gmail.com>",
@ -11,10 +11,10 @@
"test": "jest --coverage" "test": "jest --coverage"
}, },
"devDependencies": { "devDependencies": {
"@polkadot/primitives": "^0.13.8", "@polkadot/primitives": "^0.13.10",
"@polkadot/primitives-codec": "^0.13.8", "@polkadot/primitives-codec": "^0.13.10",
"@polkadot/primitives-json": "^0.13.8", "@polkadot/primitives-json": "^0.13.10",
"@polkadot/ui-app": "^0.4.12", "@polkadot/ui-app": "^0.5.0",
"@polkadot/util-crypto": "^0.19.6" "@polkadot/util-crypto": "^0.19.7"
} }
} }

View File

@ -11,6 +11,7 @@ import './BlockHeader.css';
import React from 'react'; import React from 'react';
import headerHash from '@polkadot/primitives-codec/header/hash'; import headerHash from '@polkadot/primitives-codec/header/hash';
import classes from '@polkadot/ui-app/src/util/classes';
import u8aToHex from '@polkadot/util/u8a/toHex'; import u8aToHex from '@polkadot/util/u8a/toHex';
import translate from '../translate'; import translate from '../translate';
@ -30,7 +31,7 @@ function BlockHeader ({ className, label = '#', value, style }: Props): React$No
return ( return (
<div <div
className={['explorer--BlockHeader', className].join(' ')} className={classes('explorer--BlockHeader', className)}
style={style} style={style}
> >
<div className='number'> <div className='number'>

View File

@ -9,6 +9,7 @@ import './index.css';
import React from 'react'; import React from 'react';
import classes from '@polkadot/ui-app/src/util/classes';
import BestNumber from '@polkadot/ui-react-rx/BestNumber'; import BestNumber from '@polkadot/ui-react-rx/BestNumber';
import BestHash from './BestHash'; import BestHash from './BestHash';
@ -20,7 +21,7 @@ type Props = I18nProps & {};
function App ({ className, style, t }: Props): React$Node { function App ({ className, style, t }: Props): React$Node {
return ( return (
<div <div
className={['explorer--App', className].join(' ')} className={classes('explorer--App', className)}
style={style} style={style}
> >
<BestNumber <BestNumber

View File

@ -1,6 +1,6 @@
{ {
"name": "@polkadot/app-extrinsics", "name": "@polkadot/app-extrinsics",
"version": "0.4.12", "version": "0.5.0",
"main": "index.js", "main": "index.js",
"repository": "https://github.com/polkadot-js/apps.git", "repository": "https://github.com/polkadot-js/apps.git",
"author": "Jaco Greeff <jacogr@gmail.com>", "author": "Jaco Greeff <jacogr@gmail.com>",
@ -11,9 +11,9 @@
"test": "jest --coverage" "test": "jest --coverage"
}, },
"devDependencies": { "devDependencies": {
"@polkadot/extrinsics": "^0.13.8", "@polkadot/extrinsics": "^0.13.10",
"@polkadot/extrinsics-codec": "^0.13.8", "@polkadot/extrinsics-codec": "^0.13.10",
"@polkadot/ui-app": "^0.4.12", "@polkadot/ui-app": "^0.5.0",
"react-dropzone": "^4.2.9" "react-dropzone": "^4.2.9"
} }
} }

View File

@ -10,6 +10,7 @@ import React from 'react';
import InputAddress from '@polkadot/ui-app/src/InputAddress'; import InputAddress from '@polkadot/ui-app/src/InputAddress';
import Labelled from '@polkadot/ui-app/src/Labelled'; import Labelled from '@polkadot/ui-app/src/Labelled';
import classes from '@polkadot/ui-app/src/util/classes';
import Balance from '@polkadot/ui-react-rx/Balance'; import Balance from '@polkadot/ui-react-rx/Balance';
import translate from './translate'; import translate from './translate';
@ -45,7 +46,7 @@ class Account extends React.PureComponent<Props, State> {
return ( return (
<div <div
className={['extrinsics--Account', 'ui--row', className].join(' ')} className={classes('extrinsics--Account', 'ui--row', className)}
style={style} style={style}
> >
<div className='large'> <div className='large'>

View File

@ -13,6 +13,7 @@ import React from 'react';
import encode from '@polkadot/extrinsics-codec/encode/extrinsic'; import encode from '@polkadot/extrinsics-codec/encode/extrinsic';
import InputExtrinsic from '@polkadot/ui-app/src/InputExtrinsic'; import InputExtrinsic from '@polkadot/ui-app/src/InputExtrinsic';
import Params from '@polkadot/ui-app/src/Params'; import Params from '@polkadot/ui-app/src/Params';
import classes from '@polkadot/ui-app/src/util/classes';
import isUndefined from '@polkadot/util/is/undefined'; import isUndefined from '@polkadot/util/is/undefined';
import paramComponents from './Params'; import paramComponents from './Params';
@ -48,7 +49,7 @@ export default class ExtrinsicDisplay extends React.PureComponent<Props, State>
return ( return (
<div <div
className={['extrinsics--Extrinsic', className].join(' ')} className={classes('extrinsics--Extrinsic', className)}
style={style} style={style}
> >
<InputExtrinsic <InputExtrinsic

View File

@ -9,6 +9,7 @@ import type { BareProps } from '@polkadot/ui-app/types';
import React from 'react'; import React from 'react';
import Labelled from '@polkadot/ui-app/src/Labelled'; import Labelled from '@polkadot/ui-app/src/Labelled';
import classes from '@polkadot/ui-app/src/util/classes';
import RxNonce from '@polkadot/ui-react-rx/Nonce'; import RxNonce from '@polkadot/ui-react-rx/Nonce';
type Props = BareProps & { type Props = BareProps & {
@ -20,7 +21,7 @@ type Props = BareProps & {
export default function Nonce ({ className, label, style, onChange, value }: Props): React$Node { export default function Nonce ({ className, label, style, onChange, value }: Props): React$Node {
return ( return (
<div <div
className={['ui--row', className].join(' ')} className={classes('ui--row', className)}
style={style} style={style}
> >
<Labelled <Labelled

View File

@ -11,6 +11,7 @@ import React from 'react';
import extrinsics from '@polkadot/extrinsics-substrate'; import extrinsics from '@polkadot/extrinsics-substrate';
import Button from '@polkadot/ui-app/src/Button'; import Button from '@polkadot/ui-app/src/Button';
import classes from '@polkadot/ui-app/src/util/classes';
import Account from './Account'; import Account from './Account';
import Extrinsic from './Extrinsic'; import Extrinsic from './Extrinsic';
@ -43,7 +44,7 @@ class Selection extends React.PureComponent<Props, State> {
return ( return (
<div <div
className={['extrinsics--Selection', className].join(' ')} className={classes('extrinsics--Selection', className)}
style={style} style={style}
> >
<Account <Account

View File

@ -10,6 +10,7 @@ import BN from 'bn.js';
import React from 'react'; import React from 'react';
import { Trans } from 'react-i18next'; import { Trans } from 'react-i18next';
import classes from '@polkadot/ui-app/src/util/classes';
import IdentityIcon from '@polkadot/ui-react/IdentityIcon'; import IdentityIcon from '@polkadot/ui-react/IdentityIcon';
import u8aToHexShort from '@polkadot/util/u8a/toHexShort'; import u8aToHexShort from '@polkadot/util/u8a/toHexShort';
import addressEncode from '@polkadot/util-keyring/address/encode'; import addressEncode from '@polkadot/util-keyring/address/encode';
@ -25,7 +26,7 @@ function Decoded ({ className, style, t, value: { extrinsic: { name, section },
return ( return (
<div <div
className={['extrinsics--Signer-Decoded', className].join(' ')} className={classes('extrinsics--Signer-Decoded', className)}
style={style} style={style}
> >
<div className='expanded'> <div className='expanded'>

View File

@ -9,6 +9,7 @@ import type { KeyringPair } from '@polkadot/util-keyring/types';
import React from 'react'; import React from 'react';
import Password from '@polkadot/ui-app/src/Password'; import Password from '@polkadot/ui-app/src/Password';
import classes from '@polkadot/ui-app/src/util/classes';
import keyring from '@polkadot/ui-keyring/src'; import keyring from '@polkadot/ui-keyring/src';
import translate from '../translate'; import translate from '../translate';
@ -51,7 +52,7 @@ class Unlock extends React.PureComponent<Props, State> {
return ( return (
<div <div
className={['extrinsics--Signer-Unlock', className].join(' ')} className={classes('extrinsics--Signer-Unlock', className)}
style={style} style={style}
> >
<div className='ui--row'> <div className='ui--row'>

View File

@ -13,6 +13,7 @@ import React from 'react';
import Button from '@polkadot/ui-app/src/Button'; import Button from '@polkadot/ui-app/src/Button';
import Modal from '@polkadot/ui-app/src/Modal'; import Modal from '@polkadot/ui-app/src/Modal';
import classes from '@polkadot/ui-app/src/util/classes';
import keyring from '@polkadot/ui-keyring/src'; import keyring from '@polkadot/ui-keyring/src';
import withApi from '@polkadot/ui-react-rx/with/api'; import withApi from '@polkadot/ui-react-rx/with/api';
@ -69,7 +70,7 @@ class Signer extends React.PureComponent<Props, State> {
return ( return (
<Modal <Modal
className={['extrinsics--Signer', className].join(' ')} className={classes('extrinsics--Signer', className)}
dimmer='inverted' dimmer='inverted'
open open
style={style} style={style}

View File

@ -8,6 +8,8 @@ import type { QueueTx } from './types';
import React from 'react'; import React from 'react';
import classes from '@polkadot/ui-app/src/util/classes';
type Props = BareProps & { type Props = BareProps & {
queue: Array<QueueTx> queue: Array<QueueTx>
} }
@ -23,12 +25,12 @@ export default function Status ({ className, queue, style }: Props): React$Node
return ( return (
<div <div
className={['extrinsics--Status', className].join(' ')} className={classes('extrinsics--Status', className)}
style={style} style={style}
> >
{available.map(({ extrinsic: { name, section }, id, status }) => {available.map(({ extrinsic: { name, section }, id, status }) =>
<div <div
className={['extrinsics--Status-Item', status].join(' ')} className={classes('extrinsics--Status-Item', status)}
key={id} key={id}
> >
<div className='header'> <div className='header'>

View File

@ -10,6 +10,8 @@ import './index.css';
import React from 'react'; import React from 'react';
import classes from '@polkadot/ui-app/src/util/classes';
import Selection from './Selection'; import Selection from './Selection';
import Signer from './Signer'; import Signer from './Signer';
import Status from './Status'; import Status from './Status';
@ -31,7 +33,7 @@ export default class App extends React.PureComponent<Props, State> {
return ( return (
<div <div
className={['extrinsics--App', className].join(' ')} className={classes('extrinsics--App', className)}
style={style} style={style}
> >
<Selection onQueue={this.onQueue} /> <Selection onQueue={this.onQueue} />

View File

@ -1,6 +1,6 @@
{ {
"name": "@polkadot/app-storage", "name": "@polkadot/app-storage",
"version": "0.4.12", "version": "0.5.0",
"main": "index.js", "main": "index.js",
"repository": "https://github.com/polkadot-js/apps.git", "repository": "https://github.com/polkadot-js/apps.git",
"author": "Jaco Greeff <jacogr@gmail.com>", "author": "Jaco Greeff <jacogr@gmail.com>",
@ -11,6 +11,6 @@
"test": "jest --coverage" "test": "jest --coverage"
}, },
"devDependencies": { "devDependencies": {
"@polkadot/ui-app": "^0.4.12" "@polkadot/ui-app": "^0.5.0"
} }
} }

View File

@ -8,6 +8,8 @@ import type { StorageQuery } from './types';
import React from 'react'; import React from 'react';
import classes from '@polkadot/ui-app/src/util/classes';
import translate from './translate'; import translate from './translate';
import Query from './Query'; import Query from './Query';
@ -23,7 +25,7 @@ function Queries ({ className, onRemove, style, value }: Props): React$Node {
return ( return (
<div <div
className={['storage--Queries', className].join(' ')} className={classes('storage--Queries', className)}
style={style} style={style}
> >
{value.map((query) => {value.map((query) =>

View File

@ -12,6 +12,7 @@ import Button from '@polkadot/ui-app/src/Button';
import Labelled from '@polkadot/ui-app/src/Labelled'; import Labelled from '@polkadot/ui-app/src/Labelled';
import typeToText from '@polkadot/ui-app/src/Params/typeToText'; import typeToText from '@polkadot/ui-app/src/Params/typeToText';
import valueToText from '@polkadot/ui-app/src/Params/valueToText'; import valueToText from '@polkadot/ui-app/src/Params/valueToText';
import classes from '@polkadot/ui-app/src/util/classes';
import withStorageDiv from '@polkadot/ui-react-rx/with/storageDiv'; import withStorageDiv from '@polkadot/ui-react-rx/with/storageDiv';
import translate from './translate'; import translate from './translate';
@ -23,7 +24,8 @@ type Props = I18nProps & {
type State = { type State = {
inputs: Array<React$Node>, inputs: Array<React$Node>,
Component: React$ComponentType<*>; // flowlint-next-line unclear-type:off
Component: React$ComponentType<any>;
}; };
const cache = []; const cache = [];
@ -32,14 +34,15 @@ class Query extends React.PureComponent<Props, State> {
state: State = ({}: $Shape<State>); state: State = ({}: $Shape<State>);
static getDerivedStateFromProps ({ value: { id, key, params } }: Props, prevState: State): State | null { static getDerivedStateFromProps ({ value: { id, key, params } }: Props, prevState: State): State | null {
const Component = ((): React$ComponentType<*> => { // flowlint-next-line unclear-type:off
const Component = ((): React$ComponentType<any> => {
if (!cache[id]) { if (!cache[id]) {
const values = params.map(({ value }) => value); const values = params.map(({ value }) => value);
cache[id] = withStorageDiv(key, { params: values })( cache[id] = withStorageDiv(key, { params: values })(
(value) => (value) =>
valueToText(key.type, value), valueToText(key.type, value),
{ className: 'ui disabled dropdown selection' } { className: 'ui--output' }
); );
} }
@ -67,7 +70,7 @@ class Query extends React.PureComponent<Props, State> {
return ( return (
<div <div
className={['storage--Query', 'storage--actionrow', className].join(' ')} className={classes('storage--Query', 'storage--actionrow', className)}
style={style} style={style}
> >
<Labelled <Labelled

View File

@ -15,6 +15,7 @@ import Button from '@polkadot/ui-app/src/Button';
import InputStorage from '@polkadot/ui-app/src/InputStorage'; import InputStorage from '@polkadot/ui-app/src/InputStorage';
import Labelled from '@polkadot/ui-app/src/Labelled'; import Labelled from '@polkadot/ui-app/src/Labelled';
import Params from '@polkadot/ui-app/src/Params'; import Params from '@polkadot/ui-app/src/Params';
import classes from '@polkadot/ui-app/src/util/classes';
import isUndefined from '@polkadot/util/is/undefined'; import isUndefined from '@polkadot/util/is/undefined';
import translate from './translate'; import translate from './translate';
@ -44,7 +45,7 @@ class Selection extends React.PureComponent<Props, State> {
return ( return (
<div <div
className={['storage--Selection', 'storage--actionrow', className].join(' ')} className={classes('storage--Selection', 'storage--actionrow', className)}
style={style} style={style}
> >
<div className='storage--actionrow-value'> <div className='storage--actionrow-value'>

View File

@ -10,6 +10,8 @@ import './index.css';
import React from 'react'; import React from 'react';
import classes from '@polkadot/ui-app/src/util/classes';
import Queries from './Queries'; import Queries from './Queries';
import Selection from './Selection'; import Selection from './Selection';
import translate from './translate'; import translate from './translate';
@ -31,7 +33,7 @@ class App extends React.PureComponent<Props, State> {
return ( return (
<div <div
className={['storage--App', className].join(' ')} className={classes('storage--App', className)}
style={style} style={style}
> >
<Selection onAdd={this.onAdd} /> <Selection onAdd={this.onAdd} />

View File

@ -8,5 +8,6 @@ import type { StorageDef$Key } from '@polkadot/storage/types';
export type StorageQuery = { export type StorageQuery = {
id: number, id: number,
key: StorageDef$Key, key: StorageDef$Key,
params: Array<*> // flowlint-next-line unclear-type:off
params: Array<any>
} }

View File

@ -0,0 +1,15 @@
ISC License (ISC)
Copyright 2017-2018 Jaco Greeff <jacogr@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

View File

@ -0,0 +1 @@
# @polkadot/app-toolbox

View File

@ -0,0 +1,17 @@
{
"name": "@polkadot/app-toolbox",
"version": "0.5.0",
"main": "index.js",
"repository": "https://github.com/polkadot-js/apps.git",
"author": "Jaco Greeff <jacogr@gmail.com>",
"license": "ISC",
"scripts": {
"build": "polkadot-dev-build-babel",
"check": "stylelint 'src/**/*.css' && eslint src && flow check",
"test": "jest --coverage"
},
"devDependencies": {
"@polkadot/ui-app": "^0.5.0",
"@polkadot/ui-keyring": "^0.5.0"
}
}

View File

@ -0,0 +1,95 @@
// 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 { I18nProps as Props } from '@polkadot/ui-app/types';
import React from 'react';
import Input from '@polkadot/ui-app/src/Input';
import Output from '@polkadot/ui-app/src/Output';
import Static from '@polkadot/ui-app/src/Static';
import classes from '@polkadot/ui-app/src/util/classes';
import hexToU8a from '@polkadot/util/hex/toU8a';
import isHex from '@polkadot/util/is/hex';
import u8aFromString from '@polkadot/util/u8a/fromString';
import xxhashAsHex256 from '@polkadot/util-crypto/xxhash/asHex256';
import translate from './translate';
type State = {
data: string,
hash: string,
isHexData: boolean
};
class Hash extends React.PureComponent<Props, State> {
state: State = {
data: '',
hash: xxhashAsHex256(u8aFromString('')),
isHexData: false
};
render (): React$Node {
const { className, style, t } = this.props;
const { data, hash, isHexData } = this.state;
return (
<div
className={classes('toolbox--Hash', className)}
style={style}
>
<div className='ui--row'>
<Input
className='large'
label={t('hash.data', {
defaultValue: 'from the following data (hex or string)'
})}
onChange={this.onChangeData}
value={data}
/>
<Static
className='small'
label={t('hash.isHex', {
defaultValue: 'hex input data'
})}
value={
isHexData
? t('hash.isHex.yes', {
defaultValue: 'Yes'
})
: t('hash.isHex.no', {
defaultValue: 'No'
})
}
/>
</div>
<div className='ui--row'>
<Output
className='full toolbox--hex'
isHidden={hash.length === 0}
label={t('hash.output', {
defaultValue: 'the resulting hash is'
})}
value={hash}
withCopy
/>
</div>
</div>
);
}
onChangeData = (data: string): void => {
const isHexData = isHex(data);
const hash = xxhashAsHex256(
isHexData
? hexToU8a(data)
: u8aFromString(data)
);
this.setState({ data, hash, isHexData });
}
}
export default translate(Hash);

View File

@ -0,0 +1,194 @@
// 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 { I18nProps as Props } from '@polkadot/ui-app/types';
import type { KeyringPair } from '@polkadot/util-keyring/types';
import React from 'react';
import Button from '@polkadot/ui-app/src/Button';
import Input from '@polkadot/ui-app/src/Input';
import InputAddress from '@polkadot/ui-app/src/InputAddress';
import Output from '@polkadot/ui-app/src/Output';
import Static from '@polkadot/ui-app/src/Static';
import classes from '@polkadot/ui-app/src/util/classes';
import keyring from '@polkadot/ui-keyring/src';
import hexToU8a from '@polkadot/util/hex/toU8a';
import isHex from '@polkadot/util/is/hex';
import u8aFromString from '@polkadot/util/u8a/fromString';
import u8aToHex from '@polkadot/util/u8a/toHex';
import Unlock from './Unlock';
import translate from './translate';
type State = {
currentPair: KeyringPair | null,
defaultPublicKey?: Uint8Array,
data: string,
isHexData: boolean,
isLocked: boolean,
isUnlockVisible: boolean,
signature: string
};
class Sign extends React.PureComponent<Props, State> {
state: State;
constructor (props: Props) {
super(props);
const pairs = keyring.getPairs();
const currentPair = pairs[0] || null;
this.state = {
currentPair,
defaultPublicKey: currentPair
? currentPair.publicKey()
: void 0,
data: '',
isHexData: false,
isLocked: currentPair
? !currentPair.hasSecretKey()
: false,
isUnlockVisible: false,
signature: ''
};
}
render (): React$Node {
const { className, style, t } = this.props;
const { currentPair, data, defaultPublicKey, isHexData, isLocked, isUnlockVisible, signature } = this.state;
return (
<div
className={classes('toolbox--Sign', className)}
style={style}
>
<div className='ui--row'>
<InputAddress
className='full'
defaultValue={defaultPublicKey}
isInput={false}
label={t('sign.account', {
defaultValue: 'using my account'
})}
onChange={this.onChangeAccount}
type='account'
/>
</div>
<div className='ui--row'>
<Input
className='large'
label={t('sign.data', {
defaultValue: 'sign the following data (hex or string)'
})}
onChange={this.onChangeData}
value={data}
/>
<Static
className='small'
label={t('sign.isHex', {
defaultValue: 'hex input data'
})}
value={
isHexData
? t('sign.isHex.yes', {
defaultValue: 'Yes'
})
: t('sign.isHex.no', {
defaultValue: 'No'
})
}
/>
</div>
<div className='ui--row'>
<Output
className='full toolbox--hex'
isHidden={signature.length === 0}
label={t('sign.signed', {
defaultValue: 'signature of supplied data'
})}
value={signature}
withCopy
/>
</div>
<Unlock
isVisible={isUnlockVisible}
onClose={this.toggleUnlock}
pair={currentPair}
/>
{
isLocked
? (
<Button.Group>
<Button
isPrimary
onClick={this.toggleUnlock}
text={t('sign.unlock', {
defaultValue: 'Unlock account'
})}
/>
</Button.Group>
)
: null
}
</div>
);
}
nextState = (newState: $Shape<State>): void => {
this.setState(
(prevState: State): $Shape<State> => {
const { currentPair = prevState.currentPair, data = prevState.data, isHexData = prevState.isHexData, isUnlockVisible = prevState.isUnlockVisible } = newState;
const isLocked = !currentPair || !currentPair.hasSecretKey();
let signature = '';
if (!isLocked && currentPair) {
signature = u8aToHex(
currentPair.sign(
isHexData
? hexToU8a(data)
: u8aFromString(data)
)
);
}
return {
currentPair,
data,
isHexData,
isLocked,
isUnlockVisible,
signature
};
}
);
}
toggleUnlock = (): void => {
const { isUnlockVisible } = this.state;
this.nextState({
isUnlockVisible: !isUnlockVisible
});
}
onChangeAccount = (publicKey: Uint8Array): void => {
const currentPair = keyring.getPair(publicKey);
this.nextState({ currentPair });
}
onChangeData = (data: string): void => {
const isHexData = isHex(data);
this.nextState({ data, isHexData });
}
onUnlock = (): void => {
}
}
export default translate(Sign);

View File

@ -0,0 +1,182 @@
// 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 { I18nProps } from '@polkadot/ui-app/types';
import type { KeyringPair } from '@polkadot/util-keyring/types';
import React from 'react';
import { Trans } from 'react-i18next';
import Button from '@polkadot/ui-app/src/Button';
import Modal from '@polkadot/ui-app/src/Modal';
import Password from '@polkadot/ui-app/src/Password';
import classes from '@polkadot/ui-app/src/util/classes';
import IdentityIcon from '@polkadot/ui-react/IdentityIcon';
import translate from './translate';
type Props = I18nProps & {
isVisible: boolean,
onClose: () => void,
pair: KeyringPair
};
type UnlockI18n = {
key: string,
value: I18Next$Translate$Config
}
type State = {
address: string,
password: string,
unlockError: UnlockI18n | null
};
class Unlock extends React.PureComponent<Props, State> {
state: State = {
address: '',
password: '',
unlockError: null
};
static getDerivedStateFromProps ({ pair }: Props, prevState: State): $Shape<State> {
const address = pair
? pair.address()
: '';
const isSame = address !== prevState.address;
return {
address,
password: isSame
? prevState.password
: '',
unlockError: isSame
? prevState.unlockError
: null
};
}
render (): React$Node {
const { className, isVisible, style, t } = this.props;
const { address, password, unlockError } = this.state;
if (!isVisible) {
return null;
}
return (
<Modal
className={classes('toolbox--Unlock', className)}
dimmer='inverted'
open
style={style}
>
<Modal.Header>
{t('unlock.header', {
defaultValue: 'Unlock account'
})}
</Modal.Header>
<Modal.Content>
<div className='toolbox--Unlock-Content'>
<div className='expanded'>
<p>
<Trans i18nkey='unlock.info'>
You are about to unlock your account <span className='code'>{address}</span> to allow for the signing of messages.
</Trans>
</p>
</div>
<IdentityIcon
className='icon'
value={address}
/>
</div>
<div className='toolbox--Unlock-Entry'>
<div className='ui--row'>
<Password
className='medium'
isError={!!unlockError}
label={t('unlock.password', {
defaultValue: 'unlock account using'
})}
onChange={this.onChangePassword}
value={password}
/>
</div>
</div>
</Modal.Content>
<Modal.Actions>
<Button.Group>
<Button
isNegative
onClick={this.onCancel}
text={t('unlock.cancel', {
defaultValue: 'Cancel'
})}
/>
<Button.Or />
<Button
isPrimary
onClick={this.onUnlock}
text={t('unlock.doit', {
defaultValue: 'Unlock'
})}
/>
</Button.Group>
</Modal.Actions>
</Modal>
);
}
unlockAccount (password?: string): ?UnlockI18n {
const { pair } = this.props;
if (pair.hasSecretKey()) {
return null;
}
try {
// $FlowFixMe typo in underlying type, fixed at base (upgrades)
pair.decodePkcs8(void 0, password);
} catch (error) {
return {
key: 'unlock.generic',
value: {
defaultValue: error.message
}
};
}
return null;
}
onChangePassword = (password: string): void => {
this.setState({
password,
unlockError: null
});
}
onCancel = (): void => {
const { onClose } = this.props;
onClose();
}
onUnlock = (): void => {
const { onClose } = this.props;
const { password } = this.state;
const unlockError = this.unlockAccount(password);
if (unlockError) {
this.setState({ unlockError });
return;
}
onClose();
};
}
export default translate(Unlock);

View File

@ -0,0 +1,177 @@
// 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 { I18nProps as Props } from '@polkadot/ui-app/types';
import React from 'react';
import Icon from '@polkadot/ui-app/src/Icon';
import Input from '@polkadot/ui-app/src/Input';
import InputAddress from '@polkadot/ui-app/src/InputAddress';
import Static from '@polkadot/ui-app/src/Static';
import classes from '@polkadot/ui-app/src/util/classes';
import keyring from '@polkadot/ui-keyring/src';
import hexToU8a from '@polkadot/util/hex/toU8a';
import isHex from '@polkadot/util/is/hex';
import u8aFromString from '@polkadot/util/u8a/fromString';
import naclVerify from '@polkadot/util-crypto/nacl/verify';
import translate from './translate';
type State = {
currentPublicKey: Uint8Array | null,
defaultPublicKey?: Uint8Array,
data: string,
isHexData: boolean,
isValidAddress: boolean,
isValidSignature: boolean,
isValid: boolean,
signature: string
};
class Verify extends React.PureComponent<Props, State> {
state: State;
constructor (props: Props) {
super(props);
const pairs = keyring.getPairs();
const currentPair = pairs[0];
const currentPublicKey = currentPair
? currentPair.publicKey()
: null;
this.state = {
currentPublicKey,
defaultPublicKey: currentPublicKey || void 0,
data: '',
isHexData: false,
isValidAddress: !!currentPair,
isValidSignature: false,
isValid: false,
signature: ''
};
}
render (): React$Node {
const { className, style, t } = this.props;
const { defaultPublicKey, data, isHexData, isValid, isValidAddress, isValidSignature, signature } = this.state;
return (
<div
className={classes('toolbox--Verify', className)}
style={style}
>
<div className='ui--row'>
<Input
className='large'
label={t('verify.data', {
defaultValue: 'using the following data (hex or string)'
})}
onChange={this.onChangeData}
value={data}
/>
<Static
className='small'
label={t('verify.isHex', {
defaultValue: 'hex input data'
})}
value={
isHexData
? t('verify.isHex.yes', {
defaultValue: 'Yes'
})
: t('verify.isHex.no', {
defaultValue: 'No'
})
}
/>
</div>
<div className='ui--row'>
<InputAddress
className='full'
defaultValue={defaultPublicKey}
isError={!isValidAddress}
isInput
label={t('verify.account', {
defaultValue: 'verify using address'
})}
onChange={this.onChangeAddress}
/>
</div>
<div className='ui--row'>
<Input
className='full'
icon={
<Icon
color={isValid ? 'green' : (isValidSignature ? 'red' : void 0)}
name={isValid ? 'check circle' : (isValidSignature ? 'exclamation circle' : 'help circle')}
size='big'
/>
}
isError={!isValidSignature}
label={t('verify.signature', {
defaultValue: 'checking the supplied signature'
})}
onChange={this.onChangeSignature}
value={signature}
/>
</div>
</div>
);
}
nextState (newState: $Shape<State>): void {
this.setState(
(prevState: State): $Shape<State> => {
const { isHexData = prevState.isHexData, isValidAddress = prevState.isValidAddress, isValidSignature = prevState.isValidSignature, currentPublicKey = prevState.currentPublicKey, data = prevState.data, signature = prevState.signature } = newState;
let isValid = isValidAddress && isValidSignature;
if (isValid && currentPublicKey) {
isValid = naclVerify(
isHexData
? hexToU8a(data)
: u8aFromString(data),
hexToU8a(signature),
currentPublicKey
);
}
return {
isHexData,
isValid,
isValidAddress,
isValidSignature,
currentPublicKey,
data,
signature
};
}
);
}
onChangeData = (data: string): void => {
const isHexData = isHex(data);
this.nextState({ data, isHexData });
}
onChangeSignature = (signature: string): void => {
console.log('onChangeSig', isHex(signature), signature.length);
const isValidSignature = isHex(signature) && signature.length === 130;
this.nextState({ signature, isValidSignature });
}
onChangeAddress = (currentPublicKey: Uint8Array): void => {
const isValidAddress = currentPublicKey && currentPublicKey.length === 32;
this.nextState({ currentPublicKey, isValidAddress });
}
}
export default translate(Verify);

View File

@ -0,0 +1,41 @@
/* 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. */
.toolbox--App {
padding: 1em 2em;
}
.toolbox--App-navigation.ui--Button-Group {
margin-bottom: 2em;
text-align: center;
}
.toolbox--hex .ui--output {
font-family: monospace;
}
.toolbox--Unlock-Content {
align-content: center;
display: flex;
line-height: 1.5em;
}
.toolbox--Unlock-Content .expanded {
padding-right: 2em;
}
.toolbox--Unlock-Content .expanded .code {
background: #f5f5f5;
font-family: monospace;
margin: 0 0.25em;
overflow-wrap: break-word;
padding: 0.25em 0.5em;
word-break: break-all;
word-break: break-word;
word-wrap: break-word;
}
.toolbox--Unlock-Entry {
padding-top: 1.5rem;
}

View File

@ -0,0 +1,94 @@
// 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 { I18nProps } from '@polkadot/ui-app/types';
import './index.css';
import React from 'react';
import Button from '@polkadot/ui-app/src/Button';
import classes from '@polkadot/ui-app/src/util/classes';
import Hash from './Hash';
import Sign from './Sign';
import Verify from './Verify';
import translate from './translate';
type Actions = 'hash' | 'sign' | 'verify';
type Props = I18nProps & {};
type State = {
action: Actions
}
// FIXME React-router would probably be the best route, not home-grown
// flowlint-next-line unclear-type:off
const Components: { [Actions]: React$ComponentType<any> } = {
'hash': Hash,
'sign': Sign,
'verify': Verify
};
class App extends React.PureComponent<Props, State> {
state: State = {
action: 'hash'
};
render (): React$Node {
const { className, style, t } = this.props;
const { action } = this.state;
const Component = Components[action];
return (
<div
className={classes('toolbox--App', className)}
style={style}
>
<Button.Group className='accounts--App-navigation'>
<Button
isPrimary={action === 'hash'}
onClick={this.selectHash}
text={t('app.hash', {
defaultValue: 'Hash data'
})}
/>
<Button.Or />
<Button
isPrimary={action === 'sign'}
onClick={this.selectSign}
text={t('app.sign', {
defaultValue: 'Sign message'
})}
/>
<Button.Or />
<Button
isPrimary={action === 'verify'}
onClick={this.selectVerify}
text={t('app.verify', {
defaultValue: 'Verify signature'
})}
/>
</Button.Group>
<Component />
</div>
);
}
selectHash = (): void => {
this.setState({ action: 'hash' });
}
selectSign = (): void => {
this.setState({ action: 'sign' });
}
selectVerify = (): void => {
this.setState({ action: 'verify' });
}
}
export default translate(App);

View File

@ -0,0 +1,8 @@
// 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 { translate } from 'react-i18next';
export default translate(['toolbox', 'ui']);

View File

@ -1,6 +1,6 @@
{ {
"name": "@polkadot/app-vanitygen", "name": "@polkadot/app-vanitygen",
"version": "0.4.12", "version": "0.5.0",
"main": "index.js", "main": "index.js",
"repository": "https://github.com/polkadot-js/apps.git", "repository": "https://github.com/polkadot-js/apps.git",
"author": "Jaco Greeff <jacogr@gmail.com>", "author": "Jaco Greeff <jacogr@gmail.com>",
@ -11,7 +11,7 @@
"test": "jest --coverage" "test": "jest --coverage"
}, },
"devDependencies": { "devDependencies": {
"@polkadot/ui-app": "^0.4.12", "@polkadot/ui-app": "^0.5.0",
"chalk": "^2.4.1", "chalk": "^2.4.1",
"yargs": "10.1.2" "yargs": "10.1.2"
}, },

View File

@ -9,6 +9,7 @@ import React from 'react';
import CopyButton from '@polkadot/ui-app/src/CopyButton'; import CopyButton from '@polkadot/ui-app/src/CopyButton';
import Button from '@polkadot/ui-app/src/Button'; import Button from '@polkadot/ui-app/src/Button';
import classes from '@polkadot/ui-app/src/util/classes';
import IdentityIcon from '@polkadot/ui-react/IdentityIcon'; import IdentityIcon from '@polkadot/ui-react/IdentityIcon';
import u8aToHex from '@polkadot/util/u8a/toHex'; import u8aToHex from '@polkadot/util/u8a/toHex';
@ -39,7 +40,7 @@ export default class Match extends React.PureComponent<Props, State> {
return ( return (
<div <div
className={['vanity--Match', className].join(' ')} className={classes('vanity--Match', className)}
style={style} style={style}
> >
<div className='vanity--Match-item'> <div className='vanity--Match-item'>

View File

@ -13,7 +13,8 @@ import React from 'react';
import Button from '@polkadot/ui-app/src/Button'; import Button from '@polkadot/ui-app/src/Button';
import Dropdown from '@polkadot/ui-app/src/Dropdown'; import Dropdown from '@polkadot/ui-app/src/Dropdown';
import Input from '@polkadot/ui-app/src/Input'; import Input from '@polkadot/ui-app/src/Input';
import Labelled from '@polkadot/ui-app/src/Labelled'; import Static from '@polkadot/ui-app/src/Static';
import classes from '@polkadot/ui-app/src/util/classes';
import Match from './Match'; import Match from './Match';
import generator from './generator'; import generator from './generator';
@ -61,7 +62,7 @@ class App extends React.PureComponent<Props, State> {
return ( return (
<div <div
className={['vanity--App', className].join(' ')} className={classes('vanity--App', className)}
style={style} style={style}
> >
<div className='ui--row'> <div className='ui--row'>
@ -85,18 +86,15 @@ class App extends React.PureComponent<Props, State> {
onChange={this.onChangeCase} onChange={this.onChangeCase}
value={withCase} value={withCase}
/> />
<Labelled <Static
className='small' className='small'
label={t('vanity.offset', { label={t('vanity.offset', {
defaultValue: 'exact offset' defaultValue: 'exact offset'
})} })}
> value={t('vanity.offset.off', {
<div className='ui dropdown selection disabled'> defaultValue: 'No'
{t('vanity.offset.off', { })}
defaultValue: 'No' />
})}
</div>
</Labelled>
</div> </div>
<Button.Group> <Button.Group>
<Button <Button

View File

@ -1,6 +1,6 @@
{ {
"name": "@polkadot/apps", "name": "@polkadot/apps",
"version": "0.4.12", "version": "0.5.0",
"description": "An Apps portal into the Polkadot network", "description": "An Apps portal into the Polkadot network",
"main": "index.js", "main": "index.js",
"homepage": ".", "homepage": ".",
@ -14,12 +14,13 @@
"test": "react-scripts test --env=jsdom --coverage" "test": "react-scripts test --env=jsdom --coverage"
}, },
"devDependencies": { "devDependencies": {
"@polkadot/app-accounts": "^0.4.12", "@polkadot/app-accounts": "^0.5.0",
"@polkadot/app-addresses": "^0.4.12", "@polkadot/app-addresses": "^0.5.0",
"@polkadot/app-explorer": "^0.4.12", "@polkadot/app-explorer": "^0.5.0",
"@polkadot/app-extrinsics": "^0.4.12", "@polkadot/app-extrinsics": "^0.5.0",
"@polkadot/app-storage": "^0.4.12", "@polkadot/app-storage": "^0.5.0",
"@polkadot/ui-app": "^0.4.12", "@polkadot/app-toolbox": "^0.5.0",
"react-remarkable": "^1.1.3" "@polkadot/app-vanitygen": "^0.5.0",
"@polkadot/ui-app": "^0.5.0"
} }
} }

View File

@ -9,6 +9,8 @@ import './App.css';
import React from 'react'; import React from 'react';
import classes from '@polkadot/ui-app/src/util/classes';
import Connecting from '../Connecting'; import Connecting from '../Connecting';
import Content from '../Content'; import Content from '../Content';
import SideBar from '../SideBar'; import SideBar from '../SideBar';
@ -19,7 +21,7 @@ type Props = I18nProps & {};
function App ({ className, style }: Props): React$Node { function App ({ className, style }: Props): React$Node {
return ( return (
<div <div
className={['apps--App', className].join(' ')} className={classes('apps--App', className)}
style={style} style={style}
> >
<SideBar className='apps--App-column' /> <SideBar className='apps--App-column' />

View File

@ -9,6 +9,7 @@ import './Connecting.css';
import React from 'react'; import React from 'react';
import classes from '@polkadot/ui-app/src/util/classes';
import withApiCall from '@polkadot/ui-react-rx/with/apiCall'; import withApiCall from '@polkadot/ui-react-rx/with/apiCall';
import translate from '../translate'; import translate from '../translate';
@ -25,7 +26,7 @@ function Connecting ({ className, style, value, t }: Props): React$Node {
// 'ui inverted page modals dimmer transition visible active' // 'ui inverted page modals dimmer transition visible active'
return ( return (
<div <div
className={['apps--Connecting', className].join(' ')} className={classes('apps--Connecting', className)}
style={style} style={style}
> >
<div className='apps--Connecting-text'> <div className='apps--Connecting-text'>

View File

@ -11,29 +11,28 @@ import './Content.css';
import React from 'react'; import React from 'react';
import { withRouter } from 'react-router'; import { withRouter } from 'react-router';
import classes from '@polkadot/ui-app/src/util/classes';
import routing from '../routing'; import routing from '../routing';
import translate from '../translate';
type Props = I18nProps & { type Props = I18nProps & {
location: Location location: Location
}; };
function Content ({ className, location, style }: Props): React$Node { function Content ({ children, className, location, style }: Props): React$Node {
const app = location.pathname.slice(1) || routing.default; const app = location.pathname.slice(1) || routing.default;
const { Component } = routing.routes.find((route) =>
route && route.name === app
) || routing.unknown;
return ( return (
<div <div
className={['apps--Content', className].join(' ')} className={classes('apps--Content', className)}
style={style} style={style}
> >
<iframe <Component />
className='apps--Content-Frame'
src={`index.html?app=${app}`}
title={app}
/>
</div> </div>
); );
} }
export default translate(
withRouter(Content) export default withRouter(Content);
);

View File

@ -9,6 +9,8 @@ import './NotFound.css';
import React from 'react'; import React from 'react';
import classes from '@polkadot/ui-app/src/util/classes';
import translate from '../translate'; import translate from '../translate';
type Props = I18nProps & {}; type Props = I18nProps & {};
@ -16,7 +18,7 @@ type Props = I18nProps & {};
function NotFound ({ className, style, t }: Props): React$Node { function NotFound ({ className, style, t }: Props): React$Node {
return ( return (
<div <div
className={['apps--NotFound', className].join(' ')} className={classes('apps--NotFound', className)}
style={style} style={style}
> >
{t('notfound.error', { {t('notfound.error', {

View File

@ -11,6 +11,7 @@ import React from 'react';
import Icon from '@polkadot/ui-app/src/Icon'; import Icon from '@polkadot/ui-app/src/Icon';
import Menu from '@polkadot/ui-app/src/Menu'; import Menu from '@polkadot/ui-app/src/Menu';
import classes from '@polkadot/ui-app/src/util/classes';
import routing from '../routing'; import routing from '../routing';
import translate from '../translate'; import translate from '../translate';
@ -21,7 +22,7 @@ type Props = I18nProps & {};
function SideBar ({ className, style, t }: Props): React$Node { function SideBar ({ className, style, t }: Props): React$Node {
return ( return (
<div <div
className={['apps--SideBar', className].join(' ')} className={classes('apps--SideBar', className)}
style={style} style={style}
> >
<Menu <Menu

View File

@ -6,22 +6,5 @@
import createApp from '@polkadot/ui-app/src'; import createApp from '@polkadot/ui-app/src';
import App from './App'; import App from './App';
import NotFound from './NotFound';
import routing from './routing';
import urlParams from './urlParams';
createApp((() => { createApp(App);
const { app } = urlParams();
if (app) {
const route = routing.routes.find((route) =>
route && route.name === app
);
return route
? route.component
: NotFound;
}
return App;
})());

View File

@ -9,7 +9,7 @@ import Accounts from '@polkadot/app-accounts/src';
export default ([ export default ([
{ {
component: Accounts, Component: Accounts,
i18n: { i18n: {
defaultValue: 'Accounts' defaultValue: 'Accounts'
}, },

View File

@ -9,7 +9,7 @@ import Addresses from '@polkadot/app-addresses/src';
export default ([ export default ([
{ {
component: Addresses, Component: Addresses,
i18n: { i18n: {
defaultValue: 'Addresses' defaultValue: 'Addresses'
}, },

View File

@ -9,7 +9,7 @@ import Explorer from '@polkadot/app-explorer/src';
export default ([ export default ([
{ {
component: Explorer, Component: Explorer,
i18n: { i18n: {
defaultValue: 'Explorer' defaultValue: 'Explorer'
}, },

View File

@ -9,7 +9,7 @@ import Extrinsics from '@polkadot/app-extrinsics/src';
export default ([ export default ([
{ {
component: Extrinsics, Component: Extrinsics,
i18n: { i18n: {
defaultValue: 'Extrinsics' defaultValue: 'Extrinsics'
}, },

View File

@ -12,11 +12,14 @@ import extrinsics from './extrinsics';
// import home from './home'; // import home from './home';
// import settings from './settings'; // import settings from './settings';
import storage from './storage'; import storage from './storage';
import toolbox from './toolbox';
import unknown from './unknown';
import vanitygen from './vanitygen'; import vanitygen from './vanitygen';
export default ({ export default ({
default: 'explorer', default: 'explorer',
routes: [].concat( routes: [].concat(
explorer, extrinsics, storage, null, accounts, addresses, vanitygen explorer, extrinsics, storage, toolbox, null, accounts, addresses, vanitygen
) ),
unknown
}: Routing); }: Routing);

View File

@ -9,7 +9,7 @@ import Storage from '@polkadot/app-storage/src';
export default ([ export default ([
{ {
component: Storage, Component: Storage,
i18n: { i18n: {
defaultValue: 'Storage' defaultValue: 'Storage'
}, },

View File

@ -0,0 +1,21 @@
// 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 { Routes } from '../types';
import Toolbox from '@polkadot/app-toolbox/src';
export default ([
{
Component: Toolbox,
i18n: {
defaultValue: 'Toolbox'
},
icon: 'configure',
isExact: false,
isHidden: false,
name: 'toolbox'
}
]: Routes);

View File

@ -0,0 +1,19 @@
// 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 { Route } from '../types';
import NotFound from '../NotFound';
export default ({
Component: NotFound,
i18n: {
defaultValue: 'Not found'
},
icon: 'error',
isExact: false,
isHidden: true,
name: 'unknown'
}: Route);

View File

@ -9,7 +9,7 @@ import Vanity from '@polkadot/app-vanitygen/src';
export default ([ export default ([
{ {
component: Vanity, Component: Vanity,
i18n: { i18n: {
defaultValue: 'Vanity' defaultValue: 'Vanity'
}, },

View File

@ -4,9 +4,11 @@
// @flow // @flow
export type Route = { export type Route = {
component: React$ComponentType<*>, // flowlint-next-line unclear-type:off
Component: React$ComponentType<any>,
i18n: I18Next$Translate$Config, i18n: I18Next$Translate$Config,
icon: React$ComponentType<*> | string, // flowlint-next-line unclear-type:off
icon: React$ComponentType<any> | string,
isExact: boolean, isExact: boolean,
isHidden: boolean, isHidden: boolean,
name: string, name: string,
@ -17,5 +19,6 @@ export type Routes = Array<Route | null>;
export type Routing = { export type Routing = {
default: string, default: string,
routes: Routes routes: Routes,
unknown: Route
} }

View File

@ -1,24 +0,0 @@
// 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
type Params = {
[string]: string
};
export default function urlParams (): Params {
if (window.location.search.indexOf('?') !== 0) {
return {};
}
const parts = window.location.search.slice(1).split('&');
return parts.reduce((params, param) => {
const [name, value] = param.split('=');
params[name] = value;
return params;
}, {});
}

View File

@ -1,6 +1,6 @@
{ {
"name": "@polkadot/ui-app", "name": "@polkadot/ui-app",
"version": "0.4.12", "version": "0.5.0",
"main": "index.js", "main": "index.js",
"repository": "https://github.com/polkadot-js/apps.git", "repository": "https://github.com/polkadot-js/apps.git",
"author": "Jaco Greeff <jacogr@gmail.com>", "author": "Jaco Greeff <jacogr@gmail.com>",
@ -11,13 +11,14 @@
"test": "jest --coverage" "test": "jest --coverage"
}, },
"dependencies": { "dependencies": {
"@polkadot/extrinsics-substrate": "^0.13.8", "@polkadot/extrinsics-substrate": "^0.13.10",
"@polkadot/params": "^0.13.8", "@polkadot/params": "^0.13.10",
"@polkadot/storage-substrate": "^0.13.8", "@polkadot/primitives": "^0.13.10",
"@polkadot/ui-keyring": "^0.4.12", "@polkadot/storage-substrate": "^0.13.10",
"@polkadot/ui-react": "^0.11.9", "@polkadot/ui-keyring": "^0.5.0",
"@polkadot/ui-react-rx": "^0.11.9", "@polkadot/ui-react": "^0.11.10",
"@polkadot/util": "^0.19.6", "@polkadot/ui-react-rx": "^0.11.10",
"@polkadot/util": "^0.19.7",
"i18next": "^11.1.1", "i18next": "^11.1.1",
"i18next-browser-languagedetector": "^2.2.0", "i18next-browser-languagedetector": "^2.2.0",
"i18next-xhr-backend": "^1.5.1", "i18next-xhr-backend": "^1.5.1",
@ -29,8 +30,5 @@
"semantic-ui-css": "^2.3.1", "semantic-ui-css": "^2.3.1",
"semantic-ui-react": "^0.79.1", "semantic-ui-react": "^0.79.1",
"store": "^2.0.12" "store": "^2.0.12"
},
"devDepependencies": {
"@polkadot/primitives": "^0.12.6"
} }
} }

View File

@ -7,12 +7,14 @@ import type { BareProps } from '../types';
import React from 'react'; import React from 'react';
import classes from '../util/classes';
type Props = BareProps; type Props = BareProps;
function ButtonDivider ({ className, style }: Props): React$Node { function ButtonDivider ({ className, style }: Props): React$Node {
return ( return (
<div <div
className={['ui button compact mini basic', className].join(' ')} className={classes('ui button compact mini basic', className)}
style={style} style={style}
/> />
); );

View File

@ -8,6 +8,7 @@ import type { BareProps } from '../types';
import React from 'react'; import React from 'react';
import SUIButton from 'semantic-ui-react/dist/es/elements/Button'; import SUIButton from 'semantic-ui-react/dist/es/elements/Button';
import classes from '../util/classes';
import Divider from './Divider'; import Divider from './Divider';
type Props = BareProps & { type Props = BareProps & {
@ -17,7 +18,7 @@ type Props = BareProps & {
function ButtonGroup ({ children, className, style }: Props): React$Node { function ButtonGroup ({ children, className, style }: Props): React$Node {
return ( return (
<div <div
className={['ui--Button-Group', className].join(' ')} className={classes('ui--Button-Group', className)}
style={style} style={style}
> >
<SUIButton.Group> <SUIButton.Group>

View File

@ -16,7 +16,7 @@ type Props = BareProps & {
isCircular?: boolean, isCircular?: boolean,
isPrimary?: boolean, isPrimary?: boolean,
size?: Button$Sizes, size?: Button$Sizes,
value?: string value?: mixed
} }
export default function CopyButton ({ className, icon = 'copy', isCircular = true, isPrimary = true, size = 'tiny', style, value }: Props): React$Node { export default function CopyButton ({ className, icon = 'copy', isCircular = true, isPrimary = true, size = 'tiny', style, value }: Props): React$Node {

View File

@ -8,6 +8,7 @@ import type { BareProps } from './types';
import React from 'react'; import React from 'react';
import SUIDropdown from 'semantic-ui-react/dist/es/modules/Dropdown'; import SUIDropdown from 'semantic-ui-react/dist/es/modules/Dropdown';
import classes from './util/classes';
import Labelled from './Labelled'; import Labelled from './Labelled';
type Props = BareProps & { type Props = BareProps & {
@ -17,8 +18,10 @@ type Props = BareProps & {
label?: React$Node, label?: React$Node,
// flowlint-next-line unclear-type:off // flowlint-next-line unclear-type:off
onChange: (value: any) => void, onChange: (value: any) => void,
onSearch?: (filteredOptions: Array<*>, query: string) => Array<*>, // flowlint-next-line unclear-type:off
options: Array<*>, onSearch?: (filteredOptions: Array<any>, query: string) => Array<any>,
// flowlint-next-line unclear-type:off
options: Array<any>,
// flowlint-next-line unclear-type:off // flowlint-next-line unclear-type:off
transform?: (value: any) => any, transform?: (value: any) => any,
value?: mixed, value?: mixed,
@ -36,7 +39,7 @@ export default class Dropdown extends React.PureComponent<Props> {
return ( return (
<Labelled <Labelled
className={['ui--Dropdown', className].join(' ')} className={classes('ui--Dropdown', className)}
label={label} label={label}
style={style} style={style}
withLabel={withLabel} withLabel={withLabel}
@ -55,7 +58,8 @@ export default class Dropdown extends React.PureComponent<Props> {
); );
} }
onChange = (event: SyntheticEvent<*>, { value }: SUIEvent): void => { // flowlint-next-line unclear-type:off
onChange = (event: SyntheticEvent<any>, { value }: SUIEvent): void => {
const { onChange, transform } = this.props; const { onChange, transform } = this.props;
onChange( onChange(

View File

@ -8,6 +8,8 @@ import type { BareProps } from './types';
import React from 'react'; import React from 'react';
import SUIInput from 'semantic-ui-react/dist/es/elements/Input'; import SUIInput from 'semantic-ui-react/dist/es/elements/Input';
import isUndefined from '@polkadot/util/is/undefined';
import Labelled from './Labelled'; import Labelled from './Labelled';
type Input$Type = 'number' | 'password' | 'text'; type Input$Type = 'number' | 'password' | 'text';
@ -15,9 +17,11 @@ type Input$Type = 'number' | 'password' | 'text';
type Props = BareProps & { type Props = BareProps & {
children?: React$Node, children?: React$Node,
defaultValue?: mixed, defaultValue?: mixed,
icon?: React$Node,
isAction?: boolean, isAction?: boolean,
isDisabled?: boolean, isDisabled?: boolean,
isError?: boolean, isError?: boolean,
isHidden?: boolean,
label?: React$Node, label?: React$Node,
max?: mixed, max?: mixed,
min?: mixed, min?: mixed,
@ -46,7 +50,7 @@ export default class Input extends React.PureComponent<Props, State> {
}; };
render (): React$Node { render (): React$Node {
const { children, className, defaultValue, isAction = false, isDisabled = false, isError = false, label, max, min, placeholder, style, type = 'text', value, withLabel } = this.props; const { children, className, defaultValue, icon, isAction = false, isDisabled = false, isError = false, isHidden = false, label, max, min, placeholder, style, type = 'text', value, withLabel } = this.props;
const { name } = this.state; const { name } = this.state;
return ( return (
@ -60,7 +64,14 @@ export default class Input extends React.PureComponent<Props, State> {
action={isAction} action={isAction}
defaultValue={defaultValue} defaultValue={defaultValue}
disabled={isDisabled} disabled={isDisabled}
id={name}
iconPosition={
isUndefined(icon)
? void 0
: 'left'
}
error={isError} error={isError}
hidden={isHidden}
max={max} max={max}
min={min} min={min}
name={name} name={name}
@ -69,14 +80,22 @@ export default class Input extends React.PureComponent<Props, State> {
type={type} type={type}
value={value} value={value}
> >
<input /> <input
autoComplete={
type === 'password'
? 'new-password'
: 'off'
}
/>
{icon}
{children} {children}
</SUIInput> </SUIInput>
</Labelled> </Labelled>
); );
} }
onChange = (event: SyntheticEvent<*>, { value }: SUIEvent): void => { // flowlint-next-line unclear-type:off
onChange = (event: SyntheticEvent<any>, { value }: SUIEvent): void => {
this.props.onChange(value); this.props.onChange(value);
} }
} }

View File

@ -8,8 +8,8 @@
width: 100%; width: 100%;
} }
.ui--InputAddress input.search { .ui--InputAddress .ui.search.selection.dropdown > input.search {
margin-left: 3rem; padding-left: 4rem;
} }
.flag--hideAddress .ui--KeyPair .ui--KeyPair-address { .flag--hideAddress .ui--KeyPair .ui--KeyPair-address {

View File

@ -15,6 +15,7 @@ import createOptionHeader from '@polkadot/ui-keyring/src/options/header';
import addressDecode from '@polkadot/util-keyring/address/decode'; import addressDecode from '@polkadot/util-keyring/address/decode';
import Dropdown from '../Dropdown'; import Dropdown from '../Dropdown';
import classes from '../util/classes';
import addressToAddress from './addressToAddress'; import addressToAddress from './addressToAddress';
type Props = BareProps & { type Props = BareProps & {
@ -68,7 +69,7 @@ export default class InputAddress extends React.Component<Props, State> {
return ( return (
<Dropdown <Dropdown
className={['ui--InputAddress', hideAddress ? 'flag--hideAddress' : '', className].join(' ')} className={classes('ui--InputAddress', hideAddress ? 'flag--hideAddress' : '', className)}
defaultValue={defaultValue} defaultValue={defaultValue}
isError={isError} isError={isError}
label={label} label={label}

View File

@ -11,6 +11,7 @@ import React from 'react';
import extrinsics from '@polkadot/extrinsics-substrate'; import extrinsics from '@polkadot/extrinsics-substrate';
import Dropdown from '../Dropdown'; import Dropdown from '../Dropdown';
import classes from '../util/classes';
import translate from '../translate'; import translate from '../translate';
import createOptions from './options/method'; import createOptions from './options/method';
@ -36,7 +37,7 @@ function SelectMethod ({ className, isError, label = '', onChange, style, t, typ
return ( return (
<Dropdown <Dropdown
className={['ui--DropdownLinked-Items', className].join(' ')} className={classes('ui--DropdownLinked-Items', className)}
isError={isError} isError={isError}
label={label || t('input.extrinsic.method', { label={label || t('input.extrinsic.method', {
defaultValue: 'with the extrinsic' defaultValue: 'with the extrinsic'

View File

@ -9,6 +9,7 @@ import type { I18nProps } from '../types';
import React from 'react'; import React from 'react';
import Dropdown from '../Dropdown'; import Dropdown from '../Dropdown';
import classes from '../util/classes';
import translate from '../translate'; import translate from '../translate';
import createOptions from './options/section'; import createOptions from './options/section';
@ -27,7 +28,7 @@ function SelectSection ({ className, defaultValue, isError, label = '', onChange
return ( return (
<Dropdown <Dropdown
className={['ui--DropdownLinked-Sections', className].join(' ')} className={classes('ui--DropdownLinked-Sections', className)}
defaultValue={defaultValue} defaultValue={defaultValue}
isError={isError} isError={isError}
label={label || t('input.extrinsic.section', { label={label || t('input.extrinsic.section', {

View File

@ -13,6 +13,7 @@ import './InputExtrinsic.css';
import React from 'react'; import React from 'react';
import map from '@polkadot/extrinsics-substrate'; import map from '@polkadot/extrinsics-substrate';
import classes from '../util/classes';
import translate from '../translate'; import translate from '../translate';
import SelectMethod from './SelectMethod'; import SelectMethod from './SelectMethod';
import SelectSection from './SelectSection'; import SelectSection from './SelectSection';
@ -50,7 +51,7 @@ class InputExtrinsic extends React.PureComponent<Props, State> {
return ( return (
<div <div
className={['ui--DropdownLinked', 'ui--row', className].join(' ')} className={classes('ui--DropdownLinked', 'ui--row', className)}
style={style} style={style}
> >
<SelectSection <SelectSection

View File

@ -10,7 +10,7 @@ import React from 'react';
import map from '@polkadot/extrinsics-substrate'; import map from '@polkadot/extrinsics-substrate';
// flowlint-next-line unclear-type:off // flowlint-next-line unclear-type:off
export default function createOptions (sectionName: any, type: 'private' | 'public'): Array<*> { export default function createOptions (sectionName: any, type: 'private' | 'public'): Array<any> {
const section = map[(sectionName: ExtrinsicSectionName)]; const section = map[(sectionName: ExtrinsicSectionName)];
if (!section) { if (!section) {

View File

@ -5,7 +5,8 @@
import map from '@polkadot/extrinsics-substrate'; import map from '@polkadot/extrinsics-substrate';
export default function createOptions (type: 'private' | 'public'): Array<*> { // flowlint-next-line unclear-type:off
export default function createOptions (type: 'private' | 'public'): Array<any> {
return Object return Object
.keys(map) .keys(map)
.sort() .sort()

View File

@ -11,6 +11,7 @@ import React from 'react';
import map from '@polkadot/storage-substrate/keys'; import map from '@polkadot/storage-substrate/keys';
import Dropdown from '../Dropdown'; import Dropdown from '../Dropdown';
import classes from '../util/classes';
import translate from '../translate'; import translate from '../translate';
import createOptions from './options/key'; import createOptions from './options/key';
@ -35,7 +36,7 @@ function SelectKey ({ className, isError, label = '', onChange, style, t, value:
return ( return (
<Dropdown <Dropdown
className={['ui--DropdownLinked-Items', className].join(' ')} className={classes('ui--DropdownLinked-Items', className)}
isError={isError} isError={isError}
label={label || t('input.storage.key', { label={label || t('input.storage.key', {
defaultValue: 'with storage key' defaultValue: 'with storage key'

View File

@ -9,6 +9,7 @@ import type { I18nProps } from '../types';
import React from 'react'; import React from 'react';
import Dropdown from '../Dropdown'; import Dropdown from '../Dropdown';
import classes from '../util/classes';
import translate from '../translate'; import translate from '../translate';
import createOptions from './options/section'; import createOptions from './options/section';
@ -26,7 +27,7 @@ const options = createOptions();
function SelectSection ({ className, defaultValue, isError, label, onChange, style, t, value: { section }, withLabel }: Props): React$Node { function SelectSection ({ className, defaultValue, isError, label, onChange, style, t, value: { section }, withLabel }: Props): React$Node {
return ( return (
<Dropdown <Dropdown
className={['ui--DropdownLinked-Sections', className].join(' ')} className={classes('ui--DropdownLinked-Sections', className)}
defaultValue={defaultValue} defaultValue={defaultValue}
isError={isError} isError={isError}
label={label || t('input.storage.section', { label={label || t('input.storage.section', {

View File

@ -11,8 +11,10 @@ import type { I18nProps } from '../types';
import '../InputExtrinsic/InputExtrinsic.css'; import '../InputExtrinsic/InputExtrinsic.css';
import React from 'react'; import React from 'react';
import map from '@polkadot/storage-substrate/keys'; import map from '@polkadot/storage-substrate/keys';
import classes from '../util/classes';
import translate from '../translate'; import translate from '../translate';
import SelectKey from './SelectKey'; import SelectKey from './SelectKey';
import SelectSection from './SelectSection'; import SelectSection from './SelectSection';
@ -48,7 +50,7 @@ class InputStorage extends React.PureComponent<Props, State> {
return ( return (
<div <div
className={['ui--DropdownLinked', 'ui--row', className].join(' ')} className={classes('ui--DropdownLinked', 'ui--row', className)}
style={style} style={style}
> >
<SelectSection <SelectSection

View File

@ -10,7 +10,7 @@ import React from 'react';
import map from '@polkadot/storage-substrate/keys'; import map from '@polkadot/storage-substrate/keys';
// flowlint-next-line unclear-type:off // flowlint-next-line unclear-type:off
export default function createOptions (sectionName: any): Array<*> { export default function createOptions (sectionName: any): Array<any> {
const section = map[(sectionName: StateDb$SectionNames)]; const section = map[(sectionName: StateDb$SectionNames)];
if (!section) { if (!section) {

View File

@ -5,7 +5,8 @@
import map from '@polkadot/storage-substrate/keys'; import map from '@polkadot/storage-substrate/keys';
export default function createOptions (): Array<*> { // flowlint-next-line unclear-type:off
export default function createOptions (): Array<any> {
return Object return Object
.keys(map) .keys(map)
.sort() .sort()

View File

@ -8,7 +8,10 @@ import type { BareProps } from './types';
import React from 'react'; import React from 'react';
import Label from 'semantic-ui-react/dist/es/elements/Label'; import Label from 'semantic-ui-react/dist/es/elements/Label';
import classes from './util/classes';
type Props = BareProps & { type Props = BareProps & {
isHidden?: boolean,
// flowlint-next-line unclear-type:off // flowlint-next-line unclear-type:off
label?: any, label?: any,
children: React$Node, children: React$Node,
@ -19,10 +22,14 @@ const defaultLabel: React$Node = (
<div>&nbsp;</div> <div>&nbsp;</div>
); );
export default function Labelled ({ className, children, label = defaultLabel, style, withLabel = true }: Props): React$Node { export default function Labelled ({ className, children, isHidden = false, label = defaultLabel, style, withLabel = true }: Props): React$Node {
if (isHidden) {
return false;
}
return ( return (
<div <div
className={className} className={classes('ui--Labelled', className)}
style={style} style={style}
> >
{ {

View 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 { BareProps } from './types';
import React from 'react';
import CopyButton from './CopyButton';
import Labelled from './Labelled';
type Props = BareProps & {
children?: React$Node,
isHidden?: boolean,
label?: React$Node,
value?: mixed,
withCopy?: boolean,
withLabel?: boolean
};
export default function Output ({ className, children, isHidden, label, style, value, withCopy = false, withLabel }: Props): React$Node {
return (
<Labelled
className={className}
isHidden={isHidden}
label={label}
style={style}
withLabel={withLabel}
>
<div className='ui--output'>
{
// flowlint-next-line unclear-type:off
((value: any): React$Node)
}
{children}
{
withCopy
? (
<CopyButton className='ui--output-button' value={value} />
)
: null
}
</div>
</Labelled>
);
}

View File

@ -7,6 +7,8 @@ import type { BareProps } from '../../types';
import React from 'react'; import React from 'react';
import classes from '../../util/classes';
type Props = BareProps & { type Props = BareProps & {
children: React$Node children: React$Node
}; };
@ -14,7 +16,7 @@ type Props = BareProps & {
export default function Bare ({ children, className, style }: Props): React$Node { export default function Bare ({ children, className, style }: Props): React$Node {
return ( return (
<div <div
className={['ui--row', className].join(' ')} className={classes('ui--row', className)}
style={style} style={style}
> >
{children} {children}

View File

@ -8,6 +8,7 @@ import type { BareProps } from '@polkadot/ui-app/types';
import React from 'react'; import React from 'react';
import Dropzone from 'react-dropzone'; import Dropzone from 'react-dropzone';
import classes from '../../util/classes';
import translate from '../../translate'; import translate from '../../translate';
import Base from './Base'; import Base from './Base';
@ -41,7 +42,7 @@ class BytesFile extends React.PureComponent<Props, State> {
withLabel={withLabel} withLabel={withLabel}
> >
<Dropzone <Dropzone
className={['ui--Param-File', isError ? 'error' : '', className].join(' ')} className={classes('ui--Param-File', isError ? 'error' : '', className)}
disabled={isDisabled} disabled={isDisabled}
multiple={false} multiple={false}
onDrop={this.onDrop} onDrop={this.onDrop}

View File

@ -41,7 +41,8 @@ const components: ComponentMap = {
'VoteThreshold': VoteThreshold 'VoteThreshold': VoteThreshold
}; };
export default function findComponent (type: Param$Types, overrides?: ComponentMap = {}): React$ComponentType<*> | Array<React$ComponentType<*>> { // flowlint-next-line unclear-type:off
export default function findComponent (type: Param$Types, overrides?: ComponentMap = {}): React$ComponentType<any> | Array<React$ComponentType<any>> {
if (Array.isArray(type)) { if (Array.isArray(type)) {
return type return type
.map((type) => .map((type) =>

View File

@ -9,6 +9,7 @@ import type { BaseProps, ComponentMap, RawParam } from '../types';
import React from 'react'; import React from 'react';
import classes from '../../util/classes';
import translate from '../../translate'; import translate from '../../translate';
import typeToText from '../typeToText'; import typeToText from '../typeToText';
import findComponent from './findComponent'; import findComponent from './findComponent';
@ -28,7 +29,8 @@ type ComponentProps = BaseProps & {
}; };
type State = { type State = {
Components: React$ComponentType<*> | Array<React$ComponentType<*>> // flowlint-next-line unclear-type:off
Components: React$ComponentType<any> | Array<React$ComponentType<any>>
| null | null
} }
@ -60,7 +62,8 @@ class ParamComponent extends React.PureComponent<Props, State> {
: this.renderComponents(); : this.renderComponents();
} }
renderComponents = (_Components: React$ComponentType<*> | Array<React$ComponentType<*>> | null = this.state.Components, startIndex: string = '0', { name, type, options = {} } = this.props.value) => { // flowlint-next-line unclear-type:off
renderComponents = (_Components: React$ComponentType<any> | Array<React$ComponentType<any>> | null = this.state.Components, startIndex: string = '0', { name, type, options = {} } = this.props.value) => {
if (!_Components) { if (!_Components) {
return null; return null;
} }
@ -69,7 +72,7 @@ class ParamComponent extends React.PureComponent<Props, State> {
if (!Array.isArray(type)) { if (!Array.isArray(type)) {
// flowlint-next-line unclear-type:off // flowlint-next-line unclear-type:off
const Component = ((_Components: any): React$ComponentType<*>); const Component = ((_Components: any): React$ComponentType<any>);
return this.renderComponent(Component, startIndex, { return this.renderComponent(Component, startIndex, {
className, className,
@ -85,7 +88,7 @@ class ParamComponent extends React.PureComponent<Props, State> {
} }
// flowlint-next-line unclear-type:off // flowlint-next-line unclear-type:off
const Components = ((_Components: any): Array<React$ComponentType<*>>); const Components = ((_Components: any): Array<React$ComponentType<any>>);
return Components.map((Component, index) => { return Components.map((Component, index) => {
return this.renderComponents(Component, `${startIndex}-${index}`, { return this.renderComponents(Component, `${startIndex}-${index}`, {
@ -96,13 +99,14 @@ class ParamComponent extends React.PureComponent<Props, State> {
}); });
} }
renderComponent = (Component: React$ComponentType<*>, sub: string, props: ComponentProps): React$Node => { // flowlint-next-line unclear-type:off
renderComponent = (Component: React$ComponentType<any>, sub: string, props: ComponentProps): React$Node => {
const { className, index, onChange, style, value: { name, type, options = {} } } = props; const { className, index, onChange, style, value: { name, type, options = {} } } = props;
const text = typeToText(type); const text = typeToText(type);
return ( return (
<Component <Component
className={['ui--Param', className].join(' ')} className={classes('ui--Param', className)}
index={index} index={index}
key={`${name}:${text}:${index}}`} key={`${name}:${text}:${index}}`}
label={`${name}: ${text} (${index})`} label={`${name}: ${text} (${index})`}

View File

@ -11,6 +11,7 @@ import './Params.css';
import React from 'react'; import React from 'react';
import classes from '../util/classes';
import translate from '../translate'; import translate from '../translate';
import Param from './Param'; import Param from './Param';
import createValues from './values'; import createValues from './values';
@ -62,7 +63,7 @@ class Params extends React.PureComponent<Props, State> {
return ( return (
<div <div
className={['ui--Params', className].join(' ')} className={classes('ui--Params', className)}
style={style} style={style}
> >
<div className='ui--Params-Content'> <div className='ui--Params-Content'>

Some files were not shown because too many files have changed in this diff Show More