Displays countdowns in time (#2339)

* Displays countdowns in time

* Lint
This commit is contained in:
Jaco Greeff 2020-03-07 13:59:20 +01:00 committed by GitHub
parent f8ad069c98
commit 8165033991
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 126 additions and 51 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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'

View File

@ -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
}}
/>
)

View File

@ -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>

View File

@ -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>

View File

@ -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) {

View 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>
);
}

View File

@ -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>
);
}

View File

@ -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';