Identity judgements (#2064)
* Display identity judgements * Small badge alignment adjustment * Linting * Check namaes against lowercase
This commit is contained in:
parent
0c50fcd773
commit
adf1c1c800
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user