More func. component conversions (#1650)
* More func. component conversions * Linting updates
This commit is contained in:
parent
6f8da05805
commit
09c45ea3c2
@ -313,14 +313,16 @@ class VanityApp extends TxComponent<Props, State> {
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(styled(VanityApp)`
|
||||
.vanity--App-matches {
|
||||
padding: 1em 0;
|
||||
}
|
||||
export default translate(
|
||||
styled(VanityApp)`
|
||||
.vanity--App-matches {
|
||||
padding: 1em 0;
|
||||
}
|
||||
|
||||
.vanity--App-stats {
|
||||
padding: 1em 0 0 0;
|
||||
opacity: 0.45;
|
||||
text-align: center;
|
||||
}
|
||||
`);
|
||||
.vanity--App-stats {
|
||||
padding: 1em 0 0 0;
|
||||
opacity: 0.45;
|
||||
text-align: center;
|
||||
}
|
||||
`
|
||||
);
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/camelcase */
|
||||
// Copyright 2017-2019 @polkadot/app-123code authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
@ -6,147 +5,103 @@
|
||||
import { Option } from '@polkadot/types';
|
||||
import { BalanceOf, EthereumAddress } from '@polkadot/types/interfaces';
|
||||
import { I18nProps } from '@polkadot/react-components/types';
|
||||
import { ApiProps } from '@polkadot/react-api/types';
|
||||
|
||||
import React from 'react';
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { withApi, withMulti } from '@polkadot/react-api';
|
||||
import { ApiContext } from '@polkadot/react-api';
|
||||
import { Button, Card } from '@polkadot/react-components';
|
||||
import { formatBalance } from '@polkadot/util';
|
||||
|
||||
import translate from './translate';
|
||||
import { addrToChecksum } from './util';
|
||||
|
||||
const ClaimInner = styled.div`
|
||||
font-size: 1.15rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
min-height: 12rem;
|
||||
align-items: center;
|
||||
margin: 0 1rem;
|
||||
|
||||
h3 {
|
||||
font-family: monospace;
|
||||
font-size: 1.5rem;
|
||||
max-width: 100%;
|
||||
margin: 0.5rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 0.5rem 0 2rem
|
||||
font-family: monospace;
|
||||
font-size: 2.5rem;
|
||||
font-weight: 200;
|
||||
}
|
||||
`;
|
||||
|
||||
interface Props extends ApiProps, I18nProps {
|
||||
interface Props extends I18nProps {
|
||||
button: React.ReactNode;
|
||||
ethereumAddress: EthereumAddress | null;
|
||||
}
|
||||
|
||||
interface State {
|
||||
claim: BalanceOf | null;
|
||||
ethereumAddress: EthereumAddress | null;
|
||||
hasClaim: boolean;
|
||||
isBusy: boolean;
|
||||
function Claim ({ button, className, ethereumAddress, t }: Props): React.ReactElement<Props> | null {
|
||||
const { api } = useContext(ApiContext);
|
||||
const [claimValue, setClaimValue] = useState<BalanceOf | null>(null);
|
||||
const [claimAddress, setClaimAddress] = useState<EthereumAddress | null>(null);
|
||||
const [isBusy, setIsBusy] = useState(false);
|
||||
|
||||
const _fetchClaim = (address: EthereumAddress): void => {
|
||||
setIsBusy(true);
|
||||
|
||||
api.query.claims
|
||||
.claims<Option<BalanceOf>>(address)
|
||||
.then((claim): void => {
|
||||
setClaimValue(claim.unwrapOr(null));
|
||||
setIsBusy(false);
|
||||
})
|
||||
.catch((): void => setIsBusy(false));
|
||||
};
|
||||
|
||||
useEffect((): void => {
|
||||
if (ethereumAddress !== claimAddress) {
|
||||
setClaimAddress(ethereumAddress);
|
||||
ethereumAddress && _fetchClaim(ethereumAddress);
|
||||
}
|
||||
}, [ethereumAddress]);
|
||||
|
||||
if (isBusy || !claimAddress) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const hasClaim = claimValue && claimValue.gten(0);
|
||||
|
||||
return (
|
||||
<Card
|
||||
isError={!hasClaim}
|
||||
isSuccess={!!hasClaim}
|
||||
>
|
||||
<div className={className}>
|
||||
{t('Your Ethereum account')}
|
||||
<h3>{addrToChecksum(claimAddress.toString())}</h3>
|
||||
{hasClaim && claimValue
|
||||
? (
|
||||
<>
|
||||
{t('has a valid claim for')}
|
||||
<h2>{formatBalance(claimValue)}</h2>
|
||||
<Button.Group>{button}</Button.Group>
|
||||
</>
|
||||
)
|
||||
: (
|
||||
<>
|
||||
{t('does not appear to have a valid claim. Please double check that you have signed the transaction correctly on the correct ETH account.')}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
class Claim extends React.PureComponent<Props, State> {
|
||||
public static getDerivedStateFromProps ({ ethereumAddress }: Props, state: State): Pick<State, never> {
|
||||
if (ethereumAddress) {
|
||||
return {
|
||||
ethereumAddress,
|
||||
hasClaim: state.claim && state.claim.gten(0)
|
||||
};
|
||||
export default translate(
|
||||
styled(Claim)`
|
||||
font-size: 1.15rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
min-height: 12rem;
|
||||
align-items: center;
|
||||
margin: 0 1rem;
|
||||
|
||||
h3 {
|
||||
font-family: monospace;
|
||||
font-size: 1.5rem;
|
||||
max-width: 100%;
|
||||
margin: 0.5rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
return {
|
||||
hasClaim: false
|
||||
};
|
||||
}
|
||||
|
||||
public state: State = {
|
||||
claim: null,
|
||||
ethereumAddress: null,
|
||||
hasClaim: false,
|
||||
isBusy: false
|
||||
}
|
||||
|
||||
public componentDidMount (): void {
|
||||
this.fetchClaim();
|
||||
}
|
||||
|
||||
public componentDidUpdate (_: Props, prevState: State): void {
|
||||
const { ethereumAddress } = this.state;
|
||||
if (ethereumAddress !== prevState.ethereumAddress) {
|
||||
this.fetchClaim();
|
||||
h2 {
|
||||
margin: 0.5rem 0 2rem;
|
||||
font-family: monospace;
|
||||
font-size: 2.5rem;
|
||||
font-weight: 200;
|
||||
}
|
||||
}
|
||||
|
||||
public render (): React.ReactNode {
|
||||
const { button, t } = this.props;
|
||||
const { claim, ethereumAddress, hasClaim, isBusy } = this.state;
|
||||
|
||||
if (isBusy || !ethereumAddress) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Card
|
||||
isError={!hasClaim || !claim}
|
||||
isSuccess={hasClaim && !!claim}
|
||||
>
|
||||
<ClaimInner>
|
||||
{t('Your Ethereum account')}
|
||||
<h3>{addrToChecksum(ethereumAddress.toString())}</h3>
|
||||
{hasClaim && !!claim
|
||||
? (
|
||||
<>
|
||||
{t('has a valid claim for')}
|
||||
<h2>{formatBalance(claim)}</h2>
|
||||
<Button.Group>
|
||||
{button}
|
||||
</Button.Group>
|
||||
</>
|
||||
)
|
||||
: (
|
||||
<>
|
||||
{t('does not appear to have a valid claim. Please double check that you have signed the transaction correctly on the correct ETH account.')}
|
||||
</>
|
||||
)}
|
||||
</ClaimInner>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
private fetchClaim (): void {
|
||||
const { api } = this.props;
|
||||
const { ethereumAddress } = this.state;
|
||||
|
||||
if (!ethereumAddress) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({ isBusy: true }, (): void => {
|
||||
api.query.claims
|
||||
.claims<Option<BalanceOf>>(ethereumAddress.toHex())
|
||||
.then((claim): void => {
|
||||
this.setState({
|
||||
claim: claim.unwrapOr(null),
|
||||
isBusy: false
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default withMulti(
|
||||
Claim,
|
||||
translate,
|
||||
withApi
|
||||
`
|
||||
);
|
||||
|
||||
@ -34,7 +34,7 @@ interface Props extends AppProps, ApiProps, I18nProps, TxModalProps {}
|
||||
|
||||
interface State extends TxModalState {
|
||||
didCopy: boolean;
|
||||
ethereumAddress?: EthereumAddress | null;
|
||||
ethereumAddress: EthereumAddress | null;
|
||||
claim?: Balance | null;
|
||||
signature?: EcdsaSignature | null;
|
||||
step: Step;
|
||||
|
||||
@ -157,7 +157,7 @@ class Developer extends React.PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
private saveDeveloper = (): void => {
|
||||
const { t } = this.props;
|
||||
const { onStatusChange, t } = this.props;
|
||||
const { types } = this.state;
|
||||
|
||||
try {
|
||||
@ -166,16 +166,18 @@ class Developer extends React.PureComponent<Props, State> {
|
||||
store.set('types', types);
|
||||
|
||||
this.setState({ isTypesValid: true });
|
||||
this.props.onStatusChange({
|
||||
|
||||
onStatusChange({
|
||||
status: 'success',
|
||||
action: t('Your custom types have been added')
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
this.setState({ isTypesValid: false });
|
||||
this.props.onStatusChange({
|
||||
|
||||
onStatusChange({
|
||||
status: 'error',
|
||||
action: t(`Error saving your custom types. ${e}`)
|
||||
action: t(`Error saving your custom types. ${error.message}`)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
import { BareProps } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import React from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import ChartJs from 'chart.js';
|
||||
import { HorizontalBar } from 'react-chartjs-2';
|
||||
import { bnToBn } from '@polkadot/util';
|
||||
@ -24,7 +24,7 @@ interface Props extends BareProps {
|
||||
interface State {
|
||||
chartData?: ChartJs.ChartData;
|
||||
chartOptions?: ChartJs.ChartOptions;
|
||||
valuesStr?: string;
|
||||
jsonValues?: string;
|
||||
}
|
||||
|
||||
interface Config {
|
||||
@ -39,74 +39,71 @@ interface Config {
|
||||
const alphaColor = (hexColor: string): string =>
|
||||
ChartJs.helpers.color(hexColor).alpha(0.65).rgbString();
|
||||
|
||||
export default class ChartHorizBar extends React.PureComponent<Props, State> {
|
||||
public state: State = {};
|
||||
function calculateOptions (aspectRatio: number, values: Value[], jsonValues: string): State {
|
||||
const chartData = values.reduce((data, { colors: [normalColor = '#00f', hoverColor], label, value }): Config => {
|
||||
const dataset = data.datasets[0];
|
||||
|
||||
public static getDerivedStateFromProps ({ aspectRatio = 4, values }: Props, prevState: State): State | null {
|
||||
const valuesStr = JSON.stringify(values);
|
||||
dataset.backgroundColor.push(alphaColor(normalColor));
|
||||
dataset.hoverBackgroundColor.push(alphaColor(hoverColor || normalColor));
|
||||
dataset.data.push(bnToBn(value).toNumber());
|
||||
data.labels.push(label);
|
||||
|
||||
if (valuesStr === prevState.valuesStr) {
|
||||
return null;
|
||||
}
|
||||
return data;
|
||||
}, {
|
||||
labels: [] as string[],
|
||||
datasets: [{
|
||||
data: [] as number[],
|
||||
backgroundColor: [] as string[],
|
||||
hoverBackgroundColor: [] as string[]
|
||||
}]
|
||||
});
|
||||
|
||||
const chartData = values.reduce((data, { colors: [normalColor = '#00f', hoverColor], label, value }): Config => {
|
||||
const dataset = data.datasets[0];
|
||||
|
||||
dataset.backgroundColor.push(alphaColor(normalColor));
|
||||
dataset.hoverBackgroundColor.push(alphaColor(hoverColor || normalColor));
|
||||
dataset.data.push(bnToBn(value).toNumber());
|
||||
data.labels.push(label);
|
||||
|
||||
return data;
|
||||
}, {
|
||||
labels: [] as string[],
|
||||
datasets: [{
|
||||
data: [] as number[],
|
||||
backgroundColor: [] as string[],
|
||||
hoverBackgroundColor: [] as string[]
|
||||
}]
|
||||
});
|
||||
|
||||
return {
|
||||
chartData,
|
||||
chartOptions: {
|
||||
// width/height by default this is "1", i.e. a square box
|
||||
aspectRatio,
|
||||
// no need for the legend, expect the labels contain everything
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
ticks: {
|
||||
beginAtZero: true,
|
||||
max: 100
|
||||
}
|
||||
}]
|
||||
}
|
||||
return {
|
||||
chartData,
|
||||
chartOptions: {
|
||||
// width/height by default this is "1", i.e. a square box
|
||||
aspectRatio,
|
||||
// no need for the legend, expect the labels contain everything
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
valuesStr
|
||||
};
|
||||
}
|
||||
|
||||
public render (): React.ReactNode {
|
||||
const { className, style } = this.props;
|
||||
const { chartData, chartOptions } = this.state;
|
||||
|
||||
if (!chartData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
<HorizontalBar
|
||||
data={chartData}
|
||||
options={chartOptions}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
scales: {
|
||||
xAxes: [{
|
||||
ticks: {
|
||||
beginAtZero: true,
|
||||
max: 100
|
||||
}
|
||||
}]
|
||||
}
|
||||
},
|
||||
jsonValues
|
||||
};
|
||||
}
|
||||
|
||||
export default function ChartHorizBar ({ aspectRatio = 4, className, style, values }: Props): React.ReactElement<Props> | null {
|
||||
const [{ chartData, chartOptions, jsonValues }, setState] = useState<State>({});
|
||||
|
||||
useEffect((): void => {
|
||||
const newJsonValues = JSON.stringify(values);
|
||||
|
||||
if (newJsonValues !== jsonValues) {
|
||||
setState(calculateOptions(aspectRatio, values, newJsonValues));
|
||||
}
|
||||
}, [values]);
|
||||
|
||||
if (!chartData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
<HorizontalBar
|
||||
data={chartData}
|
||||
options={chartOptions}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -14,23 +14,18 @@ interface Props extends BareProps {
|
||||
[index: string]: any;
|
||||
}
|
||||
|
||||
export default class Modal extends React.PureComponent<Props> {
|
||||
public static Actions = SUIModal.Actions;
|
||||
|
||||
public static Content = SUIModal.Content;
|
||||
|
||||
public static Header = SUIModal.Header;
|
||||
|
||||
public static Description = SUIModal.Description;
|
||||
|
||||
public render (): React.ReactNode {
|
||||
const { className } = this.props;
|
||||
|
||||
return (
|
||||
<SUIModal
|
||||
{...this.props}
|
||||
className={classes('theme--default', 'ui--Modal', className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
function Modal (props: Props): React.ReactElement<Props> {
|
||||
return (
|
||||
<SUIModal
|
||||
{...props}
|
||||
className={classes('theme--default', 'ui--Modal', props.className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
Modal.Actions = SUIModal.Actions;
|
||||
Modal.Content = SUIModal.Content;
|
||||
Modal.Header = SUIModal.Header;
|
||||
Modal.Description = SUIModal.Description;
|
||||
|
||||
export default Modal;
|
||||
|
||||
@ -112,7 +112,7 @@ export function FeeDisplay ({ accountId, balances_all = ZERO_BALANCE, balances_f
|
||||
const allWarn = extraWarn;
|
||||
const overLimit = txLength.gten(MAX_SIZE_BYTES);
|
||||
|
||||
(hasAvailable !== state.hasAvailable) && onChange && onChange(hasAvailable);
|
||||
onChange && onChange(hasAvailable);
|
||||
|
||||
setExtra({
|
||||
extraAmount,
|
||||
@ -149,7 +149,7 @@ export function FeeDisplay ({ accountId, balances_all = ZERO_BALANCE, balances_f
|
||||
className={[className, feeClass, 'padded'].join(' ')}
|
||||
key='txinfo'
|
||||
>
|
||||
{isSendable && (
|
||||
{!isSendable && (
|
||||
<div>
|
||||
<Icon name='ban' />
|
||||
{t('The selected account does not exist on your keyring')}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user