Group by track (#8152)
* Group by track * OCD * Move trackName extraction * Adjust empty message
This commit is contained in:
parent
95027e8fca
commit
5a3680dfe9
@ -7,6 +7,7 @@ import type { BN } from '@polkadot/util';
|
||||
import type { PalletReferenda } from '../../types';
|
||||
|
||||
import React, { useMemo } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { AddressMini } from '@polkadot/react-components';
|
||||
|
||||
@ -16,6 +17,7 @@ import Refund from './Refund';
|
||||
interface Props {
|
||||
canDeposit?: boolean;
|
||||
canRefund?: boolean;
|
||||
className?: string;
|
||||
decision: Option<PalletReferendaDeposit> | null;
|
||||
id: BN;
|
||||
palletReferenda: PalletReferenda;
|
||||
@ -23,14 +25,14 @@ interface Props {
|
||||
track?: PalletReferendaTrackInfo;
|
||||
}
|
||||
|
||||
function Deposits ({ canDeposit, canRefund, decision, id, palletReferenda, submit, track }: Props): React.ReactElement<Props> {
|
||||
function Deposits ({ canDeposit, canRefund, className = '', decision, id, palletReferenda, submit, track }: Props): React.ReactElement<Props> {
|
||||
const [valSubmit, valDeposit] = useMemo(
|
||||
() => [submit, decision && decision.unwrapOr(null)],
|
||||
[decision, submit]
|
||||
);
|
||||
|
||||
return (
|
||||
<td className='address'>
|
||||
<td className={`${className} address`}>
|
||||
{valSubmit && (
|
||||
<AddressMini
|
||||
balance={valSubmit.amount}
|
||||
@ -65,4 +67,8 @@ function Deposits ({ canDeposit, canRefund, decision, id, palletReferenda, submi
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(Deposits);
|
||||
export default React.memo(styled(Deposits)`
|
||||
.ui--AddressMini+.ui--Button {
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
`);
|
||||
|
||||
@ -10,7 +10,6 @@ import { formatNumber } from '@polkadot/util';
|
||||
import Killed from './RefKilled';
|
||||
import Ongoing from './RefOngoing';
|
||||
import Tuple from './RefTuple';
|
||||
import { getTrackName } from './util';
|
||||
|
||||
const Components: Record<string, React.ComponentType<Props>> = {
|
||||
Killed,
|
||||
@ -18,26 +17,18 @@ const Components: Record<string, React.ComponentType<Props>> = {
|
||||
};
|
||||
|
||||
function Referendum (props: Props): React.ReactElement<Props> {
|
||||
const { className, value: { id, info, track } } = props;
|
||||
const { className, value: { id, info } } = props;
|
||||
|
||||
const Component = useMemo(
|
||||
() => Components[info.type] || Tuple,
|
||||
[info]
|
||||
);
|
||||
|
||||
const trackName = useMemo(
|
||||
() => track && getTrackName(track),
|
||||
[track]
|
||||
);
|
||||
|
||||
return (
|
||||
<tr className={className}>
|
||||
<td className='number'>
|
||||
<h1>{formatNumber(id)}</h1>
|
||||
</td>
|
||||
<td className='number'>
|
||||
{trackName}
|
||||
</td>
|
||||
{/* <td>
|
||||
<textarea
|
||||
rows={8}
|
||||
|
||||
@ -19,7 +19,7 @@ import { getTypeDef } from '@polkadot/types/create';
|
||||
import { formatNumber, isHex } from '@polkadot/util';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
import { getTrackName } from './util';
|
||||
import { getTrackName } from '../util';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
// Copyright 2017-2022 @polkadot/app-referenda authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { PalletReferenda, PalletVote } from '../types';
|
||||
import type { PalletReferenda, PalletVote, ReferendaGroup } from '../types';
|
||||
|
||||
import React, { useMemo, useRef } from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
|
||||
import AddPreimage from '@polkadot/app-preimages/Preimages/Add';
|
||||
import { Button, Table } from '@polkadot/react-components';
|
||||
@ -28,19 +28,14 @@ interface Props {
|
||||
function Referenda ({ className, members, palletReferenda, palletVote }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { allAccounts } = useAccounts();
|
||||
const [referenda, tracks] = useReferenda(palletReferenda);
|
||||
const summary = useSummary(palletReferenda, referenda);
|
||||
const [grouped, tracks] = useReferenda(palletReferenda);
|
||||
const summary = useSummary(palletReferenda, grouped);
|
||||
|
||||
const isMember = useMemo(
|
||||
() => !members || allAccounts.some((a) => members.includes(a)),
|
||||
[allAccounts, members]
|
||||
);
|
||||
|
||||
const headerRef = useRef([
|
||||
[t('referenda'), 'start', 2],
|
||||
[undefined, undefined, 3]
|
||||
]);
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<Summary summary={summary} />
|
||||
@ -53,22 +48,31 @@ function Referenda ({ className, members, palletReferenda, palletVote }: Props):
|
||||
tracks={tracks}
|
||||
/>
|
||||
</Button.Group>
|
||||
<Table
|
||||
className={className}
|
||||
empty={referenda && t<string>('No referendums found')}
|
||||
header={headerRef.current}
|
||||
>
|
||||
{referenda && referenda.map((r) => (
|
||||
<Referendum
|
||||
isMember={isMember}
|
||||
key={r.key}
|
||||
members={members}
|
||||
palletReferenda={palletReferenda}
|
||||
palletVote={palletVote}
|
||||
value={r}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
{grouped.map(({ referenda, trackName }: ReferendaGroup) => (
|
||||
<Table
|
||||
empty={referenda && t<string>('No active referenda')}
|
||||
header={[
|
||||
[trackName || t('referenda'), 'start', 2],
|
||||
[undefined, undefined, 3]
|
||||
]}
|
||||
key={
|
||||
trackName
|
||||
? `track:${trackName}`
|
||||
: 'untracked'
|
||||
}
|
||||
>
|
||||
{referenda && referenda.map((r) => (
|
||||
<Referendum
|
||||
isMember={isMember}
|
||||
key={r.key}
|
||||
members={members}
|
||||
palletReferenda={palletReferenda}
|
||||
palletVote={palletVote}
|
||||
value={r}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -8,6 +8,12 @@ export type PalletReferenda = 'referenda' | 'rankedPolls' | 'fellowshipReferenda
|
||||
|
||||
export type PalletVote = 'convictionVoting' | 'rankedCollective' | 'fellowshipCollective';
|
||||
|
||||
export interface ReferendaGroup {
|
||||
track?: PalletReferendaTrackInfo;
|
||||
trackName?: string;
|
||||
referenda?: Referendum[];
|
||||
}
|
||||
|
||||
export interface Referendum {
|
||||
id: BN;
|
||||
info: PalletReferendaReferendumInfoConvictionVotingTally | PalletReferendaReferendumInfoRankedCollectiveTally;
|
||||
|
||||
@ -10,11 +10,13 @@ import { createNamedHook } from '@polkadot/react-hooks';
|
||||
import useReferenda from './useReferenda';
|
||||
|
||||
export function useCounterNamed (palletReferenda: PalletReferenda): number {
|
||||
const [referanda] = useReferenda(palletReferenda);
|
||||
const [grouped] = useReferenda(palletReferenda);
|
||||
|
||||
return useMemo(
|
||||
() => (referanda && referanda.filter(({ info }) => info.isOngoing).length) || 0,
|
||||
[referanda]
|
||||
() => grouped
|
||||
? grouped.reduce((total, { referenda }) => total + (referenda ? referenda.filter(({ info }) => info.isOngoing).length : 0), 0)
|
||||
: 0,
|
||||
[grouped]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
import type { Option } from '@polkadot/types';
|
||||
import type { PalletReferendaReferendumInfoConvictionVotingTally, PalletReferendaReferendumInfoRankedCollectiveTally, PalletReferendaTrackInfo } from '@polkadot/types/lookup';
|
||||
import type { BN } from '@polkadot/util';
|
||||
import type { PalletReferenda, Referendum } from './types';
|
||||
import type { PalletReferenda, ReferendaGroup, Referendum } from './types';
|
||||
|
||||
import { useMemo } from 'react';
|
||||
|
||||
@ -12,6 +12,7 @@ import { createNamedHook, useApi, useCall } from '@polkadot/react-hooks';
|
||||
|
||||
import useReferendaIds from './useReferendaIds';
|
||||
import useTracks from './useTracks';
|
||||
import { getTrackName } from './util';
|
||||
|
||||
const ORDER = <const> ['Ongoing', 'Approved', 'Rejected', 'Cancelled', 'Killed', 'TimedOut'];
|
||||
|
||||
@ -52,20 +53,57 @@ const OPT_MULTI = {
|
||||
info,
|
||||
isConvictionVote: isConvictionVote(info),
|
||||
key: id.toString()
|
||||
}))
|
||||
.sort((a, b) =>
|
||||
a.info.isOngoing === b.info.isOngoing
|
||||
? a.info.isOngoing
|
||||
? sortOngoing(a, b)
|
||||
: sortOther(a, b)
|
||||
: a.info.isOngoing
|
||||
? -1
|
||||
: 1
|
||||
),
|
||||
})),
|
||||
withParamsTransform: true
|
||||
};
|
||||
|
||||
function getResult (referenda?: Referendum[], tracks?: [BN, PalletReferendaTrackInfo][]): Referendum[] | undefined {
|
||||
function groupReferenda (referenda?: Referendum[]): ReferendaGroup[] {
|
||||
if (!referenda) {
|
||||
return [{}];
|
||||
}
|
||||
|
||||
const grouped: ReferendaGroup[] = [];
|
||||
const other: ReferendaGroup = { referenda: [] };
|
||||
|
||||
for (let i = 0; i < referenda.length; i++) {
|
||||
const ref = referenda[i];
|
||||
let group: ReferendaGroup | undefined = other;
|
||||
|
||||
if (ref.track) {
|
||||
group = grouped.find(({ track }) => ref.track === track);
|
||||
|
||||
if (!group) {
|
||||
group = { referenda: [], track: ref.track, trackName: getTrackName(ref.track) };
|
||||
|
||||
grouped.push(group);
|
||||
}
|
||||
}
|
||||
|
||||
group.referenda && group.referenda.push(ref);
|
||||
}
|
||||
|
||||
if ((other.referenda && other.referenda.length !== 0) || !grouped.length) {
|
||||
grouped.push(other);
|
||||
}
|
||||
|
||||
for (let i = 0; i < grouped.length; i++) {
|
||||
const group = grouped[i];
|
||||
|
||||
group.referenda && group.referenda.sort((a, b) =>
|
||||
a.info.isOngoing === b.info.isOngoing
|
||||
? a.info.isOngoing
|
||||
? sortOngoing(a, b)
|
||||
: sortOther(a, b)
|
||||
: a.info.isOngoing
|
||||
? -1
|
||||
: 1
|
||||
);
|
||||
}
|
||||
|
||||
return grouped;
|
||||
}
|
||||
|
||||
function getResult (referenda?: Referendum[], tracks?: [BN, PalletReferendaTrackInfo][]): ReferendaGroup[] {
|
||||
if (tracks && referenda) {
|
||||
for (let i = 0; i < referenda.length; i++) {
|
||||
if (referenda[i].info.isOngoing) {
|
||||
@ -78,10 +116,10 @@ function getResult (referenda?: Referendum[], tracks?: [BN, PalletReferendaTrack
|
||||
}
|
||||
}
|
||||
|
||||
return referenda;
|
||||
return groupReferenda(referenda);
|
||||
}
|
||||
|
||||
function useReferendaImpl (palletReferenda: PalletReferenda): [Referendum[] | undefined, [BN, PalletReferendaTrackInfo][] | undefined] {
|
||||
function useReferendaImpl (palletReferenda: PalletReferenda): [ReferendaGroup[], [BN, PalletReferendaTrackInfo][] | undefined] {
|
||||
const { api, isApiReady } = useApi();
|
||||
const ids = useReferendaIds(palletReferenda);
|
||||
const tracks = useTracks(palletReferenda);
|
||||
@ -90,7 +128,7 @@ function useReferendaImpl (palletReferenda: PalletReferenda): [Referendum[] | un
|
||||
return useMemo(
|
||||
() => [
|
||||
(ids && ids.length === 0)
|
||||
? []
|
||||
? [{ referenda: [] }]
|
||||
: getResult(referenda, tracks),
|
||||
tracks
|
||||
],
|
||||
|
||||
@ -2,19 +2,19 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { u32 } from '@polkadot/types';
|
||||
import type { PalletReferenda, Referendum, Summary } from './types';
|
||||
import type { PalletReferenda, ReferendaGroup, Summary } from './types';
|
||||
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { createNamedHook, useApi, useCall } from '@polkadot/react-hooks';
|
||||
|
||||
// TODO keep track of all tracks to get the number of deciding
|
||||
function useSummaryImpl (palletReferenda: PalletReferenda, referenda?: Referendum[] | undefined): Summary {
|
||||
function useSummaryImpl (palletReferenda: PalletReferenda, grouped?: ReferendaGroup[] | undefined): Summary {
|
||||
const { api } = useApi();
|
||||
const refCount = useCall<u32>(api.query[palletReferenda].referendumCount);
|
||||
const refActive = useMemo(
|
||||
() => referenda && referenda.length,
|
||||
[referenda]
|
||||
() => grouped && grouped.reduce((total, { referenda }) => total + (referenda ? referenda.length : 0), 0),
|
||||
[grouped]
|
||||
);
|
||||
|
||||
return useMemo(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user