Add loading spinners when waiting for APIs in the gas customization modal

feature/default_network_editable
Dan Miller 6 years ago
parent 7f2c5c09de
commit 7ffea926f2
  1. 8
      ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js
  2. 17
      ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/tests/advanced-tab-content-component.test.js
  3. 10
      ui/app/components/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content.component.js
  4. 11
      ui/app/components/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js
  5. 2
      ui/app/components/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js
  6. 4
      ui/app/components/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js
  7. 2
      ui/app/components/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-component.test.js
  8. 2
      ui/app/components/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js
  9. 5
      ui/app/selectors/custom-gas.js

@ -1,6 +1,7 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import classnames from 'classnames' import classnames from 'classnames'
import Loading from '../../../loading-screen'
import GasPriceChart from '../../gas-price-chart' import GasPriceChart from '../../gas-price-chart'
export default class AdvancedTabContent extends Component { export default class AdvancedTabContent extends Component {
@ -13,6 +14,7 @@ export default class AdvancedTabContent extends Component {
updateCustomGasLimit: PropTypes.func, updateCustomGasLimit: PropTypes.func,
customGasPrice: PropTypes.number, customGasPrice: PropTypes.number,
customGasLimit: PropTypes.number, customGasLimit: PropTypes.number,
gasEstimatesLoading: PropTypes.bool,
millisecondsRemaining: PropTypes.number, millisecondsRemaining: PropTypes.number,
totalFee: PropTypes.string, totalFee: PropTypes.string,
timeRemaining: PropTypes.string, timeRemaining: PropTypes.string,
@ -98,6 +100,7 @@ export default class AdvancedTabContent extends Component {
insufficientBalance, insufficientBalance,
totalFee, totalFee,
gasChartProps, gasChartProps,
gasEstimatesLoading,
} = this.props } = this.props
return ( return (
@ -112,7 +115,10 @@ export default class AdvancedTabContent extends Component {
insufficientBalance insufficientBalance
) } ) }
<div className="advanced-tab__fee-chart__title">Live Gas Price Predictions</div> <div className="advanced-tab__fee-chart__title">Live Gas Price Predictions</div>
<GasPriceChart {...gasChartProps} updateCustomGasPrice={updateCustomGasPrice} /> {!gasEstimatesLoading
? <GasPriceChart {...gasChartProps} updateCustomGasPrice={updateCustomGasPrice} />
: <Loading />
}
<div className="advanced-tab__fee-chart__speed-buttons"> <div className="advanced-tab__fee-chart__speed-buttons">
<span>Slower</span> <span>Slower</span>
<span>Faster</span> <span>Faster</span>

@ -5,6 +5,7 @@ import sinon from 'sinon'
import AdvancedTabContent from '../advanced-tab-content.component.js' import AdvancedTabContent from '../advanced-tab-content.component.js'
import GasPriceChart from '../../../gas-price-chart' import GasPriceChart from '../../../gas-price-chart'
import Loading from '../../../../loading-screen'
const propsMethodSpies = { const propsMethodSpies = {
updateCustomGasPrice: sinon.spy(), updateCustomGasPrice: sinon.spy(),
@ -60,6 +61,22 @@ describe('AdvancedTabContent Component', function () {
assert(feeChartDiv.childAt(3).hasClass('advanced-tab__fee-chart__speed-buttons')) assert(feeChartDiv.childAt(3).hasClass('advanced-tab__fee-chart__speed-buttons'))
}) })
it('should render a loading component instead of the chart if gasEstimatesLoading is true', () => {
wrapper.setProps({ gasEstimatesLoading: true })
const advancedTabChildren = wrapper.children()
assert.equal(advancedTabChildren.length, 2)
assert(advancedTabChildren.at(0).hasClass('advanced-tab__transaction-data-summary'))
assert(advancedTabChildren.at(1).hasClass('advanced-tab__fee-chart'))
const feeChartDiv = advancedTabChildren.at(1)
assert(feeChartDiv.childAt(0).hasClass('advanced-tab__gas-edit-rows'))
assert(feeChartDiv.childAt(1).hasClass('advanced-tab__fee-chart__title'))
assert(feeChartDiv.childAt(2).is(Loading))
assert(feeChartDiv.childAt(3).hasClass('advanced-tab__fee-chart__speed-buttons'))
})
it('should call renderDataSummary with the expected params', () => { it('should call renderDataSummary with the expected params', () => {
assert.equal(AdvancedTabContent.prototype.renderGasEditRows.callCount, 1) assert.equal(AdvancedTabContent.prototype.renderGasEditRows.callCount, 1)
const renderDataSummaryArgs = AdvancedTabContent.prototype.renderDataSummary.getCall(0).args const renderDataSummaryArgs = AdvancedTabContent.prototype.renderDataSummary.getCall(0).args

@ -1,5 +1,6 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import Loading from '../../../loading-screen'
import GasPriceButtonGroup from '../../gas-price-button-group' import GasPriceButtonGroup from '../../gas-price-button-group'
export default class BasicTabContent extends Component { export default class BasicTabContent extends Component {
@ -12,15 +13,20 @@ export default class BasicTabContent extends Component {
} }
render () { render () {
const { gasPriceButtonGroupProps } = this.props
return ( return (
<div className="basic-tab-content"> <div className="basic-tab-content">
<div className="basic-tab-content__title">Estimated Processing Times</div> <div className="basic-tab-content__title">Estimated Processing Times</div>
<div className="basic-tab-content__blurb">Select a higher gas fee to accelerate the processing of your transaction.*</div> <div className="basic-tab-content__blurb">Select a higher gas fee to accelerate the processing of your transaction.*</div>
<GasPriceButtonGroup {!gasPriceButtonGroupProps.loading
? <GasPriceButtonGroup
className="gas-price-button-group--alt" className="gas-price-button-group--alt"
showCheck={true} showCheck={true}
{...this.props.gasPriceButtonGroupProps} {...gasPriceButtonGroupProps}
/> />
: <Loading />
}
<div className="basic-tab-content__footer-blurb">* Accelerating a transaction by using a higher gas price increases its chances of getting processed by the network faster, but it is not always guaranteed.</div> <div className="basic-tab-content__footer-blurb">* Accelerating a transaction by using a higher gas price increases its chances of getting processed by the network faster, but it is not always guaranteed.</div>
</div> </div>
) )

@ -4,6 +4,7 @@ import { shallow } from 'enzyme'
import BasicTabContent from '../basic-tab-content.component' import BasicTabContent from '../basic-tab-content.component'
import GasPriceButtonGroup from '../../../gas-price-button-group/' import GasPriceButtonGroup from '../../../gas-price-button-group/'
import Loading from '../../../../loading-screen'
const mockGasPriceButtonGroupProps = { const mockGasPriceButtonGroupProps = {
buttonDataLoading: false, buttonDataLoading: false,
@ -60,6 +61,7 @@ describe('BasicTabContent Component', function () {
noButtonActiveByDefault, noButtonActiveByDefault,
showCheck, showCheck,
} = wrapper.find(GasPriceButtonGroup).props() } = wrapper.find(GasPriceButtonGroup).props()
assert.equal(wrapper.find(GasPriceButtonGroup).length, 1)
assert.equal(buttonDataLoading, mockGasPriceButtonGroupProps.buttonDataLoading) assert.equal(buttonDataLoading, mockGasPriceButtonGroupProps.buttonDataLoading)
assert.equal(className, mockGasPriceButtonGroupProps.className) assert.equal(className, mockGasPriceButtonGroupProps.className)
assert.equal(noButtonActiveByDefault, mockGasPriceButtonGroupProps.noButtonActiveByDefault) assert.equal(noButtonActiveByDefault, mockGasPriceButtonGroupProps.noButtonActiveByDefault)
@ -67,5 +69,14 @@ describe('BasicTabContent Component', function () {
assert.deepEqual(gasButtonInfo, mockGasPriceButtonGroupProps.gasButtonInfo) assert.deepEqual(gasButtonInfo, mockGasPriceButtonGroupProps.gasButtonInfo)
assert.equal(JSON.stringify(handleGasPriceSelection), JSON.stringify(mockGasPriceButtonGroupProps.handleGasPriceSelection)) assert.equal(JSON.stringify(handleGasPriceSelection), JSON.stringify(mockGasPriceButtonGroupProps.handleGasPriceSelection))
}) })
it('should render a loading component instead of the GasPriceButtonGroup if gasPriceButtonGroupProps.loading is true', () => {
wrapper.setProps({
gasPriceButtonGroupProps: { ...mockGasPriceButtonGroupProps, loading: true },
})
assert.equal(wrapper.find(GasPriceButtonGroup).length, 0)
assert.equal(wrapper.find(Loading).length, 1)
})
}) })
}) })

@ -68,6 +68,7 @@ export default class GasModalPageContainer extends Component {
gasChartProps, gasChartProps,
currentTimeEstimate, currentTimeEstimate,
insufficientBalance, insufficientBalance,
gasEstimatesLoading,
}) { }) {
const { transactionFee } = this.props const { transactionFee } = this.props
return ( return (
@ -81,6 +82,7 @@ export default class GasModalPageContainer extends Component {
totalFee={newTotalFiat} totalFee={newTotalFiat}
gasChartProps={gasChartProps} gasChartProps={gasChartProps}
insufficientBalance={insufficientBalance} insufficientBalance={insufficientBalance}
gasEstimatesLoading={gasEstimatesLoading}
/> />
) )
} }

@ -32,6 +32,7 @@ import {
formatTimeEstimate, formatTimeEstimate,
getFastPriceEstimateInHexWEI, getFastPriceEstimateInHexWEI,
getBasicGasEstimateLoadingStatus, getBasicGasEstimateLoadingStatus,
getGasEstimatesLoadingStatus,
getCustomGasLimit, getCustomGasLimit,
getCustomGasPrice, getCustomGasPrice,
getDefaultActiveButtonIndex, getDefaultActiveButtonIndex,
@ -65,6 +66,8 @@ import { getAdjacentGasPrices, extrapolateY } from '../gas-price-chart/gas-price
const mapStateToProps = (state, ownProps) => { const mapStateToProps = (state, ownProps) => {
const { transaction = {} } = ownProps const { transaction = {} } = ownProps
const buttonDataLoading = getBasicGasEstimateLoadingStatus(state) const buttonDataLoading = getBasicGasEstimateLoadingStatus(state)
const gasEstimatesLoading = getGasEstimatesLoadingStatus(state)
const { gasPrice: currentGasPrice, gas: currentGasLimit, value } = getTxParams(state, transaction.id) const { gasPrice: currentGasPrice, gas: currentGasLimit, value } = getTxParams(state, transaction.id)
const customModalGasPriceInHex = getCustomGasPrice(state) || currentGasPrice const customModalGasPriceInHex = getCustomGasPrice(state) || currentGasPrice
const customModalGasLimitInHex = getCustomGasLimit(state) || currentGasLimit const customModalGasLimitInHex = getCustomGasLimit(state) || currentGasLimit
@ -127,6 +130,7 @@ const mapStateToProps = (state, ownProps) => {
isSpeedUp: transaction.status === 'submitted', isSpeedUp: transaction.status === 'submitted',
txId: transaction.id, txId: transaction.id,
insufficientBalance, insufficientBalance,
gasEstimatesLoading,
} }
} }

@ -232,6 +232,7 @@ describe('GasModalPageContainer Component', function () {
customGasLimit: 456, customGasLimit: 456,
newTotalFiat: '$0.30', newTotalFiat: '$0.30',
currentTimeEstimate: '1 min 31 sec', currentTimeEstimate: '1 min 31 sec',
gasEstimatesLoading: 'mockGasEstimatesLoading',
}) })
const advancedTabContentProps = renderAdvancedTabContentResult.props const advancedTabContentProps = renderAdvancedTabContentResult.props
assert.equal(advancedTabContentProps.updateCustomGasPrice(), 'mockConvertThenUpdateCustomGasPrice') assert.equal(advancedTabContentProps.updateCustomGasPrice(), 'mockConvertThenUpdateCustomGasPrice')
@ -240,6 +241,7 @@ describe('GasModalPageContainer Component', function () {
assert.equal(advancedTabContentProps.customGasLimit, 456) assert.equal(advancedTabContentProps.customGasLimit, 456)
assert.equal(advancedTabContentProps.timeRemaining, '1 min 31 sec') assert.equal(advancedTabContentProps.timeRemaining, '1 min 31 sec')
assert.equal(advancedTabContentProps.totalFee, '$0.30') assert.equal(advancedTabContentProps.totalFee, '$0.30')
assert.equal(advancedTabContentProps.gasEstimatesLoading, 'mockGasEstimatesLoading')
}) })
}) })

@ -80,6 +80,7 @@ describe('gas-modal-page-container container', () => {
limit: 'aaaaaaaa', limit: 'aaaaaaaa',
price: 'ffffffff', price: 'ffffffff',
}, },
gasEstimatesLoading: false,
priceAndTimeEstimates: [ priceAndTimeEstimates: [
{ gasprice: 3, expectedTime: '31' }, { gasprice: 3, expectedTime: '31' },
{ gasprice: 4, expectedTime: '62' }, { gasprice: 4, expectedTime: '62' },
@ -118,6 +119,7 @@ describe('gas-modal-page-container container', () => {
defaultActiveButtonIndex: 'mockRenderableBasicEstimateData:4ffffffff', defaultActiveButtonIndex: 'mockRenderableBasicEstimateData:4ffffffff',
gasButtonInfo: 'mockRenderableBasicEstimateData:4', gasButtonInfo: 'mockRenderableBasicEstimateData:4',
}, },
gasEstimatesLoading: false,
hideBasic: true, hideBasic: true,
infoRowProps: { infoRowProps: {
originalTotalFiat: '637.41', originalTotalFiat: '637.41',

@ -33,6 +33,7 @@ const selectors = {
getDefaultActiveButtonIndex, getDefaultActiveButtonIndex,
getEstimatedGasPrices, getEstimatedGasPrices,
getEstimatedGasTimes, getEstimatedGasTimes,
getGasEstimatesLoadingStatus,
getPriceAndTimeEstimates, getPriceAndTimeEstimates,
getRenderableBasicEstimateData, getRenderableBasicEstimateData,
getRenderableEstimateDataForSmallButtonsFromGWEI, getRenderableEstimateDataForSmallButtonsFromGWEI,
@ -63,6 +64,10 @@ function getBasicGasEstimateLoadingStatus (state) {
return state.gas.basicEstimateIsLoading return state.gas.basicEstimateIsLoading
} }
function getGasEstimatesLoadingStatus (state) {
return state.gas.gasEstimatesLoading
}
function getPriceAndTimeEstimates (state) { function getPriceAndTimeEstimates (state) {
return state.gas.priceAndTimeEstimates return state.gas.priceAndTimeEstimates
} }

Loading…
Cancel
Save