diff --git a/new-lamassu-admin/src/pages/Dashboard/Dashboard.js b/new-lamassu-admin/src/pages/Dashboard/Dashboard.js
index d446593c..6a6eeb0b 100644
--- a/new-lamassu-admin/src/pages/Dashboard/Dashboard.js
+++ b/new-lamassu-admin/src/pages/Dashboard/Dashboard.js
@@ -1,7 +1,6 @@
import { useQuery } from '@apollo/react-hooks'
import Grid from '@material-ui/core/Grid'
import { makeStyles } from '@material-ui/core/styles'
-import classnames from 'classnames'
import gql from 'graphql-tag'
import * as R from 'ramda'
import React, { useState } from 'react'
@@ -13,6 +12,7 @@ import { H1, Info2, TL2, Label1 } from 'src/components/typography'
import AddMachine from 'src/pages/AddMachine'
import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.svg'
import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg'
+import { errorColor } from 'src/styling/variables'
import styles from './Dashboard.styles'
import Footer from './Footer'
@@ -46,20 +46,20 @@ const Dashboard = () => {
<>
- <>
-
-
- Cash-out
-
-
-
- Cash-in
-
- >
+
+
+ Cash-in
+
+
+
+ Cash-out
+
+
+
+ Action Required
+
diff --git a/new-lamassu-admin/src/pages/Dashboard/Dashboard.styles.js b/new-lamassu-admin/src/pages/Dashboard/Dashboard.styles.js
index 6526c4a4..a13b54d7 100644
--- a/new-lamassu-admin/src/pages/Dashboard/Dashboard.styles.js
+++ b/new-lamassu-admin/src/pages/Dashboard/Dashboard.styles.js
@@ -12,18 +12,26 @@ const { label1 } = typographyStyles
const styles = {
headerLabels: {
display: 'flex',
- flexDirection: 'row'
- },
- headerLabelContainerMargin: {
- marginRight: 24
- },
- headerLabelContainer: {
- display: 'flex',
- alignItems: 'center'
- },
- headerLabelSpan: {
- extend: label1,
- marginLeft: 6
+ flexDirection: 'row',
+ '& > div:first-child': {
+ display: 'flex',
+ alignItems: 'center',
+ marginLeft: 0
+ },
+ '& > div': {
+ display: 'flex',
+ alignItems: 'center',
+ marginLeft: 25
+ },
+ '& > div:last-child': {
+ display: 'flex',
+ alignItems: 'center',
+ marginLeft: 64
+ },
+ '& > div > span': {
+ extend: label1,
+ marginLeft: 7
+ }
},
root: {
flexGrow: 1,
diff --git a/new-lamassu-admin/src/pages/Dashboard/Footer/Footer.js b/new-lamassu-admin/src/pages/Dashboard/Footer/Footer.js
index 2a30909b..5ff9bdd3 100644
--- a/new-lamassu-admin/src/pages/Dashboard/Footer/Footer.js
+++ b/new-lamassu-admin/src/pages/Dashboard/Footer/Footer.js
@@ -1,3 +1,4 @@
+/* eslint-disable no-unused-vars */
import { useQuery } from '@apollo/react-hooks'
import { makeStyles } from '@material-ui/core'
import Grid from '@material-ui/core/Grid'
@@ -27,19 +28,15 @@ const GET_DATA = gql`
}
}
`
+
BigNumber.config({ ROUNDING_MODE: BigNumber.ROUND_HALF_UP })
const useStyles = makeStyles(styles)
const Footer = () => {
const { data } = useQuery(GET_DATA)
- const [expanded, setExpanded] = useState(false)
- const [delayedExpand, setDelayedExpand] = useState(null)
const withCommissions = R.path(['cryptoRates', 'withCommissions'])(data) ?? {}
- const classes = useStyles({
- bigFooter: R.keys(withCommissions).length > 8,
- expanded
- })
+ const classes = useStyles()
const config = R.path(['config'])(data) ?? {}
const canExpand = R.keys(withCommissions).length > 4
@@ -99,31 +96,16 @@ const Footer = () => {
)
}
- const handleMouseEnter = () => {
- setDelayedExpand(setTimeout(() => canExpand && setExpanded(true), 300))
- }
-
- const handleMouseLeave = () => {
- clearTimeout(delayedExpand)
- setExpanded(false)
- }
-
return (
- <>
-
-
-
-
+
+
+
+
{R.keys(withCommissions).map(key => renderFooterItem(key))}
-
- >
+
)
}
diff --git a/new-lamassu-admin/src/pages/Dashboard/Footer/Footer.styles.js b/new-lamassu-admin/src/pages/Dashboard/Footer/Footer.styles.js
index 4af67566..ffc26ed8 100644
--- a/new-lamassu-admin/src/pages/Dashboard/Footer/Footer.styles.js
+++ b/new-lamassu-admin/src/pages/Dashboard/Footer/Footer.styles.js
@@ -17,52 +17,34 @@ const styles = {
txOutMargin: {
marginLeft: spacer * 3
},
- footer: ({ expanded, bigFooter }) => ({
- height:
- expanded && bigFooter
- ? spacer * 12 * 3 + spacer * 3
- : expanded
- ? spacer * 12 * 2 + spacer * 2
- : spacer * 12,
+ tickerLabel: {
+ color: offColor,
+ marginTop: -5
+ },
+ footer1: {
left: 0,
bottom: 0,
position: 'fixed',
width: '100vw',
backgroundColor: white,
textAlign: 'left',
- boxShadow: '0px -1px 10px 0px rgba(50, 50, 50, 0.1)'
- }),
- tickerLabel: {
- color: offColor,
- marginTop: -5
- },
- content: {
- width: 1200,
- backgroundColor: white,
zIndex: 1,
- position: 'fixed',
- bottom: -spacer,
- transform: 'translateY(-100%)'
+ boxShadow: '0px -1px 10px 0px rgba(50, 50, 50, 0.1)',
+ minHeight: spacer * 12,
+ transition: 'min-height 0.5s ease-out',
+ '&:hover': {
+ transition: 'min-height 0.5s ease-in',
+ minHeight: 200
+ }
},
- footerContainer: ({ expanded, bigFooter }) => ({
- marginLeft: spacer * 5,
- height: 100,
- marginTop: expanded && bigFooter ? -300 : expanded ? -200 : -100,
- overflow: !expanded && 'hidden'
- }),
- mouseWatcher: ({ expanded, bigFooter }) => ({
- position: 'fixed',
- bottom: 0,
- left: 0,
- width: '100vw',
- height:
- expanded && bigFooter
- ? spacer * 12 * 3 + spacer * 3
- : expanded
- ? spacer * 12 * 2 + spacer * 2
- : spacer * 12,
- zIndex: 2
- })
+ content1: {
+ width: 1200,
+ maxHeight: 100,
+ backgroundColor: white,
+ zIndex: 2,
+ bottom: -spacer,
+ margin: '0 auto'
+ }
}
export default styles
diff --git a/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/PercentageChart.js b/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/PercentageChart.js
index c51d6e1e..a3d4c1a5 100644
--- a/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/PercentageChart.js
+++ b/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/PercentageChart.js
@@ -8,11 +8,10 @@ import { java, neon, white } from 'src/styling/variables'
const styles = {
wrapper: {
display: 'flex',
- height: 130,
- marginTop: -8
+ height: 142
},
percentageBox: {
- height: 130,
+ height: 142,
borderRadius: 4,
display: 'flex',
alignItems: 'center',
@@ -33,11 +32,11 @@ const styles = {
borderRadius: 2
},
inWidth: {
- width: value => `${value}%`
+ width: value => `${value}%`,
+ marginRight: value => (value === 100 ? 0 : 4)
},
outWidth: {
- width: value => `${100 - value}%`,
- marginRight: 4
+ width: value => `${100 - value}%`
}
}
@@ -59,14 +58,6 @@ const PercentageChart = ({ cashIn, cashOut }) => {
return (
-
- {buildPercentageView(100 - value, 'cashOut')}
-
{
)}>
{buildPercentageView(value, 'cashIn')}
+
+ {buildPercentageView(100 - value, 'cashOut')}
+
)
}
diff --git a/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/RefLineChart.js b/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/RefLineChart.js
index b825f69c..b9f82f44 100644
--- a/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/RefLineChart.js
+++ b/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/RefLineChart.js
@@ -45,7 +45,7 @@ const RefLineChart = ({
const svg = d3.select(svgRef.current)
const margin = { top: 0, right: 0, bottom: 0, left: 0 }
const width = 336 - margin.left - margin.right
- const height = 128 - margin.top - margin.bottom
+ const height = 140 - margin.top - margin.bottom
const massageData = () => {
// if we're viewing transactions for the past day, then we group by hour. If not, we group by day
@@ -148,7 +148,7 @@ const RefLineChart = ({
const y = d3
.scaleLinear()
// 30 is a margin so that the labels and the percentage change label can fit and not overlay the line path
- .range([height, 30])
+ .range([height, 40])
.domain([0, yDomain[1]])
const x = d3
.scaleTime()
diff --git a/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/RefScatterplot.js b/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/RefScatterplot.js
index ace69b0f..cce6dbf2 100644
--- a/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/RefScatterplot.js
+++ b/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/RefScatterplot.js
@@ -1,197 +1,363 @@
+import BigNumber from 'bignumber.js'
import * as d3 from 'd3'
-import { add } from 'date-fns/fp'
-import React, { useEffect, useRef, useCallback } from 'react'
+import { getTimezoneOffset } from 'date-fns-tz'
+import { add, format, startOfWeek, startOfYear } from 'date-fns/fp'
+import React, { useCallback, useEffect, useMemo, useRef } from 'react'
-import { backgroundColor, java, neon } from 'src/styling/variables'
-import { formatDate, toUtc } from 'src/utils/timezones'
+import {
+ java,
+ neon,
+ subheaderDarkColor,
+ offColor,
+ fontSecondary,
+ backgroundColor
+} from 'src/styling/variables'
+import { MINUTE, DAY, WEEK, MONTH } from 'src/utils/time'
-const RefScatterplot = ({ data: realData, timeFrame, timezone }) => {
- const svgRef = useRef()
- const drawGraph = useCallback(() => {
- const svg = d3.select(svgRef.current)
- const margin = { top: 25, right: 0, bottom: 25, left: 15 }
- const width = 555 - margin.left - margin.right
- const height = 150 - margin.top - margin.bottom
- // finds maximum value for the Y axis. Minimum value is 100. If value is multiple of 1000, add 100
- // (this is because the Y axis looks best with multiples of 100)
- const findMaxY = () => {
- if (realData.length === 0) return 100
- const maxvalueTx =
- 100 * Math.ceil(d3.max(realData, t => parseFloat(t.fiat)) / 100)
- const maxY = Math.max(100, maxvalueTx)
- if (maxY % 1000 === 0) return maxY + 100
- return maxY
- }
+const Graph = ({ data, timeFrame, timezone }) => {
+ const ref = useRef(null)
- const timeFormat = v => {
- switch (timeFrame) {
- case 'Week':
- return d3.timeFormat('%a %d')(v)
- case 'Month':
- return d3.timeFormat('%b %d')(v)
- default:
- return formatDate(v, timezone, 'HH:mm')
+ const GRAPH_HEIGHT = 250
+ const GRAPH_WIDTH = 555
+ const GRAPH_MARGIN = useMemo(
+ () => ({
+ top: 20,
+ right: 0.5,
+ bottom: 27,
+ left: 43.5
+ }),
+ []
+ )
+
+ const offset = getTimezoneOffset(timezone)
+ const NOW = Date.now() + offset
+
+ const periodDomains = {
+ Day: [NOW - DAY, NOW],
+ Week: [NOW - WEEK, NOW],
+ Month: [NOW - MONTH, NOW]
+ }
+
+ const dataPoints = useMemo(
+ () => ({
+ Day: {
+ freq: 24,
+ step: 60 * 60 * 1000,
+ tick: d3.utcHour.every(4),
+ labelFormat: '%H:%M'
+ },
+ Week: {
+ freq: 7,
+ step: 24 * 60 * 60 * 1000,
+ tick: d3.utcDay.every(1),
+ labelFormat: '%a %d'
+ },
+ Month: {
+ freq: 30,
+ step: 24 * 60 * 60 * 1000,
+ tick: d3.utcDay.every(2),
+ labelFormat: '%d'
}
- }
+ }),
+ []
+ )
- // changes values of arguments in some d3 function calls to make the graph labels look good according to the selected time frame
- const findXAxisSettings = () => {
- switch (timeFrame) {
- case 'Week':
- return {
- nice: 7,
- ticks: 7,
- subtractDays: 7,
- timeRange: [50, 500]
- }
- case 'Month':
- return {
- nice: 6,
- ticks: 6,
- subtractDays: 30,
- timeRange: [50, 500]
- }
- default:
- return {
- nice: null,
- ticks: 4,
- subtractDays: 1,
- timeRange: [50, 500]
- }
+ const getPastAndCurrentDayLabels = useCallback(d => {
+ const currentDate = new Date(d)
+ const currentDateDay = currentDate.getUTCDate()
+ const currentDateWeekday = currentDate.getUTCDay()
+ const currentDateMonth = currentDate.getUTCMonth()
+
+ const previousDate = new Date(currentDate.getTime())
+ previousDate.setUTCDate(currentDateDay - 1)
+
+ const previousDateDay = previousDate.getUTCDate()
+ const previousDateWeekday = previousDate.getUTCDay()
+ const previousDateMonth = previousDate.getUTCMonth()
+
+ const daysOfWeek = Array.from(Array(7)).map((_, i) =>
+ format('EEE', add({ days: i }, startOfWeek(new Date())))
+ )
+
+ const months = Array.from(Array(12)).map((_, i) =>
+ format('LLL', add({ months: i }, startOfYear(new Date())))
+ )
+
+ return {
+ previous:
+ currentDateMonth !== previousDateMonth
+ ? months[previousDateMonth]
+ : `${daysOfWeek[previousDateWeekday]} ${previousDateDay}`,
+ current:
+ currentDateMonth !== previousDateMonth
+ ? months[currentDateMonth]
+ : `${daysOfWeek[currentDateWeekday]} ${currentDateDay}`
+ }
+ }, [])
+
+ const buildTicks = useCallback(
+ domain => {
+ const points = []
+
+ const roundDate = d => {
+ const step = dataPoints[timeFrame].step
+ return new Date(Math.ceil(d.valueOf() / step) * step)
}
- }
- // sets width of the graph
- svg.attr('width', width)
+ for (let i = 0; i <= dataPoints[timeFrame].freq; i++) {
+ const stepDate = new Date(NOW - i * dataPoints[timeFrame].step)
+ if (roundDate(stepDate) > domain[1]) continue
+ if (stepDate < domain[0]) continue
+ points.push(roundDate(stepDate))
+ }
- // background color for the graph
- svg
- .append('rect')
- .attr('x', 0)
- .attr('y', 0)
- .attr('width', width)
- .attr('height', height + margin.top)
- .attr('fill', backgroundColor)
+ return points
+ },
+ [NOW, dataPoints, timeFrame]
+ )
- // declare g variable where more svg components will be attached
- const g = svg
- .append('g')
- .attr('transform', `translate(${margin.left},${margin.top})`)
+ const x = d3
+ .scaleUtc()
+ .domain(periodDomains[timeFrame])
+ .range([GRAPH_MARGIN.left, GRAPH_WIDTH - GRAPH_MARGIN.right])
- // y axis range: round up to 100 highest data value, if rounds up to 1000, add 100.
- // this keeps the vertical axis nice looking
- const maxY = findMaxY()
- const xAxisSettings = findXAxisSettings()
+ const y = d3
+ .scaleLinear()
+ .domain([
+ 0,
+ (d3.max(data, d => new BigNumber(d.fiat).toNumber()) ?? 1000) * 1.05
+ ])
+ .nice()
+ .range([GRAPH_HEIGHT - GRAPH_MARGIN.bottom, GRAPH_MARGIN.top])
- // y and x scales
- const y = d3
- .scaleLinear()
- .range([height, 0])
- .domain([0, maxY])
- .nice(3)
- const x = d3
- .scaleTime()
- .domain([
- add({ days: -xAxisSettings.subtractDays }, new Date()).valueOf(),
- new Date().valueOf()
- ])
- .range(xAxisSettings.timeRange)
- .nice(xAxisSettings.nice)
+ const buildBackground = useCallback(
+ g => {
+ g.append('rect')
+ .attr('x', 0)
+ .attr('y', GRAPH_MARGIN.top)
+ .attr('width', GRAPH_WIDTH)
+ .attr('height', GRAPH_HEIGHT - GRAPH_MARGIN.top - GRAPH_MARGIN.bottom)
+ .attr('fill', backgroundColor)
+ },
+ [GRAPH_MARGIN]
+ )
- const timeValue = s => {
- const date = toUtc(s)
- return x(date.valueOf())
- }
+ const buildXAxis = useCallback(
+ g =>
+ g
+ .attr(
+ 'transform',
+ `translate(0, ${GRAPH_HEIGHT - GRAPH_MARGIN.bottom})`
+ )
+ .call(
+ d3
+ .axisBottom(x)
+ .ticks(dataPoints[timeFrame].tick)
+ .tickFormat(d => {
+ return d3.timeFormat(dataPoints[timeFrame].labelFormat)(
+ d.getTime() + d.getTimezoneOffset() * MINUTE
+ )
+ })
+ )
+ .call(g => g.select('.domain').remove()),
+ [GRAPH_MARGIN, dataPoints, timeFrame, x]
+ )
- // horizontal gridlines
- const makeYGridlines = () => {
- return d3.axisLeft(y).ticks(4)
- }
- g.append('g')
- .style('color', '#eef1ff')
- .call(
- makeYGridlines()
- .tickSize(-width)
- .tickFormat('')
- )
- .call(g => g.select('.domain').remove())
+ const buildYAxis = useCallback(
+ g =>
+ g
+ .attr('transform', `translate(${GRAPH_MARGIN.left}, 0)`)
+ .call(d3.axisLeft(y).ticks(5))
+ .call(g => g.select('.domain').remove())
+ .selectAll('text')
+ .attr('dy', '-0.25rem'),
+ [GRAPH_MARGIN, y]
+ )
- /* X AXIS */
- // this one is for the labels at the bottom
- g.append('g')
- .attr('transform', 'translate(0,' + height + ')')
- .style('font-size', '13px')
- .style('color', '#5f668a')
- .style('font-family', 'MuseoSans')
- .style('margin-top', '11px')
- .call(
- d3
- .axisBottom(x)
- .ticks(xAxisSettings.ticks)
- .tickSize(0)
- .tickFormat(timeFormat)
- )
- .selectAll('text')
- .attr('dy', '1.5em')
- // this is for the x axis line. It is the same color as the horizontal grid lines
- g.append('g')
- .attr('transform', 'translate(0,' + height + ')')
- .style('color', '#eef1ff')
- .call(
- d3
- .axisBottom(x)
- .ticks(6)
- .tickSize(0)
- .tickFormat('')
- )
- .selectAll('text')
- .attr('dy', '1.5em')
+ const buildGrid = useCallback(
+ g => {
+ g.attr('stroke', subheaderDarkColor)
+ .attr('fill', subheaderDarkColor)
+ // Vertical lines
+ .call(g =>
+ g
+ .append('g')
+ .selectAll('line')
+ .data(buildTicks(x.domain()))
+ .join('line')
+ .attr('x1', d => 0.5 + x(d))
+ .attr('x2', d => 0.5 + x(d))
+ .attr('y1', GRAPH_MARGIN.top)
+ .attr('y2', GRAPH_HEIGHT - GRAPH_MARGIN.bottom)
+ .attr('stroke-width', 1)
+ )
+ // Horizontal lines
+ .call(g =>
+ g
+ .append('g')
+ .selectAll('line')
+ .data(
+ d3
+ .axisLeft(y)
+ .scale()
+ .ticks(5)
+ )
+ .join('line')
+ .attr('y1', d => 0.5 + y(d))
+ .attr('y2', d => 0.5 + y(d))
+ .attr('x1', GRAPH_MARGIN.left)
+ .attr('x2', GRAPH_WIDTH - GRAPH_MARGIN.right)
+ )
+ // Thick vertical lines
+ .call(g =>
+ g
+ .append('g')
+ .selectAll('line')
+ .data(
+ buildTicks(x.domain()).filter(x => {
+ if (timeFrame === 'day') return x.getUTCHours() === 0
+ return x.getUTCDate() === 1
+ })
+ )
+ .join('line')
+ .attr('class', 'dateSeparator')
+ .attr('x1', d => 0.5 + x(d))
+ .attr('x2', d => 0.5 + x(d))
+ .attr('y1', GRAPH_MARGIN.top - 10)
+ .attr('y2', GRAPH_HEIGHT - GRAPH_MARGIN.bottom)
+ .attr('stroke-width', 2)
+ .join('text')
+ )
+ // Left side breakpoint label
+ .call(g => {
+ const separator = d3
+ ?.select('.dateSeparator')
+ ?.node()
+ ?.getBBox()
- // Y axis
- g.append('g')
- .style('font-size', '13px')
- .style('color', '#5f668a')
- .style('font-family', 'MuseoSans')
- .style('margin-top', '11px')
- .call(
- d3
- .axisLeft(y)
- .ticks(4)
- .tickSize(0)
- )
- .call(g => g.select('.domain').remove())
- .selectAll('text')
- .attr('dy', '-0.40em')
- .attr('dx', '3em')
+ if (!separator) return
- // Append dots
- const dots = svg
- .append('g')
- .attr('transform', `translate(${margin.left},${margin.top})`)
+ const breakpoint = buildTicks(x.domain()).filter(x => {
+ if (timeFrame === 'day') return x.getUTCHours() === 0
+ return x.getUTCDate() === 1
+ })
- dots
- .selectAll('circle')
- .data(realData)
- .enter()
- .append('circle')
- .attr('cx', d => timeValue(d.created))
- .attr('cy', d => y(d.fiat))
- .attr('r', 4)
- .style('fill', d => (d.txClass === 'cashIn' ? java : neon))
- }, [realData, timeFrame, timezone])
+ const labels = getPastAndCurrentDayLabels(breakpoint)
+
+ return g
+ .append('text')
+ .attr('x', separator.x - 7)
+ .attr('y', separator.y)
+ .attr('text-anchor', 'end')
+ .attr('dy', '.25em')
+ .text(labels.previous)
+ })
+ // Right side breakpoint label
+ .call(g => {
+ const separator = d3
+ ?.select('.dateSeparator')
+ ?.node()
+ ?.getBBox()
+
+ if (!separator) return
+
+ const breakpoint = buildTicks(x.domain()).filter(x => {
+ if (timeFrame === 'day') return x.getUTCHours() === 0
+ return x.getUTCDate() === 1
+ })
+
+ const labels = getPastAndCurrentDayLabels(breakpoint)
+
+ return g
+ .append('text')
+ .attr('x', separator.x + 7)
+ .attr('y', separator.y)
+ .attr('text-anchor', 'start')
+ .attr('dy', '.25em')
+ .text(labels.current)
+ })
+ },
+ [GRAPH_MARGIN, buildTicks, getPastAndCurrentDayLabels, x, y, timeFrame]
+ )
+
+ const formatTicksText = useCallback(
+ () =>
+ d3
+ .selectAll('.tick text')
+ .style('stroke', offColor)
+ .style('fill', offColor)
+ .style('stroke-width', 0)
+ .style('font-family', fontSecondary),
+ []
+ )
+
+ const formatText = useCallback(
+ () =>
+ d3
+ .selectAll('text')
+ .style('stroke', offColor)
+ .style('fill', offColor)
+ .style('stroke-width', 0)
+ .style('font-family', fontSecondary),
+ []
+ )
+
+ const formatTicks = useCallback(() => {
+ d3.selectAll('.tick line')
+ .style('stroke', 'transparent')
+ .style('fill', 'transparent')
+ }, [])
+
+ const drawData = useCallback(
+ g => {
+ g.selectAll('circle')
+ .data(data)
+ .join('circle')
+ .attr('cx', d => {
+ const created = new Date(d.created)
+ return x(created.setTime(created.getTime() + offset))
+ })
+ .attr('cy', d => y(new BigNumber(d.fiat).toNumber()))
+ .attr('fill', d => (d.txClass === 'cashIn' ? java : neon))
+ .attr('r', 3.5)
+ },
+ [data, offset, x, y]
+ )
+
+ const drawChart = useCallback(() => {
+ const svg = d3
+ .select(ref.current)
+ .attr('viewBox', [0, 0, GRAPH_WIDTH, GRAPH_HEIGHT])
+
+ svg.append('g').call(buildBackground)
+ svg.append('g').call(buildGrid)
+ svg.append('g').call(buildXAxis)
+ svg.append('g').call(buildYAxis)
+ svg.append('g').call(formatTicksText)
+ svg.append('g').call(formatText)
+ svg.append('g').call(formatTicks)
+ svg.append('g').call(drawData)
+
+ return svg.node()
+ }, [
+ buildBackground,
+ buildGrid,
+ buildXAxis,
+ buildYAxis,
+ drawData,
+ formatText,
+ formatTicks,
+ formatTicksText
+ ])
useEffect(() => {
- // first we clear old chart DOM elements on component update
- d3.select(svgRef.current)
+ d3.select(ref.current)
.selectAll('*')
.remove()
- drawGraph()
- }, [drawGraph])
+ drawChart()
+ }, [drawChart])
- return (
- <>
-
- >
- )
+ return
}
-export default RefScatterplot
+
+export default Graph
diff --git a/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/SystemPerformance.js b/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/SystemPerformance.js
index 500c1bd8..341f3385 100644
--- a/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/SystemPerformance.js
+++ b/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/SystemPerformance.js
@@ -9,10 +9,11 @@ import * as R from 'ramda'
import React, { useState } from 'react'
import { EmptyTable } from 'src/components/table'
-import { Label1, Label2 } from 'src/components/typography/index'
+import { Label1, Label2, P } from 'src/components/typography/index'
import { ReactComponent as PercentDownIcon } from 'src/styling/icons/dashboard/down.svg'
import { ReactComponent as PercentNeutralIcon } from 'src/styling/icons/dashboard/equal.svg'
import { ReactComponent as PercentUpIcon } from 'src/styling/icons/dashboard/up.svg'
+import { java, neon } from 'src/styling/variables'
import { fromNamespace } from 'src/utils/config'
import { toTimezone } from 'src/utils/timezones'
@@ -199,9 +200,27 @@ const SystemPerformance = () => {
{/* todo new customers */}
-
+
- Transactions
+
+
Transactions
+
+
{timezone} timezone
+
+
+
+ In
+
+
+
+ Out
+
+
+
{
/>
-
+
-
+
Profit from commissions
@@ -233,23 +252,22 @@ const SystemPerformance = () => {
/>
-
-
- Direction
-
-
-
- Out
-
-
-
- In
-
+
+ Direction
+
+
+
+ In
+
+
+
+ Out
+
+
div': {
+ display: 'flex',
+ flexDirection: 'row',
+ alignItems: 'center',
+ marginLeft: 15,
+ '&:first-child': {
+ marginLeft: 0
+ },
+ '& > p': {
+ marginLeft: 8
+ }
+ }
+ },
+ txGraphContainer: {
+ height: 300,
+ marginTop: 30
+ },
+ commissionsGraphContainer: {
+ height: 250,
+ marginTop: 30
+ },
+ verticalLine: {
+ height: 15,
+ width: 1,
+ backgroundColor: offDarkColor,
+ marginLeft: 31,
+ marginRight: 16
}
}
diff --git a/new-lamassu-admin/src/pages/Locales/helper.js b/new-lamassu-admin/src/pages/Locales/helper.js
index 3158402e..f4e9aa76 100644
--- a/new-lamassu-admin/src/pages/Locales/helper.js
+++ b/new-lamassu-admin/src/pages/Locales/helper.js
@@ -2,7 +2,7 @@ import * as R from 'ramda'
import * as Yup from 'yup'
import Autocomplete from 'src/components/inputs/formik/Autocomplete.js'
-import timezoneList from 'src/utils/timezone-list'
+import { labels as timezoneList } from 'src/utils/timezone-list'
const getFields = (getData, names, onChange, auxElements = []) => {
return R.filter(
diff --git a/new-lamassu-admin/src/utils/timezone-list.js b/new-lamassu-admin/src/utils/timezone-list.js
index 848cea87..c2d681cd 100644
--- a/new-lamassu-admin/src/utils/timezone-list.js
+++ b/new-lamassu-admin/src/utils/timezone-list.js
@@ -3,85 +3,89 @@ import { getTimezoneOffset } from 'date-fns-tz'
import * as R from 'ramda'
const timezones = {
- 'Pacific/Midway': 'Midway Island, Samoa',
- 'Pacific/Honolulu': 'Hawaii',
- 'America/Juneau': 'Alaska',
- 'America/Boise': 'Mountain Time',
- 'America/Dawson': 'Dawson, Yukon',
- 'America/Chihuahua': 'Chihuahua, La Paz, Mazatlan',
- 'America/Phoenix': 'Arizona',
- 'America/Chicago': 'Central Time',
- 'America/Regina': 'Saskatchewan',
- 'America/Mexico_City': 'Guadalajara, Mexico City, Monterrey',
- 'America/Belize': 'Central America',
- 'America/Detroit': 'Eastern Time',
- 'America/Bogota': 'Bogota, Lima, Quito',
- 'America/Caracas': 'Caracas, La Paz',
- 'America/Santiago': 'Santiago',
- 'America/St_Johns': 'Newfoundland and Labrador',
- 'America/Sao_Paulo': 'Brasilia',
- 'America/Tijuana': 'Tijuana',
- 'America/Montevideo': 'Montevideo',
- 'America/Argentina/Buenos_Aires': 'Buenos Aires, Georgetown',
- 'America/Godthab': 'Greenland',
- 'America/Los_Angeles': 'Pacific Time',
- 'Atlantic/Azores': 'Azores',
- 'Atlantic/Cape_Verde': 'Cape Verde Islands',
- GMT: 'UTC',
- 'Europe/London': 'Edinburgh, London',
- 'Europe/Dublin': 'Dublin',
- 'Europe/Lisbon': 'Lisbon',
- 'Africa/Casablanca': 'Casablanca, Monrovia',
- 'Atlantic/Canary': 'Canary Islands',
- 'Europe/Belgrade': 'Belgrade, Bratislava, Budapest, Ljubljana, Prague',
- 'Europe/Sarajevo': 'Sarajevo, Skopje, Warsaw, Zagreb',
- 'Europe/Brussels': 'Brussels, Copenhagen, Madrid, Paris',
- 'Europe/Amsterdam': 'Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna',
- 'Africa/Algiers': 'West Central Africa',
- 'Europe/Bucharest': 'Bucharest',
- 'Africa/Cairo': 'Cairo',
- 'Europe/Helsinki': 'Helsinki, Kiev, Riga, Sofia, Tallinn, Vilnius',
- 'Europe/Athens': 'Athens, Istanbul, Minsk',
- 'Asia/Jerusalem': 'Jerusalem',
- 'Africa/Harare': 'Harare, Pretoria',
- 'Europe/Moscow': 'Moscow, St. Petersburg, Volgograd',
- 'Asia/Kuwait': 'Kuwait, Riyadh',
- 'Africa/Nairobi': 'Nairobi',
- 'Asia/Baghdad': 'Baghdad',
- 'Asia/Tehran': 'Tehran',
- 'Asia/Dubai': 'Abu Dhabi, Muscat',
- 'Asia/Baku': 'Baku, Tbilisi, Yerevan',
- 'Asia/Kabul': 'Kabul',
- 'Asia/Yekaterinburg': 'Ekaterinburg',
- 'Asia/Karachi': 'Islamabad, Karachi, Tashkent',
- 'Asia/Kolkata': 'Chennai, Kolkata, Mumbai, New Delhi',
- 'Asia/Kathmandu': 'Kathmandu',
- 'Asia/Dhaka': 'Astana, Dhaka',
- 'Asia/Colombo': 'Sri Jayawardenepura',
- 'Asia/Almaty': 'Almaty, Novosibirsk',
- 'Asia/Rangoon': 'Yangon Rangoon',
- 'Asia/Bangkok': 'Bangkok, Hanoi, Jakarta',
- 'Asia/Krasnoyarsk': 'Krasnoyarsk',
- 'Asia/Shanghai': 'Beijing, Chongqing, Hong Kong SAR, Urumqi',
- 'Asia/Kuala_Lumpur': 'Kuala Lumpur, Singapore',
- 'Asia/Taipei': 'Taipei',
- 'Australia/Perth': 'Perth',
- 'Asia/Irkutsk': 'Irkutsk, Ulaanbaatar',
- 'Asia/Seoul': 'Seoul',
- 'Asia/Tokyo': 'Osaka, Sapporo, Tokyo',
- 'Asia/Yakutsk': 'Yakutsk',
- 'Australia/Darwin': 'Darwin',
- 'Australia/Adelaide': 'Adelaide',
- 'Australia/Sydney': 'Canberra, Melbourne, Sydney',
- 'Australia/Brisbane': 'Brisbane',
- 'Australia/Hobart': 'Hobart',
- 'Asia/Vladivostok': 'Vladivostok',
- 'Pacific/Guam': 'Guam, Port Moresby',
- 'Asia/Magadan': 'Magadan, Solomon Islands, New Caledonia',
- 'Asia/Kamchatka': 'Kamchatka, Marshall Islands',
- 'Pacific/Fiji': 'Fiji Islands',
- 'Pacific/Auckland': 'Auckland, Wellington',
- 'Pacific/Tongatapu': "Nuku'alofa"
+ 'Pacific/Midway': { short: 'SST', long: 'Midway Island, Samoa' },
+ 'Pacific/Honolulu': { short: 'HAST', long: 'Hawaii' },
+ 'America/Juneau': { short: 'AKST', long: 'Alaska' },
+ 'America/Boise': { long: 'Mountain Time' },
+ 'America/Dawson': { long: 'Dawson, Yukon' },
+ 'America/Chihuahua': { long: 'Chihuahua, La Paz, Mazatlan' },
+ 'America/Phoenix': { long: 'Arizona' },
+ 'America/Chicago': { long: 'Central Time' },
+ 'America/Regina': { long: 'Saskatchewan' },
+ 'America/Mexico_City': { long: 'Guadalajara, Mexico City, Monterrey' },
+ 'America/Belize': { long: 'Central America' },
+ 'America/Detroit': { long: 'Eastern Time' },
+ 'America/Bogota': { long: 'Bogota, Lima, Quito' },
+ 'America/Caracas': { long: 'Caracas, La Paz' },
+ 'America/Santiago': { long: 'Santiago' },
+ 'America/St_Johns': { long: 'Newfoundland and Labrador' },
+ 'America/Sao_Paulo': { long: 'Brasilia' },
+ 'America/Tijuana': { long: 'Tijuana' },
+ 'America/Montevideo': { long: 'Montevideo' },
+ 'America/Argentina/Buenos_Aires': { long: 'Buenos Aires, Georgetown' },
+ 'America/Godthab': { long: 'Greenland' },
+ 'America/Los_Angeles': { long: 'Pacific Time' },
+ 'Atlantic/Azores': { long: 'Azores' },
+ 'Atlantic/Cape_Verde': { long: 'Cape Verde Islands' },
+ GMT: { long: 'UTC' },
+ 'Europe/London': { long: 'Edinburgh, London' },
+ 'Europe/Dublin': { long: 'Dublin' },
+ 'Europe/Lisbon': { long: 'Lisbon' },
+ 'Africa/Casablanca': { long: 'Casablanca, Monrovia' },
+ 'Atlantic/Canary': { long: 'Canary Islands' },
+ 'Europe/Belgrade': {
+ long: 'Belgrade, Bratislava, Budapest, Ljubljana, Prague'
+ },
+ 'Europe/Sarajevo': { long: 'Sarajevo, Skopje, Warsaw, Zagreb' },
+ 'Europe/Brussels': { long: 'Brussels, Copenhagen, Madrid, Paris' },
+ 'Europe/Amsterdam': {
+ long: 'Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna'
+ },
+ 'Africa/Algiers': { long: 'West Central Africa' },
+ 'Europe/Bucharest': { long: 'Bucharest' },
+ 'Africa/Cairo': { long: 'Cairo' },
+ 'Europe/Helsinki': { long: 'Helsinki, Kiev, Riga, Sofia, Tallinn, Vilnius' },
+ 'Europe/Athens': { long: 'Athens, Istanbul, Minsk' },
+ 'Asia/Jerusalem': { long: 'Jerusalem' },
+ 'Africa/Harare': { long: 'Harare, Pretoria' },
+ 'Europe/Moscow': { long: 'Moscow, St. Petersburg, Volgograd' },
+ 'Asia/Kuwait': { long: 'Kuwait, Riyadh' },
+ 'Africa/Nairobi': { long: 'Nairobi' },
+ 'Asia/Baghdad': { long: 'Baghdad' },
+ 'Asia/Tehran': { long: 'Tehran' },
+ 'Asia/Dubai': { long: 'Abu Dhabi, Muscat' },
+ 'Asia/Baku': { long: 'Baku, Tbilisi, Yerevan' },
+ 'Asia/Kabul': { long: 'Kabul' },
+ 'Asia/Yekaterinburg': { long: 'Ekaterinburg' },
+ 'Asia/Karachi': { long: 'Islamabad, Karachi, Tashkent' },
+ 'Asia/Kolkata': { long: 'Chennai, Kolkata, Mumbai, New Delhi' },
+ 'Asia/Kathmandu': { long: 'Kathmandu' },
+ 'Asia/Dhaka': { long: 'Astana, Dhaka' },
+ 'Asia/Colombo': { long: 'Sri Jayawardenepura' },
+ 'Asia/Almaty': { long: 'Almaty, Novosibirsk' },
+ 'Asia/Rangoon': { long: 'Yangon Rangoon' },
+ 'Asia/Bangkok': { long: 'Bangkok, Hanoi, Jakarta' },
+ 'Asia/Krasnoyarsk': { long: 'Krasnoyarsk' },
+ 'Asia/Shanghai': { long: 'Beijing, Chongqing, Hong Kong SAR, Urumqi' },
+ 'Asia/Kuala_Lumpur': { long: 'Kuala Lumpur, Singapore' },
+ 'Asia/Taipei': { long: 'Taipei' },
+ 'Australia/Perth': { long: 'Perth' },
+ 'Asia/Irkutsk': { long: 'Irkutsk, Ulaanbaatar' },
+ 'Asia/Seoul': { long: 'Seoul' },
+ 'Asia/Tokyo': { long: 'Osaka, Sapporo, Tokyo' },
+ 'Asia/Yakutsk': { long: 'Yakutsk' },
+ 'Australia/Darwin': { long: 'Darwin' },
+ 'Australia/Adelaide': { long: 'Adelaide' },
+ 'Australia/Sydney': { long: 'Canberra, Melbourne, Sydney' },
+ 'Australia/Brisbane': { long: 'Brisbane' },
+ 'Australia/Hobart': { long: 'Hobart' },
+ 'Asia/Vladivostok': { long: 'Vladivostok' },
+ 'Pacific/Guam': { long: 'Guam, Port Moresby' },
+ 'Asia/Magadan': { long: 'Magadan, Solomon Islands, New Caledonia' },
+ 'Asia/Kamchatka': { long: 'Kamchatka, Marshall Islands' },
+ 'Pacific/Fiji': { long: 'Fiji Islands' },
+ 'Pacific/Auckland': { long: 'Auckland, Wellington' },
+ 'Pacific/Tongatapu': { long: "Nuku'alofa" }
}
const buildTzLabels = timezoneList => {
@@ -106,7 +110,7 @@ const buildTzLabels = timezoneList => {
const prefix = `(GMT${isNegative ? `-` : `+`}${hours}:${minutes})`
acc.push({
- label: `${prefix} - ${value[1]}`,
+ label: `${prefix} - ${value[1].long}`,
code: value[0]
})
@@ -117,4 +121,6 @@ const buildTzLabels = timezoneList => {
)
}
-export default buildTzLabels(timezones)
+const labels = buildTzLabels(timezones)
+
+export { labels, timezones }