aboutsummaryrefslogtreecommitdiffstats
path: root/ui/app/components/gas-customization/gas-price-chart/gas-price-chart.component.js
diff options
context:
space:
mode:
Diffstat (limited to 'ui/app/components/gas-customization/gas-price-chart/gas-price-chart.component.js')
-rw-r--r--ui/app/components/gas-customization/gas-price-chart/gas-price-chart.component.js417
1 files changed, 57 insertions, 360 deletions
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 69bbd12f6..69f8b3a91 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
@@ -2,75 +2,18 @@ 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')
-}
-
-function appendOrUpdateCircle ({ circle, data, itemIndex, cx, cy, cssId, appendOnly }) {
- if (appendOnly || circle.empty()) {
- circle.data([data])
- .enter().append('circle')
- .attr('class', () => this.generateClass('c3-selected-circle', itemIndex))
- .attr('id', cssId)
- .attr('cx', cx)
- .attr('cy', cy)
- .attr('stroke', () => this.color(data))
- .attr('r', 6)
- } else {
- circle.data([data])
- .attr('cx', cx)
- .attr('cy', cy)
- }
-}
-
-function setSelectedCircle ({ chart, gasPrices, currentPrice, chartXStart, chartWidth }) {
- const numberOfValues = chart.internal.data.xs.data1.length
- const closestLowerValueIndex = gasPrices.findIndex((e, i, a) => {
- return e <= currentPrice && a[i + 1] >= currentPrice
- })
- const closestHigherValueIndex = gasPrices.findIndex((e, i, a) => {
- return e > currentPrice
- })
- const closestHigherValue = gasPrices[closestHigherValueIndex]
- const closestLowerValue = gasPrices[closestLowerValueIndex]
-
- if (closestHigherValue && closestLowerValue) {
- const closestLowerCircle = d3.select(`.c3-circle-${closestLowerValueIndex}`)
- const closestHigherCircle = d3.select(`.c3-circle-${closestHigherValueIndex}`)
- const { x: lowerX, y: lowerY } = closestLowerCircle.node().getBoundingClientRect()
- const { x: higherX, y: higherY } = closestHigherCircle.node().getBoundingClientRect()
- const currentX = lowerX + (higherX - lowerX) * (currentPrice - closestLowerValue) / (closestHigherValue - closestLowerValue)
- const slope = (higherY - lowerY) / (higherX - lowerX)
- const newTimeEstimate = -1 * (slope * (higherX - currentX) - higherY)
- chart.internal.selectPointB({
- x: currentX,
- value: newTimeEstimate,
- id: 'data1',
- index: numberOfValues,
- name: 'data1',
- }, numberOfValues)
- } else {
- const setCircle = d3.select('#set-circle')
- if (!setCircle.empty()) {
- setCircle.remove()
- }
- d3.select('.c3-tooltip-container').style('display', 'none !important')
- chart.internal.hideXGridFocus()
- return
- }
-}
+import {
+ appendOrUpdateCircle,
+ generateChart,
+ generateDataUIObj,
+ getAdjacentGasPrices,
+ getCoordinateData,
+ getNewXandTimeEstimate,
+ handleChartUpdate,
+ hideDataUI,
+ setSelectedCircle,
+ setTickPosition,
+} from './gas-price-chart.utils.js'
export default class GasPriceChart extends Component {
static contextTypes = {
@@ -78,225 +21,23 @@ export default class GasPriceChart extends Component {
}
static propTypes = {
- priceAndTimeEstimates: PropTypes.array,
+ gasPrices: PropTypes.array,
+ estimatedTimes: PropTypes.array,
+ gasPricesMax: PropTypes.number,
+ estimatedTimesMax: PropTypes.number,
currentPrice: PropTypes.number,
updateCustomGasPrice: PropTypes.func,
}
- renderChart (currentPrice, priceAndTimeEstimates, updateCustomGasPrice) {
- const gasPrices = priceAndTimeEstimates.map(({ gasprice }) => gasprice)
- const gasPricesMax = gasPrices[gasPrices.length - 1] + 1
- const estimatedTimes = priceAndTimeEstimates.map(({ expectedTime }) => expectedTime)
-
- const estimatedTimesMax = estimatedTimes[0]
- const chart = c3.generate({
- size: {
- height: 165,
- },
- transition: {
- duration: 0,
- },
- padding: {left: 20, right: 15, top: 6, bottom: 10},
- data: {
- x: 'x',
- columns: [
- ['x', ...gasPrices],
- ['data1', ...estimatedTimes],
- ],
- types: {
- data1: 'area',
- },
- selection: {
- enabled: false,
- },
- },
- color: {
- data1: '#259de5',
- },
- axis: {
- x: {
- min: gasPrices[0],
- max: gasPricesMax,
- tick: {
- values: [Math.floor(gasPrices[0]), Math.ceil(gasPricesMax)],
- outer: false,
- format: function (val) { return val + ' GWEI' },
- },
- padding: {left: gasPricesMax / 50, right: gasPricesMax / 50},
- label: {
- text: 'Gas Price ($)',
- position: 'outer-center',
- },
- },
- y: {
- padding: {top: 7, bottom: 7},
- tick: {
- values: [Math.floor(estimatedTimesMax * 0.05), Math.ceil(estimatedTimesMax * 0.97)],
- outer: false,
- },
- label: {
- text: 'Confirmation time (sec)',
- position: 'outer-middle',
- },
- min: 0,
- },
- },
- legend: {
- show: false,
- },
- grid: {
- x: {},
- lines: {
- front: false,
- },
- },
- point: {
- focus: {
- expand: {
- enabled: false,
- r: 3.5,
- },
- },
- },
- tooltip: {
- format: {
- title: (v) => v.toPrecision(4),
- },
- contents: function (d, defaultTitleFormat, defaultValueFormat, color) {
- const config = this.config
- const titleFormat = config.tooltip_format_title || defaultTitleFormat
- let text
- let title
- d.forEach(el => {
- if (el && (el.value || el.value === 0) && !text) {
- title = titleFormat ? titleFormat(el.x) : el.x
- text = "<table class='" + 'custom-tooltip' + "'>" + (title || title === 0 ? "<tr><th colspan='2'>" + title + '</th></tr>' : '')
- }
- })
- return text + '</table>' + "<div class='tooltip-arrow'></div>"
- },
- position: function (data, width, height, element) {
- const overlayedCircle = d3.select('#overlayed-circle')
- if (overlayedCircle.empty()) {
- return { top: -100, left: -100 }
- }
-
- const { x: circleX, y: circleY, width: circleWidth } = overlayedCircle.node().getBoundingClientRect()
- const { x: chartXStart, y: chartYStart } = d3.select('.c3-chart').node().getBoundingClientRect()
-
- // TODO: Confirm the below constants work with all data sets and screen sizes
- // TODO: simplify l149-l159
- let y = circleY - chartYStart - 19
- if (circleY - circleWidth < chartYStart + 5) {
- y = y + circleWidth + 38
- d3.select('.tooltip-arrow').style('margin-top', '-16px')
- } else {
- d3.select('.tooltip-arrow').style('margin-top', '4px')
- }
- return {
- top: y,
- left: circleX - chartXStart + circleWidth - (gasPricesMax / 50),
- }
- },
- show: true,
- },
- })
-
- chart.internal.selectPoint = function (data, itemIndex = (data.index || 0)) {
- const { x: circleX, y: circleY, width: circleWidth } = d3.select('#overlayed-circle')
- .node()
- .getBoundingClientRect()
- const { x: chartXStart, y: chartYStart } = d3.select('.c3-areas-data1')
- .node()
- .getBoundingClientRect()
-
- d3.select('#set-circle').remove()
-
- const circle = this.main
- .select('.' + 'c3-selected-circles' + this.getTargetSelectorSuffix(data.id))
- .selectAll('.' + 'c3-selected-circle' + '-' + itemIndex)
-
- appendOrUpdateCircle.bind(this)({
- circle,
- data,
- itemIndex,
- cx: () => circleX - chartXStart + circleWidth + 2,
- cy: () => circleY - chartYStart + circleWidth + 1,
- cssId: 'set-circle',
- appendOnly: true,
- })
- }
-
- chart.internal.selectPointB = function (data, itemIndex = (data.index || 0)) {
- const { x: chartXStart, y: chartYStart } = d3.select('.c3-areas-data1')
- .node()
- .getBoundingClientRect()
-
- d3.select('#set-circle').remove()
-
- const circle = this.main
- .select('.' + 'c3-selected-circles' + this.getTargetSelectorSuffix(data.id))
- .selectAll('.' + 'c3-selected-circle' + '-' + itemIndex)
-
- appendOrUpdateCircle.bind(this)({
- circle,
- data,
- itemIndex,
- cx: () => data.x - chartXStart + 11,
- cy: () => data.value - chartYStart + 10,
- cssId: 'set-circle',
- appendOnly: true,
- })
- }
-
- chart.internal.overlayPoint = function (data, itemIndex) {
- const circle = this.main
- .select('.' + 'c3-selected-circles' + this.getTargetSelectorSuffix(data.id))
- .selectAll('.' + 'c3-selected-circle' + '-' + itemIndex)
-
- appendOrUpdateCircle.bind(this)({
- circle,
- data,
- itemIndex,
- cx: this.circleX.bind(this),
- cy: this.circleY.bind(this),
- cssId: 'overlayed-circle',
- })
- }
-
- chart.internal.setCurrentCircle = function (data, itemIndex) {
- const circle = this.main
- .select('.' + 'c3-selected-circles' + this.getTargetSelectorSuffix(data.id))
- .selectAll('#current-circle')
-
- appendOrUpdateCircle.bind(this)({
- circle,
- data,
- itemIndex,
- cx: this.circleX.bind(this),
- cy: this.circleY.bind(this),
- cssId: 'current-circle',
- })
- }
-
- chart.internal.showTooltip = function (selectedData, element) {
- const $$ = this
- const config = $$.config
- const forArc = $$.hasArcType()
- const dataToShow = selectedData.filter((d) => d && (d.value || d.value === 0))
- const positionFunction = config.tooltip_position || chart.internal.prototype.tooltipPosition
- if (dataToShow.length === 0 || !config.tooltip_show) {
- return
- }
- $$.tooltip.html(config.tooltip_contents.call($$, selectedData, $$.axis.getXAxisTickFormat(), $$.getYFormat(forArc), $$.color)).style('display', 'flex')
-
- // Get tooltip dimensions
- const tWidth = $$.tooltip.property('offsetWidth')
- const tHeight = $$.tooltip.property('offsetHeight')
- const position = positionFunction.call(this, dataToShow, tWidth, tHeight, element)
- // Set tooltip
- $$.tooltip.style('top', position.top + 'px').style('left', position.left + 'px')
- }
+ renderChart ({
+ currentPrice,
+ gasPrices,
+ estimatedTimes,
+ gasPricesMax,
+ estimatedTimesMax,
+ updateCustomGasPrice,
+ }) {
+ const chart = generateChart(gasPrices, estimatedTimes, gasPricesMax, estimatedTimesMax)
setTimeout(function () {
setTickPosition('y', 0, -5, 8)
@@ -310,84 +51,42 @@ export default class GasPriceChart extends Component {
d3.select('.c3-xgrid-focus line').attr('y2', 98)
d3.select('.c3-chart').on('mouseout', () => {
- const overLayedCircle = d3.select('#overlayed-circle')
- if (!overLayedCircle.empty()) {
- overLayedCircle.remove()
- }
- d3.select('.c3-tooltip-container').style('display', 'none !important')
+ hideDataUI(chart, '#overlayed-circle')
})
- const chartRect = d3.select('.c3-areas-data1')
- const { x: chartXStart, width: chartWidth } = chartRect.node().getBoundingClientRect()
-
d3.select('.c3-chart').on('click', () => {
- const overlayedCircle = d3.select('#overlayed-circle')
- const numberOfValues = chart.internal.data.xs.data1.length
- const { x: circleX, y: circleY } = overlayedCircle.node().getBoundingClientRect()
- const { x: xData } = overlayedCircle.datum()
- chart.internal.selectPoint({
- x: circleX - chartXStart,
- value: circleY - 1.5,
- id: 'data1',
- index: numberOfValues,
- name: 'data1',
- }, numberOfValues)
- updateCustomGasPrice(xData)
+ const { x: newGasPrice } = d3.select('#overlayed-circle').datum()
+ updateCustomGasPrice(newGasPrice)
})
- setSelectedCircle({ chart, gasPrices, currentPrice, chartXStart, chartWidth })
+ const { x: chartXStart, width: chartWidth } = getCoordinateData('.c3-areas-data1')
- d3.select('.c3-chart').on('mousemove', function () {
- const chartMouseXPos = d3.event.clientX - chartXStart
- const posPercentile = chartMouseXPos / chartWidth
+ handleChartUpdate ({
+ chart,
+ gasPrices,
+ newPrice: currentPrice,
+ cssId: '#set-circle',
+ })
- const currentPosValue = (gasPrices[gasPrices.length - 1] - gasPrices[0]) * posPercentile + gasPrices[0]
- const closestLowerValueIndex = gasPrices.findIndex((e, i, a) => {
- return e <= currentPosValue && a[i + 1] >= currentPosValue
+ d3.select('.c3-chart').on('mousemove', function () {
+ const { currentPosValue, newTimeEstimate } = getNewXandTimeEstimate({
+ xMousePos: d3.event.clientX,
+ chartXStart,
+ chartWidth,
+ gasPrices,
+ estimatedTimes,
})
- const closestLowerValue = gasPrices[closestLowerValueIndex]
- const estimatedClosestLowerTimeEstimate = estimatedTimes[closestLowerValueIndex]
- const closestHigherValueIndex = gasPrices.findIndex((e, i, a) => {
- return e > currentPosValue
- })
- const closestHigherValue = gasPrices[closestHigherValueIndex]
- if (!closestHigherValue || !closestLowerValue) {
- const overLayedCircle = d3.select('#overlayed-circle')
- if (!overLayedCircle.empty()) {
- overLayedCircle.remove()
- }
- d3.select('.c3-tooltip-container').style('display', 'none !important')
- chart.internal.hideXGridFocus()
- return
+ if (currentPosValue === null && newTimeEstimate === null) {
+ hideDataUI(chart, '#overlayed-circle')
}
- const estimatedClosestHigherTimeEstimate = estimatedTimes[closestHigherValueIndex]
- const slope = (estimatedClosestHigherTimeEstimate - estimatedClosestLowerTimeEstimate) / (closestHigherValue - closestLowerValue)
- const newTimeEstimate = -1 * (slope * (closestHigherValue - currentPosValue) - estimatedClosestHigherTimeEstimate)
+ const indexOfNewCircle = estimatedTimes.length + 1
+ const dataUIObj = generateDataUIObj(currentPosValue, indexOfNewCircle, newTimeEstimate)
- const newEstimatedTimes = [...estimatedTimes, newTimeEstimate]
- chart.internal.overlayPoint({
- x: currentPosValue,
- value: newTimeEstimate,
- id: 'data1',
- index: newEstimatedTimes.length,
- name: 'data1',
- }, newEstimatedTimes.length)
- chart.internal.showTooltip([{
- x: currentPosValue,
- value: newTimeEstimate,
- id: 'data1',
- index: newEstimatedTimes.length,
- name: 'data1',
- }], chartRect._groups[0])
- chart.internal.showXGridFocus([{
- x: currentPosValue,
- value: newTimeEstimate,
- id: 'data1',
- index: newEstimatedTimes.length,
- name: 'data1',
- }])
+ chart.internal.overlayPoint(dataUIObj, indexOfNewCircle)
+ chart.internal.showTooltip([dataUIObj], d3.select('.c3-areas-data1')._groups[0])
+ chart.internal.showXGridFocus([dataUIObj])
})
}, 0)
@@ -395,22 +94,20 @@ export default class GasPriceChart extends Component {
}
componentDidUpdate (prevProps) {
- if (prevProps.currentPrice !== this.props.currentPrice) {
- const chartRect = d3.select('.c3-areas-data1')
- const { x: chartXStart, width: chartWidth } = chartRect.node().getBoundingClientRect()
- setSelectedCircle({
+ const { gasPrices, currentPrice: newPrice } = this.props
+
+ if (prevProps.currentPrice !== newPrice) {
+ handleChartUpdate ({
chart: this.chart,
- currentPrice: this.props.currentPrice,
- gasPrices: this.props.priceAndTimeEstimates.map(({ gasprice }) => gasprice),
- chartXStart,
- chartWidth,
+ gasPrices,
+ newPrice,
+ cssId: '#set-circle',
})
}
}
componentDidMount () {
- const { currentPrice, priceAndTimeEstimates, updateCustomGasPrice } = this.props
- this.renderChart(currentPrice, priceAndTimeEstimates, updateCustomGasPrice)
+ this.renderChart(this.props)
}
render () {