Display schedule on democracy (#3287)
This commit is contained in:
parent
b7e9dc72da
commit
d048f06e60
49
packages/page-democracy/src/Overview/Scheduled.tsx
Normal file
49
packages/page-democracy/src/Overview/Scheduled.tsx
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright 2017-2020 @polkadot/app-democracy 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 { BlockNumber } from '@polkadot/types/interfaces';
|
||||
import { ScheduledExt } from './types';
|
||||
|
||||
import React from 'react';
|
||||
import { CallExpander } from '@polkadot/react-components';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import { BlockToTime } from '@polkadot/react-query';
|
||||
import { formatNumber } from '@polkadot/util';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
value: ScheduledExt;
|
||||
}
|
||||
|
||||
function Scheduled ({ className = '', value: { call, count, maybePeriodic, nextBlockNumber } }: Props): React.ReactElement<Props> {
|
||||
const { api } = useApi();
|
||||
const bestNumber = useCall<BlockNumber>(api.derive.chain.bestNumber, []);
|
||||
const period = maybePeriodic.unwrapOr(null);
|
||||
|
||||
return (
|
||||
<tr className={className}>
|
||||
<td className='all'><CallExpander value={call} /></td>
|
||||
<td className='number together'>
|
||||
{bestNumber && (
|
||||
<>
|
||||
<BlockToTime blocks={nextBlockNumber.sub(bestNumber)} />
|
||||
#{formatNumber(nextBlockNumber)}
|
||||
</>
|
||||
)}
|
||||
</td>
|
||||
<td className='number together'>
|
||||
{period && (
|
||||
formatNumber(period[0])
|
||||
)}
|
||||
</td>
|
||||
<td className='number together'>
|
||||
{period && (
|
||||
formatNumber(count) + ' / ' + formatNumber(period[1])
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(Scheduled);
|
||||
89
packages/page-democracy/src/Overview/Scheduler.tsx
Normal file
89
packages/page-democracy/src/Overview/Scheduler.tsx
Normal file
@ -0,0 +1,89 @@
|
||||
// Copyright 2017-2020 @polkadot/app-democracy 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 { BlockNumber, Scheduled } from '@polkadot/types/interfaces';
|
||||
import { ScheduledExt } from './types';
|
||||
|
||||
import React, { useMemo } from 'react';
|
||||
import { Table } from '@polkadot/react-components';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import { Option } from '@polkadot/types';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
import ScheduledView from './Scheduled';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
function Schedule ({ className = '' }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const bestNumber = useCall<BlockNumber>(api.derive.chain.bestNumber, []);
|
||||
const items = useCall<ScheduledExt[]>(api.query.scheduler.agenda.entries as any, [], {
|
||||
transform: (entries: [{ args: [BlockNumber] }, Option<Scheduled>[]][]): ScheduledExt[] =>
|
||||
entries
|
||||
.filter(([, vecSchedOpt]) => vecSchedOpt.some((schedOpt) => schedOpt.isSome))
|
||||
.reduce((items: ScheduledExt[], [key, vecSchedOpt]): ScheduledExt[] => {
|
||||
const blockNumber = key.args[0];
|
||||
|
||||
return vecSchedOpt
|
||||
.filter((schedOpt) => schedOpt.isSome)
|
||||
.map((schedOpt) => schedOpt.unwrap())
|
||||
.reduce((items: ScheduledExt[], { call, maybeId, maybePeriodic, priority }, index) => {
|
||||
items.push({ blockNumber, call, count: 0, key: `${blockNumber.toString()}-${index}`, maybeId, maybePeriodic, nextBlockNumber: blockNumber, priority });
|
||||
|
||||
return items;
|
||||
}, items);
|
||||
}, [])
|
||||
});
|
||||
|
||||
const header = useMemo(() => [
|
||||
[t('scheduled'), 'start'],
|
||||
[t('remaining')],
|
||||
[t('period')],
|
||||
[t('count')]
|
||||
], [t]);
|
||||
|
||||
let scheduled: ScheduledExt[] | undefined;
|
||||
|
||||
if (bestNumber && items) {
|
||||
scheduled = items
|
||||
.map((schedule): ScheduledExt => {
|
||||
if (schedule.maybePeriodic.isSome) {
|
||||
const [inc, max] = schedule.maybePeriodic.unwrap();
|
||||
const nextBlockNumber = schedule.blockNumber.toBn();
|
||||
let count = 0;
|
||||
|
||||
while (max.gtn(count) && nextBlockNumber.lt(bestNumber)) {
|
||||
count++;
|
||||
nextBlockNumber.iadd(inc);
|
||||
}
|
||||
|
||||
schedule.count = count;
|
||||
schedule.nextBlockNumber = nextBlockNumber;
|
||||
}
|
||||
|
||||
return schedule;
|
||||
})
|
||||
.filter(({ nextBlockNumber }) => nextBlockNumber.gt(bestNumber));
|
||||
}
|
||||
|
||||
return (
|
||||
<Table
|
||||
className={className}
|
||||
empty={scheduled?.length === 0 && t<string>('No active schedules')}
|
||||
header={header}
|
||||
>
|
||||
{scheduled?.map((scheduled): React.ReactNode => (
|
||||
<ScheduledView
|
||||
key={scheduled.key}
|
||||
value={scheduled}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(Schedule);
|
||||
@ -14,6 +14,7 @@ import DispatchQueue from './DispatchQueue';
|
||||
import Externals from './Externals';
|
||||
import Proposals from './Proposals';
|
||||
import Referendums from './Referendums';
|
||||
import Scheduler from './Scheduler';
|
||||
import Summary from './Summary';
|
||||
import PreImage from './PreImage';
|
||||
import Propose from './Propose';
|
||||
@ -54,6 +55,9 @@ function Overview ({ className }: Props): React.ReactElement<Props> {
|
||||
<Proposals />
|
||||
<DispatchQueue />
|
||||
<Externals />
|
||||
{api.query.scheduler && (
|
||||
<Scheduler />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
19
packages/page-democracy/src/Overview/types.ts
Normal file
19
packages/page-democracy/src/Overview/types.ts
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2017-2020 @polkadot/app-democracy 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 { BlockNumber, Call, SchedulePeriod, SchedulePriority } from '@polkadot/types/interfaces';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Bytes, Option } from '@polkadot/types';
|
||||
|
||||
export interface ScheduledExt {
|
||||
blockNumber: BlockNumber;
|
||||
call: Call;
|
||||
count: number;
|
||||
key: string;
|
||||
maybeId: Option<Bytes>;
|
||||
maybePeriodic: Option<SchedulePeriod>;
|
||||
priority: SchedulePriority;
|
||||
nextBlockNumber: BN;
|
||||
}
|
||||
@ -11,6 +11,7 @@ import { bnToBn } from '@polkadot/util';
|
||||
interface Props {
|
||||
className?: string;
|
||||
isDisabled?: boolean;
|
||||
size?: 'normal' | 'small'
|
||||
total?: UInt | BN | number | null;
|
||||
value?: UInt | BN | number | null;
|
||||
}
|
||||
@ -33,7 +34,7 @@ function DivClip ({ angle, type }: RotateProps): React.ReactElement<RotateProps>
|
||||
|
||||
const Clip = React.memo(DivClip);
|
||||
|
||||
function Progress ({ className = '', isDisabled, total, value }: Props): React.ReactElement<Props> | null {
|
||||
function Progress ({ className = '', isDisabled, size = 'normal', total, value }: Props): React.ReactElement<Props> | null {
|
||||
const _total = bnToBn(total || 0);
|
||||
const angle = _total.gtn(0)
|
||||
? (bnToBn(value || 0).muln(36000).div(_total).toNumber() / 100)
|
||||
@ -44,7 +45,7 @@ function Progress ({ className = '', isDisabled, total, value }: Props): React.R
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`ui--Progress${isDisabled ? ' isDisabled' : ''} ${className}`}>
|
||||
<div className={`ui--Progress${isDisabled ? ' isDisabled' : ''} ${size}Size ${className}`}>
|
||||
<div className='background ui--highlight--bg' />
|
||||
<Clip
|
||||
angle={
|
||||
@ -141,4 +142,20 @@ export default React.memo(styled(Progress)`
|
||||
text-shadow: 0 0 2px #f5f4f3;
|
||||
}
|
||||
}
|
||||
|
||||
&.smallSize {
|
||||
height: 2.25rem;
|
||||
width: 2.25rem;
|
||||
|
||||
.inner {
|
||||
bottom: 0.1875rem;
|
||||
left: 0.1875rem;
|
||||
right: 0.1875rem;
|
||||
top: 0.1875rem;
|
||||
}
|
||||
|
||||
div {
|
||||
font-size: 0.625rem;
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user