From 284f7a667db377f9024ce1e32e016b46423eec5a Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Wed, 22 Apr 2020 14:44:54 +0200 Subject: [PATCH] useMemo for table headers/footers/filters (#2601) * useMemo for table headers/footers/filters * contacts mishap --- packages/page-accounts/src/Accounts/index.tsx | 70 ++++++++++--------- packages/page-accounts/src/Contacts/index.tsx | 46 ++++++------ packages/page-accounts/src/Vanity/index.tsx | 28 ++++---- packages/page-council/src/Motions/index.tsx | 20 +++--- .../page-council/src/Overview/Candidates.tsx | 22 +++--- .../page-council/src/Overview/Members.tsx | 12 ++-- .../src/Overview/DispatchQueue.tsx | 14 ++-- .../page-democracy/src/Overview/Externals.tsx | 16 +++-- .../page-democracy/src/Overview/Proposals.tsx | 16 +++-- .../src/Overview/Referendums.tsx | 20 +++--- packages/page-explorer/src/BlockHeaders.tsx | 10 +-- .../src/BlockInfo/Extrinsics.tsx | 14 ++-- packages/page-explorer/src/BlockInfo/Logs.tsx | 6 +- packages/page-explorer/src/Events.tsx | 10 +-- packages/page-explorer/src/NodeInfo/Peers.tsx | 16 +++-- .../src/Overview/Parachains.tsx | 16 ++--- packages/page-society/src/Overview/Bids.tsx | 14 ++-- .../page-society/src/Overview/Candidates.tsx | 16 +++-- .../page-society/src/Overview/Defender.tsx | 14 ++-- .../page-society/src/Overview/Members.tsx | 12 ++-- packages/page-staking/src/Actions/index.tsx | 38 +++++----- .../page-staking/src/Overview/CurrentList.tsx | 56 ++++++++------- packages/page-staking/src/Payouts/index.tsx | 54 +++++++------- packages/page-staking/src/Targets/index.tsx | 44 ++++++------ .../page-tech-comm/src/Overview/Members.tsx | 10 +-- .../page-tech-comm/src/Proposals/index.tsx | 18 ++--- .../page-treasury/src/Overview/Proposals.tsx | 18 ++--- packages/page-treasury/src/Overview/Tips.tsx | 20 +++--- 28 files changed, 362 insertions(+), 288 deletions(-) diff --git a/packages/page-accounts/src/Accounts/index.tsx b/packages/page-accounts/src/Accounts/index.tsx index eb937339b1..9ca2e30a33 100644 --- a/packages/page-accounts/src/Accounts/index.tsx +++ b/packages/page-accounts/src/Accounts/index.tsx @@ -7,7 +7,7 @@ import { ComponentProps as Props } from '../types'; import { SortedAccount } from './types'; import BN from 'bn.js'; -import React, { useCallback, useEffect, useState } from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import styled from 'styled-components'; import keyring from '@polkadot/ui-keyring'; import { getLedger, isLedger } from '@polkadot/react-api'; @@ -98,7 +98,7 @@ function Overview ({ className, onStatusChange }: Props): React.ReactElement({ accounts: {} }); const [sortedAccounts, setSortedAccounts] = useState([]); - const [filter, setFilter] = useState(''); + const [filterOn, setFilter] = useState(''); useEffect((): void => { setSortedAccounts( @@ -119,6 +119,38 @@ function Overview ({ className, onStatusChange }: Props): React.ReactElement [ + [t('accounts'), 'start', 3], + [t('parent'), 'address'], + [t('type')], + [t('tags'), 'start'], + [t('transactions')], + [t('balances')], + [undefined, undefined, 2] + ], [t]); + + const footer = useMemo(() => ( + + + + {balanceTotal && } + + + + ), [balanceTotal]); + + const filter = useMemo(() => ( +
+ +
+ ), [filterOn, t]); + return (
@@ -171,40 +203,14 @@ function Overview ({ className, onStatusChange }: Props): React.ReactElement - - - } - footer={ - - - - } - header={[ - [t('accounts'), 'start', 3], - [t('parent'), 'address'], - [t('type')], - [t('tags'), 'start'], - [t('transactions')], - [t('balances')], - [undefined, undefined, 2] - ]} + filter={filter} + footer={footer} + header={header} > {sortedAccounts.map(({ account, isFavorite }): React.ReactNode => ( ([]); - const [filter, setFilter] = useState(''); + const [filterOn, setFilter] = useState(''); useEffect((): void => { setSortedAddresses( @@ -39,6 +39,26 @@ function Overview ({ className, onStatusChange }: Props): React.ReactElement [ + [t('contacts'), 'start', 2], + [t('tags'), 'start'], + [t('transactions')], + [t('balances')], + [undefined, undefined, 2] + ], [t]); + + const filter = useMemo(() => ( +
+ +
+ ), [filterOn, t]); + return (
@@ -56,29 +76,13 @@ function Overview ({ className, onStatusChange }: Props): React.ReactElement - -
- } - header={[ - [t('contacts'), 'start', 2], - [t('tags'), 'start'], - [t('transactions')], - [t('balances')], - [undefined, undefined, 2] - ]} + filter={filter} + header={header} > {sortedAddresses.map(({ address, isFavorite }): React.ReactNode => (
[ + [t('matches'), 'start', 2], + [t('Evaluated {{count}} keys in {{elapsed}}s ({{avg}} keys/s)', { + replace: { + avg: (keyCount / (elapsed / 1000)).toFixed(3), + count: keyCount, + elapsed: (elapsed / 1000).toFixed(2) + } + }), 'start'], + [t('secret'), 'start'], + [] + ], [elapsed, keyCount, t]); + return (
@@ -217,18 +230,7 @@ function VanityApp ({ className, onStatusChange }: Props): React.ReactElement {matches.map((match): React.ReactNode => ( [ + [t('motions'), 'start', 2], + [t('threshold')], + [t('voting end')], + [t('aye'), 'address'], + [t('nay'), 'address'], + [undefined, undefined, 2] + ], [t]); + return (
@@ -45,14 +54,7 @@ function Proposals ({ className, motions, prime }: Props): React.ReactElement
- - {balanceTotal && } - -
{motions?.map((motion: DeriveCollectiveProposal): React.ReactNode => ( { const { t } = useTranslation(); + const headerRunners = useMemo(() => [ + [t('runners up'), 'start', 2], + [t('backing')] + ], [t]); + + const headerCandidates = useMemo(() => [ + [t('candidates'), 'start', 2], + [t('backing')] + ], [t]); + return ( <>
{electionsInfo?.runnersUp.map(([accountId, balance]): React.ReactNode => (
{electionsInfo?.candidates.map((accountId): React.ReactNode => ( { const { t } = useTranslation(); + const header = useMemo(() => [ + [t('members'), 'start', 2], + [t('backing')] + ], [t]); + return (
{electionsInfo?.members.map(([accountId, balance]): React.ReactNode => ( | null const { api } = useApi(); const queued = useCall(api.derive.democracy.dispatchQueue, []); + const header = useMemo(() => [ + [t('dispatch queue'), 'start', 2], + [t('enact')], + [undefined, undefined, 2] + ], [t]); + return (
{queued?.map((entry): React.ReactNode => ( | null { const { api } = useApi(); const external = useCall(api.derive.democracy.nextExternal, []); + const header = useMemo(() => [ + [t('external'), 'start'], + [t('proposer'), 'address'], + [t('locked')], + [] + ], [t]); + return (
{external && }
diff --git a/packages/page-democracy/src/Overview/Proposals.tsx b/packages/page-democracy/src/Overview/Proposals.tsx index ac63d178b2..85d1ef6121 100644 --- a/packages/page-democracy/src/Overview/Proposals.tsx +++ b/packages/page-democracy/src/Overview/Proposals.tsx @@ -4,7 +4,7 @@ import { DeriveProposal } from '@polkadot/api-derive/types'; -import React from 'react'; +import React, { useMemo } from 'react'; import { Table } from '@polkadot/react-components'; import { useApi, useCall } from '@polkadot/react-hooks'; @@ -20,16 +20,18 @@ function Proposals ({ className }: Props): React.ReactElement { const { api } = useApi(); const proposals = useCall(api.derive.democracy.proposals, []); + const header = useMemo(() => [ + [t('proposals'), 'start', 2], + [t('proposer'), 'address'], + [t('locked')], + [undefined, undefined, 3] + ], [t]); + return ( {proposals?.map((proposal): React.ReactNode => ( { const { api } = useApi(); const referendums = useCall(api.derive.democracy.referendums, []); + const header = useMemo(() => [ + [t('referenda'), 'start', 2], + [t('remaining')], + [t('activate')], + [t('aye')], + [t('nay')], + [undefined, undefined, 3] + ], [t]); + return (
{referendums?.map((referendum): React.ReactNode => ( { const { t } = useTranslation(); + const header = useMemo(() => [ + [t('recent blocks'), 'start', 3] + ], [t]); + return (
{headers .filter((header) => !!header) diff --git a/packages/page-explorer/src/BlockInfo/Extrinsics.tsx b/packages/page-explorer/src/BlockInfo/Extrinsics.tsx index 10a665679d..757d3fa263 100644 --- a/packages/page-explorer/src/BlockInfo/Extrinsics.tsx +++ b/packages/page-explorer/src/BlockInfo/Extrinsics.tsx @@ -4,7 +4,7 @@ import { BlockNumber, EventRecord, Extrinsic } from '@polkadot/types/interfaces'; -import React from 'react'; +import React, { useMemo } from 'react'; import { Table } from '@polkadot/react-components'; import { useTranslation } from '../translate'; @@ -21,15 +21,17 @@ interface Props { function Extrinsics ({ blockNumber, className, events, label, value }: Props): React.ReactElement { const { t } = useTranslation(); + const header = useMemo(() => [ + [label || t('extrinsics'), 'start', 2], + [t('events'), 'start', 2], + [t('signer'), 'address'] + ], [label, t]); + return (
{value?.map((extrinsic, index): React.ReactNode => diff --git a/packages/page-explorer/src/BlockInfo/Logs.tsx b/packages/page-explorer/src/BlockInfo/Logs.tsx index 3370904b67..c1f6df8780 100644 --- a/packages/page-explorer/src/BlockInfo/Logs.tsx +++ b/packages/page-explorer/src/BlockInfo/Logs.tsx @@ -5,7 +5,7 @@ import { DigestItem } from '@polkadot/types/interfaces'; import { Codec, TypeDef } from '@polkadot/types/types'; -import React from 'react'; +import React, { useMemo } from 'react'; import { Struct, Tuple, Raw, Vec, getTypeDef } from '@polkadot/types'; import { Expander, Table } from '@polkadot/react-components'; import Params from '@polkadot/react-params'; @@ -103,10 +103,12 @@ function Logs (props: Props): React.ReactElement | null { const { value } = props; const { t } = useTranslation(); + const header = useMemo(() => [[t('logs'), 'start']], [t]); + return (
{value?.map((log, index) => ( diff --git a/packages/page-explorer/src/Events.tsx b/packages/page-explorer/src/Events.tsx index 109eb84325..ee64bff87e 100644 --- a/packages/page-explorer/src/Events.tsx +++ b/packages/page-explorer/src/Events.tsx @@ -4,7 +4,7 @@ import { EventRecord } from '@polkadot/types/interfaces'; -import React from 'react'; +import React, { useMemo } from 'react'; import { Table } from '@polkadot/react-components'; import Event from './Event'; @@ -20,12 +20,14 @@ interface Props { function Events ({ emptyLabel, eventClassName, events, label }: Props): React.ReactElement { const { t } = useTranslation(); + const header = useMemo(() => [ + [label || t('recent events'), 'start'] + ], [label, t]); + return (
{events .filter(({ event: { method, section } }): boolean => !!method && !!section) diff --git a/packages/page-explorer/src/NodeInfo/Peers.tsx b/packages/page-explorer/src/NodeInfo/Peers.tsx index 572b811b4d..76574495df 100644 --- a/packages/page-explorer/src/NodeInfo/Peers.tsx +++ b/packages/page-explorer/src/NodeInfo/Peers.tsx @@ -4,7 +4,7 @@ import { PeerInfo } from '@polkadot/types/interfaces'; -import React from 'react'; +import React, { useMemo } from 'react'; import { formatNumber } from '@polkadot/util'; import { useTranslation } from '../translate'; @@ -18,16 +18,18 @@ interface Props { function Peers ({ className, peers }: Props): React.ReactElement { const { t } = useTranslation(); + const header = useMemo(() => [ + [t('connected peers'), 'start'], + [t('role'), 'start'], + [t('best #'), 'number'], + [t('best hash'), 'hash'] + ], [t]); + return (
{peers?.sort((a, b): number => b.bestNumber.cmp(a.bestNumber)).map((peer) => ( diff --git a/packages/page-parachains/src/Overview/Parachains.tsx b/packages/page-parachains/src/Overview/Parachains.tsx index aad471873f..94033d3a84 100644 --- a/packages/page-parachains/src/Overview/Parachains.tsx +++ b/packages/page-parachains/src/Overview/Parachains.tsx @@ -4,7 +4,7 @@ import { DeriveParachain } from '@polkadot/api-derive/types'; -import React from 'react'; +import React, { useMemo } from 'react'; import styled from 'styled-components'; import { Table } from '@polkadot/react-components'; @@ -18,14 +18,14 @@ interface Props { function Parachains ({ parachains }: Props): React.ReactElement { const { t } = useTranslation(); + const header = useMemo(() => [ + [t('parachains'), 'start', 4], + [t('swap to id')], + [t('scheduling')] + ], [t]); + return ( -
+
{parachains.map((parachain): React.ReactNode => ( { const { api } = useApi(); const bids = useCall(api.query.society.bids, []); + const header = useMemo(() => [ + [t('bids'), 'start'], + [t('kind')], + [t('value')] + ], [t]); + return (
{bids?.map((bid): React.ReactNode => ( (api.derive.society.candidates, []); + const header = useMemo(() => [ + [t('candidates'), 'start'], + [t('kind')], + [t('value')], + [t('votes'), 'start'] + ], [t]); + return (
{candidates?.map((candidate): React.ReactNode => ( [accountId.toString(), vote as SocietyVote]) }); + const header = useMemo(() => [ + [t('defender'), 'start'], + [t('votes'), 'start'], + [] + ], [t]); + if (!info || !info.hasDefender || !info.defender) { return null; } @@ -36,11 +42,7 @@ function Defender ({ className, info, isMember, ownMembers }: Props): React.Reac return (
+ + + ), [stashTotal]); + return (
{api.tx.staking.payoutStakers && ( @@ -123,22 +149,8 @@ function Payouts ({ className, isInElection }: Props): React.ReactElement
diff --git a/packages/page-society/src/Overview/Members.tsx b/packages/page-society/src/Overview/Members.tsx index 13a15e0e7a..2c8d9a779d 100644 --- a/packages/page-society/src/Overview/Members.tsx +++ b/packages/page-society/src/Overview/Members.tsx @@ -4,7 +4,7 @@ import { DeriveSociety, DeriveSocietyMember } from '@polkadot/api-derive/types'; -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import { Table } from '@polkadot/react-components'; import { useApi, useCall } from '@polkadot/react-hooks'; @@ -28,14 +28,16 @@ function Members ({ className, info }: Props): React.ReactElement { ); }, [info, members]); + const header = useMemo(() => [ + [t('members'), 'start', 3], + [t('strikes')] + ], [t]); + return ( {filtered.map((member): React.ReactNode => ( [ + [t('stashes'), 'start'], + [t('controller'), 'address'], + [t('rewards'), 'number'], + [t('bonded'), 'number'], + [undefined, undefined, 2] + ], [t]); + + const footer = useMemo(() => ( + + + + ), [bondedTotal]); + return (
+ + {bondedTotal && } + +
- - - } - header={[ - [t('stashes'), 'start'], - [t('controller'), 'address'], - [t('rewards'), 'number'], - [t('bonded'), 'number'], - [undefined, undefined, 2] - ]} + footer={footer} + header={header} > {foundStashes?.map(([stashId, isOwnStash]): React.ReactNode => ( [ + [t('intentions'), 'start', 3], + [t('nominators'), 'start', 2], + [t('commission'), 'number', 1], + [undefined, undefined, 3] + ], [t]); + + const headerWaiting = useMemo(() => [ + [t('validators'), 'start', 3], + [t('other stake')], + [t('own stake')], + [t('commission')], + [t('points')], + [t('last #')], + [] + ], [t]); + + const filter = useMemo(() => ( + + ), [nameFilter, t]); + const _renderRows = useCallback( (addresses?: AccountExtend[], isMain?: boolean): React.ReactNode[] => (addresses || []).map(([address, isElected, isFavorite]): React.ReactNode => ( @@ -139,12 +166,7 @@ function CurrentList ({ hasQueries, isIntentions, next, setNominators, stakingOv ? (
- - {bondedTotal && } - -
{_renderRows(elected, false).concat(..._renderRows(waiting, false))}
@@ -152,24 +174,8 @@ function CurrentList ({ hasQueries, isIntentions, next, setNominators, stakingOv : ( - } - header={[ - [t('validators'), 'start', 3], - [t('other stake')], - [t('own stake')], - [t('commission')], - [t('points')], - [t('last #')], - [] - ]} + filter={filter} + header={headerWaiting} > {_renderRows(validators, true)}
diff --git a/packages/page-staking/src/Payouts/index.tsx b/packages/page-staking/src/Payouts/index.tsx index ffcaa0341b..5eb46b2d10 100644 --- a/packages/page-staking/src/Payouts/index.tsx +++ b/packages/page-staking/src/Payouts/index.tsx @@ -6,7 +6,7 @@ import { DeriveStakerReward } from '@polkadot/api-derive/types'; import { PayoutStash, PayoutValidator } from './types'; import BN from 'bn.js'; -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import styled from 'styled-components'; import { Button, Table } from '@polkadot/react-components'; import { useApi, useOwnEraRewards } from '@polkadot/react-hooks'; @@ -109,6 +109,32 @@ function Payouts ({ className, isInElection }: Props): React.ReactElement } }, [allRewards]); + const headerStashes = useMemo(() => [ + [t('payout/stash'), 'start'], + [t('eras'), 'start'], + [t('available')], + [('remaining')], + [undefined, undefined, 3] + ], [t]); + + const headerValidators = useMemo(() => [ + [t('payout/validator'), 'start'], + [t('eras'), 'start'], + [t('available')], + [('remaining')], + [undefined, undefined, 3] + ], [t]); + + const footer = useMemo(() => ( +
+ + {stashTotal && } + +
- - - } - header={[ - [t('payout/stash'), 'start'], - [t('eras'), 'start'], - [t('available')], - [('remaining')], - [undefined, undefined, 3] - ]} + footer={footer} + header={headerStashes} isFixed > {stashes?.map((payout): React.ReactNode => ( @@ -153,13 +165,7 @@ function Payouts ({ className, isInElection }: Props): React.ReactElement {api.tx.staking.payoutStakers && (
- - {stashTotal && } - -
{validators?.map((payout): React.ReactNode => ( diff --git a/packages/page-staking/src/Targets/index.tsx b/packages/page-staking/src/Targets/index.tsx index 79225cd1cf..ccaeaccb64 100644 --- a/packages/page-staking/src/Targets/index.tsx +++ b/packages/page-staking/src/Targets/index.tsx @@ -210,6 +210,28 @@ function Targets ({ className }: Props): React.ReactElement { } }, [allAccounts, amount, electedInfo, favorites, lastReward, sortBy, sortFromMax]); + const header = useMemo(() => [ + [t('validators'), 'start', 3], + ...['rankComm', 'rankBondTotal', 'rankBondOwn', 'rankBondOther', 'rankOverall'].map((header) => [ + <>{labels[header]}, + `isClickable ${sortBy === header && 'ui--highlight--border'} number`, + 1, + (): void => _sort(header as 'rankComm') + ]), + [] + ], [_sort, labels, sortBy, sortFromMax, t]); + + const filter = useMemo(() => ( + + ), [_amount, t]); + return (
{ />
- } - header={[ - [t('validators'), 'start', 3], - ...['rankComm', 'rankBondTotal', 'rankBondOwn', 'rankBondOther', 'rankOverall'].map((header) => [ - <>{labels[header]}, - `isClickable ${sortBy === header && 'ui--highlight--border'} number`, - 1, - (): void => _sort(header as 'rankComm') - ]), - [] - ]} + filter={filter} + header={header} > {sorted?.map((info): React.ReactNode => { const { t } = useTranslation(); + const header = useMemo(() => [ + [t('members'), 'start', 3] + ], [t]); + return (
{members?.map((accountId): React.ReactNode => ( diff --git a/packages/page-tech-comm/src/Proposals/index.tsx b/packages/page-tech-comm/src/Proposals/index.tsx index 9c67a58ffa..72fe7a9052 100644 --- a/packages/page-tech-comm/src/Proposals/index.tsx +++ b/packages/page-tech-comm/src/Proposals/index.tsx @@ -5,7 +5,7 @@ import { Hash } from '@polkadot/types/interfaces'; import { ComponentProps as Props } from '../types'; -import React from 'react'; +import React, { useMemo } from 'react'; import { Button, Table } from '@polkadot/react-components'; import { useTranslation } from '../translate'; @@ -15,6 +15,14 @@ import Propose from './Propose'; function Proposals ({ className, isMember, members, prime, proposals }: Props): React.ReactElement { const { t } = useTranslation(); + const header = useMemo(() => [ + [t('proposals'), 'start', 2], + [t('threshold')], + [t('aye'), 'address'], + [t('nay'), 'address'], + [] + ], [t]); + return (
@@ -25,13 +33,7 @@ function Proposals ({ className, isMember, members, prime, proposals }: Props):
{proposals?.map((hash: Hash): React.ReactNode => ( [ + [isApprovals ? t('Approved') : t('Proposals'), 'start', 2], + [t('beneficiary'), 'address'], + [t('payment')], + [t('bond')], + [undefined, undefined, 2] + ], [isApprovals, t]); + return (
{proposals?.map((proposal): React.ReactNode => ( { const { t } = useTranslation(); + const header = useMemo(() => [ + [t('tips'), 'start'], + [t('finder'), 'address'], + [t('fee')], + [t('reason'), 'start'], + [], + [] + ], [t]); + return (
{hashes?.map((hash): React.ReactNode => (