Save target/overview toggles (#4249)
This commit is contained in:
parent
78dd9d0fe1
commit
593b42c275
@ -9,7 +9,7 @@ import type { SortedTargets, ValidatorInfo } from '../types';
|
||||
import React, { useCallback, useContext, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import { Table } from '@polkadot/react-components';
|
||||
import { useApi, useCall, useLoadingDelay } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall, useLoadingDelay, useSavedFlags } from '@polkadot/react-hooks';
|
||||
import { BlockAuthorsContext } from '@polkadot/react-query';
|
||||
|
||||
import Filtering from '../Filtering';
|
||||
@ -78,7 +78,7 @@ function CurrentList ({ favorites, hasQueries, isIntentions, stakingOverview, ta
|
||||
const recentlyOnline = useCall<DeriveHeartbeats>(!isIntentions && api.derive.imOnline?.receivedHeartbeats);
|
||||
const nominatedBy = useNominations(isIntentions);
|
||||
const [nameFilter, setNameFilter] = useState<string>('');
|
||||
const [withIdentity, setWithIdentity] = useState(false);
|
||||
const [toggles, setToggle] = useSavedFlags('staking:overview', { withIdentity: false });
|
||||
|
||||
// we have a very large list, so we use a loading delay
|
||||
const isLoading = useLoadingDelay();
|
||||
@ -134,10 +134,10 @@ function CurrentList ({ favorites, hasQueries, isIntentions, stakingOverview, ta
|
||||
points={eraPoints[address]}
|
||||
toggleFavorite={toggleFavorite}
|
||||
validatorInfo={infoMap?.[address]}
|
||||
withIdentity={withIdentity}
|
||||
withIdentity={toggles.withIdentity}
|
||||
/>
|
||||
)),
|
||||
[byAuthor, eraPoints, hasQueries, infoMap, nameFilter, nominatedBy, recentlyOnline, toggleFavorite, withIdentity]
|
||||
[byAuthor, eraPoints, hasQueries, infoMap, nameFilter, nominatedBy, recentlyOnline, toggleFavorite, toggles]
|
||||
);
|
||||
|
||||
return isIntentions
|
||||
@ -155,8 +155,8 @@ function CurrentList ({ favorites, hasQueries, isIntentions, stakingOverview, ta
|
||||
<Filtering
|
||||
nameFilter={nameFilter}
|
||||
setNameFilter={setNameFilter}
|
||||
setWithIdentity={setWithIdentity}
|
||||
withIdentity={withIdentity}
|
||||
setWithIdentity={setToggle.withIdentity}
|
||||
withIdentity={toggles.withIdentity}
|
||||
/>
|
||||
}
|
||||
header={headerWaitingRef.current}
|
||||
@ -179,8 +179,8 @@ function CurrentList ({ favorites, hasQueries, isIntentions, stakingOverview, ta
|
||||
<Filtering
|
||||
nameFilter={nameFilter}
|
||||
setNameFilter={setNameFilter}
|
||||
setWithIdentity={setWithIdentity}
|
||||
withIdentity={withIdentity}
|
||||
setWithIdentity={setToggle.withIdentity}
|
||||
withIdentity={toggles.withIdentity}
|
||||
/>
|
||||
}
|
||||
header={headerActiveRef.current}
|
||||
|
||||
@ -10,7 +10,7 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { Button, Icon, Table, Toggle } from '@polkadot/react-components';
|
||||
import { useApi, useAvailableSlashes, useBlocksPerDays } from '@polkadot/react-hooks';
|
||||
import { useApi, useAvailableSlashes, useBlocksPerDays, useSavedFlags } from '@polkadot/react-hooks';
|
||||
|
||||
import { MAX_NOMINATIONS } from '../constants';
|
||||
import ElectionBanner from '../ElectionBanner';
|
||||
@ -33,10 +33,7 @@ interface Props {
|
||||
toggleFavorite: (address: string) => void;
|
||||
}
|
||||
|
||||
interface Flags {
|
||||
daysPayout: BN;
|
||||
isBabe: boolean;
|
||||
maxPaid: BN | undefined;
|
||||
interface SavedFlags {
|
||||
withElected: boolean;
|
||||
withGroup: boolean;
|
||||
withIdentity: boolean;
|
||||
@ -45,6 +42,12 @@ interface Flags {
|
||||
withoutOver: boolean;
|
||||
}
|
||||
|
||||
interface Flags extends SavedFlags {
|
||||
daysPayout: BN;
|
||||
isBabe: boolean;
|
||||
maxPaid: BN | undefined;
|
||||
}
|
||||
|
||||
interface SortState {
|
||||
sortBy: TargetSortBy;
|
||||
sortFromMax: boolean;
|
||||
@ -180,12 +183,14 @@ function Targets ({ className = '', isInElection, ownStashes, targets: { avgStak
|
||||
const allIdentity = useIdentities(validatorIds);
|
||||
const [selected, setSelected] = useState<string[]>([]);
|
||||
const [{ isQueryFiltered, nameFilter }, setNameFilter] = useState({ isQueryFiltered: false, nameFilter: '' });
|
||||
const [withElected, setWithElected] = useState(false);
|
||||
const [withGroup, setWithGroup] = useState(true);
|
||||
const [withIdentity, setWithIdentity] = useState(false);
|
||||
const [withPayout, setWithPayout] = useState(false);
|
||||
const [withoutComm, setWithoutComm] = useState(true);
|
||||
const [withoutOver, setWithoutOver] = useState(true);
|
||||
const [toggles, setToggle] = useSavedFlags('staking:targets', {
|
||||
withElected: false,
|
||||
withGroup: true,
|
||||
withIdentity: false,
|
||||
withPayout: false,
|
||||
withoutComm: true,
|
||||
withoutOver: true
|
||||
});
|
||||
const [{ sortBy, sortFromMax }, setSortBy] = useState<SortState>({ sortBy: 'rankOverall', sortFromMax: true });
|
||||
const [sorted, setSorted] = useState<ValidatorInfo[] | undefined>();
|
||||
|
||||
@ -198,18 +203,13 @@ function Targets ({ className = '', isInElection, ownStashes, targets: { avgStak
|
||||
|
||||
const flags = useMemo(
|
||||
() => ({
|
||||
...toggles,
|
||||
daysPayout,
|
||||
isBabe: !!api.consts.babe,
|
||||
isQueryFiltered,
|
||||
maxPaid: api.consts.staking?.maxNominatorRewardedPerValidator,
|
||||
withElected,
|
||||
withGroup,
|
||||
withIdentity,
|
||||
withPayout,
|
||||
withoutComm,
|
||||
withoutOver
|
||||
maxPaid: api.consts.staking?.maxNominatorRewardedPerValidator
|
||||
}),
|
||||
[api, daysPayout, isQueryFiltered, withElected, withGroup, withIdentity, withPayout, withoutComm, withoutOver]
|
||||
[api, daysPayout, isQueryFiltered, toggles]
|
||||
);
|
||||
|
||||
const filtered = useMemo(
|
||||
@ -282,14 +282,14 @@ function Targets ({ className = '', isInElection, ownStashes, targets: { avgStak
|
||||
<Filtering
|
||||
nameFilter={nameFilter}
|
||||
setNameFilter={_setNameFilter}
|
||||
setWithIdentity={setWithIdentity}
|
||||
withIdentity={withIdentity}
|
||||
setWithIdentity={setToggle.withIdentity}
|
||||
withIdentity={toggles.withIdentity}
|
||||
>
|
||||
<Toggle
|
||||
className='staking--buttonToggle'
|
||||
label={t<string>('single from operator')}
|
||||
onChange={setWithGroup}
|
||||
value={withGroup}
|
||||
onChange={setToggle.withGroup}
|
||||
value={toggles.withGroup}
|
||||
/>
|
||||
<Toggle
|
||||
className='staking--buttonToggle'
|
||||
@ -298,8 +298,8 @@ function Targets ({ className = '', isInElection, ownStashes, targets: { avgStak
|
||||
? t<string>('no {{maxComm}}%+ comm', { replace: { maxComm: MAX_COMM_PERCENT } })
|
||||
: t<string>('no median+ comm')
|
||||
}
|
||||
onChange={setWithoutComm}
|
||||
value={withoutComm}
|
||||
onChange={setToggle.withoutComm}
|
||||
value={toggles.withoutComm}
|
||||
/>
|
||||
<Toggle
|
||||
className='staking--buttonToggle'
|
||||
@ -308,27 +308,27 @@ function Targets ({ className = '', isInElection, ownStashes, targets: { avgStak
|
||||
? t<string>('no {{maxCap}}%+ capacity', { replace: { maxCap: MAX_CAP_PERCENT } })
|
||||
: t<string>('no at capacity')
|
||||
}
|
||||
onChange={setWithoutOver}
|
||||
value={withoutOver}
|
||||
onChange={setToggle.withoutOver}
|
||||
value={toggles.withoutOver}
|
||||
/>
|
||||
{api.consts.babe && (
|
||||
// FIXME have some sane era defaults for Aura
|
||||
<Toggle
|
||||
className='staking--buttonToggle'
|
||||
label={t<string>('recent payouts')}
|
||||
onChange={setWithPayout}
|
||||
value={withPayout}
|
||||
onChange={setToggle.withPayout}
|
||||
value={toggles.withPayout}
|
||||
/>
|
||||
)}
|
||||
<Toggle
|
||||
className='staking--buttonToggle'
|
||||
label={t<string>('only elected')}
|
||||
onChange={setWithElected}
|
||||
value={withElected}
|
||||
onChange={setToggle.withElected}
|
||||
value={toggles.withElected}
|
||||
/>
|
||||
</Filtering>
|
||||
</div>
|
||||
), [api, nameFilter, _setNameFilter, t, withElected, withGroup, withIdentity, withPayout, withoutComm, withoutOver]);
|
||||
), [api, nameFilter, _setNameFilter, setToggle, t, toggles]);
|
||||
|
||||
const displayList = isQueryFiltered
|
||||
? validators
|
||||
|
||||
@ -29,6 +29,7 @@ export { useOwnStashes, useOwnStashIds } from './useOwnStashes';
|
||||
export { useOwnStashInfos } from './useOwnStashInfos';
|
||||
export { usePassword } from './usePassword';
|
||||
export { useRegistrars } from './useRegistrars';
|
||||
export { useSavedFlags } from './useSavedFlags';
|
||||
export { useSudo } from './useSudo';
|
||||
export { useToggle } from './useToggle';
|
||||
export { useVotingStatus } from './useVotingStatus';
|
||||
|
||||
51
packages/react-hooks/src/useSavedFlags.ts
Normal file
51
packages/react-hooks/src/useSavedFlags.ts
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright 2017-2020 @polkadot/react-hooks authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import store from 'store';
|
||||
|
||||
import { isBoolean } from '@polkadot/util';
|
||||
|
||||
type Flags = Record<string, boolean>;
|
||||
|
||||
type Setters<T extends Flags> = Record<keyof T, (value: boolean) => void>;
|
||||
|
||||
type State<T extends Flags> = [T, Setters<T>];
|
||||
|
||||
function getInitial <T extends Flags> (storageKey: string, initial: T): T {
|
||||
const saved = store.get(`flags:${storageKey}`, {}) as T;
|
||||
|
||||
return Object.keys(initial).reduce((result, key: keyof T): T => {
|
||||
if (isBoolean(saved[key])) {
|
||||
result[key] = saved[key];
|
||||
}
|
||||
|
||||
return result;
|
||||
}, { ...initial });
|
||||
}
|
||||
|
||||
function getSetters <T extends Flags> (flags: T, setFlags: React.Dispatch<React.SetStateAction<T>>): Setters<T> {
|
||||
const setFlag = (key: keyof T) =>
|
||||
(value: boolean) =>
|
||||
setFlags((state) => ({ ...state, [key]: value }));
|
||||
|
||||
return Object.keys(flags).reduce((setters, key: keyof T): Setters<T> => {
|
||||
setters[key] = setFlag(key);
|
||||
|
||||
return setters;
|
||||
}, {} as Setters<T>);
|
||||
}
|
||||
|
||||
export function useSavedFlags <T extends Flags> (storageKey: string, initial: T): State<T> {
|
||||
const [flags, setFlags] = useState(getInitial(storageKey, initial));
|
||||
const [setters] = useState(getSetters(initial, setFlags));
|
||||
|
||||
useEffect(
|
||||
(): void => {
|
||||
store.set(`flags:${storageKey}`, flags);
|
||||
},
|
||||
[flags, storageKey]
|
||||
);
|
||||
|
||||
return [flags, setters];
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user