Wrap Latency/Stats graphs inside NextTick (#8875)

This commit is contained in:
Jaco 2023-01-24 10:29:48 +02:00 committed by GitHub
parent 9a4710c668
commit 2efde7c452
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 96 additions and 39 deletions

View File

@ -7,7 +7,7 @@ import type { ApiStats } from '@polkadot/react-hooks/ctx/types';
import React, { useMemo } from 'react';
import styled from 'styled-components';
import { CardSummary, Spinner, SummaryBox } from '@polkadot/react-components';
import { CardSummary, NextTick, SummaryBox } from '@polkadot/react-components';
import { useApiStats } from '@polkadot/react-hooks';
import { formatNumber } from '@polkadot/util';
@ -111,38 +111,55 @@ function Api ({ className }: Props): React.ReactElement<Props> {
[stats]
);
if (stats.length <= 3) {
return <Spinner />;
}
const { stats: { total: { bytesRecv, bytesSent, requests: tReq, subscriptions: tSub } } } = stats[stats.length - 1];
const last = stats[stats.length - 1];
const isLoaded = last && (stats.length > 3);
const EMPTY_NUMBER = <span className='--tmp'>99</span>;
const EMPTY_BYTES = <span className='--tmp'>1,000kB</span>;
return (
<StyledDiv className={className}>
<SummaryBox>
<section>
<CardSummary label={t<string>('sent')}>{formatNumber(bytesSent / 1024)}kB</CardSummary>
<CardSummary label={t<string>('recv')}>{formatNumber(bytesRecv / 1024)}kB</CardSummary>
<CardSummary label={t<string>('sent')}>
{isLoaded
? <>{formatNumber(last.stats.total.bytesSent / 1024)}kB</>
: EMPTY_BYTES}
</CardSummary>
<CardSummary label={t<string>('recv')}>
{isLoaded
? <>{formatNumber(last.stats.total.bytesRecv / 1024)}kB</>
: EMPTY_BYTES}
</CardSummary>
</section>
<section>
<CardSummary label={t<string>('total req')}>{formatNumber(tReq)}</CardSummary>
<CardSummary label={t<string>('total sub')}>{formatNumber(tSub)}</CardSummary>
<CardSummary label={t<string>('total req')}>
{isLoaded
? <>{formatNumber(last.stats.total.requests)}</>
: EMPTY_NUMBER}
</CardSummary>
<CardSummary label={t<string>('total sub')}>
{isLoaded
? <>{formatNumber(last.stats.total.subscriptions)}</>
: EMPTY_NUMBER}
</CardSummary>
</section>
</SummaryBox>
<Chart
colors={COLORS_REQUESTS}
legends={requestsLegend}
options={OPTIONS}
title={t<string>('requests made')}
value={requestsChart}
/>
<Chart
colors={COLORS_BYTES}
legends={bytesLegend}
options={OPTIONS}
title={t<string>('bytes transferred')}
value={bytesChart}
/>
<NextTick isActive={isLoaded}>
<Chart
colors={COLORS_REQUESTS}
legends={requestsLegend}
options={OPTIONS}
title={t<string>('requests made')}
value={requestsChart}
/>
<Chart
colors={COLORS_BYTES}
legends={bytesLegend}
options={OPTIONS}
title={t<string>('bytes transferred')}
value={bytesChart}
/>
</NextTick>
</StyledDiv>
);
}

View File

@ -6,7 +6,7 @@ import type { ChartContents, Detail } from './types';
import React, { useEffect, useMemo, useState } from 'react';
import styled from 'styled-components';
import { CardSummary, Spinner, SummaryBox } from '@polkadot/react-components';
import { CardSummary, NextTick, SummaryBox } from '@polkadot/react-components';
import { formatNumber, nextTick } from '@polkadot/util';
import { useTranslation } from '../translate';
@ -178,20 +178,17 @@ function Latency ({ className }: Props): React.ReactElement<Props> {
: EMPTY_TIME}
</CardSummary>
</SummaryBox>
{isLoaded
? ORDER.map((key, i) =>
shouldRender[i] && (
<Chart
colors={COLORS[key]}
key={key}
legends={legend[key]}
title={title[key]}
value={points[key]}
/>
)
)
: <Spinner />
}
<NextTick isActive={isLoaded}>
{ORDER.map((key) => (
<Chart
colors={COLORS[key]}
key={key}
legends={legend[key]}
title={title[key]}
value={points[key]}
/>
))}
</NextTick>
</StyledDiv>
);
}

View File

@ -0,0 +1,42 @@
// Copyright 2017-2023 @polkadot/react-components authors & contributors
// SPDX-License-Identifier: Apache-2.0
import React, { useEffect, useState } from 'react';
import { nextTick } from '@polkadot/util';
import Spinner from './Spinner';
interface Props {
children: React.ReactNode[];
isActive?: boolean;
}
function NextTick ({ children, isActive = true }: Props): React.ReactElement<Props> {
const [visibility, setVisibility] = useState(() => new Array<boolean>(children.length).fill(false));
useEffect((): void => {
if (isActive) {
const index = visibility.findIndex((v) => !v);
if (index !== -1) {
nextTick(() =>
setVisibility(
visibility.map((v, i) => (i === index) || v)
)
);
}
}
}, [isActive, visibility]);
return (
<>
{isActive
? visibility.map((isVisible, index) => isVisible && children[index])
: <Spinner />
}
</>
);
}
export default React.memo(NextTick);

View File

@ -71,6 +71,7 @@ export { default as MarkError } from './MarkError';
export { default as MarkWarning } from './MarkWarning';
export { default as Menu } from './Menu';
export { default as Modal } from './Modal';
export { default as NextTick } from './NextTick';
export { default as Nonce } from './Nonce';
export { default as Output } from './Output';
export { default as Password } from './Password';