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:
Nicolas Gotchac 2017-01-09 09:38:27 +01:00 committed by Jaco Greeff
parent 71e6e24a1f
commit cf0a20f08b
13 changed files with 161 additions and 99 deletions

View File

@ -75,6 +75,10 @@ export default class Contract {
return this._functions;
}
get receipt () {
return this._receipt;
}
get instance () {
this._instance.address = this._address;
return this._instance;
@ -139,6 +143,7 @@ export default class Contract {
}
setState({ state: 'hasReceipt', receipt });
this._receipt = receipt;
this._address = receipt.contractAddress;
return this._address;
});

View File

@ -455,10 +455,15 @@ class DeployContract extends Component {
this.setState({ step: 'DEPLOYMENT' });
api
.newContract(abiParsed)
const contract = api.newContract(abiParsed);
contract
.deploy(options, params, this.onDeploymentState)
.then((address) => {
const blockNumber = contract._receipt
? contract.receipt.blockNumber.toNumber()
: null;
return Promise.all([
api.parity.setAccountName(address, name),
api.parity.setAccountMeta(address, {
@ -466,8 +471,9 @@ class DeployContract extends Component {
contract: true,
timestamp: Date.now(),
deleted: false,
source,
description
blockNumber,
description,
source
})
])
.then(() => {

View File

@ -23,7 +23,7 @@
.empty {
line-height: 24px;
margin: 0.75em 0.5em 0 0;
margin: 0 0.5em 0 0;
opacity: 0.25;
}

View File

@ -14,7 +14,7 @@
/* You should have received a copy of the GNU General Public License
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
*/
.byline {
.byline, .description {
overflow: hidden;
position: relative;
line-height: 1.2em;
@ -31,6 +31,11 @@
}
}
.description {
font-size: 0.75em;
margin: 0.5em 0 0;
}
.title {
text-transform: uppercase;
margin: 0;

View File

@ -22,13 +22,14 @@ import styles from './title.css';
export default class Title extends Component {
static propTypes = {
byline: nodeOrStringProptype(),
className: PropTypes.string,
title: nodeOrStringProptype(),
byline: nodeOrStringProptype()
description: nodeOrStringProptype(),
title: nodeOrStringProptype()
}
render () {
const { className, title, byline } = this.props;
const { byline, className, title } = this.props;
const byLine = typeof byline === 'string'
? (
@ -46,6 +47,29 @@ export default class Title extends Component {
<div className={ styles.byline }>
{ byLine }
</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>
);
}

View File

@ -57,7 +57,7 @@ class List extends Component {
}
renderAccounts () {
const { accounts, balances, empty, link, handleAddSearchToken } = this.props;
const { accounts, balances, empty } = this.props;
if (empty) {
return (
@ -80,20 +80,29 @@ class List extends Component {
return (
<div
className={ styles.item }
key={ address }>
<Summary
link={ link }
account={ account }
balance={ balance }
owners={ owners }
handleAddSearchToken={ handleAddSearchToken }
showCertifications
/>
key={ address }
>
{ this.renderSummary(account, balance, owners) }
</div>
);
});
}
renderSummary (account, balance, owners) {
const { handleAddSearchToken, link } = this.props;
return (
<Summary
account={ account }
balance={ balance }
handleAddSearchToken={ handleAddSearchToken }
link={ link }
owners={ owners }
showCertifications
/>
);
}
getAddresses () {
const filteredAddresses = this.getFilteredAddresses();
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') {
return accountA.name.localeCompare(accountB.name);
}
@ -177,7 +194,9 @@ class List extends Component {
return tagsA.localeCompare(tagsB);
}
const reverse = key === 'timestamp' ? -1 : 1;
const reverse = _reverse
? -1
: 1;
const metaA = accountA.meta[key];
const metaB = accountB.meta[key];

View File

@ -19,6 +19,7 @@ import React, { Component, PropTypes } from 'react';
import { Link } from 'react-router';
import { isEqual } from 'lodash';
import ReactTooltip from 'react-tooltip';
import { FormattedMessage } from 'react-intl';
import { Balance, Container, ContainerTitle, IdentityIcon, IdentityName, Tags, Input } from '~/ui';
import Certifications from '~/ui/Certifications';
@ -107,14 +108,22 @@ export default class Summary extends Component {
/>
);
const description = this.getDescription(account.meta);
return (
<Container>
<Tags tags={ tags } handleAddSearchToken={ handleAddSearchToken } />
<IdentityIcon
address={ address } />
<ContainerTitle
title={ this.renderLink() }
byline={ addressComponent } />
<div className={ styles.heading }>
<IdentityIcon
address={ address }
/>
<ContainerTitle
byline={ addressComponent }
className={ styles.main }
description={ description }
title={ this.renderLink() }
/>
</div>
{ this.renderOwners() }
{ 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 () {
const { owners } = this.props;
const ownersValid = (owners || []).filter((owner) => owner.address && new BigNumber(owner.address).gt(0));

View File

@ -56,3 +56,12 @@
}
}
}
.heading {
display: flex;
flex-direction: row;
.main {
flex: 1;
}
}

View File

@ -45,6 +45,11 @@
}
}
.blockNumber {
color: rgba(255, 255, 255, 0.25);
margin-top: 1.5em;
}
.origin {
text-align: left;
padding-left: 32px;

View File

@ -17,6 +17,9 @@
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-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 AvPlayArrow from 'material-ui/svg-icons/av/play-arrow';
import ContentCreate from 'material-ui/svg-icons/content/create';
@ -136,7 +139,9 @@ class Contract extends Component {
account={ account }
balance={ balance }
isContract
/>
>
{ this.renderBlockNumber(account.meta) }
</Header>
<Queries
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) {
const { showDetailsDialog } = this.state;

View File

@ -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';

View File

@ -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>
);
}
}

View File

@ -45,7 +45,7 @@ class Contracts extends Component {
state = {
addContract: false,
deployContract: false,
sortOrder: 'timestamp',
sortOrder: 'blockNumber',
searchValues: [],
searchTokens: []
}
@ -92,7 +92,8 @@ class Contracts extends Component {
empty={ !hasContracts }
order={ sortOrder }
orderFallback='name'
handleAddSearchToken={ this.onAddSearchToken } />
handleAddSearchToken={ this.onAddSearchToken }
/>
</Page>
</div>
);
@ -109,7 +110,8 @@ class Contracts extends Component {
id='sortContracts'
order={ this.state.sortOrder }
metas={ [
{ key: 'timestamp', label: 'date' }
{ key: 'timestamp', label: 'date' },
{ key: 'blockNumber:-1', label: 'mined block' }
] }
showDefault={ false }
onChange={ onChange } />