feat: add operator info page
feat: save/load operator info feat: add formik switch component feat: add input validation fix: correct formik switch behaviour fix: change infoCardEnabled to a radio input style: move styles out of js feat: add error feedback
This commit is contained in:
parent
b9d2341cd1
commit
7b59e36cb4
10 changed files with 516 additions and 18 deletions
41
new-lamassu-admin/src/components/ErrorMessage.js
Normal file
41
new-lamassu-admin/src/components/ErrorMessage.js
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
import React from 'react'
|
||||||
|
import classnames from 'classnames'
|
||||||
|
import { makeStyles } from '@material-ui/core'
|
||||||
|
|
||||||
|
import { ReactComponent as ErrorIcon } from 'src/styling/icons/warning-icon/tomato.svg'
|
||||||
|
import { errorColor } from 'src/styling/variables'
|
||||||
|
|
||||||
|
import { Info3 } from './typography'
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
wrapper: {
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
'& > svg': {
|
||||||
|
marginRight: 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
color: errorColor,
|
||||||
|
margin: 0,
|
||||||
|
whiteSpace: 'break-spaces',
|
||||||
|
width: 250
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const useStyles = makeStyles(styles)
|
||||||
|
|
||||||
|
const ErrorMessage = ({ className, children, ...props }) => {
|
||||||
|
const classes = useStyles()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classnames(classes.wrapper, className)}>
|
||||||
|
<ErrorIcon />
|
||||||
|
<Info3 className={classes.message}>{children}</Info3>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ErrorMessage
|
||||||
|
|
@ -48,12 +48,12 @@ const RadioGroup = ({
|
||||||
value={value}
|
value={value}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
className={classnames(className)}>
|
className={classnames(className)}>
|
||||||
{options.map((options, idx) => (
|
{options.map((option, idx) => (
|
||||||
<Label
|
<Label
|
||||||
key={idx}
|
key={idx}
|
||||||
value={options.value}
|
value={option.value}
|
||||||
control={<GreenRadio />}
|
control={<GreenRadio />}
|
||||||
label={options.label}
|
label={option.label}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</MaterialRadioGroup>
|
</MaterialRadioGroup>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
import Checkbox from './Checkbox'
|
import Checkbox from './Checkbox'
|
||||||
import TextInput from './TextInput'
|
import TextInput from './TextInput'
|
||||||
|
import Switch from './Switch'
|
||||||
|
import RadioGroup from './RadioGroup'
|
||||||
|
|
||||||
export { Checkbox, TextInput }
|
export { Checkbox, TextInput, Switch, RadioGroup }
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,9 @@ 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 => value.replace(mask, '$1 $2 $3 $4 $5 $6')
|
const maskValue = value =>
|
||||||
|
value ? value.replace(mask, '$1 $2 $3 $4 $5 $6') : ''
|
||||||
|
|
||||||
const PhoneNumberInputFormik = memo(({ ...props }) => {
|
const PhoneNumberInputFormik = memo(({ ...props }) => {
|
||||||
const { onChange, value } = props.field
|
const { onChange, value } = props.field
|
||||||
|
|
|
||||||
42
new-lamassu-admin/src/components/inputs/formik/RadioGroup.js
Normal file
42
new-lamassu-admin/src/components/inputs/formik/RadioGroup.js
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
import React, { memo } from 'react'
|
||||||
|
import { makeStyles } from '@material-ui/core'
|
||||||
|
|
||||||
|
import { Label1 } from 'src/components/typography'
|
||||||
|
|
||||||
|
import { RadioGroup } from '../base'
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
label: {
|
||||||
|
height: 16,
|
||||||
|
lineHeight: '16px',
|
||||||
|
margin: [[0, 0, 4, 0]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const useStyles = makeStyles(styles)
|
||||||
|
|
||||||
|
const RadioGroupFormik = memo(({ ...props }) => {
|
||||||
|
const classes = useStyles()
|
||||||
|
|
||||||
|
const { name, onChange, value } = props.field
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{props.label && <Label1 className={classes.label}>{props.label}</Label1>}
|
||||||
|
<RadioGroup
|
||||||
|
name={name}
|
||||||
|
value={value}
|
||||||
|
options={props.options}
|
||||||
|
ariaLabel={name}
|
||||||
|
onChange={e => {
|
||||||
|
onChange(e)
|
||||||
|
props.resetError()
|
||||||
|
}}
|
||||||
|
className={props.className}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
export default RadioGroupFormik
|
||||||
304
new-lamassu-admin/src/pages/OperatorInfo/ContactInfo.js
Normal file
304
new-lamassu-admin/src/pages/OperatorInfo/ContactInfo.js
Normal file
|
|
@ -0,0 +1,304 @@
|
||||||
|
import React, { useState } from 'react'
|
||||||
|
import classnames from 'classnames'
|
||||||
|
import * as R from 'ramda'
|
||||||
|
import * as Yup from 'yup'
|
||||||
|
import { gql } from 'apollo-boost'
|
||||||
|
import { Form, Formik, Field as FormikField } from 'formik'
|
||||||
|
import { makeStyles } from '@material-ui/core'
|
||||||
|
import { useQuery, useMutation } from '@apollo/react-hooks'
|
||||||
|
|
||||||
|
import { Info2, Info3, Label1 } from 'src/components/typography'
|
||||||
|
import TextInputFormik from 'src/components/inputs/formik/TextInput'
|
||||||
|
import RadioGroupFormik from 'src/components/inputs/formik/RadioGroup'
|
||||||
|
import {
|
||||||
|
PhoneNumberInputFormik,
|
||||||
|
maskValue,
|
||||||
|
mask
|
||||||
|
} from 'src/components/inputs/formik/PhoneNumberInput'
|
||||||
|
import { Link } from 'src/components/buttons'
|
||||||
|
import ErrorMessage from 'src/components/ErrorMessage'
|
||||||
|
import { ReactComponent as EditIcon } from 'src/styling/icons/action/edit/enabled.svg'
|
||||||
|
import { ReactComponent as WarningIcon } from 'src/styling/icons/warning-icon/comet.svg'
|
||||||
|
|
||||||
|
import {
|
||||||
|
styles as globalStyles,
|
||||||
|
contactInfoStyles
|
||||||
|
} from './OperatorInfo.styles'
|
||||||
|
|
||||||
|
const fieldStyles = {
|
||||||
|
field: {
|
||||||
|
position: 'relative',
|
||||||
|
width: 280,
|
||||||
|
height: 46,
|
||||||
|
padding: [[0, 4, 4, 4]]
|
||||||
|
},
|
||||||
|
notEditing: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
'& > p:first-child': {
|
||||||
|
height: 16,
|
||||||
|
lineHeight: '16px',
|
||||||
|
margin: [[0, 0, 4, 0]]
|
||||||
|
},
|
||||||
|
'& > p:last-child': {
|
||||||
|
margin: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fieldUseStyles = makeStyles(fieldStyles)
|
||||||
|
|
||||||
|
const Field = ({ editing, field, displayValue, ...props }) => {
|
||||||
|
const classes = fieldUseStyles()
|
||||||
|
|
||||||
|
const classNames = {
|
||||||
|
[classes.field]: true,
|
||||||
|
[classes.notEditing]: !editing
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className={classnames(classNames)}>
|
||||||
|
{!editing && (
|
||||||
|
<>
|
||||||
|
<Label1>{field.label}</Label1>
|
||||||
|
<Info3>{displayValue(field.value)}</Info3>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{editing && (
|
||||||
|
<FormikField
|
||||||
|
id={field.name}
|
||||||
|
name={field.name}
|
||||||
|
component={field.component}
|
||||||
|
placeholder={field.placeholder}
|
||||||
|
type={field.type}
|
||||||
|
label={field.label}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const GET_CONFIG = gql`
|
||||||
|
{
|
||||||
|
config
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const SAVE_CONFIG = gql`
|
||||||
|
mutation Save($config: JSONObject) {
|
||||||
|
saveConfig(config: $config)
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const INFO_CARD_ENABLED = 'On'
|
||||||
|
const INFO_CARD_DISABLED = 'Off'
|
||||||
|
|
||||||
|
const styles = R.merge(globalStyles, contactInfoStyles)
|
||||||
|
|
||||||
|
const contactUseStyles = makeStyles(styles)
|
||||||
|
|
||||||
|
const ContactInfo = () => {
|
||||||
|
const [editing, setEditing] = useState(false)
|
||||||
|
const [info, setInfo] = useState(null)
|
||||||
|
const [error, setError] = useState(null)
|
||||||
|
const [saveConfig] = useMutation(SAVE_CONFIG, {
|
||||||
|
onCompleted: data => {
|
||||||
|
const { operatorInfo } = data.saveConfig
|
||||||
|
setInfo(operatorInfo)
|
||||||
|
setEditing(false)
|
||||||
|
},
|
||||||
|
onError: e => setError(e)
|
||||||
|
})
|
||||||
|
|
||||||
|
useQuery(GET_CONFIG, {
|
||||||
|
onCompleted: data => {
|
||||||
|
const operatorInfo = data.config
|
||||||
|
setInfo(operatorInfo ?? {})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const save = it => {
|
||||||
|
return saveConfig({ variables: { config: { operatorInfo: it } } })
|
||||||
|
}
|
||||||
|
|
||||||
|
const classes = contactUseStyles()
|
||||||
|
|
||||||
|
if (!info) return null
|
||||||
|
|
||||||
|
const fields = [
|
||||||
|
{
|
||||||
|
name: 'infoCardEnabled',
|
||||||
|
label: 'Info Card Enabled',
|
||||||
|
value: info.infoCardEnabled ?? INFO_CARD_DISABLED,
|
||||||
|
type: 'select',
|
||||||
|
component: RadioGroupFormik
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'fullName',
|
||||||
|
label: 'Full name',
|
||||||
|
value: info.fullName ?? '',
|
||||||
|
type: 'text',
|
||||||
|
component: TextInputFormik
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'phoneNumber',
|
||||||
|
label: 'Phone number',
|
||||||
|
value: maskValue(info.phoneNumber) ?? '',
|
||||||
|
type: 'text',
|
||||||
|
component: PhoneNumberInputFormik
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'email',
|
||||||
|
label: 'Email',
|
||||||
|
value: info.email ?? '',
|
||||||
|
type: 'text',
|
||||||
|
component: TextInputFormik
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'website',
|
||||||
|
label: 'Website',
|
||||||
|
value: info.website ?? '',
|
||||||
|
type: 'text',
|
||||||
|
component: TextInputFormik
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'companyNumber',
|
||||||
|
label: 'Company number',
|
||||||
|
value: info.companyNumber ?? '',
|
||||||
|
type: 'text',
|
||||||
|
component: TextInputFormik
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const findField = name => R.find(R.propEq('name', name))(fields)
|
||||||
|
const findValue = name => findField(name).value
|
||||||
|
|
||||||
|
const displayTextValue = value => value
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className={classes.header}>
|
||||||
|
<Info2>Contact information</Info2>
|
||||||
|
{!editing && (
|
||||||
|
<button onClick={() => setEditing(true)}>
|
||||||
|
<EditIcon />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className={classes.section}>
|
||||||
|
<Formik
|
||||||
|
initialValues={{
|
||||||
|
infoCardEnabled: findValue('infoCardEnabled'),
|
||||||
|
fullName: findValue('fullName'),
|
||||||
|
phoneNumber: info.phoneNumber ?? '',
|
||||||
|
email: findValue('email'),
|
||||||
|
website: findValue('website'),
|
||||||
|
companyNumber: findValue('companyNumber')
|
||||||
|
}}
|
||||||
|
validationSchema={Yup.object().shape({
|
||||||
|
fullName: Yup.string().max(100, 'Too long'),
|
||||||
|
phoneNumber: Yup.string()
|
||||||
|
.matches(mask, { excludeEmptyString: true })
|
||||||
|
.max(100, 'Too long'),
|
||||||
|
email: Yup.string()
|
||||||
|
.email('Please enter a valid email address')
|
||||||
|
.max(100, 'Too long'),
|
||||||
|
website: Yup.string()
|
||||||
|
.url('Please enter a valid url')
|
||||||
|
.max(100, 'Too long'),
|
||||||
|
companyNumber: Yup.string().max(30, 'Too long')
|
||||||
|
})}
|
||||||
|
onSubmit={values => {
|
||||||
|
save(values)
|
||||||
|
}}>
|
||||||
|
<Form>
|
||||||
|
<div className={classnames(classes.row, classes.radioButtonsRow)}>
|
||||||
|
<Field
|
||||||
|
field={findField('infoCardEnabled')}
|
||||||
|
editing={editing}
|
||||||
|
displayValue={displayTextValue}
|
||||||
|
options={[
|
||||||
|
{ label: 'On', value: INFO_CARD_ENABLED },
|
||||||
|
{ label: 'Off', value: INFO_CARD_DISABLED }
|
||||||
|
]}
|
||||||
|
className={classes.radioButtons}
|
||||||
|
resetError={() => setError(null)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={classes.row}>
|
||||||
|
<Field
|
||||||
|
field={findField('fullName')}
|
||||||
|
editing={editing}
|
||||||
|
displayValue={displayTextValue}
|
||||||
|
onFocus={() => setError(null)}
|
||||||
|
/>
|
||||||
|
<Field
|
||||||
|
field={findField('phoneNumber')}
|
||||||
|
editing={editing}
|
||||||
|
displayValue={displayTextValue}
|
||||||
|
onFocus={() => setError(null)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={classes.row}>
|
||||||
|
<Field
|
||||||
|
field={findField('email')}
|
||||||
|
editing={editing}
|
||||||
|
displayValue={displayTextValue}
|
||||||
|
onFocus={() => setError(null)}
|
||||||
|
/>
|
||||||
|
<Field
|
||||||
|
field={findField('website')}
|
||||||
|
editing={editing}
|
||||||
|
displayValue={displayTextValue}
|
||||||
|
onFocus={() => setError(null)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={classes.row}>
|
||||||
|
<Field
|
||||||
|
field={findField('companyNumber')}
|
||||||
|
editing={editing}
|
||||||
|
displayValue={displayTextValue}
|
||||||
|
onFocus={() => setError(null)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={classnames(classes.row, classes.submit)}>
|
||||||
|
{editing && (
|
||||||
|
<>
|
||||||
|
<Link color="primary" type="submit">
|
||||||
|
Save
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
color="secondary"
|
||||||
|
onClick={() => {
|
||||||
|
setEditing(false)
|
||||||
|
setError(null)
|
||||||
|
}}>
|
||||||
|
Cancel
|
||||||
|
</Link>
|
||||||
|
{error && (
|
||||||
|
<ErrorMessage className={classes.errorMessage}>
|
||||||
|
Failed to save changes
|
||||||
|
</ErrorMessage>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
</Formik>
|
||||||
|
</div>
|
||||||
|
<div className={classnames(classes.section, classes.infoMessage)}>
|
||||||
|
<WarningIcon />
|
||||||
|
<Label1>
|
||||||
|
Sharing your information with your customers through your machines
|
||||||
|
allows them to contact you in case there's a problem with a machine in
|
||||||
|
your network or a transaction.
|
||||||
|
</Label1>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ContactInfo
|
||||||
58
new-lamassu-admin/src/pages/OperatorInfo/OperatorInfo.js
Normal file
58
new-lamassu-admin/src/pages/OperatorInfo/OperatorInfo.js
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
import React, { useState } from 'react'
|
||||||
|
import * as R from 'ramda'
|
||||||
|
import { makeStyles } from '@material-ui/core'
|
||||||
|
|
||||||
|
import Sidebar from 'src/components/Sidebar'
|
||||||
|
import Title from 'src/components/Title'
|
||||||
|
|
||||||
|
import logsStyles from '../Logs.styles'
|
||||||
|
|
||||||
|
import ContactInfo from './ContactInfo'
|
||||||
|
|
||||||
|
const localStyles = {
|
||||||
|
contentWrapper: {
|
||||||
|
marginLeft: 48,
|
||||||
|
paddingTop: 15
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = R.merge(logsStyles, localStyles)
|
||||||
|
|
||||||
|
const useStyles = makeStyles(styles)
|
||||||
|
|
||||||
|
const CONTACT_INFORMATION = 'Contact information'
|
||||||
|
const RECEIPT = 'Receipt'
|
||||||
|
const COIN_ATM_RADAR = 'Coin ATM Radar'
|
||||||
|
const TERMS_CONDITIONS = 'Terms & Conditions'
|
||||||
|
|
||||||
|
const pages = [CONTACT_INFORMATION, RECEIPT, COIN_ATM_RADAR, TERMS_CONDITIONS]
|
||||||
|
|
||||||
|
const OperatorInfo = () => {
|
||||||
|
const [selected, setSelected] = useState(CONTACT_INFORMATION)
|
||||||
|
const classes = useStyles()
|
||||||
|
|
||||||
|
const isSelected = it => selected === it
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className={classes.titleWrapper}>
|
||||||
|
<div className={classes.titleAndButtonsContainer}>
|
||||||
|
<Title>Operator information</Title>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={classes.wrapper}>
|
||||||
|
<Sidebar
|
||||||
|
data={pages}
|
||||||
|
isSelected={isSelected}
|
||||||
|
displayName={it => it}
|
||||||
|
onClick={it => setSelected(it)}
|
||||||
|
/>
|
||||||
|
<div className={classes.contentWrapper}>
|
||||||
|
{isSelected(CONTACT_INFORMATION) && <ContactInfo />}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default OperatorInfo
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
import { offColor } from 'src/styling/variables'
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
header: {
|
||||||
|
display: 'flex',
|
||||||
|
'& > button': {
|
||||||
|
border: 'none',
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
marginLeft: 20,
|
||||||
|
cursor: 'pointer'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
section: {
|
||||||
|
marginBottom: 52
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const contactInfoStyles = {
|
||||||
|
row: {
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
marginBottom: 28,
|
||||||
|
'&:last-child': {
|
||||||
|
marginBottom: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
infoMessage: {
|
||||||
|
display: 'flex',
|
||||||
|
marginBottom: 52,
|
||||||
|
'& > p': {
|
||||||
|
width: 330,
|
||||||
|
color: offColor,
|
||||||
|
marginTop: 4,
|
||||||
|
marginLeft: 16
|
||||||
|
}
|
||||||
|
},
|
||||||
|
radioButtonsRow: {
|
||||||
|
height: 60
|
||||||
|
},
|
||||||
|
radioButtons: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row'
|
||||||
|
},
|
||||||
|
submit: {
|
||||||
|
justifyContent: 'flex-start',
|
||||||
|
padding: [[0, 4, 4, 4]],
|
||||||
|
height: 20,
|
||||||
|
'& > button': {
|
||||||
|
marginRight: 40
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { styles, contactInfoStyles }
|
||||||
|
|
@ -10,6 +10,7 @@ import ServerLogs from 'src/pages/ServerLogs'
|
||||||
import Transactions from 'src/pages/Transactions/Transactions'
|
import Transactions from 'src/pages/Transactions/Transactions'
|
||||||
import Services from 'src/pages/Services/Services'
|
import Services from 'src/pages/Services/Services'
|
||||||
import AuthRegister from 'src/pages/AuthRegister'
|
import AuthRegister from 'src/pages/AuthRegister'
|
||||||
|
import OperatorInfo from 'src/pages/OperatorInfo/OperatorInfo'
|
||||||
|
|
||||||
const tree = [
|
const tree = [
|
||||||
{ key: 'transactions', label: 'Transactions', route: '/transactions' },
|
{ key: 'transactions', label: 'Transactions', route: '/transactions' },
|
||||||
|
|
@ -44,7 +45,8 @@ const tree = [
|
||||||
key: 'services',
|
key: 'services',
|
||||||
label: '3rd party services',
|
label: '3rd party services',
|
||||||
route: '/settings/3rd-party-services'
|
route: '/settings/3rd-party-services'
|
||||||
}
|
},
|
||||||
|
{ key: 'info', label: 'Operator Info', route: '/settings/operator-info' }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
// compliance: { label: 'Compliance', children: [{ label: 'Locale', route: '/locale' }] }
|
// compliance: { label: 'Compliance', children: [{ label: 'Locale', route: '/locale' }] }
|
||||||
|
|
@ -72,6 +74,7 @@ const Routes = () => (
|
||||||
<Route path="/settings/commissions" component={Commissions} />
|
<Route path="/settings/commissions" component={Commissions} />
|
||||||
<Route path="/settings/locale" component={Locales} />
|
<Route path="/settings/locale" component={Locales} />
|
||||||
<Route path="/settings/3rd-party-services" component={Services} />
|
<Route path="/settings/3rd-party-services" component={Services} />
|
||||||
|
<Route path="/settings/operator-info" component={OperatorInfo} />
|
||||||
<Route path="/maintenance/logs" component={Logs} />
|
<Route path="/maintenance/logs" component={Logs} />
|
||||||
<Route path="/maintenance/funding" component={Funding} />
|
<Route path="/maintenance/funding" component={Funding} />
|
||||||
<Route path="/maintenance/server-logs" component={ServerLogs} />
|
<Route path="/maintenance/server-logs" component={ServerLogs} />
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,10 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<svg width="22px" height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
<svg width="22px" height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<!-- Generator: Sketch 60.1 (88133) - https://sketch.com -->
|
<!-- Generator: Sketch 61.2 (89653) - https://sketch.com -->
|
||||||
<title>icon/action/edit/enabled</title>
|
<title>icon/action/edit/enabled</title>
|
||||||
<desc>Created with Sketch.</desc>
|
<desc>Created with Sketch.</desc>
|
||||||
<defs>
|
<g id="icon/action/edit/enabled" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
|
||||||
<rect id="path-1" x="0" y="0" width="22" height="22"></rect>
|
<path d="M1,18 L1,18 C1,19.657 2.343,21 4,21 L18,21 C19.657,21 21,19.657 21,18" id="Stroke-1" stroke="#1B2559" stroke-width="2"></path>
|
||||||
</defs>
|
<polygon id="Stroke-3" stroke="#1B2559" stroke-width="2" points="6 12 17 1 21 5 10 16 6 16"></polygon>
|
||||||
<g id="icon/action/edit/enabled" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
|
||||||
<mask id="mask-2" fill="white">
|
|
||||||
<use xlink:href="#path-1"></use>
|
|
||||||
</mask>
|
|
||||||
<g id="Background"></g>
|
|
||||||
<path d="M1,18 L1,18 C1,19.657 2.343,21 4,21 L18,21 C19.657,21 21,19.657 21,18" id="Stroke-1" stroke="#1B2559" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" mask="url(#mask-2)"></path>
|
|
||||||
<polygon id="Stroke-3" stroke="#1B2559" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" mask="url(#mask-2)" points="6 12 17 1 21 5 10 16 6 16"></polygon>
|
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 749 B |
Loading…
Add table
Add a link
Reference in a new issue