Adds new gas customization modal container (without content)

feature/default_network_editable
Dan Miller 6 years ago
parent 35670e9261
commit f9aa5a70de
  1. 18
      app/_locales/en/messages.json
  2. 79
      ui/app/components/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js
  3. 11
      ui/app/components/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js
  4. 1
      ui/app/components/gas-customization/gas-modal-page-container/index.js
  5. 50
      ui/app/components/gas-customization/gas-modal-page-container/index.scss
  6. 156
      ui/app/components/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-component.test.js
  7. 44
      ui/app/components/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js
  8. 2
      ui/app/components/index.scss
  9. 36
      ui/app/components/modals/modal.js
  10. 2
      ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.container.js
  11. 1
      ui/app/css/itcss/settings/variables.scss

@ -80,12 +80,18 @@
"addAcquiredTokens": { "addAcquiredTokens": {
"message": "Add the tokens you've acquired using MetaMask" "message": "Add the tokens you've acquired using MetaMask"
}, },
"advanced": {
"message": "Advanced"
},
"amount": { "amount": {
"message": "Amount" "message": "Amount"
}, },
"amountPlusGas": { "amountPlusGas": {
"message": "Amount + Gas" "message": "Amount + Gas"
}, },
"amountPlusTxFee": {
"message": "Amount + TX Fee"
},
"appDescription": { "appDescription": {
"message": "Ethereum Browser Extension", "message": "Ethereum Browser Extension",
"description": "The description of the application" "description": "The description of the application"
@ -127,6 +133,9 @@
"balanceIsInsufficientGas": { "balanceIsInsufficientGas": {
"message": "Insufficient balance for current gas total" "message": "Insufficient balance for current gas total"
}, },
"basic": {
"message": "Basic"
},
"beta": { "beta": {
"message": "BETA" "message": "BETA"
}, },
@ -303,6 +312,9 @@
"customGas": { "customGas": {
"message": "Customize Gas" "message": "Customize Gas"
}, },
"customGasSubTitle": {
"message": "Increasing fee may decrease processing times, but it is not guaranteed."
},
"customToken": { "customToken": {
"message": "Custom Token" "message": "Custom Token"
}, },
@ -755,6 +767,9 @@
"optionalNickname": { "optionalNickname": {
"message": "Nickname (optional)" "message": "Nickname (optional)"
}, },
"newTotal": {
"message": "New Total"
},
"next": { "next": {
"message": "Next" "message": "Next"
}, },
@ -820,6 +835,9 @@
"parameters": { "parameters": {
"message": "Parameters" "message": "Parameters"
}, },
"originalTotal": {
"message": "Original Total"
},
"password": { "password": {
"message": "Password" "message": "Password"
}, },

@ -0,0 +1,79 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import PageContainer from '../../page-container'
import { Tabs, Tab } from '../../tabs'
export default class GasModalPageContainer extends Component {
static contextTypes = {
t: PropTypes.func,
}
static propTypes = {
hideModal: PropTypes.func,
}
state = {}
renderBasicTabContent () {
return (
<div className="basic-tab"/>
)
}
renderAdvancedTabContent () {
return (
<div className="advanced-tab"/>
)
}
renderInfoRow (className, totalLabelKey, fiatTotal, cryptoTotal) {
return (
<div className={className}>
<div className="total-info">
<span className="total-label">{`${this.context.t(totalLabelKey)}:`}</span><span className="total-value">{fiatTotal}</span>
</div>
<div className="sum-info">
<span className="sum-label">{`${this.context.t('amountPlusTxFee')}`}</span><span className="sum-value">{cryptoTotal}</span>
</div>
</div>
)
}
renderTabContent (mainTabContent) {
return (
<div className="gas-modal-content">
{ mainTabContent() }
{ this.renderInfoRow('info-row--fade', 'originalTotal', '$20.02 USD', '0.06685 ETH') }
{ this.renderInfoRow('info-row', 'newTotal', '$20.02 USD', '0.06685 ETH') }
</div>
)
}
renderTabs () {
return (
<Tabs>
<Tab name={this.context.t('basic')}>
{ this.renderTabContent(this.renderBasicTabContent) }
</Tab>
<Tab name={this.context.t('advanced')}>
{ this.renderTabContent(this.renderAdvancedTabContent) }
</Tab>
</Tabs>
)
}
render () {
const { hideModal } = this.props
return (
<PageContainer
title={this.context.t('customGas')}
subtitle={this.context.t('customGasSpeedUp')}
tabsComponent={this.renderTabs()}
disabled={false}
onCancel={() => hideModal()}
onClose={() => hideModal()}
/>
)
}
}

@ -0,0 +1,11 @@
import { connect } from 'react-redux'
import GasModalPageContainer from './gas-modal-page-container.component'
import { hideModal } from '../../../actions'
const mapDispatchToProps = dispatch => {
return {
hideModal: () => dispatch(hideModal()),
}
}
export default connect(null, mapDispatchToProps)(GasModalPageContainer)

@ -0,0 +1 @@
export { default } from './gas-modal-page-container.container'

@ -0,0 +1,50 @@
.gas-modal-content {
.basic-tab {
height: 219px;
}
.advanced-tab {
height: 475px;
}
.info-row, .info-row--fade {
width: 100%;
background: $polar;
padding: 15px 21px;
display: flex;
flex-flow: column;
color: $scorpion;
.total-info, .sum-info {
display: flex;
flex-flow: row;
justify-content: space-between;
}
.total-info {
.total-label {
font-size: 16px;
}
.total-value {
font-size: 16px;
font-weight: bold;
}
}
.sum-info {
.sum-label {
font-size: 12px;
}
.sum-value {
font-size: 14px;
}
}
}
.info-row--fade {
background: white;
color: $dusty-gray;
}
}

@ -0,0 +1,156 @@
import React from 'react'
import assert from 'assert'
import { shallow } from 'enzyme'
import sinon from 'sinon'
import GasModalPageContainer from '../gas-modal-page-container.component.js'
import PageContainer from '../../../page-container'
import { Tab } from '../../../tabs'
const propsMethodSpies = {
hideModal: sinon.spy(),
}
describe('GasModalPageContainer Component', function () {
let wrapper
beforeEach(() => {
wrapper = shallow(<GasModalPageContainer
hideModal={propsMethodSpies.hideModal}
/>, { context: { t: (str1, str2) => str2 ? str1 + str2 : str1 } })
})
afterEach(() => {
propsMethodSpies.hideModal.resetHistory()
})
describe('render', () => {
it('should render a PageContainer compenent', () => {
assert.equal(wrapper.find(PageContainer).length, 1)
})
it('should pass correct props to PageContainer', () => {
const {
title,
subtitle,
disabled,
} = wrapper.find(PageContainer).props()
assert.equal(title, 'customGas')
assert.equal(subtitle, 'customGasSpeedUp')
assert.equal(disabled, false)
})
it('should pass the correct onCancel and onClose methods to PageContainer', () => {
const {
onCancel,
onClose,
} = wrapper.find(PageContainer).props()
assert.equal(propsMethodSpies.hideModal.callCount, 0)
onCancel()
assert.equal(propsMethodSpies.hideModal.callCount, 1)
onClose()
assert.equal(propsMethodSpies.hideModal.callCount, 2)
})
it('should pass the correct renderTabs property to PageContainer', () => {
sinon.stub(GasModalPageContainer.prototype, 'renderTabs').returns('mockTabs')
const renderTabsWrapperTester = shallow(<GasModalPageContainer />, { context: { t: (str1, str2) => str2 ? str1 + str2 : str1 } })
const { tabsComponent } = renderTabsWrapperTester.find(PageContainer).props()
assert.equal(tabsComponent, 'mockTabs')
GasModalPageContainer.prototype.renderTabs.restore()
})
})
describe('renderTabs', () => {
it('should render a Tabs component with "Basic" and "Advanced" tabs', () => {
const renderTabsResult = wrapper.instance().renderTabs()
const renderedTabs = shallow(renderTabsResult)
assert.equal(renderedTabs.props().className, 'tabs')
const tabs = renderedTabs.find(Tab)
assert.equal(tabs.length, 2)
assert.equal(tabs.at(0).props().name, 'basic')
assert.equal(tabs.at(1).props().name, 'advanced')
assert.equal(tabs.at(0).childAt(0).props().className, 'gas-modal-content')
assert.equal(tabs.at(1).childAt(0).props().className, 'gas-modal-content')
})
it('should render the expected children of each tab', () => {
const GP = GasModalPageContainer.prototype
sinon.spy(GP, 'renderTabContent')
assert.equal(GP.renderTabContent.callCount, 0)
wrapper.instance().renderTabs()
assert.equal(GP.renderTabContent.callCount, 2)
assert.deepEqual(GP.renderTabContent.firstCall.args, [wrapper.instance().renderBasicTabContent])
assert.deepEqual(GP.renderTabContent.secondCall.args, [wrapper.instance().renderAdvancedTabContent])
GP.renderTabContent.restore()
})
})
describe('renderTabContent', () => {
it('should render a root gas-modal-content div', () => {
const renderTabContentResult = wrapper.instance().renderTabContent(() => {})
const renderedTabContent = shallow(renderTabContentResult)
assert.equal(renderedTabContent.props().className, 'gas-modal-content')
})
it('should render the element returned by the passed func as its first child', () => {
const renderTabContentResult = wrapper.instance().renderTabContent(() => <span>Mock content</span>)
const renderedTabContent = shallow(renderTabContentResult)
assert(renderedTabContent.childAt(0).equals(<span>Mock content</span>))
})
it('should render the element results of renderInfoRow calls as second and third childs', () => {
const GP = GasModalPageContainer.prototype
sinon.stub(GP, 'renderInfoRow').callsFake((...args) => args.join(','))
const renderTabContentResult = wrapper.instance().renderTabContent(() => <span>Mock content</span>)
const renderedTabContent = shallow(renderTabContentResult)
assert.equal(renderedTabContent.childAt(1).text(), 'info-row--fade,originalTotal,$20.02 USD,0.06685 ETH')
assert.equal(renderedTabContent.childAt(2).text(), 'info-row,newTotal,$20.02 USD,0.06685 ETH')
GP.renderInfoRow.restore()
})
})
describe('renderInfoRow', () => {
it('should render a div with the passed className and two children, each with the expected text', () => {
const renderInfoRowResult = wrapper.instance().renderInfoRow('mockClassName', 'mockLabelKey', 'mockFiatAmount', 'mockCryptoAmount')
const renderedInfoRow = shallow(renderInfoRowResult)
assert.equal(renderedInfoRow.props().className, 'mockClassName')
const firstChild = renderedInfoRow.childAt(0)
const secondhild = renderedInfoRow.childAt(1)
assert.equal(firstChild.props().className, 'total-info')
assert.equal(secondhild.props().className, 'sum-info')
assert.equal(firstChild.childAt(0).text(), 'mockLabelKey:')
assert.equal(firstChild.childAt(1).text(), 'mockFiatAmount')
assert.equal(secondhild.childAt(0).text(), 'amountPlusTxFee')
assert.equal(secondhild.childAt(1).text(), 'mockCryptoAmount')
})
})
describe('renderBasicTabContent', () => {
it('should render', () => {
const renderBasicTabContentResult = wrapper.instance().renderBasicTabContent()
const renderedBasicTabContent = shallow(renderBasicTabContentResult)
assert.equal(renderedBasicTabContent.props().className, 'basic-tab')
})
})
describe('renderAdvancedTabContent', () => {
it('should render', () => {
const renderAdvancedTabContentResult = wrapper.instance().renderAdvancedTabContent()
const renderedAdvancedTabContent = shallow(renderAdvancedTabContentResult)
assert.equal(renderedAdvancedTabContent.props().className, 'advanced-tab')
})
})
})

@ -0,0 +1,44 @@
import assert from 'assert'
import proxyquire from 'proxyquire'
import sinon from 'sinon'
// let mapStateToProps
let mapDispatchToProps
const actionSpies = {
hideModal: sinon.spy(),
}
proxyquire('../gas-modal-page-container.container.js', {
'react-redux': {
connect: (ms, md) => {
// mapStateToProps = ms
mapDispatchToProps = md
return () => ({})
},
},
'../../../actions': actionSpies,
})
describe('gas-modal-page-container container', () => {
describe('mapDispatchToProps()', () => {
let dispatchSpy
let mapDispatchToPropsObject
beforeEach(() => {
dispatchSpy = sinon.spy()
mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy)
})
describe('hideModal()', () => {
it('should dispatch a hideModal action', () => {
mapDispatchToPropsObject.hideModal()
assert(dispatchSpy.calledOnce)
assert(actionSpies.hideModal.calledOnce)
})
})
})
})

@ -63,3 +63,5 @@
@import './sidebars/index'; @import './sidebars/index';
@import './unit-input/index'; @import './unit-input/index';
@import './gas-customization/gas-modal-page-container/index'

@ -17,18 +17,17 @@ const ExportPrivateKeyModal = require('./export-private-key-modal')
const NewAccountModal = require('./new-account-modal') const NewAccountModal = require('./new-account-modal')
const ShapeshiftDepositTxModal = require('./shapeshift-deposit-tx-modal.js') const ShapeshiftDepositTxModal = require('./shapeshift-deposit-tx-modal.js')
const HideTokenConfirmationModal = require('./hide-token-confirmation-modal') const HideTokenConfirmationModal = require('./hide-token-confirmation-modal')
const CustomizeGasModal = require('../customize-gas-modal')
const NotifcationModal = require('./notification-modal') const NotifcationModal = require('./notification-modal')
const QRScanner = require('./qr-scanner') const QRScanner = require('./qr-scanner')
import ConfirmRemoveAccount from './confirm-remove-account' import ConfirmRemoveAccount from './confirm-remove-account'
import ConfirmResetAccount from './confirm-reset-account' import ConfirmResetAccount from './confirm-reset-account'
import TransactionConfirmed from './transaction-confirmed' import TransactionConfirmed from './transaction-confirmed'
import ConfirmCustomizeGasModal from './customize-gas'
import CancelTransaction from './cancel-transaction' import CancelTransaction from './cancel-transaction'
import WelcomeBeta from './welcome-beta' import WelcomeBeta from './welcome-beta'
import RejectTransactions from './reject-transactions' import RejectTransactions from './reject-transactions'
import ClearApprovedOrigins from './clear-approved-origins' import ClearApprovedOrigins from './clear-approved-origins'
import ConfirmCustomizeGasModal from '../gas-customization/gas-modal-page-container'
const modalContainerBaseStyle = { const modalContainerBaseStyle = {
transform: 'translate3d(-50%, 0, 0px)', transform: 'translate3d(-50%, 0, 0px)',
@ -295,7 +294,7 @@ const MODALS = {
CUSTOMIZE_GAS: { CUSTOMIZE_GAS: {
contents: [ contents: [
h(CustomizeGasModal), h(ConfirmCustomizeGasModal),
], ],
mobileModalStyle: { mobileModalStyle: {
width: '100vw', width: '100vw',
@ -307,35 +306,16 @@ const MODALS = {
margin: '0 auto', margin: '0 auto',
}, },
laptopModalStyle: { laptopModalStyle: {
width: '720px', width: 'auto',
height: '377px', height: '0px',
top: '80px', top: '80px',
left: '0px',
transform: 'none', transform: 'none',
left: '0',
right: '0',
margin: '0 auto', margin: '0 auto',
position: 'relative',
}, },
}, contentStyle: {
borderRadius: '8px',
CONFIRM_CUSTOMIZE_GAS: {
contents: h(ConfirmCustomizeGasModal),
mobileModalStyle: {
width: '100vw',
height: '100vh',
top: '0',
transform: 'none',
left: '0',
right: '0',
margin: '0 auto',
},
laptopModalStyle: {
width: '720px',
height: '377px',
top: '80px',
transform: 'none',
left: '0',
right: '0',
margin: '0 auto',
}, },
}, },

@ -117,7 +117,7 @@ const mapDispatchToProps = dispatch => {
return dispatch(showModal({ name: 'TRANSACTION_CONFIRMED', onSubmit })) return dispatch(showModal({ name: 'TRANSACTION_CONFIRMED', onSubmit }))
}, },
showCustomizeGasModal: ({ txData, onSubmit, validate }) => { showCustomizeGasModal: ({ txData, onSubmit, validate }) => {
return dispatch(showModal({ name: 'CONFIRM_CUSTOMIZE_GAS', txData, onSubmit, validate })) return dispatch(showModal({ name: 'CUSTOMIZE_GAS', txData, onSubmit, validate }))
}, },
updateGasAndCalculate: ({ gasLimit, gasPrice }) => { updateGasAndCalculate: ({ gasLimit, gasPrice }) => {
return dispatch(updateGasAndCalculate({ gasLimit, gasPrice })) return dispatch(updateGasAndCalculate({ gasLimit, gasPrice }))

@ -56,6 +56,7 @@ $zumthor: #edf7ff;
$ecstasy: #f7861c; $ecstasy: #f7861c;
$linen: #fdf4f4; $linen: #fdf4f4;
$oslo-gray: #8C8E94; $oslo-gray: #8C8E94;
$polar: #fafcfe;
/* /*
Z-Indicies Z-Indicies

Loading…
Cancel
Save