partial: Dashboard and Locales css migration

This commit is contained in:
Rafael Taranto 2025-05-06 13:44:23 +01:00
parent d7b2e12f94
commit 5f81487dcc
25 changed files with 314 additions and 883 deletions

View file

@ -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 React from 'react'
import { white } from 'src/styling/variables'
import Paper from '@mui/material/Paper'
import classnames from 'classnames'
const cardState = Object.freeze({
DEFAULT: 'default',
@ -12,24 +10,11 @@ const cardState = Object.freeze({
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 classes = useStyles()
return (
<Grid item className={classnames(className, classes.card)}>
<Paper className={classnames('p-6', className)}>
{state === cardState.SHRUNK ? shrunkComponent : children}
</Grid>
</Paper>
)
}

View file

@ -1,14 +1,12 @@
import { useQuery, gql } from "@apollo/client";
import { useQuery, gql } from '@apollo/client'
import Button from '@mui/material/Button'
import Grid from '@mui/material/Grid'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import * as R from 'ramda'
import React from 'react'
import { cardState } from 'src/components/CollapsibleCard'
import { Label1, H4 } from 'src/components/typography'
import styles from './Alerts.styles'
import AlertsTable from './AlertsTable'
const NUM_TO_RENDER = 3
@ -31,10 +29,7 @@ const GET_ALERTS = gql`
}
`
const useStyles = makeStyles(styles)
const Alerts = ({ onReset, onExpand, size }) => {
const classes = useStyles()
const showAllItems = size === cardState.EXPANDED
const { data } = useQuery(GET_ALERTS)
const alerts = R.path(['alerts'])(data) ?? []
@ -44,35 +39,30 @@ const Alerts = ({ onReset, onExpand, size }) => {
)(data?.machines ?? [])
const alertsLength = alerts.length
const alertsTableContainerClasses = {
[classes.alertsTableContainer]: !showAllItems,
[classes.expandedAlertsTableContainer]: showAllItems
}
return (
<>
<div className={classes.container}>
<H4 className={classes.h4}>{`Alerts (${alertsLength})`}</H4>
<div className="flex justify-between">
<H4 noMargin>{`Alerts (${alertsLength})`}</H4>
{showAllItems && (
<Label1 className={classes.upperButtonLabel}>
<Label1 noMargin className="-mt-1">
<Button
onClick={onReset}
size="small"
disableRipple
disableFocusRipple
className={classes.button}>
className="p-0 text-zodiac normal-case">
{'Show less'}
</Button>
</Label1>
)}
</div>
<Grid
className={classnames(alertsTableContainerClasses)}
className={classnames({ 'm-0': true, 'max-h-115': showAllItems })}
container
spacing={1}>
<Grid item xs={12}>
{!alerts.length && (
<Label1 className={classes.noAlertsLabel}>
<Label1 className="text-comet -ml-1 h-30">
No new alerts. Your system is running smoothly.
</Label1>
)}
@ -85,13 +75,13 @@ const Alerts = ({ onReset, onExpand, size }) => {
</Grid>
{!showAllItems && alertsLength > NUM_TO_RENDER && (
<Grid item xs={12}>
<Label1 className={classes.centerLabel}>
<Label1 className="text-center mb-0">
<Button
onClick={() => onExpand('alerts')}
size="small"
disableRipple
disableFocusRipple
className={classes.button}>
className="p-0 text-zodiac normal-case">
{`Show all (${alerts.length})`}
</Button>
</Label1>

View file

@ -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

View file

@ -1,4 +1,3 @@
import { makeStyles } from '@mui/styles'
import List from '@mui/material/List'
import ListItem from '@mui/material/ListItem'
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 WarningIcon from 'src/styling/icons/warning-icon/tomato.svg?react'
import styles from './Alerts.styles'
const useStyles = makeStyles(styles)
const icons = {
error: <WarningIcon style={{ height: 20, width: 20, marginRight: 12 }} />,
fiatBalance: (
@ -28,7 +24,6 @@ const links = {
const AlertsTable = ({ numToRender, alerts, machines }) => {
const history = useHistory()
const classes = useStyles()
const alertsToRender = R.slice(0, numToRender, alerts)
const alertMessage = alert => {
@ -40,16 +35,16 @@ const AlertsTable = ({ numToRender, alerts, machines }) => {
}
return (
<List dense className={classes.table}>
<List dense className="max-h-116 overflow-y-auto overflow-x-hidden">
{alertsToRender.map((alert, idx) => {
return (
<ListItem key={idx}>
{icons[alert.type] || (
<Wrench style={{ height: 23, width: 23, marginRight: 8 }} />
)}
<P className={classes.listItemText}>{alertMessage(alert)}</P>
<P className="my-2">{alertMessage(alert)}</P>
<AlertLinkIcon
className={classes.linkIcon}
className="ml-auto cursor-pointer"
onClick={() => history.push(links[alert.type] || '/dashboard')}
/>
</ListItem>

View file

@ -1,6 +1,4 @@
import { useQuery, gql } from "@apollo/client";
import Grid from '@mui/material/Grid'
import { makeStyles } from '@mui/styles'
import { useQuery, gql } from '@apollo/client'
import * as R from 'ramda'
import React, { useState } from 'react'
import { useHistory } from 'react-router-dom'
@ -13,11 +11,10 @@ import { Button } from 'src/components/buttons'
import AddMachine from 'src/pages/AddMachine'
import { errorColor } from 'src/styling/variables'
import styles from './Dashboard.styles'
import Footer from './Footer'
import LeftSide from './LeftSide'
import RightSide from './RightSide'
const useStyles = makeStyles(styles)
import Paper from '@mui/material/Paper'
import SystemPerformance from './SystemPerformance/index.js'
const GET_DATA = gql`
query getData {
@ -30,7 +27,6 @@ const GET_DATA = gql`
const Dashboard = () => {
const history = useHistory()
const classes = useStyles()
const [open, setOpen] = useState(false)
const { data, loading } = useQuery(GET_DATA)
@ -44,16 +40,16 @@ const Dashboard = () => {
!R.isEmpty(data.machines) ? (
<>
<TitleSection title="Dashboard">
<div className={classes.headerLabels}>
<div>
<div className="flex gap-6">
<div className="flex items-center gap-2">
<TxInIcon />
<span>Cash-in</span>
</div>
<div>
<div className="flex items-center gap-2">
<TxOutIcon />
<span>Cash-out</span>
</div>
<div>
<div className="flex items-center gap-2">
<svg width={12} height={12}>
<rect width={12} height={12} rx={3} fill={errorColor} />
</svg>
@ -61,15 +57,15 @@ const Dashboard = () => {
</div>
</div>
</TitleSection>
<div className={classes.root}>
<Grid container>
<Grid container direction="column" item xs={6}>
<LeftSide />
</Grid>
<Grid container direction="column" item xs={6}>
<div className="flex mb-30 gap-4">
<div className="flex flex-col flex-1">
<Paper className="p-6">
<SystemPerformance />
</Paper>
</div>
<div className="flex flex-col flex-1">
<RightSide />
</Grid>
</Grid>
</div>
</div>
<Footer />
</>
@ -79,17 +75,17 @@ const Dashboard = () => {
<AddMachine close={() => setOpen(false)} onPaired={onPaired} />
)}
<TitleSection title="Dashboard">
<div className={classes.headerLabels}>
<div className="flex flex-row">
<span>
<TL2 className={classes.inline}>{data?.serverVersion}</TL2>{' '}
<Label1 className={classes.inline}> server version</Label1>
<TL2 className="inline">{data?.serverVersion}</TL2>{' '}
<Label1 className="inline"> server version</Label1>
</span>
</div>
</TitleSection>
<div className={classes.emptyMachinesRoot}>
<div className={classes.emptyMachinesContent}>
<H1 className={classes.offColor}>No machines on your system yet</H1>
<Info2 className={classes.offColor}>
<div className="h-75 bg-zircon border-zircon2 border-2">
<div className="flex flex-col h-full justify-center items-center gap-6">
<H1 className="text-comet2">No machines on your system yet</H1>
<Info2 className="text-comet2">
To fully take advantage of Lamassu Admin, add a new machine to
your system
</Info2>

View file

@ -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

View file

@ -1,8 +1,6 @@
import { useQuery, gql } from "@apollo/client";
import { useQuery, gql } from '@apollo/client'
import { makeStyles } from '@mui/styles'
import Grid from '@mui/material/Grid'
import BigNumber from 'bignumber.js'
import classnames from 'classnames'
import * as R from 'ramda'
import React from 'react'
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 styles from './Footer.styles'
import classes from './Footer.module.css'
const GET_DATA = gql`
query getData {
cryptoRates
@ -29,12 +28,10 @@ const GET_DATA = gql`
BigNumber.config({ ROUNDING_MODE: BigNumber.ROUND_HALF_UP })
const useStyles = makeStyles(styles)
const Footer = () => {
const { data } = useQuery(GET_DATA)
const withCommissions = R.path(['cryptoRates', 'withCommissions'])(data) ?? {}
const classes = useStyles()
const config = R.path(['config'])(data) ?? {}
// const canExpand = R.keys(withCommissions).length > 4
@ -72,36 +69,31 @@ const Footer = () => {
).toFormat(2)
return (
<Grid key={key} item xs={3}>
<Label2 className={classes.label}>
<div className="flex flex-col w-1/4">
<Label2 className="text-comet mt-3 mb-2">
{cryptoCurrencies[idx].display}
</Label2>
<div className={classes.headerLabels}>
<div className={classes.headerLabel}>
<div className="flex gap-6">
<div className="flex items-center gap-1">
<TxInIcon />
<Label2>{` ${cashIn} ${localeFiatCurrency}`}</Label2>
<Label2 noMargin>{`${cashIn} ${localeFiatCurrency}`}</Label2>
</div>
<div className={classnames(classes.headerLabel, classes.txOutMargin)}>
<div className="flex items-center gap-1">
<TxOutIcon />
<Label2>{` ${cashOut} ${localeFiatCurrency}`}</Label2>
<Label2 noMargin>{`${cashOut} ${localeFiatCurrency}`}</Label2>
</div>
</div>
<Label2
className={
classes.tickerLabel
}>{`${tickerName}: ${avgOfAskBid} ${localeFiatCurrency}`}</Label2>
</Grid>
<Label2 className="text-comet mt-2">
{`${tickerName}: ${avgOfAskBid} ${localeFiatCurrency}`}
</Label2>
</div>
)
}
return (
<div className={classes.footer1}>
<div className={classes.content1}>
<Grid container>
<Grid container className={classes.footerContainer1}>
{R.keys(withCommissions).map(key => renderFooterItem(key))}
</Grid>
</Grid>
</div>
</div>
)

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -1,29 +1,23 @@
import Button from '@mui/material/Button'
import Grid from '@mui/material/Grid'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React, { useState } from 'react'
import CollapsibleCard, { cardState } from 'src/components/CollapsibleCard'
import { H4, Label1 } from 'src/components/typography'
import Alerts from './Alerts'
import styles from './Dashboard.styles'
import SystemStatus from './SystemStatus'
const useStyles = makeStyles(styles)
const ShrunkCard = ({ title, buttonName, onUnshrink }) => {
const classes = useStyles()
return (
<div className={classes.container}>
<H4 className={classes.h4}>{title}</H4>
<Label1 className={classes.upperButtonLabel}>
<div className="flex justify-between">
<H4 className="mt-0">{title}</H4>
<Label1 className="text-center my-0">
<Button
onClick={onUnshrink}
size="small"
disableRipple
disableFocusRipple
className={classes.button}>
className="p-0 text-zodiac normal-case">
{buttonName}
</Button>
</Label1>
@ -32,7 +26,6 @@ const ShrunkCard = ({ title, buttonName, onUnshrink }) => {
}
const RightSide = () => {
const classes = useStyles()
const [systemStatusSize, setSystemStatusSize] = useState(cardState.DEFAULT)
const [alertsSize, setAlertsSize] = useState(cardState.DEFAULT)
@ -41,14 +34,12 @@ const RightSide = () => {
setSystemStatusSize(cardState.DEFAULT)
}
return (
<Grid item xs={12} className={classes.displayFlex}>
<div style={{ flex: 1, display: 'flex', flexDirection: 'column' }}>
<>
<div className="flex flex-1 flex-col">
<div className="flex-1 flex flex-col gap-4">
<CollapsibleCard
className={classnames({
[classes.alertsCard]: alertsSize !== cardState.SHRUNK,
[classes.shrunkCard]: alertsSize === cardState.SHRUNK,
[classes.expandedCard]: alertsSize === cardState.EXPANDED
'flex-[0.1]': alertsSize === cardState.SHRUNK,
'flex-[0.9]': alertsSize === cardState.EXPANDED
})}
state={alertsSize}
shrunkComponent={
@ -69,9 +60,9 @@ const RightSide = () => {
</CollapsibleCard>
<CollapsibleCard
className={classnames({
[classes.shrunkCard]: systemStatusSize === cardState.SHRUNK,
[classes.systemStatusCard]: systemStatusSize !== cardState.SHRUNK,
[classes.expandedCard]: alertsSize === cardState.EXPANDED
'flex-[0.1]': systemStatusSize === cardState.SHRUNK,
'flex-1': systemStatusSize === cardState.DEFAULT,
'flex-[0.9]': systemStatusSize === cardState.EXPANDED
})}
state={systemStatusSize}
shrunkComponent={
@ -90,9 +81,8 @@ const RightSide = () => {
size={systemStatusSize}
/>
</CollapsibleCard>
</>
</div>
</Grid>
</div>
)
}

View file

@ -1,77 +1,30 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import React from 'react'
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 value = cashIn || cashOut !== 0 ? cashIn : 50
const classes = useStyles(value)
const buildPercentageView = value => {
if (value <= 15) return
return <Label1 className={classes.label}>{value}%</Label1>
return <Label1 className="text-white">{value}%</Label1>
}
const percentageClasses = {
[classes.percentageBox]: true,
[classes.other]: value < 5 && value > 0
'h-35 rounded-sm flex items-center justify-center': true,
'min-w-2 rounded-xs': value < 5 && value > 0
}
return (
<div className={classes.wrapper}>
<div className="flex h-35 gap-1">
<div
className={classnames(
percentageClasses,
classes.inColor,
classes.inWidth
)}>
className={classnames(percentageClasses, 'bg-java')}
style={{ width: `${value}%` }}>
{buildPercentageView(value, 'cashIn')}
</div>
<div
className={classnames(
percentageClasses,
classes.outColor,
classes.outWidth
)}>
className={classnames(percentageClasses, 'bg-neon')}
style={{ width: `${100 - value}%` }}>
{buildPercentageView(100 - value, 'cashOut')}
</div>
</div>

View file

@ -2,8 +2,6 @@ import * as d3 from 'd3'
import * as R from 'ramda'
import React, { useEffect, useRef, useCallback } from 'react'
import { backgroundColor, zircon, primaryColor } from 'src/styling/variables'
const transactionProfit = R.prop('profit')
const mockPoint = (tx, offsetMs, profit) => {
@ -106,7 +104,7 @@ const RefLineChart = ({
.attr('y', -margin.top)
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top)
.attr('fill', backgroundColor)
.attr('fill', 'var(--ghost)')
.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 )
@ -120,9 +118,9 @@ const RefLineChart = ({
.attr('y2', '100%')
.selectAll('stop')
.data([
{ offset: '0%', color: zircon },
{ offset: '25%', color: zircon },
{ offset: '100%', color: backgroundColor }
{ offset: '0%', color: 'var(--zircon)' },
{ offset: '25%', color: 'var(--zircon)' },
{ offset: '100%', color: 'var(--ghost)' }
])
.enter()
.append('stop')
@ -181,7 +179,7 @@ const RefLineChart = ({
.attr('fill', 'none')
.attr('stroke-width', '2')
.attr('stroke-linejoin', 'round')
.attr('stroke', primaryColor)
.attr('stroke', 'var(--zodiac)')
}, [realData, timeFrame, previousTimeData, previousProfit])
useEffect(() => {

View file

@ -4,14 +4,6 @@ import { getTimezoneOffset } from 'date-fns-tz'
import { add, format, startOfWeek, startOfYear } from 'date-fns/fp'
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 { MINUTE, DAY, WEEK, MONTH } from 'src/utils/time'
@ -143,7 +135,7 @@ const Graph = ({ data, timeFrame, timezone }) => {
.attr('y', GRAPH_MARGIN.top)
.attr('width', GRAPH_WIDTH)
.attr('height', GRAPH_HEIGHT - GRAPH_MARGIN.top - GRAPH_MARGIN.bottom)
.attr('fill', backgroundColor)
.attr('fill', 'var(--ghost)')
},
[GRAPH_MARGIN]
)
@ -191,8 +183,8 @@ const Graph = ({ data, timeFrame, timezone }) => {
const buildGrid = useCallback(
g => {
g.attr('stroke', subheaderDarkColor)
.attr('fill', subheaderDarkColor)
g.attr('stroke', 'var(--zircon2)')
.attr('fill', 'var(--zircon2)')
// Vertical lines
.call(g =>
g
@ -277,10 +269,10 @@ const Graph = ({ data, timeFrame, timezone }) => {
() =>
d3
.selectAll('.tick text')
.style('stroke', offColor)
.style('fill', offColor)
.style('stroke', 'var(--comet)')
.style('fill', 'var(--comet)')
.style('stroke-width', 0)
.style('font-family', fontSecondary),
.style('font-family', 'var(--museo)'),
[]
)
@ -288,10 +280,10 @@ const Graph = ({ data, timeFrame, timezone }) => {
() =>
d3
.selectAll('text')
.style('stroke', offColor)
.style('fill', offColor)
.style('stroke', 'var(--comet)')
.style('fill', 'var(--comet)')
.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))
})
.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)
},
[data, offset, x, y]

View file

@ -2,10 +2,10 @@ import React from 'react'
import { Info1, Label1 } from 'src/components/typography/index'
const InfoWithLabel = ({ info, label }) => {
return (
<>
<Info1 style={{ marginBottom: 0 }}>{info}</Info1>
<Label1 style={{ margin: 0 }}>{label}</Label1>
</>
<div className="flex flex-col">
<Info1 className="mb-0">{info}</Info1>
<Label1 className="m-0">{label}</Label1>
</div>
)
}

View file

@ -1,16 +1,11 @@
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import * as R from 'ramda'
import React, { useState } from 'react'
import { H4 } from 'src/components/typography'
import styles from './SystemPerformance.styles'
const useStyles = makeStyles(styles)
const ranges = ['Month', 'Week', 'Day']
const Nav = ({ handleSetRange, showPicker }) => {
const classes = useStyles()
const [clickedItem, setClickedItem] = useState('Day')
const isSelected = R.equals(clickedItem)
@ -20,22 +15,20 @@ const Nav = ({ handleSetRange, showPicker }) => {
}
return (
<div className={classnames(classes.titleWrapper)}>
<div className={classes.titleAndButtonsContainer}>
<H4 className={classes.h4}>{'System performance'}</H4>
</div>
<div className="flex justify-between items-center">
<H4 noMargin>{'System performance'}</H4>
{showPicker && (
<div className={classes.navContainer}>
<div className="flex gap-6">
{ranges.map((it, idx) => {
return (
<div
key={idx}
onClick={e => handleClick(e.target.innerText)}
className={
className={classnames({
'cursor-pointer text-comet': true,
'font-bold text-zodiac border-b-zodiac border-b-2':
isSelected(it)
? classnames(classes.newHighlightedLabel, classes.navButton)
: classnames(classes.label, classes.navButton)
}>
})}>
{it}
</div>
)

View file

@ -1,12 +1,10 @@
import { useQuery, gql } from "@apollo/client";
import Grid from '@mui/material/Grid'
import { makeStyles } from '@mui/styles'
import { useQuery, gql } from '@apollo/client'
import BigNumber from 'bignumber.js'
import classnames from 'classnames'
import { isAfter } from 'date-fns/fp'
import * as R from 'ramda'
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 PercentNeutralIcon from 'src/styling/icons/dashboard/equal.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 InfoWithLabel from './InfoWithLabel'
import Nav from './Nav'
import styles from './SystemPerformance.styles'
BigNumber.config({ ROUNDING_MODE: BigNumber.ROUND_HALF_UP })
const getFiats = R.map(R.prop('fiat'))
const useStyles = makeStyles(styles)
const GET_DATA = gql`
query getData($excludeTestingCustomers: Boolean) {
@ -54,7 +50,6 @@ const GET_DATA = gql`
`
const SystemPerformance = () => {
const classes = useStyles()
const [selectedRange, setSelectedRange] = useState('Day')
const { data, loading } = useQuery(GET_DATA, {
variables: { excludeTestingCustomers: true }
@ -162,17 +157,17 @@ const SystemPerformance = () => {
const percentChange = getPercentChange()
const percentageClasses = {
[classes.percentDown]: percentChange < 0,
[classes.percentUp]: percentChange > 0,
[classes.percentNeutral]: percentChange === 0
'text-tomato': percentChange < 0,
'text-spring4': percentChange > 0,
'text-comet': percentChange === 0,
'flex items-center justify-center gap-1': true
}
const getPercentageIcon = () => {
if (percentChange === 0)
return <PercentNeutralIcon className={classes.directionIcon} />
if (percentChange > 0)
return <PercentUpIcon className={classes.directionIcon} />
return <PercentDownIcon className={classes.directionIcon} />
const className = 'w-4 h-4'
if (percentChange === 0) return <PercentNeutralIcon className={className} />
if (percentChange > 0) return <PercentUpIcon className={className} />
return <PercentDownIcon className={className} />
}
return (
@ -182,49 +177,43 @@ const SystemPerformance = () => {
handleSetRange={setSelectedRange}
/>
{!loading && R.isEmpty(data.transactions) && (
<EmptyTable
className={classes.emptyTransactions}
message="No transactions so far"
/>
<EmptyTable className="pt-10" message="No transactions so far" />
)}
{!loading && !R.isEmpty(data.transactions) && (
<>
<Grid container spacing={2}>
<Grid item xs={3}>
<InfoWithLabel
info={getNumTransactions()}
label={'transactions'}
/>
</Grid>
<Grid item xs={3}>
<div className="flex flex-col gap-12">
<div className="flex gap-16">
<InfoWithLabel info={getNumTransactions()} label={'transactions'} />
<InfoWithLabel
info={getFiatVolume()}
label={`${data?.config.locale_fiatCurrency} volume`}
/>
</Grid>
{/* todo new customers */}
</Grid>
<Grid container className={classes.txGraphContainer}>
<Grid item xs={12}>
<div className={classes.graphHeader}>
</div>
<div className="h-62">
<div className="flex justify-between mb-4">
<Label2 noMargin>Transactions</Label2>
<div className={classes.labelWrapper}>
<div className="flex items-center">
<P noMargin>
{timezones[timezone]?.short ?? timezones[timezone]?.long}{' '}
timezone
</P>
<span className={classes.verticalLine} />
<div>
<span className="h-4 w-[1px] bg-comet2 mr-4 ml-8" />
<div className="flex flex-row gap-4">
<div className="flex items-center">
<svg width={8} height={8}>
<rect width={8} height={8} rx={4} fill={java} />
</svg>
<Label1 noMargin>In</Label1>
<Label1 noMargin className="ml-2">
In
</Label1>
</div>
<div>
<div className="flex items-center">
<svg width={8} height={8}>
<rect width={8} height={8} rx={4} fill={neon} />
</svg>
<Label1 noMargin>Out</Label1>
<Label1 noMargin className="ml-2">
Out
</Label1>
</div>
</div>
</div>
</div>
@ -233,23 +222,22 @@ const SystemPerformance = () => {
data={transactionsToShow}
timezone={timezone}
/>
</Grid>
</Grid>
<Grid container className={classes.commissionGraphContainer}>
<Grid item xs={8}>
<Label2 noMargin className={classes.commissionProfitTitle}>
</div>
<div className="flex h-62">
<div className="flex-2">
<Label2 noMargin className="mb-4">
Profit from commissions
</Label2>
<div className={classes.profitContainer}>
<div className={classes.profitLabel}>
<div className="flex justify-between mt-6 mr-7 -mb-8 ml-4 relative">
<Info2 noMargin>
{`${getProfit(transactionsToShow).toFormat(2)} ${
data?.config.locale_fiatCurrency
}`}
</div>
<div className={classnames(percentageClasses)}>
</Info2>
<Info2 noMargin className={classnames(percentageClasses)}>
{getPercentageIcon()}
{`${new BigNumber(percentChange).toFormat(2)}%`}
</div>
</Info2>
</div>
<LineChart
timeFrame={selectedRange}
@ -257,34 +245,36 @@ const SystemPerformance = () => {
previousTimeData={transactionsLastTimePeriod}
previousProfit={getProfit(transactionsLastTimePeriod)}
/>
</Grid>
<Grid item xs={4}>
<Grid container className={classes.graphHeader}>
</div>
<div className="flex-1">
<div className="flex items-center justify-between mb-4">
<Label2 noMargin>Direction</Label2>
<div className={classes.labelWrapper}>
<div>
<div className="flex flex-row gap-4">
<div className="flex items-center">
<svg width={8} height={8}>
<rect width={8} height={8} rx={2} fill={java} />
</svg>
<Label1 noMargin>In</Label1>
<Label1 noMargin className="ml-2">
In
</Label1>
</div>
<div>
<div className="flex items-center">
<svg width={8} height={8}>
<rect width={8} height={8} rx={2} fill={neon} />
</svg>
<Label1 noMargin>Out</Label1>
<Label1 noMargin className="ml-2">
Out
</Label1>
</div>
</div>
</div>
</Grid>
<Grid item xs>
<PercentageChart
cashIn={getDirectionPercent().cashIn}
cashOut={getDirectionPercent().cashOut}
/>
</Grid>
</Grid>
</Grid>
</>
</div>
</div>
</div>
)}
</>
)

View file

@ -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

View file

@ -1,12 +1,11 @@
import { useQuery, gql } from "@apollo/client";
import { makeStyles, withStyles } from '@mui/styles'
import { useQuery, gql } from '@apollo/client'
import { styled } from '@mui/material/styles'
import Table from '@mui/material/Table'
import TableBody from '@mui/material/TableBody'
import TableCell from '@mui/material/TableCell'
import TableContainer from '@mui/material/TableContainer'
import TableHead from '@mui/material/TableHead'
import TableRow from '@mui/material/TableRow'
import classnames from 'classnames'
import * as R from 'ramda'
import React from 'react'
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 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 styles from './MachinesTable.styles'
// percentage threshold where below this number the text in the cash cassettes percentage turns red
const PERCENTAGE_THRESHOLD = 20
@ -29,27 +25,20 @@ const GET_CONFIG = gql`
}
`
const useStyles = makeStyles(styles)
const StyledCell = withStyles({
root: {
const StyledCell = styled(TableCell)({
borderBottom: '4px solid white',
padding: 0,
paddingLeft: 15
}
})(TableCell)
paddingLeft: '15px'
})
const HeaderCell = withStyles({
root: {
const HeaderCell = styled(TableCell)({
borderBottom: '4px solid white',
padding: 0,
paddingLeft: 15,
paddingLeft: '15px',
backgroundColor: 'white'
}
})(TableCell)
})
const MachinesTable = ({ machines = [], numToRender }) => {
const classes = useStyles()
const history = useHistory()
const { data } = useQuery(GET_CONFIG)
@ -69,7 +58,7 @@ const MachinesTable = ({ machines = [], numToRender }) => {
R.defaultTo(PERCENTAGE_THRESHOLD)
)(fillingPercentageSettings)
return percent < percentageThreshold ? (
<TL2 className={classes.error}>{`${percent}%`}</TL2>
<TL2 className="text-tomato">{`${percent}%`}</TL2>
) : (
<TL2>{`${percent}%`}</TL2>
)
@ -87,30 +76,32 @@ const MachinesTable = ({ machines = [], numToRender }) => {
)
return (
<TableContainer className={classes.table}>
<TableContainer className="max-h-110">
<Table>
<TableHead>
<TableRow>
<HeaderCell>
<div className={classes.header}>
<Label2 className={classes.label}>Machines</Label2>
<div className="flex items-center">
<Label2 noMargin className="text-comet">
Machines
</Label2>
</div>
</HeaderCell>
<HeaderCell>
<div className={`${classes.header} ${classes.statusHeader}`}>
<Label2 className={classes.label}>Status</Label2>
<div className="flex items-center">
<Label2 noMargin className="text-comet">
Status
</Label2>
</div>
</HeaderCell>
{/* <HeaderCell>
<div className={classes.header}>
<TxInIcon />
</div>
</HeaderCell> */}
{R.times(R.identity, maxNumberOfCassettes).map((it, idx) => (
<HeaderCell key={idx}>
<div className={classes.header}>
<div className="flex items-center whitespace-pre">
<TxOutIcon />
<Label2 className={classes.label}> {it + 1}</Label2>
<Label2 noMargin className="text-comet">
{' '}
{it + 1}
</Label2>
</div>
</HeaderCell>
))}
@ -122,20 +113,23 @@ const MachinesTable = ({ machines = [], numToRender }) => {
return (
<TableRow
onClick={() => redirect(machine)}
className={classnames(classes.row)}
className="boder-b-0 bg-ghost"
key={machine.deviceId + idx}>
<StyledCell align="left">
<div className={classes.machineNameWrapper}>
<TableCell
sx={{
borderBottom: '4px solid white',
padding: 0,
paddingLeft: '15px'
}}
align="left">
<div className="flex items-center">
<TL2>{machine.name}</TL2>
<MachineLinkIcon
className={classnames(
classes.machineRedirectIcon,
classes.clickableRow
)}
className="cursor-pointer ml-2"
onClick={() => redirect(machine)}
/>
</div>
</StyledCell>
</TableCell>
<StyledCell>
<Status status={machine.statuses[0]} />
</StyledCell>

View file

@ -6,10 +6,6 @@ import {
} from 'src/styling/variables'
const styles = {
container: {
display: 'flex',
justifyContent: 'space-between'
},
label: {
margin: 0,
color: offColor
@ -45,30 +41,12 @@ const styles = {
bottom: 160,
marginBottom: 0
},
upperButtonLabel: {
textAlign: 'center',
marginBottom: 0,
marginTop: 0
},
statusHeader: {
marginLeft: 2
},
table: {
maxHeight: 440,
'&::-webkit-scrollbar': {
width: 7
},
'&::-webkit-scrollbar-thumb': {
backgroundColor: offColor,
borderRadius: 5
}
},
tableBody: {
overflow: 'auto'
},
h4: {
marginTop: 0
},
tl2: {
display: 'inline'
},
@ -76,11 +54,9 @@ const styles = {
display: 'inline'
},
machinesTableContainer: {
marginTop: 10,
height: 220
},
expandedMachinesTableContainer: {
marginTop: 10,
height: 414
},
centerLabel: {

View file

@ -1,18 +1,12 @@
import { useQuery, gql } from "@apollo/client";
import { useQuery, gql } from '@apollo/client'
import Button from '@mui/material/Button'
import Grid from '@mui/material/Grid'
import { makeStyles } from '@mui/styles'
import classnames from 'classnames'
import * as R from 'ramda'
import React from 'react'
import { cardState as cardState_ } from 'src/components/CollapsibleCard'
// import ActionButton from 'src/components/buttons/ActionButton'
import { H4, TL2, Label1 } from 'src/components/typography'
import MachinesTable from './MachinesTable'
import styles from './MachinesTable.styles'
const useStyles = makeStyles(styles)
// number of machines in the table to render on page load
const NUM_TO_RENDER = 4
@ -59,29 +53,28 @@ const GET_DATA = gql`
} */
const SystemStatus = ({ onReset, onExpand, size }) => {
const classes = useStyles()
const { data, loading } = useQuery(GET_DATA)
const machines = R.path(['machines'])(data) ?? []
const showAllItems = size === cardState_.EXPANDED
const machinesTableContainerClasses = {
[classes.machinesTableContainer]: !showAllItems,
[classes.expandedMachinesTableContainer]: showAllItems
'h-55': !showAllItems,
'h-103': showAllItems
}
// const uptime = data?.uptime ?? [{}]
return (
<>
<div className={classes.container}>
<H4 className={classes.h4}>System status</H4>{' '}
<div className="flex justify-between">
<H4 className="mt-0">System status</H4>
{showAllItems && (
<Label1 className={classes.upperButtonLabel}>
<Label1 noMargin className="-mt-1">
<Button
onClick={onReset}
size="small"
disableRipple
disableFocusRipple
className={classes.button}>
className="p-0 text-zodiac normal-case">
{'Show less'}
</Button>
</Label1>
@ -89,54 +82,29 @@ const SystemStatus = ({ onReset, onExpand, size }) => {
</div>
{!loading && (
<>
<Grid container spacing={1}>
{/*
On hold until system uptime is implemented
<Grid item xs={4}>
<TL2 className={classes.tl2}>
{parseUptime(uptime[0].time)}
</TL2>
<Label1 className={classes.label1}> System up time</Label1>
</Grid> */}
<Grid item xs={4}>
<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}>
<div className="mb-4">
<TL2 className="inline">{data?.serverVersion}</TL2>
<Label1 className="inline"> server version</Label1>
</div>
<div className={classnames(machinesTableContainerClasses)}>
<MachinesTable
numToRender={showAllItems ? Infinity : NUM_TO_RENDER}
machines={machines}
/>
</Grid>
</Grid>
</div>
{!showAllItems && machines.length > NUM_TO_RENDER && (
<Grid item xs={12}>
<Label1 className={classes.centerLabel}>
<div>
<Label1 className="text-center mb-0">
<Button
onClick={() => onExpand()}
size="small"
disableRipple
disableFocusRipple
className={classes.button}>
className="p-0 text-zodiac normal-case">
{`Show all (${machines.length})`}
</Button>
</Label1>
</Grid>
</div>
)}
</>
)}

View file

@ -1,5 +1,4 @@
import { useQuery, useMutation, gql } from "@apollo/client";
import { makeStyles } from '@mui/styles'
import { useQuery, useMutation, gql } from '@apollo/client'
import * as R from 'ramda'
import React, { useState } from 'react'
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 { fromNamespace, toNamespace, namespaces } from 'src/utils/config'
import { styles } from './Locales.styles'
import {
mainFields,
overrides,
@ -25,8 +23,6 @@ import {
overridesDefaults
} from './helper'
const useStyles = makeStyles(styles)
const GET_DATA = gql`
query getData {
config
@ -75,8 +71,6 @@ const GET_MARKETS = gql`
`
const FiatCurrencyChangeAlert = ({ open, close, save }) => {
const classes = useStyles()
return (
<Modal
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
counts for the new currency for cash-out on the new currency to work.
</P>
<div className={classes.rightAligned}>
<div className="ml-auto">
<Link onClick={close} color="secondary">
Cancel
</Link>
<Link className={classes.rightLink} onClick={save} color="primary">
<Link className="ml-5" onClick={save} color="primary">
Save
</Link>
</div>

View file

@ -1,12 +0,0 @@
const styles = {
rightAligned: {
marginTop: '20px',
marginLeft: 'auto',
marginBottom: '20px'
},
rightLink: {
marginLeft: '20px'
}
}
export { styles }

View file

@ -22,6 +22,7 @@
--ghost: #fafbff;
--zircon: #ebefff;
--zircon2: #dbdfed;
--java: #16d6d3;
--neon: #5a67ff;
@ -45,6 +46,8 @@
--color-tomato: var(--tomato);
--color-ghost: var(--ghost);
--color-zircon: var(--zircon);
--color-zircon2: var(--zircon2);
--color-java: var(--java);
--color-neon: var(--neon);
--color-malachite: var(--malachite);
--color-orange-yellow: var(--orange-yellow);

View file

@ -151,6 +151,13 @@ theme = createTheme(theme, {
}
}
},
MuiPaper: {
styleOverrides: {
elevation1: {
boxShadow: '0 0 4px 0 rgba(0, 0, 0, 0.08)'
}
}
},
MuiChip: {
styleOverrides: {
root: {