Displays countdowns in time (#2339)
* Displays countdowns in time * Lint
This commit is contained in:
parent
f8ad069c98
commit
8165033991
@ -45,7 +45,8 @@ export default function Summary ({ bestNumber, className, electionsInfo: { membe
|
||||
label={t('term progress')}
|
||||
progress={{
|
||||
total: termDuration,
|
||||
value: bestNumber.mod(termDuration)
|
||||
value: bestNumber.mod(termDuration),
|
||||
withTime: true
|
||||
}}
|
||||
/>
|
||||
</section>
|
||||
|
||||
@ -46,7 +46,8 @@ function Summary ({ t }: Props): React.ReactElement<Props> {
|
||||
label={t('launch period')}
|
||||
progress={{
|
||||
value: bestNumber.mod(api.consts.democracy.launchPeriod).addn(1),
|
||||
total: api.consts.democracy.launchPeriod
|
||||
total: api.consts.democracy.launchPeriod,
|
||||
withTime: true
|
||||
}}
|
||||
/>
|
||||
</section>
|
||||
|
||||
@ -4,13 +4,16 @@
|
||||
|
||||
import { I18nProps as Props } from '@polkadot/react-components/types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import React from 'react';
|
||||
import { SummaryBox, CardSummary } from '@polkadot/react-components';
|
||||
import { BestFinalized, BestNumber, TimeNow, TimePeriod, TotalIssuance } from '@polkadot/react-query';
|
||||
import { BestFinalized, BestNumber, BlockToTime, TimeNow, TotalIssuance } from '@polkadot/react-query';
|
||||
|
||||
import SummarySession from './SummarySession';
|
||||
import translate from './translate';
|
||||
|
||||
const ONE_BLOCK = new BN(1);
|
||||
|
||||
function Summary ({ t }: Props): React.ReactElement<Props> {
|
||||
return (
|
||||
<SummaryBox>
|
||||
@ -22,7 +25,7 @@ function Summary ({ t }: Props): React.ReactElement<Props> {
|
||||
className='ui--media-small'
|
||||
label={t('target')}
|
||||
>
|
||||
<TimePeriod />
|
||||
<BlockToTime blocks={ONE_BLOCK} />
|
||||
</CardSummary>
|
||||
<CardSummary
|
||||
className='ui--media-small'
|
||||
|
||||
@ -40,7 +40,8 @@ export default function SummarySession ({ withEra = true, withSession = true }:
|
||||
label={sessionLabel}
|
||||
progress={{
|
||||
total: sessionInfo.sessionLength,
|
||||
value: sessionInfo.sessionProgress
|
||||
value: sessionInfo.sessionProgress,
|
||||
withTime: true
|
||||
}}
|
||||
/>
|
||||
)
|
||||
@ -57,7 +58,8 @@ export default function SummarySession ({ withEra = true, withSession = true }:
|
||||
label={eraLabel}
|
||||
progress={{
|
||||
total: sessionInfo.eraLength,
|
||||
value: sessionInfo.eraProgress
|
||||
value: sessionInfo.eraProgress,
|
||||
withTime: true
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
||||
@ -73,7 +73,8 @@ function Summary ({ className, info }: Props): React.ReactElement<Props> {
|
||||
label={t('rotation')}
|
||||
progress={{
|
||||
total: api.consts.society.rotationPeriod as BlockNumber,
|
||||
value: bestNumber.mod(api.consts.society.rotationPeriod as BlockNumber)
|
||||
value: bestNumber.mod(api.consts.society.rotationPeriod as BlockNumber),
|
||||
withTime: true
|
||||
}}
|
||||
/>
|
||||
</section>
|
||||
@ -82,7 +83,8 @@ function Summary ({ className, info }: Props): React.ReactElement<Props> {
|
||||
label={t('challenge')}
|
||||
progress={{
|
||||
total: api.consts.society.challengePeriod as BlockNumber,
|
||||
value: bestNumber.mod(api.consts.society.challengePeriod as BlockNumber)
|
||||
value: bestNumber.mod(api.consts.society.challengePeriod as BlockNumber),
|
||||
withTime: true
|
||||
}}
|
||||
/>
|
||||
</section>
|
||||
|
||||
@ -57,7 +57,8 @@ export default function Summary ({ approvalCount, proposalCount }: Props): React
|
||||
label={t('spend period')}
|
||||
progress={{
|
||||
total: spendPeriod,
|
||||
value: bestNumber.mod(spendPeriod)
|
||||
value: bestNumber.mod(spendPeriod),
|
||||
withTime: true
|
||||
}}
|
||||
/>
|
||||
</section>
|
||||
|
||||
@ -12,6 +12,7 @@ import { formatNumber, isUndefined } from '@polkadot/util';
|
||||
|
||||
import Progress, { Colors as ProgressColors } from './Progress';
|
||||
import Labelled from './Labelled';
|
||||
import { BlockToTime } from '@polkadot/react-query';
|
||||
|
||||
interface ProgressProps {
|
||||
color?: ProgressColors;
|
||||
@ -19,6 +20,7 @@ interface ProgressProps {
|
||||
isPercent?: boolean;
|
||||
total?: BN | UInt;
|
||||
value?: BN | UInt;
|
||||
withTime?: boolean;
|
||||
}
|
||||
|
||||
interface Props extends BareProps {
|
||||
@ -51,6 +53,8 @@ function CardSummary ({ children, className, help, label, progress }: Props): Re
|
||||
return null;
|
||||
}
|
||||
|
||||
const isTimed = progress && progress.withTime && !isUndefined(progress.total);
|
||||
|
||||
return (
|
||||
<article className={className}>
|
||||
<Labelled
|
||||
@ -60,13 +64,21 @@ function CardSummary ({ children, className, help, label, progress }: Props): Re
|
||||
>
|
||||
{children}{
|
||||
progress && !progress.hideValue && (
|
||||
!left || isUndefined(progress.total)
|
||||
? '-'
|
||||
: `${left}${progress.isPercent ? '' : '/'}${
|
||||
progress.isPercent
|
||||
? '%'
|
||||
: formatNumber(progress.total)
|
||||
}`
|
||||
<>
|
||||
{isTimed && (
|
||||
<BlockToTime blocks={progress.total} />
|
||||
)}
|
||||
<div className={isTimed ? 'isSecondary' : 'isPrimary'}>
|
||||
{!left || isUndefined(progress.total)
|
||||
? '-'
|
||||
: `${left}${progress.isPercent ? '' : '/'}${
|
||||
progress.isPercent
|
||||
? '%'
|
||||
: formatNumber(progress.total)
|
||||
}`
|
||||
}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
{progress && <Progress {...progress} />}
|
||||
@ -120,6 +132,13 @@ export default styled(CardSummary)`
|
||||
margin: 0.2rem 0 -0.5rem !important;
|
||||
background: rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
.isSecondary {
|
||||
font-size: 1.1rem;
|
||||
font-weight: normal;
|
||||
line-height: 1.1rem;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media(max-width: 767px) {
|
||||
|
||||
80
packages/react-query/src/BlockToTime.tsx
Normal file
80
packages/react-query/src/BlockToTime.tsx
Normal file
@ -0,0 +1,80 @@
|
||||
// Copyright 2017-2020 @polkadot/react-query authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { BareProps } from '@polkadot/react-api/types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import React, { useMemo } from 'react';
|
||||
import { useApi } from '@polkadot/react-hooks';
|
||||
|
||||
import { useTranslation } from './translate';
|
||||
|
||||
interface Props extends BareProps {
|
||||
blocks?: BN;
|
||||
children?: React.ReactNode;
|
||||
label?: React.ReactNode;
|
||||
}
|
||||
|
||||
type Time = [number, number, number, number];
|
||||
|
||||
const HRS = 60 * 60;
|
||||
const DAY = HRS * 24;
|
||||
|
||||
function addTime (a: Time, b: Time): Time {
|
||||
return [a[0] + b[0], a[1] + b[1], a[2] + b[2], a[3] + b[3]];
|
||||
}
|
||||
|
||||
function extractTime (value?: number): Time {
|
||||
if (!value) {
|
||||
return [0, 0, 0, 0];
|
||||
} else if (value < 60) {
|
||||
return [0, 0, 0, value];
|
||||
}
|
||||
|
||||
const mins = value / 60;
|
||||
|
||||
if (mins < 60) {
|
||||
const round = Math.floor(mins);
|
||||
|
||||
return addTime([0, 0, round, 0], extractTime(value - (round * 60)));
|
||||
}
|
||||
|
||||
const hrs = mins / 60;
|
||||
|
||||
if (hrs < 24) {
|
||||
const round = Math.floor(hrs);
|
||||
|
||||
return addTime([0, round, 0, 0], extractTime(value - (round * HRS)));
|
||||
}
|
||||
|
||||
const round = Math.floor(hrs / 24);
|
||||
|
||||
return addTime([round, 0, 0, 0], extractTime(value - (round * DAY)));
|
||||
}
|
||||
|
||||
export default function BlockToTime ({ blocks, children, className, label, style }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const time = useMemo((): string => {
|
||||
const blockTime = (api.consts.babe?.expectedBlockTime || (api.consts.timestamp.minimumPeriod.muln(2))).divn(1000);
|
||||
const time = extractTime(blocks?.mul(blockTime).toNumber());
|
||||
|
||||
return [
|
||||
time[0] ? (time[0] > 1) ? t('{{d}} days', { replace: { d: time[0] } }) : t('1 day') : null,
|
||||
time[1] ? (time[1] > 1) ? t('{{h}} hrs', { replace: { h: time[1] } }) : t('1 hr') : null,
|
||||
time[2] ? (time[2] > 1) ? t('{{m}} mins', { replace: { m: time[2] } }) : t('1 min') : null,
|
||||
time[3] ? (time[3] > 1) ? t('{{s}} s', { replace: { s: time[3] } }) : t('1 s') : null
|
||||
].filter((value): value is string => !!value)
|
||||
.join(', ');
|
||||
}, [api, t]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
{label || ''}{time}{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
// Copyright 2017-2020 @polkadot/react-query authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { BareProps } from '@polkadot/react-api/types';
|
||||
|
||||
import React from 'react';
|
||||
import { useApi } from '@polkadot/react-hooks';
|
||||
import { formatNumber } from '@polkadot/util';
|
||||
|
||||
interface Props extends BareProps {
|
||||
children?: React.ReactNode;
|
||||
label?: React.ReactNode;
|
||||
}
|
||||
|
||||
export default function TimePeriod ({ children, className, label, style }: Props): React.ReactElement<Props> {
|
||||
const { api } = useApi();
|
||||
const minimumPeriod = api.consts?.timestamp?.minimumPeriod;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
{label || ''}{
|
||||
api.consts?.babe?.expectedBlockTime
|
||||
? `${formatNumber(api.consts.babe.expectedBlockTime.toNumber() / 1000)}s`
|
||||
: minimumPeriod
|
||||
? `${formatNumber(minimumPeriod.gtn(1000) ? (minimumPeriod.toNumber() / 500) : (minimumPeriod.toNumber() * 2))}s`
|
||||
: '-'
|
||||
}{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -7,6 +7,7 @@ export { default as Balance } from './Balance';
|
||||
export { default as BalanceFree } from './BalanceFree';
|
||||
export { default as BalanceVoting } from './BalanceVoting';
|
||||
export { BlockAuthors, BlockAuthorsContext, ValidatorsContext } from './BlockAuthors';
|
||||
export { default as BlockToTime } from './BlockToTime';
|
||||
export { default as Bonded } from './Bonded';
|
||||
export { default as BestFinalized } from './BestFinalized';
|
||||
export { default as BestNumber } from './BestNumber';
|
||||
@ -19,5 +20,4 @@ export { default as NodeName } from './NodeName';
|
||||
export { default as NodeVersion } from './NodeVersion';
|
||||
export { default as Nonce } from './Nonce';
|
||||
export { default as TimeNow } from './TimeNow';
|
||||
export { default as TimePeriod } from './TimePeriod';
|
||||
export { default as TotalIssuance } from './TotalIssuance';
|
||||
|
||||
Loading…
Reference in New Issue
Block a user