Display contract block creation (#4069)
* Add contract block creation to metadata * Display mined block for contract on Contracts view * Better use of Summary for Accounts * Add sorted by mined block for contracts * Proper Block Number sort // display in contract page * PR Grumble * Linting issues
This commit is contained in:
parent
71e6e24a1f
commit
cf0a20f08b
@ -75,6 +75,10 @@ export default class Contract {
|
|||||||
return this._functions;
|
return this._functions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get receipt () {
|
||||||
|
return this._receipt;
|
||||||
|
}
|
||||||
|
|
||||||
get instance () {
|
get instance () {
|
||||||
this._instance.address = this._address;
|
this._instance.address = this._address;
|
||||||
return this._instance;
|
return this._instance;
|
||||||
@ -139,6 +143,7 @@ export default class Contract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setState({ state: 'hasReceipt', receipt });
|
setState({ state: 'hasReceipt', receipt });
|
||||||
|
this._receipt = receipt;
|
||||||
this._address = receipt.contractAddress;
|
this._address = receipt.contractAddress;
|
||||||
return this._address;
|
return this._address;
|
||||||
});
|
});
|
||||||
|
@ -455,10 +455,15 @@ class DeployContract extends Component {
|
|||||||
|
|
||||||
this.setState({ step: 'DEPLOYMENT' });
|
this.setState({ step: 'DEPLOYMENT' });
|
||||||
|
|
||||||
api
|
const contract = api.newContract(abiParsed);
|
||||||
.newContract(abiParsed)
|
|
||||||
|
contract
|
||||||
.deploy(options, params, this.onDeploymentState)
|
.deploy(options, params, this.onDeploymentState)
|
||||||
.then((address) => {
|
.then((address) => {
|
||||||
|
const blockNumber = contract._receipt
|
||||||
|
? contract.receipt.blockNumber.toNumber()
|
||||||
|
: null;
|
||||||
|
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
api.parity.setAccountName(address, name),
|
api.parity.setAccountName(address, name),
|
||||||
api.parity.setAccountMeta(address, {
|
api.parity.setAccountMeta(address, {
|
||||||
@ -466,8 +471,9 @@ class DeployContract extends Component {
|
|||||||
contract: true,
|
contract: true,
|
||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
deleted: false,
|
deleted: false,
|
||||||
source,
|
blockNumber,
|
||||||
description
|
description,
|
||||||
|
source
|
||||||
})
|
})
|
||||||
])
|
])
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
.empty {
|
.empty {
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
margin: 0.75em 0.5em 0 0;
|
margin: 0 0.5em 0 0;
|
||||||
opacity: 0.25;
|
opacity: 0.25;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
/* You should have received a copy of the GNU General Public License
|
/* You should have received a copy of the GNU General Public License
|
||||||
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
.byline {
|
.byline, .description {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
line-height: 1.2em;
|
line-height: 1.2em;
|
||||||
@ -31,6 +31,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
font-size: 0.75em;
|
||||||
|
margin: 0.5em 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -22,13 +22,14 @@ import styles from './title.css';
|
|||||||
|
|
||||||
export default class Title extends Component {
|
export default class Title extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
byline: nodeOrStringProptype(),
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
title: nodeOrStringProptype(),
|
description: nodeOrStringProptype(),
|
||||||
byline: nodeOrStringProptype()
|
title: nodeOrStringProptype()
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { className, title, byline } = this.props;
|
const { byline, className, title } = this.props;
|
||||||
|
|
||||||
const byLine = typeof byline === 'string'
|
const byLine = typeof byline === 'string'
|
||||||
? (
|
? (
|
||||||
@ -46,6 +47,29 @@ export default class Title extends Component {
|
|||||||
<div className={ styles.byline }>
|
<div className={ styles.byline }>
|
||||||
{ byLine }
|
{ byLine }
|
||||||
</div>
|
</div>
|
||||||
|
{ this.renderDescription() }
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderDescription () {
|
||||||
|
const { description } = this.props;
|
||||||
|
|
||||||
|
if (!description) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const desc = typeof description === 'string'
|
||||||
|
? (
|
||||||
|
<span title={ description }>
|
||||||
|
{ description }
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
: description;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={ styles.description }>
|
||||||
|
{ desc }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ class List extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderAccounts () {
|
renderAccounts () {
|
||||||
const { accounts, balances, empty, link, handleAddSearchToken } = this.props;
|
const { accounts, balances, empty } = this.props;
|
||||||
|
|
||||||
if (empty) {
|
if (empty) {
|
||||||
return (
|
return (
|
||||||
@ -80,20 +80,29 @@ class List extends Component {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={ styles.item }
|
className={ styles.item }
|
||||||
key={ address }>
|
key={ address }
|
||||||
<Summary
|
>
|
||||||
link={ link }
|
{ this.renderSummary(account, balance, owners) }
|
||||||
account={ account }
|
|
||||||
balance={ balance }
|
|
||||||
owners={ owners }
|
|
||||||
handleAddSearchToken={ handleAddSearchToken }
|
|
||||||
showCertifications
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderSummary (account, balance, owners) {
|
||||||
|
const { handleAddSearchToken, link } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Summary
|
||||||
|
account={ account }
|
||||||
|
balance={ balance }
|
||||||
|
handleAddSearchToken={ handleAddSearchToken }
|
||||||
|
link={ link }
|
||||||
|
owners={ owners }
|
||||||
|
showCertifications
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
getAddresses () {
|
getAddresses () {
|
||||||
const filteredAddresses = this.getFilteredAddresses();
|
const filteredAddresses = this.getFilteredAddresses();
|
||||||
return this.sortAddresses(filteredAddresses);
|
return this.sortAddresses(filteredAddresses);
|
||||||
@ -122,7 +131,15 @@ class List extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
compareAccounts (accountA, accountB, key) {
|
compareAccounts (accountA, accountB, key, _reverse = null) {
|
||||||
|
if (key && key.split(':')[1] === '-1') {
|
||||||
|
return this.compareAccounts(accountA, accountB, key.split(':')[0], true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key === 'timestamp' && _reverse === null) {
|
||||||
|
return this.compareAccounts(accountA, accountB, key, true);
|
||||||
|
}
|
||||||
|
|
||||||
if (key === 'name') {
|
if (key === 'name') {
|
||||||
return accountA.name.localeCompare(accountB.name);
|
return accountA.name.localeCompare(accountB.name);
|
||||||
}
|
}
|
||||||
@ -177,7 +194,9 @@ class List extends Component {
|
|||||||
return tagsA.localeCompare(tagsB);
|
return tagsA.localeCompare(tagsB);
|
||||||
}
|
}
|
||||||
|
|
||||||
const reverse = key === 'timestamp' ? -1 : 1;
|
const reverse = _reverse
|
||||||
|
? -1
|
||||||
|
: 1;
|
||||||
|
|
||||||
const metaA = accountA.meta[key];
|
const metaA = accountA.meta[key];
|
||||||
const metaB = accountB.meta[key];
|
const metaB = accountB.meta[key];
|
||||||
|
@ -19,6 +19,7 @@ import React, { Component, PropTypes } from 'react';
|
|||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
import { isEqual } from 'lodash';
|
import { isEqual } from 'lodash';
|
||||||
import ReactTooltip from 'react-tooltip';
|
import ReactTooltip from 'react-tooltip';
|
||||||
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { Balance, Container, ContainerTitle, IdentityIcon, IdentityName, Tags, Input } from '~/ui';
|
import { Balance, Container, ContainerTitle, IdentityIcon, IdentityName, Tags, Input } from '~/ui';
|
||||||
import Certifications from '~/ui/Certifications';
|
import Certifications from '~/ui/Certifications';
|
||||||
@ -107,14 +108,22 @@ export default class Summary extends Component {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const description = this.getDescription(account.meta);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Tags tags={ tags } handleAddSearchToken={ handleAddSearchToken } />
|
<Tags tags={ tags } handleAddSearchToken={ handleAddSearchToken } />
|
||||||
<IdentityIcon
|
<div className={ styles.heading }>
|
||||||
address={ address } />
|
<IdentityIcon
|
||||||
<ContainerTitle
|
address={ address }
|
||||||
title={ this.renderLink() }
|
/>
|
||||||
byline={ addressComponent } />
|
<ContainerTitle
|
||||||
|
byline={ addressComponent }
|
||||||
|
className={ styles.main }
|
||||||
|
description={ description }
|
||||||
|
title={ this.renderLink() }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{ this.renderOwners() }
|
{ this.renderOwners() }
|
||||||
{ this.renderBalance() }
|
{ this.renderBalance() }
|
||||||
@ -123,6 +132,26 @@ export default class Summary extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getDescription (meta = {}) {
|
||||||
|
const { blockNumber } = meta;
|
||||||
|
|
||||||
|
if (!blockNumber) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const formattedBlockNumber = (new BigNumber(blockNumber)).toFormat();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormattedMessage
|
||||||
|
id='accounts.summary.minedBlock'
|
||||||
|
defaultMessage='Mined at block #{blockNumber}'
|
||||||
|
values={ {
|
||||||
|
blockNumber: formattedBlockNumber
|
||||||
|
} }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
renderOwners () {
|
renderOwners () {
|
||||||
const { owners } = this.props;
|
const { owners } = this.props;
|
||||||
const ownersValid = (owners || []).filter((owner) => owner.address && new BigNumber(owner.address).gt(0));
|
const ownersValid = (owners || []).filter((owner) => owner.address && new BigNumber(owner.address).gt(0));
|
||||||
|
@ -56,3 +56,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.heading {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
.main {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -45,6 +45,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.blockNumber {
|
||||||
|
color: rgba(255, 255, 255, 0.25);
|
||||||
|
margin-top: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
.origin {
|
.origin {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
padding-left: 32px;
|
padding-left: 32px;
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
import React, { Component, PropTypes } from 'react';
|
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 { FormattedMessage } from 'react-intl';
|
||||||
|
import BigNumber from 'bignumber.js';
|
||||||
|
|
||||||
import ActionDelete from 'material-ui/svg-icons/action/delete';
|
import ActionDelete from 'material-ui/svg-icons/action/delete';
|
||||||
import AvPlayArrow from 'material-ui/svg-icons/av/play-arrow';
|
import AvPlayArrow from 'material-ui/svg-icons/av/play-arrow';
|
||||||
import ContentCreate from 'material-ui/svg-icons/content/create';
|
import ContentCreate from 'material-ui/svg-icons/content/create';
|
||||||
@ -136,7 +139,9 @@ class Contract extends Component {
|
|||||||
account={ account }
|
account={ account }
|
||||||
balance={ balance }
|
balance={ balance }
|
||||||
isContract
|
isContract
|
||||||
/>
|
>
|
||||||
|
{ this.renderBlockNumber(account.meta) }
|
||||||
|
</Header>
|
||||||
|
|
||||||
<Queries
|
<Queries
|
||||||
accountsInfo={ accountsInfo }
|
accountsInfo={ accountsInfo }
|
||||||
@ -156,6 +161,28 @@ class Contract extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderBlockNumber (meta = {}) {
|
||||||
|
const { blockNumber } = meta;
|
||||||
|
|
||||||
|
if (!blockNumber) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const formattedBlockNumber = (new BigNumber(blockNumber)).toFormat();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={ styles.blockNumber }>
|
||||||
|
<FormattedMessage
|
||||||
|
id='contract.minedBlock'
|
||||||
|
defaultMessage='Mined at block #{blockNumber}'
|
||||||
|
values={ {
|
||||||
|
blockNumber: formattedBlockNumber
|
||||||
|
} }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
renderDetails (contract) {
|
renderDetails (contract) {
|
||||||
const { showDetailsDialog } = this.state;
|
const { showDetailsDialog } = this.state;
|
||||||
|
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
// Copyright 2015, 2016 Parity Technologies (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 './summary';
|
|
@ -1,52 +0,0 @@
|
|||||||
// Copyright 2015, 2016 Parity Technologies (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 { Link } from 'react-router';
|
|
||||||
|
|
||||||
import { Container, ContainerTitle, IdentityIcon, IdentityName } from '~/ui';
|
|
||||||
|
|
||||||
export default class Summary extends Component {
|
|
||||||
static contextTypes = {
|
|
||||||
api: React.PropTypes.object.isRequired
|
|
||||||
}
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
contract: PropTypes.object.isRequired,
|
|
||||||
children: PropTypes.node
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const contract = this.props.contract;
|
|
||||||
|
|
||||||
if (!contract) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const viewLink = `/app/${contract.address}`;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Container>
|
|
||||||
<IdentityIcon
|
|
||||||
address={ contract.address } />
|
|
||||||
<ContainerTitle
|
|
||||||
title={ <Link to={ viewLink }>{ <IdentityName address={ contract.address } unknown /> }</Link> }
|
|
||||||
byline={ contract.address } />
|
|
||||||
{ this.props.children }
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -45,7 +45,7 @@ class Contracts extends Component {
|
|||||||
state = {
|
state = {
|
||||||
addContract: false,
|
addContract: false,
|
||||||
deployContract: false,
|
deployContract: false,
|
||||||
sortOrder: 'timestamp',
|
sortOrder: 'blockNumber',
|
||||||
searchValues: [],
|
searchValues: [],
|
||||||
searchTokens: []
|
searchTokens: []
|
||||||
}
|
}
|
||||||
@ -92,7 +92,8 @@ class Contracts extends Component {
|
|||||||
empty={ !hasContracts }
|
empty={ !hasContracts }
|
||||||
order={ sortOrder }
|
order={ sortOrder }
|
||||||
orderFallback='name'
|
orderFallback='name'
|
||||||
handleAddSearchToken={ this.onAddSearchToken } />
|
handleAddSearchToken={ this.onAddSearchToken }
|
||||||
|
/>
|
||||||
</Page>
|
</Page>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -109,7 +110,8 @@ class Contracts extends Component {
|
|||||||
id='sortContracts'
|
id='sortContracts'
|
||||||
order={ this.state.sortOrder }
|
order={ this.state.sortOrder }
|
||||||
metas={ [
|
metas={ [
|
||||||
{ key: 'timestamp', label: 'date' }
|
{ key: 'timestamp', label: 'date' },
|
||||||
|
{ key: 'blockNumber:-1', label: 'mined block' }
|
||||||
] }
|
] }
|
||||||
showDefault={ false }
|
showDefault={ false }
|
||||||
onChange={ onChange } />
|
onChange={ onChange } />
|
||||||
|
Loading…
Reference in New Issue
Block a user