Identity judgements (#2064)

* Display identity judgements

* Small badge alignment adjustment

* Linting

* Check namaes against lowercase
This commit is contained in:
Jaco Greeff 2019-12-17 13:40:39 +01:00 committed by GitHub
parent 0c50fcd773
commit adf1c1c800
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 113 additions and 22 deletions

View File

@ -34,9 +34,10 @@ function AddressToggle ({ address, className, filter, onChange, value }: Props):
if (!filter || address.includes(filter) || extracted.toLowerCase().includes(filter)) {
isFiltered = false;
} else if (info) {
const { accountId, accountIndex, nickname } = info;
const { accountId, accountIndex, identity, nickname } = info;
const filterLower = filter.toLowerCase();
if (accountId?.toString().includes(filter) || accountIndex?.toString().includes(filter) || nickname?.toLowerCase().includes(filter)) {
if (identity.displayName?.toLowerCase().includes(filterLower) || accountId?.toString().includes(filter) || accountIndex?.toString().includes(filter) || nickname?.toLowerCase().includes(filterLower)) {
isFiltered = false;
}
}

View File

@ -12,18 +12,19 @@ interface Props {
hover?: React.ReactNode;
info: React.ReactNode;
isInline?: boolean;
isSmall?: boolean;
isTooltip?: boolean;
type: 'counter' | 'online' | 'offline' | 'next' | 'runnerup' | 'selected';
type: 'counter' | 'online' | 'offline' | 'next' | 'runnerup' | 'selected' | 'green' | 'blue' | 'brown' | 'gray';
}
let badgeId = 0;
function Badge ({ className, hover, info, isInline, isTooltip, type }: Props): React.ReactElement<Props> | null {
function Badge ({ className, hover, info, isInline, isSmall, isTooltip, type }: Props): React.ReactElement<Props> | null {
const [key] = useState(`${Date.now()}-${badgeId++}`);
return (
<div
className={`ui--Badge ${isInline && 'isInline'} ${isTooltip && 'isTooltip'} ${type} ${className}`}
className={`ui--Badge ${isInline && 'isInline'} ${isTooltip && 'isTooltip'} ${isSmall && 'isSmall'} ${type} ${className}`}
data-for={`badge-status-${key}`}
data-tip={true}
data-tip-disable={!isTooltip}
@ -55,6 +56,20 @@ export default styled(Badge)`
text-align: center;
width: 22px;
i.icon {
margin: 0;
width: 1em;
}
&.isSmall {
box-shadow: none;
font-size: 10px;
height: 16px;
line-height: 16px;
padding: 0;
width: 16px;
}
&:not(.isInline) {
display: flex;
justify-content: center;
@ -66,7 +81,8 @@ export default styled(Badge)`
margin-right: 0.25rem;
}
&.next {
&.next,
&.blue {
background: steelblue;
}
@ -80,24 +96,29 @@ export default styled(Badge)`
vertical-align: middle;
}
&.runnerup {
&.gray {
background: #eee;
color: #888;
}
&.runnerup,
&.brown {
background: brown;
}
&.online,
&.selected {
&.selected,
&.green {
background: green;
}
& > * {
line-height: 22px;
overflow: hidden;
transition: all ease 0.25;
}
.badge {
font-weight: bold;
width: auto;
&.isSmall > * {
line-height: 16px;
}
.detail {

View File

@ -7,6 +7,8 @@ import { BareProps } from '@polkadot/react-api/types';
import { AccountId, AccountIndex, Address } from '@polkadot/types/interfaces';
import React, { useEffect, useMemo, useState } from 'react';
import styled from 'styled-components';
import { Badge, Icon } from '@polkadot/react-components';
import { getAddressName } from '@polkadot/react-components/util';
import { useCall, useApi } from '@polkadot/react-hooks';
@ -21,14 +23,14 @@ interface Props extends BareProps {
withShort?: boolean;
}
const nameCache: Map<string, string> = new Map();
const nameCache: Map<string, React.ReactNode> = new Map();
function defaultOrAddr (defaultName = '', _address: AccountId | AccountIndex | Address | string | Uint8Array, _accountIndex?: AccountIndex | null): string {
function defaultOrAddr (defaultName = '', _address: AccountId | AccountIndex | Address | string | Uint8Array, _accountIndex?: AccountIndex | null): [React.ReactNode, boolean] {
const accountId = _address.toString();
const cached = nameCache.get(accountId);
if (cached) {
return cached;
return [cached, false];
}
const accountIndex = (_accountIndex || '').toString();
@ -37,24 +39,68 @@ function defaultOrAddr (defaultName = '', _address: AccountId | AccountIndex | A
if (isAddress && accountIndex) {
nameCache.set(accountId, accountIndex);
return accountIndex;
return [accountIndex, false];
}
return extracted;
return [extracted, !isAddress];
}
export default function AccountName ({ children, className, defaultName, label, onClick, override, style, toggle, value, withShort }: Props): React.ReactElement<Props> {
function AccountName ({ children, className, defaultName, label, onClick, override, style, toggle, value, withShort }: Props): React.ReactElement<Props> {
const { api } = useApi();
const info = useCall<DeriveAccountInfo>(api.derive.accounts.info as any, [value]);
const address = useMemo((): string => (value || '').toString(), [value]);
const [name, setName] = useState(defaultOrAddr(defaultName, address));
const _extractName = (accountId?: AccountId, accountIndex?: AccountIndex): React.ReactNode => {
const [name, isLocal] = defaultOrAddr(defaultName, accountId || address, withShort ? null : accountIndex);
return (
<div className='via-identity'>
<div className={`name ${isLocal ? '' : 'other'}`}>{name}</div>
</div>
);
};
const [name, setName] = useState<React.ReactNode>((): React.ReactNode => _extractName());
useEffect((): void => {
const { accountId, accountIndex, identity, nickname } = info || {};
const retrieved = identity?.displayName || nickname;
if (retrieved) {
const name = retrieved.toUpperCase();
if (api.query.identity?.identityOf) {
if (identity?.displayName) {
const { judgements, displayName } = identity;
const isGood = judgements.some(([, judgement]): boolean => judgement.isKnownGood || judgement.isReasonable);
const isBad = judgements.some(([, judgement]): boolean => judgement.isErroneous || judgement.isLowQuality);
// FIXME This needs to be i18n, with plurals
const hover = `${judgements.length ? judgements.length : 'no'} judgement${judgements.length === 1 ? '' : 's'}${judgements.length ? ': ' : ''}${judgements.map(([, judgement]): string => judgement.toString()).join(', ')}`;
const name = (
<div className='via-identity'>
<Badge
hover={hover}
info={<Icon name={isGood ? 'check' : 'minus'} />}
isInline
isSmall
isTooltip
type={
isGood
? 'green'
: isBad
? 'brown'
: 'gray'
}
/>
<div className='name'>{displayName.toUpperCase()}</div>
</div>
);
nameCache.set(address, name);
setName((): React.ReactNode => name);
} else {
setName((): React.ReactNode => _extractName(accountId, accountIndex));
}
} else if (nickname) {
const name = nickname.toUpperCase();
nameCache.set(address, name);
setName(name);
@ -77,3 +123,26 @@ export default function AccountName ({ children, className, defaultName, label,
</div>
);
}
export default styled(AccountName)`
.via-identity {
display: inline-block;
.name {
display: inline-block;
&.other {
opacity: 0.6;
}
}
> * {
line-height: 1em;
vertical-align: middle;
}
.ui--Badge {
margin-top: -2px;
}
}
`;