aboutsummaryrefslogtreecommitdiffstats
path: root/ui/app/components
diff options
context:
space:
mode:
Diffstat (limited to 'ui/app/components')
-rw-r--r--ui/app/components/account-dropdowns.js19
-rw-r--r--ui/app/components/balance-component.js92
-rw-r--r--ui/app/components/buy-options.js74
-rw-r--r--ui/app/components/dropdown.js2
-rw-r--r--ui/app/components/ens-input.js7
-rw-r--r--ui/app/components/modal.js96
-rw-r--r--ui/app/components/network.js2
-rw-r--r--ui/app/components/pending-tx.js634
-rw-r--r--ui/app/components/tx-view.js231
-rw-r--r--ui/app/components/wallet-content-display.js56
-rw-r--r--ui/app/components/wallet-view.js133
11 files changed, 1024 insertions, 322 deletions
diff --git a/ui/app/components/account-dropdowns.js b/ui/app/components/account-dropdowns.js
index b23600e9b..3129e0226 100644
--- a/ui/app/components/account-dropdowns.js
+++ b/ui/app/components/account-dropdowns.js
@@ -218,16 +218,16 @@ class AccountDropdowns extends Component {
},
[
enableAccountsSelector && h(
- // 'i.fa.fa-angle-down',
- 'div.cursor-pointer.color-orange.accounts-selector',
+ 'i.fa.fa-angle-down',
+ // 'div.cursor-pointer.color-orange.accounts-selector',
{
style: {
- // fontSize: '1.8em',
- background: 'url(images/switch_acc.svg) white center center no-repeat',
- height: '25px',
- width: '25px',
- transform: 'scale(0.75)',
- marginRight: '3px',
+ // fontSize: '135%',
+ // background: 'url(images/switch_acc.svg) white center center no-repeat',
+ // height: '25px',
+ // width: '25px',
+ // transform: 'scale(0.75)',
+ // marginRight: '3px',
},
onClick: (event) => {
event.stopPropagation()
@@ -243,8 +243,7 @@ class AccountDropdowns extends Component {
'i.fa.fa-ellipsis-h',
{
style: {
- marginRight: '0.5em',
- fontSize: '1.8em',
+ fontSize: '135%',
},
onClick: (event) => {
event.stopPropagation()
diff --git a/ui/app/components/balance-component.js b/ui/app/components/balance-component.js
new file mode 100644
index 000000000..47da24c74
--- /dev/null
+++ b/ui/app/components/balance-component.js
@@ -0,0 +1,92 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+
+const { formatBalance, generateBalanceObject } = require('../util')
+
+module.exports = BalanceComponent
+
+inherits(BalanceComponent, Component)
+function BalanceComponent () {
+ Component.call(this)
+}
+
+BalanceComponent.prototype.render = function () {
+ const props = this.props
+ const { balanceValue } = props
+ const needsParse = 'needsParse' in props ? props.needsParse : true
+ const formattedBalance = balanceValue ? formatBalance(balanceValue, 6, needsParse) : '...'
+
+ return h('div.balance-container', {}, [
+ // laptop: 50px 50px
+ // mobile: 100px 100px
+
+ // TODO: balance icon needs to be passed in
+ h('img.balance-icon', {
+ src: '../images/eth_logo.svg',
+ style: {},
+ }),
+
+ this.renderBalance(formattedBalance),
+ ])
+}
+
+BalanceComponent.prototype.renderBalance = function (formattedBalance) {
+ const props = this.props
+ const { shorten } = props
+ const showFiat = 'showFiat' in props ? props.showFiat : true
+
+ if (formattedBalance === 'None' || formattedBalance === '...') {
+ return h('div.flex-column.balance-display', {}, [
+ h('div.token-amount', {
+ style: {},
+ }, formattedBalance),
+ ])
+ }
+
+ // laptop: 5vw?
+ // phone: 50vw?
+ return h('div.flex-column.balance-display', {}, [
+ h('div.token-amount', {
+ style: {},
+ }, this.getTokenBalance(formattedBalance, shorten)),
+
+ showFiat ? this.renderFiatValue(formattedBalance) : null,
+ ])
+}
+
+BalanceComponent.prototype.renderFiatValue = function (formattedBalance) {
+
+ const props = this.props
+ const { conversionRate, currentCurrency } = props
+
+ const fiatDisplayNumber = this.getFiatDisplayNumber(formattedBalance, conversionRate)
+
+ return this.renderFiatAmount(fiatDisplayNumber, currentCurrency)
+}
+
+BalanceComponent.prototype.renderFiatAmount = function (fiatDisplayNumber, fiatSuffix) {
+ if (fiatDisplayNumber === 'N/A') return null
+
+ return h('div.fiat-amount', {
+ style: {},
+ }, `${fiatDisplayNumber} ${fiatSuffix}`)
+}
+
+BalanceComponent.prototype.getTokenBalance = function (formattedBalance, shorten) {
+ const balanceObj = generateBalanceObject(formattedBalance, shorten ? 1 : 3)
+
+ const balanceValue = shorten ? balanceObj.shortBalance : balanceObj.balance
+ const label = balanceObj.label
+
+ return `${balanceValue} ${label}`
+}
+
+BalanceComponent.prototype.getFiatDisplayNumber = function (formattedBalance, conversionRate) {
+ if (formattedBalance === 'None') return formattedBalance
+ if (conversionRate === 0) return 'N/A'
+
+ const splitBalance = formattedBalance.split(' ')
+
+ return (Number(splitBalance[0]) * conversionRate).toFixed(2)
+}
diff --git a/ui/app/components/buy-options.js b/ui/app/components/buy-options.js
new file mode 100644
index 000000000..d36328efd
--- /dev/null
+++ b/ui/app/components/buy-options.js
@@ -0,0 +1,74 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const connect = require('react-redux').connect
+const actions = require('../actions')
+
+function mapStateToProps (state) {
+ return {
+ network: state.metamask.network,
+ address: state.metamask.selectedAddress,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ toCoinbase: (address) => {
+ dispatch(actions.buyEth({ network: '1', address, amount: 0 }))
+ },
+ }
+}
+
+inherits(BuyOptions, Component)
+function BuyOptions () {
+ Component.call(this)
+}
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(BuyOptions)
+
+// BuyOptions is currently meant to be rendered inside <Modal />
+// It is the only component in this codebase that does so
+// It utilizes modal styles
+BuyOptions.prototype.render = function () {
+ return h('div', {}, [
+ h('div.modal-content.transfers-subview', {
+ }, [
+ h('div.modal-content-title-wrapper.flex-column.flex-center', {
+ style: {},
+ }, [
+ h('div.modal-content-title', {
+ style: {},
+ }, 'Transfers'),
+ h('div', {}, 'How would you like to buy Ether?'),
+ ]),
+
+ h('div.modal-content-options.flex-column.flex-center', {}, [
+
+ h('div.modal-content-option', {
+ onClick: () => {
+ const { toCoinbase, address } = this.props
+ toCoinbase(address)
+ },
+ }, [
+ h('div.modal-content-option-title', {}, 'Coinbase'),
+ h('div.modal-content-option-subtitle', {}, 'Buy with Fiat'),
+ ]),
+
+ h('div.modal-content-option', {}, [
+ h('div.modal-content-option-title', {}, 'Shapeshift'),
+ h('div.modal-content-option-subtitle', {}, 'Trade any digital asset for any other'),
+ ]),
+
+ h('div.modal-content-option', {}, [
+ h('div.modal-content-option-title', {}, 'Direct Deposit'),
+ h('div.modal-content-option-subtitle', {}, 'Deposit from another account'),
+ ]),
+
+ ]),
+
+ h('div.modal-content-footer', {
+ style: {},
+ }, 'Cancel'),
+ ])
+ ])
+}
diff --git a/ui/app/components/dropdown.js b/ui/app/components/dropdown.js
index 34c7149ee..d9593efe2 100644
--- a/ui/app/components/dropdown.js
+++ b/ui/app/components/dropdown.js
@@ -22,7 +22,7 @@ class Dropdown extends Component {
{
useCssTransition,
isOpen,
- zIndex: 11,
+ zIndex: 30,
onClickOutside,
style,
innerStyle: innerStyleDefaults,
diff --git a/ui/app/components/ens-input.js b/ui/app/components/ens-input.js
index 3a33ebf74..93c07599d 100644
--- a/ui/app/components/ens-input.js
+++ b/ui/app/components/ens-input.js
@@ -44,6 +44,13 @@ EnsInput.prototype.render = function () {
return h('div', {
style: { width: '100%' },
}, [
+ h('span', {
+ style: {
+ textAlign: 'left',
+ }
+ }, [
+ 'To:'
+ ]),
h('input.large-input', opts),
// The address book functionality.
h('datalist#addresses',
diff --git a/ui/app/components/modal.js b/ui/app/components/modal.js
new file mode 100644
index 000000000..89de1cedb
--- /dev/null
+++ b/ui/app/components/modal.js
@@ -0,0 +1,96 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const connect = require('react-redux').connect
+const FadeModal = require('boron').FadeModal
+const actions = require('../actions')
+const isMobileView = require('../../lib/is-mobile-view')
+
+function mapStateToProps (state) {
+ return {
+ active: state.appState.modalOpen
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ hideModal: () => {
+ dispatch(actions.hideModal())
+ },
+ }
+}
+
+inherits(Modal, Component)
+function Modal () {
+ Component.call(this)
+}
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(Modal)
+
+const mobileModalStyles = {
+ width: '95%',
+ boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px',
+}
+
+const laptopModalStyles = {
+ width: '66%',
+ top: '30%',
+ boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px',
+}
+
+const backdropStyles = {
+ backgroundColor: 'rgba(245, 245, 245, 0.85)',
+}
+
+Modal.prototype.render = function () {
+
+ return h(FadeModal,
+ {
+ className: 'modal',
+ keyboard: false,
+ onHide: () => {this.onHide()},
+ ref: (ref) => {
+ this.modalRef = ref
+ },
+ modalStyle: isMobileView() ? mobileModalStyles : laptopModalStyles,
+ backdropStyle: backdropStyles,
+ },
+ this.props.children,
+ )
+}
+
+Modal.prototype.componentWillReceiveProps = function(nextProps) {
+ if (nextProps.active) {
+ this.show()
+ } else if (this.props.active) {
+ this.hide()
+ }
+}
+
+Modal.prototype.onHide = function() {
+ if (this.props.onHideCallback) {
+ this.props.onHideCallback()
+ }
+ this.props.hideModal()
+}
+
+Modal.prototype.hide = function() {
+ this.modalRef.hide()
+}
+
+Modal.prototype.show = function() {
+ this.modalRef.show()
+}
+
+// TODO: specify default props and proptypes
+// Modal.defaultProps = {}
+
+// const elementType = require('react-prop-types/lib/elementType')
+// const PropTypes from 'prop-types'
+
+// Modal.propTypes = {
+// active: PropTypes.bool,
+// hideModal: PropTypes.func.isRequired,
+// component: elementType,
+// onHideCallback: PropTypes.func,
+// }
diff --git a/ui/app/components/network.js b/ui/app/components/network.js
index 698a0bbb9..ba1d0ea11 100644
--- a/ui/app/components/network.js
+++ b/ui/app/components/network.js
@@ -60,7 +60,7 @@ Network.prototype.render = function () {
}
return (
- h('#network_component.pointer', {
+ h('.network-component.pointer', {
title: hoverText,
onClick: (event) => this.props.onClick(event),
}, [
diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js
index 5324ccd64..1c47440f2 100644
--- a/ui/app/components/pending-tx.js
+++ b/ui/app/components/pending-tx.js
@@ -20,6 +20,34 @@ const GWEI_FACTOR = new BN(1e9)
const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR)
const MIN_GAS_LIMIT_BN = new BN(21000)
+
+// Faked, for Icon
+const Identicon = require('./identicon')
+const ARAGON = '960b236A07cf122663c4303350609A66A7B288C0'
+
+// Next: create separate react components
+// roughly 5 components:
+// heroIcon
+// numericDisplay (contains symbol + currency)
+// divider
+// contentBox
+// actionButtons
+const sectionDivider = h('div', {
+ style: {
+ height:'1px',
+ background:'#E7E7E7',
+ },
+})
+
+const contentDivider = h('div', {
+ style: {
+ marginLeft: '16px',
+ marginRight: '16px',
+ height:'1px',
+ background:'#E7E7E7',
+ },
+})
+
module.exports = PendingTx
inherits(PendingTx, Component)
function PendingTx () {
@@ -70,344 +98,342 @@ PendingTx.prototype.render = function () {
this.inputs = []
return (
-
- h('div', {
- key: txMeta.id,
+ h('div.flex-column.flex-grow', {
+ style: {
+ // overflow: 'scroll',
+ minWidth: '355px', // TODO: maxWidth TBD, use home.html
+ },
}, [
- h('form#pending-tx-form', {
- onSubmit: this.onSubmit.bind(this),
-
+ // Main Send token Card
+ h('div.send-screen.flex-column.flex-grow', {
+ style: {
+ marginLeft: '3.5%',
+ marginRight: '3.5%',
+ background: '#FFFFFF', // $background-white
+ boxShadow: '0 2px 4px 0 rgba(0,0,0,0.08)',
+ }
}, [
+ h('section.flex-center.flex-row', {
+ style: {
+ zIndex: 15, // $token-icon-z-index
+ marginTop: '-35px',
+ }
+ }, [
+ h(Identicon, {
+ address: ARAGON,
+ diameter: 76,
+ }),
+ ]),
- // tx info
- h('div', [
+ //
+ // Required Fields
+ //
- h('.flex-row.flex-center', {
- style: {
- maxWidth: '100%',
- },
- }, [
+ h('h3.flex-center', {
+ style: {
+ marginTop: '-18px',
+ fontSize: '16px',
+ },
+ }, [
+ 'Confirm Transaction',
+ ]),
- h(MiniAccountPanel, {
- imageSeed: address,
- picOrder: 'right',
- }, [
- h('span.font-small', {
- style: {
- fontFamily: 'Montserrat Bold, Montserrat, sans-serif',
- },
- }, identity.name),
-
- h(Copyable, {
- value: ethUtil.toChecksumAddress(address),
- }, [
- h('span.font-small', {
- style: {
- fontFamily: 'Montserrat Light, Montserrat, sans-serif',
- },
- }, addressSummary(address, 6, 4, false)),
- ]),
-
- h('span.font-small', {
- style: {
- fontFamily: 'Montserrat Light, Montserrat, sans-serif',
- },
- }, [
- h(EthBalance, {
- value: balance,
- conversionRate,
- currentCurrency,
- inline: true,
- labelColor: '#F7861C',
- }),
- ]),
- ]),
+ h('h3.flex-center', {
+ style: {
+ textAlign: 'center',
+ fontSize: '12px',
+ },
+ }, [
+ 'You\'re sending to Recipient ...5924',
+ ]),
- forwardCarrat(),
+ h('h3.flex-center', {
+ style: {
+ textAlign: 'center',
+ fontSize: '36px',
+ marginTop: '8px',
+ },
+ }, [
+ '0.24',
+ ]),
- this.miniAccountPanelForRecipient(),
- ]),
+ h('h3.flex-center', {
+ style: {
+ textAlign: 'center',
+ fontSize: '12px',
+ marginTop: '4px',
+ },
+ }, [
+ 'ANT',
+ ]),
- h('style', `
- .table-box {
- margin: 7px 0px 0px 0px;
- width: 100%;
- }
- .table-box .row {
- margin: 0px;
- background: rgb(236,236,236);
- display: flex;
- justify-content: space-between;
- font-family: Montserrat Light, sans-serif;
- font-size: 13px;
- padding: 5px 25px;
- }
- .table-box .row .value {
- font-family: Montserrat Regular;
- }
- `),
+ // error message
+ props.error && h('span.error.flex-center', props.error),
- h('.table-box', [
+ sectionDivider,
- // Ether Value
- // Currently not customizable, but easily modified
- // in the way that gas and gasLimit currently are.
- h('.row', [
- h('.cell.label', 'Amount'),
- h(EthBalance, { value: txParams.value, currentCurrency, conversionRate }),
- ]),
+ h('section.flex-row.flex-center', {
+ }, [
+ h('div', {
+ style: {
+ width: '50%',
+ }
+ }, [
+ h('span', {
+ style: {
+ textAlign: 'left',
+ fontSize: '12px',
+ }
+ }, [
+ 'From'
+ ])
+ ]),
- // Gas Limit (customizable)
- h('.cell.row', [
- h('.cell.label', 'Gas Limit'),
- h('.cell.value', {
- }, [
- h(BNInput, {
- name: 'Gas Limit',
- value: gasBn,
- precision: 0,
- scale: 0,
- // The hard lower limit for gas.
- min: MIN_GAS_LIMIT_BN.toString(10),
- max: safeGasLimit,
- suffix: 'UNITS',
- style: {
- position: 'relative',
- top: '5px',
- },
- onChange: this.gasLimitChanged.bind(this),
-
- ref: (hexInput) => { this.inputs.push(hexInput) },
- }),
- ]),
- ]),
+ h('div', {
+ style: {
+ width: '50%',
+ }
+ },[
+ h('div', {
+ style: {
+ textAlign: 'left',
+ fontSize: '10px',
+ marginBottom: '-10px',
+ },
+ }, 'Aragon Token'),
- // Gas Price (customizable)
- h('.cell.row', [
- h('.cell.label', 'Gas Price'),
- h('.cell.value', {
- }, [
- h(BNInput, {
- name: 'Gas Price',
- value: gasPriceBn,
- precision: 9,
- scale: 9,
- suffix: 'GWEI',
- min: MIN_GAS_PRICE_GWEI_BN.toString(10),
- style: {
- position: 'relative',
- top: '5px',
- },
- onChange: this.gasPriceChanged.bind(this),
- ref: (hexInput) => { this.inputs.push(hexInput) },
- }),
- ]),
- ]),
+ h('div', {
+ style: {
+ textAlign: 'left',
+ fontSize: '8px',
+ },
+ }, 'Your Balance 2.34 ANT')
+ ])
+ ]),
- // Max Transaction Fee (calculated)
- h('.cell.row', [
- h('.cell.label', 'Max Transaction Fee'),
- h(EthBalance, { value: txFeeBn.toString(16), currentCurrency, conversionRate }),
- ]),
+ contentDivider,
- h('.cell.row', {
+ h('section.flex-row.flex-center', {
+ }, [
+ h('div', {
+ style: {
+ width: '50%',
+ }
+ }, [
+ h('span', {
style: {
- fontFamily: 'Montserrat Regular',
- background: 'white',
- padding: '10px 25px',
- },
+ textAlign: 'left',
+ fontSize: '12px',
+ }
}, [
- h('.cell.label', 'Max Total'),
- h('.cell.value', {
- style: {
- display: 'flex',
- alignItems: 'center',
- },
- }, [
- h(EthBalance, {
- value: maxCost.toString(16),
- currentCurrency,
- conversionRate,
- inline: true,
- labelColor: 'black',
- fontSize: '16px',
- }),
- ]),
- ]),
+ 'To'
+ ])
+ ]),
- // Data size row:
- h('.cell.row', {
+ h('div', {
+ style: {
+ width: '50%',
+ }
+ },[
+ h('div', {
style: {
- background: '#f7f7f7',
- paddingBottom: '0px',
+ textAlign: 'left',
+ fontSize: '10px',
+ marginBottom: '-10px',
},
- }, [
- h('.cell.label'),
- h('.cell.value', {
- style: {
- fontFamily: 'Montserrat Light',
- fontSize: '11px',
- },
- }, `Data included: ${dataLength} bytes`),
- ]),
- ]), // End of Table
+ }, 'Ethereum Address'),
+ h('div', {
+ style: {
+ textAlign: 'left',
+ fontSize: '8px',
+ },
+ }, '...5924')
+ ])
]),
- h('style', `
- .conf-buttons button {
- margin-left: 10px;
- text-transform: uppercase;
- }
- `),
+ contentDivider,
- txMeta.simulationFails ?
- h('.error', {
- style: {
- marginLeft: 50,
- fontSize: '0.9em',
- },
- }, 'Transaction Error. Exception thrown in contract code.')
- : null,
-
- !isValidAddress ?
- h('.error', {
+ h('section.flex-row.flex-center', {
+ }, [
+ h('div', {
style: {
- marginLeft: 50,
- fontSize: '0.9em',
- },
- }, 'Recipient address is invalid. Sending this transaction will result in a loss of ETH.')
- : null,
-
- insufficientBalance ?
- h('span.error', {
+ width: '50%',
+ }
+ }, [
+ h('span', {
+ style: {
+ textAlign: 'left',
+ fontSize: '12px',
+ }
+ }, [
+ 'Gas Fee'
+ ])
+ ]),
+
+ h('div', {
style: {
- marginLeft: 50,
- fontSize: '0.9em',
- },
- }, 'Insufficient balance for transaction')
- : null,
-
- // send + cancel
- h('.flex-row.flex-space-around.conf-buttons', {
+ width: '50%',
+ }
+ },[
+ h('div', {
+ style: {
+ textAlign: 'left',
+ fontSize: '10px',
+ marginBottom: '-10px',
+ },
+ }, '$0.04 USD'),
+
+ h('div', {
+ style: {
+ textAlign: 'left',
+ fontSize: '8px',
+ },
+ }, '0.001575 ETH')
+ ])
+ ]),
+
+ contentDivider,
+
+ h('section.flex-row.flex-center', {
style: {
- display: 'flex',
- justifyContent: 'flex-end',
- margin: '14px 25px',
- },
+ backgroundColor: '#F6F6F6', // $wild-sand
+ borderRadius: '8px',
+ marginLeft: '10px',
+ marginRight: '10px',
+ paddingLeft: '6px',
+ paddingRight: '6px',
+ marginBottom: '10px',
+ }
}, [
+ h('div', {
+ style: {
+ width: '50%',
+ }
+ }, [
+ h('div', {
+ style: {
+ textAlign: 'left',
+ fontSize: '12px',
+ marginBottom: '-10px',
+ }
+ }, [
+ 'Total Tokens'
+ ]),
+ h('div', {
+ style: {
+ textAlign: 'left',
+ fontSize: '8px',
+ }
+ }, [
+ 'Total Gas'
+ ])
- insufficientBalance ?
- h('button.btn-green', {
- onClick: props.buyEth,
- }, 'Buy Ether')
- : null,
-
- h('button', {
- onClick: (event) => {
- this.resetGasFields()
- event.preventDefault()
- },
- }, 'Reset'),
-
- // Accept Button
- h('input.confirm.btn-green', {
- type: 'submit',
- value: 'SUBMIT',
- style: { marginLeft: '10px' },
- disabled: insufficientBalance || !this.state.valid || !isValidAddress || this.state.submitting,
- }),
+ ]),
- h('button.cancel.btn-red', {
- onClick: props.cancelTransaction,
- }, 'Reject'),
- ]),
- ]),
- ])
- )
-}
+ h('div', {
+ style: {
+ width: '50%',
+ }
+ },[
+ h('div', {
+ style: {
+ textAlign: 'left',
+ fontSize: '10px',
+ marginBottom: '-10px',
+ },
+ }, '0.24 ANT (127.00 USD)'),
-PendingTx.prototype.miniAccountPanelForRecipient = function () {
- const props = this.props
- const txData = props.txData
- const txParams = txData.txParams || {}
- const isContractDeploy = !('to' in txParams)
-
- // If it's not a contract deploy, send to the account
- if (!isContractDeploy) {
- return h(MiniAccountPanel, {
- imageSeed: txParams.to,
- picOrder: 'left',
- }, [
+ h('div', {
+ style: {
+ textAlign: 'left',
+ fontSize: '8px',
+ },
+ }, '0.249 ETH')
+ ])
+ ]),
- h('span.font-small', {
- style: {
- fontFamily: 'Montserrat Bold, Montserrat, sans-serif',
- },
- }, nameForAddress(txParams.to, props.identities)),
+ ]), // end of container
- h(Copyable, {
- value: ethUtil.toChecksumAddress(txParams.to),
+ h('form#pending-tx-form.flex-column.flex-center', {
+ onSubmit: this.onSubmit.bind(this),
}, [
- h('span.font-small', {
+ // Reset Button
+ // h('button', {
+ // onClick: (event) => {
+ // this.resetGasFields()
+ // event.preventDefault()
+ // },
+ // }, 'Reset'),
+
+ // Accept Button
+ h('input.confirm.btn-green', {
+ type: 'submit',
+ value: 'CONFIRM',
style: {
- fontFamily: 'Montserrat Light, Montserrat, sans-serif',
+ marginTop: '8px',
+ width: '8em',
+ color: '#FFFFFF',
+ borderRadius: '2px',
+ fontSize: '12px',
+ lineHeight: '20px',
+ textAlign: 'center',
+ borderStyle: 'none',
},
- }, addressSummary(txParams.to, 6, 4, false)),
- ]),
-
- ])
- } else {
- return h(MiniAccountPanel, {
- picOrder: 'left',
- }, [
+ disabled: insufficientBalance || !this.state.valid || !isValidAddress || this.state.submitting,
+ }),
- h('span.font-small', {
- style: {
- fontFamily: 'Montserrat Bold, Montserrat, sans-serif',
- },
- }, 'New Contract'),
-
- ])
- }
-}
-
-PendingTx.prototype.gasPriceChanged = function (newBN, valid) {
- log.info(`Gas price changed to: ${newBN.toString(10)}`)
- const txMeta = this.gatherTxMeta()
- txMeta.txParams.gasPrice = '0x' + newBN.toString('hex')
- this.setState({
- txData: clone(txMeta),
- valid,
- })
-}
-
-PendingTx.prototype.gasLimitChanged = function (newBN, valid) {
- log.info(`Gas limit changed to ${newBN.toString(10)}`)
- const txMeta = this.gatherTxMeta()
- txMeta.txParams.gas = '0x' + newBN.toString('hex')
- this.setState({
- txData: clone(txMeta),
- valid,
- })
+ // Cancel Button
+ h('button.cancel.btn-light', {
+ style: {
+ background: '#F7F7F7', // $alabaster
+ border: 'none',
+ opacity: 1,
+ width: '8em',
+ },
+ onClick: props.cancelTransaction,
+ }, 'CANCEL'),
+ ]),
+ ]) // end of minwidth wrapper
+ )
}
-PendingTx.prototype.resetGasFields = function () {
- log.debug(`pending-tx resetGasFields`)
-
- this.inputs.forEach((hexInput) => {
- if (hexInput) {
- hexInput.setValid()
- }
- })
-
- this.setState({
- txData: null,
- valid: true,
- })
-}
+// PendingTx.prototype.gasPriceChanged = function (newBN, valid) {
+// log.info(`Gas price changed to: ${newBN.toString(10)}`)
+// const txMeta = this.gatherTxMeta()
+// txMeta.txParams.gasPrice = '0x' + newBN.toString('hex')
+// this.setState({
+// txData: clone(txMeta),
+// valid,
+// })
+// }
+
+// PendingTx.prototype.gasLimitChanged = function (newBN, valid) {
+// log.info(`Gas limit changed to ${newBN.toString(10)}`)
+// const txMeta = this.gatherTxMeta()
+// txMeta.txParams.gas = '0x' + newBN.toString('hex')
+// this.setState({
+// txData: clone(txMeta),
+// valid,
+// })
+// }
+
+// PendingTx.prototype.resetGasFields = function () {
+// log.debug(`pending-tx resetGasFields`)
+
+// this.inputs.forEach((hexInput) => {
+// if (hexInput) {
+// hexInput.setValid()
+// }
+// })
+
+// this.setState({
+// txData: null,
+// valid: true,
+// })
+// }
PendingTx.prototype.onSubmit = function (event) {
event.preventDefault()
@@ -466,15 +492,3 @@ PendingTx.prototype.bnMultiplyByFraction = function (targetBN, numerator, denomi
const denomBN = new BN(denominator)
return targetBN.mul(numBN).div(denomBN)
}
-
-function forwardCarrat () {
- return (
- h('img', {
- src: 'images/forward-carrat.svg',
- style: {
- padding: '5px 6px 0px 10px',
- height: '37px',
- },
- })
- )
-}
diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js
new file mode 100644
index 000000000..9d7bc9138
--- /dev/null
+++ b/ui/app/components/tx-view.js
@@ -0,0 +1,231 @@
+const Component = require('react').Component
+const connect = require('react-redux').connect
+const h = require('react-hyperscript')
+const ethUtil = require('ethereumjs-util')
+const inherits = require('util').inherits
+const actions = require('../actions')
+// slideout menu
+const WalletView = require('./wallet-view')
+
+// balance component
+const BalanceComponent = require('./balance-component')
+
+const Identicon = require('./identicon')
+// const AccountDropdowns = require('./account-dropdowns').AccountDropdowns
+// const Content = require('./wallet-content-display')
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(TxView)
+
+function mapStateToProps (state) {
+ return {
+ sidebarOpen: state.appState.sidebarOpen,
+ identities: state.metamask.identities,
+ accounts: state.metamask.accounts,
+ address: state.metamask.selectedAddress,
+ conversionRate: state.metamask.conversionRate,
+ currentCurrency: state.metamask.currentCurrency,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ showSidebar: () => { dispatch(actions.showSidebar()) },
+ hideSidebar: () => { dispatch(actions.hideSidebar()) },
+ showModal: () => { dispatch(actions.showModal()) },
+ }
+}
+
+const contentDivider = h('div', {
+ style: {
+ marginLeft: '1.3em',
+ marginRight: '1.3em',
+ height:'1px',
+ background:'#E7E7E7', // TODO: make custom color
+ },
+})
+
+inherits(TxView, Component)
+function TxView () {
+ Component.call(this)
+}
+
+TxView.prototype.render = function () {
+
+ var props = this.props
+ var selected = props.address || Object.keys(props.accounts)[0]
+ var checksumAddress = selected && ethUtil.toChecksumAddress(selected)
+ var identity = props.identities[selected]
+ var account = props.accounts[selected]
+ const { conversionRate, currentCurrency } = props
+
+ return h('div.tx-view.flex-column', {
+ style: {},
+ }, [
+
+ h('div.flex-row.phone-visible', {
+ style: {
+ margin: '1em 0.9em',
+ alignItems: 'center'
+ },
+ onClick: () => {
+ this.props.sidebarOpen ? this.props.hideSidebar() : this.props.showSidebar()
+ },
+ }, [
+ // burger
+ h('div.fa.fa-bars', {
+ style: {
+ fontSize: '1.3em',
+ },
+ }, []),
+
+ // account display
+ h('.identicon-wrapper.select-none', {
+ style: {
+ marginLeft: '0.9em',
+ },
+ }, [
+ h(Identicon, {
+ diameter: 24,
+ address: selected,
+ }),
+ ]),
+
+ h('span.account-name', {
+ style: {},
+ }, [
+ identity.name,
+ ]),
+
+ ]),
+
+ // laptop: flex-row, flex-center
+ // mobile: flex-column
+ h('div.hero-balance', {
+ style: {},
+ }, [
+
+ h(BalanceComponent, {
+ balanceValue: account && account.balance,
+ conversionRate,
+ currentCurrency,
+ style: {},
+ }),
+
+ // laptop: 10vw?
+ // phone: 75vw?
+ h('div.flex-row.flex-center.hero-balance-buttons', {
+ style: {}
+ }, [
+ h('button.btn-clear', {
+ style: {
+ textAlign: 'center',
+ },
+ onClick: () => {
+ this.props.showModal()
+ },
+ }, 'BUY'),
+
+ h('button.btn-clear', {
+ style: {
+ textAlign: 'center',
+ marginLeft: '1.4em',
+ },
+ }, 'SEND'),
+
+ ]),
+ ]),
+
+ h('div.flex-row', {
+ style: {
+ margin: '1.8em 0.9em 0.8em 0.9em',
+ }
+ }, [
+
+ // tx-view-tab.js
+ h('div.flex-row', {
+ }, [
+
+ h('div', {
+ style: {
+ borderBottom: '0.07em solid black',
+ paddingBottom: '0.015em',
+ }
+ }, 'TRANSACTIONS'),
+
+ h('div', {
+ style: {
+ marginLeft: '1.25em',
+ }
+ }, 'TOKENS'),
+
+ ]),
+ ]),
+
+ contentDivider,
+
+ this.renderTransactionListItem(),
+
+ contentDivider,
+
+ this.renderTransactionListItem(),
+
+ contentDivider,
+
+ ])
+ // column
+ // tab row
+ // divider
+ // item
+}
+
+TxView.prototype.renderTransactionListItem = function () {
+ return h('div.flex-column', {
+ style: {
+ alignItems: 'stretch',
+ margin: '0.6em 1.3em 0.6em 1.3em',
+ }
+ }, [
+
+ h('div', {
+ style: {
+ flexGrow: 1,
+ marginTop: '0.3em',
+ }
+ }, 'Jul 01, 2017'),
+
+ h('div.flex-row', {
+ style: {
+ alignItems: 'stretch',
+ }
+ }, [
+
+ h('div', {
+ style: {
+ flexGrow: 1,
+ }
+ }, 'icon'),
+
+ h('div', {
+ style: {
+ flexGrow: 3,
+ }
+ }, 'Hash'),
+
+ h('div', {
+ style: {
+ flexGrow: 5,
+ }
+ }, 'Status'),
+
+ h('div', {
+ style: {
+ flexGrow: 2,
+ }
+ }, 'Details'),
+
+ ])
+
+ ])
+}
+
+
diff --git a/ui/app/components/wallet-content-display.js b/ui/app/components/wallet-content-display.js
new file mode 100644
index 000000000..3baffad69
--- /dev/null
+++ b/ui/app/components/wallet-content-display.js
@@ -0,0 +1,56 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+
+module.exports = WalletContentDisplay
+
+inherits(WalletContentDisplay, Component)
+function WalletContentDisplay () {
+ Component.call(this)
+}
+
+WalletContentDisplay.prototype.render = function () {
+ const { title, amount, fiatValue, active, style } = this.props
+
+ // TODO: Separate component: wallet-content-account
+ return h('div.flex-column', {
+ style: {
+ marginLeft: '1.3em',
+ alignItems: 'flex-start',
+ ...style,
+ }
+ }, [
+
+ h('span', {
+ style: {
+ fontSize: '1.1em',
+ },
+ }, title),
+
+ h('span', {
+ style: {
+ fontSize: '1.8em',
+ margin: '0.4em 0em',
+ },
+ }, amount),
+
+ h('span', {
+ style: {
+ fontSize: '1.3em',
+ },
+ }, fiatValue),
+
+ active && h('div', {
+ style: {
+ position: 'absolute',
+ marginLeft: '-1.3em',
+ height: '6em',
+ width: '0.3em',
+ background: '#D8D8D8', // TODO: add to resuable colors
+ }
+ }, [
+ ])
+ ])
+
+}
+
diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js
new file mode 100644
index 000000000..3c331a100
--- /dev/null
+++ b/ui/app/components/wallet-view.js
@@ -0,0 +1,133 @@
+const Component = require('react').Component
+const connect = require('react-redux').connect
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const Identicon = require('./identicon')
+const AccountDropdowns = require('./account-dropdowns').AccountDropdowns
+const Content = require('./wallet-content-display')
+const actions = require('../actions')
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(WalletView)
+
+function mapStateToProps (state) {
+ return {
+ network: state.metamask.network,
+ sidebarOpen: state.appState.sidebarOpen,
+ identities: state.metamask.identities,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ showSendPage: () => {dispatch(actions.showSendPage())},
+ hideSidebar: () => {dispatch(actions.hideSidebar())},
+ }
+}
+
+inherits(WalletView, Component)
+function WalletView () {
+ Component.call(this)
+}
+
+const noop = () => {}
+
+WalletView.prototype.render = function () {
+ const selected = '0x82df11beb942BEeeD58d466fCb0F0791365C7684' // TODO: remove fake address
+ const { network, responsiveDisplayClassname, style, identities } = this.props
+
+ return h('div.wallet-view.flex-column' + (responsiveDisplayClassname || ''), {
+ style: {},
+ }, [
+
+ // TODO: Separate component: wallet account details
+ h('div.flex-column', {
+ style: {}
+ }, [
+
+ h('div.flex-row.account-options-menu', {
+ }, [
+
+ h(AccountDropdowns, {
+ // selected,
+ // network,
+ // identities: props.identities,
+ enableAccountOptions: true,
+ }, []),
+
+ ]),
+
+ h('div.flex-column.flex-center', {
+ style: {
+ // constrains size of absolutely positioned wrappers
+ position: 'relative',
+ },
+ }, [
+
+ h('.identicon-wrapper.select-none', {
+ style: {
+ marginBottom: '1%',
+ },
+ }, [
+ h(Identicon, {
+ diameter: 54,
+ address: selected,
+ }),
+ ]),
+
+ h('span.account-name', {
+ style: {}
+ }, [
+ 'Account 1'
+ ]),
+
+ h(AccountDropdowns, {
+ style: {
+ position: 'absolute',
+ left: 'calc(50% + 28px + 5.5px)',
+ // left: '42px',
+ // top: '-10px'
+ // left: '66.5%',
+ top: '19.5%',
+ },
+ selected,
+ network,
+ identities,
+ enableAccountsSelector: true,
+ }, []),
+ ]),
+
+ h(
+ AccountDropdowns,
+ {
+ style: {
+ marginLeft: 'auto',
+ cursor: 'pointer',
+ },
+ selected,
+ network, // TODO: this prop could be in the account dropdown container
+ identities: {},
+ },
+ ),
+
+ ]),
+
+ h(Content, {
+ title: 'Wallet',
+ amount: '1001.124 ETH',
+ fiatValue: '$300,000.00 USD',
+ active: true,
+ }),
+
+ // Wallet contents
+ h(Content, {
+ title: "Total Token Balance",
+ amount: "45.439 ETH",
+ fiatValue: "$13,000.00 USD",
+ active: false,
+ style: {
+ marginTop: '1.3em',
+ }
+ })
+
+ ])
+}