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