Hover & signer name updates (#646)

* Hover should not hop all over the screen

* Rework signer with name/address display
This commit is contained in:
Jaco Greeff 2019-01-25 11:34:56 +01:00 committed by GitHub
parent e695149786
commit 077dfc398d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 175 additions and 158 deletions

View File

@ -27,7 +27,6 @@ class Events extends React.PureComponent<Props> {
<h1>{t('events')}</h1>
<div className='explorer--BlockByHash-flexable'>
<EventsDisplay
isSummary
eventClassName='explorer--BlockByHash-block'
value={value}
/>

View File

@ -60,17 +60,21 @@ class Extrinsics extends React.PureComponent<Props> {
<h3>
{section}.{method}&nbsp;(#{numberFormat(index)})
</h3>
<div className='ui--hover description'>{
meta && meta.documentation && meta.documentation.length
? meta.documentation.map((doc) => doc.toString()).join(' ')
: ''
}</div>
{this.renderSigner(extrinsic)}
</div>
<Call
className='ui--hover details'
value={extrinsic}
/>
<div className='ui--hover'>
<div className='ui--hover-content'>
<div className='description'>{
meta && meta.documentation && meta.documentation.length
? meta.documentation.map((doc) => doc.toString()).join(' ')
: ''
}</div>
<Call
className='details'
value={extrinsic}
/>
</div>
</div>
</article>
</div>
);

View File

@ -48,18 +48,17 @@ class Logs extends React.PureComponent<Props> {
return (
<div
className='ui--hoverable explorer--BlockByHash-block'
className='explorer--BlockByHash-block'
key={index}
>
<article className='explorer--Container'>
<article className='explorer--Container ui--hoverable'>
<div className='header'>
<h3>
{item.type.toString()}
</h3>
<div className='ui--hover description' />
<h3>{item.type.toString()}</h3>
</div>
<div className='ui--hover details'>
{content}
<div className='ui--hover'>
<div className='ui--hover-content'>
{content}
</div>
</div>
</article>
</div>

View File

@ -10,23 +10,6 @@
.explorer--BlockHeader {
animation: fadein 1.5s;
> div {
padding: 0.5em;
overflow: hidden;
}
&.ui--hoverable {
.details > .contains {
margin-top: 0;
}
&:hover {
.details > .contains {
margin-top: 0.5rem;
}
}
}
.author {
font-size: 1rem;
text-align: right;
@ -37,6 +20,11 @@
}
}
.header-outer {
padding: 0.5rem;
overflow: hidden;
}
.header {
color: rgba(0, 0, 0, 0.6);
display: flex;
@ -61,7 +49,6 @@
.hash {
font-size: 1.5rem;
font-family: sans-serif;
/*opacity: 0.75;*/
}
}
@ -76,34 +63,26 @@
box-sizing: border-box;
}
.details {
box-sizing: border-box;
flex: 1;
min-width: 0;
.contains {
border: 0;
padding: 0.5rem;
text-align: center;
overflow: hidden;
> .contains {
border: 0;
margin-top: 0.5rem;
opacity: 0.75;
> .info {
margin-bottom: 0.125em;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
> .info {
margin-bottom: 0.125em;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
> div {
display: inline-block;
padding: 0 0.25em;
vertical-align: middle;
> div {
display: inline-block;
padding: 0 0.25em;
vertical-align: middle;
&.type {
opacity: 0.75;
text-align: right;
width: 10em;
}
&.type {
opacity: 0.75;
text-align: right;
width: 10em;
}
}
}

View File

@ -36,7 +36,7 @@ export default class BlockHeader extends React.PureComponent<Props> {
return (
<article className={['explorer--BlockHeader', isSummary ? 'ui--hoverable summary' : ''].join(' ')}>
<div className='details'>
<div className='header-outer'>
<div className='header'>
<div className='number'>{
withLink
@ -50,7 +50,9 @@ export default class BlockHeader extends React.PureComponent<Props> {
: undefined
}</div>
</div>
<div className='ui--hover contains'>
</div>
<div className='ui--hover'>
<div className='ui--hover-content contains'>
<div className='info'>
<div className='type'>parentHash</div>
<div className='hash'>{

View File

@ -45,9 +45,9 @@ class BlockHeaders extends React.PureComponent<Props> {
return (
<div className='explorer--BlockHeaders'>
{headers.map((header, index) => (
{headers.map((header) => (
<BlockHeader
isSummary={index !== 0}
isSummary
key={header.blockNumber.toString()}
value={header}
withLink={!header.blockNumber.isZero()}

View File

@ -12,7 +12,6 @@ import { numberFormat } from '@polkadot/ui-reactive/util/index';
import translate from './translate';
type Props = I18nProps & {
isSummary?: boolean,
value?: Array<EventRecord>,
emptyLabel?: React.ReactNode,
eventClassName?: string,
@ -46,14 +45,14 @@ class Events extends React.PureComponent<Props> {
}
private renderEvent = ({ event, phase }: EventRecord, index: number) => {
const { isSummary, withoutIndex } = this.props;
const { withoutIndex } = this.props;
const extIndex = !withoutIndex && phase.type === 'ApplyExtrinsic'
? phase.asApplyExtrinsic
: -1;
return (
<article
className={['explorer--Container', (isSummary || index) ? 'ui--hoverable' : ''].join(' ')}
className={['explorer--Container', 'ui--hoverable'].join(' ')}
key={index}
>
<div className='header'>
@ -64,18 +63,23 @@ class Events extends React.PureComponent<Props> {
: ''
}
</h3>
<div className='ui--hover description'>
{
event.meta.documentation && event.meta.documentation.length
? event.meta.documentation.map((doc) => doc.toString()).join(' ')
: ''
}
</div>
<div className='ui--hover'>
<div className='ui--hover-content'>
<div className='description'>
{
event.meta.documentation && event.meta.documentation.length
? event.meta.documentation.map((doc) => doc.toString()).join(' ')
: ''
}
</div>
<EventDisplay
className='details'
value={event}
/>
</div>
</div>
<EventDisplay
className='ui--hover details'
value={event}
/>
</article>
);
}

View File

@ -45,11 +45,6 @@
.explorer--Container {
color: inherit;
&:not(.ui--hoverable) .header .description,
&.ui--hoverable:hover .header .description {
margin: 0.25rem 0 0.5rem 0;
}
.header {
position: relative;
vertical-align: middle;
@ -57,14 +52,15 @@
h3 {
margin: 0;
}
}
.description {
color: rgba(0, 0, 0, 0.6);
overflow: hidden;
text-overflow: ellipsis;
vertical-align: middle;
white-space: nowrap;
}
.description {
color: rgba(0, 0, 0, 0.6);
margin: 0rem 0 0.5rem 0;
overflow: hidden;
text-overflow: ellipsis;
vertical-align: middle;
white-space: nowrap;
}
> .details {

View File

@ -24,9 +24,9 @@ class AddressRow extends AddressSummary {
{this.renderAddress()}
{this.renderBalance()}
{this.renderNonce()}
{this.renderChildren()}
</div>
</div>
{this.renderChildren()}
</div>
);
}

View File

@ -196,8 +196,10 @@ class AddressSummary extends React.PureComponent<Props> {
}
return (
<div className='ui--AddressSummary-children ui--hover'>
{children}
<div className='ui--hover'>
<div className='ui--AddressSummary-children ui--hover-content'>
{children}
</div>
</div>
);
}

View File

@ -11,7 +11,7 @@ import React from 'react';
import store from 'store';
import keyring from '@polkadot/ui-keyring';
import keyringOption from '@polkadot/ui-keyring/options';
import makeOption from '@polkadot/ui-keyring/options/item';
import createItem from '@polkadot/ui-keyring/options/item';
import { withMulti, withObservable } from '@polkadot/ui-api/index';
import Dropdown from '../Dropdown';
@ -25,7 +25,7 @@ type Props = BareProps & {
isError?: boolean,
isInput?: boolean,
label?: string,
onChange: (value: string | null) => void,
onChange?: (value: string | null) => void,
optionsAll?: KeyringOptions,
placeholder?: string,
type?: KeyringOption$Type,
@ -59,6 +59,22 @@ const transformToAccountId = (value: string): string | null => {
: accountId;
};
const createOption = (address: string) => {
let name: string | undefined;
try {
name = keyring.getAccount(address).getMeta().name;
} catch (error) {
try {
name = keyring.getAddress(address).getMeta().name;
} catch (error) {
// ok, we don't have account or address
}
}
return createItem(address, name);
};
class InputAddress extends React.PureComponent<Props, State> {
constructor (props: Props) {
super(props);
@ -126,7 +142,7 @@ class InputAddress extends React.PureComponent<Props, State> {
onSearch={this.onSearch}
options={
isDisabled && actualValue
? [makeOption(actualValue)]
? [createOption(actualValue)]
: optionsAll[type]
}
style={style}
@ -169,7 +185,7 @@ class InputAddress extends React.PureComponent<Props, State> {
InputAddress.setLastValue(type, address);
onChange(transformToAccountId(address));
onChange && onChange(transformToAccountId(address));
}
private onSearch = (filteredOptions: KeyringSectionOptions, _query: string): KeyringSectionOptions => {

View File

@ -69,11 +69,6 @@ header .ui--Button-Group {
text-align: right;
}
.ui--AddressRow {
display: flex;
width: 100%;
}
.ui--AddressRow-base {
display: flex;
}
@ -100,25 +95,13 @@ header .ui--Button-Group {
}
.ui--AddressSummary-children {
padding-top: 0.5rem;
margin-top: 0.5rem !important;
}
.ui--AddressRow .ui--AddressSummary-children {
display: block;
}
.ui--hoverable {
.ui--AddressSummary-children.ui--hover {
padding-top: 0;
}
&:hover {
.ui--AddressSummary-children.ui--hover {
padding-top: 0.5rem;
}
}
}
.ui--AddressSummary .rx--updated {
background: transparent !important;
}

View File

@ -2,19 +2,34 @@
/* This software may be modified and distributed under the terms
/* of the Apache-2.0 license. See the LICENSE file for details. */
.ui--hoverable {
article.ui--hoverable {
.ui--hover {
height: 0;
opacity: 0;
transition: none;
transform: scale(0);
position: relative;
margin: 0 -1.5rem;
}
&:hover .ui--hover {
height: auto;
opacity: 1;
transform: scale(1);
transition: all 0.25s ease-in;
.ui--hover-content {
border: 1px solid #4e4e4e;
border-radius: 0 0 0.25rem 0.25rem;
border-top-width: 0;
border-left-width: 0.25rem;
background: white;
display: none !important;
left: -0.25rem;
padding: 0.5rem 1.5rem 1rem;
position: absolute;
right: -1px;
top: -1px;
z-index: 50;
}
&:hover,
&.active {
border-color: #4e4e4e;
.ui--hover-content {
display: block !important;
}
}
}

View File

@ -14,7 +14,6 @@
background-color: $button-primary-color;
}
.ui.primary.button:hover,
.ui.buttons .primary.button:hover {
background-color: $button-primary-color-hover;
@ -97,4 +96,15 @@
.ui.red.progress .bar {
background-color: $red;
}
article.ui--hoverable {
.ui--hover-content {
border-color: $wild-orchid;
}
&:hover,
&.active {
border-color: $wild-orchid;
}
}
}

View File

@ -8,7 +8,7 @@
.ui--Params-Content {
box-sizing: border-box;
padding-left: 2em;
padding-left: 1.5rem;
}
.ui--Param-text {

View File

@ -6,9 +6,8 @@ import { I18nProps } from '@polkadot/ui-app/types';
import { QueueTx } from '@polkadot/ui-app/Status/types';
import React from 'react';
import { Trans } from 'react-i18next';
import { Method } from '@polkadot/types';
import { Call, IdentityIcon, Modal } from '@polkadot/ui-app/index';
import { Call, InputAddress, Modal } from '@polkadot/ui-app/index';
import Fees from './Fees';
import translate from './translate';
@ -20,47 +19,52 @@ type Props = I18nProps & {
class Transaction extends React.PureComponent<Props> {
render () {
const { children, t, value: { accountId, extrinsic, isUnsigned } } = this.props;
const { children, value: { extrinsic } } = this.props;
if (!extrinsic) {
return null;
}
const { method, section } = Method.findFunction(extrinsic.callIndex);
const header = isUnsigned
? (
<Trans i18nKey='decoded.short-unsigned'>You are about to submit an (unsigned) inherent transaction calling <span className='code'>{section}.{method}</span></Trans>
)
: (
<Trans i18nKey='decoded.short-signed'>You are about to sign a transaction from <span className='code'>{accountId}</span> calling <span className='code'>{section}.{method}</span> </Trans>
);
const icon = isUnsigned
? undefined
: (
<IdentityIcon
className='icon'
value={accountId}
/>
);
return [
<Modal.Header key='header'>
{t('Submit Transaction')}
{section}.{method}
</Modal.Header>,
<Modal.Content className='ui--signer-Signer-Content' key='content'>
<div className='ui--signer-Signer-Decoded'>
<div className='expanded'>
<p>{header}</p>
<div className='ui--signer-Signer-children'>
{this.renderAccount()}
{children}
</div>
<Call value={extrinsic} />
{this.renderFees()}
</div>
{icon}
</div>
{children}
</Modal.Content>
];
}
private renderAccount () {
const { t, value: { accountId, isUnsigned } } = this.props;
if (isUnsigned || !accountId) {
return null;
}
return (
<InputAddress
className='full'
defaultValue={accountId}
isDisabled
isInput
label={t('from my account')}
withLabel
/>
);
}
private renderFees () {
const { value: { accountId, extrinsic, isUnsigned } } = this.props;
@ -69,12 +73,10 @@ class Transaction extends React.PureComponent<Props> {
}
return (
<div className='ui--Params-Content'>
<Fees
accountId={accountId}
extrinsic={extrinsic}
/>
</div>
<Fees
accountId={accountId}
extrinsic={extrinsic}
/>
);
}
}

View File

@ -57,7 +57,7 @@ class Unlock extends React.PureComponent<Props, State> {
autoFocus={autoFocus}
className='medium'
isError={isError}
label={label || t('unlock account using the password')}
label={label || t('unlocked using the password')}
onChange={onChange}
onKeyDown={onKeyDown}
tabIndex={tabIndex}

View File

@ -11,12 +11,14 @@
line-height: 1.5em;
}
.ui--signer-Signer-Unlock {
padding-top: 1.5rem;
.ui--signer-Signer-children {
padding: 0.25rem 0 0 0;
}
.ui--signer-Signer-Content .expanded {
padding-right: 2em;
h3 {
margin-bottom: 0.75rem;
}
.code {
background: #f5f5f5;
@ -28,6 +30,10 @@
word-break: break-word;
word-wrap: break-word;
}
.hl {
font-weight: 700;
}
}
.ui--signer-Status {