feat: add y log scale

This commit is contained in:
Nikola Ubavic 2022-08-11 20:19:59 +02:00 committed by Rafael
parent f079a2926b
commit 80715259b1
4 changed files with 75 additions and 33 deletions

View file

@ -1,4 +1,14 @@
import { offDarkColor, tomato, neon, java } from 'src/styling/variables' import {
offColor,
offDarkColor,
tomato,
neon,
java
} from 'src/styling/variables'
import typographyStyles from '../../components/typography/styles'
const { label1 } = typographyStyles
const styles = { const styles = {
overviewLegend: { overviewLegend: {
@ -135,6 +145,18 @@ const styles = {
topMachinesRadio: { topMachinesRadio: {
display: 'flex', display: 'flex',
flexDirection: 'row' flexDirection: 'row'
},
graphHeaderSwitchBox: {
display: 'flex',
flexDirection: 'column',
'& > *': {
margin: 0
},
'& > :first-child': {
marginBottom: 2,
extend: label1,
color: offColor
}
} }
} }

View file

@ -1,8 +1,8 @@
import { Box } from '@material-ui/core' import { Box } from '@material-ui/core'
import { makeStyles } from '@material-ui/core/styles' import { makeStyles } from '@material-ui/core/styles'
import React from 'react' import React, { useState } from 'react'
import { Select } from 'src/components/inputs' import { Select, Switch } from 'src/components/inputs'
import { H2 } from 'src/components/typography' import { H2 } from 'src/components/typography'
import { primaryColor } from 'src/styling/variables' import { primaryColor } from 'src/styling/variables'
@ -25,6 +25,8 @@ const OverTimeDotGraphHeader = ({
}) => { }) => {
const classes = useStyles() const classes = useStyles()
const [logarithmic, setLogarithmic] = useState()
const legend = { const legend = {
cashIn: <div className={classes.cashInIcon}></div>, cashIn: <div className={classes.cashInIcon}></div>,
cashOut: <div className={classes.cashOutIcon}></div>, cashOut: <div className={classes.cashOutIcon}></div>,
@ -57,6 +59,10 @@ const OverTimeDotGraphHeader = ({
</Box> </Box>
</div> </div>
<div className={classes.graphHeaderRight}> <div className={classes.graphHeaderRight}>
<div className={classes.graphHeaderSwitchBox}>
<span>Log. scale</span>
<Switch onChange={event => setLogarithmic(event.target.checked)} />
</div>
<Select <Select
label="Machines" label="Machines"
onSelectedItemChange={handleMachineChange} onSelectedItemChange={handleMachineChange}
@ -74,6 +80,7 @@ const OverTimeDotGraphHeader = ({
currency={currency} currency={currency}
selectedMachine={selectedMachine} selectedMachine={selectedMachine}
machines={machines} machines={machines}
log={logarithmic}
/> />
</> </>
) )

View file

@ -15,7 +15,8 @@ const GraphWrapper = ({
currency, currency,
selectedMachine, selectedMachine,
machines, machines,
selectedDay selectedDay,
log
}) => { }) => {
const [selectionCoords, setSelectionCoords] = useState(null) const [selectionCoords, setSelectionCoords] = useState(null)
const [selectionDateInterval, setSelectionDateInterval] = useState(null) const [selectionDateInterval, setSelectionDateInterval] = useState(null)
@ -33,6 +34,7 @@ const GraphWrapper = ({
setSelectionDateInterval={setSelectionDateInterval} setSelectionDateInterval={setSelectionDateInterval}
setSelectionData={setSelectionData} setSelectionData={setSelectionData}
selectedMachine={selectedMachine} selectedMachine={selectedMachine}
log={log}
/> />
) )
case 'topMachinesVolume': case 'topMachinesVolume':

View file

@ -23,7 +23,8 @@ const Graph = ({
timezone, timezone,
setSelectionCoords, setSelectionCoords,
setSelectionData, setSelectionData,
setSelectionDateInterval setSelectionDateInterval,
log = false
}) => { }) => {
const ref = useRef(null) const ref = useRef(null)
@ -171,7 +172,7 @@ const Graph = ({
.domain(periodDomains[period.code]) .domain(periodDomains[period.code])
.range([GRAPH_MARGIN.left, GRAPH_WIDTH]) .range([GRAPH_MARGIN.left, GRAPH_WIDTH])
const y = d3 const yLin = d3
.scaleLinear() .scaleLinear()
.domain([ .domain([
0, 0,
@ -180,6 +181,16 @@ const Graph = ({
.nice() .nice()
.range([GRAPH_HEIGHT - GRAPH_MARGIN.bottom, GRAPH_MARGIN.top]) .range([GRAPH_HEIGHT - GRAPH_MARGIN.bottom, GRAPH_MARGIN.top])
const yLog = d3
.scaleLog()
.domain([
(d3.min(data, d => new BigNumber(d.fiat).toNumber()) ?? 1) * 0.9,
(d3.max(data, d => new BigNumber(d.fiat).toNumber()) ?? 1000) * 1.1
])
.range([GRAPH_HEIGHT - GRAPH_MARGIN.bottom, GRAPH_MARGIN.top])
const y = log ? yLog : yLin
const getAreaInterval = (breakpoints, dataLimits, graphLimits) => { const getAreaInterval = (breakpoints, dataLimits, graphLimits) => {
const fullBreakpoints = [ const fullBreakpoints = [
graphLimits[1], graphLimits[1],
@ -226,14 +237,11 @@ const Graph = ({
d.getTime() + d.getTimezoneOffset() * MINUTE d.getTime() + d.getTimezoneOffset() * MINUTE
) )
}) })
.tickSizeOuter(0)
) )
.call(g => g.select('.domain').remove())
.call(g => .call(g =>
g g
.append('line') .select('.domain')
.attr('x1', GRAPH_MARGIN.left)
.attr('y1', -GRAPH_HEIGHT + GRAPH_MARGIN.top + GRAPH_MARGIN.bottom)
.attr('x2', GRAPH_MARGIN.left)
.attr('stroke', primaryColor) .attr('stroke', primaryColor)
.attr('stroke-width', 1) .attr('stroke-width', 1)
), ),
@ -244,18 +252,22 @@ const Graph = ({
g => g =>
g g
.attr('transform', `translate(${GRAPH_MARGIN.left}, 0)`) .attr('transform', `translate(${GRAPH_MARGIN.left}, 0)`)
.call(d3.axisLeft(y).ticks(GRAPH_HEIGHT / 100)) .call(
.call(g => g.select('.domain').remove()) d3
.call(g => .axisLeft(y)
g .ticks(GRAPH_HEIGHT / 100)
.selectAll('.tick line') .tickSizeOuter(0)
.filter(d => d === 0) .tickFormat(d => {
.clone() if (log && !['1', '2', '5'].includes(d.toString()[0])) return ''
.attr('x2', GRAPH_WIDTH - GRAPH_MARGIN.left)
.attr('stroke-width', 1) if (d > 1000) return Math.floor(d / 1000) + 'k'
.attr('stroke', primaryColor) else return d
), })
[GRAPH_MARGIN, y] )
.select('.domain')
.attr('stroke', primaryColor)
.attr('stroke-width', 1),
[GRAPH_MARGIN, y, log]
) )
const buildGrid = useCallback( const buildGrid = useCallback(
@ -484,25 +496,23 @@ const Graph = ({
const buildAvg = useCallback( const buildAvg = useCallback(
g => { g => {
const mean = d3.mean(data, d => new BigNumber(d.fiat).toNumber()) ?? 0
if (log && mean === 0) return
g.attr('stroke', primaryColor) g.attr('stroke', primaryColor)
.attr('stroke-width', 3) .attr('stroke-width', 3)
.attr('stroke-dasharray', '10, 5') .attr('stroke-dasharray', '10, 5')
.call(g => .call(g =>
g g
.append('line') .append('line')
.attr( .attr('y1', 0.5 + y(mean))
'y1', .attr('y2', 0.5 + y(mean))
0.5 + y(d3.mean(data, d => new BigNumber(d.fiat).toNumber()) ?? 0)
)
.attr(
'y2',
0.5 + y(d3.mean(data, d => new BigNumber(d.fiat).toNumber()) ?? 0)
)
.attr('x1', GRAPH_MARGIN.left) .attr('x1', GRAPH_MARGIN.left)
.attr('x2', GRAPH_WIDTH) .attr('x2', GRAPH_WIDTH)
) )
}, },
[GRAPH_MARGIN, y, data] [GRAPH_MARGIN, y, data, log]
) )
const drawData = useCallback( const drawData = useCallback(
@ -561,5 +571,6 @@ export default memo(
Graph, Graph,
(prev, next) => (prev, next) =>
R.equals(prev.period, next.period) && R.equals(prev.period, next.period) &&
R.equals(prev.selectedMachine, next.selectedMachine) R.equals(prev.selectedMachine, next.selectedMachine) &&
R.equals(prev.log, next.log)
) )