simplify tx confirmations display (#3559)
* Hash component * DRY code by using Hash component * TxHash component: show hash inline * TxHash component: less verbose confirmations display * TxHash component: rename ui/Hash to ui/ShortenedHash * signer: center message in TransactionFinished * style fixes
This commit is contained in:
parent
eec99ebad8
commit
2b178d8233
@ -18,6 +18,8 @@ import React, { Component, PropTypes } from 'react';
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
|
|
||||||
|
import ShortenedHash from '../ShortenedHash';
|
||||||
|
|
||||||
const defaultName = 'UNNAMED';
|
const defaultName = 'UNNAMED';
|
||||||
|
|
||||||
class IdentityName extends Component {
|
class IdentityName extends Component {
|
||||||
@ -41,7 +43,7 @@ class IdentityName extends Component {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const addressFallback = shorten ? this.formatHash(address) : address;
|
const addressFallback = shorten ? (<ShortenedHash data={ address } />) : address;
|
||||||
const fallback = unknown ? defaultName : addressFallback;
|
const fallback = unknown ? defaultName : addressFallback;
|
||||||
const isUuid = hasAccount && account.name === account.uuid;
|
const isUuid = hasAccount && account.name === account.uuid;
|
||||||
const displayName = (name && name.toUpperCase().trim()) ||
|
const displayName = (name && name.toUpperCase().trim()) ||
|
||||||
@ -55,14 +57,6 @@ class IdentityName extends Component {
|
|||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
formatHash (hash) {
|
|
||||||
if (!hash || hash.length <= 16) {
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
return `${hash.substr(2, 6)}...${hash.slice(-6)}`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
|
17
js/src/ui/ShortenedHash/index.js
Normal file
17
js/src/ui/ShortenedHash/index.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
export default from './shortenedHash';
|
21
js/src/ui/ShortenedHash/shortenedHash.css
Normal file
21
js/src/ui/ShortenedHash/shortenedHash.css
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/* Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||||
|
/* This file is part of Parity.
|
||||||
|
/*
|
||||||
|
/* Parity is free software: you can redistribute it and/or modify
|
||||||
|
/* it under the terms of the GNU General Public License as published by
|
||||||
|
/* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
/* (at your option) any later version.
|
||||||
|
/*
|
||||||
|
/* Parity is distributed in the hope that it will be useful,
|
||||||
|
/* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
/* GNU General Public License for more details.
|
||||||
|
/*
|
||||||
|
/* You should have received a copy of the GNU General Public License
|
||||||
|
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.hash {
|
||||||
|
display: inline-block;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
41
js/src/ui/ShortenedHash/shortenedHash.js
Normal file
41
js/src/ui/ShortenedHash/shortenedHash.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import React, { Component, PropTypes } from 'react';
|
||||||
|
|
||||||
|
import styles from './shortenedHash.css';
|
||||||
|
|
||||||
|
export default class ShortenedHash extends Component {
|
||||||
|
static propTypes = {
|
||||||
|
data: PropTypes.string.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { data } = this.props;
|
||||||
|
|
||||||
|
let shortened = data.toLowerCase();
|
||||||
|
if (shortened.slice(0, 2) === '0x') {
|
||||||
|
shortened = shortened.slice(2);
|
||||||
|
}
|
||||||
|
if (shortened.length > (6 + 6)) {
|
||||||
|
shortened = shortened.slice(0, 6) + '…' + shortened.slice(-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<abbr className={ styles.hash } title={ shortened }>{ shortened }</abbr>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -15,19 +15,12 @@
|
|||||||
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.details {
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
}
|
|
||||||
|
|
||||||
.hash {
|
.hash {
|
||||||
padding-top: 1em;
|
padding-top: 1em;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confirm {
|
.confirm {
|
||||||
padding-top: 1em;
|
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,9 @@ import React, { Component, PropTypes } from 'react';
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { LinearProgress } from 'material-ui';
|
import { LinearProgress } from 'material-ui';
|
||||||
|
|
||||||
import { txLink } from '../../3rdparty/etherscan/links';
|
import { txLink } from '../../3rdparty/etherscan/links';
|
||||||
|
import ShortenedHash from '../ShortenedHash';
|
||||||
|
|
||||||
import styles from './txHash.css';
|
import styles from './txHash.css';
|
||||||
|
|
||||||
@ -62,22 +64,23 @@ class TxHash extends Component {
|
|||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { hash, isTest, summary } = this.props;
|
const { hash, isTest, summary } = this.props;
|
||||||
let header = null;
|
|
||||||
|
|
||||||
if (!summary) {
|
const link = (
|
||||||
header = (
|
<a href={ txLink(hash, isTest) } target='_blank'>
|
||||||
<div className={ styles.header }>
|
<ShortenedHash data={ hash } />
|
||||||
The transaction has been posted to the network with a transaction hash of
|
</a>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let header = (
|
||||||
|
<p>The transaction has been posted to the network, with a hash of { link }.</p>
|
||||||
|
);
|
||||||
|
if (summary) {
|
||||||
|
header = (<p>{ link }</p>);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ styles.details }>
|
<div>
|
||||||
{ header }
|
{ header }
|
||||||
<div className={ styles.hash }>
|
|
||||||
<a href={ txLink(hash, isTest) } target='_blank'>{ hash }</a>
|
|
||||||
</div>
|
|
||||||
{ this.renderConfirmations() }
|
{ this.renderConfirmations() }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -87,17 +90,29 @@ class TxHash extends Component {
|
|||||||
const { maxConfirmations } = this.props;
|
const { maxConfirmations } = this.props;
|
||||||
const { blockNumber, transaction } = this.state;
|
const { blockNumber, transaction } = this.state;
|
||||||
|
|
||||||
let txBlock = 'Pending';
|
if (!(transaction && transaction.blockNumber && transaction.blockNumber.gt(0))) {
|
||||||
let confirmations = 'No';
|
return (
|
||||||
let value = 0;
|
<div className={ styles.confirm }>
|
||||||
|
<LinearProgress
|
||||||
if (transaction && transaction.blockNumber && transaction.blockNumber.gt(0)) {
|
className={ styles.progressbar }
|
||||||
const num = blockNumber.minus(transaction.blockNumber).plus(1);
|
color='white'
|
||||||
txBlock = `#${transaction.blockNumber.toFormat(0)}`;
|
mode='indeterminate'
|
||||||
confirmations = num.toFormat(0);
|
/>
|
||||||
value = num.gt(maxConfirmations) ? maxConfirmations : num.toNumber();
|
<div className={ styles.progressinfo }>waiting for confirmations</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const confirmations = blockNumber.minus(transaction.blockNumber).plus(1);
|
||||||
|
const value = Math.min(confirmations.toNumber(), maxConfirmations);
|
||||||
|
let count;
|
||||||
|
if (confirmations.gt(maxConfirmations)) {
|
||||||
|
count = confirmations.toFormat(0);
|
||||||
|
} else {
|
||||||
|
count = confirmations.toFormat(0) + `/${maxConfirmations}`;
|
||||||
|
}
|
||||||
|
const unit = value === 1 ? 'confirmation' : 'confirmations';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ styles.confirm }>
|
<div className={ styles.confirm }>
|
||||||
<LinearProgress
|
<LinearProgress
|
||||||
@ -106,9 +121,10 @@ class TxHash extends Component {
|
|||||||
max={ maxConfirmations }
|
max={ maxConfirmations }
|
||||||
value={ value }
|
value={ value }
|
||||||
color='white'
|
color='white'
|
||||||
mode='determinate' />
|
mode='determinate'
|
||||||
|
/>
|
||||||
<div className={ styles.progressinfo }>
|
<div className={ styles.progressinfo }>
|
||||||
{ txBlock } / { confirmations } confirmations
|
<abbr title={ `block #${blockNumber.toFormat(0)}` }>{ count } { unit }</abbr>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -37,6 +37,7 @@ import Modal, { Busy as BusyStep, Completed as CompletedStep } from './Modal';
|
|||||||
import muiTheme from './Theme';
|
import muiTheme from './Theme';
|
||||||
import Page from './Page';
|
import Page from './Page';
|
||||||
import ParityBackground from './ParityBackground';
|
import ParityBackground from './ParityBackground';
|
||||||
|
import ShortenedHash from './ShortenedHash';
|
||||||
import SignerIcon from './SignerIcon';
|
import SignerIcon from './SignerIcon';
|
||||||
import Tags from './Tags';
|
import Tags from './Tags';
|
||||||
import Tooltips, { Tooltip } from './Tooltips';
|
import Tooltips, { Tooltip } from './Tooltips';
|
||||||
@ -79,6 +80,7 @@ export {
|
|||||||
Page,
|
Page,
|
||||||
ParityBackground,
|
ParityBackground,
|
||||||
RadioButtons,
|
RadioButtons,
|
||||||
|
ShortenedHash,
|
||||||
SignerIcon,
|
SignerIcon,
|
||||||
Tags,
|
Tags,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
|
@ -19,6 +19,7 @@ import React, { Component, PropTypes } from 'react';
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
import { IdentityIcon, IdentityName, MethodDecoding } from '../../../../ui';
|
import { IdentityIcon, IdentityName, MethodDecoding } from '../../../../ui';
|
||||||
|
import ShortenedHash from '../../../../ui/ShortenedHash';
|
||||||
import { txLink, addressLink } from '../../../../3rdparty/etherscan/links';
|
import { txLink, addressLink } from '../../../../3rdparty/etherscan/links';
|
||||||
|
|
||||||
import styles from '../transactions.css';
|
import styles from '../transactions.css';
|
||||||
@ -95,7 +96,7 @@ export default class Transaction extends Component {
|
|||||||
href={ txLink(transaction.hash, isTest) }
|
href={ txLink(transaction.hash, isTest) }
|
||||||
target='_blank'
|
target='_blank'
|
||||||
>
|
>
|
||||||
{ this.formatHash(transaction.hash) }
|
<ShortenedHash data={ transaction.hash } />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
@ -150,14 +151,6 @@ export default class Transaction extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
formatHash (hash) {
|
|
||||||
if (!hash || hash.length <= 16) {
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
return `${hash.substr(2, 6)}...${hash.slice(-6)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
formatNumber (number) {
|
formatNumber (number) {
|
||||||
return new BigNumber(number).toFormat();
|
return new BigNumber(number).toFormat();
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import moment from 'moment';
|
|||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
|
|
||||||
import { IdentityIcon, IdentityName, Input, InputAddress } from '../../../../ui';
|
import { IdentityIcon, IdentityName, Input, InputAddress } from '../../../../ui';
|
||||||
|
import ShortenedHash from '../../../../ui/ShortenedHash';
|
||||||
import { txLink } from '../../../../3rdparty/etherscan/links';
|
import { txLink } from '../../../../3rdparty/etherscan/links';
|
||||||
|
|
||||||
import styles from '../../contract.css';
|
import styles from '../../contract.css';
|
||||||
@ -71,7 +72,7 @@ export default class Event extends Component {
|
|||||||
<div className={ styles.eventType }>
|
<div className={ styles.eventType }>
|
||||||
{ event.type }({ keys })
|
{ event.type }({ keys })
|
||||||
</div>
|
</div>
|
||||||
<a href={ url } target='_blank'>{ this.formatHash(event.transactionHash) }</a>
|
<a href={ url } target='_blank'><ShortenedHash data={ event.transactionHash } /></a>
|
||||||
</td>
|
</td>
|
||||||
<td className={ styles.eventDetails }>
|
<td className={ styles.eventDetails }>
|
||||||
<div className={ styles.eventParams }>
|
<div className={ styles.eventParams }>
|
||||||
@ -82,14 +83,6 @@ export default class Event extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
formatHash (hash) {
|
|
||||||
if (!hash || hash.length <= 16) {
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
return `${hash.substr(2, 6)}...${hash.slice(-6)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderAddressName (address, withName = true) {
|
renderAddressName (address, withName = true) {
|
||||||
return (
|
return (
|
||||||
<span className={ styles.eventAddress }>
|
<span className={ styles.eventAddress }>
|
||||||
|
Loading…
Reference in New Issue
Block a user