Fixes #103: Convert functional components to pure (#135)

* ui-signer pureComponentify

* ui-react pureCompify

* Status queue prop

* ui-app Button

* ui-app InputExtrinsic

* apps, app-rpc, ui-app, ui-react

* app-extrinsics, app-explorer, apps

* fixes for tslint

* more linter fixes

* Update index.tsx

* Update index.tsx

* Update Nonce.tsx

* Update index.tsx

* Update Results.tsx

* Update index.tsx

* Update Queries.tsx

* Update NodeInfo.tsx

* Update index.tsx

* Update Item.tsx

* style fixes

* TSLINTs
This commit is contained in:
YJ 2018-07-12 22:40:31 -07:00 committed by Jaco Greeff
parent 6a694f7c5b
commit 57800cdb83
31 changed files with 710 additions and 590 deletions

View File

@ -20,52 +20,55 @@ type Props = I18nProps & {
value?: Header
};
function BlockHeader ({ className, value, style }: Props) {
if (!value) {
return null;
}
class BlockHeader extends React.PureComponent<Props> {
render () {
const { className, value, style } = this.props;
if (!value) {
return null;
}
const hash = headerHash(value);
// tslint:disable-next-line:variable-name
const { extrinsicsRoot, number, parentHash, stateRoot } = value;
const hash = headerHash(value);
// tslint:disable-next-line:variable-name
const { extrinsicsRoot, number, parentHash, stateRoot } = value;
return (
<div
className={classes('explorer--BlockHeader', className)}
style={style}
>
<div className='number'>
<div>{numberFormat(number)}</div>
</div>
<div className='details'>
<div className='hash'>
{u8aToHex(hash)}
return (
<div
className={classes('explorer--BlockHeader', className)}
style={style}
>
<div className='number'>
<div>{numberFormat(number)}</div>
</div>
<div className='details'>
<div className='hash'>
{u8aToHex(hash)}
</div>
<table className='contains'>
<tbody>
<tr>
<td className='type'>parentHash</td>
<td className='hash'>
{u8aToHex(parentHash)}
</td>
</tr>
<tr>
<td className='type'>extrinsicsRoot</td>
<td className='hash'>
{u8aToHex(extrinsicsRoot)}
</td>
</tr>
<tr>
<td className='type'>stateRoot</td>
<td className='hash'>
{u8aToHex(stateRoot)}
</td>
</tr>
</tbody>
</table>
</div>
<table className='contains'>
<tbody>
<tr>
<td className='type'>parentHash</td>
<td className='hash'>
{u8aToHex(parentHash)}
</td>
</tr>
<tr>
<td className='type'>extrinsicsRoot</td>
<td className='hash'>
{u8aToHex(extrinsicsRoot)}
</td>
</tr>
<tr>
<td className='type'>stateRoot</td>
<td className='hash'>
{u8aToHex(stateRoot)}
</td>
</tr>
</tbody>
</table>
</div>
</div>
);
);
}
}
export default translate(BlockHeader);

View File

@ -17,22 +17,26 @@ import translate from './translate';
type Props = I18nProps & {};
function ExplorerApp ({ className, style, t }: Props) {
return (
<div
className={classes('explorer--App', className)}
style={style}
>
<BestNumber
className='explorer--BestNumber'
label={t('app.bestNumber', {
defaultValue: 'best #'
})}
/>
<BestHash />
<BlockHeaders />
</div>
);
class ExplorerApp extends React.PureComponent<Props> {
render () {
const { className, style, t } = this.props;
return (
<div
className={classes('explorer--App', className)}
style={style}
>
<BestNumber
className='explorer--BestNumber'
label={t('app.bestNumber', {
defaultValue: 'best #'
})}
/>
<BestHash />
<BlockHeaders />
</div>
);
}
}
export default translate(ExplorerApp);

View File

@ -17,22 +17,26 @@ type Props = BareProps & {
value?: Uint8Array
};
export default function Nonce ({ className, label, style, onChange, value }: Props) {
return (
<div
className={classes('ui--row', className)}
style={style}
>
<Labelled
className='small'
label={label}
export default class Nonce extends React.PureComponent<Props> {
render () {
const { className, label, style, onChange, value } = this.props;
return (
<div
className={classes('ui--row', className)}
style={style}
>
<RxNonce
className='ui disabled dropdown selection'
onChange={onChange}
params={value}
/>
</Labelled>
</div>
);
<Labelled
className='small'
label={label}
>
<RxNonce
className='ui disabled dropdown selection'
onChange={onChange}
params={value}
/>
</Labelled>
</div>
);
}
}

View File

@ -16,17 +16,21 @@ import Selection from './Selection';
type Props = BareProps;
export default function ExtrinsicsApp ({ className, style }: Props) {
return (
<div
className={classes('extrinsics--App', className)}
style={style}
>
<QueueConsumer>
{({ queueAdd }: QueueProps) => (
<Selection queueAdd={queueAdd} />
)}
</QueueConsumer>
</div>
);
export default class ExtrinsicsApp extends React.PureComponent<Props> {
render () {
const { className, style } = this.props;
return (
<div
className={classes('extrinsics--App', className)}
style={style}
>
<QueueConsumer>
{({ queueAdd }: QueueProps) => (
<Selection queueAdd={queueAdd} />
)}
</QueueConsumer>
</div>
);
}
}

View File

@ -17,34 +17,38 @@ type Props = BareProps & {
queue: Array<QueueTx>
};
export default function Results ({ className, queue = [], style }: Props) {
const filtered = queue
.filter(({ error, result }) =>
!isUndefined(error) || !isUndefined(result)
)
.reverse();
export default class Results extends React.PureComponent<Props> {
render () {
const { className, queue = [], style } = this.props;
if (!filtered.length) {
return null;
const filtered = queue
.filter(({ error, result }) =>
!isUndefined(error) || !isUndefined(result)
)
.reverse();
if (!filtered.length) {
return null;
}
return (
<div
className={classes('rpc--Results', className)}
style={style}
>
{filtered.map(({ error, id, result, rpc: { section, name } }) => (
<Output
isError={!!error}
key={id}
label={`${id}: ${section}.${name}`}
value={
error
? error.message
: resultToText(result)
}
/>
))}
</div>
);
}
return (
<div
className={classes('rpc--Results', className)}
style={style}
>
{filtered.map(({ error, id, result, rpc: { section, name } }) => (
<Output
isError={!!error}
key={id}
label={`${id}: ${section}.${name}`}
value={
error
? error.message
: resultToText(result)
}
/>
))}
</div>
);
}

View File

@ -17,24 +17,28 @@ import Selection from './Selection';
type Props = BareProps & {};
export default function RpcApp ({ className, style }: Props) {
return (
<div
className={classes('rpc--App', className)}
style={style}
>
<QueueConsumer>
{({ queue, queueAdd }: QueueProps) => [
<Selection
key='add'
queueAdd={queueAdd}
/>,
<Results
key='results'
queue={queue}
/>
]}
</QueueConsumer>
</div>
);
export default class RpcApp extends React.PureComponent<Props> {
render () {
const { className, style } = this.props;
return (
<div
className={classes('rpc--App', className)}
style={style}
>
<QueueConsumer>
{({ queue, queueAdd }: QueueProps) => [
<Selection
key='add'
queueAdd={queueAdd}
/>,
<Results
key='results'
queue={queue}
/>
]}
</QueueConsumer>
</div>
);
}
}

View File

@ -17,25 +17,29 @@ type Props = I18nProps & {
value?: Array<StorageQuery>
};
function Queries ({ className, onRemove, style, value }: Props) {
if (!value || !value.length) {
return null;
}
class Queries extends React.PureComponent<Props> {
render () {
const { className, onRemove, style, value } = this.props;
return (
<div
className={classes('storage--Queries', className)}
style={style}
>
{value.map((query) =>
<Query
key={query.id}
onRemove={onRemove}
value={query}
/>
)}
</div>
);
if (!value || !value.length) {
return null;
}
return (
<div
className={classes('storage--Queries', className)}
style={style}
>
{value.map((query) =>
<Query
key={query.id}
onRemove={onRemove}
value={query}
/>
)}
</div>
);
}
}
export default translate(Queries);

View File

@ -21,24 +21,28 @@ function updateTestInfo (chain?: string) {
keyring.setTestMode(isTestChain(chain));
}
function NodeInfo ({ className, style, t }: Props) {
return (
<div className={classes('apps--NodeInfo', className)}>
<Chain
label={t('info.chain', {
defaultValue: 'chain: '
class NodeInfo extends React.PureComponent<Props> {
render () {
const { className, style, t } = this.props;
return (
<div className={classes('apps--NodeInfo', className)} style={style}>
<Chain
label={t('info.chain', {
defaultValue: 'chain: '
})}
onChange={updateTestInfo}
/>
<NodeName label={t('info.name', {
defaultValue: 'client: '
})}
onChange={updateTestInfo}
/>
<NodeName label={t('info.name', {
defaultValue: 'client: '
})}
/>
<NodeVersion label={t('info.name', {
defaultValue: 'version: '
})} />
</div>
);
/>
<NodeVersion label={t('info.name', {
defaultValue: 'version: '
})} />
</div>
);
}
}
export default translate(NodeInfo);

View File

@ -14,17 +14,21 @@ import translate from '../translate';
type Props = I18nProps & {};
function NotFound ({ className, style, t }: Props) {
return (
<div
className={classes('apps--NotFound', className)}
style={style}
>
{t('notfound.error', {
defaultValue: 'ERROR: You have tried to access an application that does not exist'
})}
</div>
);
class NotFound extends React.PureComponent<Props> {
render () {
const { className, style, t } = this.props;
return (
<div
className={classes('apps--NotFound', className)}
style={style}
>
{t('notfound.error', {
defaultValue: 'ERROR: You have tried to access an application that does not exist'
})}
</div>
);
}
}
export default translate(NotFound);

View File

@ -17,17 +17,21 @@ type Props = I18nProps & {
route: Route
};
export default function Item ({ route: { i18n, icon, isExact, name, path = '' }, t }: Props) {
return (
<Menu.Item className='apps--SideBar-Item'>
<NavLink
activeClassName='apps--SideBar-Item-NavLink-active'
className='apps--SideBar-Item-NavLink'
exact={isExact}
to={path || `/${name}`}
>
<Icon name={icon} /> {t(`sidebar.${name}`, i18n)}
</NavLink>
</Menu.Item>
);
export default class Item extends React.PureComponent<Props> {
render () {
const { route: { i18n, icon, isExact, name, path = '' }, t } = this.props;
return (
<Menu.Item className='apps--SideBar-Item'>
<NavLink
activeClassName='apps--SideBar-Item-NavLink-active'
className='apps--SideBar-Item-NavLink'
exact={isExact}
to={path || `/${name}`}
>
<Icon name={icon} /> {t(`sidebar.${name}`, i18n)}
</NavLink>
</Menu.Item>
);
}
}

View File

@ -20,51 +20,55 @@ type Props = I18nProps & {
children?: React.ReactNode
};
function SideBar ({ children, className, style, t }: Props) {
return (
<div
className={classes('apps--SideBar', className)}
style={style}
>
<Menu
secondary
vertical
class SideBar extends React.PureComponent<Props> {
render () {
const { children, className, style, t } = this.props;
return (
<div
className={classes('apps--SideBar', className)}
style={style}
>
{
routing.routes
.filter((route) =>
!route || !route.isHidden
)
.map((route, index) => (
route
? (
<Item
key={route.name}
t={t}
route={route}
/>
)
: (
<Menu.Divider
hidden
key={index}
/>
)
))
}
<Menu.Divider hidden />
<Menu.Item className='apps--SideBar-Item'>
<a
className='apps--SideBar-Item-NavLink'
href='https://github.com/polkadot-js/apps'>
<Icon name='github' /> GitHub
</a>
</Menu.Item>
<Menu.Divider hidden />
{children}
</Menu>
</div>
);
<Menu
secondary
vertical
>
{
routing.routes
.filter((route) =>
!route || !route.isHidden
)
.map((route, index) => (
route
? (
<Item
key={route.name}
t={t}
route={route}
/>
)
: (
<Menu.Divider
hidden
key={index}
/>
)
))
}
<Menu.Divider hidden />
<Menu.Item className='apps--SideBar-Item'>
<a
className='apps--SideBar-Item-NavLink'
href='https://github.com/polkadot-js/apps'>
<Icon name='github' /> GitHub
</a>
</Menu.Item>
<Menu.Divider hidden />
{children}
</Menu>
</div>
);
}
}
export default translate(SideBar);

View File

@ -8,13 +8,15 @@ import React from 'react';
import classes from '../util/classes';
function ButtonDivider ({ className, style }: DividerProps) {
return (
<div
className={classes('ui button compact mini basic', className)}
style={style}
/>
);
}
export default class ButtonDivider extends React.Component<DividerProps> {
render () {
const { className, style } = this.props;
export default ButtonDivider;
return (
<div
className={classes('ui button compact mini basic', className)}
style={style}
/>
);
}
}

View File

@ -11,18 +11,23 @@ import Button from '@polkadot/ui-app/Button';
import classes from '../util/classes';
import Divider from './Divider';
function ButtonGroup ({ children, className, style }: GroupProps) {
return (
<div
className={classes('ui--Button-Group', className)}
style={style}
>
<SUIButton.Group>
<Button.Group.Divider style={{ padding: '0em' }} />
{children}
</SUIButton.Group>
</div>
);
// ({ children, className, style }: GroupProps)
class ButtonGroup extends React.PureComponent<GroupProps> {
render () {
const { children, className, style } = this.props;
return (
<div
className={classes('ui--Button-Group', className)}
style={style}
>
<SUIButton.Group>
<Button.Group.Divider style={{ padding: '0em' }} />
{children}
</SUIButton.Group>
</div>
);
}
}
(ButtonGroup as GroupType).Divider = Divider;

View File

@ -15,20 +15,24 @@ type Props = I18nProps & {
text?: string
};
function ButtonOr ({ className, style, t, text }: Props) {
return (
<SUIButton.Or
className={className}
style={style}
text={
isUndefined(text)
? t('button.or', {
defaultValue: 'or'
})
: text
}
/>
);
class ButtonOr extends React.PureComponent<Props> {
render () {
const { className, style, t, text } = this.props;
return (
<SUIButton.Or
className={className}
style={style}
text={
isUndefined(text)
? t('button.or', {
defaultValue: 'or'
})
: text
}
/>
);
}
}
export default translate(ButtonOr);

View File

@ -15,31 +15,35 @@ import Divider from './Divider';
import Group from './Group';
import Or from './Or';
function Button ({ children, className, floated, icon, isBasic = false, isCircular = false, isDisabled = false, isNegative = false, isPrimary = false, onClick, size, style, text }: ButtonProps) {
const props = {
basic: isBasic,
circular: isCircular,
className,
disabled: isDisabled,
floated,
icon,
negative: isNegative,
onClick,
primary: isPrimary,
size,
secondary: isBasic && !(isPrimary || isNegative),
style
};
class Button extends React.PureComponent<ButtonProps> {
render () {
const { children, className, floated, icon, isBasic = false, isCircular = false, isDisabled = false, isNegative = false, isPrimary = false, onClick, size, style, text } = this.props;
return isUndefined(text) && isUndefined(children)
? (
<SUIButton {...props} />
)
: (
<SUIButton {...props}>
{text}{children}
</SUIButton>
);
const props = {
basic: isBasic || false,
circular: isCircular,
className,
disabled: isDisabled,
floated,
icon,
negative: isNegative,
onClick,
primary: isPrimary,
size,
secondary: isBasic && !(isPrimary || isNegative || false),
style
};
return isUndefined(text) && isUndefined(children)
? (
<SUIButton {...props} />
)
: (
<SUIButton {...props}>
{text}{children}
</SUIButton>
);
}
}
(Button as ButtonType).Divider = Divider;

View File

@ -18,17 +18,21 @@ type Props = BareProps & {
value?: any
};
export default function CopyButton ({ className, icon = 'copy', isCircular = true, isPrimary = true, size = 'tiny', style, value }: Props) {
return (
<CopyToClipboard text={value}>
<Button
className={className}
icon={icon}
isCircular={isCircular}
isPrimary={isPrimary}
size={size}
style={style}
/>
</CopyToClipboard>
);
export default class CopyButton extends React.PureComponent<Props> {
render () {
const { className, icon = 'copy', isCircular = true, isPrimary = true, size = 'tiny', style, value } = this.props;
return (
<CopyToClipboard text={value}>
<Button
className={className}
icon={icon}
isCircular={isCircular}
isPrimary={isPrimary}
size={size}
style={style}
/>
</CopyToClipboard>
);
}
}

View File

@ -25,29 +25,35 @@ type Props = I18nProps & {
withLabel?: boolean
};
function SelectMethod ({ className, isError, label = '', onChange, options, style, t, type, value: { name, section }, withLabel }: Props) {
if (!options.length) {
return null;
// ({ className, isError, label = '', onChange, options, style, t, type, value: { name, section }, withLabel }: Props) {
class SelectMethod extends React.PureComponent<Props> {
render () {
const { className, isError, label = '', onChange, options, style, t, type, value: { name, section }, withLabel } = this.props;
if (!options.length) {
return null;
}
const transform = (name: Extrinsic$Sections): SectionItem<Extrinsics> =>
extrinsics[section][type][name];
return (
<Dropdown
className={classes('ui--DropdownLinked-Items', className)}
isError={isError}
label={label || t('input.extrinsic.method', {
defaultValue: 'with the extrinsic'
})}
onChange={onChange}
options={options}
style={style}
transform={transform}
value={name}
withLabel={withLabel}
/>
);
}
const transform = (name: Extrinsic$Sections): SectionItem<Extrinsics> =>
extrinsics[section][type][name];
return (
<Dropdown
className={classes('ui--DropdownLinked-Items', className)}
isError={isError}
label={label || t('input.extrinsic.method', {
defaultValue: 'with the extrinsic'
})}
onChange={onChange}
options={options}
style={style}
transform={transform}
value={name}
withLabel={withLabel}
/>
);
}
export default translate(SelectMethod);

View File

@ -23,22 +23,26 @@ type Props = I18nProps & {
withLabel?: boolean
};
function SelectSection ({ className, defaultValue, isError, label = '', onChange, options, style, t, value: { section }, withLabel }: Props) {
return (
<Dropdown
className={classes('ui--DropdownLinked-Sections', className)}
defaultValue={defaultValue}
isError={isError}
label={label || t('input.extrinsic.section', {
defaultValue: 'from extrinsic section'
})}
onChange={onChange}
options={options}
style={style}
value={section}
withLabel={withLabel}
/>
);
class SelectSection extends React.PureComponent<Props> {
render () {
const { className, defaultValue, isError, label = '', onChange, options, style, t, value: { section }, withLabel } = this.props;
return (
<Dropdown
className={classes('ui--DropdownLinked-Sections', className)}
defaultValue={defaultValue}
isError={isError}
label={label || t('input.extrinsic.section', {
defaultValue: 'from extrinsic section'
})}
onChange={onChange}
options={options}
style={style}
value={section}
withLabel={withLabel}
/>
);
}
}
export default translate(SelectSection);

View File

@ -24,29 +24,33 @@ type Props = I18nProps & {
withLabel?: boolean
};
function SelectMethod ({ className, isError, label = '', onChange, options, style, t, value: { name, section }, withLabel }: Props) {
if (!options.length) {
return null;
class SelectMethod extends React.PureComponent<Props> {
render () {
const { className, isError, label = '', onChange, options, style, t, value: { name, section }, withLabel } = this.props;
if (!options.length) {
return null;
}
const transform = (name: Interface$Sections): SectionItem<Interfaces> =>
map[section].public[name];
return (
<Dropdown
className={classes('ui--DropdownLinked-Items', className)}
isError={isError}
label={label || t('input.rpc.method', {
defaultValue: 'with method name'
})}
onChange={onChange}
options={options}
style={style}
transform={transform}
value={name}
withLabel={withLabel}
/>
);
}
const transform = (name: Interface$Sections): SectionItem<Interfaces> =>
map[section].public[name];
return (
<Dropdown
className={classes('ui--DropdownLinked-Items', className)}
isError={isError}
label={label || t('input.rpc.method', {
defaultValue: 'with method name'
})}
onChange={onChange}
options={options}
style={style}
transform={transform}
value={name}
withLabel={withLabel}
/>
);
}
export default translate(SelectMethod);

View File

@ -23,22 +23,26 @@ type Props = I18nProps & {
withLabel?: boolean
};
function SelectSection ({ className, defaultValue, isError, label, onChange, options, style, t, value: { section }, withLabel }: Props) {
return (
<Dropdown
className={classes('ui--DropdownLinked-Sections', className)}
defaultValue={defaultValue}
isError={isError}
label={label || t('input.rpc.section', {
defaultValue: 'rpc area'
})}
onChange={onChange}
options={options}
style={style}
value={section}
withLabel={withLabel}
/>
);
class SelectSection extends React.PureComponent<Props> {
render () {
const { className, defaultValue, isError, label, onChange, options, style, t, value: { section }, withLabel } = this.props;
return (
<Dropdown
className={classes('ui--DropdownLinked-Sections', className)}
defaultValue={defaultValue}
isError={isError}
label={label || t('input.rpc.section', {
defaultValue: 'rpc area'
})}
onChange={onChange}
options={options}
style={style}
value={section}
withLabel={withLabel}
/>
);
}
}
export default translate(SelectSection);

View File

@ -24,29 +24,33 @@ type Props = I18nProps & {
withLabel?: boolean
};
function SelectKey ({ className, isError, label = '', onChange, options, style, t, value: { name, section }, withLabel }: Props) {
if (!options.length) {
return null;
class SelectKey extends React.PureComponent<Props> {
render () {
const { className, isError, label = '', onChange, options, style, t, value: { name, section }, withLabel } = this.props;
if (!options.length) {
return null;
}
const transform = (name: string): SectionItem<Storages> =>
map[section].public[name];
return (
<Dropdown
className={classes('ui--DropdownLinked-Items', className)}
isError={isError}
label={label || t('input.storage.key', {
defaultValue: 'with storage key'
})}
onChange={onChange}
options={options}
style={style}
transform={transform}
value={name}
withLabel={withLabel}
/>
);
}
const transform = (name: string): SectionItem<Storages> =>
map[section].public[name];
return (
<Dropdown
className={classes('ui--DropdownLinked-Items', className)}
isError={isError}
label={label || t('input.storage.key', {
defaultValue: 'with storage key'
})}
onChange={onChange}
options={options}
style={style}
transform={transform}
value={name}
withLabel={withLabel}
/>
);
}
export default translate(SelectKey);

View File

@ -23,22 +23,26 @@ type Props = I18nProps & {
withLabel?: boolean
};
function SelectSection ({ className, defaultValue, isError, label, onChange, options, style, t, value: { section }, withLabel }: Props) {
return (
<Dropdown
className={classes('ui--DropdownLinked-Sections', className)}
defaultValue={defaultValue}
isError={isError}
label={label || t('input.storage.section', {
defaultValue: 'storage area'
})}
onChange={onChange}
options={options}
style={style}
value={section}
withLabel={withLabel}
/>
);
class SelectSection extends React.PureComponent<Props> {
render () {
const { className, defaultValue, isError, label, onChange, options, style, t, value: { section }, withLabel } = this.props;
return (
<Dropdown
className={classes('ui--DropdownLinked-Sections', className)}
defaultValue={defaultValue}
isError={isError}
label={label || t('input.storage.section', {
defaultValue: 'storage area'
})}
onChange={onChange}
options={options}
style={style}
value={section}
withLabel={withLabel}
/>
);
}
}
export default translate(SelectSection);

View File

@ -20,22 +20,26 @@ const defaultLabel: any = (// node?
<div>&nbsp;</div>
);
export default function Labelled ({ className, children, isHidden = false, label = defaultLabel, style, withLabel = true }: Props) {
if (isHidden) {
return null;
}
export default class Labelled extends React.PureComponent<Props> {
render () {
const { className, children, isHidden = false, label = defaultLabel, style, withLabel = true } = this.props;
return (
<div
className={classes('ui--Labelled', className)}
style={style}
>
{
withLabel
? <Label>{label}</Label>
: null
}
{children}
</div>
);
if (isHidden) {
return null;
}
return (
<div
className={classes('ui--Labelled', className)}
style={style}
>
{
withLabel
? <Label>{label}</Label>
: null
}
{children}
</div>
);
}
}

View File

@ -20,26 +20,30 @@ type Props = BareProps & {
withLabel?: boolean
};
export default function Output ({ className, children, isError = false, isHidden, label, style, value, withCopy = false, withLabel }: Props) {
return (
<Labelled
className={className}
isHidden={isHidden}
label={label}
style={style}
withLabel={withLabel}
>
<div className={classes('ui--output', isError && 'error')}>
{value}
{children}
{
withCopy
? (
<CopyButton className='ui--output-button' value={value} />
)
: null
}
</div>
</Labelled>
);
export default class Output extends React.PureComponent<Props> {
render () {
const { className, children, isError = false, isHidden, label, style, value, withCopy = false, withLabel } = this.props;
return (
<Labelled
className={className}
isHidden={isHidden}
label={label}
style={style}
withLabel={withLabel}
>
<div className={classes('ui--output', isError && 'error')}>
{value}
{children}
{
withCopy
? (
<CopyButton className='ui--output-button' value={value} />
)
: null
}
</div>
</Labelled>
);
}
}

View File

@ -16,19 +16,23 @@ type Props = BareProps & {
withLabel?: boolean
};
export default function Static ({ className, children, isHidden, label, style, value, withLabel }: Props) {
return (
<Labelled
className={className}
isHidden={isHidden}
label={label}
style={style}
withLabel={withLabel}
>
<div className='ui dropdown selection disabled'>
{value}
{children}
</div>
</Labelled>
);
export default class Static extends React.PureComponent<Props> {
render () {
const { className, children, isHidden, label, style, value, withLabel } = this.props;
return (
<Labelled
className={className}
isHidden={isHidden}
label={label}
style={style}
withLabel={withLabel}
>
<div className='ui dropdown selection disabled'>
{value}
{children}
</div>
</Labelled>
);
}
}

View File

@ -13,26 +13,29 @@ type DemoProps = {
component: string
};
export default function Demo ({ attrs, attrsReq, children, component }: DemoProps) {
const allAttrs = Object.assign({ className: '"..."', style: '{...}' }, attrs);
const attrsText = Object
.keys(allAttrs)
.map((attr) => {
const value = allAttrs[attr];
const bool = value === 'bool';
const opt = bool || !attrsReq.includes(attr);
export default class Demo extends React.PureComponent<DemoProps> {
render () {
const { attrs, attrsReq, children, component } = this.props;
const allAttrs = Object.assign({ className: '"..."', style: '{...}' }, attrs);
const attrsText = Object
.keys(allAttrs)
.map((attr) => {
const value = allAttrs[attr];
const bool = value === 'bool';
const opt = bool || !attrsReq.includes(attr);
return `${opt ? '[' : ''}${attr}${bool ? '' : '='}${bool ? '' : value}${opt ? ']' : ''}`;
})
.sort()
.join('\n ');
return `${opt ? '[' : ''}${attr}${bool ? '' : '='}${bool ? '' : value}${opt ? ']' : ''}`;
})
.sort()
.join('\n ');
return (
<Container className='ui--DemoContainer'>
<pre className='ui--DemoHeader'>
{`<${component}\n ${attrsText}\n/>`}
</pre>
{children}
</Container>
);
return (
<Container className='ui--DemoContainer'>
<pre className='ui--DemoHeader'>
{`<${component}\n ${attrsText}\n/>`}
</pre>
{children}
</Container>
);
}
}

View File

@ -12,13 +12,15 @@ type Props = BaseProps & {
children: any // React$Node
};
export default function Container ({ children, className, style }: Props) {
return (
<div
className={['ui--Container', className].join(' ')}
style={style}
>
{children}
</div>
);
export default class Container extends React.PureComponent<Props> {
render () {
return (
<div
className={['ui--Container', this.props.className].join(' ')}
style={this.props.style}
>
{this.props.children}
</div>
);
}
}

View File

@ -9,34 +9,37 @@ import addressEncode from '@polkadot/util-keyring/address/encode';
import Container from '../Container/Demo';
import IdentityIcon from './index';
export default function Demo () {
const identities: Array<Uint8Array | string> = [new Uint8Array(32)];
export default class Demo extends React.PureComponent {
render () {
const identities: Array<Uint8Array | string> = [new Uint8Array(32)];
while (identities.length !== 10) {
identities.push(
addressEncode(randomAsU8a(32))
while (identities.length !== 10) {
identities.push(
addressEncode(randomAsU8a(32))
);
}
return (
<Container
component='IdentityIcon'
attrs={{
size: '<number>',
value: '{...}'
}}
attrsReq={[
'value'
]}
>
{
identities.map((value) => (
<IdentityIcon
key={value.toString()}
value={value}
/>
))
}
</Container>
);
}
return (
<Container
component='IdentityIcon'
attrs={{
size: '<number>',
value: '{...}'
}}
attrsReq={[
'value'
]}
>
{
identities.map((value) => (
<IdentityIcon
key={value.toString()}
value={value}
/>
))
}
</Container>
);
}

View File

@ -15,12 +15,16 @@ type Props = BaseProps & {
value: string | Uint8Array
};
export default function IdentityIcon ({ className, size = 64, style, value }: Props) {
return (
<div
className={['ui--IdentityIcon', className].join(' ')}
ref={appendIcon(value, size)}
style={style}
/>
);
export default class IdentityIcon extends React.PureComponent<Props> {
render () {
const { className, size = 64, style, value } = this.props;
return (
<div
className={['ui--IdentityIcon', className].join(' ')}
ref={appendIcon(value, size)} // TODO: The append should probably be in this class and done in a more "React-y" way
style={style}
/>
);
}
}

View File

@ -13,33 +13,37 @@ type Props = BareProps & {
queue: Array<QueueTx>
};
export default function Status ({ className, queue, style }: Props) {
const available = queue.filter(({ status }) =>
!['completed', 'incomplete'].includes(status)
);
export default class Status extends React.PureComponent<Props> {
render () {
const { queue, className, style } = this.props;
const available = queue.filter(({ status }) =>
if (!available.length) {
return null;
!['completed', 'incomplete'].includes(status)
);
if (!available.length) {
return null;
}
return (
<div
className={classes('ui--signer-Status', className)}
style={style}
>
{available.map(({ rpc: { name, section }, id, status }) =>
<div
className={classes('ui--signer-Status-Item', status)}
key={id}
>
<div className='header'>
{section}.{name}
</div>
<div className='status'>
{status}
</div>
</div>
)}
</div>
);
}
return (
<div
className={classes('ui--signer-Status', className)}
style={style}
>
{available.map(({ rpc: { name, section }, id, status }) =>
<div
className={classes('ui--signer-Status-Item', status)}
key={id}
>
<div className='header'>
{section}.{name}
</div>
<div className='status'>
{status}
</div>
</div>
)}
</div>
);
}

View File

@ -22,27 +22,31 @@ export type SignerType = React.ComponentType<Props> & {
Queue: React.ComponentType<QueueComponentProps>
};
function Signer ({ children, className, style }: Props) {
return (
<Queue>
{children}
<QueueConsumer>
{({ queue, queueSetStatus }: QueueProps) => [
<Modal
className={className}
key='signer-modal'
queue={queue}
queueSetStatus={queueSetStatus}
style={style}
/>,
<Status
key='signer-status'
queue={queue}
/>
]}
</QueueConsumer>
</Queue>
);
class Signer extends React.PureComponent<Props> {
render () {
const { children, className, style } = this.props;
return (
<Queue>
{children}
<QueueConsumer>
{({ queue, queueSetStatus }: QueueProps) => [
<Modal
className={className}
key='signer-modal'
queue={queue}
queueSetStatus={queueSetStatus}
style={style}
/>,
<Status
key='signer-status'
queue={queue}
/>
]}
</QueueConsumer>
</Queue>
);
}
}
(Signer as SignerType).Queue = Queue;