From 58e3dab9bcc2bf0f5f92d34aa3c6f1857834d153 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Thu, 23 Jan 2020 15:41:15 +0100 Subject: [PATCH] Allow sorting of staking returns (#2183) --- .../app-staking/src/Targets/Validator.tsx | 8 +- packages/app-staking/src/Targets/index.tsx | 99 ++++++++++++++----- packages/app-staking/src/Targets/types.ts | 5 +- packages/react-components/src/Table.tsx | 15 ++- 4 files changed, 94 insertions(+), 33 deletions(-) diff --git a/packages/app-staking/src/Targets/Validator.tsx b/packages/app-staking/src/Targets/Validator.tsx index be9300a580..8853d56748 100644 --- a/packages/app-staking/src/Targets/Validator.tsx +++ b/packages/app-staking/src/Targets/Validator.tsx @@ -43,10 +43,10 @@ export default function Validator ({ info: { accountId, bondOther, bondOwn, bond : {t('commission')}} value={validatorPayment} /> } - {t('total stake')}} value={bondTotal} /> - {t('own stake')}} value={bondOwn} /> - {t('other stake')}} value={bondOther} > ({formatNumber(numNominators)}) - {t('payout (est.)')}} value={rewardPayout} /> + {t('total stake')}} value={bondTotal} /> + {t('own stake')}} value={bondOwn} /> + {t('other stake')}} value={bondOther} > ({formatNumber(numNominators)}) + {t('payout (est.)')}} value={rewardPayout} /> b.commissionPer - a.commissionPer) + .map((info, index): ValidatorInfo => { + info.rankComm = index + 1; + + return info; + }) + .sort((a, b): number => b.bondOther.cmp(a.bondOther)) + .map((info, index): ValidatorInfo => { + info.rankBondOther = index + 1; + + return info; + }) + .sort((a, b): number => b.bondOwn.cmp(a.bondOwn)) + .map((info, index): ValidatorInfo => { + info.rankBondOwn = index + 1; + + return info; + }) .sort((a, b): number => b.bondTotal.cmp(a.bondTotal)) .map((info, index): ValidatorInfo => { - info.rankBonded = index + 1; + info.rankBondTotal = index + 1; return info; }) @@ -59,30 +79,15 @@ function sortValidators (list: ValidatorInfo[]): ValidatorInfo[] { ? cmp : a.rankReward === b.rankReward ? a.rankPayment === b.rankPayment - ? a.rankBonded === b.rankBonded - ? 0 - : a.rankBonded < b.rankBonded - ? 1 - : -1 - : a.rankPayment < b.rankPayment - ? 1 - : -1 - : a.rankReward < b.rankReward - ? 1 - : -1; + ? b.rankBondTotal - a.rankBondTotal + : b.rankPayment - a.rankPayment + : b.rankReward - a.rankReward; }) .map((info, index): ValidatorInfo => { info.rankOverall = index + 1; return info; - }) - .sort((a, b): number => - a.isFavorite === b.isFavorite - ? 0 - : a.isFavorite - ? -1 - : 1 - ); + }); } function extractInfo (allAccounts: string[], amount: BN = new BN(0), electedInfo: DerivedStakingElected, favorites: string[], lastReward: BN): AllInfo { @@ -126,7 +131,10 @@ function extractInfo (allAccounts: string[], amount: BN = new BN(0), electedInfo key, commissionPer: (((prefs as ValidatorPrefs).commission?.unwrap() || new BN(0)).muln(10000).div(PERBILL).toNumber() / 100), numNominators: exposure.others.length, - rankBonded: 0, + rankBondOther: 0, + rankBondOwn: 0, + rankBondTotal: 0, + rankComm: 0, rankOverall: 0, rankPayment: 0, rankReward: 0, @@ -149,8 +157,31 @@ function Targets ({ className, sessionRewards }: Props): React.ReactElement({ totalStaked: new BN(0), validators: [] }); + const [{ sorted, sortBy, sortFromMax }, setSorted] = useState<{ sorted: ValidatorInfo[]; sortBy: SortBy; sortFromMax: boolean }>({ sorted: [], sortBy: 'rankOverall', sortFromMax: true }); const amount = useDebounce(_amount); + const _sort = (newSortBy: SortBy, unsorted = validators, isAdjust = true): void => { + const newSortFromMax = isAdjust && newSortBy === sortBy ? !sortFromMax : true; + + setSorted({ + 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 + ) + }); + }; + useEffect((): void => { if (sessionRewards && sessionRewards.length) { const lastRewardSession = sessionRewards.filter(({ reward }): boolean => reward.gtn(0)); @@ -165,17 +196,22 @@ function Targets ({ className, sessionRewards }: Props): React.ReactElement { if (electedInfo) { - setWorkable(extractInfo(allAccounts, amount, electedInfo, favorites, lastReward)); + const { totalStaked, validators } = extractInfo(allAccounts, amount, electedInfo, favorites, lastReward); + + setWorkable({ totalStaked, validators }); + _sort('rankOverall', validators, false); } }, [allAccounts, amount, electedInfo, favorites, lastReward]); + const sortIcon = `chevron ${sortFromMax ? 'down' : 'up'}` as 'chevron up'; + return (
- {validators.length + {sorted.length ? ( <> + + + + + {['rankComm', 'rankBondTotal', 'rankBondOwn', 'rankBondOther', 'rankOverall'].map((header): React.ReactNode => ( + + ))} + + - {validators.map((info): React.ReactNode => + {sorted.map((info): React.ReactNode =>
    _sort(header as 'rankComm')} + >{sortBy === header ? : ''}