Add ParaLink component (#4625)
This commit is contained in:
parent
6e485f8370
commit
d7cdfecc18
@ -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<Props> {
|
||||
function Fund ({ bestNumber, className, info: { cap, end, owner, parachain, raised } }: Props): React.ReactElement<Props> {
|
||||
const remaining = useMemo(() => bestNumber && end.sub(bestNumber), [bestNumber, end]);
|
||||
|
||||
return (
|
||||
<tr className={className}>
|
||||
<td className='number'><h1>{id}</h1></td>
|
||||
<td className='number'><h1>{parachain}</h1></td>
|
||||
<td><ParaLink id={parachain} /></td>
|
||||
<td className='address'><AddressMini value={owner} /></td>
|
||||
<td className='number'><FormatBalance value={raised} /></td>
|
||||
<td className='number'><FormatBalance value={cap} /></td>
|
||||
|
||||
@ -31,7 +31,7 @@ function Funds ({ bestNumber, className, fundIndexes }: Props): React.ReactEleme
|
||||
const [funds, setFunds] = useState<Fund[] | undefined>();
|
||||
|
||||
const headerRef = useRef([
|
||||
[t('campaigns'), 'start', 2],
|
||||
[t('campaigns'), 'start', 3],
|
||||
[t('raised'), 'number'],
|
||||
[t('cap'), 'number'],
|
||||
[t('end'), 'number']
|
||||
|
||||
@ -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<Props> {
|
||||
const { api } = useApi();
|
||||
const { api: paraApi, endpoints } = useParaApi(id);
|
||||
const { api: paraApi } = useParaApi(id);
|
||||
const paraBest = useCall<BlockNumber>(paraApi?.rpc.chain.subscribeNewHeads, undefined, transformHeader);
|
||||
const lastRelayNumber = useCall<BN>(lastInclusion && api.rpc.chain.getHeader, [lastInclusion && lastInclusion[1]], transformHeader);
|
||||
const paraInfo = useCallMulti<QueryState>([
|
||||
@ -89,11 +89,6 @@ function Parachain ({ bestNumber, className = '', id, isScheduled, lastBacked, l
|
||||
[bestNumber, lastRelayNumber, paraInfo]
|
||||
);
|
||||
|
||||
const chainLink = useMemo(
|
||||
() => getChainLink(endpoints),
|
||||
[endpoints]
|
||||
);
|
||||
|
||||
return (
|
||||
<tr className={className}>
|
||||
<td className='number'><h1>{formatNumber(id)}</h1></td>
|
||||
@ -103,7 +98,7 @@ function Parachain ({ bestNumber, className = '', id, isScheduled, lastBacked, l
|
||||
icon='clock'
|
||||
/>
|
||||
)}</td>
|
||||
<td className='badge together'>{chainLink}</td>
|
||||
<td className='badge together'><ParaLink id={id} /></td>
|
||||
<td className='all start together hash'>{paraInfo.headHex}</td>
|
||||
<td className='number'>{blockDelay && <BlockToTime blocks={blockDelay} />}</td>
|
||||
<td className='number'>
|
||||
|
||||
@ -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<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const info = useCall<ParaGenesisArgs | null>(api.query.paras.upcomingParasGenesis, [id], transformGenesis);
|
||||
const endpoints = useParaEndpoints(id);
|
||||
|
||||
const chainLink = useMemo(
|
||||
() => getChainLink(endpoints),
|
||||
[endpoints]
|
||||
);
|
||||
|
||||
return (
|
||||
<tr key={id.toString()}>
|
||||
<td className='number'><h1>{formatNumber(id)}</h1></td>
|
||||
<td className='badge together'>{chainLink}</td>
|
||||
<td className='badge together'><ParaLink id={id} /></td>
|
||||
<td className='all start together hash'>
|
||||
{info && (
|
||||
sliceHex(info.genesisHead, 8)
|
||||
|
||||
@ -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<Pr
|
||||
const { allAccounts } = useAccounts();
|
||||
const { hasSudoKey, sudoKey } = useSudo();
|
||||
const proposal = useProposal(id, approvedIds, scheduled);
|
||||
const endpoints = useParaEndpoints(id);
|
||||
|
||||
const chainLink = useMemo(
|
||||
() => getChainLink(endpoints),
|
||||
[endpoints]
|
||||
);
|
||||
|
||||
const cancelTx = useMemo(
|
||||
() => api.tx.sudo && hasSudoKey
|
||||
@ -64,7 +58,7 @@ function Proposal ({ approvedIds, id, scheduled }: Props): React.ReactElement<Pr
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td className='badge together'>{chainLink}</td>
|
||||
<td className='badge together'><ParaLink id={id} /></td>
|
||||
<td className='start together'>{proposal.proposal?.name.toUtf8()}</td>
|
||||
<td className='address'>{proposal.proposal && <AddressSmall value={proposal.proposal.proposer} />}</td>
|
||||
<td className='number media--1100'>{proposal.proposal && <FormatBalance value={proposal.proposal.balance} />}</td>
|
||||
|
||||
@ -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;
|
||||
}
|
||||
`);
|
||||
|
||||
12
packages/page-parachains/src/util.ts
Normal file
12
packages/page-parachains/src/util.ts
Normal file
@ -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;
|
||||
}
|
||||
@ -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 (
|
||||
<>
|
||||
<ChainImg
|
||||
isInline
|
||||
logo={info || 'empty'}
|
||||
withoutHl
|
||||
/>
|
||||
<a
|
||||
className='chainAlign'
|
||||
href={`${window.location.origin}${window.location.pathname}?rpc=${encodeURIComponent(value)}`}
|
||||
>{text}</a>
|
||||
</>
|
||||
);
|
||||
}
|
||||
51
packages/react-components/src/ParaLink.tsx
Normal file
51
packages/react-components/src/ParaLink.tsx
Normal file
@ -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<Props> | null {
|
||||
const endpoints = useParaEndpoints(id);
|
||||
|
||||
if (!endpoints.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { info, text, value } = endpoints[endpoints.length - 1];
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<ChainImg
|
||||
isInline
|
||||
logo={info || 'empty'}
|
||||
withoutHl
|
||||
/>
|
||||
<a
|
||||
className='chainAlign'
|
||||
href={`${window.location.origin}${window.location.pathname}?rpc=${encodeURIComponent(value)}`}
|
||||
>{text}</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(styled(ParaLink)`
|
||||
vertical-align: middle;
|
||||
|
||||
a.chainAlign {
|
||||
display: inline-block;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
`);
|
||||
@ -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';
|
||||
|
||||
Loading…
Reference in New Issue
Block a user