Rework staking rendering (object passing) (#2425)
* Rework staking rendering (object passing) * onlineCount check * Rework reward sorting
This commit is contained in:
parent
71ffaf7487
commit
7c7df9873c
@ -2,8 +2,8 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId, Balance, RewardPoint } from '@polkadot/types/interfaces';
|
||||
import { DeriveAccountInfo, DerivedStakingQuery, DerivedHeartbeatAuthor } from '@polkadot/api-derive/types';
|
||||
import { AccountId, Balance } from '@polkadot/types/interfaces';
|
||||
import { DeriveAccountInfo, DerivedStakingQuery } from '@polkadot/api-derive/types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
@ -22,13 +22,14 @@ interface Props {
|
||||
defaultName: string;
|
||||
filterName: string;
|
||||
hasQueries: boolean;
|
||||
heartbeat?: false | DerivedHeartbeatAuthor;
|
||||
isAuthor?: boolean;
|
||||
isElected: boolean;
|
||||
isFavorite: boolean;
|
||||
isMain?: boolean;
|
||||
lastBlock?: string;
|
||||
points?: false | RewardPoint;
|
||||
onlineCount?: false | number;
|
||||
onlineMessage?: boolean;
|
||||
points?: false | number;
|
||||
setNominators?: false | ((nominators: string[]) => void);
|
||||
toggleFavorite: (accountId: string) => void;
|
||||
withNominations?: boolean;
|
||||
@ -97,7 +98,7 @@ function checkVisibility (api: ApiPromise, address: string, filterName: string,
|
||||
return isVisible;
|
||||
}
|
||||
|
||||
function Address ({ address, className, filterName, hasQueries, heartbeat, isAuthor, isElected, isFavorite, isMain, lastBlock, points, setNominators, toggleFavorite, withNominations }: Props): React.ReactElement<Props> | null {
|
||||
function Address ({ address, className, filterName, hasQueries, isAuthor, isElected, isFavorite, isMain, lastBlock, onlineCount, onlineMessage, points, setNominators, toggleFavorite, withNominations }: Props): React.ReactElement<Props> | null {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const info = useCall<DeriveAccountInfo>(api.derive.accounts.info as any, [address]);
|
||||
@ -160,12 +161,12 @@ function Address ({ address, className, filterName, hasQueries, heartbeat, isAut
|
||||
type='next'
|
||||
/>
|
||||
)}
|
||||
{heartbeat && (heartbeat.blockCount.gtn(0) || heartbeat.hasMessage) && (
|
||||
{(!!onlineCount || onlineMessage) && (
|
||||
<Badge
|
||||
hover={t('Active with {{blocks}} blocks authored{{hasMessage}} heartbeat message', {
|
||||
replace: {
|
||||
blocks: formatNumber(heartbeat.blockCount),
|
||||
hasMessage: heartbeat.hasMessage ? ' and a' : ', no'
|
||||
blocks: formatNumber(onlineCount || 0),
|
||||
hasMessage: onlineMessage ? ' and a' : ', no'
|
||||
}
|
||||
})}
|
||||
info={<Icon name='check' />}
|
||||
@ -219,7 +220,7 @@ function Address ({ address, className, filterName, hasQueries, heartbeat, isAut
|
||||
)}
|
||||
</td>
|
||||
<td className='number'>
|
||||
{points && points.gtn(0) && (
|
||||
{points && (
|
||||
<><label>{t('points')}</label>{formatNumber(points)}</>
|
||||
)}
|
||||
</td>
|
||||
|
||||
@ -77,7 +77,7 @@ function getDetails (stakingOverview: DerivedStakingOverview, validators: Accoun
|
||||
return {
|
||||
address,
|
||||
points: points
|
||||
? points[1]
|
||||
? points[1].toNumber()
|
||||
: undefined
|
||||
};
|
||||
});
|
||||
@ -123,13 +123,14 @@ function CurrentList ({ authorsMap, hasQueries, isIntentions, isVisible, lastAut
|
||||
defaultName={defaultName}
|
||||
filterName={nameFilter}
|
||||
hasQueries={hasQueries}
|
||||
heartbeat={isMain && recentlyOnline && recentlyOnline[address]}
|
||||
isAuthor={lastAuthors && lastAuthors.includes(address)}
|
||||
isElected={isElected}
|
||||
isFavorite={isFavorite}
|
||||
isMain={isMain}
|
||||
key={address}
|
||||
lastBlock={authorsMap[address]}
|
||||
onlineCount={isMain && recentlyOnline?.[address]?.blockCount.toNumber()}
|
||||
onlineMessage={isMain && recentlyOnline?.[address]?.hasMessage}
|
||||
points={isMain && addressDetails[address] && addressDetails[address].points}
|
||||
setNominators={isIntentions && setNominators}
|
||||
toggleFavorite={toggleFavorite}
|
||||
|
||||
@ -2,9 +2,7 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { RewardPoint } from '@polkadot/types/interfaces';
|
||||
|
||||
export interface AddressDetails {
|
||||
address: string;
|
||||
points?: RewardPoint;
|
||||
points?: number;
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@ interface Props {
|
||||
|
||||
interface AllInfo {
|
||||
nominators: string[];
|
||||
sorted?: ValidatorInfo[];
|
||||
totalStaked?: BN;
|
||||
validators: ValidatorInfo[];
|
||||
}
|
||||
@ -154,6 +155,18 @@ function extractInfo (allAccounts: string[], amount: BN = new BN(0), electedInfo
|
||||
return { nominators, totalStaked, validators };
|
||||
}
|
||||
|
||||
function sort (sortBy: SortBy, sortFromMax: boolean, validators: ValidatorInfo[]): ValidatorInfo[] {
|
||||
return validators
|
||||
.sort((a, b): number => sortFromMax
|
||||
? a[sortBy] - b[sortBy]
|
||||
: b[sortBy] - a[sortBy]
|
||||
)
|
||||
.sort((a, b): number => a.isFavorite === b.isFavorite
|
||||
? 0
|
||||
: (a.isFavorite ? -1 : 1)
|
||||
);
|
||||
}
|
||||
|
||||
function Targets ({ className }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
@ -170,41 +183,29 @@ function Targets ({ className }: Props): React.ReactElement<Props> {
|
||||
const [_amount, setAmount] = useState<BN | undefined>(new BN(1_000));
|
||||
const electedInfo = useCall<DerivedStakingElected>(api.derive.staking.electedInfo, []);
|
||||
const [favorites, toggleFavorite] = useFavorites(STORE_FAVS_BASE);
|
||||
const [{ nominators, validators, totalStaked }, setWorkable] = useState<AllInfo>({ nominators: [], validators: [] });
|
||||
const [{ sorted, sortBy, sortFromMax }, setSorted] = useState<{ sorted?: ValidatorInfo[]; sortBy: SortBy; sortFromMax: boolean }>({ sortBy: 'rankOverall', sortFromMax: true });
|
||||
const [{ nominators, validators, sorted, totalStaked }, setWorkable] = useState<AllInfo>({ nominators: [], validators: [] });
|
||||
const [{ sortBy, sortFromMax }, setSortBy] = useState<{ sortBy: SortBy; sortFromMax: boolean }>({ sortBy: 'rankOverall', sortFromMax: true });
|
||||
const amount = useDebounce(_amount);
|
||||
|
||||
const _sort = useCallback(
|
||||
(newSortBy: SortBy, unsorted: ValidatorInfo[] = validators, isAdjust = true): void => {
|
||||
const newSortFromMax = isAdjust && newSortBy === sortBy
|
||||
? !sortFromMax
|
||||
: true;
|
||||
|
||||
setSorted({
|
||||
(newSortBy: SortBy): void =>
|
||||
setSortBy(({ sortBy, sortFromMax }) => ({
|
||||
sortBy: newSortBy,
|
||||
sortFromMax: newSortFromMax,
|
||||
sorted: unsorted
|
||||
.sort((a, b): number => newSortFromMax
|
||||
? a[newSortBy] - b[newSortBy]
|
||||
: b[newSortBy] - a[newSortBy]
|
||||
)
|
||||
.sort((a, b): number => a.isFavorite === b.isFavorite
|
||||
? 0
|
||||
: (a.isFavorite ? -1 : 1)
|
||||
)
|
||||
});
|
||||
},
|
||||
[sortBy, sortFromMax, validators]
|
||||
sortFromMax: newSortBy === sortBy
|
||||
? !sortFromMax
|
||||
: true
|
||||
})),
|
||||
[sortBy]
|
||||
);
|
||||
|
||||
useEffect((): void => {
|
||||
if (electedInfo) {
|
||||
const { nominators, totalStaked, validators } = extractInfo(allAccounts, amount, electedInfo, favorites, lastReward);
|
||||
const sorted = sort(sortBy, sortFromMax, validators);
|
||||
|
||||
setWorkable({ nominators, totalStaked, validators });
|
||||
_sort('rankOverall', validators, false);
|
||||
setWorkable({ nominators, totalStaked, sorted, validators });
|
||||
}
|
||||
}, [allAccounts, amount, electedInfo, favorites, lastReward]);
|
||||
}, [allAccounts, amount, electedInfo, favorites, lastReward, sortBy, sortFromMax]);
|
||||
|
||||
if (!sorted) {
|
||||
return <Spinner />;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user