diff --git a/packages/page-society/src/Candidates/Bid.tsx b/packages/page-society/src/Candidates/Bid.tsx
index a0e26f810f..e099987b39 100644
--- a/packages/page-society/src/Candidates/Bid.tsx
+++ b/packages/page-society/src/Candidates/Bid.tsx
@@ -3,13 +3,14 @@
import type { Bid } from '@polkadot/types/interfaces';
-import React, { useEffect, useState } from 'react';
+import React, { useMemo } from 'react';
import { AddressSmall, TxButton } from '@polkadot/react-components';
import { useAccounts, useApi } from '@polkadot/react-hooks';
import { FormatBalance } from '@polkadot/react-query';
import { useTranslation } from '../translate';
+import BidType from './BidType';
interface Props {
index: number;
@@ -20,22 +21,22 @@ function BidRow ({ index, value: { kind, value, who } }: Props): React.ReactElem
const { t } = useTranslation();
const { api } = useApi();
const { allAccounts } = useAccounts();
- const [isBidder, setIsBidder] = useState(false);
- useEffect((): void => {
- const address = who.toString();
+ const isBidder = useMemo(
+ (): boolean => {
+ const address = who.toString();
- setIsBidder(allAccounts.some((accountId) => accountId === address));
- }, [allAccounts, who]);
+ return allAccounts.some((accountId) => accountId === address);
+ },
+ [allAccounts, who]
+ );
return (
- |
+ |
|
-
- {kind.type}
- |
+
|
diff --git a/packages/page-society/src/Candidates/BidType.tsx b/packages/page-society/src/Candidates/BidType.tsx
new file mode 100644
index 0000000000..48efed7ebd
--- /dev/null
+++ b/packages/page-society/src/Candidates/BidType.tsx
@@ -0,0 +1,30 @@
+// Copyright 2017-2021 @polkadot/app-society authors & contributors
+// SPDX-License-Identifier: Apache-2.0
+
+import type { BidKind } from '@polkadot/types/interfaces';
+
+import React, { useMemo } from 'react';
+
+import { AddressSmall } from '@polkadot/react-components';
+
+interface Props {
+ value?: BidKind;
+}
+
+function BidType ({ value }: Props): React.ReactElement {
+ const vouchId = useMemo(
+ () => value?.isVouch
+ ? value.asVouch[0]
+ : null,
+ [value]
+ );
+
+ return (
+ <>
+ {value && value.type} |
+ {vouchId && } |
+ >
+ );
+}
+
+export default React.memo(BidType);
diff --git a/packages/page-society/src/Candidates/Bids.tsx b/packages/page-society/src/Candidates/Bids.tsx
index d75f3a3e88..f58ee0b57d 100644
--- a/packages/page-society/src/Candidates/Bids.tsx
+++ b/packages/page-society/src/Candidates/Bids.tsx
@@ -22,7 +22,7 @@ function Bids ({ className }: Props): React.ReactElement {
const headerRef = useRef([
[t('bids'), 'start'],
- [t('kind')],
+ [t('bid kind'), 'start', 2],
[t('value')],
[]
]);
diff --git a/packages/page-society/src/Candidates/Candidate.tsx b/packages/page-society/src/Candidates/Candidate.tsx
index f5d8abcf13..93c0b4678b 100644
--- a/packages/page-society/src/Candidates/Candidate.tsx
+++ b/packages/page-society/src/Candidates/Candidate.tsx
@@ -13,6 +13,7 @@ import { useApi, useCall } from '@polkadot/react-hooks';
import { FormatBalance } from '@polkadot/react-query';
import Votes from '../Overview/Votes';
+import BidType from './BidType';
import CandidateVoting from './CandidateVoting';
interface Props {
@@ -28,7 +29,7 @@ function Candidate ({ allMembers, isMember, ownMembers, value: { accountId, kind
transform: (voteOpts: Option[]): VoteType[] =>
voteOpts
.map((voteOpt, index): [string, Option] => [allMembers[index], voteOpt])
- .filter(([, voteOpt]): boolean => voteOpt.isSome)
+ .filter(([, voteOpt]) => voteOpt.isSome)
.map(([accountId, voteOpt]): VoteType => [accountId, voteOpt.unwrap()])
});
@@ -37,9 +38,7 @@ function Candidate ({ allMembers, isMember, ownMembers, value: { accountId, kind
|
-
- {kind.type}
- |
+
|
diff --git a/packages/page-society/src/Candidates/Candidates.tsx b/packages/page-society/src/Candidates/Candidates.tsx
index d7bfde78f4..9d6d946685 100644
--- a/packages/page-society/src/Candidates/Candidates.tsx
+++ b/packages/page-society/src/Candidates/Candidates.tsx
@@ -23,9 +23,9 @@ function Candidates ({ allMembers, candidates, className = '', isMember, ownMemb
const headerRef = useRef([
[t('candidates'), 'start'],
- [t('kind')],
+ [t('bid kind'), 'start', 2],
[t('value')],
- [t('votes'), 'expand'],
+ [undefined, 'expand'],
[]
]);
diff --git a/packages/page-society/src/Overview/Defender.tsx b/packages/page-society/src/Overview/Defender.tsx
index 29bc968fd0..35aaf807ea 100644
--- a/packages/page-society/src/Overview/Defender.tsx
+++ b/packages/page-society/src/Overview/Defender.tsx
@@ -35,7 +35,7 @@ function Defender ({ className = '', info, isMember, ownMembers }: Props): React
const headerRef = useRef([
[t('defender'), 'start'],
- [t('votes'), 'expand'],
+ [undefined, 'expand'],
[]
]);
diff --git a/packages/page-society/src/Overview/Summary.tsx b/packages/page-society/src/Overview/Summary.tsx
index e7cbff39ac..5071fb0a7e 100644
--- a/packages/page-society/src/Overview/Summary.tsx
+++ b/packages/page-society/src/Overview/Summary.tsx
@@ -1,6 +1,7 @@
// Copyright 2017-2021 @polkadot/app-society authors & contributors
// SPDX-License-Identifier: Apache-2.0
+import type BN from 'bn.js';
import type { DeriveSociety } from '@polkadot/api-derive/types';
import type { BlockNumber } from '@polkadot/types/interfaces';
@@ -16,9 +17,10 @@ import { useTranslation } from '../translate';
interface Props {
className?: string;
info?: DeriveSociety;
+ payoutTotal?: BN;
}
-function Summary ({ className = '', info }: Props): React.ReactElement {
+function Summary ({ className = '', info, payoutTotal }: Props): React.ReactElement {
const { t } = useTranslation();
const { api } = useApi();
const members = useCall(api.derive.society.members);
@@ -65,6 +67,14 @@ function Summary ({ className = '', info }: Props): React.ReactElement {
>
)}
+ {payoutTotal && (
+ ('payouts')}>
+
+
+ )}
{pot && (
('pot')}>
{
+function Overview ({ className, info, isMember, mapMembers, ownMembers, payoutTotal }: Props): React.ReactElement {
return (
-
+
{
+function Suspension ({ balance, bid, value }: Props): React.ReactElement {
return (
|
|
+
+
+ {balance && (
+
+ )}
+ |
);
}
diff --git a/packages/page-society/src/Suspended/index.tsx b/packages/page-society/src/Suspended/index.tsx
index 1c88947de9..5602bb9df2 100644
--- a/packages/page-society/src/Suspended/index.tsx
+++ b/packages/page-society/src/Suspended/index.tsx
@@ -1,8 +1,9 @@
// Copyright 2017-2021 @polkadot/app-society authors & contributors
// SPDX-License-Identifier: Apache-2.0
-import type { StorageKey } from '@polkadot/types';
-import type { AccountId } from '@polkadot/types/interfaces';
+import type { Option, StorageKey } from '@polkadot/types';
+import type { AccountId, BalanceOf, BidKind } from '@polkadot/types/interfaces';
+import type { ITuple } from '@polkadot/types/types';
import React, { useRef } from 'react';
@@ -16,7 +17,25 @@ interface Props {
className?: string;
}
-const optExtract = {
+interface CandidateSuspend {
+ accountId: AccountId;
+ balance: BalanceOf;
+ bid: BidKind;
+}
+
+const optExtractCandidates = {
+ transform: (entries: [StorageKey<[AccountId]>, Option>][]): CandidateSuspend[] =>
+ entries
+ .filter(([{ args: [accountId] }, opt]) => opt.isSome && accountId)
+ .map(([{ args: [accountId] }, opt]) => {
+ const [balance, bid] = opt.unwrap();
+
+ return { accountId, balance, bid };
+ })
+ .sort((a, b) => a.balance.cmp(b.balance))
+};
+
+const optExtractAccounts = {
transform: (keys: StorageKey<[AccountId]>[]): AccountId[] =>
keys
.map(({ args: [accountId] }) => accountId)
@@ -26,12 +45,14 @@ const optExtract = {
function Suspended ({ className }: Props): React.ReactElement {
const { t } = useTranslation();
const { api } = useApi();
- const candidates = useCall(api.query.society.suspendedCandidates.keys, undefined, optExtract);
- const members = useCall(api.query.society.suspendedMembers.keys, undefined, optExtract);
+ const candidates = useCall(api.query.society.suspendedCandidates.entries, undefined, optExtractCandidates);
+ const members = useCall(api.query.society.suspendedMembers.keys, undefined, optExtractAccounts);
const headerRef = useRef({
candidates: [
- [t('candidates'), 'start']
+ [t('candidates'), 'start'],
+ [t('bid kind'), 'start', 2],
+ [t('value')]
],
members: [
[t('members'), 'start']
@@ -45,7 +66,7 @@ function Suspended ({ className }: Props): React.ReactElement {
empty={members && t('No suspended members')}
header={headerRef.current.members}
>
- {members && members.map((accountId): React.ReactNode => (
+ {members?.map((accountId): React.ReactNode => (
{
empty={candidates && t('No suspended candidates')}
header={headerRef.current.candidates}
>
- {candidates && candidates.map((accountId): React.ReactNode => (
+ {candidates?.map(({ accountId, balance, bid }): React.ReactNode => (
diff --git a/packages/page-society/src/index.tsx b/packages/page-society/src/index.tsx
index 0198ca8127..a183298db5 100644
--- a/packages/page-society/src/index.tsx
+++ b/packages/page-society/src/index.tsx
@@ -1,10 +1,10 @@
// Copyright 2017-2021 @polkadot/app-society authors & contributors
// SPDX-License-Identifier: Apache-2.0
-import type BN from 'bn.js';
import type { DeriveSociety, DeriveSocietyMember } from '@polkadot/api-derive/types';
import type { MapMember } from './types';
+import BN from 'bn.js';
import React, { useMemo } from 'react';
import { Route, Switch } from 'react-router';
@@ -72,8 +72,8 @@ function finalSort (a: MapMember, b: MapMember): number {
: skepticSort(a, b);
}
-function getMapMembers (members: DeriveSocietyMember[], skeptics: string[], voters: string[], info: DeriveSociety, warnStrikes: BN): MapMember[] {
- return members
+function getMapMembers (members: DeriveSocietyMember[], skeptics: string[], voters: string[], info: DeriveSociety, warnStrikes: BN): [MapMember[], BN] {
+ const mapMembers = members
.filter((member) => !info.hasDefender || !member.accountId.eq(info.defender))
.map((member): MapMember => ({
isCandidateVoter: voters.includes(member.accountId.toString()),
@@ -87,6 +87,13 @@ function getMapMembers (members: DeriveSocietyMember[], skeptics: string[], vote
.sort(({ member: a }, { member: b }) => (b.payouts.length - a.payouts.length) || b.strikes.cmp(a.strikes))
.sort(voterSort)
.sort(finalSort);
+
+ return [
+ mapMembers,
+ mapMembers.reduce((total, { member: { payouts } }) =>
+ payouts.reduce((total, [, balance]) => total.iadd(balance), total), new BN(0)
+ )
+ ];
}
function SocietyApp ({ basePath, className }: Props): React.ReactElement {
@@ -98,10 +105,10 @@ function SocietyApp ({ basePath, className }: Props): React.ReactElement
const members = useCall(api.derive.society.members);
const { candidates, skeptics, voters } = useVoters();
- const mapMembers = useMemo(
+ const [mapMembers, payoutTotal] = useMemo(
() => members && info && skeptics && voters
? getMapMembers(members, skeptics, voters, info, api.consts.society.maxStrikes.mul(BN_TWO).div(BN_THREE))
- : undefined,
+ : [undefined, undefined],
[api, info, members, skeptics, voters]
);
@@ -124,12 +131,10 @@ function SocietyApp ({ basePath, className }: Props): React.ReactElement
return (
-
+
isMember={isMember}
mapMembers={mapMembers}
ownMembers={ownMembers}
+ payoutTotal={payoutTotal}
/>
diff --git a/packages/react-components/src/CardSummary.tsx b/packages/react-components/src/CardSummary.tsx
index 24533d4cf0..76e1477a61 100644
--- a/packages/react-components/src/CardSummary.tsx
+++ b/packages/react-components/src/CardSummary.tsx
@@ -122,7 +122,7 @@ export default React.memo(styled(CardSummary)`
text-align: right;
> * {
- margin: 0.5rem 0;
+ margin: 0.25rem 0;
&:first-child {
margin-top: 0;
diff --git a/packages/react-components/src/Progress.tsx b/packages/react-components/src/Progress.tsx
index 3d5adad097..b7aa0479ed 100644
--- a/packages/react-components/src/Progress.tsx
+++ b/packages/react-components/src/Progress.tsx
@@ -12,7 +12,6 @@ import { bnToBn } from '@polkadot/util';
interface Props {
className?: string;
isDisabled?: boolean;
- size?: 'normal' | 'small'
total?: UInt | BN | number | null;
value?: UInt | BN | number | null;
}
@@ -35,7 +34,7 @@ function DivClip ({ angle, type }: RotateProps): React.ReactElement
const Clip = React.memo(DivClip);
-function Progress ({ className = '', isDisabled, size = 'normal', total, value }: Props): React.ReactElement | null {
+function Progress ({ className = '', isDisabled, total, value }: Props): React.ReactElement | null {
const _total = bnToBn(total || 0);
const angle = _total.gtn(0)
? (bnToBn(value || 0).muln(36000).div(_total).toNumber() / 100)
@@ -48,7 +47,7 @@ function Progress ({ className = '', isDisabled, size = 'normal', total, value }
const drawAngle = angle % 360;
return (
-