From 0ba6f7d9bb5c2183d8a370fd0955e18d45616207 Mon Sep 17 00:00:00 2001 From: Dan Miller Date: Thu, 20 Sep 2018 13:36:23 -0230 Subject: Adds not yet functional gas price chart. --- package.json | 2 + test/setup.js | 2 + .../advanced-tab-content.component.js | 5 + .../advanced-tab-content/index.scss | 33 +++-- .../tests/advanced-tab-content-component.test.js | 4 +- .../gas-modal-page-container.container.js | 2 +- .../gas-modal-page-container/index.scss | 3 +- .../gas-price-chart/gas-price-chart.component.js | 151 ++++++++++++++++++++- .../gas-customization/gas-price-chart/index.scss | 104 +++++++++++++- .../tests/gas-price-chart.component.test.js | 2 +- .../page-container/page-container.component.js | 2 +- 11 files changed, 290 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index ecdf88202..5e5b9e893 100644 --- a/package.json +++ b/package.json @@ -98,11 +98,13 @@ "browser-passworder": "^2.0.3", "browserify-derequire": "^0.9.4", "browserify-unibabel": "^3.0.0", + "c3": "^0.6.7", "classnames": "^2.2.5", "clone": "^2.1.2", "copy-to-clipboard": "^3.0.8", "css-loader": "^0.28.11", "currency-formatter": "^1.4.2", + "d3": "^5.7.0", "debounce": "1.1.0", "debounce-stream": "^2.0.0", "deep-extend": "^0.5.1", diff --git a/test/setup.js b/test/setup.js index 8e7965a37..1a69f4866 100644 --- a/test/setup.js +++ b/test/setup.js @@ -3,3 +3,5 @@ require('babel-register')({ }) require('./helper') + +window.SVGPathElement = window.SVGPathElement || { prototype: {} } 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 5218dd477..f90da0a88 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 @@ -94,7 +94,12 @@ export default class AdvancedTabContent extends Component { customGasLimit, updateCustomGasLimit ) } +
Live Gas Price Predictions
+
+ Slower + Faster +
) 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 ae99ba4aa..9c89688e2 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 @@ -38,19 +38,32 @@ } } - &__fee-chart-title { - font-size: 14px; - color: $scorpion; - margin-top: 22px; - } - &__fee-chart { - padding-left: 10px; margin-top: 8px; - height: 258px; + height: 265px; background: #F8F9FB; border-bottom: 1px solid #d2d8dd; border-top: 1px solid #d2d8dd; + position: relative; + + &__title { + font-size: 12px; + color: #313A5E; + margin-left: 22px; + margin-bottom: 11px; + } + + &__speed-buttons { + position: absolute; + bottom: 13px; + display: flex; + justify-content: space-between; + padding-left: 20px; + padding-right: 19px; + width: 100%; + font-size: 10px; + color: #888EA3; + } } &__slider-container { @@ -59,11 +72,11 @@ } &__gas-edit-rows { - height: 87px; + height: 73px; display: flex; flex-flow: row; justify-content: space-between; - margin-left: 10px; + margin-left: 20px; margin-right: 10px; margin-top: 9px; } 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 14863e59d..27a2326b8 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 @@ -54,7 +54,9 @@ describe('AdvancedTabContent Component', function () { const feeChartDiv = advancedTabChildren.at(1) assert(feeChartDiv.childAt(0).hasClass('advanced-tab__gas-edit-rows')) - assert(feeChartDiv.childAt(1).is(GasPriceChart)) + assert(feeChartDiv.childAt(1).hasClass('advanced-tab__fee-chart__title')) + assert(feeChartDiv.childAt(2).is(GasPriceChart)) + assert(feeChartDiv.childAt(3).hasClass('advanced-tab__fee-chart__speed-buttons')) }) it('should call renderDataSummary with the expected params', () => { 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 ae233578b..0d8d9d8e4 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 @@ -154,7 +154,7 @@ function calcCustomGasLimit (customGasLimitInHex) { function getTxParams (state) { const { confirmTransaction: { txData }, metamask: { send } } = state - + console.log('txData', txData) return txData.txParams || { from: send.from, gas: send.gasLimit, 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 c49d69bf7..debd9b5ee 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 @@ -3,7 +3,8 @@ .gas-modal-page-container { .page-container { - width: 391px; + max-width: 391px; + min-height: 585px; &__header { padding: 0px; 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 7c32058b7..7dadafa95 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 @@ -1,15 +1,162 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' +import * as d3 from 'd3' +import c3 from 'c3' + +function setTickPosition (axis, n, newPosition, secondNewPosition) { + const positionToShift = axis === 'y' ? 'x' : 'y' + const secondPositionToShift = axis === 'y' ? 'y' : 'x' + d3.select('#chart') + .select(`.c3-axis-${axis}`) + .selectAll('.tick') + .filter((d, i) => i === n) + .select('text') + .attr(positionToShift, 0) + .select('tspan') + .attr(positionToShift, newPosition) + .attr(secondPositionToShift, secondNewPosition || 0) + .style('visibility', 'visible') +} export default class GasPriceChart extends Component { static contextTypes = { t: PropTypes.func, } + static propTypes = { + } + + renderChart () { + c3.generate({ + size: { + height: 154, + }, + padding: {left: 36, right: 25, top: -5, bottom: 5}, + data: { + x: 'x', + columns: [ + ['x', 0, 0.01, 0.02, 0.03, 0.05, 0.07, 0.11, 0.15, 0.29, 0.35, 0.5, 0.55, 0.60, 0.63, 0.77, 0.88, 0.92, 0.93, 0.98, 0.99], + ['data1', 100, 66, 55, 50, 45, 25, 22, 20.1, 20, 19.9, 15, 12, 10, 9.9, 8.0, 4.0, 3, 1, 0.5, 0.2], + ], + types: { + data1: 'area', + }, + }, + color: { + data1: '#259de5', + }, + axis: { + x: { + min: 0, + max: 1, + tick: { + values: ['0', '1.00'], + outer: false, + format: val => val === '0' ? val : '$' + val, + }, + padding: {left: 0.005, right: 0}, + label: { + text: 'Gas Price ($)', + position: 'outer-center', + }, + }, + y: { + padding: {top: 2, bottom: 0}, + tick: { + values: ['5', '97'], + outer: false, + format: val => val === '5' ? '0' : '100', + }, + label: { + text: 'Confirmation time (sec)', + position: 'outer-middle', + }, + }, + }, + legend: { + show: false, + }, + grid: { + x: { + lines: [ + {value: 0.0833}, + {value: 0.1667}, + {value: 0.2500}, + {value: 0.3333}, + {value: 0.4167}, + {value: 0.5000}, + {value: 0.5833}, + {value: 0.6667}, + {value: 0.7500}, + {value: 0.8333}, + {value: 0.9167}, + {value: 1.0000}, + ], + }, + lines: { + front: false, + }, + }, + point: { + focus: { + expand: { + enabled: true, + r: 3.5, + }, + }, + }, + tooltip: { + contents: function (d, defaultTitleFormat, defaultValueFormat, color) { + const $$ = this + const config = $$.config + const titleFormat = config.tooltip_format_title || defaultTitleFormat + + let text, title + d.forEach(n => { + if (n && (n.value || n.value === 0)) { + + if (!text) { + title = titleFormat ? titleFormat(n.x) : n.x + text = "" + (title || title === 0 ? "' : '') + } + } + }) + // for (i = 0; i < d.length; i++) { + // if (! (d[i] && (d[i].value || d[i].value === 0))) { continue; } + + // if (! text) { + // title = titleFormat ? titleFormat(d[i].x) : d[i].x; + // text = "
" + title + '
" + (title || title === 0 ? "" : ""); + // } + // } + return text + '
" + title + "
' + "
" + }, + position: function (data, width, height, element) { + const x = d3.event.pageX - document.getElementById('chart').getBoundingClientRect().x + 19 + const y = d3.event.pageY - document.getElementById('chart').getBoundingClientRect().y + 20 + return {top: y, left: x} + }, + }, + }) + + setTimeout(() => { + setTickPosition('y', 0, -5, 2) + setTickPosition('y', 1, -3) + setTickPosition('x', 0, 3) + setTickPosition('x', 1, 3, -5) + d3.select('.c3-axis-x-label').attr('transform', 'translate(0,-15)') + d3.select('.c3-axis-y-label').attr('transform', 'translate(42, 2) rotate(-90)') + }, 0) + } + + componentDidMount () { + this.renderChart() + } + render () { return ( -
-
+
+
) } diff --git a/ui/app/components/gas-customization/gas-price-chart/index.scss b/ui/app/components/gas-customization/gas-price-chart/index.scss index 14e7a12a8..bfe9b807b 100644 --- a/ui/app/components/gas-customization/gas-price-chart/index.scss +++ b/ui/app/components/gas-customization/gas-price-chart/index.scss @@ -1,6 +1,104 @@ .gas-price-chart { - &__container { - display: flex; - position: relative; + display: flex; + position: relative; + + .tick text, .c3-axis-x-label, .c3-axis-y-label { + font-family: Roboto; + font-style: normal; + font-weight: bold; + line-height: normal; + font-size: 8px; + text-align: center; + fill: #9A9CA6 !important; } + + .custom-tooltip { + background: rgba(0, 0, 0, 1); + box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25); + border-radius: 3px; + transform: translate(-41px, -50px); + opacity: 1 !important; + width: 44px; + height: 21px; + z-index: 1; + } + + .tooltip-arrow { + background: rgba(0, 0, 0, 1); + box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.5); + top: -35px; + left: -23px; + transform: rotate(45deg); + opacity: 1 !important; + width: 9px; + height: 9px; + position: absolute; + display: inline-block; + } + + .custom-tooltip th { + font-family: Roboto; + font-style: normal; + font-weight: 500; + line-height: normal; + font-size: 10px; + text-align: center; + + color: #FFFFFF; + } + + .c3-circle._expanded_ { + fill: #FFFFFF !important; + stroke-width: 2.4px !important; + stroke: #2d9fd9 !important; + } + + .c3-axis-x-label, .c3-axis-y-label { + font-weight: normal; + } + + .tick text tspan { + visibility: hidden; + } + + .c3-circle { + fill: #2d9fd9 !important; + } + + .c3-line-data1 { + stroke: #2d9fd9 !important; + background: rgba(0,0,0,0) !important; + color: rgba(0,0,0,0) !important; + } + + .c3 path { + fill: none; + } + + .c3 path.c3-area-data1 { + opacity: 1; + fill: #e9edf1 !important; + } + + .c3-xgrid-line line { + stroke: #B8B8B8 !important; + } + + .c3-axis .tick line {display: none;} + + .c3-axis-x .domain { + fill: none; + stroke: none; + } + + .c3-axis-y .domain { + fill: none; + stroke: #C8CCD6; + } +} + +@import url(//fonts.googleapis.com/css?family=Roboto:400,700,300); + +#chart { + background: #F8F9FB } diff --git a/ui/app/components/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js b/ui/app/components/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js index 474b7b7b6..1a0f6760e 100644 --- a/ui/app/components/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js +++ b/ui/app/components/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js @@ -17,7 +17,7 @@ describe('GasPriceChart Component', function () { }) it('should render the chart div', () => { - assert(wrapper.childAt(0).hasClass('gas-price-chart__container')) + assert(wrapper.childAt(0).hasClass('gas-price-chart__root')) assert.equal(wrapper.childAt(0).props().id, 'chart') }) }) diff --git a/ui/app/components/page-container/page-container.component.js b/ui/app/components/page-container/page-container.component.js index 27daf4c04..d618dae4f 100644 --- a/ui/app/components/page-container/page-container.component.js +++ b/ui/app/components/page-container/page-container.component.js @@ -23,7 +23,7 @@ export default class PageContainer extends PureComponent { // PageContainerFooter props cancelText: PropTypes.string, disabled: PropTypes.bool, - hideCancel: PropTypes.string, + hideCancel: PropTypes.bool, onCancel: PropTypes.func, onSubmit: PropTypes.func, submitText: PropTypes.string, -- cgit