chore: reformat code

This commit is contained in:
Rafael Taranto 2025-05-12 14:49:39 +01:00
parent 3d930aa73b
commit aedabcbdee
509 changed files with 6030 additions and 4266 deletions

View file

@ -1,5 +1,5 @@
{ {
"trailingComma": "none", "trailingComma": "all",
"tabWidth": 2, "tabWidth": 2,
"semi": false, "semi": false,
"singleQuote": true, "singleQuote": true,

View file

@ -2,7 +2,6 @@ import js from '@eslint/js'
import globals from 'globals' import globals from 'globals'
import pluginReact from 'eslint-plugin-react' import pluginReact from 'eslint-plugin-react'
import json from '@eslint/json' import json from '@eslint/json'
import css from '@eslint/css'
import { defineConfig, globalIgnores } from 'eslint/config' import { defineConfig, globalIgnores } from 'eslint/config'
import reactCompiler from 'eslint-plugin-react-compiler' import reactCompiler from 'eslint-plugin-react-compiler'
import eslintConfigPrettier from 'eslint-config-prettier/flat' import eslintConfigPrettier from 'eslint-config-prettier/flat'
@ -16,7 +15,13 @@ export default defineConfig([
}, },
{ {
files: ['packages/admin-ui/**/*.{js,mjs,jsx}'], files: ['packages/admin-ui/**/*.{js,mjs,jsx}'],
languageOptions: { sourceType: 'module', globals: globals.browser } languageOptions: {
sourceType: 'module',
globals: {
...globals.browser,
process: 'readonly'
}
}
}, },
{ {
files: ['packages/server/**/*.{js,cjs}'], files: ['packages/server/**/*.{js,cjs}'],
@ -35,15 +40,8 @@ export default defineConfig([
language: 'json/json', language: 'json/json',
extends: ['json/recommended'] extends: ['json/recommended']
}, },
{
files: ['**/*.css'],
plugins: { css },
language: 'css/css',
extends: ['css/recommended']
},
{ {
rules: { rules: {
// 'no-unused-vars': 'on',
'react/prop-types': 'off', 'react/prop-types': 'off',
'react/display-name': 'off', 'react/display-name': 'off',
'react/no-unescaped-entities': 'off', 'react/no-unescaped-entities': 'off',

View file

@ -34,7 +34,7 @@ const Main = () => {
onCompleted: userResponse => { onCompleted: userResponse => {
if (!userData && userResponse?.userData) if (!userData && userResponse?.userData)
setUserData(userResponse.userData) setUserData(userResponse.userData)
} },
}) })
const route = location.pathname const route = location.pathname

View file

@ -42,4 +42,4 @@
.navButton:hover { .navButton:hover {
background-color: rgba(0, 0, 0, 0.04); background-color: rgba(0, 0, 0, 0.04);
} }

View file

@ -7,7 +7,7 @@ import classnames from 'classnames'
const cardState = Object.freeze({ const cardState = Object.freeze({
DEFAULT: 'default', DEFAULT: 'default',
SHRUNK: 'shrunk', SHRUNK: 'shrunk',
EXPANDED: 'expanded' EXPANDED: 'expanded',
}) })
const CollapsibleCard = ({ className, state, shrunkComponent, children }) => { const CollapsibleCard = ({ className, state, shrunkComponent, children }) => {
@ -19,7 +19,7 @@ const CollapsibleCard = ({ className, state, shrunkComponent, children }) => {
} }
CollapsibleCard.propTypes = { CollapsibleCard.propTypes = {
shrunkComponent: PropTypes.node.isRequired shrunkComponent: PropTypes.node.isRequired,
} }
export default CollapsibleCard export default CollapsibleCard

View file

@ -101,5 +101,5 @@ export const ConfirmDialog = memo(
</DialogActions> </DialogActions>
</Dialog> </Dialog>
) )
} },
) )

View file

@ -14,7 +14,7 @@ const CopyToClipboard = ({
buttonClassname, buttonClassname,
children, children,
wrapperClassname, wrapperClassname,
removeSpace = true removeSpace = true,
}) => { }) => {
const [anchorEl, setAnchorEl] = useState(null) const [anchorEl, setAnchorEl] = useState(null)
@ -68,7 +68,7 @@ const CopyToClipboard = ({
</> </>
)} )}
</div> </div>
); )
} }
export default CopyToClipboard export default CopyToClipboard

View file

@ -34,7 +34,7 @@ export const DeleteDialog = ({
item = 'item', item = 'item',
confirmationMessage = `Are you sure you want to delete this ${item}?`, confirmationMessage = `Are you sure you want to delete this ${item}?`,
extraMessage, extraMessage,
errorMessage = '' errorMessage = '',
}) => { }) => {
return ( return (
<Dialog open={open} aria-labelledby="form-dialog-title"> <Dialog open={open} aria-labelledby="form-dialog-title">

View file

@ -50,7 +50,7 @@ const ImagePopper = memo(
</div> </div>
</ClickAwayListener> </ClickAwayListener>
) )
} },
) )
export default ImagePopper export default ImagePopper

View file

@ -7,7 +7,7 @@ import { H1 } from 'src/components/typography'
import CloseIcon from 'src/styling/icons/action/close/zodiac.svg?react' import CloseIcon from 'src/styling/icons/action/close/zodiac.svg?react'
export const InformativeDialog = memo( export const InformativeDialog = memo(
({ title = '', open, onDissmised, disabled = false, data, ...props }) => { ({ title = '', open, onDissmised, data, ...props }) => {
const innerOnClose = () => { const innerOnClose = () => {
onDissmised() onDissmised()
} }
@ -16,8 +16,8 @@ export const InformativeDialog = memo(
<Dialog <Dialog
PaperProps={{ PaperProps={{
style: { style: {
borderRadius: 8 borderRadius: 8,
} },
}} }}
fullWidth fullWidth
open={open} open={open}
@ -35,5 +35,5 @@ export const InformativeDialog = memo(
<DialogContent>{data}</DialogContent> <DialogContent>{data}</DialogContent>
</Dialog> </Dialog>
) )
} },
) )

View file

@ -15,7 +15,6 @@ import { formatDate } from 'src/utils/timezones'
import Popper from './Popper' import Popper from './Popper'
import DateRangePicker from './date-range-picker/DateRangePicker' import DateRangePicker from './date-range-picker/DateRangePicker'
import { RadioGroup } from './inputs' import { RadioGroup } from './inputs'
import typographyStyles from './typography/styles'
import { H4, Info1, Label1, Label2 } from './typography/index.jsx' import { H4, Info1, Label1, Label2 } from './typography/index.jsx'
const DateContainer = ({ date, children }) => { const DateContainer = ({ date, children }) => {
@ -31,7 +30,7 @@ const DateContainer = ({ date, children }) => {
<div className="flex flex-col"> <div className="flex flex-col">
<Label2 noMargin>{`${format( <Label2 noMargin>{`${format(
'MMM', 'MMM',
date date,
)} ${format('yyyy', date)}`}</Label2> )} ${format('yyyy', date)}`}</Label2>
<Label1 noMargin className="text-comet"> <Label1 noMargin className="text-comet">
{format('EEEE', date)} {format('EEEE', date)}
@ -57,7 +56,7 @@ const LogsDownloaderPopover = ({
getLogs, getLogs,
timezone, timezone,
simplified, simplified,
className className,
}) => { }) => {
const [selectedRadio, setSelectedRadio] = useState(ALL) const [selectedRadio, setSelectedRadio] = useState(ALL)
const [selectedAdvancedRadio, setSelectedAdvancedRadio] = useState(ADVANCED) const [selectedAdvancedRadio, setSelectedAdvancedRadio] = useState(ADVANCED)
@ -65,12 +64,12 @@ const LogsDownloaderPopover = ({
const [range, setRange] = useState({ from: null, until: null }) const [range, setRange] = useState({ from: null, until: null })
const [anchorEl, setAnchorEl] = useState(null) const [anchorEl, setAnchorEl] = useState(null)
const [fetchLogs] = useLazyQuery(query, { const [fetchLogs] = useLazyQuery(query, {
onCompleted: data => createLogsFile(getLogs(data), range) onCompleted: data => createLogsFile(getLogs(data), range),
}) })
const dateRangePickerClasses = { const dateRangePickerClasses = {
'block h-full': selectedRadio === RANGE, 'block h-full': selectedRadio === RANGE,
hidden: selectedRadio === ALL hidden: selectedRadio === ALL,
} }
const handleRadioButtons = evt => { const handleRadioButtons = evt => {
@ -88,7 +87,7 @@ const LogsDownloaderPopover = ({
(from, until) => { (from, until) => {
setRange({ from, until }) setRange({ from, until })
}, },
[setRange] [setRange],
) )
const downloadLogs = (range, args) => { const downloadLogs = (range, args) => {
@ -97,8 +96,8 @@ const LogsDownloaderPopover = ({
variables: { variables: {
...args, ...args,
simplified: selectedAdvancedRadio === SIMPLIFIED, simplified: selectedAdvancedRadio === SIMPLIFIED,
excludeTestingCustomers: true excludeTestingCustomers: true,
} },
}) })
} }
@ -112,8 +111,8 @@ const LogsDownloaderPopover = ({
from: range.from, from: range.from,
until: range.until, until: range.until,
simplified: selectedAdvancedRadio === SIMPLIFIED, simplified: selectedAdvancedRadio === SIMPLIFIED,
excludeTestingCustomers: true excludeTestingCustomers: true,
} },
}) })
} }
} }
@ -124,7 +123,7 @@ const LogsDownloaderPopover = ({
} }
const blob = new window.Blob([logs], { const blob = new window.Blob([logs], {
type: 'text/plain;charset=utf-8' type: 'text/plain;charset=utf-8',
}) })
FileSaver.saveAs( FileSaver.saveAs(
@ -132,8 +131,8 @@ const LogsDownloaderPopover = ({
selectedRadio === ALL selectedRadio === ALL
? `${formatDateFile(new Date())}_${name}.csv` ? `${formatDateFile(new Date())}_${name}.csv`
: `${formatDateFile(range.from)}_${formatDateFile( : `${formatDateFile(range.from)}_${formatDateFile(
range.until range.until,
)}_${name}.csv` )}_${name}.csv`,
) )
} }
@ -147,12 +146,12 @@ const LogsDownloaderPopover = ({
const radioButtonOptions = [ const radioButtonOptions = [
{ display: 'All logs', code: ALL }, { display: 'All logs', code: ALL },
{ display: 'Date range', code: RANGE } { display: 'Date range', code: RANGE },
] ]
const advancedRadioButtonOptions = [ const advancedRadioButtonOptions = [
{ display: 'Advanced logs', code: ADVANCED }, { display: 'Advanced logs', code: ADVANCED },
{ display: 'Simplified logs', code: SIMPLIFIED } { display: 'Simplified logs', code: SIMPLIFIED },
] ]
const open = Boolean(anchorEl) const open = Boolean(anchorEl)
@ -201,9 +200,9 @@ const LogsDownloaderPopover = ({
hours: 23, hours: 23,
minutes: 59, minutes: 59,
seconds: 59, seconds: 59,
milliseconds: 999 milliseconds: 999,
}, },
new Date() new Date(),
)} )}
onRangeChange={handleRangeChange} onRangeChange={handleRangeChange}
/> />

View file

@ -17,14 +17,12 @@ const Modal = ({
infoPanel, infoPanel,
handleClose, handleClose,
children, children,
secondaryModal,
className, className,
closeOnEscape, closeOnEscape,
closeOnBackdropClick, closeOnBackdropClick,
...props ...props
}) => { }) => {
const TitleCase = small ? H4 : H1 const TitleCase = small ? H4 : H1
const closeSize = xl ? 28 : small ? 16 : 20
const innerClose = (evt, reason) => { const innerClose = (evt, reason) => {
if (!closeOnBackdropClick && reason === 'backdropClick') return if (!closeOnBackdropClick && reason === 'backdropClick') return
@ -44,7 +42,7 @@ const Modal = ({
style={{ width, height, minHeight: height ?? 400 }} style={{ width, height, minHeight: height ?? 400 }}
className={classnames( className={classnames(
'flex flex-col max-h-[90vh] rounded-lg outline-0', 'flex flex-col max-h-[90vh] rounded-lg outline-0',
className className,
)}> )}>
<div className="flex"> <div className="flex">
{title && ( {title && (
@ -78,11 +76,11 @@ const Modal = ({
style={{ style={{
width, width,
height: infoPanelHeight, height: infoPanelHeight,
minHeight: infoPanelHeight ?? 200 minHeight: infoPanelHeight ?? 200,
}} }}
className={classnames( className={classnames(
'mt-4 flex flex-col max-h-[90vh] overflow-y-auto rounded-lg outline-0', 'mt-4 flex flex-col max-h-[90vh] overflow-y-auto rounded-lg outline-0',
className className,
)}> )}>
<div className="w-full flex flex-col flex-1 py-0 px-6"> <div className="w-full flex flex-col flex-1 py-0 px-6">
{infoPanel} {infoPanel}

View file

@ -52,28 +52,28 @@ const NotificationCenter = ({
hasUnreadProp, hasUnreadProp,
buttonCoords, buttonCoords,
popperRef, popperRef,
refetchHasUnreadHeader refetchHasUnreadHeader,
}) => { }) => {
const { data, loading } = useQuery(GET_NOTIFICATIONS, { const { data, loading } = useQuery(GET_NOTIFICATIONS, {
pollInterval: 60000 pollInterval: 60000,
}) })
const [xOffset, setXoffset] = useState(300) const [xOffset, setXoffset] = useState(300)
const [showingUnread, setShowingUnread] = useState(false) const [showingUnread, setShowingUnread] = useState(false)
const machines = R.compose( const machines = R.compose(
R.map(R.prop('name')), R.map(R.prop('name')),
R.indexBy(R.prop('deviceId')) R.indexBy(R.prop('deviceId')),
)(R.path(['machines'])(data) ?? []) )(R.path(['machines'])(data) ?? [])
const notifications = R.path(['notifications'])(data) ?? [] const notifications = R.path(['notifications'])(data) ?? []
const [hasUnread, setHasUnread] = useState(hasUnreadProp) const [hasUnread, setHasUnread] = useState(hasUnreadProp)
const [toggleClearNotification] = useMutation(TOGGLE_CLEAR_NOTIFICATION, { const [toggleClearNotification] = useMutation(TOGGLE_CLEAR_NOTIFICATION, {
onError: () => console.error('Error while clearing notification'), onError: () => console.error('Error while clearing notification'),
refetchQueries: () => ['getNotifications'] refetchQueries: () => ['getNotifications'],
}) })
const [clearAllNotifications] = useMutation(CLEAR_ALL_NOTIFICATIONS, { const [clearAllNotifications] = useMutation(CLEAR_ALL_NOTIFICATIONS, {
onError: () => console.error('Error while clearing all notifications'), onError: () => console.error('Error while clearing all notifications'),
refetchQueries: () => ['getNotifications'] refetchQueries: () => ['getNotifications'],
}) })
useEffect(() => { useEffect(() => {
@ -103,7 +103,7 @@ const NotificationCenter = ({
valid={n.valid} valid={n.valid}
toggleClear={() => toggleClear={() =>
toggleClearNotification({ toggleClearNotification({
variables: { id: n.id, read: !n.read } variables: { id: n.id, read: !n.read },
}) })
} }
/> />
@ -121,7 +121,7 @@ const NotificationCenter = ({
className={classes.notificationIcon} className={classes.notificationIcon}
style={{ style={{
top: buttonCoords?.y ?? 0, top: buttonCoords?.y ?? 0,
left: buttonCoords?.x ? buttonCoords.x - xOffset : 0 left: buttonCoords?.x ? buttonCoords.x - xOffset : 0,
}}> }}>
<NotificationIconZodiac /> <NotificationIconZodiac />
{hasUnread && <div className={classes.hasUnread} />} {hasUnread && <div className={classes.hasUnread} />}

View file

@ -6,8 +6,10 @@
box-shadow: 0 0 14px 0 rgba(0, 0, 0, 0.24); box-shadow: 0 0 14px 0 rgba(0, 0, 0, 0.24);
} }
.container @media only screen and (max-width: 1920px) { @media only screen and (max-width: 1920px) {
width: 30vw; .container {
width: 30vw;
}
} }
.header { .header {
@ -75,7 +77,7 @@
} }
.unread { .unread {
background-color: var(--spring3) background-color: var(--spring3);
} }
.notificationRowIcon { .notificationRowIcon {
@ -83,11 +85,11 @@
} }
.notificationRowIcon > * { .notificationRowIcon > * {
margin-left: 24px margin-left: 24px;
} }
.readIconWrapper { .readIconWrapper {
flex-grow: 1 flex-grow: 1;
} }
.unreadIcon { .unreadIcon {
@ -118,7 +120,7 @@
} }
.notificationBody { .notificationBody {
margin: 0 margin: 0;
} }
.notificationSubtitle { .notificationSubtitle {
@ -142,4 +144,4 @@
height: 9px; height: 9px;
background-color: var(--spring); background-color: var(--spring);
border-radius: 50%; border-radius: 50%;
} }

View file

@ -12,37 +12,36 @@ import classes from './NotificationCenter.module.css'
const types = { const types = {
transaction: { transaction: {
display: 'Transactions', display: 'Transactions',
icon: <Transaction height={16} width={16} /> icon: <Transaction height={16} width={16} />,
}, },
highValueTransaction: { highValueTransaction: {
display: 'Transactions', display: 'Transactions',
icon: <Transaction height={16} width={16} /> icon: <Transaction height={16} width={16} />,
}, },
fiatBalance: { fiatBalance: {
display: 'Maintenance', display: 'Maintenance',
icon: <Wrench height={16} width={16} /> icon: <Wrench height={16} width={16} />,
}, },
cryptoBalance: { cryptoBalance: {
display: 'Maintenance', display: 'Maintenance',
icon: <Wrench height={16} width={16} /> icon: <Wrench height={16} width={16} />,
}, },
compliance: { compliance: {
display: 'Compliance', display: 'Compliance',
icon: <WarningIcon height={16} width={16} /> icon: <WarningIcon height={16} width={16} />,
}, },
error: { display: 'Error', icon: <WarningIcon height={16} width={16} /> } error: { display: 'Error', icon: <WarningIcon height={16} width={16} /> },
} }
const NotificationRow = ({ const NotificationRow = ({
id, id,
type, type,
detail,
message, message,
deviceName, deviceName,
created, created,
read, read,
valid, valid,
toggleClear toggleClear,
}) => { }) => {
const typeDisplay = R.path([type, 'display'])(types) ?? null const typeDisplay = R.path([type, 'display'])(types) ?? null
const icon = R.path([type, 'icon'])(types) ?? ( const icon = R.path([type, 'icon'])(types) ?? (
@ -50,7 +49,7 @@ const NotificationRow = ({
) )
const age = prettyMs(new Date().getTime() - new Date(created).getTime(), { const age = prettyMs(new Date().getTime() - new Date(created).getTime(), {
compact: true, compact: true,
verbose: true verbose: true,
}) })
const notificationTitle = const notificationTitle =
typeDisplay && deviceName typeDisplay && deviceName
@ -61,13 +60,13 @@ const NotificationRow = ({
const iconClass = { const iconClass = {
[classes.readIcon]: read, [classes.readIcon]: read,
[classes.unreadIcon]: !read [classes.unreadIcon]: !read,
} }
return ( return (
<div <div
className={classnames( className={classnames(
classes.notificationRow, classes.notificationRow,
!read && valid ? classes.unread : '' !read && valid ? classes.unread : '',
)}> )}>
<div className={classes.notificationRowIcon}> <div className={classes.notificationRowIcon}>
<div>{icon}</div> <div>{icon}</div>

View file

@ -1,2 +1,3 @@
import NotificationCenter from './NotificationCenter' import NotificationCenter from './NotificationCenter'
export default NotificationCenter export default NotificationCenter

View file

@ -14,7 +14,7 @@ const Popover = ({ children, bgColor = white, className, ...props }) => {
top: ['bottom'], top: ['bottom'],
bottom: ['top'], bottom: ['top'],
left: ['right'], left: ['right'],
right: ['left'] right: ['left'],
} }
const modifiers = [ const modifiers = [
@ -22,36 +22,36 @@ const Popover = ({ children, bgColor = white, className, ...props }) => {
name: 'flip', name: 'flip',
enabled: R.defaultTo(false, props.flip), enabled: R.defaultTo(false, props.flip),
options: { options: {
allowedAutoPlacements: flipPlacements[props.placement] allowedAutoPlacements: flipPlacements[props.placement],
} },
}, },
{ {
name: 'preventOverflow', name: 'preventOverflow',
enabled: true, enabled: true,
options: { options: {
rootBoundary: 'scrollParent' rootBoundary: 'scrollParent',
} },
}, },
{ {
name: 'offset', name: 'offset',
enabled: true, enabled: true,
options: { options: {
offset: [0, 10] offset: [0, 10],
} },
}, },
{ {
name: 'arrow', name: 'arrow',
enabled: R.defaultTo(true, props.showArrow), enabled: R.defaultTo(true, props.showArrow),
options: { options: {
element: arrowRef element: arrowRef,
} },
}, },
{ {
name: 'computeStyles', name: 'computeStyles',
options: { options: {
gpuAcceleration: false gpuAcceleration: false,
} },
} },
] ]
return ( return (

View file

@ -30,4 +30,4 @@
.tooltip[data-popper-placement^='right'] > div > span { .tooltip[data-popper-placement^='right'] > div > span {
left: -4px; left: -4px;
} }

View file

@ -12,7 +12,6 @@ const SearchBox = memo(
filters = [], filters = [],
options = [], options = [],
inputPlaceholder = '', inputPlaceholder = '',
size,
onChange, onChange,
...props ...props
}) => { }) => {
@ -20,7 +19,7 @@ const SearchBox = memo(
const inputClasses = { const inputClasses = {
'flex flex-1 h-8 px-2 py-2 font-md items-center rounded-2xl bg-zircon text-comet': true, 'flex flex-1 h-8 px-2 py-2 font-md items-center rounded-2xl bg-zircon text-comet': true,
'rounded-b-none': popupOpen 'rounded-b-none': popupOpen,
} }
const innerOnChange = filters => onChange(filters) const innerOnChange = filters => onChange(filters)
@ -57,7 +56,7 @@ const SearchBox = memo(
placeholder={inputPlaceholder} placeholder={inputPlaceholder}
inputProps={{ inputProps={{
className: 'font-bold', className: 'font-bold',
...params.inputProps ...params.inputProps,
}} }}
/> />
) )
@ -74,10 +73,11 @@ const SearchBox = memo(
<div className="w-[88%] h-[1px] my-p mx-auto border-1 border-comet" /> <div className="w-[88%] h-[1px] my-p mx-auto border-1 border-comet" />
{children} {children}
</Paper> </Paper>
) ),
}} /> }}
); />
} )
},
) )
export default SearchBox export default SearchBox

View file

@ -12,7 +12,7 @@ const SearchFilter = ({
filters, filters,
onFilterDelete, onFilterDelete,
deleteAllFilters, deleteAllFilters,
entries = 0 entries = 0,
}) => { }) => {
return ( return (
<> <>
@ -33,7 +33,7 @@ const SearchFilter = ({
<Label3 className="text-comet m-auto mr-3">{`${entries} ${singularOrPlural( <Label3 className="text-comet m-auto mr-3">{`${entries} ${singularOrPlural(
entries, entries,
`entry`, `entry`,
`entries` `entries`,
)}`}</Label3> )}`}</Label3>
} }
<ActionButton <ActionButton

View file

@ -18,13 +18,13 @@ const Stepper = memo(({ steps, currentStep, color = 'spring', className }) => {
const separatorClasses = { const separatorClasses = {
'w-7 h-[2px] border-2 z-1': true, 'w-7 h-[2px] border-2 z-1': true,
'border-spring': color === 'spring', 'border-spring': color === 'spring',
'border-zodiac': color === 'zodiac' 'border-zodiac': color === 'zodiac',
} }
const separatorEmptyClasses = { const separatorEmptyClasses = {
'w-7 h-[2px] border-2 z-1': true, 'w-7 h-[2px] border-2 z-1': true,
'border-dust': color === 'spring', 'border-dust': color === 'spring',
'border-comet': color === 'zodiac' 'border-comet': color === 'zodiac',
} }
return ( return (

View file

@ -9,4 +9,4 @@
height: 100%; height: 100%;
width: 100%; width: 100%;
overflow: visible; overflow: visible;
} }

View file

@ -6,7 +6,7 @@ import { TL1 } from './typography'
const Subtitle = memo(({ children, className, extraMarginTop }) => { const Subtitle = memo(({ children, className, extraMarginTop }) => {
const classNames = { const classNames = {
'text-comet my-4': true, 'text-comet my-4': true,
'mt-18': extraMarginTop 'mt-18': extraMarginTop,
} }
return <TL1 className={classnames(classNames, className)}>{children}</TL1> return <TL1 className={classnames(classNames, className)}>{children}</TL1>

View file

@ -4,30 +4,6 @@ import React, { useState, memo } from 'react'
import Popper from 'src/components/Popper' import Popper from 'src/components/Popper'
import HelpIcon from 'src/styling/icons/action/help/zodiac.svg?react' import HelpIcon from 'src/styling/icons/action/help/zodiac.svg?react'
const useStyles = {
transparentButton: {
border: 'none',
backgroundColor: 'transparent',
outline: 'none',
cursor: 'pointer',
marginTop: 4
},
relativelyPositioned: {
position: 'relative'
},
safeSpace: {
position: 'absolute',
backgroundColor: '#0000',
height: 40,
left: '-50%',
width: '200%'
},
popoverContent: ({ width }) => ({
width,
padding: [[10, 15]]
})
}
const usePopperHandler = () => { const usePopperHandler = () => {
const [helpPopperAnchorEl, setHelpPopperAnchorEl] = useState(null) const [helpPopperAnchorEl, setHelpPopperAnchorEl] = useState(null)
@ -50,7 +26,7 @@ const usePopperHandler = () => {
helpPopperOpen, helpPopperOpen,
handleOpenHelpPopper, handleOpenHelpPopper,
openHelpPopper, openHelpPopper,
handleCloseHelpPopper handleCloseHelpPopper,
} }
} }

View file

@ -25,27 +25,27 @@ const BooleanPropertiesTable = memo(
const [editing, setEditing] = useState(forcedEditing) const [editing, setEditing] = useState(forcedEditing)
const initialValues = R.fromPairs( const initialValues = R.fromPairs(
elements.map(it => [it.name, data[it.name]?.toString() ?? 'false']) elements.map(it => [it.name, data[it.name]?.toString() ?? 'false']),
) )
const validationSchema = Yup.object().shape( const validationSchema = Yup.object().shape(
R.fromPairs( R.fromPairs(
elements.map(it => [ elements.map(it => [
it.name, it.name,
Yup.mixed().oneOf(['true', 'false', true, false]).required() Yup.mixed().oneOf(['true', 'false', true, false]).required(),
]) ]),
) ),
) )
const innerSave = async values => { const innerSave = async values => {
const toBoolean = (num, _) => R.equals(num, 'true') const toBoolean = num => R.equals(num, 'true')
save(R.mapObjIndexed(toBoolean, R.filter(R.complement(R.isNil))(values))) save(R.mapObjIndexed(toBoolean, R.filter(R.complement(R.isNil))(values)))
setEditing(false) setEditing(false)
} }
const radioButtonOptions = [ const radioButtonOptions = [
{ display: 'Yes', code: 'true' }, { display: 'Yes', code: 'true' },
{ display: 'No', code: 'false' } { display: 'No', code: 'false' },
] ]
return ( return (
<div className="flex w-sm flex-col "> <div className="flex w-sm flex-col ">
@ -117,7 +117,7 @@ const BooleanPropertiesTable = memo(
</Formik> </Formik>
</div> </div>
) )
} },
) )
export default BooleanPropertiesTable export default BooleanPropertiesTable

View file

@ -21,7 +21,7 @@ const ActionButton = memo(
[moduleStyles.secondary]: color === 'secondary', [moduleStyles.secondary]: color === 'secondary',
[moduleStyles.spring]: color === 'spring', [moduleStyles.spring]: color === 'spring',
[moduleStyles.tomato]: color === 'tomato', [moduleStyles.tomato]: color === 'tomato',
[moduleStyles.center]: center [moduleStyles.center]: center,
} }
return ( return (
@ -35,7 +35,7 @@ const ActionButton = memo(
<div <div
className={classnames( className={classnames(
moduleStyles.actionButtonIcon, moduleStyles.actionButtonIcon,
moduleStyles.actionButtonIconActive moduleStyles.actionButtonIconActive,
)}> )}>
<InverseIcon /> <InverseIcon />
</div> </div>
@ -43,7 +43,7 @@ const ActionButton = memo(
{children && <div>{children}</div>} {children && <div>{children}</div>}
</button> </button>
) )
} },
) )
export default ActionButton export default ActionButton

View file

@ -4,18 +4,18 @@ import {
subheaderColor, subheaderColor,
subheaderDarkColor, subheaderDarkColor,
offColor, offColor,
offDarkColor offDarkColor,
} from 'src/styling/variables' } from 'src/styling/variables'
const colors = (color1, color2, color3) => { const colors = (color1, color2, color3) => {
return { return {
backgroundColor: color1, backgroundColor: color1,
'&:hover': { '&:hover': {
backgroundColor: color2 backgroundColor: color2,
}, },
'&:active': { '&:active': {
backgroundColor: color3 backgroundColor: color3,
} },
} }
} }
@ -30,23 +30,23 @@ export default {
height: buttonHeight, height: buttonHeight,
color: fontColor, color: fontColor,
'&:active': { '&:active': {
color: white color: white,
} },
}, },
primary: { primary: {
extend: colors(subheaderColor, subheaderDarkColor, offColor), extend: colors(subheaderColor, subheaderDarkColor, offColor),
'&:active': { '&:active': {
color: white, color: white,
'& $buttonIcon': { '& $buttonIcon': {
display: 'none' display: 'none',
}, },
'& $buttonIconActive': { '& $buttonIconActive': {
display: 'block' display: 'block',
} },
}, },
'& $buttonIconActive': { '& $buttonIconActive': {
display: 'none' display: 'none',
} },
}, },
secondary: { secondary: {
extend: colors(offColor, offDarkColor, white), extend: colors(offColor, offDarkColor, white),
@ -54,17 +54,17 @@ export default {
'&:active': { '&:active': {
color: fontColor, color: fontColor,
'& $buttonIcon': { '& $buttonIcon': {
display: 'flex' display: 'flex',
}, },
'& $buttonIconActive': { '& $buttonIconActive': {
display: 'none' display: 'none',
} },
}, },
'& $buttonIcon': { '& $buttonIcon': {
display: 'none' display: 'none',
}, },
'& $buttonIconActive': { '& $buttonIconActive': {
display: 'flex' display: 'flex',
} },
} },
} }

View file

@ -29,15 +29,15 @@ const ActionButton = memo(
'text-white', 'text-white',
{ {
[moduleStyles.buttonSm]: size === 'sm', [moduleStyles.buttonSm]: size === 'sm',
[moduleStyles.buttonXl]: size === 'xl' [moduleStyles.buttonXl]: size === 'xl',
} },
)} )}
{...props}> {...props}>
{children} {children}
</button> </button>
</div> </div>
) )
} },
) )
export default ActionButton export default ActionButton

View file

@ -14,13 +14,13 @@
.buttonXl { .buttonXl {
composes: h1 from '../typography/typography.module.css'; composes: h1 from '../typography/typography.module.css';
height: 61px; height: 61px;
border-radius: 15px border-radius: 15px;
} }
.buttonSm { .buttonSm {
height: 32px; height: 32px;
padding: 0 16px; padding: 0 16px;
border-radius: 8px border-radius: 8px;
} }
.button:disabled { .button:disabled {
@ -46,4 +46,4 @@
margin-top: 2px; margin-top: 2px;
background-color: var(--spring2); background-color: var(--spring2);
box-shadow: 0 2px var(--spring4); box-shadow: 0 2px var(--spring4);
} }

View file

@ -11,7 +11,7 @@ const FeatureButton = memo(
classes.baseButton, classes.baseButton,
classes.roundButton, classes.roundButton,
classes.primary, classes.primary,
className className,
)} )}
{...props}> {...props}>
{Icon && ( {Icon && (
@ -23,7 +23,7 @@ const FeatureButton = memo(
<div <div
className={classnames( className={classnames(
classes.buttonIcon, classes.buttonIcon,
classes.buttonIconActive classes.buttonIconActive,
)}> )}>
<InverseIcon /> <InverseIcon />
</div> </div>
@ -31,7 +31,7 @@ const FeatureButton = memo(
{children} {children}
</button> </button>
) )
} },
) )
export default FeatureButton export default FeatureButton

View file

@ -11,7 +11,6 @@ const IDButton = memo(
className, className,
Icon, Icon,
InverseIcon, InverseIcon,
popoverWidth = 152,
children, children,
popoverClassname, popoverClassname,
...props ...props
@ -25,11 +24,11 @@ const IDButton = memo(
[classes.idButton]: true, [classes.idButton]: true,
[classes.primary]: true, [classes.primary]: true,
[classes.open]: open, [classes.open]: open,
[classes.closed]: !open [classes.closed]: !open,
} }
const iconClassNames = { const iconClassNames = {
[classes.buttonIcon]: true [classes.buttonIcon]: true,
} }
const handleClick = event => { const handleClick = event => {
@ -74,7 +73,7 @@ const IDButton = memo(
</Popover> </Popover>
</> </>
) )
} },
) )
export default IDButton export default IDButton

View file

@ -10,7 +10,7 @@ const Link = memo(
[classes.primary]: color === 'primary', [classes.primary]: color === 'primary',
[classes.secondary]: color === 'secondary', [classes.secondary]: color === 'secondary',
[classes.noColor]: color === 'noColor', [classes.noColor]: color === 'noColor',
[classes.action]: color === 'action' [classes.action]: color === 'action',
} }
return ( return (
@ -21,7 +21,7 @@ const Link = memo(
{children} {children}
</button> </button>
) )
} },
) )
export default Link export default Link

View file

@ -44,4 +44,4 @@
.action:hover { .action:hover {
box-shadow: none; box-shadow: none;
background-color: rgba(72, 246, 148, 0.8); background-color: rgba(72, 246, 148, 0.8);
} }

View file

@ -12,14 +12,14 @@ const SubpageButton = memo(
InverseIcon, InverseIcon,
toggle, toggle,
forceDisable = false, forceDisable = false,
children children,
}) => { }) => {
const [active, setActive] = useState(false) const [active, setActive] = useState(false)
const isActive = forceDisable ? false : active const isActive = forceDisable ? false : active
const classNames = { const classNames = {
[classes.button]: true, [classes.button]: true,
[classes.normal]: !isActive, [classes.normal]: !isActive,
[classes.active]: isActive [classes.active]: isActive,
} }
const normalButton = <Icon className={classes.buttonIcon} /> const normalButton = <Icon className={classes.buttonIcon} />
@ -29,14 +29,14 @@ const SubpageButton = memo(
<InverseIcon <InverseIcon
className={classnames( className={classnames(
classes.buttonIcon, classes.buttonIcon,
classes.buttonIconActiveLeft classes.buttonIconActiveLeft,
)} )}
/> />
<H4 className="text-white">{children}</H4> <H4 className="text-white">{children}</H4>
<CancelIconInverse <CancelIconInverse
className={classnames( className={classnames(
classes.buttonIcon, classes.buttonIcon,
classes.buttonIconActiveRight classes.buttonIconActiveRight,
)} )}
/> />
</> </>
@ -56,7 +56,7 @@ const SubpageButton = memo(
{isActive ? activeButton : normalButton} {isActive ? activeButton : normalButton}
</button> </button>
) )
} },
) )
export default SubpageButton export default SubpageButton

View file

@ -27,7 +27,7 @@
} }
.active:hover { .active:hover {
background-color: var(--comet); background-color: var(--comet);
} }
.buttonIcon { .buttonIcon {

View file

@ -8,10 +8,10 @@ export default {
extend: baseButton, extend: baseButton,
padding: 0, padding: 0,
color: white, color: white,
borderRadius: baseButton.height / 2 borderRadius: baseButton.height / 2,
}, },
normalButton: { normalButton: {
width: baseButton.height width: baseButton.height,
}, },
activeButton: { activeButton: {
display: 'flex', display: 'flex',
@ -21,26 +21,26 @@ export default {
fontWeight: 'bold', fontWeight: 'bold',
padding: '0 5px', padding: '0 5px',
'&:hover': { '&:hover': {
backgroundColor: offColor backgroundColor: offColor,
} },
}, },
buttonIcon: { buttonIcon: {
width: 16, width: 16,
height: 16, height: 16,
overflow: 'visible', overflow: 'visible',
'& g': { '& g': {
strokeWidth: 1.8 strokeWidth: 1.8,
} },
}, },
buttonIconActiveLeft: { buttonIconActiveLeft: {
marginRight: 12, marginRight: 12,
marginLeft: 4 marginLeft: 4,
}, },
buttonIconActiveRight: { buttonIconActiveRight: {
marginRight: 5, marginRight: 5,
marginLeft: 20 marginLeft: 20,
}, },
white: { white: {
color: white color: white,
} },
} }

View file

@ -15,5 +15,5 @@ export {
IDButton, IDButton,
AddButton, AddButton,
SupportLinkButton, SupportLinkButton,
SubpageButton SubpageButton,
} }

View file

@ -10,7 +10,7 @@ import {
lastDayOfMonth, lastDayOfMonth,
startOfMonth, startOfMonth,
startOfWeek, startOfWeek,
sub sub,
} from 'date-fns/fp' } from 'date-fns/fp'
import * as R from 'ramda' import * as R from 'ramda'
import React, { useState } from 'react' import React, { useState } from 'react'
@ -24,7 +24,7 @@ const Calendar = ({ minDate, maxDate, handleSelect, ...props }) => {
const [currentDisplayedMonth, setCurrentDisplayedMonth] = useState(new Date()) const [currentDisplayedMonth, setCurrentDisplayedMonth] = useState(new Date())
const weekdays = Array.from(Array(7)).map((_, i) => const weekdays = Array.from(Array(7)).map((_, i) =>
format('EEEEE', add({ days: i }, startOfWeek(new Date()))) format('EEEEE', add({ days: i }, startOfWeek(new Date()))),
) )
const monthLength = month => getDaysInMonth(month) const monthLength = month => getDaysInMonth(month)
@ -33,21 +33,21 @@ const Calendar = ({ minDate, maxDate, handleSelect, ...props }) => {
const lastMonth = sub({ months: 1 }, month) const lastMonth = sub({ months: 1 }, month)
const lastMonthRange = R.range(0, getDay(startOfMonth(month))).reverse() const lastMonthRange = R.range(0, getDay(startOfMonth(month))).reverse()
const lastMonthDays = R.map(i => const lastMonthDays = R.map(i =>
sub({ days: i }, lastDayOfMonth(lastMonth)) sub({ days: i }, lastDayOfMonth(lastMonth)),
)(lastMonthRange) )(lastMonthRange)
const thisMonthRange = R.range(0, monthLength(month)) const thisMonthRange = R.range(0, monthLength(month))
const thisMonthDays = R.map(i => add({ days: i }, startOfMonth(month)))( const thisMonthDays = R.map(i => add({ days: i }, startOfMonth(month)))(
thisMonthRange thisMonthRange,
) )
const nextMonth = add({ months: 1 }, month) const nextMonth = add({ months: 1 }, month)
const nextMonthRange = R.range( const nextMonthRange = R.range(
0, 0,
42 - lastMonthDays.length - thisMonthDays.length 42 - lastMonthDays.length - thisMonthDays.length,
) )
const nextMonthDays = R.map(i => add({ days: i }, startOfMonth(nextMonth)))( const nextMonthDays = R.map(i => add({ days: i }, startOfMonth(nextMonth)))(
nextMonthRange nextMonthRange,
) )
return R.concat(R.concat(lastMonthDays, thisMonthDays), nextMonthDays) return R.concat(R.concat(lastMonthDays, thisMonthDays), nextMonthDays)
@ -63,7 +63,7 @@ const Calendar = ({ minDate, maxDate, handleSelect, ...props }) => {
isSameMonth(minDate, prevMonth) || isSameMonth(minDate, prevMonth) ||
differenceInMonths(minDate, prevMonth) > 0 differenceInMonths(minDate, prevMonth) > 0
? prevMonth ? prevMonth
: currentDisplayedMonth : currentDisplayedMonth,
) )
} }
} }
@ -75,7 +75,7 @@ const Calendar = ({ minDate, maxDate, handleSelect, ...props }) => {
isSameMonth(maxDate, nextMonth) || isSameMonth(maxDate, nextMonth) ||
differenceInMonths(nextMonth, maxDate) > 0 differenceInMonths(nextMonth, maxDate) > 0
? nextMonth ? nextMonth
: currentDisplayedMonth : currentDisplayedMonth,
) )
} }
} }
@ -91,7 +91,7 @@ const Calendar = ({ minDate, maxDate, handleSelect, ...props }) => {
<span> <span>
{`${format('MMMM', currentDisplayedMonth)} ${format( {`${format('MMMM', currentDisplayedMonth)} ${format(
'yyyy', 'yyyy',
currentDisplayedMonth currentDisplayedMonth,
)}`} )}`}
</span> </span>
<button <button

View file

@ -53,7 +53,7 @@
padding-right: 5px; padding-right: 5px;
} }
.table th, .table th,
.table td { .table td {
margin: 0; margin: 0;
padding: 3px 0 3px 0; padding: 3px 0 3px 0;
@ -63,4 +63,4 @@
font-size: 13px; font-size: 13px;
font-family: var(--museo); font-family: var(--museo);
font-weight: 700; font-weight: 700;
} }

View file

@ -23,14 +23,14 @@ const DateRangePicker = ({ minDate, maxDate, className, onRangeChange }) => {
if (from && !to) { if (from && !to) {
if (differenceInDays(from, day) >= 0) { if (differenceInDays(from, day) >= 0) {
setTo( setTo(
set({ hours: 23, minutes: 59, seconds: 59, milliseconds: 999 }, day) set({ hours: 23, minutes: 59, seconds: 59, milliseconds: 999 }, day),
) )
} else { } else {
setTo( setTo(
set( set(
{ hours: 23, minutes: 59, seconds: 59, milliseconds: 999 }, { hours: 23, minutes: 59, seconds: 59, milliseconds: 999 },
R.clone(from) R.clone(from),
) ),
) )
setFrom(day) setFrom(day)
} }

View file

@ -8,24 +8,24 @@ const Tile = ({
isUpperBound, isUpperBound,
isBetween, isBetween,
isDisabled, isDisabled,
children children,
}) => { }) => {
const selected = isLowerBound || isUpperBound const selected = isLowerBound || isUpperBound
const rangeClasses = { const rangeClasses = {
[classes.between]: isBetween && !(isLowerBound && isUpperBound), [classes.between]: isBetween && !(isLowerBound && isUpperBound),
[classes.lowerBound]: isLowerBound && !isUpperBound, [classes.lowerBound]: isLowerBound && !isUpperBound,
[classes.upperBound]: isUpperBound && !isLowerBound [classes.upperBound]: isUpperBound && !isLowerBound,
} }
const buttonWrapperClasses = { const buttonWrapperClasses = {
[classes.wrapper]: true, [classes.wrapper]: true,
[classes.selected]: selected [classes.selected]: selected,
} }
const buttonClasses = { const buttonClasses = {
[classes.button]: true, [classes.button]: true,
[classes.disabled]: isDisabled [classes.disabled]: isDisabled,
} }
return ( return (

View file

@ -5,7 +5,7 @@ import {
Td, Td,
THead, THead,
TDoubleLevelHead, TDoubleLevelHead,
ThDoubleLevel ThDoubleLevel,
} from 'src/components/fake-table/Table' } from 'src/components/fake-table/Table'
import { sentenceCase } from 'src/utils/string' import { sentenceCase } from 'src/utils/string'
@ -24,11 +24,11 @@ const groupSecondHeader = elements => {
{ {
width: R.sum(R.map(R.prop('width'), group)), width: R.sum(R.map(R.prop('width'), group)),
elements: group, elements: group,
name: doubleHeader(group[0]) name: doubleHeader(group[0]),
} },
] ],
), ),
R.reduce(R.concat, []) R.reduce(R.concat, []),
) )
return R.all(R.pipe(doubleHeader, R.isNil), elements) return R.all(R.pipe(doubleHeader, R.isNil), elements)
@ -47,7 +47,7 @@ const Header = () => {
enableToggle, enableToggle,
toggleWidth, toggleWidth,
orderedBy, orderedBy,
DEFAULT_COL_SIZE DEFAULT_COL_SIZE,
} = useContext(TableCtx) } = useContext(TableCtx)
const mapElement2 = (it, idx) => { const mapElement2 = (it, idx) => {
@ -66,11 +66,13 @@ const Header = () => {
const mapElement = ( const mapElement = (
{ name, display, width = DEFAULT_COL_SIZE, header, textAlign }, { name, display, width = DEFAULT_COL_SIZE, header, textAlign },
idx idx,
) => { ) => {
const orderClasses = classnames({ const orderClasses = classnames({
'whitespace-nowrap': 'whitespace-nowrap':
R.isNil(header) && !R.isNil(orderedBy) && R.equals(name, orderedBy.code) R.isNil(header) &&
!R.isNil(orderedBy) &&
R.equals(name, orderedBy.code),
}) })
const attachOrderedByToComplexHeader = header => { const attachOrderedByToComplexHeader = header => {
@ -82,6 +84,7 @@ const Header = () => {
spanChild.props.children = R.append(' -', spanChild.props.children) spanChild.props.children = R.append(' -', spanChild.props.children)
return cloneHeader return cloneHeader
} catch (e) { } catch (e) {
console.error(e)
return header return header
} }
} }

View file

@ -18,7 +18,7 @@ const NamespacedTable = ({
const innerData = R.map(it => ({ const innerData = R.map(it => ({
id: it, id: it,
...fromNamespace(it)(data) ...fromNamespace(it)(data),
}))(namespaces) }))(namespaces)
return ( return (

View file

@ -35,7 +35,7 @@ const ActionCol = ({ disabled, editing }) => {
forceAdd, forceAdd,
clearError, clearError,
actionColSize, actionColSize,
error error,
} = useContext(TableCtx) } = useContext(TableCtx)
const disableEdit = disabled || (disableRowEdit && disableRowEdit(values)) const disableEdit = disabled || (disableRowEdit && disableRowEdit(values))
@ -136,10 +136,10 @@ const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
PrefixComponent = Label2, PrefixComponent = Label2,
suffix, suffix,
SuffixComponent = Label2, SuffixComponent = Label2,
textStyle = it => {}, textStyle = () => {},
isHidden = it => false, isHidden = () => false,
view = it => it?.toString(), view = it => it?.toString(),
inputProps = {} inputProps = {},
} = config } = config
const fields = names ?? [name] const fields = names ?? [name]
@ -158,7 +158,7 @@ const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
size, size,
bold, bold,
textAlign: isEditing ? editingAlign : textAlign, textAlign: isEditing ? editingAlign : textAlign,
...inputProps ...inputProps,
} }
const newAlign = isEditing ? editingAlign : textAlign const newAlign = isEditing ? editingAlign : textAlign
@ -174,7 +174,7 @@ const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
className={{ className={{
[moduleStyles.extraPaddingRight]: extraPaddingRight, [moduleStyles.extraPaddingRight]: extraPaddingRight,
[moduleStyles.extraPadding]: extraPadding, [moduleStyles.extraPadding]: extraPadding,
'flex items-center': suffix || prefix 'flex items-center': suffix || prefix,
}} }}
width={width} width={width}
size={size} size={size}
@ -225,7 +225,7 @@ const groupStriped = elements => {
return R.insert( return R.insert(
index, index,
{ width, editable: false, view: () => <StripesSvg /> }, { width, editable: false, view: () => <StripesSvg /> },
noStripe noStripe,
) )
} }
@ -238,7 +238,7 @@ const ERow = ({ editing, disabled, lastOfGroup, newRow }) => {
error, error,
enableToggle, enableToggle,
rowSize, rowSize,
stripeWhen stripeWhen,
} = useContext(TableCtx) } = useContext(TableCtx)
const shouldStripe = !editing && stripeWhen && stripeWhen(values) const shouldStripe = !editing && stripeWhen && stripeWhen(values)
@ -255,11 +255,11 @@ const ERow = ({ editing, disabled, lastOfGroup, newRow }) => {
: -1 : -1
const elementToFocusIndex = innerElements.findIndex( const elementToFocusIndex = innerElements.findIndex(
it => it.editable === undefined || it.editable it => it.editable === undefined || it.editable,
) )
const classNames = { const classNames = {
[moduleStyles.lastOfGroup]: lastOfGroup [moduleStyles.lastOfGroup]: lastOfGroup,
} }
const touchedErrors = R.pick(R.keys(touched), errors) const touchedErrors = R.pick(R.keys(touched), errors)

View file

@ -26,4 +26,4 @@
.fields { .fields {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }

View file

@ -19,7 +19,7 @@ const DEFAULT_COL_SIZE = 100
const getWidth = R.compose( const getWidth = R.compose(
R.reduce(R.add)(0), R.reduce(R.add)(0),
R.map(it => it.width ?? DEFAULT_COL_SIZE) R.map(it => it.width ?? DEFAULT_COL_SIZE),
) )
const ETable = ({ const ETable = ({
@ -54,7 +54,7 @@ const ETable = ({
createText = 'Add override', createText = 'Add override',
forceAdd = false, forceAdd = false,
tbodyWrapperClass, tbodyWrapperClass,
orderedBy = null orderedBy = null,
}) => { }) => {
const [editingId, setEditingId] = useState(null) const [editingId, setEditingId] = useState(null)
const [adding, setAdding] = useState(false) const [adding, setAdding] = useState(false)
@ -80,6 +80,7 @@ const ETable = ({
try { try {
await save({ [name]: list }, it) await save({ [name]: list }, it)
} catch (err) { } catch (err) {
console.error(err)
setSaving(false) setSaving(false)
return return
} }
@ -152,7 +153,7 @@ const ETable = ({
stripeWhen, stripeWhen,
forceAdd, forceAdd,
orderedBy, orderedBy,
DEFAULT_COL_SIZE DEFAULT_COL_SIZE,
} }
return ( return (

View file

@ -35,20 +35,20 @@ const Td = ({
size, size,
bold, bold,
textAlign, textAlign,
action action,
}) => { }) => {
const inlineStyle = { const inlineStyle = {
...style, ...style,
width, width,
textAlign, textAlign,
fontSize: size === 'sm' ? '14px' : size === 'lg' ? '24px' : '' fontSize: size === 'sm' ? '14px' : size === 'lg' ? '24px' : '',
} }
const cssClasses = { const cssClasses = {
[styles.td]: !header, [styles.td]: !header,
[styles.tdHeader]: header, [styles.tdHeader]: header,
'font-bold': !header && (bold || size === 'lg'), 'font-bold': !header && (bold || size === 'lg'),
[styles.actionCol]: action [styles.actionCol]: action,
} }
return ( return (
@ -88,21 +88,21 @@ const Tr = ({
children, children,
className, className,
size, size,
newRow newRow,
}) => { }) => {
const inlineStyle = { const inlineStyle = {
minHeight: size === 'sm' ? '34px' : size === 'lg' ? '68px' : '48px' minHeight: size === 'sm' ? '34px' : size === 'lg' ? '68px' : '48px',
} }
const cardClasses = { const cardClasses = {
[styles.card]: true, [styles.card]: true,
[styles.trError]: error, [styles.trError]: error,
[styles.trAdding]: newRow [styles.trAdding]: newRow,
} }
const mainContentClasses = { const mainContentClasses = {
[styles.mainContent]: true, [styles.mainContent]: true,
[styles.sizeSm]: size === 'sm', [styles.sizeSm]: size === 'sm',
[styles.sizeLg]: size === 'lg' [styles.sizeLg]: size === 'lg',
} }
return ( return (
@ -141,5 +141,5 @@ export {
Td, Td,
Th, Th,
ThDoubleLevel, ThDoubleLevel,
EditCell EditCell,
} }

View file

@ -9,7 +9,6 @@ import { P } from 'src/components/typography'
import TextInput from './TextInput' import TextInput from './TextInput'
const Autocomplete = ({ const Autocomplete = ({
optionsLimit = 5, // set limit = null for no limit
limit, limit,
options, options,
label, label,
@ -17,7 +16,6 @@ const Autocomplete = ({
multiple, multiple,
onChange, onChange,
labelProp, labelProp,
shouldStayOpen,
value: outsideValue, value: outsideValue,
error, error,
fullWidth, fullWidth,
@ -61,11 +59,11 @@ const Autocomplete = ({
const filterOptions = (array, { inputValue }) => const filterOptions = (array, { inputValue }) =>
R.union( R.union(
R.isEmpty(inputValue) ? valueArray() : [], R.isEmpty(inputValue) ? valueArray() : [],
filter(array, inputValue) filter(array, inputValue),
).slice( ).slice(
0, 0,
R.defaultTo(undefined)(limit) && R.defaultTo(undefined)(limit) &&
Math.max(limit, R.isEmpty(inputValue) ? valueArray().length : 0) Math.max(limit, R.isEmpty(inputValue) ? valueArray().length : 0),
) )
return ( return (
@ -105,7 +103,7 @@ const Autocomplete = ({
'flex w-4 h-4 rounded-md': true, 'flex w-4 h-4 rounded-md': true,
'bg-spring4': props.warning === 'clean', 'bg-spring4': props.warning === 'clean',
'bg-orange-yellow': props.warning === 'partial', 'bg-orange-yellow': props.warning === 'partial',
'bg-tomato': props.warning === 'important' 'bg-tomato': props.warning === 'important',
} }
const hoverableElement = <div className={classnames(className)} /> const hoverableElement = <div className={classnames(className)} />
@ -122,9 +120,10 @@ const Autocomplete = ({
) )
}} }}
slotProps={{ slotProps={{
chip: { onDelete: null } chip: { onDelete: null },
}} /> }}
); />
)
} }
export default Autocomplete export default Autocomplete

View file

@ -11,7 +11,7 @@ const CodeInput = ({
numInputs, numInputs,
error, error,
inputStyle, inputStyle,
containerStyle containerStyle,
}) => { }) => {
return ( return (
<OtpInput <OtpInput
@ -26,7 +26,7 @@ const CodeInput = ({
inputStyle, inputStyle,
classes.input, classes.input,
'font-museo font-black text-4xl', 'font-museo font-black text-4xl',
error && 'border-tomato' error && 'border-tomato',
)} )}
inputType={'tel'} inputType={'tel'}
renderInput={props => <input {...props} />} renderInput={props => <input {...props} />}

View file

@ -23,7 +23,7 @@ const Dropdown = ({ label, name, options, onChange, value, className }) => {
))} ))}
</Select> </Select>
</FormControl> </FormControl>
); )
} }
export default Dropdown export default Dropdown

View file

@ -18,7 +18,6 @@ const NumberInput = memo(
bold, bold,
className, className,
decimalPlaces, decimalPlaces,
InputProps,
...props ...props
}) => { }) => {
return ( return (
@ -41,14 +40,14 @@ const NumberInput = memo(
onChange({ onChange({
target: { target: {
id: name, id: name,
value: values.floatValue value: values.floatValue,
} },
}) })
}} }}
{...props} {...props}
/> />
) )
} },
) )
export default NumberInput export default NumberInput

View file

@ -13,7 +13,7 @@ const RadioGroup = ({
onChange, onChange,
className, className,
labelClassName, labelClassName,
radioClassName radioClassName,
}) => { }) => {
return ( return (
<> <>

View file

@ -29,7 +29,7 @@ const SecretInput = memo(
placeholder={isPasswordFilled ? placeholder : ''} placeholder={isPasswordFilled ? placeholder : ''}
/> />
) )
} },
) )
export default SecretInput export default SecretInput

View file

@ -7,20 +7,19 @@ import Arrowdown from 'src/styling/icons/action/arrow/regular.svg?react'
import styles from './Select.module.css' import styles from './Select.module.css'
function Select({ className, label, items, ...props }) { function Select({ className, label, items, ...props }) {
const { const {
isOpen, isOpen,
selectedItem, selectedItem,
getToggleButtonProps, getToggleButtonProps,
getLabelProps, getLabelProps,
getMenuProps, getMenuProps,
getItemProps getItemProps,
} = useSelect({ } = useSelect({
items, items,
selectedItem: props.selectedItem, selectedItem: props.selectedItem,
onSelectedItemChange: item => { onSelectedItemChange: item => {
props.onSelectedItemChange(item.selectedItem) props.onSelectedItemChange(item.selectedItem)
} },
}) })
const selectClassNames = { const selectClassNames = {
@ -28,7 +27,7 @@ function Select({ className, label, items, ...props }) {
[styles.selectFiltered]: props.defaultAsFilter [styles.selectFiltered]: props.defaultAsFilter
? true ? true
: !R.equals(selectedItem, props.default), : !R.equals(selectedItem, props.default),
[styles.open]: isOpen [styles.open]: isOpen,
} }
return ( return (

View file

@ -97,4 +97,4 @@
.open button { .open button {
border-radius: 8px 8px 0 0; border-radius: 8px 8px 0 0;
} }

View file

@ -13,7 +13,6 @@ const TextInput = memo(
onBlur, onBlur,
value, value,
error, error,
suffix,
textAlign, textAlign,
width, width,
inputClasses, inputClasses,
@ -29,7 +28,7 @@ const TextInput = memo(
const style = { const style = {
width: width, width: width,
textAlign: textAlign textAlign: textAlign,
} }
const sizeClass = const sizeClass =
@ -40,7 +39,7 @@ const TextInput = memo(
: styles.size : styles.size
const divClass = { const divClass = {
[styles.bold]: bold [styles.bold]: bold,
} }
return ( return (
@ -60,15 +59,16 @@ const TextInput = memo(
classes: { classes: {
root: sizeClass, root: sizeClass,
underline: filled ? styles.underline : null, underline: filled ? styles.underline : null,
input: inputClasses input: inputClasses,
}, },
...InputProps ...InputProps,
}, },
htmlInput: { style: { textAlign } } htmlInput: { style: { textAlign } },
}} /> }}
); />
} )
},
) )
export default TextInput export default TextInput

View file

@ -21,4 +21,4 @@
.underline:hover:not(.Mui-disabled)::before { .underline:hover:not(.Mui-disabled)::before {
border-bottom-color: var(--spring); border-bottom-color: var(--spring);
} }

View file

@ -7,6 +7,7 @@ import RadioGroup from './RadioGroup'
import SecretInput from './SecretInput' import SecretInput from './SecretInput'
import TextInput from './TextInput' import TextInput from './TextInput'
import ToggleButtonGroup from './ToggleButtonGroup' import ToggleButtonGroup from './ToggleButtonGroup'
export { export {
Checkbox, Checkbox,
CodeInput, CodeInput,
@ -16,5 +17,5 @@ export {
RadioGroup, RadioGroup,
Autocomplete, Autocomplete,
ToggleButtonGroup, ToggleButtonGroup,
Dropdown Dropdown,
} }

View file

@ -11,12 +11,12 @@ import { primaryColor as zodiac, tomato } from '../../../styling/variables.js'
const colors = { const colors = {
cashOut: { cashOut: {
empty: tomato, empty: tomato,
full: zodiac full: zodiac,
}, },
cashIn: { cashIn: {
empty: zodiac, empty: zodiac,
full: tomato full: tomato,
} },
} }
const Cashbox = ({ const Cashbox = ({
@ -28,7 +28,7 @@ const Cashbox = ({
emptyPartClassName, emptyPartClassName,
labelClassName, labelClassName,
omitInnerPercentage, omitInnerPercentage,
isLow isLow,
}) => { }) => {
const ltHalf = percent <= 51 const ltHalf = percent <= 51
const color = const color =
@ -72,7 +72,7 @@ const CashIn = ({
width, width,
height, height,
total, total,
omitInnerPercentage omitInnerPercentage,
}) => { }) => {
const percent = (100 * notes) / capacity const percent = (100 * notes) / capacity
const isLow = percent < threshold const isLow = percent < threshold
@ -117,7 +117,7 @@ const CashOut = ({
threshold, threshold,
width, width,
height, height,
omitInnerPercentage omitInnerPercentage,
}) => { }) => {
const percent = (100 * notes) / capacity const percent = (100 * notes) / capacity
const isLow = percent < threshold const isLow = percent < threshold
@ -159,7 +159,7 @@ const CashOutLite = ({
currency, currency,
notes, notes,
threshold, threshold,
width width,
}) => { }) => {
const percent = (100 * notes) / capacity const percent = (100 * notes) / capacity
const isLow = percent < threshold const isLow = percent < threshold

View file

@ -49,4 +49,4 @@
border: 2px solid; border: 2px solid;
text-align: end; text-align: end;
display: inline-block; display: inline-block;
} }

View file

@ -33,7 +33,7 @@ const CashCassetteInput = memo(
/> />
</div> </div>
) )
} },
) )
export default CashCassetteInput export default CashCassetteInput

View file

@ -3,20 +3,13 @@ import React, { memo } from 'react'
import { Checkbox } from '../base' import { Checkbox } from '../base'
const CheckboxInput = memo( const CheckboxInput = memo(
({ ({ label, enabled = true, disabledMessage = '', ...props }) => {
label,
textAlign,
fullWidth,
enabled = true,
disabledMessage = '',
...props
}) => {
const { name, onChange, value } = props.field const { name, onChange, value } = props.field
const settings = { const settings = {
enabled: enabled, enabled: enabled,
label: label, label: label,
disabledMessage: disabledMessage disabledMessage: disabledMessage,
} }
return ( return (
@ -28,7 +21,7 @@ const CheckboxInput = memo(
{...props} {...props}
/> />
) )
} },
) )
export default CheckboxInput export default CheckboxInput

View file

@ -15,5 +15,5 @@ export {
SecretInput, SecretInput,
RadioGroup, RadioGroup,
CashCassetteInput, CashCassetteInput,
Dropdown Dropdown,
} }

View file

@ -14,5 +14,5 @@ export {
Select, Select,
RadioGroup, RadioGroup,
CashIn, CashIn,
CashOut CashOut,
} }

View file

@ -177,16 +177,16 @@ const Header = memo(({ tree, user }) => {
name: 'offset', name: 'offset',
enabled: true, enabled: true,
options: { options: {
offset: ['100vw', '100vw'] offset: ['100vw', '100vw'],
} },
}, },
{ {
name: 'preventOverflow', name: 'preventOverflow',
enabled: true, enabled: true,
options: { options: {
rootBoundary: 'viewport' rootBoundary: 'viewport',
} },
} },
]}> ]}>
<NotificationCenter <NotificationCenter
popperRef={popperRef} popperRef={popperRef}

View file

@ -49,7 +49,7 @@
} }
.li::after { .li::after {
content: ""; content: '';
display: block; display: block;
background: white; background: white;
width: 0; width: 0;

View file

@ -14,7 +14,7 @@ const Sidebar = ({
onClick, onClick,
children, children,
itemRender, itemRender,
loading = false loading = false,
}) => { }) => {
return ( return (
<div className={styles.sidebar}> <div className={styles.sidebar}>
@ -30,7 +30,7 @@ const Sidebar = ({
[styles.activeLink]: isSelected(it), [styles.activeLink]: isSelected(it),
[styles.customRenderActiveLink]: itemRender && isSelected(it), [styles.customRenderActiveLink]: itemRender && isSelected(it),
[styles.customRenderLink]: itemRender, [styles.customRenderLink]: itemRender,
[styles.link]: true [styles.link]: true,
})}> })}>
{itemRender ? itemRender(it, isSelected(it)) : displayName(it)} {itemRender ? itemRender(it, isSelected(it)) : displayName(it)}
</div> </div>
@ -54,7 +54,7 @@ const Stepper = ({ step, it, idx, steps }) => {
className={classnames({ className={classnames({
[styles.itemText]: true, [styles.itemText]: true,
[styles.itemTextActive]: active, [styles.itemTextActive]: active,
[styles.itemTextPast]: past [styles.itemTextPast]: past,
})}> })}>
{it.label} {it.label}
</span> </span>
@ -65,7 +65,7 @@ const Stepper = ({ step, it, idx, steps }) => {
<div <div
className={classnames({ className={classnames({
[styles.stepperPath]: true, [styles.stepperPath]: true,
[styles.stepperPast]: past [styles.stepperPast]: past,
})}></div> })}></div>
)} )}
</div> </div>

View file

@ -39,7 +39,7 @@
} }
.link::after { .link::after {
content: ""; content: '';
display: block; display: block;
background: var(--zodiac); background: var(--zodiac);
width: 4px; width: 4px;
@ -103,4 +103,4 @@
.stepperPast { .stepperPast {
border: 1px solid var(--zodiac); border: 1px solid var(--zodiac);
} }

View file

@ -15,13 +15,13 @@ const TitleSection = ({
buttons = [], buttons = [],
children, children,
appendix, appendix,
appendixRight appendixRight,
}) => { }) => {
return ( return (
<div <div
className={classnames( className={classnames(
'flex justify-between items-center flex-row', 'flex justify-between items-center flex-row',
className className,
)}> )}>
<div className="flex items-center"> <div className="flex items-center">
<Title>{title}</Title> <Title>{title}</Title>
@ -44,7 +44,7 @@ const TitleSection = ({
{button.text} {button.text}
</Info1> </Info1>
</SubpageButton> </SubpageButton>
) ),
)} )}
</> </>
)} )}

View file

@ -12,7 +12,7 @@ const STATES = {
EMPTY: 'EMPTY', EMPTY: 'EMPTY',
RUNNING: 'RUNNING', RUNNING: 'RUNNING',
FAILURE: 'FAILURE', FAILURE: 'FAILURE',
FILLED: 'FILLED' FILLED: 'FILLED',
} }
const MACHINE = gql` const MACHINE = gql`
@ -47,7 +47,7 @@ const MACHINE_LOGS = gql`
const createCsv = async ({ machineLogsCsv }) => { const createCsv = async ({ machineLogsCsv }) => {
const machineLogs = new Blob([machineLogsCsv], { const machineLogs = new Blob([machineLogsCsv], {
type: 'text/plain;charset=utf-8' type: 'text/plain;charset=utf-8',
}) })
FileSaver.saveAs(machineLogs, 'machineLogs.csv') FileSaver.saveAs(machineLogs, 'machineLogs.csv')
@ -59,11 +59,11 @@ const DiagnosticsModal = ({ onClose, deviceId, sendAction }) => {
let timeout = null let timeout = null
const [fetchSummary, { loading }] = useLazyQuery(MACHINE_LOGS, { const [fetchSummary, { loading }] = useLazyQuery(MACHINE_LOGS, {
onCompleted: data => createCsv(data) onCompleted: data => createCsv(data),
}) })
const { data, stopPolling, startPolling } = useQuery(MACHINE, { const { data, stopPolling, startPolling } = useQuery(MACHINE, {
variables: { deviceId } variables: { deviceId },
}) })
useEffect(() => { useEffect(() => {
@ -168,8 +168,8 @@ const DiagnosticsModal = ({ onClose, deviceId, sendAction }) => {
variables: { variables: {
from: subMinutes(new Date(timestamp), 5), from: subMinutes(new Date(timestamp), 5),
deviceId, deviceId,
limit: 500 limit: 500,
} },
}) })
}} }}
className="mt-auto ml-auto mr-2 mb-0"> className="mt-auto ml-auto mr-2 mb-0">

View file

@ -49,7 +49,7 @@ const isStaticState = machineState => {
'unpaired', 'unpaired',
'maintenance', 'maintenance',
'virgin', 'virgin',
'wifiList' 'wifiList',
] ]
return staticStates.includes(machineState) return staticStates.includes(machineState)
} }
@ -73,7 +73,7 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
const [fetchMachineEvents, { loading: loadingEvents }] = useLazyQuery( const [fetchMachineEvents, { loading: loadingEvents }] = useLazyQuery(
MACHINE, MACHINE,
preflightOptions preflightOptions,
) )
const [simpleMachineAction] = useMutation(MACHINE_ACTION) const [simpleMachineAction] = useMutation(MACHINE_ACTION)
@ -86,7 +86,7 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
onCompleted: () => { onCompleted: () => {
onActionSuccess && onActionSuccess() onActionSuccess && onActionSuccess()
setAction({ display: action.display, command: null }) setAction({ display: action.display, command: null })
} },
}) })
const confirmDialogOpen = Boolean(action.command) const confirmDialogOpen = Boolean(action.command)
@ -100,7 +100,7 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
? warningMessage ? warningMessage
: null : null
setAction({ ...actionToDo, message }) setAction({ ...actionToDo, message })
} },
}) })
fetchMachineEvents() fetchMachineEvents()
} }
@ -118,7 +118,7 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
setAction({ setAction({
command: 'rename', command: 'rename',
display: 'Rename', display: 'Rename',
confirmationMessage: 'Write the new name for this machine' confirmationMessage: 'Write the new name for this machine',
}) })
}> }>
Rename Rename
@ -131,7 +131,7 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
onClick={() => onClick={() =>
setAction({ setAction({
command: 'unpair', command: 'unpair',
display: 'Unpair' display: 'Unpair',
}) })
}> }>
Unpair Unpair
@ -144,7 +144,7 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
onClick={() => onClick={() =>
setAction({ setAction({
command: 'reboot', command: 'reboot',
display: 'Reboot' display: 'Reboot',
}) })
}> }>
Reboot Reboot
@ -159,7 +159,7 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
command: 'shutdown', command: 'shutdown',
display: 'Shutdown', display: 'Shutdown',
message: message:
'In order to bring it back online, the machine will need to be visited and its power reset.' 'In order to bring it back online, the machine will need to be visited and its power reset.',
}) })
}> }>
Shutdown Shutdown
@ -172,7 +172,7 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
onClick={() => { onClick={() => {
machineStatusPreflight({ machineStatusPreflight({
command: 'restartServices', command: 'restartServices',
display: 'Restart services for' display: 'Restart services for',
}) })
}}> }}>
Restart services Restart services
@ -188,7 +188,7 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
command: 'emptyUnit', command: 'emptyUnit',
display: 'Empty', display: 'Empty',
message: message:
"Triggering this action will move all cash inside the machine towards its cashbox (if possible), allowing for the collection of cash from the machine via only its cashbox. Depending on how full the cash units are, it's possible that this action will need to be used more than once to ensure that the unit is left completely empty." "Triggering this action will move all cash inside the machine towards its cashbox (if possible), allowing for the collection of cash from the machine via only its cashbox. Depending on how full the cash units are, it's possible that this action will need to be used more than once to ensure that the unit is left completely empty.",
}) })
}}> }}>
Empty Unit Empty Unit
@ -205,7 +205,7 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
command: 'refillUnit', command: 'refillUnit',
display: 'Refill', display: 'Refill',
message: message:
'Triggering this action will refill the recyclers in this machine, by using bills present in its cassettes. This action may require manual operation of the cassettes and close attention to make sure that the denominations in the cassettes match the denominations in the recyclers.' 'Triggering this action will refill the recyclers in this machine, by using bills present in its cassettes. This action may require manual operation of the cassettes and close attention to make sure that the denominations in the cassettes match the denominations in the recyclers.',
}) })
}}> }}>
Refill Unit Refill Unit
@ -228,8 +228,8 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
simpleMachineAction({ simpleMachineAction({
variables: { variables: {
deviceId: machine.deviceId, deviceId: machine.deviceId,
action: 'diagnostics' action: 'diagnostics',
} },
}) })
} }
deviceId={machine.deviceId} deviceId={machine.deviceId}
@ -253,8 +253,8 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
variables: { variables: {
deviceId: machine.deviceId, deviceId: machine.deviceId,
action: `${action?.command}`, action: `${action?.command}`,
...(action?.command === 'rename' && { newName: value }) ...(action?.command === 'rename' && { newName: value }),
} },
}) })
}} }}
onDismissed={() => { onDismissed={() => {

View file

@ -7,7 +7,7 @@ import {
TBody, TBody,
Td, Td,
Th, Th,
Tr Tr,
} from 'src/components/fake-table/Table' } from 'src/components/fake-table/Table'
import EditIcon from 'src/styling/icons/action/edit/white.svg?react' import EditIcon from 'src/styling/icons/action/edit/white.svg?react'
@ -19,7 +19,7 @@ const SingleRowTable = ({
title, title,
items, items,
onEdit, onEdit,
className className,
}) => { }) => {
return ( return (
<> <>

View file

@ -8,7 +8,7 @@ const EmptyTable = memo(({ message, className }) => {
<div <div
className={classNames( className={classNames(
className, className,
'flex flex-col items-center w-full mt-13 text-sm font-bold font-museo' 'flex flex-col items-center w-full mt-13 text-sm font-bold font-museo',
)}> )}>
<EmptyTableIcon /> <EmptyTableIcon />
<H4>{message}</H4> <H4>{message}</H4>

View file

@ -7,7 +7,7 @@ const Table = memo(({ className, children, ...props }) => {
{...props} {...props}
className={classnames( className={classnames(
'table-fixed border-separate border-spacing-0', 'table-fixed border-separate border-spacing-0',
className className,
)}> )}>
{children} {children}
</table> </table>

View file

@ -7,7 +7,7 @@ const TableCell = memo(
({ colspan, rightAlign, className, children, ...props }) => { ({ colspan, rightAlign, className, children, ...props }) => {
const styles = { const styles = {
[classes.tableCell]: true, [classes.tableCell]: true,
'text-right': rightAlign 'text-right': rightAlign,
} }
return ( return (
@ -18,7 +18,7 @@ const TableCell = memo(
{children} {children}
</td> </td>
) )
} },
) )
export default TableCell export default TableCell

View file

@ -5,7 +5,7 @@ const TableHeaderCell = memo(
({ rightAlign, children, className, ...props }) => { ({ rightAlign, children, className, ...props }) => {
const styles = { const styles = {
'bg-zodiac text-white py-0 px-6 h-8 text-sm text-left': true, 'bg-zodiac text-white py-0 px-6 h-8 text-sm text-left': true,
'text-right': rightAlign 'text-right': rightAlign,
} }
return ( return (
@ -13,7 +13,7 @@ const TableHeaderCell = memo(
{children} {children}
</th> </th>
) )
} },
) )
export default TableHeaderCell export default TableHeaderCell

View file

@ -8,7 +8,7 @@ const TableRow = memo(
'h-8': !header && size === 'sm', 'h-8': !header && size === 'sm',
'h-9 font-bold text-base ': !header && size === 'lg', 'h-9 font-bold text-base ': !header && size === 'lg',
'bg-misty-rose': error, 'bg-misty-rose': error,
'bg-spring3': success 'bg-spring3': success,
} }
return ( return (
@ -16,7 +16,7 @@ const TableRow = memo(
{children} {children}
</tr> </tr>
) )
} },
) )
export default TableRow export default TableRow

View file

@ -15,5 +15,5 @@ export {
TableHead, TableHead,
TableHeader, TableHeader,
TableRow, TableRow,
TableBody TableBody,
} }

View file

@ -5,7 +5,7 @@ import {
AutoSizer, AutoSizer,
List, List,
CellMeasurer, CellMeasurer,
CellMeasurerCache CellMeasurerCache,
} from 'react-virtualized' } from 'react-virtualized'
import { import {
Table, Table,
@ -13,7 +13,7 @@ import {
THead, THead,
Tr, Tr,
Td, Td,
Th Th,
} from 'src/components/fake-table/Table' } from 'src/components/fake-table/Table'
import { H4 } from 'src/components/typography' import { H4 } from 'src/components/typography'
import ExpandClosedIcon from 'src/styling/icons/action/expand/closed.svg?react' import ExpandClosedIcon from 'src/styling/icons/action/expand/closed.svg?react'
@ -40,7 +40,7 @@ const Row = ({
const trClasses = { const trClasses = {
'cursor-pointer': hasPointer, 'cursor-pointer': hasPointer,
'border-2 border-transparent': true, 'border-2 border-transparent': true,
'border-2 border-zircon shadow-md': expanded 'border-2 border-zircon shadow-md': expanded,
} }
return ( return (
@ -79,7 +79,7 @@ const Row = ({
<div className="pb-3"> <div className="pb-3">
<Tr <Tr
className={classnames({ className={classnames({
'border-2 border-zircon shadow-md': expanded 'border-2 border-zircon shadow-md': expanded,
})}> })}>
<Td width={width}> <Td width={width}>
<Details it={data} timezone={props.timezone} /> <Details it={data} timezone={props.timezone} />
@ -126,7 +126,7 @@ const DataTable = ({
const cache = new CellMeasurerCache({ const cache = new CellMeasurerCache({
defaultHeight: 58, defaultHeight: 58,
fixedWidth: true fixedWidth: true,
}) })
function rowRenderer({ index, key, parent, style }) { function rowRenderer({ index, key, parent, style }) {
@ -168,12 +168,12 @@ const DataTable = ({
<div <div
className={classnames({ className={classnames({
'flex flex-1 flex-col': true, 'flex flex-1 flex-col': true,
[className]: !!className [className]: !!className,
})}> })}>
<Table <Table
className={classnames( className={classnames(
'mb-12 min-h-50 flex-1 flex flex-col', 'mb-12 min-h-50 flex-1 flex flex-col',
tableClassName tableClassName,
)} )}
style={{ width }}> style={{ width }}>
<THead> <THead>

View file

@ -7,7 +7,7 @@ function H1({ children, noMargin, className, ...props }) {
const classNames = { const classNames = {
[styles.h1]: true, [styles.h1]: true,
[styles.noMargin]: noMargin, [styles.noMargin]: noMargin,
[className]: !!className [className]: !!className,
} }
return ( return (
@ -21,7 +21,7 @@ function H2({ children, noMargin, className, ...props }) {
const classNames = { const classNames = {
[styles.h2]: true, [styles.h2]: true,
[styles.noMargin]: noMargin, [styles.noMargin]: noMargin,
[className]: !!className [className]: !!className,
} }
return ( return (
@ -35,7 +35,7 @@ function H3({ children, noMargin, className, ...props }) {
const classNames = { const classNames = {
[styles.h3]: true, [styles.h3]: true,
[styles.noMargin]: noMargin, [styles.noMargin]: noMargin,
[className]: !!className [className]: !!className,
} }
return ( return (
@ -49,7 +49,7 @@ function H4({ children, noMargin, className, ...props }) {
const classNames = { const classNames = {
[styles.h4]: true, [styles.h4]: true,
[styles.noMargin]: noMargin, [styles.noMargin]: noMargin,
[className]: !!className [className]: !!className,
} }
return ( return (
@ -63,7 +63,7 @@ function H5({ children, noMargin, className, ...props }) {
const classNames = { const classNames = {
[styles.h5]: true, [styles.h5]: true,
[styles.noMargin]: noMargin, [styles.noMargin]: noMargin,
[className]: !!className [className]: !!className,
} }
return ( return (
@ -90,7 +90,7 @@ function pBuilder(elementClass) {
[className]: !!className, [className]: !!className,
[styles[elementClass]]: elementClass, [styles[elementClass]]: elementClass,
[styles.inline]: inline, [styles.inline]: inline,
[styles.noMargin]: noMargin [styles.noMargin]: noMargin,
} }
return ( return (
<p className={classnames(classNames)} {...props}> <p className={classnames(classNames)} {...props}>
@ -115,5 +115,5 @@ export {
Mono, Mono,
Label1, Label1,
Label2, Label2,
Label3 Label3,
} }

View file

@ -7,132 +7,132 @@ import {
fontSize5, fontSize5,
fontPrimary, fontPrimary,
fontSecondary, fontSecondary,
fontMonospaced fontMonospaced,
} from 'src/styling/variables' } from 'src/styling/variables'
const base = { const base = {
lineHeight: '120%', lineHeight: '120%',
color: fontColor color: fontColor,
} }
export default { export default {
base: { base: {
lineHeight: '120%', lineHeight: '120%',
color: fontColor color: fontColor,
}, },
h1: { h1: {
extend: base, extend: base,
fontSize: fontSize1, fontSize: fontSize1,
fontFamily: fontPrimary, fontFamily: fontPrimary,
fontWeight: 900 fontWeight: 900,
}, },
h2: { h2: {
extend: base, extend: base,
fontSize: fontSize2, fontSize: fontSize2,
fontFamily: fontPrimary, fontFamily: fontPrimary,
fontWeight: 900 fontWeight: 900,
}, },
h3: { h3: {
extend: base, extend: base,
fontSize: fontSize4, fontSize: fontSize4,
fontFamily: fontPrimary, fontFamily: fontPrimary,
fontWeight: 900 fontWeight: 900,
}, },
h4: { h4: {
extend: base, extend: base,
fontSize: fontSize4, fontSize: fontSize4,
fontFamily: fontPrimary, fontFamily: fontPrimary,
fontWeight: 700 fontWeight: 700,
}, },
h5: { h5: {
extend: base, extend: base,
fontSize: fontSize3, fontSize: fontSize3,
fontFamily: fontPrimary, fontFamily: fontPrimary,
fontWeight: 700 fontWeight: 700,
}, },
p: { p: {
...base, ...base,
fontSize: fontSize4, fontSize: fontSize4,
fontFamily: fontSecondary, fontFamily: fontSecondary,
fontWeight: 500 fontWeight: 500,
}, },
tl1: { tl1: {
extend: base, extend: base,
fontSize: fontSize2, fontSize: fontSize2,
fontFamily: fontSecondary, fontFamily: fontSecondary,
fontWeight: 700 fontWeight: 700,
}, },
tl2: { tl2: {
extend: base, extend: base,
fontSize: fontSize4, fontSize: fontSize4,
fontFamily: fontSecondary, fontFamily: fontSecondary,
fontWeight: 700 fontWeight: 700,
}, },
info1: { info1: {
extend: base, extend: base,
fontSize: fontSize1, fontSize: fontSize1,
fontFamily: fontSecondary, fontFamily: fontSecondary,
fontWeight: 700 fontWeight: 700,
}, },
info2: { info2: {
extend: base, extend: base,
fontSize: fontSize3, fontSize: fontSize3,
fontFamily: fontSecondary, fontFamily: fontSecondary,
fontWeight: 700 fontWeight: 700,
}, },
info3: { info3: {
extend: base, extend: base,
fontSize: fontSize3, fontSize: fontSize3,
fontFamily: fontSecondary, fontFamily: fontSecondary,
fontWeight: 500 fontWeight: 500,
}, },
mono: { mono: {
extend: base, extend: base,
fontSize: fontSize4, fontSize: fontSize4,
fontFamily: fontMonospaced, fontFamily: fontMonospaced,
fontWeight: 500 fontWeight: 500,
}, },
monoBold: { monoBold: {
fontWeight: 700 fontWeight: 700,
}, },
monoSmall: { monoSmall: {
fontSize: fontSize5 fontSize: fontSize5,
}, },
inputFont: { inputFont: {
fontSize: fontSize2, fontSize: fontSize2,
fontFamily: fontSecondary, fontFamily: fontSecondary,
fontWeight: 500, fontWeight: 500,
lineHeight: '110%', lineHeight: '110%',
color: fontColor color: fontColor,
}, },
regularLabel: { regularLabel: {
fontSize: fontSize4, fontSize: fontSize4,
fontFamily: fontSecondary, fontFamily: fontSecondary,
fontWeight: 500, fontWeight: 500,
lineHeight: '110%' lineHeight: '110%',
}, },
label1: { label1: {
fontSize: fontSize5, fontSize: fontSize5,
fontFamily: fontSecondary, fontFamily: fontSecondary,
fontWeight: 500, fontWeight: 500,
color: fontColor color: fontColor,
}, },
label2: { label2: {
fontSize: fontSize5, fontSize: fontSize5,
fontFamily: fontSecondary, fontFamily: fontSecondary,
fontWeight: 700, fontWeight: 700,
color: fontColor color: fontColor,
}, },
label3: { label3: {
fontSize: fontSize4, fontSize: fontSize4,
fontFamily: fontSecondary, fontFamily: fontSecondary,
fontWeight: 500, fontWeight: 500,
color: fontColor color: fontColor,
}, },
inline: { inline: {
display: 'inline' display: 'inline',
}, },
noMargin: { noMargin: {
margin: 0 margin: 0,
} },
} }

View file

@ -7,5 +7,5 @@ ReactDOM.render(
<React.StrictMode> <React.StrictMode>
<App /> <App />
</React.StrictMode>, </React.StrictMode>,
document.getElementById('root') document.getElementById('root'),
) )

View file

@ -58,7 +58,7 @@ const QrCodeComponent = ({ qrCode, name, count, onPaired }) => {
if (hasNewMachine) { if (hasNewMachine) {
timeout.current = setTimeout( timeout.current = setTimeout(
() => onPaired(addedMachine), () => onPaired(addedMachine),
CLOSE_SCREEN_TIMEOUT CLOSE_SCREEN_TIMEOUT,
) )
} }
@ -111,7 +111,7 @@ const QrCodeComponent = ({ qrCode, name, count, onPaired }) => {
} }
const initialValues = { const initialValues = {
name: '' name: '',
} }
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
@ -124,9 +124,9 @@ const validationSchema = Yup.object().shape({
(value, context) => (value, context) =>
!R.includes( !R.includes(
R.toLower(value), R.toLower(value),
R.map(R.toLower, context.options.context.machineNames) R.map(R.toLower, context.options.context.machineNames),
) ),
) ),
}) })
const MachineNameComponent = ({ nextStep, setQrCode, setName }) => { const MachineNameComponent = ({ nextStep, setQrCode, setName }) => {
@ -138,7 +138,7 @@ const MachineNameComponent = ({ nextStep, setQrCode, setName }) => {
setQrCode(createPairingTotem) setQrCode(createPairingTotem)
nextStep() nextStep()
}, },
onError: e => console.log(e) onError: e => console.log(e),
}) })
const { data } = useQuery(GET_MACHINES) const { data } = useQuery(GET_MACHINES)
@ -147,7 +147,7 @@ const MachineNameComponent = ({ nextStep, setQrCode, setName }) => {
const uniqueNameValidator = value => { const uniqueNameValidator = value => {
try { try {
validationSchema.validateSync(value, { validationSchema.validateSync(value, {
context: { machineNames: machineNames } context: { machineNames: machineNames },
}) })
} catch (error) { } catch (error) {
return error return error
@ -189,12 +189,12 @@ const MachineNameComponent = ({ nextStep, setQrCode, setName }) => {
const steps = [ const steps = [
{ {
label: 'Machine name', label: 'Machine name',
component: MachineNameComponent component: MachineNameComponent,
}, },
{ {
label: 'Scan QR code', label: 'Scan QR code',
component: QrCodeComponent component: QrCodeComponent,
} },
] ]
const renderStepper = (step, it, idx) => { const renderStepper = (step, it, idx) => {
@ -208,7 +208,7 @@ const renderStepper = (step, it, idx) => {
className={classnames({ className={classnames({
'mr-6 text-comet': true, 'mr-6 text-comet': true,
'text-zodiac font-bold': active, 'text-zodiac font-bold': active,
'text-zodiac': past 'text-zodiac': past,
})}> })}>
{it.label} {it.label}
</span> </span>
@ -219,7 +219,7 @@ const renderStepper = (step, it, idx) => {
<div <div
className={classnames({ className={classnames({
'absolute h-7 w-px border border-comet border-solid right-2 top-[18px]': true, 'absolute h-7 w-px border border-comet border-solid right-2 top-[18px]': true,
'border-zodiac': past 'border-zodiac': past,
})}></div> })}></div>
)} )}
</div> </div>

View file

@ -26,29 +26,29 @@ const REPRESENTING_OPTIONS = [
{ code: 'overTime', display: 'Over time' }, { code: 'overTime', display: 'Over time' },
{ code: 'volumeOverTime', display: 'Volume' }, { code: 'volumeOverTime', display: 'Volume' },
{ code: 'topMachines', display: 'Top machines' }, { code: 'topMachines', display: 'Top machines' },
{ code: 'hourOfTheDay', display: 'Hour of the day' } { code: 'hourOfTheDay', display: 'Hour of the day' },
] ]
const PERIOD_OPTIONS = [ const PERIOD_OPTIONS = [
{ code: 'day', display: 'Last 24 hours' }, { code: 'day', display: 'Last 24 hours' },
{ code: 'threeDays', display: 'Last 3 days' }, { code: 'threeDays', display: 'Last 3 days' },
{ code: 'week', display: 'Last 7 days' }, { code: 'week', display: 'Last 7 days' },
{ code: 'month', display: 'Last 30 days' } { code: 'month', display: 'Last 30 days' },
] ]
const TIME_OPTIONS = { const TIME_OPTIONS = {
day: DAY, day: DAY,
threeDays: 3 * DAY, threeDays: 3 * DAY,
week: WEEK, week: WEEK,
month: MONTH month: MONTH,
} }
const DAY_OPTIONS = R.map( const DAY_OPTIONS = R.map(
it => ({ it => ({
code: R.toLower(it), code: R.toLower(it),
display: it display: it,
}), }),
Array.from(Array(7)).map((_, i) => Array.from(Array(7)).map((_, i) =>
format('EEEE', add({ days: i }, startOfWeek(new Date()))) format('EEEE', add({ days: i }, startOfWeek(new Date()))),
) ),
) )
const GET_TRANSACTIONS = gql` const GET_TRANSACTIONS = gql`
@ -112,7 +112,7 @@ const OverviewEntry = ({ label, value, oldValue, currency }) => {
const growthClasses = { const growthClasses = {
'font-bold': true, 'font-bold': true,
'text-malachite': R.gt(value, oldValue), 'text-malachite': R.gt(value, oldValue),
'text-tomato': R.gt(oldValue, value) 'text-tomato': R.gt(oldValue, value),
} }
return ( return (
@ -139,8 +139,8 @@ const Analytics = () => {
variables: { variables: {
from: subDays(65, endOfToday()), from: subDays(65, endOfToday()),
until: endOfToday(), until: endOfToday(),
excludeTestingCustomers: true excludeTestingCustomers: true,
} },
}) })
const { data: configResponse, loading: configLoading } = useQuery(GET_DATA) const { data: configResponse, loading: configLoading } = useQuery(GET_DATA)
@ -148,7 +148,7 @@ const Analytics = () => {
const [period, setPeriod] = useState(PERIOD_OPTIONS[0]) const [period, setPeriod] = useState(PERIOD_OPTIONS[0])
const [machine, setMachine] = useState(MACHINE_OPTIONS[0]) const [machine, setMachine] = useState(MACHINE_OPTIONS[0])
const [selectedDay, setSelectedDay] = useState( const [selectedDay, setSelectedDay] = useState(
R.equals(representing.code, 'hourOfTheDay') ? DAY_OPTIONS[0] : null R.equals(representing.code, 'hourOfTheDay') ? DAY_OPTIONS[0] : null,
) )
const loading = txLoading || configLoading const loading = txLoading || configLoading
@ -175,20 +175,20 @@ const Analytics = () => {
tx => tx =>
(!tx.dispensed || !tx.expired) && (!tx.dispensed || !tx.expired) &&
(tx.sendConfirmed || tx.dispense) && (tx.sendConfirmed || tx.dispense) &&
!tx.hasError !tx.hasError,
) ),
) ?? [] ) ?? []
const machineOptions = R.clone(MACHINE_OPTIONS) const machineOptions = R.clone(MACHINE_OPTIONS)
R.forEach( R.forEach(
m => machineOptions.push({ code: m.deviceId, display: m.name }), m => machineOptions.push({ code: m.deviceId, display: m.name }),
machines machines,
) )
const machineTxs = R.filter( const machineTxs = R.filter(
tx => (machine.code === 'all' ? true : tx.deviceId === machine.code), tx => (machine.code === 'all' ? true : tx.deviceId === machine.code),
data data,
) )
const filteredData = timeInterval => ({ const filteredData = timeInterval => ({
@ -213,35 +213,35 @@ const Analytics = () => {
txDay < Date.now() - TIME_OPTIONS[timeInterval] && txDay < Date.now() - TIME_OPTIONS[timeInterval] &&
txDay >= Date.now() - 2 * TIME_OPTIONS[timeInterval] txDay >= Date.now() - 2 * TIME_OPTIONS[timeInterval]
) )
}) ?? [] }) ?? [],
}) })
const txs = { const txs = {
current: filteredData(period.code).current.length, current: filteredData(period.code).current.length,
previous: filteredData(period.code).previous.length previous: filteredData(period.code).previous.length,
} }
const median = values => (values.length === 0 ? 0 : R.median(values)) const median = values => (values.length === 0 ? 0 : R.median(values))
const medianAmount = { const medianAmount = {
current: median(R.map(d => d.fiat, filteredData(period.code).current)), current: median(R.map(d => d.fiat, filteredData(period.code).current)),
previous: median(R.map(d => d.fiat, filteredData(period.code).previous)) previous: median(R.map(d => d.fiat, filteredData(period.code).previous)),
} }
const txVolume = { const txVolume = {
current: R.sum(R.map(d => d.fiat, filteredData(period.code).current)), current: R.sum(R.map(d => d.fiat, filteredData(period.code).current)),
previous: R.sum(R.map(d => d.fiat, filteredData(period.code).previous)) previous: R.sum(R.map(d => d.fiat, filteredData(period.code).previous)),
} }
const commissions = { const commissions = {
current: R.sum(R.map(d => d.profit, filteredData(period.code).current)), current: R.sum(R.map(d => d.profit, filteredData(period.code).current)),
previous: R.sum(R.map(d => d.profit, filteredData(period.code).previous)) previous: R.sum(R.map(d => d.profit, filteredData(period.code).previous)),
} }
const handleRepresentationChange = newRepresentation => { const handleRepresentationChange = newRepresentation => {
setRepresenting(newRepresentation) setRepresenting(newRepresentation)
setSelectedDay( setSelectedDay(
R.equals(newRepresentation.code, 'hourOfTheDay') ? DAY_OPTIONS[0] : null R.equals(newRepresentation.code, 'hourOfTheDay') ? DAY_OPTIONS[0] : null,
) )
} }

View file

@ -13,20 +13,19 @@ const GraphTooltip = ({
coords, coords,
data, data,
dateInterval, dateInterval,
period,
currency, currency,
representing representing,
}) => { }) => {
const formattedDateInterval = !R.includes('hourOfDay', representing.code) const formattedDateInterval = !R.includes('hourOfDay', representing.code)
? [ ? [
formatDate(dateInterval[1], null, 'MMM d'), formatDate(dateInterval[1], null, 'MMM d'),
formatDate(dateInterval[1], null, 'HH:mm'), formatDate(dateInterval[1], null, 'HH:mm'),
formatDate(dateInterval[0], null, 'HH:mm') formatDate(dateInterval[0], null, 'HH:mm'),
] ]
: [ : [
formatDate(dateInterval[1], null, 'MMM d'), formatDate(dateInterval[1], null, 'MMM d'),
formatDateNonUtc(dateInterval[1], 'HH:mm'), formatDateNonUtc(dateInterval[1], 'HH:mm'),
formatDateNonUtc(dateInterval[0], 'HH:mm') formatDateNonUtc(dateInterval[0], 'HH:mm'),
] ]
const transactions = R.reduce( const transactions = R.reduce(
@ -37,7 +36,7 @@ const GraphTooltip = ({
return acc return acc
}, },
{ volume: 0, cashIn: 0, cashOut: 0 }, { volume: 0, cashIn: 0, cashOut: 0 },
data data,
) )
return ( return (

View file

@ -12,7 +12,7 @@ import classes from './wrappers.module.css'
const options = [ const options = [
{ code: 'hourOfDayTransactions', display: 'Transactions' }, { code: 'hourOfDayTransactions', display: 'Transactions' },
{ code: 'hourOfDayVolume', display: 'Volume' } { code: 'hourOfDayVolume', display: 'Volume' },
] ]
const HourOfDayBarGraphHeader = ({ const HourOfDayBarGraphHeader = ({
@ -26,13 +26,13 @@ const HourOfDayBarGraphHeader = ({
dayOptions, dayOptions,
handleDayChange, handleDayChange,
timezone, timezone,
currency currency,
}) => { }) => {
const [graphType /*, setGraphType */] = useState(options[0].code) const [graphType /*, setGraphType */] = useState(options[0].code)
const legend = { const legend = {
cashIn: <div className={classes.cashInIcon}></div>, cashIn: <div className={classes.cashInIcon}></div>,
cashOut: <div className={classes.cashOutIcon}></div> cashOut: <div className={classes.cashOutIcon}></div>,
} }
const offset = getTimezoneOffset(timezone) const offset = getTimezoneOffset(timezone)
@ -41,7 +41,7 @@ const HourOfDayBarGraphHeader = ({
(acc, value) => { (acc, value) => {
const created = new Date(value.created) const created = new Date(value.created)
created.setTime( created.setTime(
created.getTime() + created.getTimezoneOffset() * MINUTE + offset created.getTime() + created.getTimezoneOffset() * MINUTE + offset,
) )
switch (created.getDay()) { switch (created.getDay()) {
case 0: case 0:
@ -71,7 +71,7 @@ const HourOfDayBarGraphHeader = ({
return acc return acc
}, },
R.fromPairs(R.map(it => [it.code, []], dayOptions)), R.fromPairs(R.map(it => [it.code, []], dayOptions)),
data data,
) )
return ( return (

View file

@ -18,7 +18,7 @@ const OverTimeDotGraphHeader = ({
selectedMachine, selectedMachine,
handleMachineChange, handleMachineChange,
timezone, timezone,
currency currency,
}) => { }) => {
const [logarithmic, setLogarithmic] = useState() const [logarithmic, setLogarithmic] = useState()
@ -35,7 +35,7 @@ const OverTimeDotGraphHeader = ({
d="M 5 6 l 20 0" d="M 5 6 l 20 0"
/> />
</svg> </svg>
) ),
} }
return ( return (

View file

@ -8,7 +8,7 @@ import classes from './wrappers.module.css'
const options = [ const options = [
{ code: 'topMachinesTransactions', display: 'Transactions' }, { code: 'topMachinesTransactions', display: 'Transactions' },
{ code: 'topMachinesVolume', display: 'Volume' } { code: 'topMachinesVolume', display: 'Volume' },
] ]
const TopMachinesBarGraphHeader = ({ const TopMachinesBarGraphHeader = ({
@ -18,13 +18,13 @@ const TopMachinesBarGraphHeader = ({
machines, machines,
selectedMachine, selectedMachine,
timezone, timezone,
currency currency,
}) => { }) => {
const [graphType /*, setGraphType */] = useState(options[0].code) const [graphType /*, setGraphType */] = useState(options[0].code)
const legend = { const legend = {
cashIn: <div className={classes.cashInIcon}></div>, cashIn: <div className={classes.cashInIcon}></div>,
cashOut: <div className={classes.cashOutIcon}></div> cashOut: <div className={classes.cashOutIcon}></div>,
} }
return ( return (

View file

@ -18,7 +18,7 @@ const VolumeOverTimeGraphHeader = ({
selectedMachine, selectedMachine,
handleMachineChange, handleMachineChange,
timezone, timezone,
currency currency,
}) => { }) => {
const [logarithmic, setLogarithmic] = useState() const [logarithmic, setLogarithmic] = useState()
@ -42,7 +42,7 @@ const VolumeOverTimeGraphHeader = ({
strokeLinecap="round" strokeLinecap="round"
/> />
</svg> </svg>
) ),
} }
return ( return (

View file

@ -12,7 +12,7 @@
.graphHeaderRight { .graphHeaderRight {
margin-top: 15px; margin-top: 15px;
display: flex; display: flex;
gap: 30px gap: 30px;
} }
.cashInIcon { .cashInIcon {
@ -45,12 +45,12 @@
.graphHeaderSwitchBox { .graphHeaderSwitchBox {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
/*'& > *': {*/ /*'& > *': {*/
/* margin: 0*/ /* margin: 0*/
/*},*/ /*},*/
/*'& > :first-child': {*/ /*'& > :first-child': {*/
/* marginBottom: 2,*/ /* marginBottom: 2,*/
/* extend: label1,*/ /* extend: label1,*/
/* color: offColor*/ /* color: offColor*/
/*}*/ /*}*/
} }

View file

@ -17,7 +17,7 @@ const GraphWrapper = ({
selectedMachine, selectedMachine,
machines, machines,
selectedDay, selectedDay,
log log,
}) => { }) => {
const [selectionCoords, setSelectionCoords] = useState(null) const [selectionCoords, setSelectionCoords] = useState(null)
const [selectionDateInterval, setSelectionDateInterval] = useState(null) const [selectionDateInterval, setSelectionDateInterval] = useState(null)

View file

@ -11,7 +11,7 @@ import {
subheaderDarkColor, subheaderDarkColor,
fontColor, fontColor,
fontSecondary, fontSecondary,
subheaderColor subheaderColor,
} from 'src/styling/variables' } from 'src/styling/variables'
import { MINUTE } from 'src/utils/time' import { MINUTE } from 'src/utils/time'
import { toUtc } from 'src/utils/timezones' import { toUtc } from 'src/utils/timezones'
@ -22,7 +22,6 @@ const Graph = ({
setSelectionCoords, setSelectionCoords,
setSelectionData, setSelectionData,
setSelectionDateInterval, setSelectionDateInterval,
selectedMachine
}) => { }) => {
const ref = useRef(null) const ref = useRef(null)
@ -36,9 +35,9 @@ const Graph = ({
top: 25, top: 25,
right: 0.5, right: 0.5,
bottom: 27, bottom: 27,
left: 36.5 left: 36.5,
}), }),
[] [],
) )
const offset = getTimezoneOffset(timezone) const offset = getTimezoneOffset(timezone)
@ -64,7 +63,7 @@ const Graph = ({
const tzCreated = new Date(it.created).setTime( const tzCreated = new Date(it.created).setTime(
new Date(it.created).getTime() + new Date(it.created).getTime() +
new Date(it.created).getTimezoneOffset() * MINUTE + new Date(it.created).getTimezoneOffset() * MINUTE +
offset offset,
) )
const created = new Date(tzCreated) const created = new Date(tzCreated)
@ -77,7 +76,7 @@ const Graph = ({
created.getUTCHours() < new Date(upperBound).getUTCHours()) created.getUTCHours() < new Date(upperBound).getUTCHours())
) )
}, data), }, data),
[data, offset] [data, offset],
) )
const txClassByHourInterval = useCallback( const txClassByHourInterval = useCallback(
@ -91,16 +90,16 @@ const Graph = ({
return acc return acc
}, },
{ cashIn: 0, cashOut: 0 }, { cashIn: 0, cashOut: 0 },
filterByHourInterval(lowerBound, upperBound) filterByHourInterval(lowerBound, upperBound),
), ),
[filterByHourInterval] [filterByHourInterval],
) )
const x = d3 const x = d3
.scaleUtc() .scaleUtc()
.domain([ .domain([
toUtc(startOfDay(new Date())), toUtc(startOfDay(new Date())),
toUtc(add({ days: 1 }, startOfDay(new Date()))) toUtc(add({ days: 1 }, startOfDay(new Date()))),
]) ])
.rangeRound([GRAPH_MARGIN.left, GRAPH_WIDTH - GRAPH_MARGIN.right]) .rangeRound([GRAPH_MARGIN.left, GRAPH_WIDTH - GRAPH_MARGIN.right])
@ -111,7 +110,7 @@ const Graph = ({
const upperBound = R.clone(it) const upperBound = R.clone(it)
return [lowerBound, filterByHourInterval(lowerBound, upperBound)] return [lowerBound, filterByHourInterval(lowerBound, upperBound)]
}, },
R.init(getTickIntervals(x.domain(), 2)) R.init(getTickIntervals(x.domain(), 2)),
) )
const groupedByTxClass = R.map( const groupedByTxClass = R.map(
@ -121,7 +120,7 @@ const Graph = ({
const upperBound = R.clone(it) const upperBound = R.clone(it)
return [lowerBound, txClassByHourInterval(lowerBound, upperBound)] return [lowerBound, txClassByHourInterval(lowerBound, upperBound)]
}, },
R.init(getTickIntervals(x.domain(), 2)) R.init(getTickIntervals(x.domain(), 2)),
) )
const y = d3 const y = d3
@ -130,13 +129,13 @@ const Graph = ({
0, 0,
d3.max( d3.max(
groupedByTxClass.map(it => it[1]), groupedByTxClass.map(it => it[1]),
d => d.cashIn + d.cashOut d => d.cashIn + d.cashOut,
) !== 0 ) !== 0
? d3.max( ? d3.max(
groupedByTxClass.map(it => it[1]), groupedByTxClass.map(it => it[1]),
d => d.cashIn + d.cashOut d => d.cashIn + d.cashOut,
) )
: 50 : 50,
]) ])
.range([GRAPH_HEIGHT - GRAPH_MARGIN.bottom, GRAPH_MARGIN.top]) .range([GRAPH_HEIGHT - GRAPH_MARGIN.bottom, GRAPH_MARGIN.top])
@ -145,15 +144,15 @@ const Graph = ({
g g
.attr( .attr(
'transform', 'transform',
`translate(0, ${GRAPH_HEIGHT - GRAPH_MARGIN.bottom})` `translate(0, ${GRAPH_HEIGHT - GRAPH_MARGIN.bottom})`,
) )
.call( .call(
d3 d3
.axisBottom(x) .axisBottom(x)
.ticks(d3.timeHour.every(2)) .ticks(d3.timeHour.every(2))
.tickFormat(d3.timeFormat('%H:%M')) .tickFormat(d3.timeFormat('%H:%M')),
), ),
[GRAPH_MARGIN, x] [GRAPH_MARGIN, x],
) )
const buildYAxis = useCallback( const buildYAxis = useCallback(
@ -165,10 +164,10 @@ const Graph = ({
.axisLeft(y) .axisLeft(y)
.ticks(GRAPH_HEIGHT / 100) .ticks(GRAPH_HEIGHT / 100)
.tickSize(0) .tickSize(0)
.tickFormat(``) .tickFormat(``),
) )
.call(g => g.select('.domain').remove()), .call(g => g.select('.domain').remove()),
[GRAPH_MARGIN, y] [GRAPH_MARGIN, y],
) )
const buildVerticalLines = useCallback( const buildVerticalLines = useCallback(
@ -195,7 +194,7 @@ const Graph = ({
}) })
.attr('y1', GRAPH_MARGIN.top) .attr('y1', GRAPH_MARGIN.top)
.attr('y2', GRAPH_HEIGHT - GRAPH_MARGIN.bottom), .attr('y2', GRAPH_HEIGHT - GRAPH_MARGIN.bottom),
[GRAPH_MARGIN, x] [GRAPH_MARGIN, x],
) )
const buildHoverableEventRects = useCallback( const buildHoverableEventRects = useCallback(
@ -227,15 +226,15 @@ const Graph = ({
const endDate = R.clone(date) const endDate = R.clone(date)
const filteredData = groupedByDateInterval.find(it => const filteredData = groupedByDateInterval.find(it =>
R.equals(startDate, it[0]) R.equals(startDate, it[0]),
)[1] )[1]
const rectXCoords = { const rectXCoords = {
left: R.clone(d.target.getBoundingClientRect().x), left: R.clone(d.target.getBoundingClientRect().x),
right: R.clone( right: R.clone(
d.target.getBoundingClientRect().x + d.target.getBoundingClientRect().x +
d.target.getBoundingClientRect().width d.target.getBoundingClientRect().width,
) ),
} }
const xCoord = const xCoord =
@ -248,18 +247,18 @@ const Graph = ({
setSelectionData(filteredData) setSelectionData(filteredData)
setSelectionCoords({ setSelectionCoords({
x: Math.round(xCoord), x: Math.round(xCoord),
y: Math.round(yCoord) y: Math.round(yCoord),
}) })
d3.select(`#event-rect-${x(d.target.__data__)}`).attr( d3.select(`#event-rect-${x(d.target.__data__)}`).attr(
'fill', 'fill',
subheaderColor subheaderColor,
) )
}) })
.on('mouseleave', d => { .on('mouseleave', d => {
d3.select(`#event-rect-${x(d.target.__data__)}`).attr( d3.select(`#event-rect-${x(d.target.__data__)}`).attr(
'fill', 'fill',
'transparent' 'transparent',
) )
setSelectionDateInterval(null) setSelectionDateInterval(null)
setSelectionData(null) setSelectionData(null)
@ -271,8 +270,8 @@ const Graph = ({
setSelectionCoords, setSelectionCoords,
setSelectionData, setSelectionData,
setSelectionDateInterval, setSelectionDateInterval,
x x,
] ],
) )
const buildEventRects = useCallback( const buildEventRects = useCallback(
@ -298,7 +297,7 @@ const Graph = ({
.attr('height', GRAPH_HEIGHT - GRAPH_MARGIN.bottom - GRAPH_MARGIN.top) .attr('height', GRAPH_HEIGHT - GRAPH_MARGIN.bottom - GRAPH_MARGIN.top)
.attr('stroke', 'transparent') .attr('stroke', 'transparent')
.attr('fill', 'transparent'), .attr('fill', 'transparent'),
[GRAPH_MARGIN, x] [GRAPH_MARGIN, x],
) )
const formatTicksText = useCallback( const formatTicksText = useCallback(
@ -309,7 +308,7 @@ const Graph = ({
.style('fill', fontColor) .style('fill', fontColor)
.style('stroke-width', 0.5) .style('stroke-width', 0.5)
.style('font-family', fontSecondary), .style('font-family', fontSecondary),
[] [],
) )
const drawCashIn = useCallback( const drawCashIn = useCallback(
@ -334,7 +333,7 @@ const Graph = ({
GRAPH_HEIGHT - GRAPH_HEIGHT -
y(interval[1].cashIn) - y(interval[1].cashIn) -
GRAPH_MARGIN.bottom - GRAPH_MARGIN.bottom -
BAR_MARGIN / 2 BAR_MARGIN / 2,
) )
}) })
.attr('width', d => { .attr('width', d => {
@ -348,7 +347,7 @@ const Graph = ({
}) })
.attr('rx', 2.5) .attr('rx', 2.5)
}, },
[x, y, GRAPH_MARGIN, groupedByTxClass] [x, y, GRAPH_MARGIN, groupedByTxClass],
) )
const drawCashOut = useCallback( const drawCashOut = useCallback(
@ -377,7 +376,7 @@ const Graph = ({
GRAPH_HEIGHT - GRAPH_HEIGHT -
y(interval[1].cashOut) - y(interval[1].cashOut) -
GRAPH_MARGIN.bottom - GRAPH_MARGIN.bottom -
BAR_MARGIN / 2 BAR_MARGIN / 2,
) )
}) })
.attr('width', d => { .attr('width', d => {
@ -391,7 +390,7 @@ const Graph = ({
}) })
.attr('rx', 2.5) .attr('rx', 2.5)
}, },
[x, y, GRAPH_MARGIN, groupedByTxClass] [x, y, GRAPH_MARGIN, groupedByTxClass],
) )
const drawChart = useCallback(() => { const drawChart = useCallback(() => {
@ -417,7 +416,7 @@ const Graph = ({
buildVerticalLines, buildVerticalLines,
drawCashIn, drawCashIn,
formatTicksText, formatTicksText,
drawCashOut drawCashOut,
]) ])
useEffect(() => { useEffect(() => {
@ -433,5 +432,5 @@ export default memo(
(prev, next) => (prev, next) =>
R.equals(prev.period, next.period) && R.equals(prev.period, next.period) &&
R.equals(prev.selectedDay, next.selectedDay) && R.equals(prev.selectedDay, next.selectedDay) &&
R.equals(prev.selectedMachine, next.selectedMachine) R.equals(prev.selectedMachine, next.selectedMachine),
) )

View file

@ -13,7 +13,7 @@ import {
fontColor, fontColor,
primaryColor, primaryColor,
fontSecondary, fontSecondary,
subheaderColor subheaderColor,
} from 'src/styling/variables' } 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'
@ -25,7 +25,7 @@ const Graph = ({
setSelectionCoords, setSelectionCoords,
setSelectionData, setSelectionData,
setSelectionDateInterval, setSelectionDateInterval,
log = false log = false,
}) => { }) => {
const ref = useRef(null) const ref = useRef(null)
@ -38,9 +38,9 @@ const Graph = ({
top: 25, top: 25,
right: 3.5, right: 3.5,
bottom: 27, bottom: 27,
left: 38 left: 38,
}), }),
[] [],
) )
const offset = getTimezoneOffset(timezone) const offset = getTimezoneOffset(timezone)
@ -50,7 +50,7 @@ const Graph = ({
day: [NOW - DAY, NOW], day: [NOW - DAY, NOW],
threeDays: [NOW - 3 * DAY, NOW], threeDays: [NOW - 3 * DAY, NOW],
week: [NOW - WEEK, NOW], week: [NOW - WEEK, NOW],
month: [NOW - MONTH, NOW] month: [NOW - MONTH, NOW],
} }
const dataPoints = useMemo( const dataPoints = useMemo(
@ -59,28 +59,28 @@ const Graph = ({
freq: 24, freq: 24,
step: 60 * 60 * 1000, step: 60 * 60 * 1000,
tick: d3.utcHour.every(1), tick: d3.utcHour.every(1),
labelFormat: '%H:%M' labelFormat: '%H:%M',
}, },
threeDays: { threeDays: {
freq: 12, freq: 12,
step: 6 * 60 * 60 * 1000, step: 6 * 60 * 60 * 1000,
tick: d3.utcDay.every(1), tick: d3.utcDay.every(1),
labelFormat: '%a %d' labelFormat: '%a %d',
}, },
week: { week: {
freq: 7, freq: 7,
step: 24 * 60 * 60 * 1000, step: 24 * 60 * 60 * 1000,
tick: d3.utcDay.every(1), tick: d3.utcDay.every(1),
labelFormat: '%a %d' labelFormat: '%a %d',
}, },
month: { month: {
freq: 30, freq: 30,
step: 24 * 60 * 60 * 1000, step: 24 * 60 * 60 * 1000,
tick: d3.utcDay.every(1), tick: d3.utcDay.every(1),
labelFormat: '%d' labelFormat: '%d',
} },
}), }),
[] [],
) )
const getPastAndCurrentDayLabels = useCallback(d => { const getPastAndCurrentDayLabels = useCallback(d => {
@ -97,11 +97,11 @@ const Graph = ({
const previousDateMonth = previousDate.getUTCMonth() const previousDateMonth = previousDate.getUTCMonth()
const daysOfWeek = Array.from(Array(7)).map((_, i) => const daysOfWeek = Array.from(Array(7)).map((_, i) =>
format('EEE', add({ days: i }, startOfWeek(new Date()))) format('EEE', add({ days: i }, startOfWeek(new Date()))),
) )
const months = Array.from(Array(12)).map((_, i) => const months = Array.from(Array(12)).map((_, i) =>
format('LLL', add({ months: i }, startOfYear(new Date()))) format('LLL', add({ months: i }, startOfYear(new Date()))),
) )
return { return {
@ -112,7 +112,7 @@ const Graph = ({
current: current:
currentDateMonth !== previousDateMonth currentDateMonth !== previousDateMonth
? months[currentDateMonth] ? months[currentDateMonth]
: `${daysOfWeek[currentDateWeekday]} ${currentDateDay}` : `${daysOfWeek[currentDateWeekday]} ${currentDateDay}`,
} }
}, []) }, [])
@ -134,7 +134,7 @@ const Graph = ({
return points return points
}, },
[NOW, dataPoints, period.code] [NOW, dataPoints, period.code],
) )
const buildAreas = useCallback( const buildAreas = useCallback(
@ -159,7 +159,7 @@ const Graph = ({
return points return points
}, },
[NOW, dataPoints, period.code] [NOW, dataPoints, period.code],
) )
const x = d3 const x = d3
@ -177,7 +177,7 @@ const Graph = ({
.scaleLinear() .scaleLinear()
.domain([ .domain([
0, 0,
(d3.max(data, d => new BigNumber(d.fiat).toNumber()) ?? 1000) * 1.03 (d3.max(data, d => new BigNumber(d.fiat).toNumber()) ?? 1000) * 1.03,
]) ])
.nice() .nice()
.range([GRAPH_HEIGHT - GRAPH_MARGIN.bottom, GRAPH_MARGIN.top]) .range([GRAPH_HEIGHT - GRAPH_MARGIN.bottom, GRAPH_MARGIN.top])
@ -186,7 +186,7 @@ const Graph = ({
.scaleLog() .scaleLog()
.domain([ .domain([
(d3.min(data, d => new BigNumber(d.fiat).toNumber()) ?? 1) * 0.9, (d3.min(data, d => new BigNumber(d.fiat).toNumber()) ?? 1) * 0.9,
(d3.max(data, d => new BigNumber(d.fiat).toNumber()) ?? 1000) * 1.1 (d3.max(data, d => new BigNumber(d.fiat).toNumber()) ?? 1000) * 1.1,
]) ])
.range([GRAPH_HEIGHT - GRAPH_MARGIN.bottom, GRAPH_MARGIN.top]) .range([GRAPH_HEIGHT - GRAPH_MARGIN.bottom, GRAPH_MARGIN.top])
@ -196,7 +196,7 @@ const Graph = ({
const fullBreakpoints = [ const fullBreakpoints = [
graphLimits[1], graphLimits[1],
...R.filter(it => it > dataLimits[0] && it < dataLimits[1], breakpoints), ...R.filter(it => it > dataLimits[0] && it < dataLimits[1], breakpoints),
dataLimits[0] dataLimits[0],
] ]
const intervals = [] const intervals = []
@ -227,7 +227,7 @@ const Graph = ({
g g
.attr( .attr(
'transform', 'transform',
`translate(0, ${GRAPH_HEIGHT - GRAPH_MARGIN.bottom})` `translate(0, ${GRAPH_HEIGHT - GRAPH_MARGIN.bottom})`,
) )
.call( .call(
d3 d3
@ -235,18 +235,18 @@ const Graph = ({
.ticks(dataPoints[period.code].tick) .ticks(dataPoints[period.code].tick)
.tickFormat(d => { .tickFormat(d => {
return d3.timeFormat(dataPoints[period.code].labelFormat)( return d3.timeFormat(dataPoints[period.code].labelFormat)(
d.getTime() + d.getTimezoneOffset() * MINUTE d.getTime() + d.getTimezoneOffset() * MINUTE,
) )
}) })
.tickSizeOuter(0) .tickSizeOuter(0),
) )
.call(g => .call(g =>
g g
.select('.domain') .select('.domain')
.attr('stroke', primaryColor) .attr('stroke', primaryColor)
.attr('stroke-width', 1) .attr('stroke-width', 1),
), ),
[GRAPH_MARGIN, dataPoints, period.code, x] [GRAPH_MARGIN, dataPoints, period.code, x],
) )
const buildYAxis = useCallback( const buildYAxis = useCallback(
@ -264,12 +264,12 @@ const Graph = ({
if (d >= 1000) return numberToFiatAmount(d / 1000) + 'k' if (d >= 1000) return numberToFiatAmount(d / 1000) + 'k'
return numberToFiatAmount(d) return numberToFiatAmount(d)
}) }),
) )
.select('.domain') .select('.domain')
.attr('stroke', primaryColor) .attr('stroke', primaryColor)
.attr('stroke-width', 1), .attr('stroke-width', 1),
[GRAPH_MARGIN, y, log] [GRAPH_MARGIN, y, log],
) )
const buildGrid = useCallback( const buildGrid = useCallback(
@ -286,7 +286,7 @@ const Graph = ({
.attr('x1', d => 0.5 + x(d)) .attr('x1', d => 0.5 + x(d))
.attr('x2', d => 0.5 + x(d)) .attr('x2', d => 0.5 + x(d))
.attr('y1', GRAPH_MARGIN.top) .attr('y1', GRAPH_MARGIN.top)
.attr('y2', GRAPH_HEIGHT - GRAPH_MARGIN.bottom) .attr('y2', GRAPH_HEIGHT - GRAPH_MARGIN.bottom),
) )
// Horizontal lines // Horizontal lines
.call(g => .call(g =>
@ -297,13 +297,13 @@ const Graph = ({
d3 d3
.axisLeft(y) .axisLeft(y)
.scale() .scale()
.ticks(GRAPH_HEIGHT / 100) .ticks(GRAPH_HEIGHT / 100),
) )
.join('line') .join('line')
.attr('y1', d => 0.5 + y(d)) .attr('y1', d => 0.5 + y(d))
.attr('y2', d => 0.5 + y(d)) .attr('y2', d => 0.5 + y(d))
.attr('x1', GRAPH_MARGIN.left) .attr('x1', GRAPH_MARGIN.left)
.attr('x2', GRAPH_WIDTH) .attr('x2', GRAPH_WIDTH),
) )
// Vertical transparent rectangles for events // Vertical transparent rectangles for events
.call(g => .call(g =>
@ -319,14 +319,14 @@ const Graph = ({
const intervals = getAreaInterval( const intervals = getAreaInterval(
buildAreas(x.domain()).map(it => Math.round(x(it) * 100) / 100), buildAreas(x.domain()).map(it => Math.round(x(it) * 100) / 100),
x.range(), x.range(),
x2.range() x2.range(),
) )
const interval = getAreaIntervalByX(intervals, xValue) const interval = getAreaIntervalByX(intervals, xValue)
return Math.round((interval[0] - interval[1]) * 100) / 100 return Math.round((interval[0] - interval[1]) * 100) / 100
}) })
.attr( .attr(
'height', 'height',
GRAPH_HEIGHT - GRAPH_MARGIN.bottom - GRAPH_MARGIN.top GRAPH_HEIGHT - GRAPH_MARGIN.bottom - GRAPH_MARGIN.top,
) )
.attr('stroke', 'transparent') .attr('stroke', 'transparent')
.attr('fill', 'transparent') .attr('fill', 'transparent')
@ -336,7 +336,7 @@ const Graph = ({
const intervals = getAreaInterval( const intervals = getAreaInterval(
buildAreas(x.domain()).map(it => Math.round(x(it) * 100) / 100), buildAreas(x.domain()).map(it => Math.round(x(it) * 100) / 100),
x.range(), x.range(),
x2.range() x2.range(),
) )
const dateInterval = getDateIntervalByX(areas, intervals, xValue) const dateInterval = getDateIntervalByX(areas, intervals, xValue)
@ -354,8 +354,8 @@ const Graph = ({
left: R.clone(d.target.getBoundingClientRect().x), left: R.clone(d.target.getBoundingClientRect().x),
right: R.clone( right: R.clone(
d.target.getBoundingClientRect().x + d.target.getBoundingClientRect().x +
d.target.getBoundingClientRect().width d.target.getBoundingClientRect().width,
) ),
} }
const xCoord = const xCoord =
@ -370,7 +370,7 @@ const Graph = ({
setSelectionData(filteredData) setSelectionData(filteredData)
setSelectionCoords({ setSelectionCoords({
x: Math.round(xCoord), x: Math.round(xCoord),
y: Math.round(yCoord) y: Math.round(yCoord),
}) })
d3.select(d.target).attr('fill', subheaderColor) d3.select(d.target).attr('fill', subheaderColor)
@ -380,7 +380,7 @@ const Graph = ({
setSelectionDateInterval(null) setSelectionDateInterval(null)
setSelectionData(null) setSelectionData(null)
setSelectionCoords(null) setSelectionCoords(null)
}) }),
) )
// Thick vertical lines // Thick vertical lines
.call(g => .call(g =>
@ -391,7 +391,7 @@ const Graph = ({
buildTicks(x.domain()).filter(x => { buildTicks(x.domain()).filter(x => {
if (period.code === 'day') return x.getUTCHours() === 0 if (period.code === 'day') return x.getUTCHours() === 0
return x.getUTCDate() === 1 return x.getUTCDate() === 1
}) }),
) )
.join('line') .join('line')
.attr('class', 'dateSeparator') .attr('class', 'dateSeparator')
@ -400,7 +400,7 @@ const Graph = ({
.attr('y1', GRAPH_MARGIN.top - 50) .attr('y1', GRAPH_MARGIN.top - 50)
.attr('y2', GRAPH_HEIGHT - GRAPH_MARGIN.bottom) .attr('y2', GRAPH_HEIGHT - GRAPH_MARGIN.bottom)
.attr('stroke-width', 5) .attr('stroke-width', 5)
.join('text') .join('text'),
) )
// Left side breakpoint label // Left side breakpoint label
.call(g => { .call(g => {
@ -458,8 +458,8 @@ const Graph = ({
offset, offset,
setSelectionCoords, setSelectionCoords,
setSelectionData, setSelectionData,
setSelectionDateInterval setSelectionDateInterval,
] ],
) )
const formatTicksText = useCallback( const formatTicksText = useCallback(
@ -470,7 +470,7 @@ const Graph = ({
.style('fill', fontColor) .style('fill', fontColor)
.style('stroke-width', 0.5) .style('stroke-width', 0.5)
.style('font-family', fontSecondary), .style('font-family', fontSecondary),
[] [],
) )
const formatText = useCallback( const formatText = useCallback(
@ -481,7 +481,7 @@ const Graph = ({
.style('fill', offColor) .style('fill', offColor)
.style('stroke-width', 0.5) .style('stroke-width', 0.5)
.style('font-family', fontSecondary), .style('font-family', fontSecondary),
[] [],
) )
const formatTicks = useCallback(() => { const formatTicks = useCallback(() => {
@ -505,10 +505,10 @@ const Graph = ({
.attr('y1', 0.5 + y(median)) .attr('y1', 0.5 + y(median))
.attr('y2', 0.5 + y(median)) .attr('y2', 0.5 + y(median))
.attr('x1', GRAPH_MARGIN.left) .attr('x1', GRAPH_MARGIN.left)
.attr('x2', GRAPH_WIDTH) .attr('x2', GRAPH_WIDTH),
) )
}, },
[GRAPH_MARGIN, y, data, log] [GRAPH_MARGIN, y, data, log],
) )
const drawData = useCallback( const drawData = useCallback(
@ -524,7 +524,7 @@ const Graph = ({
.attr('fill', d => (d.txClass === 'cashIn' ? java : neon)) .attr('fill', d => (d.txClass === 'cashIn' ? java : neon))
.attr('r', 3.5) .attr('r', 3.5)
}, },
[data, offset, x, y] [data, offset, x, y],
) )
const drawChart = useCallback(() => { const drawChart = useCallback(() => {
@ -550,7 +550,7 @@ const Graph = ({
drawData, drawData,
formatText, formatText,
formatTicks, formatTicks,
formatTicksText formatTicksText,
]) ])
useEffect(() => { useEffect(() => {
@ -566,5 +566,5 @@ export default memo(
(prev, next) => (prev, next) =>
R.equals(prev.period, next.period) && R.equals(prev.period, next.period) &&
R.equals(prev.selectedMachine, next.selectedMachine) && R.equals(prev.selectedMachine, next.selectedMachine) &&
R.equals(prev.log, next.log) R.equals(prev.log, next.log),
) )

View file

@ -8,7 +8,7 @@ import {
differenceInMilliseconds, differenceInMilliseconds,
format, format,
startOfWeek, startOfWeek,
startOfYear startOfYear,
} from 'date-fns/fp' } from 'date-fns/fp'
import * as R from 'ramda' import * as R from 'ramda'
import React, { memo, useCallback, useEffect, useMemo, useRef } from 'react' import React, { memo, useCallback, useEffect, useMemo, useRef } from 'react'
@ -21,7 +21,7 @@ import {
fontColor, fontColor,
primaryColor, primaryColor,
fontSecondary, fontSecondary,
subheaderColor subheaderColor,
} from 'src/styling/variables' } 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'
@ -33,7 +33,7 @@ const Graph = ({
setSelectionCoords, setSelectionCoords,
setSelectionData, setSelectionData,
setSelectionDateInterval, setSelectionDateInterval,
log = false log = false,
}) => { }) => {
const ref = useRef(null) const ref = useRef(null)
@ -46,9 +46,9 @@ const Graph = ({
top: 25, top: 25,
right: 3.5, right: 3.5,
bottom: 27, bottom: 27,
left: 38 left: 38,
}), }),
[] [],
) )
const offset = getTimezoneOffset(timezone) const offset = getTimezoneOffset(timezone)
@ -58,7 +58,7 @@ const Graph = ({
day: [NOW - DAY, NOW], day: [NOW - DAY, NOW],
threeDays: [NOW - 3 * DAY, NOW], threeDays: [NOW - 3 * DAY, NOW],
week: [NOW - WEEK, NOW], week: [NOW - WEEK, NOW],
month: [NOW - MONTH, NOW] month: [NOW - MONTH, NOW],
} }
const dataPoints = useMemo( const dataPoints = useMemo(
@ -67,28 +67,28 @@ const Graph = ({
freq: 24, freq: 24,
step: 60 * 60 * 1000, step: 60 * 60 * 1000,
tick: d3.utcHour.every(1), tick: d3.utcHour.every(1),
labelFormat: '%H:%M' labelFormat: '%H:%M',
}, },
threeDays: { threeDays: {
freq: 12, freq: 12,
step: 6 * 60 * 60 * 1000, step: 6 * 60 * 60 * 1000,
tick: d3.utcDay.every(1), tick: d3.utcDay.every(1),
labelFormat: '%a %d' labelFormat: '%a %d',
}, },
week: { week: {
freq: 7, freq: 7,
step: 24 * 60 * 60 * 1000, step: 24 * 60 * 60 * 1000,
tick: d3.utcDay.every(1), tick: d3.utcDay.every(1),
labelFormat: '%a %d' labelFormat: '%a %d',
}, },
month: { month: {
freq: 30, freq: 30,
step: 24 * 60 * 60 * 1000, step: 24 * 60 * 60 * 1000,
tick: d3.utcDay.every(1), tick: d3.utcDay.every(1),
labelFormat: '%d' labelFormat: '%d',
} },
}), }),
[] [],
) )
const getPastAndCurrentDayLabels = useCallback(d => { const getPastAndCurrentDayLabels = useCallback(d => {
@ -105,11 +105,11 @@ const Graph = ({
const previousDateMonth = previousDate.getUTCMonth() const previousDateMonth = previousDate.getUTCMonth()
const daysOfWeek = Array.from(Array(7)).map((_, i) => const daysOfWeek = Array.from(Array(7)).map((_, i) =>
format('EEE', add({ days: i }, startOfWeek(new Date()))) format('EEE', add({ days: i }, startOfWeek(new Date()))),
) )
const months = Array.from(Array(12)).map((_, i) => const months = Array.from(Array(12)).map((_, i) =>
format('LLL', add({ months: i }, startOfYear(new Date()))) format('LLL', add({ months: i }, startOfYear(new Date()))),
) )
return { return {
@ -120,7 +120,7 @@ const Graph = ({
current: current:
currentDateMonth !== previousDateMonth currentDateMonth !== previousDateMonth
? months[currentDateMonth] ? months[currentDateMonth]
: `${daysOfWeek[currentDateWeekday]} ${currentDateDay}` : `${daysOfWeek[currentDateWeekday]} ${currentDateDay}`,
} }
}, []) }, [])
@ -142,7 +142,7 @@ const Graph = ({
return points return points
}, },
[NOW, dataPoints, period.code] [NOW, dataPoints, period.code],
) )
const buildAreas = useCallback( const buildAreas = useCallback(
@ -167,7 +167,7 @@ const Graph = ({
return points return points
}, },
[NOW, dataPoints, period.code] [NOW, dataPoints, period.code],
) )
const x = d3 const x = d3
@ -192,14 +192,14 @@ const Graph = ({
else if (i === dates.length - 1) else if (i === dates.length - 1)
return addMilliseconds( return addMilliseconds(
-dataPoints[period.code].step, -dataPoints[period.code].step,
dates[dates.length - 2] dates[dates.length - 2],
) )
else return date else return date
}) })
.map(date => { .map(date => {
const middleOfBin = addMilliseconds( const middleOfBin = addMilliseconds(
dataPoints[period.code].step / 2, dataPoints[period.code].step / 2,
date date,
) )
const txs = data.filter(tx => { const txs = data.filter(tx => {
@ -236,7 +236,7 @@ const Graph = ({
.scaleLog() .scaleLog()
.domain([ .domain([
min === 0 ? 0.9 : min * 0.9, min === 0 ? 0.9 : min * 0.9,
(max === min ? min + Math.pow(10, 2 * min + 1) : max) * 2 (max === min ? min + Math.pow(10, 2 * min + 1) : max) * 2,
]) ])
.clamp(true) .clamp(true)
.range([GRAPH_HEIGHT - GRAPH_MARGIN.bottom, GRAPH_MARGIN.top]) .range([GRAPH_HEIGHT - GRAPH_MARGIN.bottom, GRAPH_MARGIN.top])
@ -247,7 +247,7 @@ const Graph = ({
const fullBreakpoints = [ const fullBreakpoints = [
graphLimits[1], graphLimits[1],
...R.filter(it => it > dataLimits[0] && it < dataLimits[1], breakpoints), ...R.filter(it => it > dataLimits[0] && it < dataLimits[1], breakpoints),
dataLimits[0] dataLimits[0],
] ]
const intervals = [] const intervals = []
@ -278,7 +278,7 @@ const Graph = ({
g g
.attr( .attr(
'transform', 'transform',
`translate(0, ${GRAPH_HEIGHT - GRAPH_MARGIN.bottom})` `translate(0, ${GRAPH_HEIGHT - GRAPH_MARGIN.bottom})`,
) )
.call( .call(
d3 d3
@ -286,18 +286,18 @@ const Graph = ({
.ticks(dataPoints[period.code].tick) .ticks(dataPoints[period.code].tick)
.tickFormat(d => { .tickFormat(d => {
return d3.timeFormat(dataPoints[period.code].labelFormat)( return d3.timeFormat(dataPoints[period.code].labelFormat)(
d.getTime() + d.getTimezoneOffset() * MINUTE d.getTime() + d.getTimezoneOffset() * MINUTE,
) )
}) })
.tickSizeOuter(0) .tickSizeOuter(0),
) )
.call(g => .call(g =>
g g
.select('.domain') .select('.domain')
.attr('stroke', primaryColor) .attr('stroke', primaryColor)
.attr('stroke-width', 1) .attr('stroke-width', 1),
), ),
[GRAPH_MARGIN, dataPoints, period.code, x] [GRAPH_MARGIN, dataPoints, period.code, x],
) )
const buildYAxis = useCallback( const buildYAxis = useCallback(
@ -315,12 +315,12 @@ const Graph = ({
if (d >= 1000) return numberToFiatAmount(d / 1000) + 'k' if (d >= 1000) return numberToFiatAmount(d / 1000) + 'k'
return numberToFiatAmount(d) return numberToFiatAmount(d)
}) }),
) )
.select('.domain') .select('.domain')
.attr('stroke', primaryColor) .attr('stroke', primaryColor)
.attr('stroke-width', 1), .attr('stroke-width', 1),
[GRAPH_MARGIN, y, log] [GRAPH_MARGIN, y, log],
) )
const buildGrid = useCallback( const buildGrid = useCallback(
@ -337,7 +337,7 @@ const Graph = ({
.attr('x1', d => 0.5 + x(d)) .attr('x1', d => 0.5 + x(d))
.attr('x2', d => 0.5 + x(d)) .attr('x2', d => 0.5 + x(d))
.attr('y1', GRAPH_MARGIN.top) .attr('y1', GRAPH_MARGIN.top)
.attr('y2', GRAPH_HEIGHT - GRAPH_MARGIN.bottom) .attr('y2', GRAPH_HEIGHT - GRAPH_MARGIN.bottom),
) )
// Horizontal lines // Horizontal lines
.call(g => .call(g =>
@ -348,13 +348,13 @@ const Graph = ({
d3 d3
.axisLeft(y) .axisLeft(y)
.scale() .scale()
.ticks(GRAPH_HEIGHT / 100) .ticks(GRAPH_HEIGHT / 100),
) )
.join('line') .join('line')
.attr('y1', d => 0.5 + y(d)) .attr('y1', d => 0.5 + y(d))
.attr('y2', d => 0.5 + y(d)) .attr('y2', d => 0.5 + y(d))
.attr('x1', GRAPH_MARGIN.left) .attr('x1', GRAPH_MARGIN.left)
.attr('x2', GRAPH_WIDTH) .attr('x2', GRAPH_WIDTH),
) )
// Vertical transparent rectangles for events // Vertical transparent rectangles for events
.call(g => .call(g =>
@ -370,14 +370,14 @@ const Graph = ({
const intervals = getAreaInterval( const intervals = getAreaInterval(
buildAreas(x.domain()).map(it => Math.round(x(it) * 100) / 100), buildAreas(x.domain()).map(it => Math.round(x(it) * 100) / 100),
x.range(), x.range(),
x2.range() x2.range(),
) )
const interval = getAreaIntervalByX(intervals, xValue) const interval = getAreaIntervalByX(intervals, xValue)
return Math.round((interval[0] - interval[1]) * 100) / 100 return Math.round((interval[0] - interval[1]) * 100) / 100
}) })
.attr( .attr(
'height', 'height',
GRAPH_HEIGHT - GRAPH_MARGIN.bottom - GRAPH_MARGIN.top GRAPH_HEIGHT - GRAPH_MARGIN.bottom - GRAPH_MARGIN.top,
) )
.attr('stroke', 'transparent') .attr('stroke', 'transparent')
.attr('fill', 'transparent') .attr('fill', 'transparent')
@ -387,7 +387,7 @@ const Graph = ({
const intervals = getAreaInterval( const intervals = getAreaInterval(
buildAreas(x.domain()).map(it => Math.round(x(it) * 100) / 100), buildAreas(x.domain()).map(it => Math.round(x(it) * 100) / 100),
x.range(), x.range(),
x2.range() x2.range(),
) )
const dateInterval = getDateIntervalByX(areas, intervals, xValue) const dateInterval = getDateIntervalByX(areas, intervals, xValue)
@ -405,8 +405,8 @@ const Graph = ({
left: R.clone(d.target.getBoundingClientRect().x), left: R.clone(d.target.getBoundingClientRect().x),
right: R.clone( right: R.clone(
d.target.getBoundingClientRect().x + d.target.getBoundingClientRect().x +
d.target.getBoundingClientRect().width d.target.getBoundingClientRect().width,
) ),
} }
const xCoord = const xCoord =
@ -421,7 +421,7 @@ const Graph = ({
setSelectionData(filteredData) setSelectionData(filteredData)
setSelectionCoords({ setSelectionCoords({
x: Math.round(xCoord), x: Math.round(xCoord),
y: Math.round(yCoord) y: Math.round(yCoord),
}) })
d3.select(d.target).attr('fill', subheaderColor) d3.select(d.target).attr('fill', subheaderColor)
@ -431,7 +431,7 @@ const Graph = ({
setSelectionDateInterval(null) setSelectionDateInterval(null)
setSelectionData(null) setSelectionData(null)
setSelectionCoords(null) setSelectionCoords(null)
}) }),
) )
// Thick vertical lines // Thick vertical lines
.call(g => .call(g =>
@ -442,7 +442,7 @@ const Graph = ({
buildTicks(x.domain()).filter(x => { buildTicks(x.domain()).filter(x => {
if (period.code === 'day') return x.getUTCHours() === 0 if (period.code === 'day') return x.getUTCHours() === 0
return x.getUTCDate() === 1 return x.getUTCDate() === 1
}) }),
) )
.join('line') .join('line')
.attr('class', 'dateSeparator') .attr('class', 'dateSeparator')
@ -451,7 +451,7 @@ const Graph = ({
.attr('y1', GRAPH_MARGIN.top - 50) .attr('y1', GRAPH_MARGIN.top - 50)
.attr('y2', GRAPH_HEIGHT - GRAPH_MARGIN.bottom) .attr('y2', GRAPH_HEIGHT - GRAPH_MARGIN.bottom)
.attr('stroke-width', 5) .attr('stroke-width', 5)
.join('text') .join('text'),
) )
// Left side breakpoint label // Left side breakpoint label
.call(g => { .call(g => {
@ -509,8 +509,8 @@ const Graph = ({
offset, offset,
setSelectionCoords, setSelectionCoords,
setSelectionData, setSelectionData,
setSelectionDateInterval setSelectionDateInterval,
] ],
) )
const formatTicksText = useCallback( const formatTicksText = useCallback(
@ -521,7 +521,7 @@ const Graph = ({
.style('fill', fontColor) .style('fill', fontColor)
.style('stroke-width', 0.5) .style('stroke-width', 0.5)
.style('font-family', fontSecondary), .style('font-family', fontSecondary),
[] [],
) )
const formatText = useCallback( const formatText = useCallback(
@ -532,7 +532,7 @@ const Graph = ({
.style('fill', offColor) .style('fill', offColor)
.style('stroke-width', 0.5) .style('stroke-width', 0.5)
.style('font-family', fontSecondary), .style('font-family', fontSecondary),
[] [],
) )
const formatTicks = useCallback(() => { const formatTicks = useCallback(() => {
@ -574,7 +574,7 @@ const Graph = ({
.line() .line()
.curve(d3.curveMonotoneX) .curve(d3.curveMonotoneX)
.x(d => x(d.date)) .x(d => x(d.date))
.y(d => y(d.cashIn)) .y(d => y(d.cashIn)),
) )
g.append('g') g.append('g')
@ -599,10 +599,10 @@ const Graph = ({
.line() .line()
.curve(d3.curveMonotoneX) .curve(d3.curveMonotoneX)
.x(d => x(d.date)) .x(d => x(d.date))
.y(d => y(d.cashOut)) .y(d => y(d.cashOut)),
) )
}, },
[x, y, bins, GRAPH_MARGIN] [x, y, bins, GRAPH_MARGIN],
) )
const drawChart = useCallback(() => { const drawChart = useCallback(() => {
@ -626,7 +626,7 @@ const Graph = ({
drawData, drawData,
formatText, formatText,
formatTicks, formatTicks,
formatTicksText formatTicksText,
]) ])
useEffect(() => { useEffect(() => {
@ -642,5 +642,5 @@ export default memo(
(prev, next) => (prev, next) =>
R.equals(prev.period, next.period) && R.equals(prev.period, next.period) &&
R.equals(prev.selectedMachine, next.selectedMachine) && R.equals(prev.selectedMachine, next.selectedMachine) &&
R.equals(prev.log, next.log) R.equals(prev.log, next.log),
) )

View file

@ -8,10 +8,10 @@ import {
neon, neon,
subheaderDarkColor, subheaderDarkColor,
fontColor, fontColor,
fontSecondary fontSecondary,
} from 'src/styling/variables' } from 'src/styling/variables'
const Graph = ({ data, machines, currency, selectedMachine }) => { const Graph = ({ data, machines, currency }) => {
const ref = useRef(null) const ref = useRef(null)
const AMOUNT_OF_MACHINES = 5 const AMOUNT_OF_MACHINES = 5
@ -24,9 +24,9 @@ const Graph = ({ data, machines, currency, selectedMachine }) => {
top: 25, top: 25,
right: 0.5, right: 0.5,
bottom: 27, bottom: 27,
left: 36.5 left: 36.5,
}), }),
[] [],
) )
const machinesClone = R.clone(machines) const machinesClone = R.clone(machines)
@ -41,7 +41,7 @@ const Graph = ({ data, machines, currency, selectedMachine }) => {
if (!R.isNil(machinesClone[it])) return machinesClone[it] if (!R.isNil(machinesClone[it])) return machinesClone[it]
return { code: `ghostMachine${it}`, display: `` } return { code: `ghostMachine${it}`, display: `` }
}, },
R.times(R.identity, AMOUNT_OF_MACHINES) R.times(R.identity, AMOUNT_OF_MACHINES),
) )
const txByDevice = R.reduce( const txByDevice = R.reduce(
@ -50,14 +50,14 @@ const Graph = ({ data, machines, currency, selectedMachine }) => {
return acc return acc
}, },
{}, {},
filledMachines filledMachines,
) )
const getDeviceVolume = deviceId => const getDeviceVolume = deviceId =>
R.reduce( R.reduce(
(acc, value) => acc + BigNumber(value.fiat).toNumber(), (acc, value) => acc + BigNumber(value.fiat).toNumber(),
0, 0,
txByDevice[deviceId] txByDevice[deviceId],
) )
const getDeviceVolumeByTxClass = deviceId => const getDeviceVolumeByTxClass = deviceId =>
@ -70,18 +70,18 @@ const Graph = ({ data, machines, currency, selectedMachine }) => {
return acc return acc
}, },
{ cashIn: 0, cashOut: 0 }, { cashIn: 0, cashOut: 0 },
txByDevice[deviceId] txByDevice[deviceId],
) )
const devicesByVolume = R.sort( const devicesByVolume = R.sort(
(a, b) => b[1] - a[1], (a, b) => b[1] - a[1],
R.map(m => [m.code, getDeviceVolume(m.code)], filledMachines) R.map(m => [m.code, getDeviceVolume(m.code)], filledMachines),
) )
const topMachines = R.take(AMOUNT_OF_MACHINES, devicesByVolume) const topMachines = R.take(AMOUNT_OF_MACHINES, devicesByVolume)
const txClassVolumeByDevice = R.fromPairs( const txClassVolumeByDevice = R.fromPairs(
R.map(v => [v[0], getDeviceVolumeByTxClass(v[0])], topMachines) R.map(v => [v[0], getDeviceVolumeByTxClass(v[0])], topMachines),
) )
const x = d3 const x = d3
@ -94,7 +94,9 @@ const Graph = ({ data, machines, currency, selectedMachine }) => {
.scaleLinear() .scaleLinear()
.domain([ .domain([
0, 0,
d3.max(topMachines, d => d[1]) !== 0 ? d3.max(topMachines, d => d[1]) : 50 d3.max(topMachines, d => d[1]) !== 0
? d3.max(topMachines, d => d[1])
: 50,
]) ])
.range([GRAPH_HEIGHT - GRAPH_MARGIN.bottom, GRAPH_MARGIN.top]) .range([GRAPH_HEIGHT - GRAPH_MARGIN.bottom, GRAPH_MARGIN.top])
@ -104,7 +106,7 @@ const Graph = ({ data, machines, currency, selectedMachine }) => {
.attr('class', 'x-axis-1') .attr('class', 'x-axis-1')
.attr( .attr(
'transform', 'transform',
`translate(0, ${GRAPH_HEIGHT - GRAPH_MARGIN.bottom})` `translate(0, ${GRAPH_HEIGHT - GRAPH_MARGIN.bottom})`,
) )
.call( .call(
d3 d3
@ -113,12 +115,12 @@ const Graph = ({ data, machines, currency, selectedMachine }) => {
d => d =>
`${ `${
R.find(it => it.code === d[0], filledMachines).display ?? '' R.find(it => it.code === d[0], filledMachines).display ?? ''
}` }`,
) )
.tickSize(0) .tickSize(0)
.tickPadding(10) .tickPadding(10),
), ),
[GRAPH_MARGIN, x, filledMachines] [GRAPH_MARGIN, x, filledMachines],
) )
const buildXAxis2 = useCallback( const buildXAxis2 = useCallback(
@ -126,7 +128,7 @@ const Graph = ({ data, machines, currency, selectedMachine }) => {
g.attr('class', 'x-axis-2') g.attr('class', 'x-axis-2')
.attr( .attr(
'transform', 'transform',
`translate(0, ${GRAPH_HEIGHT - GRAPH_MARGIN.bottom})` `translate(0, ${GRAPH_HEIGHT - GRAPH_MARGIN.bottom})`,
) )
.call( .call(
d3 d3
@ -134,24 +136,24 @@ const Graph = ({ data, machines, currency, selectedMachine }) => {
.tickFormat(d => .tickFormat(d =>
R.includes(`ghostMachine`, d[0]) R.includes(`ghostMachine`, d[0])
? `` ? ``
: `${d[1].toFixed(2)} ${currency}` : `${d[1].toFixed(2)} ${currency}`,
) )
.tickSize(0) .tickSize(0)
.tickPadding(10) .tickPadding(10),
) )
}, },
[GRAPH_MARGIN, x, currency] [GRAPH_MARGIN, x, currency],
) )
const positionXAxisLabels = useCallback(() => { const positionXAxisLabels = useCallback(() => {
d3.selectAll('.x-axis-1 .tick text').attr('transform', function (d) { d3.selectAll('.x-axis-1 .tick text').attr('transform', function () {
const widthPerEntry = (x.range()[1] - x.range()[0]) / AMOUNT_OF_MACHINES const widthPerEntry = (x.range()[1] - x.range()[0]) / AMOUNT_OF_MACHINES
return `translate(${-widthPerEntry / 2.25 + this.getBBox().width / 2}, 0)` return `translate(${-widthPerEntry / 2.25 + this.getBBox().width / 2}, 0)`
}) })
}, [x]) }, [x])
const positionXAxis2Labels = useCallback(() => { const positionXAxis2Labels = useCallback(() => {
d3.selectAll('.x-axis-2 .tick text').attr('transform', function (d) { d3.selectAll('.x-axis-2 .tick text').attr('transform', function () {
const widthPerEntry = (x.range()[1] - x.range()[0]) / AMOUNT_OF_MACHINES const widthPerEntry = (x.range()[1] - x.range()[0]) / AMOUNT_OF_MACHINES
return `translate(${widthPerEntry / 2.25 - this.getBBox().width / 2}, 0)` return `translate(${widthPerEntry / 2.25 - this.getBBox().width / 2}, 0)`
}) })
@ -166,10 +168,10 @@ const Graph = ({ data, machines, currency, selectedMachine }) => {
.axisLeft(y) .axisLeft(y)
.ticks(GRAPH_HEIGHT / 100) .ticks(GRAPH_HEIGHT / 100)
.tickSize(0) .tickSize(0)
.tickFormat(``) .tickFormat(``),
) )
.call(g => g.select('.domain').remove()), .call(g => g.select('.domain').remove()),
[GRAPH_MARGIN, y] [GRAPH_MARGIN, y],
) )
const formatTicksText = useCallback( const formatTicksText = useCallback(
@ -180,7 +182,7 @@ const Graph = ({ data, machines, currency, selectedMachine }) => {
.style('fill', fontColor) .style('fill', fontColor)
.style('stroke-width', 0.5) .style('stroke-width', 0.5)
.style('font-family', fontSecondary), .style('font-family', fontSecondary),
[] [],
) )
const buildGrid = useCallback( const buildGrid = useCallback(
@ -213,10 +215,10 @@ const Graph = ({ data, machines, currency, selectedMachine }) => {
return 0.5 + x(d) - paddedXValue return 0.5 + x(d) - paddedXValue
}) })
.attr('y1', GRAPH_MARGIN.top) .attr('y1', GRAPH_MARGIN.top)
.attr('y2', GRAPH_HEIGHT - GRAPH_MARGIN.bottom) .attr('y2', GRAPH_HEIGHT - GRAPH_MARGIN.bottom),
) )
}, },
[GRAPH_MARGIN, x] [GRAPH_MARGIN, x],
) )
const drawCashIn = useCallback( const drawCashIn = useCallback(
@ -231,13 +233,13 @@ const Graph = ({ data, machines, currency, selectedMachine }) => {
R.clamp( R.clamp(
0, 0,
GRAPH_HEIGHT, GRAPH_HEIGHT,
GRAPH_HEIGHT - y(d[1].cashIn) - GRAPH_MARGIN.bottom - BAR_MARGIN GRAPH_HEIGHT - y(d[1].cashIn) - GRAPH_MARGIN.bottom - BAR_MARGIN,
) ),
) )
.attr('width', x.bandwidth()) .attr('width', x.bandwidth())
.attr('rx', 2.5) .attr('rx', 2.5)
}, },
[txClassVolumeByDevice, x, y, GRAPH_MARGIN] [txClassVolumeByDevice, x, y, GRAPH_MARGIN],
) )
const drawCashOut = useCallback( const drawCashOut = useCallback(
@ -252,7 +254,7 @@ const Graph = ({ data, machines, currency, selectedMachine }) => {
d => d =>
y(d[1].cashIn + d[1].cashOut) - y(d[1].cashIn + d[1].cashOut) -
GRAPH_MARGIN.top + GRAPH_MARGIN.top +
GRAPH_MARGIN.bottom GRAPH_MARGIN.bottom,
) )
.attr('height', d => { .attr('height', d => {
return R.clamp( return R.clamp(
@ -261,13 +263,13 @@ const Graph = ({ data, machines, currency, selectedMachine }) => {
GRAPH_HEIGHT - GRAPH_HEIGHT -
y(d[1].cashOut) - y(d[1].cashOut) -
GRAPH_MARGIN.bottom - GRAPH_MARGIN.bottom -
BAR_MARGIN / 2 BAR_MARGIN / 2,
) )
}) })
.attr('width', x.bandwidth()) .attr('width', x.bandwidth())
.attr('rx', 2.5) .attr('rx', 2.5)
}, },
[txClassVolumeByDevice, x, y, GRAPH_MARGIN] [txClassVolumeByDevice, x, y, GRAPH_MARGIN],
) )
const drawChart = useCallback(() => { const drawChart = useCallback(() => {
@ -295,7 +297,7 @@ const Graph = ({ data, machines, currency, selectedMachine }) => {
formatTicksText, formatTicksText,
buildGrid, buildGrid,
drawCashIn, drawCashIn,
drawCashOut drawCashOut,
]) ])
useEffect(() => { useEffect(() => {
@ -310,5 +312,5 @@ export default memo(
Graph, Graph,
(prev, next) => (prev, next) =>
R.equals(prev.period, next.period) && R.equals(prev.period, next.period) &&
R.equals(prev.selectedMachine, next.selectedMachine) R.equals(prev.selectedMachine, next.selectedMachine),
) )

View file

@ -1,5 +1,6 @@
.welcomeBackground { .welcomeBackground {
background: var(--ghost) url(/wizard-background.svg) no-repeat fixed center center; background: var(--ghost) url(/wizard-background.svg) no-repeat fixed center
center;
background-size: cover; background-size: cover;
height: 100vh; height: 100vh;
width: 100vw; width: 100vw;
@ -22,7 +23,7 @@
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
margin-bottom: 30px margin-bottom: 30px;
} }
.icon { .icon {
@ -70,4 +71,3 @@
.confirm2FAInput { .confirm2FAInput {
margin-top: 25px; margin-top: 25px;
} }

View file

@ -46,7 +46,7 @@ const Input2FAState = ({ state, dispatch }) => {
onCompleted: ({ userData }) => { onCompleted: ({ userData }) => {
setUserData(userData) setUserData(userData)
history.push('/') history.push('/')
} },
}) })
const [input2FA, { error: mutationError }] = useMutation(INPUT_2FA, { const [input2FA, { error: mutationError }] = useMutation(INPUT_2FA, {
@ -55,15 +55,15 @@ const Input2FAState = ({ state, dispatch }) => {
return getUserData() return getUserData()
} }
return setInvalidToken(true) return setInvalidToken(true)
} },
}) })
const handle2FAChange = value => { const handle2FAChange = value => {
dispatch({ dispatch({
type: STATES.INPUT_2FA, type: STATES.INPUT_2FA,
payload: { payload: {
twoFAField: value twoFAField: value,
} },
}) })
setInvalidToken(false) setInvalidToken(false)
} }
@ -79,8 +79,8 @@ const Input2FAState = ({ state, dispatch }) => {
username: state.clientField, username: state.clientField,
password: state.passwordField, password: state.passwordField,
code: state.twoFAField, code: state.twoFAField,
rememberMe: state.rememberMeField rememberMe: state.rememberMeField,
} },
} }
input2FA(options) input2FA(options)

View file

@ -24,12 +24,12 @@ const validationSchema = Yup.object().shape({
localClient: Yup.string() localClient: Yup.string()
.required('Client field is required!') .required('Client field is required!')
.email('Username field should be in an email format!'), .email('Username field should be in an email format!'),
localRememberMe: Yup.boolean() localRememberMe: Yup.boolean(),
}) })
const initialValues = { const initialValues = {
localClient: '', localClient: '',
localRememberMe: false localRememberMe: false,
} }
const InputFIDOState = ({ state, strategy }) => { const InputFIDOState = ({ state, strategy }) => {
@ -74,8 +74,8 @@ const InputFIDOState = ({ state, strategy }) => {
{ {
onCompleted: ({ validateAssertion: success }) => { onCompleted: ({ validateAssertion: success }) => {
success ? getUserData() : setInvalidToken(true) success ? getUserData() : setInvalidToken(true)
} },
} },
) )
const [assertionOptions, { error: assertionQueryError }] = useLazyQuery( const [assertionOptions, { error: assertionQueryError }] = useLazyQuery(
@ -86,11 +86,11 @@ const InputFIDOState = ({ state, strategy }) => {
? { ? {
username: state.clientField, username: state.clientField,
password: state.passwordField, password: state.passwordField,
domain: window.location.hostname domain: window.location.hostname,
} }
: { : {
username: localClientField, username: localClientField,
domain: window.location.hostname domain: window.location.hostname,
}, },
onCompleted: ({ generateAssertionOptions: options }) => { onCompleted: ({ generateAssertionOptions: options }) => {
startAssertion(options) startAssertion(options)
@ -102,31 +102,31 @@ const InputFIDOState = ({ state, strategy }) => {
password: state.passwordField, password: state.passwordField,
rememberMe: state.rememberMeField, rememberMe: state.rememberMeField,
assertionResponse: res, assertionResponse: res,
domain: window.location.hostname domain: window.location.hostname,
} }
: { : {
username: localClientField, username: localClientField,
rememberMe: localRememberMeField, rememberMe: localRememberMeField,
assertionResponse: res, assertionResponse: res,
domain: window.location.hostname domain: window.location.hostname,
} }
validateAssertion({ validateAssertion({
variables variables,
}) })
}) })
.catch(err => { .catch(err => {
console.error(err) console.error(err)
setInvalidToken(true) setInvalidToken(true)
}) })
} },
} },
) )
const [getUserData, { error: queryError }] = useLazyQuery(GET_USER_DATA, { const [getUserData, { error: queryError }] = useLazyQuery(GET_USER_DATA, {
onCompleted: ({ userData }) => { onCompleted: ({ userData }) => {
setUserData(userData) setUserData(userData)
history.push('/') history.push('/')
} },
}) })
const getErrorMsg = (formikErrors, formikTouched) => { const getErrorMsg = (formikErrors, formikTouched) => {

View file

@ -1,6 +1,5 @@
import Paper from '@mui/material/Paper' import Paper from '@mui/material/Paper'
import React, { useReducer } from 'react' import React, { useReducer } from 'react'
import { H5 } from 'src/components/typography'
import Logo from 'src/styling/icons/menu/logo.svg?react' import Logo from 'src/styling/icons/menu/logo.svg?react'
import Input2FAState from './Input2FAState' import Input2FAState from './Input2FAState'
@ -18,7 +17,7 @@ const initialState = {
clientField: '', clientField: '',
passwordField: '', passwordField: '',
rememberMeField: false, rememberMeField: false,
loginState: STATES.LOGIN loginState: STATES.LOGIN,
} }
const reducer = (state, action) => { const reducer = (state, action) => {

View file

@ -44,13 +44,13 @@ const GET_USER_DATA = gql`
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
email: Yup.string().label('Email').required().email(), email: Yup.string().label('Email').required().email(),
password: Yup.string().required('Password field is required'), password: Yup.string().required('Password field is required'),
rememberMe: Yup.boolean() rememberMe: Yup.boolean(),
}) })
const initialValues = { const initialValues = {
email: '', email: '',
password: '', password: '',
rememberMe: false rememberMe: false,
} }
const getErrorMsg = (formikErrors, formikTouched, mutationError) => { const getErrorMsg = (formikErrors, formikTouched, mutationError) => {
@ -62,7 +62,7 @@ const getErrorMsg = (formikErrors, formikTouched, mutationError) => {
return null return null
} }
const LoginState = ({ state, dispatch, strategy }) => { const LoginState = ({ dispatch, strategy }) => {
const history = useHistory() const history = useHistory()
const { setUserData } = useContext(AppContext) const { setUserData } = useContext(AppContext)
@ -72,8 +72,8 @@ const LoginState = ({ state, dispatch, strategy }) => {
const options = { const options = {
variables: { variables: {
username, username,
password password,
} },
} }
const { data: loginResponse } = await login(options) const { data: loginResponse } = await login(options)
@ -84,16 +84,16 @@ const LoginState = ({ state, dispatch, strategy }) => {
payload: { payload: {
clientField: username, clientField: username,
passwordField: password, passwordField: password,
rememberMeField: rememberMe rememberMeField: rememberMe,
} },
}) })
} }
const [validateAssertion, { error: FIDOMutationError }] = useMutation( const [validateAssertion, { error: FIDOMutationError }] = useMutation(
VALIDATE_ASSERTION, VALIDATE_ASSERTION,
{ {
onCompleted: ({ validateAssertion: success }) => success && getUserData() onCompleted: ({ validateAssertion: success }) => success && getUserData(),
} },
) )
const [assertionOptions, { error: assertionQueryError }] = useLazyQuery( const [assertionOptions, { error: assertionQueryError }] = useLazyQuery(
@ -105,15 +105,15 @@ const LoginState = ({ state, dispatch, strategy }) => {
validateAssertion({ validateAssertion({
variables: { variables: {
assertionResponse: res, assertionResponse: res,
domain: window.location.hostname domain: window.location.hostname,
} },
}) })
}) })
.catch(err => { .catch(err => {
console.error(err) console.error(err)
}) })
} },
} },
) )
const [getUserData, { error: userDataQueryError }] = useLazyQuery( const [getUserData, { error: userDataQueryError }] = useLazyQuery(
@ -122,8 +122,8 @@ const LoginState = ({ state, dispatch, strategy }) => {
onCompleted: ({ userData }) => { onCompleted: ({ userData }) => {
setUserData(userData) setUserData(userData)
history.push('/') history.push('/')
} },
} },
) )
return ( return (
@ -149,7 +149,7 @@ const LoginState = ({ state, dispatch, strategy }) => {
loginMutationError || loginMutationError ||
FIDOMutationError || FIDOMutationError ||
assertionQueryError || assertionQueryError ||
userDataQueryError userDataQueryError,
)} )}
/> />
<Field <Field
@ -164,7 +164,7 @@ const LoginState = ({ state, dispatch, strategy }) => {
loginMutationError || loginMutationError ||
FIDOMutationError || FIDOMutationError ||
assertionQueryError || assertionQueryError ||
userDataQueryError userDataQueryError,
)} )}
/> />
<div className="mt-9 flex"> <div className="mt-9 flex">
@ -183,7 +183,7 @@ const LoginState = ({ state, dispatch, strategy }) => {
loginMutationError || loginMutationError ||
FIDOMutationError || FIDOMutationError ||
assertionQueryError || assertionQueryError ||
userDataQueryError userDataQueryError,
) && ( ) && (
<P className="text-tomato"> <P className="text-tomato">
{getErrorMsg( {getErrorMsg(
@ -192,7 +192,7 @@ const LoginState = ({ state, dispatch, strategy }) => {
loginMutationError || loginMutationError ||
FIDOMutationError || FIDOMutationError ||
assertionQueryError || assertionQueryError ||
userDataQueryError userDataQueryError,
)} )}
</P> </P>
)} )}
@ -202,11 +202,11 @@ const LoginState = ({ state, dispatch, strategy }) => {
onClick={() => { onClick={() => {
return strategy === 'FIDOUsernameless' return strategy === 'FIDOUsernameless'
? assertionOptions({ ? assertionOptions({
variables: { domain: window.location.hostname } variables: { domain: window.location.hostname },
}) })
: dispatch({ : dispatch({
type: 'FIDO', type: 'FIDO',
payload: {} payload: {},
}) })
}} }}
buttonClassName="w-full" buttonClassName="w-full"

Some files were not shown because too many files have changed in this diff Show more