partial: Dashboard and Locales css migration
This commit is contained in:
parent
d7b2e12f94
commit
5f81487dcc
25 changed files with 314 additions and 883 deletions
|
|
@ -1,10 +1,8 @@
|
||||||
import Grid from '@mui/material/Grid'
|
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classnames from 'classnames'
|
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import { white } from 'src/styling/variables'
|
import Paper from '@mui/material/Paper'
|
||||||
|
import classnames from 'classnames'
|
||||||
|
|
||||||
const cardState = Object.freeze({
|
const cardState = Object.freeze({
|
||||||
DEFAULT: 'default',
|
DEFAULT: 'default',
|
||||||
|
|
@ -12,24 +10,11 @@ const cardState = Object.freeze({
|
||||||
EXPANDED: 'expanded'
|
EXPANDED: 'expanded'
|
||||||
})
|
})
|
||||||
|
|
||||||
const styles = {
|
|
||||||
card: {
|
|
||||||
wordWrap: 'break-word',
|
|
||||||
boxShadow: '0 0 4px 0 rgba(0, 0, 0, 0.08)',
|
|
||||||
borderRadius: 12,
|
|
||||||
padding: 24,
|
|
||||||
backgroundColor: white
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const CollapsibleCard = ({ className, state, shrunkComponent, children }) => {
|
const CollapsibleCard = ({ className, state, shrunkComponent, children }) => {
|
||||||
const classes = useStyles()
|
|
||||||
return (
|
return (
|
||||||
<Grid item className={classnames(className, classes.card)}>
|
<Paper className={classnames('p-6', className)}>
|
||||||
{state === cardState.SHRUNK ? shrunkComponent : children}
|
{state === cardState.SHRUNK ? shrunkComponent : children}
|
||||||
</Grid>
|
</Paper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,12 @@
|
||||||
import { useQuery, gql } from "@apollo/client";
|
import { useQuery, gql } from '@apollo/client'
|
||||||
import Button from '@mui/material/Button'
|
import Button from '@mui/material/Button'
|
||||||
import Grid from '@mui/material/Grid'
|
import Grid from '@mui/material/Grid'
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { cardState } from 'src/components/CollapsibleCard'
|
import { cardState } from 'src/components/CollapsibleCard'
|
||||||
import { Label1, H4 } from 'src/components/typography'
|
import { Label1, H4 } from 'src/components/typography'
|
||||||
|
|
||||||
import styles from './Alerts.styles'
|
|
||||||
import AlertsTable from './AlertsTable'
|
import AlertsTable from './AlertsTable'
|
||||||
|
|
||||||
const NUM_TO_RENDER = 3
|
const NUM_TO_RENDER = 3
|
||||||
|
|
@ -31,10 +29,7 @@ const GET_ALERTS = gql`
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const Alerts = ({ onReset, onExpand, size }) => {
|
const Alerts = ({ onReset, onExpand, size }) => {
|
||||||
const classes = useStyles()
|
|
||||||
const showAllItems = size === cardState.EXPANDED
|
const showAllItems = size === cardState.EXPANDED
|
||||||
const { data } = useQuery(GET_ALERTS)
|
const { data } = useQuery(GET_ALERTS)
|
||||||
const alerts = R.path(['alerts'])(data) ?? []
|
const alerts = R.path(['alerts'])(data) ?? []
|
||||||
|
|
@ -44,35 +39,30 @@ const Alerts = ({ onReset, onExpand, size }) => {
|
||||||
)(data?.machines ?? [])
|
)(data?.machines ?? [])
|
||||||
const alertsLength = alerts.length
|
const alertsLength = alerts.length
|
||||||
|
|
||||||
const alertsTableContainerClasses = {
|
|
||||||
[classes.alertsTableContainer]: !showAllItems,
|
|
||||||
[classes.expandedAlertsTableContainer]: showAllItems
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={classes.container}>
|
<div className="flex justify-between">
|
||||||
<H4 className={classes.h4}>{`Alerts (${alertsLength})`}</H4>
|
<H4 noMargin>{`Alerts (${alertsLength})`}</H4>
|
||||||
{showAllItems && (
|
{showAllItems && (
|
||||||
<Label1 className={classes.upperButtonLabel}>
|
<Label1 noMargin className="-mt-1">
|
||||||
<Button
|
<Button
|
||||||
onClick={onReset}
|
onClick={onReset}
|
||||||
size="small"
|
size="small"
|
||||||
disableRipple
|
disableRipple
|
||||||
disableFocusRipple
|
disableFocusRipple
|
||||||
className={classes.button}>
|
className="p-0 text-zodiac normal-case">
|
||||||
{'Show less'}
|
{'Show less'}
|
||||||
</Button>
|
</Button>
|
||||||
</Label1>
|
</Label1>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<Grid
|
<Grid
|
||||||
className={classnames(alertsTableContainerClasses)}
|
className={classnames({ 'm-0': true, 'max-h-115': showAllItems })}
|
||||||
container
|
container
|
||||||
spacing={1}>
|
spacing={1}>
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
{!alerts.length && (
|
{!alerts.length && (
|
||||||
<Label1 className={classes.noAlertsLabel}>
|
<Label1 className="text-comet -ml-1 h-30">
|
||||||
No new alerts. Your system is running smoothly.
|
No new alerts. Your system is running smoothly.
|
||||||
</Label1>
|
</Label1>
|
||||||
)}
|
)}
|
||||||
|
|
@ -85,13 +75,13 @@ const Alerts = ({ onReset, onExpand, size }) => {
|
||||||
</Grid>
|
</Grid>
|
||||||
{!showAllItems && alertsLength > NUM_TO_RENDER && (
|
{!showAllItems && alertsLength > NUM_TO_RENDER && (
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<Label1 className={classes.centerLabel}>
|
<Label1 className="text-center mb-0">
|
||||||
<Button
|
<Button
|
||||||
onClick={() => onExpand('alerts')}
|
onClick={() => onExpand('alerts')}
|
||||||
size="small"
|
size="small"
|
||||||
disableRipple
|
disableRipple
|
||||||
disableFocusRipple
|
disableFocusRipple
|
||||||
className={classes.button}>
|
className="p-0 text-zodiac normal-case">
|
||||||
{`Show all (${alerts.length})`}
|
{`Show all (${alerts.length})`}
|
||||||
</Button>
|
</Button>
|
||||||
</Label1>
|
</Label1>
|
||||||
|
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
import { primaryColor, comet } from 'src/styling/variables'
|
|
||||||
|
|
||||||
const styles = {
|
|
||||||
container: {
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'space-between'
|
|
||||||
},
|
|
||||||
h4: {
|
|
||||||
margin: 0,
|
|
||||||
marginBottom: 10
|
|
||||||
},
|
|
||||||
centerLabel: {
|
|
||||||
marginBottom: 0,
|
|
||||||
padding: 0,
|
|
||||||
textAlign: 'center'
|
|
||||||
},
|
|
||||||
upperButtonLabel: {
|
|
||||||
marginTop: -3,
|
|
||||||
marginBottom: 24
|
|
||||||
},
|
|
||||||
button: {
|
|
||||||
color: primaryColor,
|
|
||||||
marginTop: 0,
|
|
||||||
minHeight: 0,
|
|
||||||
minWidth: 0,
|
|
||||||
padding: 0,
|
|
||||||
textTransform: 'none',
|
|
||||||
'&:hover': {
|
|
||||||
backgroundColor: 'transparent'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
alertsTableContainer: {
|
|
||||||
margin: 0
|
|
||||||
},
|
|
||||||
expandedAlertsTableContainer: {
|
|
||||||
margin: 0,
|
|
||||||
maxHeight: 460
|
|
||||||
},
|
|
||||||
noAlertsLabel: {
|
|
||||||
color: comet,
|
|
||||||
marginLeft: -5,
|
|
||||||
height: 100
|
|
||||||
},
|
|
||||||
table: {
|
|
||||||
maxHeight: 465,
|
|
||||||
overflowX: 'hidden',
|
|
||||||
overflowY: 'auto'
|
|
||||||
},
|
|
||||||
listItemText: {
|
|
||||||
margin: '8px 0 8px 0'
|
|
||||||
},
|
|
||||||
linkIcon: {
|
|
||||||
marginLeft: 'auto',
|
|
||||||
cursor: 'pointer'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export default styles
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import List from '@mui/material/List'
|
import List from '@mui/material/List'
|
||||||
import ListItem from '@mui/material/ListItem'
|
import ListItem from '@mui/material/ListItem'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
|
|
@ -10,9 +9,6 @@ import CashBoxEmpty from 'src/styling/icons/cassettes/cashbox-empty.svg?react'
|
||||||
import AlertLinkIcon from 'src/styling/icons/month arrows/right.svg?react'
|
import AlertLinkIcon from 'src/styling/icons/month arrows/right.svg?react'
|
||||||
import WarningIcon from 'src/styling/icons/warning-icon/tomato.svg?react'
|
import WarningIcon from 'src/styling/icons/warning-icon/tomato.svg?react'
|
||||||
|
|
||||||
import styles from './Alerts.styles'
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const icons = {
|
const icons = {
|
||||||
error: <WarningIcon style={{ height: 20, width: 20, marginRight: 12 }} />,
|
error: <WarningIcon style={{ height: 20, width: 20, marginRight: 12 }} />,
|
||||||
fiatBalance: (
|
fiatBalance: (
|
||||||
|
|
@ -28,7 +24,6 @@ const links = {
|
||||||
|
|
||||||
const AlertsTable = ({ numToRender, alerts, machines }) => {
|
const AlertsTable = ({ numToRender, alerts, machines }) => {
|
||||||
const history = useHistory()
|
const history = useHistory()
|
||||||
const classes = useStyles()
|
|
||||||
const alertsToRender = R.slice(0, numToRender, alerts)
|
const alertsToRender = R.slice(0, numToRender, alerts)
|
||||||
|
|
||||||
const alertMessage = alert => {
|
const alertMessage = alert => {
|
||||||
|
|
@ -40,16 +35,16 @@ const AlertsTable = ({ numToRender, alerts, machines }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<List dense className={classes.table}>
|
<List dense className="max-h-116 overflow-y-auto overflow-x-hidden">
|
||||||
{alertsToRender.map((alert, idx) => {
|
{alertsToRender.map((alert, idx) => {
|
||||||
return (
|
return (
|
||||||
<ListItem key={idx}>
|
<ListItem key={idx}>
|
||||||
{icons[alert.type] || (
|
{icons[alert.type] || (
|
||||||
<Wrench style={{ height: 23, width: 23, marginRight: 8 }} />
|
<Wrench style={{ height: 23, width: 23, marginRight: 8 }} />
|
||||||
)}
|
)}
|
||||||
<P className={classes.listItemText}>{alertMessage(alert)}</P>
|
<P className="my-2">{alertMessage(alert)}</P>
|
||||||
<AlertLinkIcon
|
<AlertLinkIcon
|
||||||
className={classes.linkIcon}
|
className="ml-auto cursor-pointer"
|
||||||
onClick={() => history.push(links[alert.type] || '/dashboard')}
|
onClick={() => history.push(links[alert.type] || '/dashboard')}
|
||||||
/>
|
/>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
import { useQuery, gql } from "@apollo/client";
|
import { useQuery, gql } from '@apollo/client'
|
||||||
import Grid from '@mui/material/Grid'
|
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { useHistory } from 'react-router-dom'
|
import { useHistory } from 'react-router-dom'
|
||||||
|
|
@ -13,11 +11,10 @@ import { Button } from 'src/components/buttons'
|
||||||
import AddMachine from 'src/pages/AddMachine'
|
import AddMachine from 'src/pages/AddMachine'
|
||||||
import { errorColor } from 'src/styling/variables'
|
import { errorColor } from 'src/styling/variables'
|
||||||
|
|
||||||
import styles from './Dashboard.styles'
|
|
||||||
import Footer from './Footer'
|
import Footer from './Footer'
|
||||||
import LeftSide from './LeftSide'
|
|
||||||
import RightSide from './RightSide'
|
import RightSide from './RightSide'
|
||||||
const useStyles = makeStyles(styles)
|
import Paper from '@mui/material/Paper'
|
||||||
|
import SystemPerformance from './SystemPerformance/index.js'
|
||||||
|
|
||||||
const GET_DATA = gql`
|
const GET_DATA = gql`
|
||||||
query getData {
|
query getData {
|
||||||
|
|
@ -30,7 +27,6 @@ const GET_DATA = gql`
|
||||||
|
|
||||||
const Dashboard = () => {
|
const Dashboard = () => {
|
||||||
const history = useHistory()
|
const history = useHistory()
|
||||||
const classes = useStyles()
|
|
||||||
const [open, setOpen] = useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
|
|
||||||
const { data, loading } = useQuery(GET_DATA)
|
const { data, loading } = useQuery(GET_DATA)
|
||||||
|
|
@ -44,16 +40,16 @@ const Dashboard = () => {
|
||||||
!R.isEmpty(data.machines) ? (
|
!R.isEmpty(data.machines) ? (
|
||||||
<>
|
<>
|
||||||
<TitleSection title="Dashboard">
|
<TitleSection title="Dashboard">
|
||||||
<div className={classes.headerLabels}>
|
<div className="flex gap-6">
|
||||||
<div>
|
<div className="flex items-center gap-2">
|
||||||
<TxInIcon />
|
<TxInIcon />
|
||||||
<span>Cash-in</span>
|
<span>Cash-in</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div className="flex items-center gap-2">
|
||||||
<TxOutIcon />
|
<TxOutIcon />
|
||||||
<span>Cash-out</span>
|
<span>Cash-out</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div className="flex items-center gap-2">
|
||||||
<svg width={12} height={12}>
|
<svg width={12} height={12}>
|
||||||
<rect width={12} height={12} rx={3} fill={errorColor} />
|
<rect width={12} height={12} rx={3} fill={errorColor} />
|
||||||
</svg>
|
</svg>
|
||||||
|
|
@ -61,15 +57,15 @@ const Dashboard = () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</TitleSection>
|
</TitleSection>
|
||||||
<div className={classes.root}>
|
<div className="flex mb-30 gap-4">
|
||||||
<Grid container>
|
<div className="flex flex-col flex-1">
|
||||||
<Grid container direction="column" item xs={6}>
|
<Paper className="p-6">
|
||||||
<LeftSide />
|
<SystemPerformance />
|
||||||
</Grid>
|
</Paper>
|
||||||
<Grid container direction="column" item xs={6}>
|
</div>
|
||||||
<RightSide />
|
<div className="flex flex-col flex-1">
|
||||||
</Grid>
|
<RightSide />
|
||||||
</Grid>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Footer />
|
<Footer />
|
||||||
</>
|
</>
|
||||||
|
|
@ -79,17 +75,17 @@ const Dashboard = () => {
|
||||||
<AddMachine close={() => setOpen(false)} onPaired={onPaired} />
|
<AddMachine close={() => setOpen(false)} onPaired={onPaired} />
|
||||||
)}
|
)}
|
||||||
<TitleSection title="Dashboard">
|
<TitleSection title="Dashboard">
|
||||||
<div className={classes.headerLabels}>
|
<div className="flex flex-row">
|
||||||
<span>
|
<span>
|
||||||
<TL2 className={classes.inline}>{data?.serverVersion}</TL2>{' '}
|
<TL2 className="inline">{data?.serverVersion}</TL2>{' '}
|
||||||
<Label1 className={classes.inline}> server version</Label1>
|
<Label1 className="inline"> server version</Label1>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</TitleSection>
|
</TitleSection>
|
||||||
<div className={classes.emptyMachinesRoot}>
|
<div className="h-75 bg-zircon border-zircon2 border-2">
|
||||||
<div className={classes.emptyMachinesContent}>
|
<div className="flex flex-col h-full justify-center items-center gap-6">
|
||||||
<H1 className={classes.offColor}>No machines on your system yet</H1>
|
<H1 className="text-comet2">No machines on your system yet</H1>
|
||||||
<Info2 className={classes.offColor}>
|
<Info2 className="text-comet2">
|
||||||
To fully take advantage of Lamassu Admin, add a new machine to
|
To fully take advantage of Lamassu Admin, add a new machine to
|
||||||
your system
|
your system
|
||||||
</Info2>
|
</Info2>
|
||||||
|
|
|
||||||
|
|
@ -1,120 +0,0 @@
|
||||||
import typographyStyles from 'src/components/typography/styles'
|
|
||||||
import {
|
|
||||||
spacer,
|
|
||||||
white,
|
|
||||||
primaryColor,
|
|
||||||
zircon,
|
|
||||||
zircon2,
|
|
||||||
offDarkColor
|
|
||||||
} from 'src/styling/variables'
|
|
||||||
const { label1 } = typographyStyles
|
|
||||||
|
|
||||||
const styles = {
|
|
||||||
headerLabels: {
|
|
||||||
display: 'flex',
|
|
||||||
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,
|
|
||||||
display: 'flex',
|
|
||||||
marginBottom: 120
|
|
||||||
},
|
|
||||||
emptyMachinesRoot: {
|
|
||||||
height: 300,
|
|
||||||
backgroundColor: zircon,
|
|
||||||
border: `solid 2px ${zircon2}`
|
|
||||||
},
|
|
||||||
card: {
|
|
||||||
wordWrap: 'break-word',
|
|
||||||
boxShadow: '0 0 4px 0 rgba(0, 0, 0, 0.08)',
|
|
||||||
borderRadius: 12,
|
|
||||||
padding: 24,
|
|
||||||
backgroundColor: white,
|
|
||||||
flex: 1,
|
|
||||||
marginRight: 24
|
|
||||||
},
|
|
||||||
container: {
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'space-between'
|
|
||||||
},
|
|
||||||
button: {
|
|
||||||
color: primaryColor,
|
|
||||||
minHeight: 0,
|
|
||||||
minWidth: 0,
|
|
||||||
padding: 0,
|
|
||||||
textTransform: 'none',
|
|
||||||
'&:hover': {
|
|
||||||
backgroundColor: 'transparent'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
upperButtonLabel: {
|
|
||||||
textAlign: 'center',
|
|
||||||
marginBottom: 0,
|
|
||||||
marginTop: 0,
|
|
||||||
marginLeft: spacer
|
|
||||||
},
|
|
||||||
alertsCard: {
|
|
||||||
marginBottom: spacer
|
|
||||||
},
|
|
||||||
h4: {
|
|
||||||
marginTop: 0
|
|
||||||
},
|
|
||||||
centerLabel: {
|
|
||||||
marginTop: 40,
|
|
||||||
marginBottom: 0
|
|
||||||
},
|
|
||||||
systemStatusCard: {
|
|
||||||
flex: 1,
|
|
||||||
marginTop: spacer
|
|
||||||
},
|
|
||||||
expandedCard: {
|
|
||||||
flex: 0.9
|
|
||||||
},
|
|
||||||
shrunkCard: {
|
|
||||||
flex: 0.1
|
|
||||||
},
|
|
||||||
displayFlex: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column'
|
|
||||||
},
|
|
||||||
inline: {
|
|
||||||
display: 'inline'
|
|
||||||
},
|
|
||||||
emptyMachinesContent: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
height: '100%',
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
'& > :first-child': {
|
|
||||||
marginTop: 0
|
|
||||||
},
|
|
||||||
'& > *': {
|
|
||||||
marginTop: 25
|
|
||||||
}
|
|
||||||
},
|
|
||||||
offColor: {
|
|
||||||
color: offDarkColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default styles
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
import { useQuery, gql } from "@apollo/client";
|
import { useQuery, gql } from '@apollo/client'
|
||||||
import { makeStyles } from '@mui/styles'
|
import { makeStyles } from '@mui/styles'
|
||||||
import Grid from '@mui/material/Grid'
|
|
||||||
import BigNumber from 'bignumber.js'
|
import BigNumber from 'bignumber.js'
|
||||||
import classnames from 'classnames'
|
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Label2 } from 'src/components/typography'
|
import { Label2 } from 'src/components/typography'
|
||||||
|
|
@ -11,7 +9,8 @@ import TxOutIcon from 'src/styling/icons/direction/cash-out.svg?react'
|
||||||
|
|
||||||
import { fromNamespace } from 'src/utils/config'
|
import { fromNamespace } from 'src/utils/config'
|
||||||
|
|
||||||
import styles from './Footer.styles'
|
import classes from './Footer.module.css'
|
||||||
|
|
||||||
const GET_DATA = gql`
|
const GET_DATA = gql`
|
||||||
query getData {
|
query getData {
|
||||||
cryptoRates
|
cryptoRates
|
||||||
|
|
@ -29,12 +28,10 @@ const GET_DATA = gql`
|
||||||
|
|
||||||
BigNumber.config({ ROUNDING_MODE: BigNumber.ROUND_HALF_UP })
|
BigNumber.config({ ROUNDING_MODE: BigNumber.ROUND_HALF_UP })
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
const Footer = () => {
|
const Footer = () => {
|
||||||
const { data } = useQuery(GET_DATA)
|
const { data } = useQuery(GET_DATA)
|
||||||
|
|
||||||
const withCommissions = R.path(['cryptoRates', 'withCommissions'])(data) ?? {}
|
const withCommissions = R.path(['cryptoRates', 'withCommissions'])(data) ?? {}
|
||||||
const classes = useStyles()
|
|
||||||
const config = R.path(['config'])(data) ?? {}
|
const config = R.path(['config'])(data) ?? {}
|
||||||
// const canExpand = R.keys(withCommissions).length > 4
|
// const canExpand = R.keys(withCommissions).length > 4
|
||||||
|
|
||||||
|
|
@ -72,36 +69,31 @@ const Footer = () => {
|
||||||
).toFormat(2)
|
).toFormat(2)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid key={key} item xs={3}>
|
<div className="flex flex-col w-1/4">
|
||||||
<Label2 className={classes.label}>
|
<Label2 className="text-comet mt-3 mb-2">
|
||||||
{cryptoCurrencies[idx].display}
|
{cryptoCurrencies[idx].display}
|
||||||
</Label2>
|
</Label2>
|
||||||
<div className={classes.headerLabels}>
|
<div className="flex gap-6">
|
||||||
<div className={classes.headerLabel}>
|
<div className="flex items-center gap-1">
|
||||||
<TxInIcon />
|
<TxInIcon />
|
||||||
<Label2>{` ${cashIn} ${localeFiatCurrency}`}</Label2>
|
<Label2 noMargin>{`${cashIn} ${localeFiatCurrency}`}</Label2>
|
||||||
</div>
|
</div>
|
||||||
<div className={classnames(classes.headerLabel, classes.txOutMargin)}>
|
<div className="flex items-center gap-1">
|
||||||
<TxOutIcon />
|
<TxOutIcon />
|
||||||
<Label2>{` ${cashOut} ${localeFiatCurrency}`}</Label2>
|
<Label2 noMargin>{`${cashOut} ${localeFiatCurrency}`}</Label2>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Label2
|
<Label2 className="text-comet mt-2">
|
||||||
className={
|
{`${tickerName}: ${avgOfAskBid} ${localeFiatCurrency}`}
|
||||||
classes.tickerLabel
|
</Label2>
|
||||||
}>{`${tickerName}: ${avgOfAskBid} ${localeFiatCurrency}`}</Label2>
|
</div>
|
||||||
</Grid>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.footer1}>
|
<div className={classes.footer1}>
|
||||||
<div className={classes.content1}>
|
<div className={classes.content1}>
|
||||||
<Grid container>
|
{R.keys(withCommissions).map(key => renderFooterItem(key))}
|
||||||
<Grid container className={classes.footerContainer1}>
|
|
||||||
{R.keys(withCommissions).map(key => renderFooterItem(key))}
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
.footer1 {
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
position: fixed;
|
||||||
|
width: 100vw;
|
||||||
|
background-color: white;
|
||||||
|
text-align: left;
|
||||||
|
z-index: 1;
|
||||||
|
box-shadow: 0 -1px 10px 0 rgba(50, 50, 50, 0.1);
|
||||||
|
min-height: 48px;
|
||||||
|
transition: min-height 0.5s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer1:hover {
|
||||||
|
transition: min-height 0.5s ease-in;
|
||||||
|
min-height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content1 {
|
||||||
|
width: 1200px;
|
||||||
|
max-height: 100px;
|
||||||
|
background-color: white;
|
||||||
|
z-index: 2;
|
||||||
|
bottom: -8px;
|
||||||
|
margin: 0 auto;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
import { offColor, white, spacer } from 'src/styling/variables'
|
|
||||||
|
|
||||||
const styles = {
|
|
||||||
label: {
|
|
||||||
color: offColor
|
|
||||||
},
|
|
||||||
headerLabels: {
|
|
||||||
whiteSpace: 'pre',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
marginTop: -20
|
|
||||||
},
|
|
||||||
headerLabel: {
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center'
|
|
||||||
},
|
|
||||||
txOutMargin: {
|
|
||||||
marginLeft: spacer * 3
|
|
||||||
},
|
|
||||||
tickerLabel: {
|
|
||||||
color: offColor,
|
|
||||||
marginTop: -5
|
|
||||||
},
|
|
||||||
footer1: {
|
|
||||||
left: 0,
|
|
||||||
bottom: 0,
|
|
||||||
position: 'fixed',
|
|
||||||
width: '100vw',
|
|
||||||
backgroundColor: white,
|
|
||||||
textAlign: 'left',
|
|
||||||
zIndex: 1,
|
|
||||||
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
|
|
||||||
}
|
|
||||||
},
|
|
||||||
content1: {
|
|
||||||
width: 1200,
|
|
||||||
maxHeight: 100,
|
|
||||||
backgroundColor: white,
|
|
||||||
zIndex: 2,
|
|
||||||
bottom: -spacer,
|
|
||||||
margin: '0 auto'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default styles
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
import Grid from '@mui/material/Grid'
|
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import React from 'react'
|
|
||||||
|
|
||||||
import styles from './Dashboard.styles'
|
|
||||||
import SystemPerformance from './SystemPerformance'
|
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const LeftSide = () => {
|
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Grid item xs={12} className={classes.displayFlex}>
|
|
||||||
<div className={classes.card}>
|
|
||||||
<SystemPerformance />
|
|
||||||
</div>
|
|
||||||
</Grid>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LeftSide
|
|
||||||
|
|
@ -1,29 +1,23 @@
|
||||||
import Button from '@mui/material/Button'
|
import Button from '@mui/material/Button'
|
||||||
import Grid from '@mui/material/Grid'
|
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import CollapsibleCard, { cardState } from 'src/components/CollapsibleCard'
|
import CollapsibleCard, { cardState } from 'src/components/CollapsibleCard'
|
||||||
import { H4, Label1 } from 'src/components/typography'
|
import { H4, Label1 } from 'src/components/typography'
|
||||||
|
|
||||||
import Alerts from './Alerts'
|
import Alerts from './Alerts'
|
||||||
import styles from './Dashboard.styles'
|
|
||||||
import SystemStatus from './SystemStatus'
|
import SystemStatus from './SystemStatus'
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const ShrunkCard = ({ title, buttonName, onUnshrink }) => {
|
const ShrunkCard = ({ title, buttonName, onUnshrink }) => {
|
||||||
const classes = useStyles()
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.container}>
|
<div className="flex justify-between">
|
||||||
<H4 className={classes.h4}>{title}</H4>
|
<H4 className="mt-0">{title}</H4>
|
||||||
<Label1 className={classes.upperButtonLabel}>
|
<Label1 className="text-center my-0">
|
||||||
<Button
|
<Button
|
||||||
onClick={onUnshrink}
|
onClick={onUnshrink}
|
||||||
size="small"
|
size="small"
|
||||||
disableRipple
|
disableRipple
|
||||||
disableFocusRipple
|
disableFocusRipple
|
||||||
className={classes.button}>
|
className="p-0 text-zodiac normal-case">
|
||||||
{buttonName}
|
{buttonName}
|
||||||
</Button>
|
</Button>
|
||||||
</Label1>
|
</Label1>
|
||||||
|
|
@ -32,7 +26,6 @@ const ShrunkCard = ({ title, buttonName, onUnshrink }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const RightSide = () => {
|
const RightSide = () => {
|
||||||
const classes = useStyles()
|
|
||||||
const [systemStatusSize, setSystemStatusSize] = useState(cardState.DEFAULT)
|
const [systemStatusSize, setSystemStatusSize] = useState(cardState.DEFAULT)
|
||||||
const [alertsSize, setAlertsSize] = useState(cardState.DEFAULT)
|
const [alertsSize, setAlertsSize] = useState(cardState.DEFAULT)
|
||||||
|
|
||||||
|
|
@ -41,58 +34,55 @@ const RightSide = () => {
|
||||||
setSystemStatusSize(cardState.DEFAULT)
|
setSystemStatusSize(cardState.DEFAULT)
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Grid item xs={12} className={classes.displayFlex}>
|
<div className="flex flex-1 flex-col">
|
||||||
<div style={{ flex: 1, display: 'flex', flexDirection: 'column' }}>
|
<div className="flex-1 flex flex-col gap-4">
|
||||||
<>
|
<CollapsibleCard
|
||||||
<CollapsibleCard
|
className={classnames({
|
||||||
className={classnames({
|
'flex-[0.1]': alertsSize === cardState.SHRUNK,
|
||||||
[classes.alertsCard]: alertsSize !== cardState.SHRUNK,
|
'flex-[0.9]': alertsSize === cardState.EXPANDED
|
||||||
[classes.shrunkCard]: alertsSize === cardState.SHRUNK,
|
})}
|
||||||
[classes.expandedCard]: alertsSize === cardState.EXPANDED
|
state={alertsSize}
|
||||||
})}
|
shrunkComponent={
|
||||||
state={alertsSize}
|
<ShrunkCard
|
||||||
shrunkComponent={
|
title={'Alerts'}
|
||||||
<ShrunkCard
|
buttonName={'Show alerts'}
|
||||||
title={'Alerts'}
|
onUnshrink={onReset}
|
||||||
buttonName={'Show alerts'}
|
|
||||||
onUnshrink={onReset}
|
|
||||||
/>
|
|
||||||
}>
|
|
||||||
<Alerts
|
|
||||||
onExpand={() => {
|
|
||||||
setAlertsSize(cardState.EXPANDED)
|
|
||||||
setSystemStatusSize(cardState.SHRUNK)
|
|
||||||
}}
|
|
||||||
onReset={onReset}
|
|
||||||
size={alertsSize}
|
|
||||||
/>
|
/>
|
||||||
</CollapsibleCard>
|
}>
|
||||||
<CollapsibleCard
|
<Alerts
|
||||||
className={classnames({
|
onExpand={() => {
|
||||||
[classes.shrunkCard]: systemStatusSize === cardState.SHRUNK,
|
setAlertsSize(cardState.EXPANDED)
|
||||||
[classes.systemStatusCard]: systemStatusSize !== cardState.SHRUNK,
|
setSystemStatusSize(cardState.SHRUNK)
|
||||||
[classes.expandedCard]: alertsSize === cardState.EXPANDED
|
}}
|
||||||
})}
|
onReset={onReset}
|
||||||
state={systemStatusSize}
|
size={alertsSize}
|
||||||
shrunkComponent={
|
/>
|
||||||
<ShrunkCard
|
</CollapsibleCard>
|
||||||
title={'System status'}
|
<CollapsibleCard
|
||||||
buttonName={'Show machines'}
|
className={classnames({
|
||||||
onUnshrink={onReset}
|
'flex-[0.1]': systemStatusSize === cardState.SHRUNK,
|
||||||
/>
|
'flex-1': systemStatusSize === cardState.DEFAULT,
|
||||||
}>
|
'flex-[0.9]': systemStatusSize === cardState.EXPANDED
|
||||||
<SystemStatus
|
})}
|
||||||
onExpand={() => {
|
state={systemStatusSize}
|
||||||
setSystemStatusSize(cardState.EXPANDED)
|
shrunkComponent={
|
||||||
setAlertsSize(cardState.SHRUNK)
|
<ShrunkCard
|
||||||
}}
|
title={'System status'}
|
||||||
onReset={onReset}
|
buttonName={'Show machines'}
|
||||||
size={systemStatusSize}
|
onUnshrink={onReset}
|
||||||
/>
|
/>
|
||||||
</CollapsibleCard>
|
}>
|
||||||
</>
|
<SystemStatus
|
||||||
|
onExpand={() => {
|
||||||
|
setSystemStatusSize(cardState.EXPANDED)
|
||||||
|
setAlertsSize(cardState.SHRUNK)
|
||||||
|
}}
|
||||||
|
onReset={onReset}
|
||||||
|
size={systemStatusSize}
|
||||||
|
/>
|
||||||
|
</CollapsibleCard>
|
||||||
</div>
|
</div>
|
||||||
</Grid>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,77 +1,30 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Label1 } from 'src/components/typography/index'
|
import { Label1 } from 'src/components/typography/index'
|
||||||
|
|
||||||
import { java, neon, white } from 'src/styling/variables'
|
|
||||||
|
|
||||||
const styles = {
|
|
||||||
wrapper: {
|
|
||||||
display: 'flex',
|
|
||||||
height: 142
|
|
||||||
},
|
|
||||||
percentageBox: {
|
|
||||||
height: 142,
|
|
||||||
borderRadius: 4,
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
whiteSpace: 'pre'
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
color: white
|
|
||||||
},
|
|
||||||
inColor: {
|
|
||||||
backgroundColor: java
|
|
||||||
},
|
|
||||||
outColor: {
|
|
||||||
backgroundColor: neon
|
|
||||||
},
|
|
||||||
other: {
|
|
||||||
minWidth: '6px',
|
|
||||||
borderRadius: 2
|
|
||||||
},
|
|
||||||
inWidth: {
|
|
||||||
width: value => `${value}%`,
|
|
||||||
marginRight: value => (value === 100 ? 0 : 4)
|
|
||||||
},
|
|
||||||
outWidth: {
|
|
||||||
width: value => `${100 - value}%`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const PercentageChart = ({ cashIn, cashOut }) => {
|
const PercentageChart = ({ cashIn, cashOut }) => {
|
||||||
const value = cashIn || cashOut !== 0 ? cashIn : 50
|
const value = cashIn || cashOut !== 0 ? cashIn : 50
|
||||||
const classes = useStyles(value)
|
|
||||||
|
|
||||||
const buildPercentageView = value => {
|
const buildPercentageView = value => {
|
||||||
if (value <= 15) return
|
if (value <= 15) return
|
||||||
return <Label1 className={classes.label}>{value}%</Label1>
|
return <Label1 className="text-white">{value}%</Label1>
|
||||||
}
|
}
|
||||||
|
|
||||||
const percentageClasses = {
|
const percentageClasses = {
|
||||||
[classes.percentageBox]: true,
|
'h-35 rounded-sm flex items-center justify-center': true,
|
||||||
[classes.other]: value < 5 && value > 0
|
'min-w-2 rounded-xs': value < 5 && value > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.wrapper}>
|
<div className="flex h-35 gap-1">
|
||||||
<div
|
<div
|
||||||
className={classnames(
|
className={classnames(percentageClasses, 'bg-java')}
|
||||||
percentageClasses,
|
style={{ width: `${value}%` }}>
|
||||||
classes.inColor,
|
|
||||||
classes.inWidth
|
|
||||||
)}>
|
|
||||||
{buildPercentageView(value, 'cashIn')}
|
{buildPercentageView(value, 'cashIn')}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={classnames(
|
className={classnames(percentageClasses, 'bg-neon')}
|
||||||
percentageClasses,
|
style={{ width: `${100 - value}%` }}>
|
||||||
classes.outColor,
|
|
||||||
classes.outWidth
|
|
||||||
)}>
|
|
||||||
{buildPercentageView(100 - value, 'cashOut')}
|
{buildPercentageView(100 - value, 'cashOut')}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@ import * as d3 from 'd3'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useEffect, useRef, useCallback } from 'react'
|
import React, { useEffect, useRef, useCallback } from 'react'
|
||||||
|
|
||||||
import { backgroundColor, zircon, primaryColor } from 'src/styling/variables'
|
|
||||||
|
|
||||||
const transactionProfit = R.prop('profit')
|
const transactionProfit = R.prop('profit')
|
||||||
|
|
||||||
const mockPoint = (tx, offsetMs, profit) => {
|
const mockPoint = (tx, offsetMs, profit) => {
|
||||||
|
|
@ -106,7 +104,7 @@ const RefLineChart = ({
|
||||||
.attr('y', -margin.top)
|
.attr('y', -margin.top)
|
||||||
.attr('width', width + margin.left + margin.right)
|
.attr('width', width + margin.left + margin.right)
|
||||||
.attr('height', height + margin.top)
|
.attr('height', height + margin.top)
|
||||||
.attr('fill', backgroundColor)
|
.attr('fill', 'var(--ghost)')
|
||||||
.attr('transform', `translate(${0},${margin.top})`)
|
.attr('transform', `translate(${0},${margin.top})`)
|
||||||
|
|
||||||
// gradient color for the graph (creates the "url", the color is applied by calling the url, in the area color fill )
|
// gradient color for the graph (creates the "url", the color is applied by calling the url, in the area color fill )
|
||||||
|
|
@ -120,9 +118,9 @@ const RefLineChart = ({
|
||||||
.attr('y2', '100%')
|
.attr('y2', '100%')
|
||||||
.selectAll('stop')
|
.selectAll('stop')
|
||||||
.data([
|
.data([
|
||||||
{ offset: '0%', color: zircon },
|
{ offset: '0%', color: 'var(--zircon)' },
|
||||||
{ offset: '25%', color: zircon },
|
{ offset: '25%', color: 'var(--zircon)' },
|
||||||
{ offset: '100%', color: backgroundColor }
|
{ offset: '100%', color: 'var(--ghost)' }
|
||||||
])
|
])
|
||||||
.enter()
|
.enter()
|
||||||
.append('stop')
|
.append('stop')
|
||||||
|
|
@ -181,7 +179,7 @@ const RefLineChart = ({
|
||||||
.attr('fill', 'none')
|
.attr('fill', 'none')
|
||||||
.attr('stroke-width', '2')
|
.attr('stroke-width', '2')
|
||||||
.attr('stroke-linejoin', 'round')
|
.attr('stroke-linejoin', 'round')
|
||||||
.attr('stroke', primaryColor)
|
.attr('stroke', 'var(--zodiac)')
|
||||||
}, [realData, timeFrame, previousTimeData, previousProfit])
|
}, [realData, timeFrame, previousTimeData, previousProfit])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,6 @@ import { getTimezoneOffset } from 'date-fns-tz'
|
||||||
import { add, format, startOfWeek, startOfYear } from 'date-fns/fp'
|
import { add, format, startOfWeek, startOfYear } from 'date-fns/fp'
|
||||||
import React, { useCallback, useEffect, useMemo, useRef } from 'react'
|
import React, { useCallback, useEffect, useMemo, useRef } from 'react'
|
||||||
|
|
||||||
import {
|
|
||||||
java,
|
|
||||||
neon,
|
|
||||||
subheaderDarkColor,
|
|
||||||
offColor,
|
|
||||||
fontSecondary,
|
|
||||||
backgroundColor
|
|
||||||
} from 'src/styling/variables'
|
|
||||||
import { numberToFiatAmount } from 'src/utils/number'
|
import { numberToFiatAmount } from 'src/utils/number'
|
||||||
import { MINUTE, DAY, WEEK, MONTH } from 'src/utils/time'
|
import { MINUTE, DAY, WEEK, MONTH } from 'src/utils/time'
|
||||||
|
|
||||||
|
|
@ -143,7 +135,7 @@ const Graph = ({ data, timeFrame, timezone }) => {
|
||||||
.attr('y', GRAPH_MARGIN.top)
|
.attr('y', GRAPH_MARGIN.top)
|
||||||
.attr('width', GRAPH_WIDTH)
|
.attr('width', GRAPH_WIDTH)
|
||||||
.attr('height', GRAPH_HEIGHT - GRAPH_MARGIN.top - GRAPH_MARGIN.bottom)
|
.attr('height', GRAPH_HEIGHT - GRAPH_MARGIN.top - GRAPH_MARGIN.bottom)
|
||||||
.attr('fill', backgroundColor)
|
.attr('fill', 'var(--ghost)')
|
||||||
},
|
},
|
||||||
[GRAPH_MARGIN]
|
[GRAPH_MARGIN]
|
||||||
)
|
)
|
||||||
|
|
@ -191,8 +183,8 @@ const Graph = ({ data, timeFrame, timezone }) => {
|
||||||
|
|
||||||
const buildGrid = useCallback(
|
const buildGrid = useCallback(
|
||||||
g => {
|
g => {
|
||||||
g.attr('stroke', subheaderDarkColor)
|
g.attr('stroke', 'var(--zircon2)')
|
||||||
.attr('fill', subheaderDarkColor)
|
.attr('fill', 'var(--zircon2)')
|
||||||
// Vertical lines
|
// Vertical lines
|
||||||
.call(g =>
|
.call(g =>
|
||||||
g
|
g
|
||||||
|
|
@ -277,10 +269,10 @@ const Graph = ({ data, timeFrame, timezone }) => {
|
||||||
() =>
|
() =>
|
||||||
d3
|
d3
|
||||||
.selectAll('.tick text')
|
.selectAll('.tick text')
|
||||||
.style('stroke', offColor)
|
.style('stroke', 'var(--comet)')
|
||||||
.style('fill', offColor)
|
.style('fill', 'var(--comet)')
|
||||||
.style('stroke-width', 0)
|
.style('stroke-width', 0)
|
||||||
.style('font-family', fontSecondary),
|
.style('font-family', 'var(--museo)'),
|
||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -288,10 +280,10 @@ const Graph = ({ data, timeFrame, timezone }) => {
|
||||||
() =>
|
() =>
|
||||||
d3
|
d3
|
||||||
.selectAll('text')
|
.selectAll('text')
|
||||||
.style('stroke', offColor)
|
.style('stroke', 'var(--comet)')
|
||||||
.style('fill', offColor)
|
.style('fill', 'var(--comet)')
|
||||||
.style('stroke-width', 0)
|
.style('stroke-width', 0)
|
||||||
.style('font-family', fontSecondary),
|
.style('font-family', 'var(--museo)'),
|
||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -311,7 +303,9 @@ const Graph = ({ data, timeFrame, timezone }) => {
|
||||||
return x(created.setTime(created.getTime() + offset))
|
return x(created.setTime(created.getTime() + offset))
|
||||||
})
|
})
|
||||||
.attr('cy', d => y(new BigNumber(d.fiat).toNumber()))
|
.attr('cy', d => y(new BigNumber(d.fiat).toNumber()))
|
||||||
.attr('fill', d => (d.txClass === 'cashIn' ? java : neon))
|
.attr('fill', d =>
|
||||||
|
d.txClass === 'cashIn' ? 'var(--java)' : 'var(--neon)'
|
||||||
|
)
|
||||||
.attr('r', 3.5)
|
.attr('r', 3.5)
|
||||||
},
|
},
|
||||||
[data, offset, x, y]
|
[data, offset, x, y]
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@ import React from 'react'
|
||||||
import { Info1, Label1 } from 'src/components/typography/index'
|
import { Info1, Label1 } from 'src/components/typography/index'
|
||||||
const InfoWithLabel = ({ info, label }) => {
|
const InfoWithLabel = ({ info, label }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="flex flex-col">
|
||||||
<Info1 style={{ marginBottom: 0 }}>{info}</Info1>
|
<Info1 className="mb-0">{info}</Info1>
|
||||||
<Label1 style={{ margin: 0 }}>{label}</Label1>
|
<Label1 className="m-0">{label}</Label1>
|
||||||
</>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,11 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { H4 } from 'src/components/typography'
|
import { H4 } from 'src/components/typography'
|
||||||
|
|
||||||
import styles from './SystemPerformance.styles'
|
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
const ranges = ['Month', 'Week', 'Day']
|
const ranges = ['Month', 'Week', 'Day']
|
||||||
|
|
||||||
const Nav = ({ handleSetRange, showPicker }) => {
|
const Nav = ({ handleSetRange, showPicker }) => {
|
||||||
const classes = useStyles()
|
|
||||||
const [clickedItem, setClickedItem] = useState('Day')
|
const [clickedItem, setClickedItem] = useState('Day')
|
||||||
|
|
||||||
const isSelected = R.equals(clickedItem)
|
const isSelected = R.equals(clickedItem)
|
||||||
|
|
@ -20,22 +15,20 @@ const Nav = ({ handleSetRange, showPicker }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classnames(classes.titleWrapper)}>
|
<div className="flex justify-between items-center">
|
||||||
<div className={classes.titleAndButtonsContainer}>
|
<H4 noMargin>{'System performance'}</H4>
|
||||||
<H4 className={classes.h4}>{'System performance'}</H4>
|
|
||||||
</div>
|
|
||||||
{showPicker && (
|
{showPicker && (
|
||||||
<div className={classes.navContainer}>
|
<div className="flex gap-6">
|
||||||
{ranges.map((it, idx) => {
|
{ranges.map((it, idx) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={idx}
|
key={idx}
|
||||||
onClick={e => handleClick(e.target.innerText)}
|
onClick={e => handleClick(e.target.innerText)}
|
||||||
className={
|
className={classnames({
|
||||||
isSelected(it)
|
'cursor-pointer text-comet': true,
|
||||||
? classnames(classes.newHighlightedLabel, classes.navButton)
|
'font-bold text-zodiac border-b-zodiac border-b-2':
|
||||||
: classnames(classes.label, classes.navButton)
|
isSelected(it)
|
||||||
}>
|
})}>
|
||||||
{it}
|
{it}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,10 @@
|
||||||
import { useQuery, gql } from "@apollo/client";
|
import { useQuery, gql } from '@apollo/client'
|
||||||
import Grid from '@mui/material/Grid'
|
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import BigNumber from 'bignumber.js'
|
import BigNumber from 'bignumber.js'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import { isAfter } from 'date-fns/fp'
|
import { isAfter } from 'date-fns/fp'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { Label1, Label2, P } from 'src/components/typography/index'
|
import { Info2, Label1, Label2, P } from 'src/components/typography/index'
|
||||||
import PercentDownIcon from 'src/styling/icons/dashboard/down.svg?react'
|
import PercentDownIcon from 'src/styling/icons/dashboard/down.svg?react'
|
||||||
import PercentNeutralIcon from 'src/styling/icons/dashboard/equal.svg?react'
|
import PercentNeutralIcon from 'src/styling/icons/dashboard/equal.svg?react'
|
||||||
import PercentUpIcon from 'src/styling/icons/dashboard/up.svg?react'
|
import PercentUpIcon from 'src/styling/icons/dashboard/up.svg?react'
|
||||||
|
|
@ -23,12 +21,10 @@ import LineChart from './Graphs/RefLineChart'
|
||||||
import Scatterplot from './Graphs/RefScatterplot'
|
import Scatterplot from './Graphs/RefScatterplot'
|
||||||
import InfoWithLabel from './InfoWithLabel'
|
import InfoWithLabel from './InfoWithLabel'
|
||||||
import Nav from './Nav'
|
import Nav from './Nav'
|
||||||
import styles from './SystemPerformance.styles'
|
|
||||||
|
|
||||||
BigNumber.config({ ROUNDING_MODE: BigNumber.ROUND_HALF_UP })
|
BigNumber.config({ ROUNDING_MODE: BigNumber.ROUND_HALF_UP })
|
||||||
|
|
||||||
const getFiats = R.map(R.prop('fiat'))
|
const getFiats = R.map(R.prop('fiat'))
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const GET_DATA = gql`
|
const GET_DATA = gql`
|
||||||
query getData($excludeTestingCustomers: Boolean) {
|
query getData($excludeTestingCustomers: Boolean) {
|
||||||
|
|
@ -54,7 +50,6 @@ const GET_DATA = gql`
|
||||||
`
|
`
|
||||||
|
|
||||||
const SystemPerformance = () => {
|
const SystemPerformance = () => {
|
||||||
const classes = useStyles()
|
|
||||||
const [selectedRange, setSelectedRange] = useState('Day')
|
const [selectedRange, setSelectedRange] = useState('Day')
|
||||||
const { data, loading } = useQuery(GET_DATA, {
|
const { data, loading } = useQuery(GET_DATA, {
|
||||||
variables: { excludeTestingCustomers: true }
|
variables: { excludeTestingCustomers: true }
|
||||||
|
|
@ -162,17 +157,17 @@ const SystemPerformance = () => {
|
||||||
const percentChange = getPercentChange()
|
const percentChange = getPercentChange()
|
||||||
|
|
||||||
const percentageClasses = {
|
const percentageClasses = {
|
||||||
[classes.percentDown]: percentChange < 0,
|
'text-tomato': percentChange < 0,
|
||||||
[classes.percentUp]: percentChange > 0,
|
'text-spring4': percentChange > 0,
|
||||||
[classes.percentNeutral]: percentChange === 0
|
'text-comet': percentChange === 0,
|
||||||
|
'flex items-center justify-center gap-1': true
|
||||||
}
|
}
|
||||||
|
|
||||||
const getPercentageIcon = () => {
|
const getPercentageIcon = () => {
|
||||||
if (percentChange === 0)
|
const className = 'w-4 h-4'
|
||||||
return <PercentNeutralIcon className={classes.directionIcon} />
|
if (percentChange === 0) return <PercentNeutralIcon className={className} />
|
||||||
if (percentChange > 0)
|
if (percentChange > 0) return <PercentUpIcon className={className} />
|
||||||
return <PercentUpIcon className={classes.directionIcon} />
|
return <PercentDownIcon className={className} />
|
||||||
return <PercentDownIcon className={classes.directionIcon} />
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -182,74 +177,67 @@ const SystemPerformance = () => {
|
||||||
handleSetRange={setSelectedRange}
|
handleSetRange={setSelectedRange}
|
||||||
/>
|
/>
|
||||||
{!loading && R.isEmpty(data.transactions) && (
|
{!loading && R.isEmpty(data.transactions) && (
|
||||||
<EmptyTable
|
<EmptyTable className="pt-10" message="No transactions so far" />
|
||||||
className={classes.emptyTransactions}
|
|
||||||
message="No transactions so far"
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
{!loading && !R.isEmpty(data.transactions) && (
|
{!loading && !R.isEmpty(data.transactions) && (
|
||||||
<>
|
<div className="flex flex-col gap-12">
|
||||||
<Grid container spacing={2}>
|
<div className="flex gap-16">
|
||||||
<Grid item xs={3}>
|
<InfoWithLabel info={getNumTransactions()} label={'transactions'} />
|
||||||
<InfoWithLabel
|
<InfoWithLabel
|
||||||
info={getNumTransactions()}
|
info={getFiatVolume()}
|
||||||
label={'transactions'}
|
label={`${data?.config.locale_fiatCurrency} volume`}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</div>
|
||||||
<Grid item xs={3}>
|
<div className="h-62">
|
||||||
<InfoWithLabel
|
<div className="flex justify-between mb-4">
|
||||||
info={getFiatVolume()}
|
<Label2 noMargin>Transactions</Label2>
|
||||||
label={`${data?.config.locale_fiatCurrency} volume`}
|
<div className="flex items-center">
|
||||||
/>
|
<P noMargin>
|
||||||
</Grid>
|
{timezones[timezone]?.short ?? timezones[timezone]?.long}{' '}
|
||||||
{/* todo new customers */}
|
timezone
|
||||||
</Grid>
|
</P>
|
||||||
<Grid container className={classes.txGraphContainer}>
|
<span className="h-4 w-[1px] bg-comet2 mr-4 ml-8" />
|
||||||
<Grid item xs={12}>
|
<div className="flex flex-row gap-4">
|
||||||
<div className={classes.graphHeader}>
|
<div className="flex items-center">
|
||||||
<Label2 noMargin>Transactions</Label2>
|
|
||||||
<div className={classes.labelWrapper}>
|
|
||||||
<P noMargin>
|
|
||||||
{timezones[timezone]?.short ?? timezones[timezone]?.long}{' '}
|
|
||||||
timezone
|
|
||||||
</P>
|
|
||||||
<span className={classes.verticalLine} />
|
|
||||||
<div>
|
|
||||||
<svg width={8} height={8}>
|
<svg width={8} height={8}>
|
||||||
<rect width={8} height={8} rx={4} fill={java} />
|
<rect width={8} height={8} rx={4} fill={java} />
|
||||||
</svg>
|
</svg>
|
||||||
<Label1 noMargin>In</Label1>
|
<Label1 noMargin className="ml-2">
|
||||||
|
In
|
||||||
|
</Label1>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div className="flex items-center">
|
||||||
<svg width={8} height={8}>
|
<svg width={8} height={8}>
|
||||||
<rect width={8} height={8} rx={4} fill={neon} />
|
<rect width={8} height={8} rx={4} fill={neon} />
|
||||||
</svg>
|
</svg>
|
||||||
<Label1 noMargin>Out</Label1>
|
<Label1 noMargin className="ml-2">
|
||||||
|
Out
|
||||||
|
</Label1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Scatterplot
|
</div>
|
||||||
timeFrame={selectedRange}
|
<Scatterplot
|
||||||
data={transactionsToShow}
|
timeFrame={selectedRange}
|
||||||
timezone={timezone}
|
data={transactionsToShow}
|
||||||
/>
|
timezone={timezone}
|
||||||
</Grid>
|
/>
|
||||||
</Grid>
|
</div>
|
||||||
<Grid container className={classes.commissionGraphContainer}>
|
<div className="flex h-62">
|
||||||
<Grid item xs={8}>
|
<div className="flex-2">
|
||||||
<Label2 noMargin className={classes.commissionProfitTitle}>
|
<Label2 noMargin className="mb-4">
|
||||||
Profit from commissions
|
Profit from commissions
|
||||||
</Label2>
|
</Label2>
|
||||||
<div className={classes.profitContainer}>
|
<div className="flex justify-between mt-6 mr-7 -mb-8 ml-4 relative">
|
||||||
<div className={classes.profitLabel}>
|
<Info2 noMargin>
|
||||||
{`${getProfit(transactionsToShow).toFormat(2)} ${
|
{`${getProfit(transactionsToShow).toFormat(2)} ${
|
||||||
data?.config.locale_fiatCurrency
|
data?.config.locale_fiatCurrency
|
||||||
}`}
|
}`}
|
||||||
</div>
|
</Info2>
|
||||||
<div className={classnames(percentageClasses)}>
|
<Info2 noMargin className={classnames(percentageClasses)}>
|
||||||
{getPercentageIcon()}
|
{getPercentageIcon()}
|
||||||
{`${new BigNumber(percentChange).toFormat(2)}%`}
|
{`${new BigNumber(percentChange).toFormat(2)}%`}
|
||||||
</div>
|
</Info2>
|
||||||
</div>
|
</div>
|
||||||
<LineChart
|
<LineChart
|
||||||
timeFrame={selectedRange}
|
timeFrame={selectedRange}
|
||||||
|
|
@ -257,34 +245,36 @@ const SystemPerformance = () => {
|
||||||
previousTimeData={transactionsLastTimePeriod}
|
previousTimeData={transactionsLastTimePeriod}
|
||||||
previousProfit={getProfit(transactionsLastTimePeriod)}
|
previousProfit={getProfit(transactionsLastTimePeriod)}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</div>
|
||||||
<Grid item xs={4}>
|
<div className="flex-1">
|
||||||
<Grid container className={classes.graphHeader}>
|
<div className="flex items-center justify-between mb-4">
|
||||||
<Label2 noMargin>Direction</Label2>
|
<Label2 noMargin>Direction</Label2>
|
||||||
<div className={classes.labelWrapper}>
|
<div className="flex flex-row gap-4">
|
||||||
<div>
|
<div className="flex items-center">
|
||||||
<svg width={8} height={8}>
|
<svg width={8} height={8}>
|
||||||
<rect width={8} height={8} rx={2} fill={java} />
|
<rect width={8} height={8} rx={2} fill={java} />
|
||||||
</svg>
|
</svg>
|
||||||
<Label1 noMargin>In</Label1>
|
<Label1 noMargin className="ml-2">
|
||||||
|
In
|
||||||
|
</Label1>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div className="flex items-center">
|
||||||
<svg width={8} height={8}>
|
<svg width={8} height={8}>
|
||||||
<rect width={8} height={8} rx={2} fill={neon} />
|
<rect width={8} height={8} rx={2} fill={neon} />
|
||||||
</svg>
|
</svg>
|
||||||
<Label1 noMargin>Out</Label1>
|
<Label1 noMargin className="ml-2">
|
||||||
|
Out
|
||||||
|
</Label1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Grid>
|
</div>
|
||||||
<Grid item xs>
|
<PercentageChart
|
||||||
<PercentageChart
|
cashIn={getDirectionPercent().cashIn}
|
||||||
cashIn={getDirectionPercent().cashIn}
|
cashOut={getDirectionPercent().cashOut}
|
||||||
cashOut={getDirectionPercent().cashOut}
|
/>
|
||||||
/>
|
</div>
|
||||||
</Grid>
|
</div>
|
||||||
</Grid>
|
</div>
|
||||||
</Grid>
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,154 +0,0 @@
|
||||||
import {
|
|
||||||
offColor,
|
|
||||||
offDarkColor,
|
|
||||||
spacer,
|
|
||||||
primaryColor,
|
|
||||||
fontSize3,
|
|
||||||
fontSecondary,
|
|
||||||
fontColor,
|
|
||||||
spring4,
|
|
||||||
tomato,
|
|
||||||
comet
|
|
||||||
} from 'src/styling/variables'
|
|
||||||
|
|
||||||
const styles = {
|
|
||||||
titleWrapper: {
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
alignItems: 'center',
|
|
||||||
flexDirection: 'row'
|
|
||||||
},
|
|
||||||
titleAndButtonsContainer: {
|
|
||||||
display: 'flex'
|
|
||||||
},
|
|
||||||
error: {
|
|
||||||
marginLeft: 12
|
|
||||||
},
|
|
||||||
icon: {
|
|
||||||
marginRight: 6
|
|
||||||
},
|
|
||||||
h4: {
|
|
||||||
margin: 0,
|
|
||||||
marginRight: spacer * 8
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
cursor: 'pointer',
|
|
||||||
minHeight: 0,
|
|
||||||
minWidth: 0,
|
|
||||||
padding: 0,
|
|
||||||
color: offColor,
|
|
||||||
textTransform: 'none',
|
|
||||||
borderBottom: `2px solid transparent`,
|
|
||||||
display: 'inline-block',
|
|
||||||
lineHeight: 1.5,
|
|
||||||
'&:hover': {
|
|
||||||
backgroundColor: 'transparent'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
newHighlightedLabel: {
|
|
||||||
cursor: 'pointer',
|
|
||||||
color: primaryColor,
|
|
||||||
fontWeight: 700,
|
|
||||||
borderRadius: 0,
|
|
||||||
minHeight: 0,
|
|
||||||
minWidth: 0,
|
|
||||||
textTransform: 'none',
|
|
||||||
borderBottom: `2px solid ${primaryColor}`,
|
|
||||||
display: 'inline-block',
|
|
||||||
lineHeight: 1.5,
|
|
||||||
'&:hover': {
|
|
||||||
backgroundColor: 'transparent'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
navButton: {
|
|
||||||
marginLeft: 24
|
|
||||||
},
|
|
||||||
navContainer: {
|
|
||||||
display: 'flex'
|
|
||||||
},
|
|
||||||
percentUp: {
|
|
||||||
fontSize: fontSize3,
|
|
||||||
fontFamily: fontSecondary,
|
|
||||||
fontWeight: 700,
|
|
||||||
color: spring4,
|
|
||||||
height: 10
|
|
||||||
},
|
|
||||||
percentDown: {
|
|
||||||
fontSize: fontSize3,
|
|
||||||
fontFamily: fontSecondary,
|
|
||||||
fontWeight: 700,
|
|
||||||
color: tomato,
|
|
||||||
height: 13
|
|
||||||
},
|
|
||||||
percentNeutral: {
|
|
||||||
fontSize: fontSize3,
|
|
||||||
fontFamily: fontSecondary,
|
|
||||||
fontWeight: 700,
|
|
||||||
color: comet
|
|
||||||
},
|
|
||||||
profitContainer: {
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
margin: '23px 26px -30px 16px',
|
|
||||||
position: 'relative'
|
|
||||||
},
|
|
||||||
profitLabel: {
|
|
||||||
fontSize: fontSize3,
|
|
||||||
fontFamily: fontSecondary,
|
|
||||||
fontWeight: 700,
|
|
||||||
color: fontColor
|
|
||||||
},
|
|
||||||
directionIcon: {
|
|
||||||
width: 16,
|
|
||||||
height: 16,
|
|
||||||
marginBottom: -2,
|
|
||||||
marginRight: 4
|
|
||||||
},
|
|
||||||
emptyTransactions: {
|
|
||||||
paddingTop: 40
|
|
||||||
},
|
|
||||||
commissionProfitTitle: {
|
|
||||||
marginBottom: 16
|
|
||||||
},
|
|
||||||
graphHeader: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
marginBottom: 16
|
|
||||||
},
|
|
||||||
labelWrapper: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center',
|
|
||||||
'& > 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default styles
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
import { useQuery, gql } from "@apollo/client";
|
import { useQuery, gql } from '@apollo/client'
|
||||||
import { makeStyles, withStyles } from '@mui/styles'
|
import { styled } from '@mui/material/styles'
|
||||||
import Table from '@mui/material/Table'
|
import Table from '@mui/material/Table'
|
||||||
import TableBody from '@mui/material/TableBody'
|
import TableBody from '@mui/material/TableBody'
|
||||||
import TableCell from '@mui/material/TableCell'
|
import TableCell from '@mui/material/TableCell'
|
||||||
import TableContainer from '@mui/material/TableContainer'
|
import TableContainer from '@mui/material/TableContainer'
|
||||||
import TableHead from '@mui/material/TableHead'
|
import TableHead from '@mui/material/TableHead'
|
||||||
import TableRow from '@mui/material/TableRow'
|
import TableRow from '@mui/material/TableRow'
|
||||||
import classnames from 'classnames'
|
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { useHistory } from 'react-router-dom'
|
import { useHistory } from 'react-router-dom'
|
||||||
|
|
@ -15,11 +14,8 @@ import { Label2, TL2 } from 'src/components/typography'
|
||||||
import TxOutIcon from 'src/styling/icons/direction/cash-out.svg?react'
|
import TxOutIcon from 'src/styling/icons/direction/cash-out.svg?react'
|
||||||
import MachineLinkIcon from 'src/styling/icons/month arrows/right.svg?react'
|
import MachineLinkIcon from 'src/styling/icons/month arrows/right.svg?react'
|
||||||
|
|
||||||
// import TxInIcon from 'src/styling/icons/direction/cash-in.svg?react'
|
|
||||||
import { fromNamespace } from 'src/utils/config'
|
import { fromNamespace } from 'src/utils/config'
|
||||||
|
|
||||||
import styles from './MachinesTable.styles'
|
|
||||||
|
|
||||||
// percentage threshold where below this number the text in the cash cassettes percentage turns red
|
// percentage threshold where below this number the text in the cash cassettes percentage turns red
|
||||||
const PERCENTAGE_THRESHOLD = 20
|
const PERCENTAGE_THRESHOLD = 20
|
||||||
|
|
||||||
|
|
@ -29,27 +25,20 @@ const GET_CONFIG = gql`
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
const StyledCell = styled(TableCell)({
|
||||||
|
borderBottom: '4px solid white',
|
||||||
|
padding: 0,
|
||||||
|
paddingLeft: '15px'
|
||||||
|
})
|
||||||
|
|
||||||
const StyledCell = withStyles({
|
const HeaderCell = styled(TableCell)({
|
||||||
root: {
|
borderBottom: '4px solid white',
|
||||||
borderBottom: '4px solid white',
|
padding: 0,
|
||||||
padding: 0,
|
paddingLeft: '15px',
|
||||||
paddingLeft: 15
|
backgroundColor: 'white'
|
||||||
}
|
})
|
||||||
})(TableCell)
|
|
||||||
|
|
||||||
const HeaderCell = withStyles({
|
|
||||||
root: {
|
|
||||||
borderBottom: '4px solid white',
|
|
||||||
padding: 0,
|
|
||||||
paddingLeft: 15,
|
|
||||||
backgroundColor: 'white'
|
|
||||||
}
|
|
||||||
})(TableCell)
|
|
||||||
|
|
||||||
const MachinesTable = ({ machines = [], numToRender }) => {
|
const MachinesTable = ({ machines = [], numToRender }) => {
|
||||||
const classes = useStyles()
|
|
||||||
const history = useHistory()
|
const history = useHistory()
|
||||||
|
|
||||||
const { data } = useQuery(GET_CONFIG)
|
const { data } = useQuery(GET_CONFIG)
|
||||||
|
|
@ -69,7 +58,7 @@ const MachinesTable = ({ machines = [], numToRender }) => {
|
||||||
R.defaultTo(PERCENTAGE_THRESHOLD)
|
R.defaultTo(PERCENTAGE_THRESHOLD)
|
||||||
)(fillingPercentageSettings)
|
)(fillingPercentageSettings)
|
||||||
return percent < percentageThreshold ? (
|
return percent < percentageThreshold ? (
|
||||||
<TL2 className={classes.error}>{`${percent}%`}</TL2>
|
<TL2 className="text-tomato">{`${percent}%`}</TL2>
|
||||||
) : (
|
) : (
|
||||||
<TL2>{`${percent}%`}</TL2>
|
<TL2>{`${percent}%`}</TL2>
|
||||||
)
|
)
|
||||||
|
|
@ -87,30 +76,32 @@ const MachinesTable = ({ machines = [], numToRender }) => {
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableContainer className={classes.table}>
|
<TableContainer className="max-h-110">
|
||||||
<Table>
|
<Table>
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<HeaderCell>
|
<HeaderCell>
|
||||||
<div className={classes.header}>
|
<div className="flex items-center">
|
||||||
<Label2 className={classes.label}>Machines</Label2>
|
<Label2 noMargin className="text-comet">
|
||||||
|
Machines
|
||||||
|
</Label2>
|
||||||
</div>
|
</div>
|
||||||
</HeaderCell>
|
</HeaderCell>
|
||||||
<HeaderCell>
|
<HeaderCell>
|
||||||
<div className={`${classes.header} ${classes.statusHeader}`}>
|
<div className="flex items-center">
|
||||||
<Label2 className={classes.label}>Status</Label2>
|
<Label2 noMargin className="text-comet">
|
||||||
|
Status
|
||||||
|
</Label2>
|
||||||
</div>
|
</div>
|
||||||
</HeaderCell>
|
</HeaderCell>
|
||||||
{/* <HeaderCell>
|
|
||||||
<div className={classes.header}>
|
|
||||||
<TxInIcon />
|
|
||||||
</div>
|
|
||||||
</HeaderCell> */}
|
|
||||||
{R.times(R.identity, maxNumberOfCassettes).map((it, idx) => (
|
{R.times(R.identity, maxNumberOfCassettes).map((it, idx) => (
|
||||||
<HeaderCell key={idx}>
|
<HeaderCell key={idx}>
|
||||||
<div className={classes.header}>
|
<div className="flex items-center whitespace-pre">
|
||||||
<TxOutIcon />
|
<TxOutIcon />
|
||||||
<Label2 className={classes.label}> {it + 1}</Label2>
|
<Label2 noMargin className="text-comet">
|
||||||
|
{' '}
|
||||||
|
{it + 1}
|
||||||
|
</Label2>
|
||||||
</div>
|
</div>
|
||||||
</HeaderCell>
|
</HeaderCell>
|
||||||
))}
|
))}
|
||||||
|
|
@ -122,20 +113,23 @@ const MachinesTable = ({ machines = [], numToRender }) => {
|
||||||
return (
|
return (
|
||||||
<TableRow
|
<TableRow
|
||||||
onClick={() => redirect(machine)}
|
onClick={() => redirect(machine)}
|
||||||
className={classnames(classes.row)}
|
className="boder-b-0 bg-ghost"
|
||||||
key={machine.deviceId + idx}>
|
key={machine.deviceId + idx}>
|
||||||
<StyledCell align="left">
|
<TableCell
|
||||||
<div className={classes.machineNameWrapper}>
|
sx={{
|
||||||
|
borderBottom: '4px solid white',
|
||||||
|
padding: 0,
|
||||||
|
paddingLeft: '15px'
|
||||||
|
}}
|
||||||
|
align="left">
|
||||||
|
<div className="flex items-center">
|
||||||
<TL2>{machine.name}</TL2>
|
<TL2>{machine.name}</TL2>
|
||||||
<MachineLinkIcon
|
<MachineLinkIcon
|
||||||
className={classnames(
|
className="cursor-pointer ml-2"
|
||||||
classes.machineRedirectIcon,
|
|
||||||
classes.clickableRow
|
|
||||||
)}
|
|
||||||
onClick={() => redirect(machine)}
|
onClick={() => redirect(machine)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</StyledCell>
|
</TableCell>
|
||||||
<StyledCell>
|
<StyledCell>
|
||||||
<Status status={machine.statuses[0]} />
|
<Status status={machine.statuses[0]} />
|
||||||
</StyledCell>
|
</StyledCell>
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,6 @@ import {
|
||||||
} from 'src/styling/variables'
|
} from 'src/styling/variables'
|
||||||
|
|
||||||
const styles = {
|
const styles = {
|
||||||
container: {
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'space-between'
|
|
||||||
},
|
|
||||||
label: {
|
label: {
|
||||||
margin: 0,
|
margin: 0,
|
||||||
color: offColor
|
color: offColor
|
||||||
|
|
@ -45,30 +41,12 @@ const styles = {
|
||||||
bottom: 160,
|
bottom: 160,
|
||||||
marginBottom: 0
|
marginBottom: 0
|
||||||
},
|
},
|
||||||
upperButtonLabel: {
|
|
||||||
textAlign: 'center',
|
|
||||||
marginBottom: 0,
|
|
||||||
marginTop: 0
|
|
||||||
},
|
|
||||||
statusHeader: {
|
statusHeader: {
|
||||||
marginLeft: 2
|
marginLeft: 2
|
||||||
},
|
},
|
||||||
table: {
|
|
||||||
maxHeight: 440,
|
|
||||||
'&::-webkit-scrollbar': {
|
|
||||||
width: 7
|
|
||||||
},
|
|
||||||
'&::-webkit-scrollbar-thumb': {
|
|
||||||
backgroundColor: offColor,
|
|
||||||
borderRadius: 5
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tableBody: {
|
tableBody: {
|
||||||
overflow: 'auto'
|
overflow: 'auto'
|
||||||
},
|
},
|
||||||
h4: {
|
|
||||||
marginTop: 0
|
|
||||||
},
|
|
||||||
tl2: {
|
tl2: {
|
||||||
display: 'inline'
|
display: 'inline'
|
||||||
},
|
},
|
||||||
|
|
@ -76,11 +54,9 @@ const styles = {
|
||||||
display: 'inline'
|
display: 'inline'
|
||||||
},
|
},
|
||||||
machinesTableContainer: {
|
machinesTableContainer: {
|
||||||
marginTop: 10,
|
|
||||||
height: 220
|
height: 220
|
||||||
},
|
},
|
||||||
expandedMachinesTableContainer: {
|
expandedMachinesTableContainer: {
|
||||||
marginTop: 10,
|
|
||||||
height: 414
|
height: 414
|
||||||
},
|
},
|
||||||
centerLabel: {
|
centerLabel: {
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,12 @@
|
||||||
import { useQuery, gql } from "@apollo/client";
|
import { useQuery, gql } from '@apollo/client'
|
||||||
import Button from '@mui/material/Button'
|
import Button from '@mui/material/Button'
|
||||||
import Grid from '@mui/material/Grid'
|
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { cardState as cardState_ } from 'src/components/CollapsibleCard'
|
import { cardState as cardState_ } from 'src/components/CollapsibleCard'
|
||||||
// import ActionButton from 'src/components/buttons/ActionButton'
|
|
||||||
import { H4, TL2, Label1 } from 'src/components/typography'
|
import { H4, TL2, Label1 } from 'src/components/typography'
|
||||||
|
|
||||||
import MachinesTable from './MachinesTable'
|
import MachinesTable from './MachinesTable'
|
||||||
import styles from './MachinesTable.styles'
|
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
// number of machines in the table to render on page load
|
// number of machines in the table to render on page load
|
||||||
const NUM_TO_RENDER = 4
|
const NUM_TO_RENDER = 4
|
||||||
|
|
@ -59,29 +53,28 @@ const GET_DATA = gql`
|
||||||
} */
|
} */
|
||||||
|
|
||||||
const SystemStatus = ({ onReset, onExpand, size }) => {
|
const SystemStatus = ({ onReset, onExpand, size }) => {
|
||||||
const classes = useStyles()
|
|
||||||
const { data, loading } = useQuery(GET_DATA)
|
const { data, loading } = useQuery(GET_DATA)
|
||||||
|
|
||||||
const machines = R.path(['machines'])(data) ?? []
|
const machines = R.path(['machines'])(data) ?? []
|
||||||
const showAllItems = size === cardState_.EXPANDED
|
const showAllItems = size === cardState_.EXPANDED
|
||||||
|
|
||||||
const machinesTableContainerClasses = {
|
const machinesTableContainerClasses = {
|
||||||
[classes.machinesTableContainer]: !showAllItems,
|
'h-55': !showAllItems,
|
||||||
[classes.expandedMachinesTableContainer]: showAllItems
|
'h-103': showAllItems
|
||||||
}
|
}
|
||||||
// const uptime = data?.uptime ?? [{}]
|
// const uptime = data?.uptime ?? [{}]
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={classes.container}>
|
<div className="flex justify-between">
|
||||||
<H4 className={classes.h4}>System status</H4>{' '}
|
<H4 className="mt-0">System status</H4>
|
||||||
{showAllItems && (
|
{showAllItems && (
|
||||||
<Label1 className={classes.upperButtonLabel}>
|
<Label1 noMargin className="-mt-1">
|
||||||
<Button
|
<Button
|
||||||
onClick={onReset}
|
onClick={onReset}
|
||||||
size="small"
|
size="small"
|
||||||
disableRipple
|
disableRipple
|
||||||
disableFocusRipple
|
disableFocusRipple
|
||||||
className={classes.button}>
|
className="p-0 text-zodiac normal-case">
|
||||||
{'Show less'}
|
{'Show less'}
|
||||||
</Button>
|
</Button>
|
||||||
</Label1>
|
</Label1>
|
||||||
|
|
@ -89,54 +82,29 @@ const SystemStatus = ({ onReset, onExpand, size }) => {
|
||||||
</div>
|
</div>
|
||||||
{!loading && (
|
{!loading && (
|
||||||
<>
|
<>
|
||||||
<Grid container spacing={1}>
|
<div className="mb-4">
|
||||||
{/*
|
<TL2 className="inline">{data?.serverVersion}</TL2>
|
||||||
On hold until system uptime is implemented
|
<Label1 className="inline"> server version</Label1>
|
||||||
<Grid item xs={4}>
|
</div>
|
||||||
<TL2 className={classes.tl2}>
|
<div className={classnames(machinesTableContainerClasses)}>
|
||||||
{parseUptime(uptime[0].time)}
|
<MachinesTable
|
||||||
</TL2>
|
numToRender={showAllItems ? Infinity : NUM_TO_RENDER}
|
||||||
<Label1 className={classes.label1}> System up time</Label1>
|
machines={machines}
|
||||||
</Grid> */}
|
/>
|
||||||
<Grid item xs={4}>
|
</div>
|
||||||
<TL2 className={classes.tl2}>{data?.serverVersion}</TL2>
|
|
||||||
<Label1 className={classes.label1}> server version</Label1>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={4}>
|
|
||||||
{/*
|
|
||||||
On hold until system update features are implemented
|
|
||||||
<ActionButton
|
|
||||||
color="primary"
|
|
||||||
className={classes.actionButton}
|
|
||||||
onClick={() => console.log('Upgrade button clicked')}>
|
|
||||||
Update to v10.6.0
|
|
||||||
</ActionButton> */}
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
<Grid
|
|
||||||
container
|
|
||||||
spacing={1}
|
|
||||||
className={classnames(machinesTableContainerClasses)}>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<MachinesTable
|
|
||||||
numToRender={showAllItems ? Infinity : NUM_TO_RENDER}
|
|
||||||
machines={machines}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
{!showAllItems && machines.length > NUM_TO_RENDER && (
|
{!showAllItems && machines.length > NUM_TO_RENDER && (
|
||||||
<Grid item xs={12}>
|
<div>
|
||||||
<Label1 className={classes.centerLabel}>
|
<Label1 className="text-center mb-0">
|
||||||
<Button
|
<Button
|
||||||
onClick={() => onExpand()}
|
onClick={() => onExpand()}
|
||||||
size="small"
|
size="small"
|
||||||
disableRipple
|
disableRipple
|
||||||
disableFocusRipple
|
disableFocusRipple
|
||||||
className={classes.button}>
|
className="p-0 text-zodiac normal-case">
|
||||||
{`Show all (${machines.length})`}
|
{`Show all (${machines.length})`}
|
||||||
</Button>
|
</Button>
|
||||||
</Label1>
|
</Label1>
|
||||||
</Grid>
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { useQuery, useMutation, gql } from "@apollo/client";
|
import { useQuery, useMutation, gql } from '@apollo/client'
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import Modal from 'src/components/Modal'
|
import Modal from 'src/components/Modal'
|
||||||
|
|
@ -15,7 +14,6 @@ import { Link, SupportLinkButton } from 'src/components/buttons'
|
||||||
import { Table as EditableTable } from 'src/components/editableTable'
|
import { Table as EditableTable } from 'src/components/editableTable'
|
||||||
import { fromNamespace, toNamespace, namespaces } from 'src/utils/config'
|
import { fromNamespace, toNamespace, namespaces } from 'src/utils/config'
|
||||||
|
|
||||||
import { styles } from './Locales.styles'
|
|
||||||
import {
|
import {
|
||||||
mainFields,
|
mainFields,
|
||||||
overrides,
|
overrides,
|
||||||
|
|
@ -25,8 +23,6 @@ import {
|
||||||
overridesDefaults
|
overridesDefaults
|
||||||
} from './helper'
|
} from './helper'
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const GET_DATA = gql`
|
const GET_DATA = gql`
|
||||||
query getData {
|
query getData {
|
||||||
config
|
config
|
||||||
|
|
@ -75,8 +71,6 @@ const GET_MARKETS = gql`
|
||||||
`
|
`
|
||||||
|
|
||||||
const FiatCurrencyChangeAlert = ({ open, close, save }) => {
|
const FiatCurrencyChangeAlert = ({ open, close, save }) => {
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title={'Change fiat currency?'}
|
title={'Change fiat currency?'}
|
||||||
|
|
@ -94,11 +88,11 @@ const FiatCurrencyChangeAlert = ({ open, close, save }) => {
|
||||||
Also, if you have cash-out enabled, you must define new dispenser bill
|
Also, if you have cash-out enabled, you must define new dispenser bill
|
||||||
counts for the new currency for cash-out on the new currency to work.
|
counts for the new currency for cash-out on the new currency to work.
|
||||||
</P>
|
</P>
|
||||||
<div className={classes.rightAligned}>
|
<div className="ml-auto">
|
||||||
<Link onClick={close} color="secondary">
|
<Link onClick={close} color="secondary">
|
||||||
Cancel
|
Cancel
|
||||||
</Link>
|
</Link>
|
||||||
<Link className={classes.rightLink} onClick={save} color="primary">
|
<Link className="ml-5" onClick={save} color="primary">
|
||||||
Save
|
Save
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
const styles = {
|
|
||||||
rightAligned: {
|
|
||||||
marginTop: '20px',
|
|
||||||
marginLeft: 'auto',
|
|
||||||
marginBottom: '20px'
|
|
||||||
},
|
|
||||||
rightLink: {
|
|
||||||
marginLeft: '20px'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export { styles }
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
--ghost: #fafbff;
|
--ghost: #fafbff;
|
||||||
--zircon: #ebefff;
|
--zircon: #ebefff;
|
||||||
|
--zircon2: #dbdfed;
|
||||||
|
|
||||||
--java: #16d6d3;
|
--java: #16d6d3;
|
||||||
--neon: #5a67ff;
|
--neon: #5a67ff;
|
||||||
|
|
@ -45,6 +46,8 @@
|
||||||
--color-tomato: var(--tomato);
|
--color-tomato: var(--tomato);
|
||||||
--color-ghost: var(--ghost);
|
--color-ghost: var(--ghost);
|
||||||
--color-zircon: var(--zircon);
|
--color-zircon: var(--zircon);
|
||||||
|
--color-zircon2: var(--zircon2);
|
||||||
|
--color-java: var(--java);
|
||||||
--color-neon: var(--neon);
|
--color-neon: var(--neon);
|
||||||
--color-malachite: var(--malachite);
|
--color-malachite: var(--malachite);
|
||||||
--color-orange-yellow: var(--orange-yellow);
|
--color-orange-yellow: var(--orange-yellow);
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,13 @@ theme = createTheme(theme, {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
MuiPaper: {
|
||||||
|
styleOverrides: {
|
||||||
|
elevation1: {
|
||||||
|
boxShadow: '0 0 4px 0 rgba(0, 0, 0, 0.08)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
MuiChip: {
|
MuiChip: {
|
||||||
styleOverrides: {
|
styleOverrides: {
|
||||||
root: {
|
root: {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue