Merge pull request #1336 from MetaMask/buyButtonRedo

Buy button redo
feature/default_network_editable
Dan Finlay 8 years ago committed by GitHub
commit ca3faba1ac
  1. 15
      ui/app/account-detail.js
  2. 18
      ui/app/actions.js
  3. 139
      ui/app/components/buy-button-subview.js
  4. 114
      ui/app/components/coinbase-form.js
  5. 60
      ui/app/components/custom-radio-list.js
  6. 2
      ui/app/components/pending-tx.js
  7. 34
      ui/app/components/shapeshift-form.js
  8. 2
      ui/app/conf-tx.js
  9. 41
      ui/app/css/index.css
  10. 35
      ui/app/reducers/app.js

@ -16,7 +16,6 @@ const ExportAccountView = require('./components/account-export')
const ethUtil = require('ethereumjs-util')
const EditableLabel = require('./components/editable-label')
const Tooltip = require('./components/tooltip')
const BuyButtonSubview = require('./components/buy-button-subview')
module.exports = connect(mapStateToProps)(AccountDetailScreen)
function mapStateToProps (state) {
@ -238,8 +237,6 @@ AccountDetailScreen.prototype.subview = function () {
case 'export':
var state = extend({key: 'export'}, this.props)
return h(ExportAccountView, state)
case 'buyForm':
return h(BuyButtonSubview, extend({key: 'buyForm'}, this.props))
default:
return this.transactionList()
}
@ -262,15 +259,3 @@ AccountDetailScreen.prototype.transactionList = function () {
AccountDetailScreen.prototype.requestAccountExport = function () {
this.props.dispatch(actions.requestExportAccount())
}
AccountDetailScreen.prototype.buyButtonDeligator = function () {
var props = this.props
var selected = props.address || Object.keys(props.accounts)[0]
if (this.props.accountDetail.subview === 'buyForm') {
props.dispatch(actions.backToAccountDetail(props.address))
} else {
props.dispatch(actions.buyEthView(selected))
}
}

@ -134,10 +134,6 @@ var actions = {
buyEth: buyEth,
buyEthView: buyEthView,
BUY_ETH_VIEW: 'BUY_ETH_VIEW',
UPDATE_COINBASE_AMOUNT: 'UPDATE_COIBASE_AMOUNT',
updateCoinBaseAmount: updateCoinBaseAmount,
UPDATE_BUY_ADDRESS: 'UPDATE_BUY_ADDRESS',
updateBuyAddress: updateBuyAddress,
COINBASE_SUBVIEW: 'COINBASE_SUBVIEW',
coinBaseSubview: coinBaseSubview,
SHAPESHIFT_SUBVIEW: 'SHAPESHIFT_SUBVIEW',
@ -852,20 +848,6 @@ function buyEthView (address) {
}
}
function updateCoinBaseAmount (value) {
return {
type: actions.UPDATE_COINBASE_AMOUNT,
value,
}
}
function updateBuyAddress (value) {
return {
type: actions.UPDATE_BUY_ADDRESS,
value,
}
}
function coinBaseSubview () {
return {
type: actions.COINBASE_SUBVIEW,

@ -6,12 +6,15 @@ const actions = require('../actions')
const CoinbaseForm = require('./coinbase-form')
const ShapeshiftForm = require('./shapeshift-form')
const Loading = require('./loading')
const TabBar = require('./tab-bar')
const AccountPanel = require('./account-panel')
const RadioList = require('./custom-radio-list')
module.exports = connect(mapStateToProps)(BuyButtonSubview)
function mapStateToProps (state) {
return {
identity: state.appState.identity,
account: state.metamask.accounts[state.appState.buyView.buyAddress],
warning: state.appState.warning,
buyView: state.appState.buyView,
network: state.metamask.network,
@ -31,7 +34,11 @@ BuyButtonSubview.prototype.render = function () {
const isLoading = props.isSubLoading
return (
h('.buy-eth-section', [
h('.buy-eth-section.flex-column', {
style: {
alignItems: 'center',
},
}, [
// back button
h('.flex-row', {
style: {
@ -46,58 +53,79 @@ BuyButtonSubview.prototype.render = function () {
left: '10px',
},
}),
h('h2.page-subtitle', 'Buy Eth'),
]),
h(Loading, { isLoading }),
h(TabBar, {
tabs: [
{
content: [
'Coinbase',
h('a', {
onClick: (event) => this.navigateTo('https://github.com/MetaMask/faq/blob/master/COINBASE.md'),
}, [
h('i.fa.fa-question-circle', {
style: {
margin: '0px 5px',
},
}),
]),
],
key: 'coinbase',
h('h2.text-transform-uppercase.flex-center', {
style: {
width: '100vw',
background: 'rgb(235, 235, 235)',
color: 'rgb(174, 174, 174)',
paddingTop: '4px',
paddingBottom: '4px',
},
{
content: [
'Shapeshift',
h('a', {
href: 'https://github.com/MetaMask/faq/blob/master/COINBASE.md',
onClick: (event) => this.navigateTo('https://info.shapeshift.io/about'),
}, [
h('i.fa.fa-question-circle', {
style: {
margin: '0px 5px',
},
}),
]),
],
key: 'shapeshift',
}, 'Buy Eth'),
]),
h('div', {
style: {
position: 'absolute',
top: '57vh',
left: '49vw',
},
}, [
h(Loading, {isLoading}),
]),
h('div', {
style: {
width: '80%',
},
}, [
h(AccountPanel, {
showFullAddress: true,
identity: props.identity,
account: props.account,
}),
]),
h('h3.text-transform-uppercase', {
style: {
paddingLeft: '15px',
fontFamily: 'Montserrat Light',
width: '100vw',
background: 'rgb(235, 235, 235)',
color: 'rgb(174, 174, 174)',
paddingTop: '4px',
paddingBottom: '4px',
},
}, 'Select Service'),
h('.flex-row.selected-exchange', {
style: {
position: 'relative',
right: '35px',
marginTop: '20px',
marginBottom: '20px',
},
}, [
h(RadioList, {
defaultFocus: props.buyView.subview,
labels: [
'Coinbase',
'ShapeShift',
],
subtext: {
'Coinbase': 'Crypto/FIAT (USA only)',
'ShapeShift': 'Crypto',
},
],
defaultTab: 'coinbase',
tabSelected: (key) => {
switch (key) {
case 'coinbase':
props.dispatch(actions.coinBaseSubview())
break
case 'shapeshift':
props.dispatch(actions.shapeShiftSubview(props.provider.type))
break
}
onClick: this.radioHandler.bind(this),
}),
]),
h('h3.text-transform-uppercase', {
style: {
paddingLeft: '15px',
fontFamily: 'Montserrat Light',
width: '100vw',
background: 'rgb(235, 235, 235)',
color: 'rgb(174, 174, 174)',
paddingTop: '4px',
paddingBottom: '4px',
},
}),
}, props.buyView.subview),
this.formVersionSubview(),
])
)
@ -152,3 +180,12 @@ BuyButtonSubview.prototype.backButtonContext = function () {
this.props.dispatch(actions.goHome())
}
}
BuyButtonSubview.prototype.radioHandler = function (event) {
switch (event.target.title) {
case 'Coinbase':
return this.props.dispatch(actions.coinBaseSubview())
case 'ShapeShift':
return this.props.dispatch(actions.shapeShiftSubview(this.props.provider.type))
}
}

@ -4,7 +4,6 @@ const inherits = require('util').inherits
const connect = require('react-redux').connect
const actions = require('../actions')
const isValidAddress = require('../util').isValidAddress
module.exports = connect(mapStateToProps)(CoinbaseForm)
function mapStateToProps (state) {
@ -21,105 +20,36 @@ function CoinbaseForm () {
CoinbaseForm.prototype.render = function () {
var props = this.props
var amount = props.buyView.amount
var address = props.buyView.buyAddress
return h('.flex-column', {
style: {
// margin: '10px',
marginTop: '35px',
padding: '25px',
width: '100%',
},
}, [
h('.flex-column', {
style: {
alignItems: 'flex-start',
},
}, [
h('.flex-row', [
h('div', 'Address:'),
h('.ellip-address', address),
]),
h('.flex-row', [
h('div', 'Amount: $'),
h('.input-container', [
h('input.buy-inputs', {
style: {
width: '3em',
boxSizing: 'border-box',
},
defaultValue: amount,
onChange: this.handleAmount.bind(this),
}),
h('i.fa.fa-pencil-square-o.edit-text', {
style: {
fontSize: '12px',
color: '#F7861C',
position: 'relative',
bottom: '5px',
right: '11px',
},
}),
]),
]),
]),
h('.info-gray', {
style: {
fontSize: '10px',
fontFamily: 'Montserrat Light',
margin: '15px',
lineHeight: '13px',
},
},
`there is a USD$ 15 a day max and a USD$ 50
dollar limit per the life time of an account without a
coinbase account. A fee of 3.75% will be aplied to debit/credit cards.`),
!props.warning ? h('div', {
style: {
width: '340px',
height: '22px',
},
}) : props.warning && h('span.error.flex-center', props.warning),
h('.flex-row', {
style: {
justifyContent: 'space-around',
margin: '33px',
marginTop: '0px',
},
}, [
h('button', {
h('button.btn-green', {
onClick: this.toCoinbase.bind(this),
}, 'Continue to Coinbase'),
h('button', {
h('button.btn-red', {
onClick: () => props.dispatch(actions.backTobuyView(props.accounts.address)),
}, 'Cancel'),
]),
])
}
CoinbaseForm.prototype.handleAmount = function (event) {
this.props.dispatch(actions.updateCoinBaseAmount(event.target.value))
}
CoinbaseForm.prototype.handleAddress = function (event) {
this.props.dispatch(actions.updateBuyAddress(event.target.value))
}
CoinbaseForm.prototype.toCoinbase = function () {
var props = this.props
var amount = props.buyView.amount
var address = props.buyView.buyAddress
var message
if (isValidAddress(address) && isValidAmountforCoinBase(amount).valid) {
props.dispatch(actions.buyEth({ network: '1', address, amount: props.buyView.amount }))
} else if (!isValidAmountforCoinBase(amount).valid) {
message = isValidAmountforCoinBase(amount).message
return props.dispatch(actions.displayWarning(message))
} else {
message = 'Receiving address is invalid.'
return props.dispatch(actions.displayWarning(message))
}
CoinbaseForm.prototype.toCoinbase = function () {
const props = this.props
const address = props.buyView.buyAddress
props.dispatch(actions.buyEth({ network: '1', address, amount: 0 }))
}
CoinbaseForm.prototype.renderLoading = function () {
@ -131,29 +61,3 @@ CoinbaseForm.prototype.renderLoading = function () {
src: 'images/loading.svg',
})
}
function isValidAmountforCoinBase (amount) {
amount = parseFloat(amount)
if (amount) {
if (amount <= 15 && amount > 0) {
return {
valid: true,
}
} else if (amount > 15) {
return {
valid: false,
message: 'The amount can not be greater then $15',
}
} else {
return {
valid: false,
message: 'Can not buy amounts less then $0',
}
}
} else {
return {
valid: false,
message: 'The amount entered is not a number',
}
}
}

@ -0,0 +1,60 @@
const Component = require('react').Component
const h = require('react-hyperscript')
const inherits = require('util').inherits
module.exports = RadioList
inherits(RadioList, Component)
function RadioList () {
Component.call(this)
}
RadioList.prototype.render = function () {
const props = this.props
const activeClass = '.custom-radio-selected'
const inactiveClass = '.custom-radio-inactive'
const {
labels,
defaultFocus,
} = props
return (
h('.flex-row', {
style: {
fontSize: '12px',
},
}, [
h('.flex-column.custom-radios', {
style: {
marginRight: '5px',
},
},
labels.map((lable, i) => {
let isSelcted = (this.state !== null)
isSelcted = isSelcted ? (this.state.selected === lable) : (defaultFocus === lable)
return h(isSelcted ? activeClass : inactiveClass, {
title: lable,
onClick: (event) => {
this.setState({selected: event.target.title})
props.onClick(event)
},
})
})
),
h('.text', {},
labels.map((lable) => {
if (props.subtext) {
return h('.flex-row', {}, [
h('.radio-titles', lable),
h('.radio-titles-subtext', `- ${props.subtext[lable]}`),
])
} else {
return h('.radio-titles', lable)
}
})
),
])
)
}

@ -289,7 +289,7 @@ PendingTx.prototype.render = function () {
insufficientBalance ?
h('button', {
h('button.btn-green', {
onClick: props.buyEth,
}, 'Buy Ether')
: null,

@ -43,14 +43,18 @@ ShapeshiftForm.prototype.renderMain = function () {
style: {
// marginTop: '10px',
padding: '25px',
paddingTop: '5px',
width: '100%',
minHeight: '215px',
alignItems: 'center',
overflowY: 'auto',
},
}, [
h('.flex-row', {
style: {
justifyContent: 'center',
alignItems: 'baseline',
height: '42px',
},
}, [
h('img', {
@ -66,6 +70,7 @@ ShapeshiftForm.prototype.renderMain = function () {
h('input#fromCoin.buy-inputs.ex-coins', {
type: 'text',
list: 'coinList',
autoFocus: true,
dataset: {
persistentFormId: 'input-coin',
},
@ -92,7 +97,6 @@ ShapeshiftForm.prototype.renderMain = function () {
h('.icon-control', [
h('i.fa.fa-refresh.fa-4.orange', {
style: {
position: 'relative',
bottom: '5px',
left: '5px',
color: '#F7861C',
@ -121,8 +125,6 @@ ShapeshiftForm.prototype.renderMain = function () {
},
}),
]),
this.props.isSubLoading ? this.renderLoading() : null,
h('.flex-column', {
style: {
alignItems: 'flex-start',
@ -138,17 +140,6 @@ ShapeshiftForm.prototype.renderMain = function () {
this.props.warning) : this.renderInfo(),
]),
h('.flex-row', {
style: {
padding: '10px',
paddingBottom: '2px',
width: '100%',
},
}, [
h('div', 'Receiving address:'),
h('.ellip-address', this.props.buyView.buyAddress),
]),
h(this.activeToggle('.input-container'), {
style: {
padding: '10px',
@ -156,6 +147,7 @@ ShapeshiftForm.prototype.renderMain = function () {
width: '100%',
},
}, [
h('div', `${coin} Address:`),
h('input#fromCoinAddress.buy-inputs', {
@ -166,8 +158,8 @@ ShapeshiftForm.prototype.renderMain = function () {
},
style: {
boxSizing: 'border-box',
width: '278px',
height: '20px',
width: '227px',
height: '30px',
padding: ' 5px ',
},
}),
@ -177,7 +169,7 @@ ShapeshiftForm.prototype.renderMain = function () {
fontSize: '12px',
color: '#F7861C',
position: 'relative',
bottom: '5px',
bottom: '10px',
right: '11px',
},
}),
@ -190,6 +182,8 @@ ShapeshiftForm.prototype.renderMain = function () {
onClick: this.shift.bind(this),
style: {
marginTop: '10px',
position: 'relative',
bottom: '40px',
},
},
'Submit'),
@ -266,8 +260,6 @@ ShapeshiftForm.prototype.renderInfo = function () {
return h('span', {
style: {
marginTop: '10px',
marginBottom: '15px',
},
}, [
h('h3.flex-row.text-transform-uppercase', {
@ -286,10 +278,6 @@ ShapeshiftForm.prototype.renderInfo = function () {
])
}
ShapeshiftForm.prototype.handleAddress = function (event) {
this.props.dispatch(actions.updateBuyAddress(event.target.value))
}
ShapeshiftForm.prototype.activeToggle = function (elementType) {
if (!this.props.buyView.formView.response || this.props.warning) return elementType
return `${elementType}.inactive`

@ -141,7 +141,7 @@ function currentTxView (opts) {
}
ConfirmTxScreen.prototype.buyEth = function (address, event) {
this.stopPropagation(event)
event.preventDefault()
this.props.dispatch(actions.buyEthView(address))
}

@ -489,6 +489,47 @@ input.large-input {
}
/* buy eth warning screen */
.custom-radios {
justify-content: space-around;
align-items: center;
}
.custom-radio-selected {
width: 17px;
height: 17px;
border: solid;
border-style: double;
border-radius: 15px;
border-width: 5px;
background: rgba(247, 134, 28, 1);
border-color: #F7F7F7;
}
.custom-radio-inactive {
width: 14px;
height: 14px;
border: solid;
border-width: 1px;
border-radius: 24px;
border-color: #AEAEAE;
}
.radio-titles {
color: rgba(247, 134, 28, 1);
}
.radio-titles-subtext {
}
.selected-exchange {
}
.buy-radio {
}
.eth-warning{
transition: opacity 400ms ease-in, transform 400ms ease-in;

@ -469,8 +469,9 @@ function reduceApp (state, action) {
name: 'buyEth',
context: appState.currentView.name,
},
identity: state.metamask.identities[action.value],
buyView: {
subview: 'buyForm',
subview: 'Coinbase',
amount: '15.00',
buyAddress: action.value,
formView: {
@ -480,36 +481,10 @@ function reduceApp (state, action) {
},
})
case actions.UPDATE_BUY_ADDRESS:
return extend(appState, {
buyView: {
subview: 'buyForm',
formView: {
coinbase: appState.buyView.formView.coinbase,
shapeshift: appState.buyView.formView.shapeshift,
},
buyAddress: action.value,
amount: appState.buyView.amount,
},
})
case actions.UPDATE_COINBASE_AMOUNT:
return extend(appState, {
buyView: {
subview: 'buyForm',
formView: {
coinbase: true,
shapeshift: false,
},
buyAddress: appState.buyView.buyAddress,
amount: action.value,
},
})
case actions.COINBASE_SUBVIEW:
return extend(appState, {
buyView: {
subview: 'buyForm',
subview: 'Coinbase',
formView: {
coinbase: true,
shapeshift: false,
@ -522,7 +497,7 @@ function reduceApp (state, action) {
case actions.SHAPESHIFT_SUBVIEW:
return extend(appState, {
buyView: {
subview: 'buyForm',
subview: 'ShapeShift',
formView: {
coinbase: false,
shapeshift: true,
@ -537,7 +512,7 @@ function reduceApp (state, action) {
case actions.PAIR_UPDATE:
return extend(appState, {
buyView: {
subview: 'buyForm',
subview: 'ShapeShift',
formView: {
coinbase: false,
shapeshift: true,

Loading…
Cancel
Save