From d8e41a6aa5a4c64538063c6dde7afdf77b0e5793 Mon Sep 17 00:00:00 2001 From: Dan Miller Date: Tue, 27 Nov 2018 14:00:41 -0330 Subject: Final gas customization fixes --- .../advanced-tab-content.component.js | 26 ++++++--- .../advanced-tab-content/index.scss | 1 + .../tests/advanced-tab-content-component.test.js | 16 ++++-- .../gas-modal-page-container.component.js | 3 +- .../gas-modal-page-container.container.js | 29 ++++++++-- .../gas-modal-page-container/index.scss | 1 + .../gas-modal-page-container-container.test.js | 18 +++++-- .../gas-price-button-group/index.scss | 2 +- .../gas-price-chart/gas-price-chart.component.js | 2 +- .../gas-price-chart/gas-price-chart.utils.js | 54 ++++++++++++------- ui/app/components/modals/modal.js | 2 +- .../page-container-footer.component.js | 2 +- ui/app/components/sidebars/sidebar-content.scss | 40 +++++++++++--- ui/app/ducks/gas.duck.js | 15 ++++-- ui/app/ducks/tests/gas-duck.test.js | 16 +++--- ui/app/selectors/custom-gas.js | 61 +++++++++------------- ui/app/selectors/tests/custom-gas.test.js | 12 ++--- 17 files changed, 197 insertions(+), 103 deletions(-) (limited to 'ui/app') diff --git a/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js b/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js index ac68b833c..ba738ff75 100644 --- a/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js +++ b/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types' import classnames from 'classnames' import Loading from '../../../loading-screen' import GasPriceChart from '../../gas-price-chart' +import debounce from 'lodash.debounce' export default class AdvancedTabContent extends Component { static contextTypes = { @@ -22,7 +23,21 @@ export default class AdvancedTabContent extends Component { insufficientBalance: PropTypes.bool, } - gasInput (value, onChange, min, insufficientBalance, precision, showGWEI) { + constructor (props) { + super(props) + + this.debouncedGasLimitReset = debounce((dVal) => { + if (dVal < 21000) { + props.updateCustomGasLimit(21000) + } + }, 1000, { trailing: true }) + this.onChangeGasLimit = (val) => { + props.updateCustomGasLimit(val) + this.debouncedGasLimitReset(val) + } + } + + gasInput (value, onChange, min, insufficientBalance, showGWEI) { return (
onChange(Number(event.target.value))} />
-
onChange(value + 1)} />
-
onChange(value - 1)} />
+
onChange(value + 1)}>
+
onChange(value - 1)}>
{insufficientBalance &&
Insufficient Balance @@ -84,8 +98,8 @@ export default class AdvancedTabContent extends Component { renderGasEditRows (customGasPrice, updateCustomGasPrice, customGasLimit, updateCustomGasLimit, insufficientBalance) { return (
- { this.renderGasEditRow('gasPrice', customGasPrice, updateCustomGasPrice, customGasPrice, insufficientBalance, 9, true) } - { this.renderGasEditRow('gasLimit', customGasLimit, updateCustomGasLimit, customGasLimit, insufficientBalance, 0) } + { this.renderGasEditRow('gasPrice', customGasPrice, updateCustomGasPrice, customGasPrice, insufficientBalance, true) } + { this.renderGasEditRow('gasLimit', customGasLimit, this.onChangeGasLimit, customGasLimit, insufficientBalance) }
) } diff --git a/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/index.scss b/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/index.scss index b62919c0a..88c69faf4 100644 --- a/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/index.scss +++ b/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/index.scss @@ -148,6 +148,7 @@ height: 100%; display: flex; justify-content: center; + cursor: pointer; } &__i-wrap:hover { diff --git a/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/tests/advanced-tab-content-component.test.js b/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/tests/advanced-tab-content-component.test.js index f321ca696..d6920454d 100644 --- a/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/tests/advanced-tab-content-component.test.js +++ b/ui/app/components/gas-customization/gas-modal-page-container/advanced-tab-content/tests/advanced-tab-content-component.test.js @@ -155,8 +155,11 @@ describe('AdvancedTabContent Component', function () { describe('renderGasEditRows()', () => { let gasEditRows + let tempOnChangeGasLimit beforeEach(() => { + tempOnChangeGasLimit = wrapper.instance().onChangeGasLimit + wrapper.instance().onChangeGasLimit = () => 'mockOnChangeGasLimit' AdvancedTabContent.prototype.renderGasEditRow.resetHistory() gasEditRows = shallow(wrapper.instance().renderGasEditRows( 'mockGasPrice', @@ -167,6 +170,10 @@ describe('AdvancedTabContent Component', function () { )) }) + afterEach(() => { + wrapper.instance().onChangeGasLimit = tempOnChangeGasLimit + }) + it('should render the gas-edit-rows root node', () => { assert(gasEditRows.hasClass('advanced-tab__gas-edit-rows')) }) @@ -182,10 +189,10 @@ describe('AdvancedTabContent Component', function () { const renderGasEditRowSpyArgs = AdvancedTabContent.prototype.renderGasEditRow.args assert.equal(renderGasEditRowSpyArgs.length, 2) assert.deepEqual(renderGasEditRowSpyArgs[0].map(String), [ - 'gasPrice', 'mockGasPrice', () => 'mockUpdateCustomGasPriceReturn', 'mockGasPrice', false, 9, true, + 'gasPrice', 'mockGasPrice', () => 'mockUpdateCustomGasPriceReturn', 'mockGasPrice', false, true, ].map(String)) assert.deepEqual(renderGasEditRowSpyArgs[1].map(String), [ - 'gasLimit', 'mockGasLimit', () => 'mockUpdateCustomGasLimitReturn', 'mockGasLimit', false, 0, + 'gasLimit', 'mockGasLimit', () => 'mockOnChangeGasLimit', 'mockGasLimit', false, ].map(String)) }) }) @@ -234,7 +241,6 @@ describe('AdvancedTabContent Component', function () { const inputProps = gasInput.find('input').props() assert.equal(inputProps.min, 0) assert.equal(inputProps.value, 321) - assert.equal(inputProps.precision, 8) }) it('should call the passed onChange method with the value of the input onChange event', () => { @@ -257,9 +263,9 @@ describe('AdvancedTabContent Component', function () { 8, false )) - const upArrow = gasInput.find('.fa-angle-up') + const upArrow = gasInput.find('.advanced-tab__gas-edit-row__input-arrows__i-wrap').at(0) assert.equal(upArrow.props().onClick(), 329) - const downArrow = gasInput.find('.fa-angle-down') + const downArrow = gasInput.find('.advanced-tab__gas-edit-row__input-arrows__i-wrap').at(1) assert.equal(downArrow.props().onClick(), 327) }) }) diff --git a/ui/app/components/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js b/ui/app/components/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js index 5d8f92a59..be91bef0f 100644 --- a/ui/app/components/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js +++ b/ui/app/components/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js @@ -89,7 +89,7 @@ export default class GasModalPageContainer extends Component { renderInfoRows (newTotalFiat, newTotalEth, sendAmount, transactionFee) { return ( -
+
{this.context.t('sendAmount')} @@ -167,7 +167,6 @@ export default class GasModalPageContainer extends Component { onClose={() => cancelAndClose()} onSubmit={() => { onSubmit(customModalGasLimitInHex, customModalGasPriceInHex) - cancelAndClose() }} submitText={this.context.t('save')} headerCloseText={'Close'} diff --git a/ui/app/components/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js b/ui/app/components/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js index 42b96a729..c619a0988 100644 --- a/ui/app/components/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js +++ b/ui/app/components/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js @@ -142,6 +142,7 @@ const mapDispatchToProps = dispatch => { dispatch(resetCustomData()) dispatch(hideModal()) }, + hideModal: () => dispatch(hideModal()), updateCustomGasPrice, convertThenUpdateCustomGasPrice: newPrice => updateCustomGasPrice(decGWEIToHexWEI(newPrice)), convertThenUpdateCustomGasLimit: newLimit => dispatch(setCustomGasLimit(addHexPrefix(newLimit.toString(16)))), @@ -150,6 +151,8 @@ const mapDispatchToProps = dispatch => { dispatch(setGasPrice(newPrice)) }, updateConfirmTxGasAndCalculate: (gasLimit, gasPrice) => { + updateCustomGasPrice(gasPrice) + dispatch(setCustomGasLimit(addHexPrefix(gasLimit.toString(16)))) return dispatch(updateGasAndCalculate({ gasLimit, gasPrice })) }, createSpeedUpTransaction: (txId, gasPrice) => { @@ -172,6 +175,8 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { updateConfirmTxGasAndCalculate: dispatchUpdateConfirmTxGasAndCalculate, createSpeedUpTransaction: dispatchCreateSpeedUpTransaction, hideSidebar: dispatchHideSidebar, + cancelAndClose: dispatchCancelAndClose, + hideModal: dispatchHideModal, ...otherDispatchProps } = dispatchProps @@ -182,18 +187,27 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { onSubmit: (gasLimit, gasPrice) => { if (isConfirm) { dispatchUpdateConfirmTxGasAndCalculate(gasLimit, gasPrice) + dispatchHideModal() } else if (isSpeedUp) { dispatchCreateSpeedUpTransaction(txId, gasPrice) dispatchHideSidebar() + dispatchCancelAndClose() } else { dispatchSetGasData(gasLimit, gasPrice) dispatchHideGasButtonGroup() + dispatchCancelAndClose() } }, gasPriceButtonGroupProps: { ...gasPriceButtonGroupProps, handleGasPriceSelection: dispatchUpdateCustomGasPrice, }, + cancelAndClose: () => { + dispatchCancelAndClose() + if (isSpeedUp) { + dispatchHideSidebar() + } + }, } } @@ -241,20 +255,29 @@ function addHexWEIsToRenderableFiat (aHexWEI, bHexWEI, convertedCurrency, conver } function getRenderableTimeEstimate (currentGasPrice, gasPrices, estimatedTimes) { + const minGasPrice = gasPrices[0] + const maxGasPrice = gasPrices[gasPrices.length - 1] + let priceForEstimation = currentGasPrice + if (currentGasPrice < minGasPrice) { + priceForEstimation = minGasPrice + } else if (currentGasPrice > maxGasPrice) { + priceForEstimation = maxGasPrice + } + const { closestLowerValueIndex, closestHigherValueIndex, closestHigherValue, closestLowerValue, - } = getAdjacentGasPrices({ gasPrices, priceToPosition: currentGasPrice }) + } = getAdjacentGasPrices({ gasPrices, priceToPosition: priceForEstimation }) const newTimeEstimate = extrapolateY({ higherY: estimatedTimes[closestHigherValueIndex], lowerY: estimatedTimes[closestLowerValueIndex], higherX: closestHigherValue, lowerX: closestLowerValue, - xForExtrapolation: currentGasPrice, + xForExtrapolation: priceForEstimation, }) - return formatTimeEstimate(newTimeEstimate) + return formatTimeEstimate(newTimeEstimate, currentGasPrice > maxGasPrice, currentGasPrice < minGasPrice) } diff --git a/ui/app/components/gas-customization/gas-modal-page-container/index.scss b/ui/app/components/gas-customization/gas-modal-page-container/index.scss index 2532c1fc2..6c76f1bdd 100644 --- a/ui/app/components/gas-customization/gas-modal-page-container/index.scss +++ b/ui/app/components/gas-customization/gas-modal-page-container/index.scss @@ -44,6 +44,7 @@ display: flex; justify-content: center; align-items: flex-start; + margin-right: 0; } &__subtitle { diff --git a/ui/app/components/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js b/ui/app/components/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js index 82c6dcd69..512832866 100644 --- a/ui/app/components/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js +++ b/ui/app/components/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js @@ -82,10 +82,10 @@ describe('gas-modal-page-container container', () => { }, gasEstimatesLoading: false, priceAndTimeEstimates: [ - { gasprice: 3, expectedTime: '31' }, - { gasprice: 4, expectedTime: '62' }, - { gasprice: 5, expectedTime: '93' }, - { gasprice: 6, expectedTime: '124' }, + { gasprice: 3, expectedTime: 31 }, + { gasprice: 4, expectedTime: 62 }, + { gasprice: 5, expectedTime: 93 }, + { gasprice: 6, expectedTime: 124 }, ], }, confirmTransaction: { @@ -235,7 +235,7 @@ describe('gas-modal-page-container container', () => { describe('updateConfirmTxGasAndCalculate()', () => { it('should dispatch a updateGasAndCalculate action with the correct props', () => { mapDispatchToPropsObject.updateConfirmTxGasAndCalculate('ffff', 'aaaa') - assert(dispatchSpy.calledOnce) + assert.equal(dispatchSpy.callCount, 3) assert(confirmTransactionActionSpies.updateGasAndCalculate.calledOnce) assert.deepEqual(confirmTransactionActionSpies.updateGasAndCalculate.getCall(0).args[0], { gasLimit: 'ffff', gasPrice: 'aaaa' }) }) @@ -265,6 +265,8 @@ describe('gas-modal-page-container container', () => { someOtherDispatchProp: sinon.spy(), createSpeedUpTransaction: sinon.spy(), hideSidebar: sinon.spy(), + hideModal: sinon.spy(), + cancelAndClose: sinon.spy(), } ownProps = { someOwnProp: 123 } }) @@ -277,6 +279,7 @@ describe('gas-modal-page-container container', () => { dispatchProps.someOtherDispatchProp.resetHistory() dispatchProps.createSpeedUpTransaction.resetHistory() dispatchProps.hideSidebar.resetHistory() + dispatchProps.hideModal.resetHistory() }) it('should return the expected props when isConfirm is true', () => { const result = mergeProps(stateProps, dispatchProps, ownProps) @@ -290,12 +293,14 @@ describe('gas-modal-page-container container', () => { assert.equal(dispatchProps.updateConfirmTxGasAndCalculate.callCount, 0) assert.equal(dispatchProps.setGasData.callCount, 0) assert.equal(dispatchProps.hideGasButtonGroup.callCount, 0) + assert.equal(dispatchProps.hideModal.callCount, 0) result.onSubmit() assert.equal(dispatchProps.updateConfirmTxGasAndCalculate.callCount, 1) assert.equal(dispatchProps.setGasData.callCount, 0) assert.equal(dispatchProps.hideGasButtonGroup.callCount, 0) + assert.equal(dispatchProps.hideModal.callCount, 1) assert.equal(dispatchProps.updateCustomGasPrice.callCount, 0) result.gasPriceButtonGroupProps.handleGasPriceSelection() @@ -318,6 +323,7 @@ describe('gas-modal-page-container container', () => { assert.equal(dispatchProps.updateConfirmTxGasAndCalculate.callCount, 0) assert.equal(dispatchProps.setGasData.callCount, 0) assert.equal(dispatchProps.hideGasButtonGroup.callCount, 0) + assert.equal(dispatchProps.cancelAndClose.callCount, 0) result.onSubmit('mockNewLimit', 'mockNewPrice') @@ -325,6 +331,7 @@ describe('gas-modal-page-container container', () => { assert.equal(dispatchProps.setGasData.callCount, 1) assert.deepEqual(dispatchProps.setGasData.getCall(0).args, ['mockNewLimit', 'mockNewPrice']) assert.equal(dispatchProps.hideGasButtonGroup.callCount, 1) + assert.equal(dispatchProps.cancelAndClose.callCount, 1) assert.equal(dispatchProps.updateCustomGasPrice.callCount, 0) result.gasPriceButtonGroupProps.handleGasPriceSelection() @@ -343,6 +350,7 @@ describe('gas-modal-page-container container', () => { assert.equal(dispatchProps.updateConfirmTxGasAndCalculate.callCount, 0) assert.equal(dispatchProps.setGasData.callCount, 0) assert.equal(dispatchProps.hideGasButtonGroup.callCount, 0) + assert.equal(dispatchProps.cancelAndClose.callCount, 1) assert.equal(dispatchProps.createSpeedUpTransaction.callCount, 1) assert.equal(dispatchProps.hideSidebar.callCount, 1) diff --git a/ui/app/components/gas-customization/gas-price-button-group/index.scss b/ui/app/components/gas-customization/gas-price-button-group/index.scss index 6e9d01c6e..0d1450594 100644 --- a/ui/app/components/gas-customization/gas-price-button-group/index.scss +++ b/ui/app/components/gas-customization/gas-price-button-group/index.scss @@ -137,7 +137,7 @@ .gas-price-button-group--alt { display: flex; justify-content: stretch; - max-width: 342px; + width: 95%; &__button-fiat-price { font-size: 13px; diff --git a/ui/app/components/gas-customization/gas-price-chart/gas-price-chart.component.js b/ui/app/components/gas-customization/gas-price-chart/gas-price-chart.component.js index 3f382e5b2..d4c67bbde 100644 --- a/ui/app/components/gas-customization/gas-price-chart/gas-price-chart.component.js +++ b/ui/app/components/gas-customization/gas-price-chart/gas-price-chart.component.js @@ -19,7 +19,7 @@ export default class GasPriceChart extends Component { gasPrices: PropTypes.array, estimatedTimes: PropTypes.array, gasPricesMax: PropTypes.number, - estimatedTimesMax: PropTypes.string, + estimatedTimesMax: PropTypes.number, currentPrice: PropTypes.number, updateCustomGasPrice: PropTypes.func, } diff --git a/ui/app/components/gas-customization/gas-price-chart/gas-price-chart.utils.js b/ui/app/components/gas-customization/gas-price-chart/gas-price-chart.utils.js index 0b9dfbd11..f19dafcc1 100644 --- a/ui/app/components/gas-customization/gas-price-chart/gas-price-chart.utils.js +++ b/ui/app/components/gas-customization/gas-price-chart/gas-price-chart.utils.js @@ -1,5 +1,11 @@ import * as d3 from 'd3' import c3 from 'c3' +import BigNumber from 'bignumber.js' + +const newBigSigDig = n => (new BigNumber(n.toPrecision(15))) +const createOp = (a, b, op) => (newBigSigDig(a))[op](newBigSigDig(b)) +const bigNumMinus = (a = 0, b = 0) => createOp(a, b, 'minus') +const bigNumDiv = (a = 0, b = 1) => createOp(a, b, 'div') export function handleMouseMove ({ xMousePos, chartXStart, chartWidth, gasPrices, estimatedTimes, chart }) { const { currentPosValue, newTimeEstimate } = getNewXandTimeEstimate({ @@ -24,7 +30,8 @@ export function handleMouseMove ({ xMousePos, chartXStart, chartWidth, gasPrices } export function getCoordinateData (selector) { - return d3.select(selector).node().getBoundingClientRect() + const node = d3.select(selector).node() + return node ? node.getBoundingClientRect() : {} } export function generateDataUIObj (x, index, value) { @@ -70,19 +77,22 @@ export function getAdjacentGasPrices ({ gasPrices, priceToPosition }) { } } -export function extrapolateY ({ higherY, lowerY, higherX, lowerX, xForExtrapolation }) { - const slope = (higherY - lowerY) / (higherX - lowerX) - const newTimeEstimate = -1 * (slope * (higherX - xForExtrapolation) - higherY) +export function extrapolateY ({ higherY = 0, lowerY = 0, higherX = 0, lowerX = 0, xForExtrapolation = 0 }) { + const slope = bigNumMinus(higherY, lowerY).div(bigNumMinus(higherX, lowerX)) + const newTimeEstimate = slope.times(bigNumMinus(higherX, xForExtrapolation)).minus(newBigSigDig(higherY)).negated() - return newTimeEstimate + return newTimeEstimate.toNumber() } export function getNewXandTimeEstimate ({ xMousePos, chartXStart, chartWidth, gasPrices, estimatedTimes }) { - const chartMouseXPos = xMousePos - chartXStart - const posPercentile = chartMouseXPos / chartWidth + const chartMouseXPos = bigNumMinus(xMousePos, chartXStart) + const posPercentile = bigNumDiv(chartMouseXPos, chartWidth) - const currentPosValue = (gasPrices[gasPrices.length - 1] - gasPrices[0]) * posPercentile + gasPrices[0] + const currentPosValue = (bigNumMinus(gasPrices[gasPrices.length - 1], gasPrices[0])) + .times(newBigSigDig(posPercentile)) + .plus(newBigSigDig(gasPrices[0])) + .toNumber() const { closestLowerValueIndex, @@ -162,20 +172,28 @@ export function setSelectedCircle ({ closestHigherValue, }) { const numberOfValues = chart.internal.data.xs.data1.length + const { x: lowerX, y: lowerY } = getCoordinateData(`.c3-circle-${closestLowerValueIndex}`) let { x: higherX, y: higherY } = getCoordinateData(`.c3-circle-${closestHigherValueIndex}`) + let count = closestHigherValueIndex + 1 - if (lowerX === higherX) { - const { x: higherXAdjusted, y: higherYAdjusted } = getCoordinateData(`.c3-circle-${closestHigherValueIndex + 1}`) - higherY = higherYAdjusted - higherX = higherXAdjusted + if (lowerX && higherX) { + while (lowerX === higherX) { + higherX = getCoordinateData(`.c3-circle-${count}`).x + higherY = getCoordinateData(`.c3-circle-${count}`).y + count++ + } } - const currentX = lowerX + (higherX - lowerX) * (newPrice - closestLowerValue) / (closestHigherValue - closestLowerValue) + const currentX = bigNumMinus(higherX, lowerX) + .times(bigNumMinus(newPrice, closestLowerValue)) + .div(bigNumMinus(closestHigherValue, closestLowerValue)) + .plus(newBigSigDig(lowerX)) + const newTimeEstimate = extrapolateY({ higherY, lowerY, higherX, lowerX, xForExtrapolation: currentX }) chart.internal.selectPoint( - generateDataUIObj(currentX, numberOfValues, newTimeEstimate), + generateDataUIObj(currentX.toNumber(), numberOfValues, newTimeEstimate), numberOfValues ) } @@ -282,8 +300,8 @@ export function generateChart (gasPrices, estimatedTimes, gasPricesMax, estimate .style('margin-top', flipTooltip ? '-16px' : '4px') return { - top: circleY - chartYStart - 19 + (flipTooltip ? circleWidth + 38 : 0), - left: circleX - chartXStart + circleWidth - (gasPricesMaxPadded / 50), + top: bigNumMinus(circleY, chartYStart).minus(19).plus(flipTooltip ? circleWidth + 38 : 0).toNumber(), + left: bigNumMinus(circleX, chartXStart).plus(newBigSigDig(circleWidth)).minus(bigNumDiv(gasPricesMaxPadded, 50)).toNumber(), } }, show: true, @@ -298,8 +316,8 @@ export function generateChart (gasPrices, estimatedTimes, gasPricesMax, estimate appendOrUpdateCircle.bind(this)({ data, itemIndex, - cx: () => data.x - chartXStart + 11, - cy: () => data.value - chartYStart + 10, + cx: () => bigNumMinus(data.x, chartXStart).plus(11).toNumber(), + cy: () => bigNumMinus(data.value, chartYStart).plus(10).toNumber(), cssId: 'set-circle', appendOnly: true, }) diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 7ed0b6944..0a603db4e 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -399,7 +399,7 @@ function mapDispatchToProps (dispatch) { return { hideModal: (customOnHideOpts) => { dispatch(actions.hideModal()) - if (customOnHideOpts.action) { + if (customOnHideOpts && customOnHideOpts.action) { dispatch(customOnHideOpts.action(...customOnHideOpts.args)) } }, diff --git a/ui/app/components/page-container/page-container-footer/page-container-footer.component.js b/ui/app/components/page-container/page-container-footer/page-container-footer.component.js index 5725c22ac..85b16cefe 100644 --- a/ui/app/components/page-container/page-container-footer/page-container-footer.component.js +++ b/ui/app/components/page-container/page-container-footer/page-container-footer.component.js @@ -12,7 +12,7 @@ export default class PageContainerFooter extends Component { submitText: PropTypes.string, disabled: PropTypes.bool, submitButtonType: PropTypes.string, - hideCancel: PropTypes.func, + hideCancel: PropTypes.bool, } static contextTypes = { diff --git a/ui/app/components/sidebars/sidebar-content.scss b/ui/app/components/sidebars/sidebar-content.scss index 7d1f719dc..ca6b0a458 100644 --- a/ui/app/components/sidebars/sidebar-content.scss +++ b/ui/app/components/sidebars/sidebar-content.scss @@ -1,6 +1,11 @@ .sidebar-left { + display: flex; + .gas-modal-page-container { + display: flex; + .page-container { + flex: 1; max-width: 100%; &__content { @@ -12,6 +17,10 @@ max-width: 344px; min-height: auto; } + + @media screen and (min-width: $break-small) { + max-height: none; + } } .gas-price-chart { @@ -34,9 +43,10 @@ } .basic-tab-content { - height: 318px; + height: auto; margin-bottom: 0px; border-bottom: 1px solid #d2d8dd; + flex: 1 1 70%; @media screen and (max-width: $break-small) { padding-left: 14px; @@ -55,6 +65,10 @@ } .advanced-tab { + @media screen and (min-width: $break-small) { + flex: 1 1 70%; + } + &__fee-chart { height: 320px; @@ -72,14 +86,26 @@ } } + .gas-modal-content { + display: flex; + flex-direction: column; + width: 100%; - .gas-modal-content__info-row { - height: 170px; - - @media screen and (max-width: $break-small) { - height: initial; + &__info-row-wrapper { display: flex; - justify-content: center; + @media screen and (min-width: $break-small) { + flex: 1 1 30%; + } + } + + &__info-row { + height: 170px; + + @media screen and (max-width: $break-small) { + height: initial; + display: flex; + justify-content: center; + } } } } diff --git a/ui/app/ducks/gas.duck.js b/ui/app/ducks/gas.duck.js index 20a125dbb..8db24cc83 100644 --- a/ui/app/ducks/gas.duck.js +++ b/ui/app/ducks/gas.duck.js @@ -220,18 +220,25 @@ export function fetchBasicGasAndTimeEstimates () { ) .then(r => r.json()) .then(({ - average, + average: averageTimes10, avgWait, block_time: blockTime, blockNum, - fast, - fastest, + fast: fastTimes10, + fastest: fastestTimes10, fastestWait, fastWait, - safeLow, + safeLow: safeLowTimes10, safeLowWait, speed, }) => { + const [average, fast, fastest, safeLow] = [ + averageTimes10, + fastTimes10, + fastestTimes10, + safeLowTimes10, + ].map(price => (new BigNumber(price)).div(10).toNumber()) + const basicEstimates = { average, avgWait, diff --git a/ui/app/ducks/tests/gas-duck.test.js b/ui/app/ducks/tests/gas-duck.test.js index 4783db30c..bf374c7ec 100644 --- a/ui/app/ducks/tests/gas-duck.test.js +++ b/ui/app/ducks/tests/gas-duck.test.js @@ -32,15 +32,15 @@ describe('Gas Duck', () => { let tempFetch let tempDateNow const mockEthGasApiResponse = { - average: 'mockAverage', + average: 20, avgWait: 'mockAvgWait', block_time: 'mockBlock_time', blockNum: 'mockBlockNum', - fast: 'mockFast', - fastest: 'mockFastest', + fast: 30, + fastest: 40, fastestWait: 'mockFastestWait', fastWait: 'mockFastWait', - safeLow: 'mockSafeLow', + safeLow: 10, safeLowWait: 'mockSafeLowWait', speed: 'mockSpeed', } @@ -338,15 +338,15 @@ describe('Gas Duck', () => { [{ type: SET_BASIC_GAS_ESTIMATE_DATA, value: { - average: 'mockAverage', + average: 2, avgWait: 'mockAvgWait', blockTime: 'mockBlock_time', blockNum: 'mockBlockNum', - fast: 'mockFast', - fastest: 'mockFastest', + fast: 3, + fastest: 4, fastestWait: 'mockFastestWait', fastWait: 'mockFastWait', - safeLow: 'mockSafeLow', + safeLow: 1, safeLowWait: 'mockSafeLowWait', speed: 'mockSpeed', }, diff --git a/ui/app/selectors/custom-gas.js b/ui/app/selectors/custom-gas.js index ec234500d..59f240f9c 100644 --- a/ui/app/selectors/custom-gas.js +++ b/ui/app/selectors/custom-gas.js @@ -85,9 +85,9 @@ function getAveragePriceEstimateInHexWEI (state) { return getGasPriceInHexWei(averagePriceEstimate || '0x0') } -function getFastPriceEstimateInHexWEI (state, convertFromDecGWEI) { +function getFastPriceEstimateInHexWEI (state) { const fastPriceEstimate = state.gas.basicEstimates.fast - return getGasPriceInHexWei(fastPriceEstimate || '0x0', convertFromDecGWEI) + return getGasPriceInHexWei(fastPriceEstimate || '0x0') } function getDefaultActiveButtonIndex (gasButtonInfo, customGasPriceInHex, gasPrice) { @@ -100,15 +100,6 @@ function getBasicGasEstimateBlockTime (state) { return state.gas.basicEstimates.blockTime } -function apiEstimateModifiedToGWEI (estimate) { - return multiplyCurrencies(estimate, 0.10, { - toNumericBase: 'hex', - multiplicandBase: 10, - multiplierBase: 10, - numberOfDecimals: 9, - }) -} - function basicPriceEstimateToETHTotal (estimate, gasLimit, numberOfDecimals = 9) { return conversionUtil(calcGasTotal(gasLimit, estimate), { fromNumericBase: 'hex', @@ -118,26 +109,18 @@ function basicPriceEstimateToETHTotal (estimate, gasLimit, numberOfDecimals = 9) }) } -function getRenderableEthFee (estimate, gasLimit, numberOfDecimals = 9, convertFromDecGWEI) { - const initialConversion = convertFromDecGWEI - ? x => conversionUtil(x, { fromNumericBase: 'dec', toNumericBase: 'hex' }) - : apiEstimateModifiedToGWEI - +function getRenderableEthFee (estimate, gasLimit, numberOfDecimals = 9) { return pipe( - initialConversion, + x => conversionUtil(x, { fromNumericBase: 'dec', toNumericBase: 'hex' }), partialRight(basicPriceEstimateToETHTotal, [gasLimit, numberOfDecimals]), formatETHFee )(estimate, gasLimit) } -function getRenderableConvertedCurrencyFee (estimate, gasLimit, convertedCurrency, conversionRate, convertFromDecGWEI) { - const initialConversion = convertFromDecGWEI - ? x => conversionUtil(x, { fromNumericBase: 'dec', toNumericBase: 'hex' }) - : apiEstimateModifiedToGWEI - +function getRenderableConvertedCurrencyFee (estimate, gasLimit, convertedCurrency, conversionRate) { return pipe( - initialConversion, + x => conversionUtil(x, { fromNumericBase: 'dec', toNumericBase: 'hex' }), partialRight(basicPriceEstimateToETHTotal, [gasLimit]), partialRight(ethTotalToConvertedCurrency, [convertedCurrency, conversionRate]), partialRight(formatCurrency, [convertedCurrency]) @@ -153,14 +136,26 @@ function getTimeEstimateInSeconds (blockWaitEstimate) { }) } -function formatTimeEstimate (totalSeconds) { +function formatTimeEstimate (totalSeconds, greaterThanMax, lessThanMin) { const minutes = Math.floor(totalSeconds / 60) const seconds = Math.floor(totalSeconds % 60) + + if (!minutes && !seconds) { + return '...' + } + + let symbol = '~' + if (greaterThanMax) { + symbol = '< ' + } else if (lessThanMin) { + symbol = '> ' + } + const formattedMin = `${minutes ? minutes + ' min' : ''}` const formattedSec = `${seconds ? seconds + ' sec' : ''}` const formattedCombined = formattedMin && formattedSec - ? `~${formattedMin} ${formattedSec}` - : '~' + [formattedMin, formattedSec].find(t => t) + ? `${symbol}${formattedMin} ${formattedSec}` + : symbol + [formattedMin, formattedSec].find(t => t) return formattedCombined } @@ -182,13 +177,9 @@ function priceEstimateToWei (priceEstimate) { }) } -function getGasPriceInHexWei (price, convertFromDecGWEI) { - const initialConversion = convertFromDecGWEI - ? x => conversionUtil(x, { fromNumericBase: 'dec', toNumericBase: 'hex' }) - : apiEstimateModifiedToGWEI - +function getGasPriceInHexWei (price) { return pipe( - initialConversion, + x => conversionUtil(x, { fromNumericBase: 'dec', toNumericBase: 'hex' }), priceEstimateToWei, addHexPrefix )(price) @@ -259,19 +250,19 @@ function getRenderableEstimateDataForSmallButtonsFromGWEI (state) { return [ { labelKey: 'fastest', - feeInSecondaryCurrency: getRenderableConvertedCurrencyFee(fastest, gasLimit, currentCurrency, conversionRate, true), + feeInSecondaryCurrency: getRenderableConvertedCurrencyFee(fastest, gasLimit, currentCurrency, conversionRate), feeInPrimaryCurrency: getRenderableEthFee(fastest, gasLimit, NUMBER_OF_DECIMALS_SM_BTNS, true), priceInHexWei: getGasPriceInHexWei(fastest, true), }, { labelKey: 'fast', - feeInSecondaryCurrency: getRenderableConvertedCurrencyFee(fast, gasLimit, currentCurrency, conversionRate, true), + feeInSecondaryCurrency: getRenderableConvertedCurrencyFee(fast, gasLimit, currentCurrency, conversionRate), feeInPrimaryCurrency: getRenderableEthFee(fast, gasLimit, NUMBER_OF_DECIMALS_SM_BTNS, true), priceInHexWei: getGasPriceInHexWei(fast, true), }, { labelKey: 'slow', - feeInSecondaryCurrency: getRenderableConvertedCurrencyFee(safeLow, gasLimit, currentCurrency, conversionRate, true), + feeInSecondaryCurrency: getRenderableConvertedCurrencyFee(safeLow, gasLimit, currentCurrency, conversionRate), feeInPrimaryCurrency: getRenderableEthFee(safeLow, gasLimit, NUMBER_OF_DECIMALS_SM_BTNS, true), priceInHexWei: getGasPriceInHexWei(safeLow, true), }, diff --git a/ui/app/selectors/tests/custom-gas.test.js b/ui/app/selectors/tests/custom-gas.test.js index 037b1e86e..ebc300160 100644 --- a/ui/app/selectors/tests/custom-gas.test.js +++ b/ui/app/selectors/tests/custom-gas.test.js @@ -109,11 +109,11 @@ describe('custom-gas selectors', () => { gas: { basicEstimates: { blockTime: 14.16326530612245, - safeLow: 25, + safeLow: 2.5, safeLowWait: 6.6, - fast: 50, + fast: 5, fastWait: 3.3, - fastest: 100, + fastest: 10, fastestWait: 0.5, }, }, @@ -154,11 +154,11 @@ describe('custom-gas selectors', () => { gas: { basicEstimates: { blockTime: 14.16326530612245, - safeLow: 50, + safeLow: 5, safeLowWait: 13.2, - fast: 100, + fast: 10, fastWait: 6.6, - fastest: 200, + fastest: 20, fastestWait: 1.0, }, }, -- cgit