Skip to content

Commit

Permalink
Enable validator overview (#1872)
Browse files Browse the repository at this point in the history
* Enable validator overview

* CallDiv indicator for consts
  • Loading branch information
jacogr authored Nov 12, 2019
1 parent c9e9fc5 commit e7e4efe
Show file tree
Hide file tree
Showing 17 changed files with 234 additions and 128 deletions.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
"packages/*"
],
"resolutions": {
"@polkadot/api": "^0.97.0-beta.2",
"@polkadot/api-contract": "^0.97.0-beta.2",
"@polkadot/api": "^0.97.0-beta.3",
"@polkadot/api-contract": "^0.97.0-beta.3",
"@polkadot/keyring": "^1.7.0-beta.6",
"@polkadot/types": "^0.97.0-beta.2",
"@polkadot/types": "^0.97.0-beta.3",
"@polkadot/util": "^1.7.0-beta.6",
"@polkadot/util-crypto": "^1.7.0-beta.6",
"babel-core": "^7.0.0-bridge.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/app-contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.7.1",
"@polkadot/api-contract": "^0.97.0-beta.2",
"@polkadot/api-contract": "^0.97.0-beta.3",
"@polkadot/react-components": "^0.37.0-beta.72"
}
}
21 changes: 20 additions & 1 deletion packages/app-staking/src/Overview/Address.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ interface StakingState {
const WITH_VALIDATOR_PREFS = { validatorPayment: true };

function Address ({ address, authorsMap, className, defaultName, filter, isElected, isFavorite, lastAuthors, myAccounts, onFavorite, points, recentlyOnline, stakingInfo, t, withNominations = true }: Props): React.ReactElement<Props> | null {
const { isSubstrateV2 } = useContext(ApiContext);
const { api, isSubstrateV2 } = useContext(ApiContext);
const [extraInfo, setExtraInfo] = useState<[React.ReactNode, React.ReactNode][] | undefined>();
const [hasActivity, setHasActivity] = useState(true);
const [{ balanceOpts, controllerId, hasNominators, isNominatorMe, nominators, sessionId, stashId }, setStakingState] = useState<StakingState>({
Expand Down Expand Up @@ -123,6 +123,9 @@ function Address ({ address, authorsMap, className, defaultName, filter, isElect
const lastBlockNumber = authorsMap[stashId];
const isAuthor = lastAuthors && lastAuthors.includes(stashId);
const _onFavorite = (): void => onFavorite(stashId);
const _onQueryStats = (): void => {
window.location.hash = `/staking/query/${stashId}`;
};

return (
<AddressCard
Expand Down Expand Up @@ -183,6 +186,15 @@ function Address ({ address, authorsMap, className, defaultName, filter, isElect
</>
}
isDisabled={isSubstrateV2 && !hasActivity}
overlay={
api.query.imOnline?.authoredBlocks && (
<Icon
className='staking--stats'
name='line graph'
onClick={_onQueryStats}
/>
)
}
stakingInfo={stakingInfo}
value={stashId}
withBalance={balanceOpts}
Expand Down Expand Up @@ -275,6 +287,13 @@ export default withMulti(
.staking--label.controllerSpacer {
margin-top: 0.5rem;
}
.staking--stats {
bottom: 0.75rem;
cursor: pointer;
position: absolute;
right: 0.5rem;
}
`,
translate,
withCalls<Props>(
Expand Down
4 changes: 2 additions & 2 deletions packages/app-staking/src/Overview/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import Summary from './Summary';

interface Props extends BareProps, ComponentProps {}

export default function Overview ({ allControllers, allStashes, recentlyOnline, stakingOverview }: Props): React.ReactElement<Props> {
export default function Overview ({ allControllers, allStashes, className, recentlyOnline, stakingOverview }: Props): React.ReactElement<Props> {
const { isSubstrateV2 } = useContext(ApiContext);
const { byAuthor, lastBlockAuthors, lastBlockNumber } = useContext(BlockAuthorsContext);
const [next, setNext] = useState<string[]>([]);
Expand All @@ -31,7 +31,7 @@ export default function Overview ({ allControllers, allStashes, recentlyOnline,
}, [allControllers, allStashes, validators]);

return (
<div className='staking--Overview'>
<div className={`staking--Overview ${className}`}>
<Summary
allControllers={allControllers}
lastBlock={lastBlockNumber}
Expand Down
34 changes: 21 additions & 13 deletions packages/app-staking/src/Query/Validator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,14 @@ interface Props extends I18nProps {
validatorId: string;
}

interface Value {
label: string;
value: BN;
}
// assuming 4 hrs sessions, we we grab results for 10 days
const SESSIONS = 10 * (24 / 4);

function getIndexRange (currentIndex: SessionIndex): BN[] {
const range: BN[] = [];
let thisIndex: BN = currentIndex;

while (thisIndex.gtn(0) && range.length < 50) {
while (thisIndex.gtn(0) && range.length < SESSIONS) {
range.push(thisIndex);

thisIndex = thisIndex.subn(1);
Expand All @@ -40,7 +38,7 @@ function getIndexRange (currentIndex: SessionIndex): BN[] {

function Validator ({ blockCounts, className, currentIndex, t }: Props): React.ReactElement<Props> {
const [labels, setLabels] = useState<string[]>([]);
const [values, setValues] = useState<Value[]>([]);
const [{ avgSet, idxSet }, setValues] = useState<{ avgSet: number[]; idxSet: BN[] }>({ avgSet: [], idxSet: [] });

useEffect((): void => {
setLabels(
Expand All @@ -50,19 +48,29 @@ function Validator ({ blockCounts, className, currentIndex, t }: Props): React.R

useEffect((): void => {
if (blockCounts) {
setValues(
blockCounts.map((value, index): Value => ({
label: labels[index],
value
}))
);
const avgSet: number[] = [];
const idxSet: BN[] = [];

blockCounts.reduce((total: BN, value, index): BN => {
total = total.add(value);

avgSet.push(total.toNumber() / (index + 1));
idxSet.push(value);

return total;
}, new BN(0));

setValues({ avgSet, idxSet });
}
}, [blockCounts, labels]);

return (
<div className={className}>
<h1>{t('blocks per session')}</h1>
<Chart.Line values={values} />
<Chart.Line
labels={labels}
legends={[t('blocks'), t('average')]}
values={[idxSet, avgSet]} />
</div>
);
}
Expand Down
71 changes: 59 additions & 12 deletions packages/app-staking/src/Query/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

import { BareProps } from '@polkadot/react-components/types';
import { I18nProps } from '@polkadot/react-components/types';
import { ComponentProps } from '../types';

import React from 'react';
import React, { useState } from 'react';
import { withRouter, RouteComponentProps } from 'react-router-dom';
import { Button, InputAddressSimple } from '@polkadot/react-components';

import translate from '../translate';
import Validator from './Validator';

interface Props extends BareProps, ComponentProps, RouteComponentProps<{}> {
interface Props extends I18nProps, ComponentProps, RouteComponentProps<{}> {
match: {
isExact: boolean;
params: {
Expand All @@ -21,17 +23,62 @@ interface Props extends BareProps, ComponentProps, RouteComponentProps<{}> {
};
}

function Query ({ stakingOverview, match: { params: { value } } }: Props): React.ReactElement<Props> {
if (!stakingOverview) {
return <div>loading</div>;
}
// const _onQuery = (): void => {
// if (isValid && value.length !== 0) {
// window.location.hash = `/explorer/query/${value}`;
// }
// };

// return (
// <FilterOverlay className={className}>
// <Input
// className='explorer--query'
// defaultValue={propsValue}
// isError={!isValid && value.length !== 0}
// placeholder={t('block hash or number to query')}
// onChange={_setHash}
// onEnter={_onQuery}
// withLabel={false}
// >
// <Button
// icon='play'
// onClick={_onQuery}
// />
// </Input>

function Query ({ className, stakingOverview, match: { params: { value } }, t }: Props): React.ReactElement<Props> {
const [validatorId, setValidatorId] = useState<string | null>(value || null);

const _onQuery = (): void => {
if (validatorId) {
window.location.hash = `/staking/query/${validatorId}`;
}
};

return (
<Validator
currentIndex={stakingOverview.currentIndex}
validatorId={value}
/>
<div className={className}>
<InputAddressSimple
className='staking--queryInput'
defaultValue={value}
help={t('Display overview information for the selected validator, including blocks produced.')}
label={t('validator to query')}
onChange={setValidatorId}
onEnter={_onQuery}
>
<Button
icon='play'
isDisabled={!validatorId}
onClick={_onQuery}
/>
</InputAddressSimple>
{value && stakingOverview && (
<Validator
currentIndex={stakingOverview.currentIndex}
validatorId={value}
/>
)}
</div>
);
}

export default withRouter(Query);
export default translate(withRouter(Query));
32 changes: 26 additions & 6 deletions packages/app-staking/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ import { AccountId, BlockNumber } from '@polkadot/types/interfaces';
import { SubjectInfo } from '@polkadot/ui-keyring/observable/types';
import { ComponentProps } from './types';

import React from 'react';
import React, { useContext } from 'react';
import { Route, Switch } from 'react-router';
import { useRouteMatch } from 'react-router-dom';
import styled from 'styled-components';
import { Option } from '@polkadot/types';
import { HelpOverlay } from '@polkadot/react-components';
import Tabs from '@polkadot/react-components/Tabs';
import { withCalls, withMulti, withObservable } from '@polkadot/react-api';
import { ApiContext, withCalls, withMulti, withObservable } from '@polkadot/react-api';
import accountObservable from '@polkadot/ui-keyring/observable/accounts';

import Accounts from './Actions/Accounts';
Expand All @@ -36,7 +37,9 @@ const EMPY_ACCOUNTS: string[] = [];
const EMPTY_ALL: [string[], string[]] = [EMPY_ACCOUNTS, EMPY_ACCOUNTS];

function App ({ allAccounts, allStashesAndControllers: [allStashes, allControllers] = EMPTY_ALL, basePath, className, recentlyOnline, stakingOverview, t }: Props): React.ReactElement<Props> {
const _renderComponent = (Component: React.ComponentType<ComponentProps>): () => React.ReactNode => {
const { api } = useContext(ApiContext);
const routeMatch = useRouteMatch({ path: basePath, strict: true });
const _renderComponent = (Component: React.ComponentType<ComponentProps>, className?: string): () => React.ReactNode => {
// eslint-disable-next-line react/display-name
return (): React.ReactNode => {
if (!allAccounts) {
Expand All @@ -48,6 +51,7 @@ function App ({ allAccounts, allStashesAndControllers: [allStashes, allControlle
allAccounts={allAccounts}
allControllers={allControllers}
allStashes={allStashes}
className={className}
recentlyOnline={recentlyOnline}
stakingOverview={stakingOverview}
/>
Expand All @@ -63,8 +67,10 @@ function App ({ allAccounts, allStashesAndControllers: [allStashes, allControlle
basePath={basePath}
hidden={
!allAccounts || Object.keys(allAccounts).length === 0
? ['actions']
: []
? ['actions', 'query']
: api.query.imOnline?.authoredBlocks
? []
: ['query']
}
items={[
{
Expand All @@ -75,15 +81,21 @@ function App ({ allAccounts, allStashesAndControllers: [allStashes, allControlle
{
name: 'actions',
text: t('Account actions')
},
{
hasParams: true,
name: 'query',
text: t('Validator stats')
}
]}
/>
</header>
<Switch>
<Route path={`${basePath}/actions`} render={_renderComponent(Accounts)} />
<Route path={`${basePath}/query/:value`} render={_renderComponent(Query)} />
<Route render={_renderComponent(Overview)} />
<Route path={`${basePath}/query`} render={_renderComponent(Query)} />
</Switch>
{_renderComponent(Overview, routeMatch?.isExact ? '' : 'staking--hidden')()}
</main>
);
}
Expand All @@ -93,6 +105,14 @@ export default withMulti(
.rx--updated {
background: transparent !important;
}
.staking--hidden {
display: none;
}
.staking--queryInput {
margin-bottom: 1.5rem;
}
`,
translate,
withCalls<Props>(
Expand Down
1 change: 1 addition & 0 deletions packages/app-staking/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export interface ComponentProps {
allAccounts?: SubjectInfo;
allControllers: string[];
allStashes: string[];
className?: string;
recentlyOnline?: DerivedHeartbeats;
stakingOverview?: DerivedStakingOverview;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/app-storage/src/Query.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ function getCachedComponent (query: QueryTypes): CacheInstance {
if (isConst) {
const { meta, method, section } = key as unknown as ConstValue;

renderHelper = withCallDiv(`consts.${section}.${method}`);
renderHelper = withCallDiv(`consts.${section}.${method}`, { withIndicator: true });
type = meta.type.toString();
} else {
const values: any[] = params.map(({ value }): any => value);
Expand Down
2 changes: 1 addition & 1 deletion packages/app-storage/src/Selection/Consts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +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 { ConstantCodec } from '@polkadot/api-metadata/consts/types';
import { ConstantCodec } from '@polkadot/metadata/Decorated/types';
import { I18nProps } from '@polkadot/react-components/types';
import { ConstValue } from '@polkadot/react-components/InputConsts/types';
import { ComponentProps } from '../types';
Expand Down
2 changes: 1 addition & 1 deletion packages/react-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"homepage": "https://github.com/polkadot-js/ui/tree/master/packages/ui-reactive#readme",
"dependencies": {
"@babel/runtime": "^7.7.1",
"@polkadot/api": "^0.97.0-beta.2",
"@polkadot/api": "^0.97.0-beta.3",
"@polkadot/extension-dapp": "^0.14.0-beta.4",
"edgeware-node-types": "^1.0.10",
"rxjs-compat": "^6.5.3"
Expand Down
4 changes: 3 additions & 1 deletion packages/react-components/src/AddressRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export interface Props extends I18nProps, RowProps {
label?: string;
accounts_info?: DeriveAccountInfo;
noDefaultNameOpacity?: boolean;
overlay?: React.ReactNode;
stakingInfo?: DerivedStaking;
value: AccountId | AccountIndex | Address | string | null;
withAddressOrName?: boolean;
Expand Down Expand Up @@ -83,7 +84,7 @@ class AddressRow extends Row<ApiProps & Props, State> {
}

public render (): React.ReactNode {
const { accounts_info = {}, className, isContract, isDisabled, isInline, label, style } = this.props;
const { accounts_info = {}, className, isContract, isDisabled, isInline, label, overlay, style } = this.props;
const { accountId, accountIndex } = accounts_info;
const isValid = this.props.isValid || accountId || accountIndex;

Expand All @@ -104,6 +105,7 @@ class AddressRow extends Row<ApiProps & Props, State> {
{this.renderButtons()}
</div>
{this.renderChildren()}
{overlay}
</div>
);
}
Expand Down
Loading

0 comments on commit e7e4efe

Please sign in to comment.