From d7cdfecc183da44830ad5c5348e535fd2da933fd Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Sat, 6 Feb 2021 16:00:52 +0100 Subject: [PATCH] Add ParaLink component (#4625) --- packages/page-crowdloan/src/Fund.tsx | 7 +-- packages/page-crowdloan/src/Funds.tsx | 2 +- .../src/Overview/Parachain.tsx | 13 ++--- .../page-parachains/src/Overview/Upcoming.tsx | 15 ++---- .../src/Proposals/Proposal.tsx | 14 ++--- packages/page-parachains/src/index.tsx | 7 --- packages/page-parachains/src/util.ts | 12 +++++ packages/page-parachains/src/util.tsx | 39 -------------- packages/react-components/src/ParaLink.tsx | 51 +++++++++++++++++++ packages/react-components/src/index.tsx | 1 + 10 files changed, 82 insertions(+), 79 deletions(-) create mode 100644 packages/page-parachains/src/util.ts delete mode 100644 packages/page-parachains/src/util.tsx create mode 100644 packages/react-components/src/ParaLink.tsx diff --git a/packages/page-crowdloan/src/Fund.tsx b/packages/page-crowdloan/src/Fund.tsx index 63404bf51b..bb6df2f37f 100644 --- a/packages/page-crowdloan/src/Fund.tsx +++ b/packages/page-crowdloan/src/Fund.tsx @@ -6,7 +6,7 @@ import type { FundIndex, FundInfo } from '@polkadot/types/interfaces'; import React, { useMemo } from 'react'; -import { AddressMini } from '@polkadot/react-components'; +import { AddressMini, ParaLink } from '@polkadot/react-components'; import { BlockToTime, FormatBalance } from '@polkadot/react-query'; import { formatNumber } from '@polkadot/util'; @@ -17,12 +17,13 @@ interface Props { info: FundInfo; } -function Fund ({ bestNumber, className, id, info: { cap, end, owner, raised } }: Props): React.ReactElement { +function Fund ({ bestNumber, className, info: { cap, end, owner, parachain, raised } }: Props): React.ReactElement { const remaining = useMemo(() => bestNumber && end.sub(bestNumber), [bestNumber, end]); return ( -

{id}

+

{parachain}

+ diff --git a/packages/page-crowdloan/src/Funds.tsx b/packages/page-crowdloan/src/Funds.tsx index 413a80a13f..356166b4e3 100644 --- a/packages/page-crowdloan/src/Funds.tsx +++ b/packages/page-crowdloan/src/Funds.tsx @@ -31,7 +31,7 @@ function Funds ({ bestNumber, className, fundIndexes }: Props): React.ReactEleme const [funds, setFunds] = useState(); const headerRef = useRef([ - [t('campaigns'), 'start', 2], + [t('campaigns'), 'start', 3], [t('raised'), 'number'], [t('cap'), 'number'], [t('end'), 'number'] diff --git a/packages/page-parachains/src/Overview/Parachain.tsx b/packages/page-parachains/src/Overview/Parachain.tsx index 1402970c29..6de0676d27 100644 --- a/packages/page-parachains/src/Overview/Parachain.tsx +++ b/packages/page-parachains/src/Overview/Parachain.tsx @@ -8,12 +8,12 @@ import type { Codec } from '@polkadot/types/types'; import BN from 'bn.js'; import React, { useMemo } from 'react'; -import { Badge } from '@polkadot/react-components'; +import { Badge, ParaLink } from '@polkadot/react-components'; import { useApi, useCall, useCallMulti, useParaApi } from '@polkadot/react-hooks'; import { BlockToTime } from '@polkadot/react-query'; import { BN_ONE, formatNumber } from '@polkadot/util'; -import { getChainLink, sliceHex } from '../util'; +import { sliceHex } from '../util'; interface Props { bestNumber?: BN; @@ -65,7 +65,7 @@ const optionsMulti = { function Parachain ({ bestNumber, className = '', id, isScheduled, lastBacked, lastInclusion }: Props): React.ReactElement { const { api } = useApi(); - const { api: paraApi, endpoints } = useParaApi(id); + const { api: paraApi } = useParaApi(id); const paraBest = useCall(paraApi?.rpc.chain.subscribeNewHeads, undefined, transformHeader); const lastRelayNumber = useCall(lastInclusion && api.rpc.chain.getHeader, [lastInclusion && lastInclusion[1]], transformHeader); const paraInfo = useCallMulti([ @@ -89,11 +89,6 @@ function Parachain ({ bestNumber, className = '', id, isScheduled, lastBacked, l [bestNumber, lastRelayNumber, paraInfo] ); - const chainLink = useMemo( - () => getChainLink(endpoints), - [endpoints] - ); - return (

{formatNumber(id)}

@@ -103,7 +98,7 @@ function Parachain ({ bestNumber, className = '', id, isScheduled, lastBacked, l icon='clock' /> )} - {chainLink} + {paraInfo.headHex} {blockDelay && } diff --git a/packages/page-parachains/src/Overview/Upcoming.tsx b/packages/page-parachains/src/Overview/Upcoming.tsx index 97b3835f56..735529f73b 100644 --- a/packages/page-parachains/src/Overview/Upcoming.tsx +++ b/packages/page-parachains/src/Overview/Upcoming.tsx @@ -4,13 +4,14 @@ import type { Option } from '@polkadot/types'; import type { ParaGenesisArgs, ParaId } from '@polkadot/types/interfaces'; -import React, { useMemo } from 'react'; +import React from 'react'; -import { useApi, useCall, useParaEndpoints } from '@polkadot/react-hooks'; +import { ParaLink } from '@polkadot/react-components'; +import { useApi, useCall } from '@polkadot/react-hooks'; import { formatNumber } from '@polkadot/util'; import { useTranslation } from '../translate'; -import { getChainLink, sliceHex } from '../util'; +import { sliceHex } from '../util'; interface Props { id: ParaId; @@ -24,17 +25,11 @@ function Upcoming ({ id }: Props): React.ReactElement { const { t } = useTranslation(); const { api } = useApi(); const info = useCall(api.query.paras.upcomingParasGenesis, [id], transformGenesis); - const endpoints = useParaEndpoints(id); - - const chainLink = useMemo( - () => getChainLink(endpoints), - [endpoints] - ); return (

{formatNumber(id)}

- {chainLink} + {info && ( sliceHex(info.genesisHead, 8) diff --git a/packages/page-parachains/src/Proposals/Proposal.tsx b/packages/page-parachains/src/Proposals/Proposal.tsx index 4574f29cb0..8de86f0094 100644 --- a/packages/page-parachains/src/Proposals/Proposal.tsx +++ b/packages/page-parachains/src/Proposals/Proposal.tsx @@ -6,13 +6,13 @@ import type { ScheduledProposals } from '../types'; import React, { useMemo } from 'react'; -import { AddressMini, AddressSmall, Badge, TxButton } from '@polkadot/react-components'; -import { useAccounts, useApi, useParaEndpoints, useSudo } from '@polkadot/react-hooks'; +import { AddressMini, AddressSmall, Badge, ParaLink, TxButton } from '@polkadot/react-components'; +import { useAccounts, useApi, useSudo } from '@polkadot/react-hooks'; import { FormatBalance } from '@polkadot/react-query'; import { formatNumber } from '@polkadot/util'; import { useTranslation } from '../translate'; -import { getChainLink, sliceHex } from '../util'; +import { sliceHex } from '../util'; import { useProposal } from './useProposals'; interface Props { @@ -27,12 +27,6 @@ function Proposal ({ approvedIds, id, scheduled }: Props): React.ReactElement getChainLink(endpoints), - [endpoints] - ); const cancelTx = useMemo( () => api.tx.sudo && hasSudoKey @@ -64,7 +58,7 @@ function Proposal ({ approvedIds, id, scheduled }: Props): React.ReactElement )} - {chainLink} + {proposal.proposal?.name.toUtf8()} {proposal.proposal && } {proposal.proposal && } diff --git a/packages/page-parachains/src/index.tsx b/packages/page-parachains/src/index.tsx index e6885a42c9..40beb3ee2f 100644 --- a/packages/page-parachains/src/index.tsx +++ b/packages/page-parachains/src/index.tsx @@ -62,11 +62,4 @@ export default React.memo(styled(ParachainsApp)` .parachains--hidden { display: none; } - - a.chainAlign { - display: inline-block; - height: 24px; - line-height: 24px; - vertical-align: middle; - } `); diff --git a/packages/page-parachains/src/util.ts b/packages/page-parachains/src/util.ts new file mode 100644 index 0000000000..c80855f40c --- /dev/null +++ b/packages/page-parachains/src/util.ts @@ -0,0 +1,12 @@ +// Copyright 2017-2021 @polkadot/app-parachains authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import type { Codec } from '@polkadot/types/types'; + +export function sliceHex (value: Codec, max: number): string { + const hex = value.toHex(); + + return hex.length > ((2 * max) + 2) + ? `${hex.slice(0, max + 2)}…${hex.slice(-max)}` + : hex; +} diff --git a/packages/page-parachains/src/util.tsx b/packages/page-parachains/src/util.tsx deleted file mode 100644 index 3879b64b62..0000000000 --- a/packages/page-parachains/src/util.tsx +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2017-2021 @polkadot/app-parachains authors & contributors -// SPDX-License-Identifier: Apache-2.0 - -import type { LinkOption } from '@polkadot/apps-config/settings/types'; -import type { Codec } from '@polkadot/types/types'; - -import React from 'react'; - -import { ChainImg } from '@polkadot/react-components'; - -export function sliceHex (value: Codec, max: number): string { - const hex = value.toHex(); - - return hex.length > ((2 * max) + 2) - ? `${hex.slice(0, max + 2)}…${hex.slice(-max)}` - : hex; -} - -export function getChainLink (endpoints: LinkOption[]): React.ReactNode { - if (!endpoints.length) { - return null; - } - - const { info, text, value } = endpoints[endpoints.length - 1]; - - return ( - <> - - {text} - - ); -} diff --git a/packages/react-components/src/ParaLink.tsx b/packages/react-components/src/ParaLink.tsx new file mode 100644 index 0000000000..095aa8bf16 --- /dev/null +++ b/packages/react-components/src/ParaLink.tsx @@ -0,0 +1,51 @@ +// Copyright 2017-2021 @polkadot/app-staking authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import type BN from 'bn.js'; + +import React from 'react'; +import styled from 'styled-components'; + +import { useParaEndpoints } from '@polkadot/react-hooks'; + +import ChainImg from './ChainImg'; + +interface Props { + className?: string; + id: BN; +} + +function ParaLink ({ className, id }: Props): React.ReactElement | null { + const endpoints = useParaEndpoints(id); + + if (!endpoints.length) { + return null; + } + + const { info, text, value } = endpoints[endpoints.length - 1]; + + return ( +
+ + {text} +
+ ); +} + +export default React.memo(styled(ParaLink)` + vertical-align: middle; + + a.chainAlign { + display: inline-block; + height: 24px; + line-height: 24px; + vertical-align: middle; + } +`); diff --git a/packages/react-components/src/index.tsx b/packages/react-components/src/index.tsx index 8ecf7e411a..87fac7c81d 100644 --- a/packages/react-components/src/index.tsx +++ b/packages/react-components/src/index.tsx @@ -71,6 +71,7 @@ export { default as Nonce } from './Nonce'; export { default as Output } from './Output'; export { default as Password } from './Password'; export { default as PasswordStrength } from './PasswordStrength'; +export { default as ParaLink } from './ParaLink'; export { default as Popup } from './Popup'; export { default as Progress } from './Progress'; export { default as ProposedAction } from './ProposedAction';