From 09c45ea3c2f6e111cf6ba2bebebc1b6281700c9c Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Tue, 24 Sep 2019 11:42:55 +0200 Subject: [PATCH] More func. component conversions (#1650) * More func. component conversions * Linting updates --- packages/app-accounts/src/Vanity/index.tsx | 22 +- packages/app-claims/src/Claim.tsx | 209 +++++++----------- packages/app-claims/src/index.tsx | 2 +- packages/app-settings/src/Developer.tsx | 14 +- .../react-components/src/Chart/HorizBar.tsx | 133 ++++++----- packages/react-components/src/Modal.tsx | 33 ++- packages/react-signer/src/Checks/index.tsx | 4 +- 7 files changed, 184 insertions(+), 233 deletions(-) diff --git a/packages/app-accounts/src/Vanity/index.tsx b/packages/app-accounts/src/Vanity/index.tsx index 73d5ebb12b..742d2a5d0b 100644 --- a/packages/app-accounts/src/Vanity/index.tsx +++ b/packages/app-accounts/src/Vanity/index.tsx @@ -313,14 +313,16 @@ class VanityApp extends TxComponent { } } -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; + } + ` +); diff --git a/packages/app-claims/src/Claim.tsx b/packages/app-claims/src/Claim.tsx index 35093044ba..7e46c5fff9 100644 --- a/packages/app-claims/src/Claim.tsx +++ b/packages/app-claims/src/Claim.tsx @@ -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 | null { + const { api } = useContext(ApiContext); + const [claimValue, setClaimValue] = useState(null); + const [claimAddress, setClaimAddress] = useState(null); + const [isBusy, setIsBusy] = useState(false); + + const _fetchClaim = (address: EthereumAddress): void => { + setIsBusy(true); + + api.query.claims + .claims>(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 ( + +
+ {t('Your Ethereum account')} +

{addrToChecksum(claimAddress.toString())}

+ {hasClaim && claimValue + ? ( + <> + {t('has a valid claim for')} +

{formatBalance(claimValue)}

+ {button} + + ) + : ( + <> + {t('does not appear to have a valid claim. Please double check that you have signed the transaction correctly on the correct ETH account.')} + + )} +
+
+ ); } -class Claim extends React.PureComponent { - public static getDerivedStateFromProps ({ ethereumAddress }: Props, state: State): Pick { - 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 ( - - - {t('Your Ethereum account')} -

{addrToChecksum(ethereumAddress.toString())}

- {hasClaim && !!claim - ? ( - <> - {t('has a valid claim for')} -

{formatBalance(claim)}

- - {button} - - - ) - : ( - <> - {t('does not appear to have a valid claim. Please double check that you have signed the transaction correctly on the correct ETH account.')} - - )} -
-
- ); - } - - private fetchClaim (): void { - const { api } = this.props; - const { ethereumAddress } = this.state; - - if (!ethereumAddress) { - return; - } - - this.setState({ isBusy: true }, (): void => { - api.query.claims - .claims>(ethereumAddress.toHex()) - .then((claim): void => { - this.setState({ - claim: claim.unwrapOr(null), - isBusy: false - }); - }); - }); - } -} - -export default withMulti( - Claim, - translate, - withApi + ` ); diff --git a/packages/app-claims/src/index.tsx b/packages/app-claims/src/index.tsx index a44a79ccd7..8a74aea4ce 100644 --- a/packages/app-claims/src/index.tsx +++ b/packages/app-claims/src/index.tsx @@ -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; diff --git a/packages/app-settings/src/Developer.tsx b/packages/app-settings/src/Developer.tsx index 519454b4b1..d22e4b7a49 100644 --- a/packages/app-settings/src/Developer.tsx +++ b/packages/app-settings/src/Developer.tsx @@ -157,7 +157,7 @@ class Developer extends React.PureComponent { } 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 { 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}`) }); } } diff --git a/packages/react-components/src/Chart/HorizBar.tsx b/packages/react-components/src/Chart/HorizBar.tsx index 040c49e0e8..813c8dc2cb 100644 --- a/packages/react-components/src/Chart/HorizBar.tsx +++ b/packages/react-components/src/Chart/HorizBar.tsx @@ -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 { - 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 ( -
- -
- ); - } + scales: { + xAxes: [{ + ticks: { + beginAtZero: true, + max: 100 + } + }] + } + }, + jsonValues + }; +} + +export default function ChartHorizBar ({ aspectRatio = 4, className, style, values }: Props): React.ReactElement | null { + const [{ chartData, chartOptions, jsonValues }, setState] = useState({}); + + useEffect((): void => { + const newJsonValues = JSON.stringify(values); + + if (newJsonValues !== jsonValues) { + setState(calculateOptions(aspectRatio, values, newJsonValues)); + } + }, [values]); + + if (!chartData) { + return null; + } + + return ( +
+ +
+ ); } diff --git a/packages/react-components/src/Modal.tsx b/packages/react-components/src/Modal.tsx index 88448f0960..324787db22 100644 --- a/packages/react-components/src/Modal.tsx +++ b/packages/react-components/src/Modal.tsx @@ -14,23 +14,18 @@ interface Props extends BareProps { [index: string]: any; } -export default class Modal extends React.PureComponent { - 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 ( - - ); - } +function Modal (props: Props): React.ReactElement { + return ( + + ); } + +Modal.Actions = SUIModal.Actions; +Modal.Content = SUIModal.Content; +Modal.Header = SUIModal.Header; +Modal.Description = SUIModal.Description; + +export default Modal; diff --git a/packages/react-signer/src/Checks/index.tsx b/packages/react-signer/src/Checks/index.tsx index 0dc3fcbaf0..07e14710bd 100644 --- a/packages/react-signer/src/Checks/index.tsx +++ b/packages/react-signer/src/Checks/index.tsx @@ -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 && (
{t('The selected account does not exist on your keyring')}