chore: prettier config
husky needs to be delegated to v11 since it breaks with node 14 + 22 combo
This commit is contained in:
parent
dbca0c8a8c
commit
d3c3de66fe
65 changed files with 1542 additions and 22553 deletions
8
new-lamassu-admin/.prettierrc
Normal file
8
new-lamassu-admin/.prettierrc
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"trailingComma": "none",
|
||||||
|
"tabWidth": 2,
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": true,
|
||||||
|
"arrowParens": "avoid",
|
||||||
|
"bracketSameLine": true
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@ import globals from 'globals'
|
||||||
import pluginJs from '@eslint/js'
|
import pluginJs from '@eslint/js'
|
||||||
import pluginReact from 'eslint-plugin-react'
|
import pluginReact from 'eslint-plugin-react'
|
||||||
import reactCompiler from 'eslint-plugin-react-compiler'
|
import reactCompiler from 'eslint-plugin-react-compiler'
|
||||||
|
import eslintConfigPrettier from 'eslint-config-prettier'
|
||||||
|
|
||||||
/** @type {import('eslint').Linter.Config[]} */
|
/** @type {import('eslint').Linter.Config[]} */
|
||||||
export default [
|
export default [
|
||||||
|
|
@ -17,7 +18,7 @@ export default [
|
||||||
settings: {
|
settings: {
|
||||||
react: {
|
react: {
|
||||||
version: '16'
|
version: '16'
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
plugins: {
|
plugins: {
|
||||||
'react-compiler': reactCompiler
|
'react-compiler': reactCompiler
|
||||||
|
|
@ -31,7 +32,8 @@ export default [
|
||||||
'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',
|
||||||
'react-compiler/react-compiler': 'warn',
|
'react-compiler/react-compiler': 'warn'
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
]
|
eslintConfigPrettier
|
||||||
|
]
|
||||||
|
|
|
||||||
22074
new-lamassu-admin/package-lock.json
generated
22074
new-lamassu-admin/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -56,26 +56,19 @@
|
||||||
"@vitejs/plugin-react-swc": "^3.7.2",
|
"@vitejs/plugin-react-swc": "^3.7.2",
|
||||||
"esbuild-plugin-react-virtualized": "^1.0.4",
|
"esbuild-plugin-react-virtualized": "^1.0.4",
|
||||||
"eslint": "^9.16.0",
|
"eslint": "^9.16.0",
|
||||||
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-react": "^7.37.2",
|
"eslint-plugin-react": "^7.37.2",
|
||||||
"eslint-plugin-react-compiler": "^19.0.0-beta-df7b47d-20241124",
|
"eslint-plugin-react-compiler": "^19.0.0-beta-df7b47d-20241124",
|
||||||
"globals": "^15.13.0",
|
"globals": "^15.13.0",
|
||||||
"husky": "^3.1.0",
|
"lint-staged": "^15.2.10",
|
||||||
"lint-staged": "^9.5.0",
|
"prettier": "3.4.1",
|
||||||
"react-scripts": "4.0.0",
|
|
||||||
"vite": "^6.0.1",
|
"vite": "^6.0.1",
|
||||||
"vite-plugin-svgr": "^4.3.0"
|
"vite-plugin-svgr": "^4.3.0"
|
||||||
},
|
},
|
||||||
"lint-staged": {
|
|
||||||
"src/**/*.{js,jsx,ts,tsx,json,css,scss,md}": [
|
|
||||||
"eslint --fix",
|
|
||||||
"git add"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "vite",
|
"start": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview"
|
||||||
"fix": "eslint --fix --ext .js,.md,.json src/"
|
|
||||||
},
|
},
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
"production": [
|
"production": [
|
||||||
|
|
@ -88,5 +81,9 @@
|
||||||
"last 1 firefox version",
|
"last 1 firefox version",
|
||||||
"last 1 safari version"
|
"last 1 safari version"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"lint-staged": {
|
||||||
|
"*.{js,jsx,md,json}": "eslint --cache --fix",
|
||||||
|
"*.{js,jsx,css,md,json}": "prettier --write"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -115,15 +115,10 @@ const Main = () => {
|
||||||
)}
|
)}
|
||||||
<main className={classes.wrapper}>
|
<main className={classes.wrapper}>
|
||||||
{sidebar && !is404 && wizardTested && (
|
{sidebar && !is404 && wizardTested && (
|
||||||
<Slide
|
<Slide direction="left" in={true} mountOnEnter unmountOnExit>
|
||||||
direction="left"
|
<div>
|
||||||
in={true}
|
<TitleSection title={parent.title}></TitleSection>
|
||||||
mountOnEnter
|
</div>
|
||||||
unmountOnExit
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<TitleSection title={parent.title}></TitleSection>
|
|
||||||
</div>
|
|
||||||
</Slide>
|
</Slide>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,98 +1,98 @@
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogActions,
|
DialogActions,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
makeStyles
|
makeStyles
|
||||||
} from '@material-ui/core'
|
} from '@material-ui/core'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { H4, P } from 'src/components/typography'
|
import { H4, P } 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'
|
||||||
|
|
||||||
import { Button, IconButton } from 'src/components/buttons'
|
import { Button, IconButton } from 'src/components/buttons'
|
||||||
import { spacer } from 'src/styling/variables'
|
import { spacer } from 'src/styling/variables'
|
||||||
|
|
||||||
import ErrorMessage from './ErrorMessage'
|
import ErrorMessage from './ErrorMessage'
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
const useStyles = makeStyles({
|
||||||
content: {
|
content: {
|
||||||
width: 434,
|
width: 434,
|
||||||
padding: spacer * 2,
|
padding: spacer * 2,
|
||||||
paddingRight: spacer * 3.5
|
paddingRight: spacer * 3.5
|
||||||
},
|
},
|
||||||
titleSection: {
|
titleSection: {
|
||||||
padding: spacer * 2,
|
padding: spacer * 2,
|
||||||
paddingRight: spacer * 1.5,
|
paddingRight: spacer * 1.5,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
margin: 0
|
margin: 0
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
padding: spacer * 4,
|
padding: spacer * 4,
|
||||||
paddingTop: spacer * 2
|
paddingTop: spacer * 2
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
margin: 0
|
margin: 0
|
||||||
},
|
},
|
||||||
closeButton: {
|
closeButton: {
|
||||||
padding: 0,
|
padding: 0,
|
||||||
marginTop: -(spacer / 2)
|
marginTop: -(spacer / 2)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export const DialogTitle = ({ children, close }) => {
|
export const DialogTitle = ({ children, close }) => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
return (
|
return (
|
||||||
<div className={classes.titleSection}>
|
<div className={classes.titleSection}>
|
||||||
{children}
|
{children}
|
||||||
{close && (
|
{close && (
|
||||||
<IconButton
|
<IconButton
|
||||||
size={16}
|
size={16}
|
||||||
aria-label="close"
|
aria-label="close"
|
||||||
onClick={close}
|
onClick={close}
|
||||||
className={classes.closeButton}>
|
className={classes.closeButton}>
|
||||||
<CloseIcon />
|
<CloseIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DeleteDialog = ({
|
export const DeleteDialog = ({
|
||||||
title = 'Confirm Delete',
|
title = 'Confirm Delete',
|
||||||
open = false,
|
open = false,
|
||||||
onConfirmed,
|
onConfirmed,
|
||||||
onDismissed,
|
onDismissed,
|
||||||
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 = ''
|
||||||
}) => {
|
}) => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={open} aria-labelledby="form-dialog-title">
|
<Dialog open={open} aria-labelledby="form-dialog-title">
|
||||||
<DialogTitle close={() => onDismissed()}>
|
<DialogTitle close={() => onDismissed()}>
|
||||||
<H4 className={classes.title}>{title}</H4>
|
<H4 className={classes.title}>{title}</H4>
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
{errorMessage && (
|
{errorMessage && (
|
||||||
<DialogTitle>
|
<DialogTitle>
|
||||||
<ErrorMessage>
|
<ErrorMessage>
|
||||||
{errorMessage.split(':').map(error => (
|
{errorMessage.split(':').map(error => (
|
||||||
<>
|
<>
|
||||||
{error}
|
{error}
|
||||||
<br />
|
<br />
|
||||||
</>
|
</>
|
||||||
))}
|
))}
|
||||||
</ErrorMessage>
|
</ErrorMessage>
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
)}
|
)}
|
||||||
<DialogContent className={classes.content}>
|
<DialogContent className={classes.content}>
|
||||||
{confirmationMessage && <P>{confirmationMessage}</P>}
|
{confirmationMessage && <P>{confirmationMessage}</P>}
|
||||||
{extraMessage}
|
{extraMessage}
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions className={classes.actions}>
|
<DialogActions className={classes.actions}>
|
||||||
<Button onClick={onConfirmed}>Confirm</Button>
|
<Button onClick={onConfirmed}>Confirm</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,8 +55,8 @@ const styles = {
|
||||||
margin: xl
|
margin: xl
|
||||||
? [[0, 0, 'auto', 'auto']]
|
? [[0, 0, 'auto', 'auto']]
|
||||||
: small
|
: small
|
||||||
? [[12, 12, 'auto', 'auto']]
|
? [[12, 12, 'auto', 'auto']]
|
||||||
: [[16, 16, 'auto', 'auto']]
|
: [[16, 16, 'auto', 'auto']]
|
||||||
}),
|
}),
|
||||||
header: {
|
header: {
|
||||||
display: 'flex'
|
display: 'flex'
|
||||||
|
|
|
||||||
|
|
@ -60,8 +60,8 @@ const NotificationRow = ({
|
||||||
typeDisplay && deviceName
|
typeDisplay && deviceName
|
||||||
? `${typeDisplay} - ${deviceName}`
|
? `${typeDisplay} - ${deviceName}`
|
||||||
: !typeDisplay && deviceName
|
: !typeDisplay && deviceName
|
||||||
? `${deviceName}`
|
? `${deviceName}`
|
||||||
: `${typeDisplay}`
|
: `${typeDisplay}`
|
||||||
|
|
||||||
const iconClass = {
|
const iconClass = {
|
||||||
[classes.readIcon]: read,
|
[classes.readIcon]: read,
|
||||||
|
|
|
||||||
|
|
@ -1,299 +1,299 @@
|
||||||
import { makeStyles } from '@material-ui/core'
|
import { makeStyles } from '@material-ui/core'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import { Field, useFormikContext } from 'formik'
|
import { Field, useFormikContext } from 'formik'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useContext, useState } from 'react'
|
import React, { useContext, useState } from 'react'
|
||||||
import { DeleteDialog } from 'src/components/DeleteDialog'
|
import { DeleteDialog } from 'src/components/DeleteDialog'
|
||||||
import { Td, Tr } from 'src/components/fake-table/Table'
|
import { Td, Tr } from 'src/components/fake-table/Table'
|
||||||
import { Label2 } from 'src/components/typography'
|
import { Label2 } from 'src/components/typography'
|
||||||
import DisabledDeleteIcon from 'src/styling/icons/action/delete/disabled.svg?react'
|
import DisabledDeleteIcon from 'src/styling/icons/action/delete/disabled.svg?react'
|
||||||
import DeleteIcon from 'src/styling/icons/action/delete/enabled.svg?react'
|
import DeleteIcon from 'src/styling/icons/action/delete/enabled.svg?react'
|
||||||
import DisabledEditIcon from 'src/styling/icons/action/edit/disabled.svg?react'
|
import DisabledEditIcon from 'src/styling/icons/action/edit/disabled.svg?react'
|
||||||
import EditIcon from 'src/styling/icons/action/edit/enabled.svg?react'
|
import EditIcon from 'src/styling/icons/action/edit/enabled.svg?react'
|
||||||
import StripesSvg from 'src/styling/icons/stripes.svg?react'
|
import StripesSvg from 'src/styling/icons/stripes.svg?react'
|
||||||
|
|
||||||
import { Link, IconButton } from 'src/components/buttons'
|
import { Link, IconButton } from 'src/components/buttons'
|
||||||
import { Switch } from 'src/components/inputs'
|
import { Switch } from 'src/components/inputs'
|
||||||
|
|
||||||
import TableCtx from './Context'
|
import TableCtx from './Context'
|
||||||
import styles from './Row.styles'
|
import styles from './Row.styles'
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
const useStyles = makeStyles(styles)
|
||||||
|
|
||||||
const ActionCol = ({ disabled, editing }) => {
|
const ActionCol = ({ disabled, editing }) => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const { values, submitForm, resetForm } = useFormikContext()
|
const { values, submitForm, resetForm } = useFormikContext()
|
||||||
const {
|
const {
|
||||||
editWidth,
|
editWidth,
|
||||||
onEdit,
|
onEdit,
|
||||||
enableEdit,
|
enableEdit,
|
||||||
enableDelete,
|
enableDelete,
|
||||||
disableRowEdit,
|
disableRowEdit,
|
||||||
onDelete,
|
onDelete,
|
||||||
deleteWidth,
|
deleteWidth,
|
||||||
enableToggle,
|
enableToggle,
|
||||||
onToggle,
|
onToggle,
|
||||||
toggleWidth,
|
toggleWidth,
|
||||||
forceAdd,
|
forceAdd,
|
||||||
clearError,
|
clearError,
|
||||||
actionColSize,
|
actionColSize,
|
||||||
error
|
error
|
||||||
} = useContext(TableCtx)
|
} = useContext(TableCtx)
|
||||||
|
|
||||||
const disableEdit = disabled || (disableRowEdit && disableRowEdit(values))
|
const disableEdit = disabled || (disableRowEdit && disableRowEdit(values))
|
||||||
const cancel = () => {
|
const cancel = () => {
|
||||||
clearError()
|
clearError()
|
||||||
resetForm()
|
resetForm()
|
||||||
}
|
}
|
||||||
|
|
||||||
const [deleteDialog, setDeleteDialog] = useState(false)
|
const [deleteDialog, setDeleteDialog] = useState(false)
|
||||||
|
|
||||||
const onConfirmed = () => {
|
const onConfirmed = () => {
|
||||||
onDelete(values.id).then(res => {
|
onDelete(values.id).then(res => {
|
||||||
if (!R.isNil(res)) setDeleteDialog(false)
|
if (!R.isNil(res)) setDeleteDialog(false)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{editing && (
|
{editing && (
|
||||||
<Td textAlign="center" width={actionColSize}>
|
<Td textAlign="center" width={actionColSize}>
|
||||||
<Link
|
<Link
|
||||||
className={classes.saveButton}
|
className={classes.saveButton}
|
||||||
type="submit"
|
type="submit"
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={submitForm}>
|
onClick={submitForm}>
|
||||||
Save
|
Save
|
||||||
</Link>
|
</Link>
|
||||||
{!forceAdd && (
|
{!forceAdd && (
|
||||||
<Link color="secondary" onClick={cancel}>
|
<Link color="secondary" onClick={cancel}>
|
||||||
Cancel
|
Cancel
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
</Td>
|
</Td>
|
||||||
)}
|
)}
|
||||||
{!editing && enableEdit && (
|
{!editing && enableEdit && (
|
||||||
<Td textAlign="center" width={editWidth}>
|
<Td textAlign="center" width={editWidth}>
|
||||||
<IconButton
|
<IconButton
|
||||||
disabled={disableEdit}
|
disabled={disableEdit}
|
||||||
className={classes.editButton}
|
className={classes.editButton}
|
||||||
onClick={() => onEdit && onEdit(values.id)}>
|
onClick={() => onEdit && onEdit(values.id)}>
|
||||||
{disableEdit ? <DisabledEditIcon /> : <EditIcon />}
|
{disableEdit ? <DisabledEditIcon /> : <EditIcon />}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Td>
|
</Td>
|
||||||
)}
|
)}
|
||||||
{!editing && enableDelete && (
|
{!editing && enableDelete && (
|
||||||
<Td textAlign="center" width={deleteWidth}>
|
<Td textAlign="center" width={deleteWidth}>
|
||||||
<IconButton
|
<IconButton
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setDeleteDialog(true)
|
setDeleteDialog(true)
|
||||||
}}>
|
}}>
|
||||||
{disabled ? <DisabledDeleteIcon /> : <DeleteIcon />}
|
{disabled ? <DisabledDeleteIcon /> : <DeleteIcon />}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<DeleteDialog
|
<DeleteDialog
|
||||||
open={deleteDialog}
|
open={deleteDialog}
|
||||||
setDeleteDialog={setDeleteDialog}
|
setDeleteDialog={setDeleteDialog}
|
||||||
onConfirmed={onConfirmed}
|
onConfirmed={onConfirmed}
|
||||||
onDismissed={() => {
|
onDismissed={() => {
|
||||||
setDeleteDialog(false)
|
setDeleteDialog(false)
|
||||||
clearError()
|
clearError()
|
||||||
}}
|
}}
|
||||||
errorMessage={error}
|
errorMessage={error}
|
||||||
/>
|
/>
|
||||||
</Td>
|
</Td>
|
||||||
)}
|
)}
|
||||||
{!editing && enableToggle && (
|
{!editing && enableToggle && (
|
||||||
<Td textAlign="center" width={toggleWidth}>
|
<Td textAlign="center" width={toggleWidth}>
|
||||||
<Switch
|
<Switch
|
||||||
checked={!!values.active}
|
checked={!!values.active}
|
||||||
value={!!values.active}
|
value={!!values.active}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onChange={() => onToggle(values.id)}
|
onChange={() => onToggle(values.id)}
|
||||||
/>
|
/>
|
||||||
</Td>
|
</Td>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
|
const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
|
||||||
const {
|
const {
|
||||||
name,
|
name,
|
||||||
names,
|
names,
|
||||||
bypassField,
|
bypassField,
|
||||||
input,
|
input,
|
||||||
editable = true,
|
editable = true,
|
||||||
size,
|
size,
|
||||||
bold,
|
bold,
|
||||||
width,
|
width,
|
||||||
textAlign,
|
textAlign,
|
||||||
editingAlign = textAlign,
|
editingAlign = textAlign,
|
||||||
prefix,
|
prefix,
|
||||||
PrefixComponent = Label2,
|
PrefixComponent = Label2,
|
||||||
suffix,
|
suffix,
|
||||||
SuffixComponent = Label2,
|
SuffixComponent = Label2,
|
||||||
textStyle = it => {},
|
textStyle = it => {},
|
||||||
isHidden = it => false,
|
isHidden = it => false,
|
||||||
view = it => it?.toString(),
|
view = it => it?.toString(),
|
||||||
inputProps = {}
|
inputProps = {}
|
||||||
} = config
|
} = config
|
||||||
|
|
||||||
const fields = names ?? [name]
|
const fields = names ?? [name]
|
||||||
|
|
||||||
const { values } = useFormikContext()
|
const { values } = useFormikContext()
|
||||||
const isEditable = editable => {
|
const isEditable = editable => {
|
||||||
if (typeof editable === 'function') return editable(values)
|
if (typeof editable === 'function') return editable(values)
|
||||||
return editable
|
return editable
|
||||||
}
|
}
|
||||||
const isEditing = editing && isEditable(editable)
|
const isEditing = editing && isEditable(editable)
|
||||||
const isField = !bypassField
|
const isField = !bypassField
|
||||||
|
|
||||||
const classes = useStyles({
|
const classes = useStyles({
|
||||||
textAlign: isEditing ? editingAlign : textAlign,
|
textAlign: isEditing ? editingAlign : textAlign,
|
||||||
size
|
size
|
||||||
})
|
})
|
||||||
|
|
||||||
const innerProps = {
|
const innerProps = {
|
||||||
fullWidth: true,
|
fullWidth: true,
|
||||||
autoFocus: focus,
|
autoFocus: focus,
|
||||||
size,
|
size,
|
||||||
bold,
|
bold,
|
||||||
textAlign: isEditing ? editingAlign : textAlign,
|
textAlign: isEditing ? editingAlign : textAlign,
|
||||||
...inputProps
|
...inputProps
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.fields}>
|
<div className={classes.fields}>
|
||||||
{fields.map((f, idx) => (
|
{fields.map((f, idx) => (
|
||||||
<Td
|
<Td
|
||||||
key={idx}
|
key={idx}
|
||||||
className={{
|
className={{
|
||||||
[classes.extraPaddingRight]: extraPaddingRight,
|
[classes.extraPaddingRight]: extraPaddingRight,
|
||||||
[classes.extraPadding]: extraPadding,
|
[classes.extraPadding]: extraPadding,
|
||||||
[classes.withSuffix]: suffix,
|
[classes.withSuffix]: suffix,
|
||||||
[classes.withPrefix]: prefix
|
[classes.withPrefix]: prefix
|
||||||
}}
|
}}
|
||||||
width={width}
|
width={width}
|
||||||
size={size}
|
size={size}
|
||||||
bold={bold}
|
bold={bold}
|
||||||
textAlign={textAlign}>
|
textAlign={textAlign}>
|
||||||
{prefix && !isHidden(values) && (
|
{prefix && !isHidden(values) && (
|
||||||
<PrefixComponent
|
<PrefixComponent
|
||||||
className={classes.prefix}
|
className={classes.prefix}
|
||||||
style={isEditing ? {} : textStyle(values, isEditing)}>
|
style={isEditing ? {} : textStyle(values, isEditing)}>
|
||||||
{typeof prefix === 'function' ? prefix(f) : prefix}
|
{typeof prefix === 'function' ? prefix(f) : prefix}
|
||||||
</PrefixComponent>
|
</PrefixComponent>
|
||||||
)}
|
)}
|
||||||
{isEditing && isField && !isHidden(values) && (
|
{isEditing && isField && !isHidden(values) && (
|
||||||
<Field name={f} component={input} {...innerProps} />
|
<Field name={f} component={input} {...innerProps} />
|
||||||
)}
|
)}
|
||||||
{isEditing && !isField && !isHidden(values) && (
|
{isEditing && !isField && !isHidden(values) && (
|
||||||
<config.input name={f} />
|
<config.input name={f} />
|
||||||
)}
|
)}
|
||||||
{!isEditing && values && !isHidden(values) && (
|
{!isEditing && values && !isHidden(values) && (
|
||||||
<div style={textStyle(values, isEditing)}>
|
<div style={textStyle(values, isEditing)}>
|
||||||
{view(values[f], values)}
|
{view(values[f], values)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{suffix && !isHidden(values) && (
|
{suffix && !isHidden(values) && (
|
||||||
<SuffixComponent
|
<SuffixComponent
|
||||||
className={classes.suffix}
|
className={classes.suffix}
|
||||||
style={isEditing ? {} : textStyle(values, isEditing)}>
|
style={isEditing ? {} : textStyle(values, isEditing)}>
|
||||||
{suffix}
|
{suffix}
|
||||||
</SuffixComponent>
|
</SuffixComponent>
|
||||||
)}
|
)}
|
||||||
{isHidden(values) && <StripesSvg />}
|
{isHidden(values) && <StripesSvg />}
|
||||||
</Td>
|
</Td>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const groupStriped = elements => {
|
const groupStriped = elements => {
|
||||||
const [toStripe, noStripe] = R.partition(R.propEq('stripe', true))(elements)
|
const [toStripe, noStripe] = R.partition(R.propEq('stripe', true))(elements)
|
||||||
|
|
||||||
if (!toStripe.length) {
|
if (!toStripe.length) {
|
||||||
return elements
|
return elements
|
||||||
}
|
}
|
||||||
|
|
||||||
const index = R.indexOf(toStripe[0], elements)
|
const index = R.indexOf(toStripe[0], elements)
|
||||||
const width = R.compose(R.sum, R.map(R.path(['width'])))(toStripe)
|
const width = R.compose(R.sum, R.map(R.path(['width'])))(toStripe)
|
||||||
|
|
||||||
return R.insert(
|
return R.insert(
|
||||||
index,
|
index,
|
||||||
{ width, editable: false, view: () => <StripesSvg /> },
|
{ width, editable: false, view: () => <StripesSvg /> },
|
||||||
noStripe
|
noStripe
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const ERow = ({ editing, disabled, lastOfGroup, newRow }) => {
|
const ERow = ({ editing, disabled, lastOfGroup, newRow }) => {
|
||||||
const { touched, errors, values } = useFormikContext()
|
const { touched, errors, values } = useFormikContext()
|
||||||
const {
|
const {
|
||||||
elements,
|
elements,
|
||||||
enableEdit,
|
enableEdit,
|
||||||
enableDelete,
|
enableDelete,
|
||||||
error,
|
error,
|
||||||
enableToggle,
|
enableToggle,
|
||||||
rowSize,
|
rowSize,
|
||||||
stripeWhen
|
stripeWhen
|
||||||
} = useContext(TableCtx)
|
} = useContext(TableCtx)
|
||||||
|
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
|
|
||||||
const shouldStripe = !editing && stripeWhen && stripeWhen(values)
|
const shouldStripe = !editing && stripeWhen && stripeWhen(values)
|
||||||
|
|
||||||
const innerElements = shouldStripe ? groupStriped(elements) : elements
|
const innerElements = shouldStripe ? groupStriped(elements) : elements
|
||||||
const [toSHeader] = R.partition(R.has('doubleHeader'))(elements)
|
const [toSHeader] = R.partition(R.has('doubleHeader'))(elements)
|
||||||
|
|
||||||
const extraPaddingIndex = toSHeader?.length
|
const extraPaddingIndex = toSHeader?.length
|
||||||
? R.indexOf(toSHeader[0], elements)
|
? R.indexOf(toSHeader[0], elements)
|
||||||
: -1
|
: -1
|
||||||
|
|
||||||
const extraPaddingRightIndex = toSHeader?.length
|
const extraPaddingRightIndex = toSHeader?.length
|
||||||
? R.indexOf(toSHeader[toSHeader.length - 1], elements)
|
? R.indexOf(toSHeader[toSHeader.length - 1], elements)
|
||||||
: -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 = {
|
||||||
[classes.lastOfGroup]: lastOfGroup
|
[classes.lastOfGroup]: lastOfGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
const touchedErrors = R.pick(R.keys(touched), errors)
|
const touchedErrors = R.pick(R.keys(touched), errors)
|
||||||
const hasTouchedErrors = touchedErrors && R.keys(touchedErrors).length > 0
|
const hasTouchedErrors = touchedErrors && R.keys(touchedErrors).length > 0
|
||||||
const hasErrors = hasTouchedErrors || !!error
|
const hasErrors = hasTouchedErrors || !!error
|
||||||
|
|
||||||
const errorMessage =
|
const errorMessage =
|
||||||
error || (touchedErrors && R.values(touchedErrors).join(', '))
|
error || (touchedErrors && R.values(touchedErrors).join(', '))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tr
|
<Tr
|
||||||
className={classnames(classNames)}
|
className={classnames(classNames)}
|
||||||
size={rowSize}
|
size={rowSize}
|
||||||
error={editing && hasErrors}
|
error={editing && hasErrors}
|
||||||
newRow={newRow && !hasErrors}
|
newRow={newRow && !hasErrors}
|
||||||
shouldShowError
|
shouldShowError
|
||||||
errorMessage={errorMessage}>
|
errorMessage={errorMessage}>
|
||||||
{innerElements.map((it, idx) => {
|
{innerElements.map((it, idx) => {
|
||||||
return (
|
return (
|
||||||
<ECol
|
<ECol
|
||||||
key={idx}
|
key={idx}
|
||||||
config={it}
|
config={it}
|
||||||
editing={editing}
|
editing={editing}
|
||||||
focus={idx === elementToFocusIndex && editing}
|
focus={idx === elementToFocusIndex && editing}
|
||||||
extraPaddingRight={extraPaddingRightIndex === idx}
|
extraPaddingRight={extraPaddingRightIndex === idx}
|
||||||
extraPadding={extraPaddingIndex === idx}
|
extraPadding={extraPaddingIndex === idx}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
{(enableEdit || enableDelete || enableToggle) && (
|
{(enableEdit || enableDelete || enableToggle) && (
|
||||||
<ActionCol disabled={disabled} editing={editing} />
|
<ActionCol disabled={disabled} editing={editing} />
|
||||||
)}
|
)}
|
||||||
</Tr>
|
</Tr>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ERow
|
export default ERow
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ const ETable = ({
|
||||||
|
|
||||||
setSaving(true)
|
setSaving(true)
|
||||||
|
|
||||||
const it = validationSchema.cast(value, { assert: 'ignore-optionality'})
|
const it = validationSchema.cast(value, { assert: 'ignore-optionality' })
|
||||||
const index = R.findIndex(R.propEq('id', it.id))(data)
|
const index = R.findIndex(R.propEq('id', it.id))(data)
|
||||||
const list = index !== -1 ? R.update(index, it, data) : R.prepend(it, data)
|
const list = index !== -1 ? R.update(index, it, data) : R.prepend(it, data)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ import { styles } from './TextInput.styles'
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
const useStyles = makeStyles(styles)
|
||||||
|
|
||||||
const mask = /(\+)(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)(\d{1,3}){0,1}(\d{1,3}){0,1}(\d{1,3}){0,1}(\d{1,3}){0,1}(\d{1,2}){0,1}$/
|
const mask =
|
||||||
|
/(\+)(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)(\d{1,3}){0,1}(\d{1,3}){0,1}(\d{1,3}){0,1}(\d{1,3}){0,1}(\d{1,2}){0,1}$/
|
||||||
const maskValue = value =>
|
const maskValue = value =>
|
||||||
value ? value.replace(mask, '$1 $2 $3 $4 $5 $6') : ''
|
value ? value.replace(mask, '$1 $2 $3 $4 $5 $6') : ''
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,24 @@
|
||||||
import React, { memo } from 'react'
|
import React, { memo } from 'react'
|
||||||
|
|
||||||
import { SecretInput } from '../base'
|
import { SecretInput } from '../base'
|
||||||
|
|
||||||
const SecretInputFormik = memo(({ isPasswordFilled, ...props }) => {
|
const SecretInputFormik = memo(({ isPasswordFilled, ...props }) => {
|
||||||
const { name, onChange, onBlur, value } = props.field
|
const { name, onChange, onBlur, value } = props.field
|
||||||
const { touched, errors } = props.form
|
const { touched, errors } = props.form
|
||||||
|
|
||||||
const error = !isPasswordFilled && !!(touched[name] && errors[name])
|
const error = !isPasswordFilled && !!(touched[name] && errors[name])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SecretInput
|
<SecretInput
|
||||||
name={name}
|
name={name}
|
||||||
isPasswordFilled={isPasswordFilled}
|
isPasswordFilled={isPasswordFilled}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
onBlur={onBlur}
|
onBlur={onBlur}
|
||||||
value={value}
|
value={value}
|
||||||
error={error}
|
error={error}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
export default SecretInputFormik
|
export default SecretInputFormik
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,9 @@ const Header = memo(({ tree, user }) => {
|
||||||
className={classnames(classes.link, classes.whiteLink)}
|
className={classnames(classes.link, classes.whiteLink)}
|
||||||
activeClassName={classes.activeLink}>
|
activeClassName={classes.activeLink}>
|
||||||
<li className={classes.li}>
|
<li className={classes.li}>
|
||||||
<span className={classes.forceSize} data-forcesize={it.label}>
|
<span
|
||||||
|
className={classes.forceSize}
|
||||||
|
data-forcesize={it.label}>
|
||||||
{it.label}
|
{it.label}
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,10 @@ const Sidebar = ({
|
||||||
{loading && <P>Loading...</P>}
|
{loading && <P>Loading...</P>}
|
||||||
{!loading &&
|
{!loading &&
|
||||||
data?.map((it, idx) => (
|
data?.map((it, idx) => (
|
||||||
<div key={idx} className={classes.linkWrapper} onClick={() => onClick(it)}>
|
<div
|
||||||
|
key={idx}
|
||||||
|
className={classes.linkWrapper}
|
||||||
|
onClick={() => onClick(it)}>
|
||||||
<div
|
<div
|
||||||
key={idx}
|
key={idx}
|
||||||
className={classnames({
|
className={classnames({
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,6 @@ const Graph = ({
|
||||||
|
|
||||||
const step = R.clone(start)
|
const step = R.clone(start)
|
||||||
|
|
||||||
|
|
||||||
while (step <= end) {
|
while (step <= end) {
|
||||||
ticks.push(R.clone(step))
|
ticks.push(R.clone(step))
|
||||||
step.setUTCHours(step.getUTCHours() + interval)
|
step.setUTCHours(step.getUTCHours() + interval)
|
||||||
|
|
@ -105,19 +104,25 @@ const Graph = ({
|
||||||
])
|
])
|
||||||
.rangeRound([GRAPH_MARGIN.left, GRAPH_WIDTH - GRAPH_MARGIN.right])
|
.rangeRound([GRAPH_MARGIN.left, GRAPH_WIDTH - GRAPH_MARGIN.right])
|
||||||
|
|
||||||
const groupedByDateInterval = R.map(it => {
|
const groupedByDateInterval = R.map(
|
||||||
const lowerBound = R.clone(it)
|
it => {
|
||||||
it.setUTCHours(it.getUTCHours() + 2)
|
const lowerBound = R.clone(it)
|
||||||
const upperBound = R.clone(it)
|
it.setUTCHours(it.getUTCHours() + 2)
|
||||||
return [lowerBound, filterByHourInterval(lowerBound, upperBound)]
|
const upperBound = R.clone(it)
|
||||||
}, R.init(getTickIntervals(x.domain(), 2)))
|
return [lowerBound, filterByHourInterval(lowerBound, upperBound)]
|
||||||
|
},
|
||||||
|
R.init(getTickIntervals(x.domain(), 2))
|
||||||
|
)
|
||||||
|
|
||||||
const groupedByTxClass = R.map(it => {
|
const groupedByTxClass = R.map(
|
||||||
const lowerBound = R.clone(it)
|
it => {
|
||||||
it.setUTCHours(it.getUTCHours() + 2)
|
const lowerBound = R.clone(it)
|
||||||
const upperBound = R.clone(it)
|
it.setUTCHours(it.getUTCHours() + 2)
|
||||||
return [lowerBound, txClassByHourInterval(lowerBound, upperBound)]
|
const upperBound = R.clone(it)
|
||||||
}, R.init(getTickIntervals(x.domain(), 2)))
|
return [lowerBound, txClassByHourInterval(lowerBound, upperBound)]
|
||||||
|
},
|
||||||
|
R.init(getTickIntervals(x.domain(), 2))
|
||||||
|
)
|
||||||
|
|
||||||
const y = d3
|
const y = d3
|
||||||
.scaleLinear()
|
.scaleLinear()
|
||||||
|
|
@ -416,9 +421,7 @@ const Graph = ({
|
||||||
])
|
])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
d3.select(ref.current)
|
d3.select(ref.current).selectAll('*').remove()
|
||||||
.selectAll('*')
|
|
||||||
.remove()
|
|
||||||
drawChart()
|
drawChart()
|
||||||
}, [drawChart])
|
}, [drawChart])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -404,10 +404,7 @@ const Graph = ({
|
||||||
)
|
)
|
||||||
// Left side breakpoint label
|
// Left side breakpoint label
|
||||||
.call(g => {
|
.call(g => {
|
||||||
const separator = d3
|
const separator = d3?.select('.dateSeparator')?.node()?.getBBox()
|
||||||
?.select('.dateSeparator')
|
|
||||||
?.node()
|
|
||||||
?.getBBox()
|
|
||||||
|
|
||||||
if (!separator) return
|
if (!separator) return
|
||||||
|
|
||||||
|
|
@ -428,10 +425,7 @@ const Graph = ({
|
||||||
})
|
})
|
||||||
// Right side breakpoint label
|
// Right side breakpoint label
|
||||||
.call(g => {
|
.call(g => {
|
||||||
const separator = d3
|
const separator = d3?.select('.dateSeparator')?.node()?.getBBox()
|
||||||
?.select('.dateSeparator')
|
|
||||||
?.node()
|
|
||||||
?.getBBox()
|
|
||||||
|
|
||||||
if (!separator) return
|
if (!separator) return
|
||||||
|
|
||||||
|
|
@ -560,9 +554,7 @@ const Graph = ({
|
||||||
])
|
])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
d3.select(ref.current)
|
d3.select(ref.current).selectAll('*').remove()
|
||||||
.selectAll('*')
|
|
||||||
.remove()
|
|
||||||
drawChart()
|
drawChart()
|
||||||
}, [drawChart])
|
}, [drawChart])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -455,10 +455,7 @@ const Graph = ({
|
||||||
)
|
)
|
||||||
// Left side breakpoint label
|
// Left side breakpoint label
|
||||||
.call(g => {
|
.call(g => {
|
||||||
const separator = d3
|
const separator = d3?.select('.dateSeparator')?.node()?.getBBox()
|
||||||
?.select('.dateSeparator')
|
|
||||||
?.node()
|
|
||||||
?.getBBox()
|
|
||||||
|
|
||||||
if (!separator) return
|
if (!separator) return
|
||||||
|
|
||||||
|
|
@ -479,10 +476,7 @@ const Graph = ({
|
||||||
})
|
})
|
||||||
// Right side breakpoint label
|
// Right side breakpoint label
|
||||||
.call(g => {
|
.call(g => {
|
||||||
const separator = d3
|
const separator = d3?.select('.dateSeparator')?.node()?.getBBox()
|
||||||
?.select('.dateSeparator')
|
|
||||||
?.node()
|
|
||||||
?.getBBox()
|
|
||||||
|
|
||||||
if (!separator) return
|
if (!separator) return
|
||||||
|
|
||||||
|
|
@ -636,9 +630,7 @@ const Graph = ({
|
||||||
])
|
])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
d3.select(ref.current)
|
d3.select(ref.current).selectAll('*').remove()
|
||||||
.selectAll('*')
|
|
||||||
.remove()
|
|
||||||
drawChart()
|
drawChart()
|
||||||
}, [drawChart])
|
}, [drawChart])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,10 +36,13 @@ const Graph = ({ data, machines, currency, selectedMachine }) => {
|
||||||
const filledMachines =
|
const filledMachines =
|
||||||
R.length(machines) >= AMOUNT_OF_MACHINES
|
R.length(machines) >= AMOUNT_OF_MACHINES
|
||||||
? machinesClone
|
? machinesClone
|
||||||
: R.map(it => {
|
: R.map(
|
||||||
if (!R.isNil(machinesClone[it])) return machinesClone[it]
|
it => {
|
||||||
return { code: `ghostMachine${it}`, display: `` }
|
if (!R.isNil(machinesClone[it])) return machinesClone[it]
|
||||||
}, R.times(R.identity, AMOUNT_OF_MACHINES))
|
return { code: `ghostMachine${it}`, display: `` }
|
||||||
|
},
|
||||||
|
R.times(R.identity, AMOUNT_OF_MACHINES)
|
||||||
|
)
|
||||||
|
|
||||||
const txByDevice = R.reduce(
|
const txByDevice = R.reduce(
|
||||||
(acc, value) => {
|
(acc, value) => {
|
||||||
|
|
@ -108,8 +111,9 @@ const Graph = ({ data, machines, currency, selectedMachine }) => {
|
||||||
.axisBottom(x)
|
.axisBottom(x)
|
||||||
.tickFormat(
|
.tickFormat(
|
||||||
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)
|
||||||
|
|
@ -140,14 +144,14 @@ const Graph = ({ data, machines, currency, selectedMachine }) => {
|
||||||
)
|
)
|
||||||
|
|
||||||
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 (d) {
|
||||||
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 (d) {
|
||||||
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)`
|
||||||
})
|
})
|
||||||
|
|
@ -295,9 +299,7 @@ const Graph = ({ data, machines, currency, selectedMachine }) => {
|
||||||
])
|
])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
d3.select(ref.current)
|
d3.select(ref.current).selectAll('*').remove()
|
||||||
.selectAll('*')
|
|
||||||
.remove()
|
|
||||||
drawChart()
|
drawChart()
|
||||||
}, [drawChart])
|
}, [drawChart])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,10 +48,7 @@ const GET_USER_DATA = gql`
|
||||||
`
|
`
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
email: Yup.string()
|
email: Yup.string().label('Email').required().email(),
|
||||||
.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()
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -109,9 +109,7 @@ const BlacklistAdvanced = ({
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
label: Yup.string().required('A label is required!'),
|
label: Yup.string().required('A label is required!'),
|
||||||
content: Yup.string()
|
content: Yup.string().required('The message content is required!').trim()
|
||||||
.required('The message content is required!')
|
|
||||||
.trim()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,7 @@ const BlackListModal = ({ onClose, addToBlacklist, errorMsg }) => {
|
||||||
address: ''
|
address: ''
|
||||||
}}
|
}}
|
||||||
validationSchema={Yup.object({
|
validationSchema={Yup.object({
|
||||||
address: Yup.string()
|
address: Yup.string().trim().required('An address is required')
|
||||||
.trim()
|
|
||||||
.required('An address is required')
|
|
||||||
})}
|
})}
|
||||||
onSubmit={({ address }) => {
|
onSubmit={({ address }) => {
|
||||||
handleAddToBlacklist(address.trim())
|
handleAddToBlacklist(address.trim())
|
||||||
|
|
|
||||||
|
|
@ -83,63 +83,43 @@ const Wizard = ({ machine, locale, onClose, save, error }) => {
|
||||||
cassette1:
|
cassette1:
|
||||||
machine.numberOfCassettes >= 1 && step >= 1
|
machine.numberOfCassettes >= 1 && step >= 1
|
||||||
? Yup.number().required()
|
? Yup.number().required()
|
||||||
: Yup.number()
|
: Yup.number().transform(transformNumber).nullable(),
|
||||||
.transform(transformNumber)
|
|
||||||
.nullable(),
|
|
||||||
cassette2:
|
cassette2:
|
||||||
machine.numberOfCassettes >= 2 && step >= 2
|
machine.numberOfCassettes >= 2 && step >= 2
|
||||||
? Yup.number().required()
|
? Yup.number().required()
|
||||||
: Yup.number()
|
: Yup.number().transform(transformNumber).nullable(),
|
||||||
.transform(transformNumber)
|
|
||||||
.nullable(),
|
|
||||||
cassette3:
|
cassette3:
|
||||||
machine.numberOfCassettes >= 3 && step >= 3
|
machine.numberOfCassettes >= 3 && step >= 3
|
||||||
? Yup.number().required()
|
? Yup.number().required()
|
||||||
: Yup.number()
|
: Yup.number().transform(transformNumber).nullable(),
|
||||||
.transform(transformNumber)
|
|
||||||
.nullable(),
|
|
||||||
cassette4:
|
cassette4:
|
||||||
machine.numberOfCassettes >= 4 && step >= 4
|
machine.numberOfCassettes >= 4 && step >= 4
|
||||||
? Yup.number().required()
|
? Yup.number().required()
|
||||||
: Yup.number()
|
: Yup.number().transform(transformNumber).nullable(),
|
||||||
.transform(transformNumber)
|
|
||||||
.nullable(),
|
|
||||||
recycler1:
|
recycler1:
|
||||||
machine.numberOfRecyclers >= 1 && step >= machine.numberOfCassettes + 1
|
machine.numberOfRecyclers >= 1 && step >= machine.numberOfCassettes + 1
|
||||||
? Yup.number().required()
|
? Yup.number().required()
|
||||||
: Yup.number()
|
: Yup.number().transform(transformNumber).nullable(),
|
||||||
.transform(transformNumber)
|
|
||||||
.nullable(),
|
|
||||||
recycler2:
|
recycler2:
|
||||||
machine.numberOfRecyclers >= 2 && step >= machine.numberOfCassettes + 2
|
machine.numberOfRecyclers >= 2 && step >= machine.numberOfCassettes + 2
|
||||||
? Yup.number().required()
|
? Yup.number().required()
|
||||||
: Yup.number()
|
: Yup.number().transform(transformNumber).nullable(),
|
||||||
.transform(transformNumber)
|
|
||||||
.nullable(),
|
|
||||||
recycler3:
|
recycler3:
|
||||||
machine.numberOfRecyclers >= 3 && step >= machine.numberOfCassettes + 3
|
machine.numberOfRecyclers >= 3 && step >= machine.numberOfCassettes + 3
|
||||||
? Yup.number().required()
|
? Yup.number().required()
|
||||||
: Yup.number()
|
: Yup.number().transform(transformNumber).nullable(),
|
||||||
.transform(transformNumber)
|
|
||||||
.nullable(),
|
|
||||||
recycler4:
|
recycler4:
|
||||||
machine.numberOfRecyclers >= 4 && step >= machine.numberOfCassettes + 4
|
machine.numberOfRecyclers >= 4 && step >= machine.numberOfCassettes + 4
|
||||||
? Yup.number().required()
|
? Yup.number().required()
|
||||||
: Yup.number()
|
: Yup.number().transform(transformNumber).nullable(),
|
||||||
.transform(transformNumber)
|
|
||||||
.nullable(),
|
|
||||||
recycler5:
|
recycler5:
|
||||||
machine.numberOfRecyclers >= 5 && step >= machine.numberOfCassettes + 5
|
machine.numberOfRecyclers >= 5 && step >= machine.numberOfCassettes + 5
|
||||||
? Yup.number().required()
|
? Yup.number().required()
|
||||||
: Yup.number()
|
: Yup.number().transform(transformNumber).nullable(),
|
||||||
.transform(transformNumber)
|
|
||||||
.nullable(),
|
|
||||||
recycler6:
|
recycler6:
|
||||||
machine.numberOfRecyclers >= 6 && step >= machine.numberOfCassettes + 6
|
machine.numberOfRecyclers >= 6 && step >= machine.numberOfCassettes + 6
|
||||||
? Yup.number().required()
|
? Yup.number().required()
|
||||||
: Yup.number()
|
: Yup.number().transform(transformNumber).nullable()
|
||||||
.transform(transformNumber)
|
|
||||||
.nullable()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -325,10 +325,7 @@ const getOverridesSchema = (values, rawData, locale) => {
|
||||||
const highestBill = R.isEmpty(bills) ? CURRENCY_MAX : Math.max(...bills)
|
const highestBill = R.isEmpty(bills) ? CURRENCY_MAX : Math.max(...bills)
|
||||||
|
|
||||||
return Yup.object().shape({
|
return Yup.object().shape({
|
||||||
machine: Yup.string()
|
machine: Yup.string().nullable().label('Machine').required(),
|
||||||
.nullable()
|
|
||||||
.label('Machine')
|
|
||||||
.required(),
|
|
||||||
cryptoCurrencies: Yup.array()
|
cryptoCurrencies: Yup.array()
|
||||||
.test({
|
.test({
|
||||||
test() {
|
test() {
|
||||||
|
|
@ -474,13 +471,8 @@ const getListCommissionsSchema = locale => {
|
||||||
const highestBill = R.isEmpty(bills) ? CURRENCY_MAX : Math.max(...bills)
|
const highestBill = R.isEmpty(bills) ? CURRENCY_MAX : Math.max(...bills)
|
||||||
|
|
||||||
return Yup.object().shape({
|
return Yup.object().shape({
|
||||||
machine: Yup.string()
|
machine: Yup.string().label('Machine').required(),
|
||||||
.label('Machine')
|
cryptoCurrencies: Yup.array().label('Crypto currency').required().min(1),
|
||||||
.required(),
|
|
||||||
cryptoCurrencies: Yup.array()
|
|
||||||
.label('Crypto currency')
|
|
||||||
.required()
|
|
||||||
.min(1),
|
|
||||||
cashIn: Yup.number()
|
cashIn: Yup.number()
|
||||||
.label('Cash-in')
|
.label('Cash-in')
|
||||||
.min(percentMin)
|
.min(percentMin)
|
||||||
|
|
|
||||||
|
|
@ -89,8 +89,8 @@ const CustomerData = ({
|
||||||
const sanctionsDisplay = !sanctionsAt
|
const sanctionsDisplay = !sanctionsAt
|
||||||
? 'Not checked yet'
|
? 'Not checked yet'
|
||||||
: sanctions
|
: sanctions
|
||||||
? 'Passed'
|
? 'Passed'
|
||||||
: 'Failed'
|
: 'Failed'
|
||||||
|
|
||||||
const sortByName = R.sortBy(
|
const sortByName = R.sortBy(
|
||||||
R.compose(R.toLower, R.path(['customInfoRequest', 'customRequest', 'name']))
|
R.compose(R.toLower, R.path(['customInfoRequest', 'customRequest', 'name']))
|
||||||
|
|
@ -263,9 +263,7 @@ const CustomerData = ({
|
||||||
src={
|
src={
|
||||||
!R.isNil(previewPhoto)
|
!R.isNil(previewPhoto)
|
||||||
? URL.createObjectURL(previewPhoto)
|
? URL.createObjectURL(previewPhoto)
|
||||||
: `/front-camera-photo/${R.path(['frontCameraPath'])(
|
: `/front-camera-photo/${R.path(['frontCameraPath'])(customer)}`
|
||||||
customer
|
|
||||||
)}`
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
) : null
|
) : null
|
||||||
|
|
@ -304,9 +302,7 @@ const CustomerData = ({
|
||||||
src={
|
src={
|
||||||
!R.isNil(previewCard)
|
!R.isNil(previewCard)
|
||||||
? URL.createObjectURL(previewCard)
|
? URL.createObjectURL(previewCard)
|
||||||
: `/id-card-photo/${R.path(['idCardPhotoPath'])(
|
: `/id-card-photo/${R.path(['idCardPhotoPath'])(customer)}`
|
||||||
customer
|
|
||||||
)}`
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
) : null
|
) : null
|
||||||
|
|
@ -386,44 +382,50 @@ const CustomerData = ({
|
||||||
})
|
})
|
||||||
}, customInfoRequests)
|
}, customInfoRequests)
|
||||||
|
|
||||||
R.forEach(it => {
|
R.forEach(
|
||||||
customFields.push({
|
it => {
|
||||||
fields: [
|
customFields.push({
|
||||||
{
|
fields: [
|
||||||
name: it.label,
|
{
|
||||||
label: it.label,
|
name: it.label,
|
||||||
value: it.value ?? '',
|
label: it.label,
|
||||||
component: TextInput,
|
value: it.value ?? '',
|
||||||
editable: true
|
component: TextInput,
|
||||||
|
editable: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
title: it.label,
|
||||||
|
titleIcon: <EditIcon className={classes.editIcon} />,
|
||||||
|
save: values => {
|
||||||
|
updateCustomEntry({
|
||||||
|
fieldId: it.id,
|
||||||
|
value: values[it.label]
|
||||||
|
})
|
||||||
|
},
|
||||||
|
deleteEditedData: () => {},
|
||||||
|
validationSchema: Yup.object().shape({
|
||||||
|
[it.label]: Yup.string()
|
||||||
|
}),
|
||||||
|
initialValues: {
|
||||||
|
[it.label]: it.value ?? ''
|
||||||
}
|
}
|
||||||
],
|
})
|
||||||
title: it.label,
|
},
|
||||||
titleIcon: <EditIcon className={classes.editIcon} />,
|
R.path(['customFields'])(customer) ?? []
|
||||||
save: values => {
|
)
|
||||||
updateCustomEntry({
|
|
||||||
fieldId: it.id,
|
|
||||||
value: values[it.label]
|
|
||||||
})
|
|
||||||
},
|
|
||||||
deleteEditedData: () => {},
|
|
||||||
validationSchema: Yup.object().shape({
|
|
||||||
[it.label]: Yup.string()
|
|
||||||
}),
|
|
||||||
initialValues: {
|
|
||||||
[it.label]: it.value ?? ''
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}, R.path(['customFields'])(customer) ?? [])
|
|
||||||
|
|
||||||
R.forEach(it => {
|
R.forEach(
|
||||||
initialValues.smsData[it] = smsData[it]
|
it => {
|
||||||
smsDataElements.push({
|
initialValues.smsData[it] = smsData[it]
|
||||||
name: it,
|
smsDataElements.push({
|
||||||
label: onlyFirstToUpper(it),
|
name: it,
|
||||||
component: TextInput,
|
label: onlyFirstToUpper(it),
|
||||||
editable: false
|
component: TextInput,
|
||||||
})
|
editable: false
|
||||||
}, R.keys(smsData) ?? [])
|
})
|
||||||
|
},
|
||||||
|
R.keys(smsData) ?? []
|
||||||
|
)
|
||||||
|
|
||||||
const externalCompliance = R.map(it => ({
|
const externalCompliance = R.map(it => ({
|
||||||
fields: [
|
fields: [
|
||||||
|
|
@ -492,7 +494,9 @@ const CustomerData = ({
|
||||||
deleteEditedData={deleteEditedData}
|
deleteEditedData={deleteEditedData}
|
||||||
retrieveAdditionalData={retrieveAdditionalData}
|
retrieveAdditionalData={retrieveAdditionalData}
|
||||||
checkAgainstSanctions={checkAgainstSanctions}
|
checkAgainstSanctions={checkAgainstSanctions}
|
||||||
editable={editable}>{children}</EditableCard>
|
editable={editable}>
|
||||||
|
{children}
|
||||||
|
</EditableCard>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -509,7 +513,9 @@ const CustomerData = ({
|
||||||
titleIcon={titleIcon}
|
titleIcon={titleIcon}
|
||||||
editable={false}
|
editable={false}
|
||||||
hasImage={hasImage}
|
hasImage={hasImage}
|
||||||
fields={fields}>{children}</EditableCard>
|
fields={fields}>
|
||||||
|
{children}
|
||||||
|
</EditableCard>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -519,24 +525,25 @@ const CustomerData = ({
|
||||||
<div>
|
<div>
|
||||||
<div className={classes.header}>
|
<div className={classes.header}>
|
||||||
<H3 className={classes.title}>{'Customer data'}</H3>
|
<H3 className={classes.title}>{'Customer data'}</H3>
|
||||||
{// TODO: Remove false condition for next release
|
{
|
||||||
// false && (
|
// TODO: Remove false condition for next release
|
||||||
// <>
|
// false && (
|
||||||
// <FeatureButton
|
// <>
|
||||||
// active={!listView}
|
// <FeatureButton
|
||||||
// className={classes.viewIcons}
|
// active={!listView}
|
||||||
// Icon={OverviewIcon}
|
// className={classes.viewIcons}
|
||||||
// InverseIcon={OverviewReversedIcon}
|
// Icon={OverviewIcon}
|
||||||
// onClick={() => setListView(false)}
|
// InverseIcon={OverviewReversedIcon}
|
||||||
// />
|
// onClick={() => setListView(false)}
|
||||||
// <FeatureButton
|
// />
|
||||||
// active={listView}
|
// <FeatureButton
|
||||||
// className={classes.viewIcons}
|
// active={listView}
|
||||||
// Icon={CustomerListViewIcon}
|
// className={classes.viewIcons}
|
||||||
// InverseIcon={CustomerListViewReversedIcon}
|
// Icon={CustomerListViewIcon}
|
||||||
// onClick={() => setListView(true)}></FeatureButton>
|
// InverseIcon={CustomerListViewReversedIcon}
|
||||||
// </>
|
// onClick={() => setListView(true)}></FeatureButton>
|
||||||
// )
|
// </>
|
||||||
|
// )
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
|
|
@ -59,15 +59,14 @@ const CustomerNotes = ({
|
||||||
<div className={classes.notesChipList}>
|
<div className={classes.notesChipList}>
|
||||||
<NewNoteCard setOpenModal={setOpenModal} />
|
<NewNoteCard setOpenModal={setOpenModal} />
|
||||||
{customerNotes.map((it, idx) => (
|
{customerNotes.map((it, idx) => (
|
||||||
<NoteCard
|
<NoteCard
|
||||||
key={idx}
|
key={idx}
|
||||||
note={it}
|
note={it}
|
||||||
deleteNote={deleteNote}
|
deleteNote={deleteNote}
|
||||||
handleClick={setEditing}
|
handleClick={setEditing}
|
||||||
timezone={timezone}
|
timezone={timezone}
|
||||||
/>
|
/>
|
||||||
)
|
))}
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!R.isNil(editing) && (
|
{!R.isNil(editing) && (
|
||||||
|
|
|
||||||
|
|
@ -552,8 +552,8 @@ const CustomerProfile = memo(() => {
|
||||||
{name.length
|
{name.length
|
||||||
? name
|
? name
|
||||||
: email?.length
|
: email?.length
|
||||||
? email
|
? email
|
||||||
: getFormattedPhone(phone, locale.country)}
|
: getFormattedPhone(phone, locale.country)}
|
||||||
</Label2>
|
</Label2>
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
<div className={classes.panels}>
|
<div className={classes.panels}>
|
||||||
|
|
|
||||||
|
|
@ -120,9 +120,8 @@ const Customers = () => {
|
||||||
onCompleted: data => setFilteredCustomers(R.path(['customers'])(data))
|
onCompleted: data => setFilteredCustomers(R.path(['customers'])(data))
|
||||||
})
|
})
|
||||||
|
|
||||||
const { data: filtersResponse, loading: loadingFilters } = useQuery(
|
const { data: filtersResponse, loading: loadingFilters } =
|
||||||
GET_CUSTOMER_FILTERS
|
useQuery(GET_CUSTOMER_FILTERS)
|
||||||
)
|
|
||||||
|
|
||||||
const [createNewCustomer] = useMutation(CREATE_CUSTOMER, {
|
const [createNewCustomer] = useMutation(CREATE_CUSTOMER, {
|
||||||
onCompleted: () => setShowCreationModal(false),
|
onCompleted: () => setShowCreationModal(false),
|
||||||
|
|
|
||||||
|
|
@ -134,8 +134,8 @@ const CustomInfoRequestsData = ({ data }) => {
|
||||||
it.approved === null
|
it.approved === null
|
||||||
? { label: 'Pending', type: 'neutral' }
|
? { label: 'Pending', type: 'neutral' }
|
||||||
: it.approved === false
|
: it.approved === false
|
||||||
? { label: 'Rejected', type: 'error' }
|
? { label: 'Rejected', type: 'error' }
|
||||||
: { label: 'Accepted', type: 'success' }
|
: { label: 'Accepted', type: 'success' }
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
|
|
@ -59,8 +59,8 @@ const CustomerDetails = memo(({ customer, photosData, locale, timezone }) => {
|
||||||
{name.length
|
{name.length
|
||||||
? name
|
? name
|
||||||
: email?.length
|
: email?.length
|
||||||
? email
|
? email
|
||||||
: getFormattedPhone(phone, locale.country)}
|
: getFormattedPhone(phone, locale.country)}
|
||||||
</H2>
|
</H2>
|
||||||
</div>
|
</div>
|
||||||
<Box display="flex" mt="auto">
|
<Box display="flex" mt="auto">
|
||||||
|
|
|
||||||
|
|
@ -170,8 +170,8 @@ const EditableCard = ({
|
||||||
state === OVERRIDE_PENDING
|
state === OVERRIDE_PENDING
|
||||||
? { label: 'Pending', type: 'neutral' }
|
? { label: 'Pending', type: 'neutral' }
|
||||||
: state === OVERRIDE_REJECTED
|
: state === OVERRIDE_REJECTED
|
||||||
? { label: 'Rejected', type: 'error' }
|
? { label: 'Rejected', type: 'error' }
|
||||||
: { label: 'Accepted', type: 'success' }
|
: { label: 'Accepted', type: 'success' }
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,7 @@ const IdCardPhotoCard = memo(({ customerData, updateCustomer }) => {
|
||||||
{customerData.idCardPhotoPath ? (
|
{customerData.idCardPhotoPath ? (
|
||||||
<img
|
<img
|
||||||
className={classes.idCardPhoto}
|
className={classes.idCardPhoto}
|
||||||
src={`/id-card-photo/${R.path(['idCardPhotoPath'])(
|
src={`/id-card-photo/${R.path(['idCardPhotoPath'])(customerData)}`}
|
||||||
customerData
|
|
||||||
)}`}
|
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,7 @@ const initialValues = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
title: Yup.string()
|
title: Yup.string().required().trim().max(25),
|
||||||
.required()
|
|
||||||
.trim()
|
|
||||||
.max(25),
|
|
||||||
content: Yup.string().required()
|
content: Yup.string().required()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -93,8 +93,8 @@ const PropertyCard = memo(
|
||||||
state === OVERRIDE_PENDING
|
state === OVERRIDE_PENDING
|
||||||
? { label: 'Pending', type: 'neutral' }
|
? { label: 'Pending', type: 'neutral' }
|
||||||
: state === OVERRIDE_REJECTED
|
: state === OVERRIDE_REJECTED
|
||||||
? { label: 'Rejected', type: 'error' }
|
? { label: 'Rejected', type: 'error' }
|
||||||
: { label: 'Accepted', type: 'success' }
|
: { label: 'Accepted', type: 'success' }
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper
|
<Paper
|
||||||
|
|
|
||||||
|
|
@ -143,9 +143,9 @@ const getFormattedPhone = (phone, country) => {
|
||||||
const getName = it => {
|
const getName = it => {
|
||||||
const idData = R.path(['idCardData'])(it)
|
const idData = R.path(['idCardData'])(it)
|
||||||
|
|
||||||
return `${R.path(['firstName'])(idData) ?? ''} ${R.path(['lastName'])(
|
return `${R.path(['firstName'])(idData) ?? ''} ${
|
||||||
idData
|
R.path(['lastName'])(idData) ?? ''
|
||||||
) ?? ''}`.trim()
|
}`.trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manual Entry Wizard
|
// Manual Entry Wizard
|
||||||
|
|
|
||||||
|
|
@ -126,10 +126,10 @@ const RefLineChart = ({
|
||||||
])
|
])
|
||||||
.enter()
|
.enter()
|
||||||
.append('stop')
|
.append('stop')
|
||||||
.attr('offset', function(d) {
|
.attr('offset', function (d) {
|
||||||
return d.offset
|
return d.offset
|
||||||
})
|
})
|
||||||
.attr('stop-color', function(d) {
|
.attr('stop-color', function (d) {
|
||||||
return d.color
|
return d.color
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -152,20 +152,20 @@ const RefLineChart = ({
|
||||||
|
|
||||||
const line = d3
|
const line = d3
|
||||||
.line()
|
.line()
|
||||||
.x(function(d) {
|
.x(function (d) {
|
||||||
return x(new Date(d.created))
|
return x(new Date(d.created))
|
||||||
})
|
})
|
||||||
.y(function(d) {
|
.y(function (d) {
|
||||||
return y(d.profit)
|
return y(d.profit)
|
||||||
})
|
})
|
||||||
|
|
||||||
const area = d3
|
const area = d3
|
||||||
.area()
|
.area()
|
||||||
.x(function(d) {
|
.x(function (d) {
|
||||||
return x(new Date(d.created))
|
return x(new Date(d.created))
|
||||||
})
|
})
|
||||||
.y0(height)
|
.y0(height)
|
||||||
.y1(function(d) {
|
.y1(function (d) {
|
||||||
return y(d.profit)
|
return y(d.profit)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -186,9 +186,7 @@ const RefLineChart = ({
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// first we clear old chart DOM elements on component update
|
// first we clear old chart DOM elements on component update
|
||||||
d3.select(svgRef.current)
|
d3.select(svgRef.current).selectAll('*').remove()
|
||||||
.selectAll('*')
|
|
||||||
.remove()
|
|
||||||
drawGraph()
|
drawGraph()
|
||||||
}, [drawGraph, realData])
|
}, [drawGraph, realData])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -211,12 +211,7 @@ const Graph = ({ data, timeFrame, timezone }) => {
|
||||||
g
|
g
|
||||||
.append('g')
|
.append('g')
|
||||||
.selectAll('line')
|
.selectAll('line')
|
||||||
.data(
|
.data(d3.axisLeft(y).scale().ticks(5))
|
||||||
d3
|
|
||||||
.axisLeft(y)
|
|
||||||
.scale()
|
|
||||||
.ticks(5)
|
|
||||||
)
|
|
||||||
.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))
|
||||||
|
|
@ -240,10 +235,7 @@ const Graph = ({ data, timeFrame, timezone }) => {
|
||||||
)
|
)
|
||||||
// Left side breakpoint label
|
// Left side breakpoint label
|
||||||
.call(g => {
|
.call(g => {
|
||||||
const separator = d3
|
const separator = d3?.select('.dateSeparator')?.node()?.getBBox()
|
||||||
?.select('.dateSeparator')
|
|
||||||
?.node()
|
|
||||||
?.getBBox()
|
|
||||||
|
|
||||||
if (!separator) return
|
if (!separator) return
|
||||||
|
|
||||||
|
|
@ -261,10 +253,7 @@ const Graph = ({ data, timeFrame, timezone }) => {
|
||||||
})
|
})
|
||||||
// Right side breakpoint label
|
// Right side breakpoint label
|
||||||
.call(g => {
|
.call(g => {
|
||||||
const separator = d3
|
const separator = d3?.select('.dateSeparator')?.node()?.getBBox()
|
||||||
?.select('.dateSeparator')
|
|
||||||
?.node()
|
|
||||||
?.getBBox()
|
|
||||||
|
|
||||||
if (!separator) return
|
if (!separator) return
|
||||||
|
|
||||||
|
|
@ -355,9 +344,7 @@ const Graph = ({ data, timeFrame, timezone }) => {
|
||||||
])
|
])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
d3.select(ref.current)
|
d3.select(ref.current).selectAll('*').remove()
|
||||||
.selectAll('*')
|
|
||||||
.remove()
|
|
||||||
drawChart()
|
drawChart()
|
||||||
}, [drawChart])
|
}, [drawChart])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -108,14 +108,13 @@ const MachinesTable = ({ machines = [], numToRender }) => {
|
||||||
</div>
|
</div>
|
||||||
</HeaderCell> */}
|
</HeaderCell> */}
|
||||||
{R.times(R.identity, maxNumberOfCassettes).map((it, idx) => (
|
{R.times(R.identity, maxNumberOfCassettes).map((it, idx) => (
|
||||||
<HeaderCell key={idx}>
|
<HeaderCell key={idx}>
|
||||||
<div className={classes.header}>
|
<div className={classes.header}>
|
||||||
<TxOutIcon />
|
<TxOutIcon />
|
||||||
<Label2 className={classes.label}> {it + 1}</Label2>
|
<Label2 className={classes.label}> {it + 1}</Label2>
|
||||||
</div>
|
</div>
|
||||||
</HeaderCell>
|
</HeaderCell>
|
||||||
)
|
))}
|
||||||
)}
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
|
|
@ -142,18 +141,18 @@ const MachinesTable = ({ machines = [], numToRender }) => {
|
||||||
<Status status={machine.statuses[0]} />
|
<Status status={machine.statuses[0]} />
|
||||||
</StyledCell>
|
</StyledCell>
|
||||||
{R.range(1, maxNumberOfCassettes + 1).map((it, idx) =>
|
{R.range(1, maxNumberOfCassettes + 1).map((it, idx) =>
|
||||||
machine.numberOfCassettes >= it ? (
|
machine.numberOfCassettes >= it ? (
|
||||||
<StyledCell key={idx} align="left">
|
<StyledCell key={idx} align="left">
|
||||||
{makePercentageText(
|
{makePercentageText(
|
||||||
it,
|
it,
|
||||||
machine.cashUnits[`cassette${it}`]
|
machine.cashUnits[`cassette${it}`]
|
||||||
)}
|
)}
|
||||||
</StyledCell>
|
</StyledCell>
|
||||||
) : (
|
) : (
|
||||||
<StyledCell key={idx} align="left">
|
<StyledCell key={idx} align="left">
|
||||||
<TL2>{`— %`}</TL2>
|
<TL2>{`— %`}</TL2>
|
||||||
</StyledCell>
|
</StyledCell>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -153,42 +153,18 @@ const overrides = (auxData, auxElements, configureCoin) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const LocaleSchema = Yup.object().shape({
|
const LocaleSchema = Yup.object().shape({
|
||||||
country: Yup.string()
|
country: Yup.string().label('Country').required(),
|
||||||
.label('Country')
|
fiatCurrency: Yup.string().label('Fiat currency').required(),
|
||||||
.required(),
|
languages: Yup.array().label('Languages').required().min(1).max(4),
|
||||||
fiatCurrency: Yup.string()
|
cryptoCurrencies: Yup.array().label('Crypto currencies').required().min(1),
|
||||||
.label('Fiat currency')
|
timezone: Yup.string().label('Timezone').required()
|
||||||
.required(),
|
|
||||||
languages: Yup.array()
|
|
||||||
.label('Languages')
|
|
||||||
.required()
|
|
||||||
.min(1)
|
|
||||||
.max(4),
|
|
||||||
cryptoCurrencies: Yup.array()
|
|
||||||
.label('Crypto currencies')
|
|
||||||
.required()
|
|
||||||
.min(1),
|
|
||||||
timezone: Yup.string()
|
|
||||||
.label('Timezone')
|
|
||||||
.required()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const OverridesSchema = Yup.object().shape({
|
const OverridesSchema = Yup.object().shape({
|
||||||
machine: Yup.string()
|
machine: Yup.string().label('Machine').required(),
|
||||||
.label('Machine')
|
country: Yup.string().label('Country').required(),
|
||||||
.required(),
|
languages: Yup.array().label('Languages').required().min(1).max(4),
|
||||||
country: Yup.string()
|
cryptoCurrencies: Yup.array().label('Crypto currencies').required().min(1)
|
||||||
.label('Country')
|
|
||||||
.required(),
|
|
||||||
languages: Yup.array()
|
|
||||||
.label('Languages')
|
|
||||||
.required()
|
|
||||||
.min(1)
|
|
||||||
.max(4),
|
|
||||||
cryptoCurrencies: Yup.array()
|
|
||||||
.label('Crypto currencies')
|
|
||||||
.required()
|
|
||||||
.min(1)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const localeDefaults = {
|
const localeDefaults = {
|
||||||
|
|
|
||||||
|
|
@ -65,9 +65,8 @@ const IndividualDiscounts = () => {
|
||||||
const { data: discountResponse, loading: discountLoading } = useQuery(
|
const { data: discountResponse, loading: discountLoading } = useQuery(
|
||||||
GET_INDIVIDUAL_DISCOUNTS
|
GET_INDIVIDUAL_DISCOUNTS
|
||||||
)
|
)
|
||||||
const { data: customerData, loading: customerLoading } = useQuery(
|
const { data: customerData, loading: customerLoading } =
|
||||||
GET_CUSTOMERS
|
useQuery(GET_CUSTOMERS)
|
||||||
)
|
|
||||||
|
|
||||||
const [createDiscount, { error: creationError }] = useMutation(
|
const [createDiscount, { error: creationError }] = useMutation(
|
||||||
CREATE_DISCOUNT,
|
CREATE_DISCOUNT,
|
||||||
|
|
|
||||||
|
|
@ -21,14 +21,8 @@ const initialValues = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
code: Yup.string()
|
code: Yup.string().required().trim().max(25),
|
||||||
.required()
|
discount: Yup.number().required().min(0).max(100)
|
||||||
.trim()
|
|
||||||
.max(25),
|
|
||||||
discount: Yup.number()
|
|
||||||
.required()
|
|
||||||
.min(0)
|
|
||||||
.max(100)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const PromoCodesModal = ({ showModal, onClose, errorMsg, addCode }) => {
|
const PromoCodesModal = ({ showModal, onClose, errorMsg, addCode }) => {
|
||||||
|
|
|
||||||
|
|
@ -81,9 +81,8 @@ const Logs = () => {
|
||||||
|
|
||||||
const deviceId = selected?.deviceId
|
const deviceId = selected?.deviceId
|
||||||
|
|
||||||
const { data: machineResponse, loading: machinesLoading } = useQuery(
|
const { data: machineResponse, loading: machinesLoading } =
|
||||||
GET_MACHINES
|
useQuery(GET_MACHINES)
|
||||||
)
|
|
||||||
|
|
||||||
const { data: configResponse, loading: configLoading } = useQuery(GET_DATA)
|
const { data: configResponse, loading: configLoading } = useQuery(GET_DATA)
|
||||||
const timezone = R.path(['config', 'locale_timezone'], configResponse)
|
const timezone = R.path(['config', 'locale_timezone'], configResponse)
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ const CashUnitDetails = ({
|
||||||
<div className={classes.billList}>
|
<div className={classes.billList}>
|
||||||
<Label1>Cash box</Label1>
|
<Label1>Cash box</Label1>
|
||||||
{R.isEmpty(billCount) && <TL2 noMargin>Empty</TL2>}
|
{R.isEmpty(billCount) && <TL2 noMargin>Empty</TL2>}
|
||||||
{(R.keys(billCount)).map((it, idx) => (
|
{R.keys(billCount).map((it, idx) => (
|
||||||
<span key={idx}>
|
<span key={idx}>
|
||||||
<TL2 noMargin>{billCount[it]}</TL2>
|
<TL2 noMargin>{billCount[it]}</TL2>
|
||||||
<Chip label={`${it} ${currency}`} />
|
<Chip label={`${it} ${currency}`} />
|
||||||
|
|
@ -149,7 +149,7 @@ const CashUnitDetails = ({
|
||||||
noMargin
|
noMargin
|
||||||
className={classes.label}>{`Loading boxes`}</Label1>
|
className={classes.label}>{`Loading boxes`}</Label1>
|
||||||
<div className={classes.loadingBoxes}>
|
<div className={classes.loadingBoxes}>
|
||||||
{(R.range(1, machine.numberOfCassettes + 1)).map((it, idx) => (
|
{R.range(1, machine.numberOfCassettes + 1).map((it, idx) => (
|
||||||
<CashOut
|
<CashOut
|
||||||
key={idx}
|
key={idx}
|
||||||
width={60}
|
width={60}
|
||||||
|
|
|
||||||
|
|
@ -182,10 +182,8 @@ const WizardStep = ({
|
||||||
|
|
||||||
const numberOfCassettes = machine.numberOfCassettes
|
const numberOfCassettes = machine.numberOfCassettes
|
||||||
const numberOfRecyclers = machine.numberOfRecyclers
|
const numberOfRecyclers = machine.numberOfRecyclers
|
||||||
const {
|
const { name: cashUnitField, category: cashUnitCategory } =
|
||||||
name: cashUnitField,
|
getCashUnitFieldName(step, numberOfCassettes, numberOfRecyclers)
|
||||||
category: cashUnitCategory
|
|
||||||
} = getCashUnitFieldName(step, numberOfCassettes, numberOfRecyclers)
|
|
||||||
const originalCashUnitCount = machine?.cashUnits?.[cashUnitField]
|
const originalCashUnitCount = machine?.cashUnits?.[cashUnitField]
|
||||||
const cashUnitDenomination = cashoutSettings?.[cashUnitField]
|
const cashUnitDenomination = cashoutSettings?.[cashUnitField]
|
||||||
|
|
||||||
|
|
@ -317,8 +315,8 @@ const WizardStep = ({
|
||||||
{cashUnitCategory === 'cassette'
|
{cashUnitCategory === 'cassette'
|
||||||
? `dispenser`
|
? `dispenser`
|
||||||
: cashUnitCategory === 'recycler'
|
: cashUnitCategory === 'recycler'
|
||||||
? `recycler`
|
? `recycler`
|
||||||
: ``}
|
: ``}
|
||||||
)
|
)
|
||||||
</H4>
|
</H4>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ const getElements = (
|
||||||
return (
|
return (
|
||||||
<div className={classes.unitsRow}>
|
<div className={classes.unitsRow}>
|
||||||
<div className={classes.units}>
|
<div className={classes.units}>
|
||||||
{(R.range(1, m.numberOfCassettes + 1)).map((it, idx) => (
|
{R.range(1, m.numberOfCassettes + 1).map((it, idx) => (
|
||||||
<CashOutLite
|
<CashOutLite
|
||||||
key={idx}
|
key={idx}
|
||||||
width={'100%'}
|
width={'100%'}
|
||||||
|
|
|
||||||
|
|
@ -33,14 +33,8 @@ const SingleFieldEditableNumber = ({
|
||||||
setSaving(false)
|
setSaving(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const { save, data, currency, isEditing, isDisabled, setEditing } =
|
||||||
save,
|
useContext(NotificationsCtx)
|
||||||
data,
|
|
||||||
currency,
|
|
||||||
isEditing,
|
|
||||||
isDisabled,
|
|
||||||
setEditing
|
|
||||||
} = useContext(NotificationsCtx)
|
|
||||||
|
|
||||||
const schema = Yup.object().shape({
|
const schema = Yup.object().shape({
|
||||||
[name]: Yup.number()
|
[name]: Yup.number()
|
||||||
|
|
|
||||||
|
|
@ -14,14 +14,8 @@ const useStyles = makeStyles(styles)
|
||||||
const CryptoBalanceAlerts = ({ section, fieldWidth }) => {
|
const CryptoBalanceAlerts = ({ section, fieldWidth }) => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
|
|
||||||
const {
|
const { data, save, currency, setEditing, isEditing, isDisabled } =
|
||||||
data,
|
useContext(NotificationsCtx)
|
||||||
save,
|
|
||||||
currency,
|
|
||||||
setEditing,
|
|
||||||
isEditing,
|
|
||||||
isDisabled
|
|
||||||
} = useContext(NotificationsCtx)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.cryptoBalanceAlerts}>
|
<div className={classes.cryptoBalanceAlerts}>
|
||||||
|
|
|
||||||
|
|
@ -79,9 +79,7 @@ const FiatBalanceOverrides = ({ config, section }) => {
|
||||||
const percentMax = 100
|
const percentMax = 100
|
||||||
const validationSchema = Yup.object()
|
const validationSchema = Yup.object()
|
||||||
.shape({
|
.shape({
|
||||||
[MACHINE_KEY]: Yup.string()
|
[MACHINE_KEY]: Yup.string().label('Machine').required(),
|
||||||
.label('Machine')
|
|
||||||
.required(),
|
|
||||||
[CASHBOX_KEY]: Yup.number()
|
[CASHBOX_KEY]: Yup.number()
|
||||||
.label('Cash box')
|
.label('Cash box')
|
||||||
.transform(transformNumber)
|
.transform(transformNumber)
|
||||||
|
|
|
||||||
|
|
@ -1,84 +1,87 @@
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useContext } from 'react'
|
import React, { useContext } from 'react'
|
||||||
import Autocomplete from 'src/components/inputs/formik/Autocomplete'
|
import Autocomplete from 'src/components/inputs/formik/Autocomplete'
|
||||||
import * as Yup from 'yup'
|
import * as Yup from 'yup'
|
||||||
|
|
||||||
import { Table as EditableTable } from 'src/components/editableTable'
|
import { Table as EditableTable } from 'src/components/editableTable'
|
||||||
import { toNamespace, fromNamespace } from 'src/utils/config'
|
import { toNamespace, fromNamespace } from 'src/utils/config'
|
||||||
|
|
||||||
import NotificationsCtx from '../NotificationsContext'
|
import NotificationsCtx from '../NotificationsContext'
|
||||||
|
|
||||||
const filterClass = type => R.filter(it => it.class === type)
|
const filterClass = type => R.filter(it => it.class === type)
|
||||||
|
|
||||||
const ThirdPartyProvider = () => {
|
const ThirdPartyProvider = () => {
|
||||||
const { save, data: _data, error, accountsConfig } = useContext(
|
const {
|
||||||
NotificationsCtx
|
save,
|
||||||
)
|
data: _data,
|
||||||
|
error,
|
||||||
const data = fromNamespace('thirdParty')(_data)
|
accountsConfig
|
||||||
|
} = useContext(NotificationsCtx)
|
||||||
const filterOptions = type => filterClass(type)(accountsConfig || [])
|
|
||||||
|
const data = fromNamespace('thirdParty')(_data)
|
||||||
const getDisplayName = type => it =>
|
|
||||||
R.compose(
|
const filterOptions = type => filterClass(type)(accountsConfig || [])
|
||||||
R.prop('display'),
|
|
||||||
R.find(R.propEq('code', it))
|
const getDisplayName = type => it =>
|
||||||
)(filterOptions(type))
|
R.compose(
|
||||||
|
R.prop('display'),
|
||||||
const innerSave = async value => {
|
R.find(R.propEq('code', it))
|
||||||
const config = toNamespace('thirdParty')(value?.thirdParty[0])
|
)(filterOptions(type))
|
||||||
await save('thirdParty', config)
|
|
||||||
}
|
const innerSave = async value => {
|
||||||
|
const config = toNamespace('thirdParty')(value?.thirdParty[0])
|
||||||
const ThirdPartySchema = Yup.object().shape({
|
await save('thirdParty', config)
|
||||||
sms: Yup.string('SMS must be a string').required('SMS is required'),
|
}
|
||||||
email: Yup.string('Email must be a string').required('Email is required')
|
|
||||||
})
|
const ThirdPartySchema = Yup.object().shape({
|
||||||
|
sms: Yup.string('SMS must be a string').required('SMS is required'),
|
||||||
const elements = [
|
email: Yup.string('Email must be a string').required('Email is required')
|
||||||
{
|
})
|
||||||
name: 'sms',
|
|
||||||
size: 'sm',
|
const elements = [
|
||||||
view: getDisplayName('sms'),
|
{
|
||||||
width: 175,
|
name: 'sms',
|
||||||
input: Autocomplete,
|
size: 'sm',
|
||||||
inputProps: {
|
view: getDisplayName('sms'),
|
||||||
options: filterOptions('sms'),
|
width: 175,
|
||||||
valueProp: 'code',
|
input: Autocomplete,
|
||||||
labelProp: 'display'
|
inputProps: {
|
||||||
}
|
options: filterOptions('sms'),
|
||||||
},
|
valueProp: 'code',
|
||||||
{
|
labelProp: 'display'
|
||||||
name: 'email',
|
}
|
||||||
size: 'sm',
|
},
|
||||||
view: getDisplayName('email'),
|
{
|
||||||
width: 175,
|
name: 'email',
|
||||||
input: Autocomplete,
|
size: 'sm',
|
||||||
inputProps: {
|
view: getDisplayName('email'),
|
||||||
options: filterOptions('email'),
|
width: 175,
|
||||||
valueProp: 'code',
|
input: Autocomplete,
|
||||||
labelProp: 'display'
|
inputProps: {
|
||||||
}
|
options: filterOptions('email'),
|
||||||
}
|
valueProp: 'code',
|
||||||
]
|
labelProp: 'display'
|
||||||
const values = {
|
}
|
||||||
sms: data.sms ?? 'twilio',
|
}
|
||||||
email: data.email ?? 'mailgun'
|
]
|
||||||
}
|
const values = {
|
||||||
|
sms: data.sms ?? 'twilio',
|
||||||
return (
|
email: data.email ?? 'mailgun'
|
||||||
<EditableTable
|
}
|
||||||
name="thirdParty"
|
|
||||||
initialValues={values}
|
return (
|
||||||
data={R.of(values)}
|
<EditableTable
|
||||||
error={error?.message}
|
name="thirdParty"
|
||||||
enableEdit
|
initialValues={values}
|
||||||
editWidth={174}
|
data={R.of(values)}
|
||||||
save={innerSave}
|
error={error?.message}
|
||||||
validationSchema={ThirdPartySchema}
|
enableEdit
|
||||||
elements={elements}
|
editWidth={174}
|
||||||
/>
|
save={innerSave}
|
||||||
)
|
validationSchema={ThirdPartySchema}
|
||||||
}
|
elements={elements}
|
||||||
|
/>
|
||||||
export default ThirdPartyProvider
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ThirdPartyProvider
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ const DISABLE_SMS_NOTICE = gql`
|
||||||
const multiReplace = (str, obj) => {
|
const multiReplace = (str, obj) => {
|
||||||
var re = new RegExp(Object.keys(obj).join('|'), 'gi')
|
var re = new RegExp(Object.keys(obj).join('|'), 'gi')
|
||||||
|
|
||||||
return str.replace(re, function(matched) {
|
return str.replace(re, function (matched) {
|
||||||
return obj[matched.toLowerCase()]
|
return obj[matched.toLowerCase()]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -82,7 +82,8 @@ const formatContent = content => {
|
||||||
const TOOLTIPS = {
|
const TOOLTIPS = {
|
||||||
smsCode: ``,
|
smsCode: ``,
|
||||||
cashOutDispenseReady: ``,
|
cashOutDispenseReady: ``,
|
||||||
smsReceipt: formatContent(`The contents of this notice will be appended to the end of the SMS receipt sent, and not replace it.\n
|
smsReceipt:
|
||||||
|
formatContent(`The contents of this notice will be appended to the end of the SMS receipt sent, and not replace it.\n
|
||||||
To edit the contents of the SMS receipt, please go to the 'Receipt' tab`)
|
To edit the contents of the SMS receipt, please go to the 'Receipt' tab`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -124,9 +125,8 @@ const SMSNotices = () => {
|
||||||
const [previewCoords, setPreviewCoords] = useState({ x: 0, y: 0 })
|
const [previewCoords, setPreviewCoords] = useState({ x: 0, y: 0 })
|
||||||
const [errorMsg, setErrorMsg] = useState('')
|
const [errorMsg, setErrorMsg] = useState('')
|
||||||
|
|
||||||
const { data: messagesData, loading: messagesLoading } = useQuery(
|
const { data: messagesData, loading: messagesLoading } =
|
||||||
GET_SMS_NOTICES
|
useQuery(GET_SMS_NOTICES)
|
||||||
)
|
|
||||||
|
|
||||||
const timezone = R.path(['config', 'locale_timezone'])(messagesData)
|
const timezone = R.path(['config', 'locale_timezone'])(messagesData)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,9 +44,7 @@ const PREFILL = {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
cashOutDispenseReady: {
|
cashOutDispenseReady: {
|
||||||
validator: Yup.string()
|
validator: Yup.string().required('The message content is required!').trim()
|
||||||
.required('The message content is required!')
|
|
||||||
.trim()
|
|
||||||
},
|
},
|
||||||
smsReceipt: {
|
smsReceipt: {
|
||||||
validator: Yup.string().trim()
|
validator: Yup.string().trim()
|
||||||
|
|
@ -89,9 +87,7 @@ const SMSNoticesModal = ({
|
||||||
event: Yup.string().required('An event is required!'),
|
event: Yup.string().required('An event is required!'),
|
||||||
message:
|
message:
|
||||||
PREFILL[sms?.event]?.validator ??
|
PREFILL[sms?.event]?.validator ??
|
||||||
Yup.string()
|
Yup.string().required('The message content is required!').trim()
|
||||||
.required('The message content is required!')
|
|
||||||
.trim()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleSubmit = values => {
|
const handleSubmit = values => {
|
||||||
|
|
@ -155,33 +151,29 @@ const SMSNoticesModal = ({
|
||||||
<Info2 noMargin>Values to attach</Info2>
|
<Info2 noMargin>Values to attach</Info2>
|
||||||
)}
|
)}
|
||||||
<div className={classes.chipButtons}>
|
<div className={classes.chipButtons}>
|
||||||
{R.splitEvery(3, CHIPS[sms?.event]).map(
|
{R.splitEvery(3, CHIPS[sms?.event]).map((it, idx) => (
|
||||||
(it, idx) => (
|
<div key={idx}>
|
||||||
<div key={idx}>
|
{it.map((ite, idx2) => (
|
||||||
{it.map(
|
<Chip
|
||||||
(ite, idx2) => (
|
key={idx2}
|
||||||
<Chip
|
label={ite.display}
|
||||||
key={idx2}
|
size="small"
|
||||||
label={ite.display}
|
style={{ backgroundColor: zircon }}
|
||||||
size="small"
|
disabled={R.includes(ite.code, values.message)}
|
||||||
style={{ backgroundColor: zircon }}
|
className={classes.chip}
|
||||||
disabled={R.includes(ite.code, values.message)}
|
onClick={() => {
|
||||||
className={classes.chip}
|
setFieldValue(
|
||||||
onClick={() => {
|
'message',
|
||||||
setFieldValue(
|
values.message.concat(
|
||||||
'message',
|
R.last(values.message) === ' ' ? '' : ' ',
|
||||||
values.message.concat(
|
ite.code
|
||||||
R.last(values.message) === ' ' ? '' : ' ',
|
)
|
||||||
ite.code
|
)
|
||||||
)
|
}}
|
||||||
)
|
/>
|
||||||
}}
|
))}
|
||||||
/>
|
</div>
|
||||||
)
|
))}
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.footer}>
|
<div className={classes.footer}>
|
||||||
{getErrorMsg(errors, touched, creationError) && (
|
{getErrorMsg(errors, touched, creationError) && (
|
||||||
|
|
|
||||||
|
|
@ -1,67 +1,64 @@
|
||||||
import { ALL_CRYPTOS } from '@lamassu/coins/config/consts'
|
import { ALL_CRYPTOS } from '@lamassu/coins/config/consts'
|
||||||
import { getEquivalentCode } from '@lamassu/coins/lightUtils'
|
import { getEquivalentCode } from '@lamassu/coins/lightUtils'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
|
|
||||||
const WARNING_LEVELS = {
|
const WARNING_LEVELS = {
|
||||||
CLEAN: 'clean',
|
CLEAN: 'clean',
|
||||||
PARTIAL: 'partial',
|
PARTIAL: 'partial',
|
||||||
IMPORTANT: 'important'
|
IMPORTANT: 'important'
|
||||||
}
|
}
|
||||||
|
|
||||||
const secretTest = (secret, message) => ({
|
const secretTest = (secret, message) => ({
|
||||||
name: 'secret-test',
|
name: 'secret-test',
|
||||||
message: message ? `The ${message} is invalid` : 'Invalid field',
|
message: message ? `The ${message} is invalid` : 'Invalid field',
|
||||||
test(val) {
|
test(val) {
|
||||||
if (R.isNil(secret) && R.isNil(val)) {
|
if (R.isNil(secret) && R.isNil(val)) {
|
||||||
return this.createError()
|
return this.createError()
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const leadingZerosTest = (value, context) => {
|
const leadingZerosTest = (value, context) => {
|
||||||
if (
|
if (
|
||||||
R.startsWith('0', context.originalValue) &&
|
R.startsWith('0', context.originalValue) &&
|
||||||
R.length(context.originalValue) > 1
|
R.length(context.originalValue) > 1
|
||||||
) {
|
) {
|
||||||
return context.createError()
|
return context.createError()
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildCurrencyOptions = markets => {
|
const buildCurrencyOptions = markets => {
|
||||||
const prunedCoins = R.compose(
|
const prunedCoins = R.compose(R.uniq, R.map(getEquivalentCode))(ALL_CRYPTOS)
|
||||||
R.uniq,
|
return R.map(it => {
|
||||||
R.map(getEquivalentCode)
|
const unavailableCryptos = R.difference(prunedCoins, markets[it])
|
||||||
)(ALL_CRYPTOS)
|
const unavailableCryptosFiltered = R.difference(unavailableCryptos, [it]) // As the markets can have stablecoins to trade against other crypto, filter them out, as there can't be pairs such as USDT/USDT
|
||||||
return R.map(it => {
|
|
||||||
const unavailableCryptos = R.difference(prunedCoins, markets[it])
|
const unavailableMarketsStr =
|
||||||
const unavailableCryptosFiltered = R.difference(unavailableCryptos, [it]) // As the markets can have stablecoins to trade against other crypto, filter them out, as there can't be pairs such as USDT/USDT
|
R.length(unavailableCryptosFiltered) > 1
|
||||||
|
? `${R.join(
|
||||||
const unavailableMarketsStr =
|
', ',
|
||||||
R.length(unavailableCryptosFiltered) > 1
|
R.slice(0, -1, unavailableCryptosFiltered)
|
||||||
? `${R.join(
|
)} and ${R.last(unavailableCryptosFiltered)}`
|
||||||
', ',
|
: unavailableCryptosFiltered[0]
|
||||||
R.slice(0, -1, unavailableCryptosFiltered)
|
|
||||||
)} and ${R.last(unavailableCryptosFiltered)}`
|
const warningLevel = R.isEmpty(unavailableCryptosFiltered)
|
||||||
: unavailableCryptosFiltered[0]
|
? WARNING_LEVELS.CLEAN
|
||||||
|
: !R.isEmpty(unavailableCryptosFiltered) &&
|
||||||
const warningLevel = R.isEmpty(unavailableCryptosFiltered)
|
R.length(unavailableCryptosFiltered) < R.length(prunedCoins)
|
||||||
? WARNING_LEVELS.CLEAN
|
? WARNING_LEVELS.PARTIAL
|
||||||
: !R.isEmpty(unavailableCryptosFiltered) &&
|
: WARNING_LEVELS.IMPORTANT
|
||||||
R.length(unavailableCryptosFiltered) < R.length(prunedCoins)
|
|
||||||
? WARNING_LEVELS.PARTIAL
|
return {
|
||||||
: WARNING_LEVELS.IMPORTANT
|
code: R.toUpper(it),
|
||||||
|
display: R.toUpper(it),
|
||||||
return {
|
warning: warningLevel,
|
||||||
code: R.toUpper(it),
|
warningMessage: !R.isEmpty(unavailableCryptosFiltered)
|
||||||
display: R.toUpper(it),
|
? `No market pairs available for ${unavailableMarketsStr}`
|
||||||
warning: warningLevel,
|
: `All market pairs are available`
|
||||||
warningMessage: !R.isEmpty(unavailableCryptosFiltered)
|
}
|
||||||
? `No market pairs available for ${unavailableMarketsStr}`
|
}, R.keys(markets))
|
||||||
: `All market pairs are available`
|
}
|
||||||
}
|
|
||||||
}, R.keys(markets))
|
export { secretTest, leadingZerosTest, buildCurrencyOptions }
|
||||||
}
|
|
||||||
|
|
||||||
export { secretTest, leadingZerosTest, buildCurrencyOptions }
|
|
||||||
|
|
|
||||||
|
|
@ -132,14 +132,10 @@ const DetailsRow = ({ it: tx, timezone }) => {
|
||||||
Number.parseFloat(tx.commissionPercentage, 2) * 100
|
Number.parseFloat(tx.commissionPercentage, 2) * 100
|
||||||
).toFixed(2, 1) // ROUND_DOWN
|
).toFixed(2, 1) // ROUND_DOWN
|
||||||
const fixedFee = Number.parseFloat(tx.fixedFee) || 0
|
const fixedFee = Number.parseFloat(tx.fixedFee) || 0
|
||||||
const fiat = BigNumber(tx.fiat)
|
const fiat = BigNumber(tx.fiat).minus(fixedFee).toFixed(2, 1) // ROUND_DOWN
|
||||||
.minus(fixedFee)
|
|
||||||
.toFixed(2, 1) // ROUND_DOWN
|
|
||||||
const crypto = getCryptoAmount(tx)
|
const crypto = getCryptoAmount(tx)
|
||||||
const cryptoFee = tx.fee ? `${getCryptoFeeAmount(tx)} ${tx.fiatCode}` : 'N/A'
|
const cryptoFee = tx.fee ? `${getCryptoFeeAmount(tx)} ${tx.fiatCode}` : 'N/A'
|
||||||
const exchangeRate = BigNumber(fiat)
|
const exchangeRate = BigNumber(fiat).div(crypto).toFixed(2, 1) // ROUND_DOWN
|
||||||
.div(crypto)
|
|
||||||
.toFixed(2, 1) // ROUND_DOWN
|
|
||||||
const displayExRate = `1 ${tx.cryptoCode} = ${exchangeRate} ${tx.fiatCode}`
|
const displayExRate = `1 ${tx.cryptoCode} = ${exchangeRate} ${tx.fiatCode}`
|
||||||
const discount = tx.discount ? `-${tx.discount}%` : null
|
const discount = tx.discount ? `-${tx.discount}%` : null
|
||||||
|
|
||||||
|
|
@ -203,23 +199,22 @@ const DetailsRow = ({ it: tx, timezone }) => {
|
||||||
<div className={classes.walletScore}>
|
<div className={classes.walletScore}>
|
||||||
<svg width={103} height={10}>
|
<svg width={103} height={10}>
|
||||||
{R.range(0, 10).map((it, idx) => (
|
{R.range(0, 10).map((it, idx) => (
|
||||||
<circle
|
<circle
|
||||||
key={idx}
|
key={idx}
|
||||||
cx={it * 10 + 6}
|
cx={it * 10 + 6}
|
||||||
cy={4}
|
cy={4}
|
||||||
r={3.5}
|
r={3.5}
|
||||||
fill={
|
fill={
|
||||||
it < tx.walletScore
|
it < tx.walletScore
|
||||||
? !hasChainAnalysisError(tx)
|
? !hasChainAnalysisError(tx)
|
||||||
? primaryColor
|
? primaryColor
|
||||||
: errorColor
|
: errorColor
|
||||||
: !hasChainAnalysisError(tx)
|
: !hasChainAnalysisError(tx)
|
||||||
? subheaderColor
|
? subheaderColor
|
||||||
: offErrorColor
|
: offErrorColor
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)
|
))}
|
||||||
)}
|
|
||||||
</svg>
|
</svg>
|
||||||
<P
|
<P
|
||||||
noMargin
|
noMargin
|
||||||
|
|
|
||||||
|
|
@ -65,9 +65,7 @@ const ChooseType = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
inputType: Yup.string()
|
inputType: Yup.string().label('Input type').required()
|
||||||
.label('Input type')
|
|
||||||
.required()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const defaultValues = {
|
const defaultValues = {
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,8 @@ const Screen1Information = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
screen1Title: Yup.string()
|
screen1Title: Yup.string().label('Screen title').required(),
|
||||||
.label('Screen title')
|
screen1Text: Yup.string().label('Screen text').required()
|
||||||
.required(),
|
|
||||||
screen1Text: Yup.string()
|
|
||||||
.label('Screen text')
|
|
||||||
.required()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const defaultValues = {
|
const defaultValues = {
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,8 @@ const ScreenInformation = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
screen2Title: Yup.string()
|
screen2Title: Yup.string().label('Screen title').required(),
|
||||||
.label('Screen title')
|
screen2Text: Yup.string().label('Screen text').required()
|
||||||
.required(),
|
|
||||||
screen2Text: Yup.string()
|
|
||||||
.label('Screen text')
|
|
||||||
.required()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const defaultValues = {
|
const defaultValues = {
|
||||||
|
|
|
||||||
|
|
@ -40,38 +40,27 @@ const validationSchema = Yup.lazy(values => {
|
||||||
switch (values.inputType) {
|
switch (values.inputType) {
|
||||||
case 'numerical':
|
case 'numerical':
|
||||||
return Yup.object({
|
return Yup.object({
|
||||||
constraintType: Yup.string()
|
constraintType: Yup.string().label('Constraint type').required(),
|
||||||
.label('Constraint type')
|
|
||||||
.required(),
|
|
||||||
inputLength: Yup.number().when('constraintType', {
|
inputLength: Yup.number().when('constraintType', {
|
||||||
is: 'length',
|
is: 'length',
|
||||||
then: schema => schema
|
then: schema =>
|
||||||
.min(0)
|
schema.min(0).required('The number of digits is required'),
|
||||||
.required('The number of digits is required'),
|
|
||||||
otherwise: schema => schema.mixed().notRequired()
|
otherwise: schema => schema.mixed().notRequired()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
case 'text':
|
case 'text':
|
||||||
return Yup.object({
|
return Yup.object({
|
||||||
constraintType: Yup.string()
|
constraintType: Yup.string().label('Constraint type').required(),
|
||||||
.label('Constraint type')
|
inputLabel1: Yup.string().label('Text entry label').required(),
|
||||||
.required(),
|
|
||||||
inputLabel1: Yup.string()
|
|
||||||
.label('Text entry label')
|
|
||||||
.required(),
|
|
||||||
inputLabel2: Yup.string().when('constraintType', {
|
inputLabel2: Yup.string().when('constraintType', {
|
||||||
is: 'spaceSeparation',
|
is: 'spaceSeparation',
|
||||||
then: schema => schema
|
then: schema => schema.label('Second word label').required(),
|
||||||
.label('Second word label')
|
|
||||||
.required(),
|
|
||||||
otherwise: schema => schema.mixed().notRequired()
|
otherwise: schema => schema.mixed().notRequired()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
case 'choiceList':
|
case 'choiceList':
|
||||||
return Yup.object({
|
return Yup.object({
|
||||||
constraintType: Yup.string()
|
constraintType: Yup.string().label('Constraint type').required(),
|
||||||
.label('Constraint type')
|
|
||||||
.required(),
|
|
||||||
listChoices: Yup.array().test(
|
listChoices: Yup.array().test(
|
||||||
'has-2-or-more',
|
'has-2-or-more',
|
||||||
'Choice list needs to have two or more non empty fields',
|
'Choice list needs to have two or more non empty fields',
|
||||||
|
|
|
||||||
|
|
@ -65,9 +65,8 @@ const Triggers = () => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const [wizardType, setWizard] = useState(false)
|
const [wizardType, setWizard] = useState(false)
|
||||||
const { data, loading: configLoading, refetch } = useQuery(GET_CONFIG)
|
const { data, loading: configLoading, refetch } = useQuery(GET_CONFIG)
|
||||||
const { data: customInfoReqData, loading: customInfoLoading } = useQuery(
|
const { data: customInfoReqData, loading: customInfoLoading } =
|
||||||
GET_CUSTOM_REQUESTS
|
useQuery(GET_CUSTOM_REQUESTS)
|
||||||
)
|
|
||||||
const [error, setError] = useState(null)
|
const [error, setError] = useState(null)
|
||||||
const [subMenu, setSubMenu] = useState(false)
|
const [subMenu, setSubMenu] = useState(false)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,9 +45,8 @@ const AdvancedTriggersSettings = memo(() => {
|
||||||
const [isEditingOverrides, setEditingOverrides] = useState(false)
|
const [isEditingOverrides, setEditingOverrides] = useState(false)
|
||||||
|
|
||||||
const { data, loading: configLoading } = useQuery(GET_INFO)
|
const { data, loading: configLoading } = useQuery(GET_INFO)
|
||||||
const { data: customInfoReqData, loading: customInfoLoading } = useQuery(
|
const { data: customInfoReqData, loading: customInfoLoading } =
|
||||||
GET_CUSTOM_REQUESTS
|
useQuery(GET_CUSTOM_REQUESTS)
|
||||||
)
|
|
||||||
|
|
||||||
const customInfoRequests =
|
const customInfoRequests =
|
||||||
R.path(['customInfoRequests'])(customInfoReqData) ?? []
|
R.path(['customInfoRequests'])(customInfoReqData) ?? []
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,7 @@ const displayRequirement = (code, customInfoRequests) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultSchema = Yup.object().shape({
|
const defaultSchema = Yup.object().shape({
|
||||||
expirationTime: Yup.string()
|
expirationTime: Yup.string().label('Expiration time').required(),
|
||||||
.label('Expiration time')
|
|
||||||
.required(),
|
|
||||||
automation: Yup.string()
|
automation: Yup.string()
|
||||||
.label('Automation')
|
.label('Automation')
|
||||||
.matches(/(Manual|Automatic)/)
|
.matches(/(Manual|Automatic)/)
|
||||||
|
|
@ -60,9 +58,7 @@ const getOverridesSchema = (values, customInfoRequests) => {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
expirationTime: Yup.string()
|
expirationTime: Yup.string().label('Expiration time').required(),
|
||||||
.label('Expiration time')
|
|
||||||
.required(),
|
|
||||||
automation: Yup.string()
|
automation: Yup.string()
|
||||||
.label('Automation')
|
.label('Automation')
|
||||||
.matches(/(Manual|Automatic)/)
|
.matches(/(Manual|Automatic)/)
|
||||||
|
|
|
||||||
|
|
@ -110,9 +110,7 @@ const threshold = Yup.object().shape({
|
||||||
|
|
||||||
const requirement = Yup.object().shape({
|
const requirement = Yup.object().shape({
|
||||||
requirement: Yup.string().required(),
|
requirement: Yup.string().required(),
|
||||||
suspensionDays: Yup.number()
|
suspensionDays: Yup.number().transform(transformNumber).nullable()
|
||||||
.transform(transformNumber)
|
|
||||||
.nullable()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const Schema = Yup.object()
|
const Schema = Yup.object()
|
||||||
|
|
@ -266,12 +264,8 @@ const typeSchema = Yup.object()
|
||||||
'The trigger type is required'
|
'The trigger type is required'
|
||||||
),
|
),
|
||||||
threshold: Yup.object({
|
threshold: Yup.object({
|
||||||
threshold: Yup.number()
|
threshold: Yup.number().transform(transformNumber).nullable(),
|
||||||
.transform(transformNumber)
|
thresholdDays: Yup.number().transform(transformNumber).nullable()
|
||||||
.nullable(),
|
|
||||||
thresholdDays: Yup.number()
|
|
||||||
.transform(transformNumber)
|
|
||||||
.nullable()
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.test(({ threshold, triggerType }, context) => {
|
.test(({ threshold, triggerType }, context) => {
|
||||||
|
|
@ -327,13 +321,8 @@ const typeOptions = [
|
||||||
|
|
||||||
const Type = ({ ...props }) => {
|
const Type = ({ ...props }) => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const {
|
const { errors, touched, values, setTouched, handleChange } =
|
||||||
errors,
|
useFormikContext()
|
||||||
touched,
|
|
||||||
values,
|
|
||||||
setTouched,
|
|
||||||
handleChange
|
|
||||||
} = useFormikContext()
|
|
||||||
|
|
||||||
const typeClass = {
|
const typeClass = {
|
||||||
[classes.error]: errors.triggerType && touched.triggerType
|
[classes.error]: errors.triggerType && touched.triggerType
|
||||||
|
|
@ -484,24 +473,16 @@ const requirementSchema = Yup.object()
|
||||||
requirement: Yup.string().required(),
|
requirement: Yup.string().required(),
|
||||||
suspensionDays: Yup.number().when('requirement', {
|
suspensionDays: Yup.number().when('requirement', {
|
||||||
is: value => value === 'suspend',
|
is: value => value === 'suspend',
|
||||||
then: schema => schema
|
then: schema => schema.nullable().transform(transformNumber),
|
||||||
.nullable()
|
otherwise: schema => schema.nullable().transform(() => null)
|
||||||
.transform(transformNumber),
|
|
||||||
otherwise: schema => schema
|
|
||||||
.nullable()
|
|
||||||
.transform(() => null)
|
|
||||||
}),
|
}),
|
||||||
customInfoRequestId: Yup.string().when('requirement', {
|
customInfoRequestId: Yup.string().when('requirement', {
|
||||||
is: value => value !== 'custom',
|
is: value => value !== 'custom',
|
||||||
then: schema => schema
|
then: schema => schema.nullable().transform(() => '')
|
||||||
.nullable()
|
|
||||||
.transform(() => '')
|
|
||||||
}),
|
}),
|
||||||
externalService: Yup.string().when('requirement', {
|
externalService: Yup.string().when('requirement', {
|
||||||
is: value => value !== 'external',
|
is: value => value !== 'external',
|
||||||
then: schema => schema
|
then: schema => schema.nullable().transform(() => '')
|
||||||
.nullable()
|
|
||||||
.transform(() => '')
|
|
||||||
})
|
})
|
||||||
}).required()
|
}).required()
|
||||||
})
|
})
|
||||||
|
|
@ -583,13 +564,8 @@ const Requirement = ({
|
||||||
customInfoRequests = []
|
customInfoRequests = []
|
||||||
}) => {
|
}) => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const {
|
const { touched, errors, values, handleChange, setTouched } =
|
||||||
touched,
|
useFormikContext()
|
||||||
errors,
|
|
||||||
values,
|
|
||||||
handleChange,
|
|
||||||
setTouched
|
|
||||||
} = useFormikContext()
|
|
||||||
|
|
||||||
const isSuspend = values?.requirement?.requirement === 'suspend'
|
const isSuspend = values?.requirement?.requirement === 'suspend'
|
||||||
const isCustom = values?.requirement?.requirement === 'custom'
|
const isCustom = values?.requirement?.requirement === 'custom'
|
||||||
|
|
@ -766,9 +742,9 @@ const RequirementInput = ({ customInfoRequests = [] }) => {
|
||||||
R.path(['requirement', 'customInfoRequestId'])(values) ?? ''
|
R.path(['requirement', 'customInfoRequestId'])(values) ?? ''
|
||||||
const isSuspend = requirement === 'suspend'
|
const isSuspend = requirement === 'suspend'
|
||||||
const display = customRequestId
|
const display = customRequestId
|
||||||
? R.path(['customRequest', 'name'])(
|
? (R.path(['customRequest', 'name'])(
|
||||||
R.find(customReqIdMatches(customRequestId))(customInfoRequests)
|
R.find(customReqIdMatches(customRequestId))(customInfoRequests)
|
||||||
) ?? ''
|
) ?? '')
|
||||||
: getView(requirementOptions, 'display')(requirement)
|
: getView(requirementOptions, 'display')(requirement)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -798,12 +774,12 @@ const RequirementView = ({
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const display =
|
const display =
|
||||||
requirement === 'custom'
|
requirement === 'custom'
|
||||||
? R.path(['customRequest', 'name'])(
|
? (R.path(['customRequest', 'name'])(
|
||||||
R.find(customReqIdMatches(customInfoRequestId))(customInfoRequests)
|
R.find(customReqIdMatches(customInfoRequestId))(customInfoRequests)
|
||||||
) ?? ''
|
) ?? '')
|
||||||
: requirement === 'external'
|
: requirement === 'external'
|
||||||
? `External verification (${onlyFirstToUpper(externalService)})`
|
? `External verification (${onlyFirstToUpper(externalService)})`
|
||||||
: getView(requirementOptions, 'display')(requirement)
|
: getView(requirementOptions, 'display')(requirement)
|
||||||
const isSuspend = requirement === 'suspend'
|
const isSuspend = requirement === 'suspend'
|
||||||
return (
|
return (
|
||||||
<Box display="flex" alignItems="baseline">
|
<Box display="flex" alignItems="baseline">
|
||||||
|
|
|
||||||
|
|
@ -119,11 +119,10 @@ const Routes = () => {
|
||||||
{...transitionProps}
|
{...transitionProps}
|
||||||
in={true}
|
in={true}
|
||||||
mountOnEnter
|
mountOnEnter
|
||||||
unmountOnExit
|
unmountOnExit>
|
||||||
>
|
<div className={classes.wrapper}>
|
||||||
<div className={classes.wrapper}>
|
<Dashboard />
|
||||||
<Dashboard />
|
</div>
|
||||||
</div>
|
|
||||||
</Transition>
|
</Transition>
|
||||||
</PrivateRoute>
|
</PrivateRoute>
|
||||||
<PrivateRoute path="/machines" component={Machines} />
|
<PrivateRoute path="/machines" component={Machines} />
|
||||||
|
|
@ -139,19 +138,18 @@ const Routes = () => {
|
||||||
{...transitionProps}
|
{...transitionProps}
|
||||||
in={!!matchPath(location.pathname, { path: route })}
|
in={!!matchPath(location.pathname, { path: route })}
|
||||||
mountOnEnter
|
mountOnEnter
|
||||||
unmountOnExit
|
unmountOnExit>
|
||||||
>
|
|
||||||
<div className={classes.wrapper}>
|
<div className={classes.wrapper}>
|
||||||
<PrivateRoute path={route} key={key}>
|
<PrivateRoute path={route} key={key}>
|
||||||
<Page name={key}/>
|
<Page name={key} />
|
||||||
</PrivateRoute>
|
</PrivateRoute>
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
</PrivateRoute>
|
</PrivateRoute>
|
||||||
))}
|
))}
|
||||||
<PublicRoute path="/404"/>
|
<PublicRoute path="/404" />
|
||||||
<PublicRoute path="*">
|
<PublicRoute path="*">
|
||||||
<Redirect to={{ pathname: '/404' }}/>
|
<Redirect to={{ pathname: '/404' }} />
|
||||||
</PublicRoute>
|
</PublicRoute>
|
||||||
</Switch>
|
</Switch>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ const WALLET_SCORING_DEFAULT_THRESHOLD = 9
|
||||||
const AUTOMATIC = 'automatic'
|
const AUTOMATIC = 'automatic'
|
||||||
const MANUAL = 'manual'
|
const MANUAL = 'manual'
|
||||||
|
|
||||||
const IP_CHECK_REGEX = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
|
const IP_CHECK_REGEX =
|
||||||
|
/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
|
||||||
|
|
||||||
const SWEEPABLE_CRYPTOS = ['ETH']
|
const SWEEPABLE_CRYPTOS = ['ETH']
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,10 @@ const formatName = idCardData => {
|
||||||
firstName && lastName
|
firstName && lastName
|
||||||
? `${R.o(R.toUpper, R.head)(firstName)}. ${lastName}`
|
? `${R.o(R.toUpper, R.head)(firstName)}. ${lastName}`
|
||||||
: R.isNil(firstName)
|
: R.isNil(firstName)
|
||||||
? lastName
|
? lastName
|
||||||
: R.isNil(lastName)
|
: R.isNil(lastName)
|
||||||
? firstName
|
? firstName
|
||||||
: null
|
: null
|
||||||
return idCardData ? innerFormatName(idCardData) : null
|
return idCardData ? innerFormatName(idCardData) : null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,7 @@ const splitOnUpper = R.compose(
|
||||||
R.replace(/([A-Z])/g, ' $1'),
|
R.replace(/([A-Z])/g, ' $1'),
|
||||||
toFirstLower
|
toFirstLower
|
||||||
)
|
)
|
||||||
const startCase = R.compose(
|
const startCase = R.compose(R.join(' '), R.map(onlyFirstToUpper), splitOnUpper)
|
||||||
R.join(' '),
|
|
||||||
R.map(onlyFirstToUpper),
|
|
||||||
splitOnUpper
|
|
||||||
)
|
|
||||||
|
|
||||||
const sentenceCase = R.compose(onlyFirstToUpper, R.join(' '), splitOnUpper)
|
const sentenceCase = R.compose(onlyFirstToUpper, R.join(' '), splitOnUpper)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,9 @@ import fixReactVirtualized from 'esbuild-plugin-react-virtualized'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
base: '/',
|
base: '/',
|
||||||
|
build: {
|
||||||
|
outDir: 'build'
|
||||||
|
},
|
||||||
server: {
|
server: {
|
||||||
port: 3001,
|
port: 3001,
|
||||||
proxy: {
|
proxy: {
|
||||||
|
|
@ -19,18 +22,13 @@ export default defineConfig({
|
||||||
},
|
},
|
||||||
optimizeDeps: {
|
optimizeDeps: {
|
||||||
esbuildOptions: {
|
esbuildOptions: {
|
||||||
plugins: [
|
plugins: [fixReactVirtualized]
|
||||||
fixReactVirtualized,
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [react(), svgr()],
|
||||||
react(),
|
|
||||||
svgr(),
|
|
||||||
],
|
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'src': fileURLToPath(new URL('./src', import.meta.url))
|
src: fileURLToPath(new URL('./src', import.meta.url))
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue