partial: second batch of components
This commit is contained in:
parent
8cd7374ee8
commit
9f4bf1de7b
35 changed files with 616 additions and 1044 deletions
|
|
@ -1,5 +1,4 @@
|
||||||
import { useQuery, useMutation, gql } from "@apollo/client";
|
import { useQuery, useMutation, gql } from '@apollo/client'
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useState, useEffect } from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
import ActionButton from 'src/components/buttons/ActionButton'
|
import ActionButton from 'src/components/buttons/ActionButton'
|
||||||
|
|
@ -9,10 +8,8 @@ import ClearAllIconInverse from 'src/styling/icons/stage/spring/empty.svg?react'
|
||||||
import ClearAllIcon from 'src/styling/icons/stage/zodiac/empty.svg?react'
|
import ClearAllIcon from 'src/styling/icons/stage/zodiac/empty.svg?react'
|
||||||
import ShowUnreadIcon from 'src/styling/icons/stage/zodiac/full.svg?react'
|
import ShowUnreadIcon from 'src/styling/icons/stage/zodiac/full.svg?react'
|
||||||
|
|
||||||
import styles from './NotificationCenter.styles'
|
|
||||||
import NotificationRow from './NotificationRow'
|
import NotificationRow from './NotificationRow'
|
||||||
|
import classes from './NotificationCenter.module.css'
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const GET_NOTIFICATIONS = gql`
|
const GET_NOTIFICATIONS = gql`
|
||||||
query getNotifications {
|
query getNotifications {
|
||||||
|
|
@ -63,7 +60,6 @@ const NotificationCenter = ({
|
||||||
const [xOffset, setXoffset] = useState(300)
|
const [xOffset, setXoffset] = useState(300)
|
||||||
|
|
||||||
const [showingUnread, setShowingUnread] = useState(false)
|
const [showingUnread, setShowingUnread] = useState(false)
|
||||||
const classes = useStyles({ buttonCoords, xOffset })
|
|
||||||
const machines = R.compose(
|
const machines = R.compose(
|
||||||
R.map(R.prop('name')),
|
R.map(R.prop('name')),
|
||||||
R.indexBy(R.prop('deviceId'))
|
R.indexBy(R.prop('deviceId'))
|
||||||
|
|
@ -120,7 +116,13 @@ const NotificationCenter = ({
|
||||||
<div className={classes.container}>
|
<div className={classes.container}>
|
||||||
<div className={classes.header}>
|
<div className={classes.header}>
|
||||||
<H5 className={classes.headerText}>Notifications</H5>
|
<H5 className={classes.headerText}>Notifications</H5>
|
||||||
<button onClick={close} className={classes.notificationIcon}>
|
<button
|
||||||
|
onClick={close}
|
||||||
|
className={classes.notificationIcon}
|
||||||
|
style={{
|
||||||
|
top: buttonCoords?.y ?? 0,
|
||||||
|
left: buttonCoords?.x ? buttonCoords.x - xOffset : 0
|
||||||
|
}}>
|
||||||
<NotificationIconZodiac />
|
<NotificationIconZodiac />
|
||||||
{hasUnread && <div className={classes.hasUnread} />}
|
{hasUnread && <div className={classes.hasUnread} />}
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,145 @@
|
||||||
|
.container {
|
||||||
|
width: 40vw;
|
||||||
|
height: 110vh;
|
||||||
|
right: 0;
|
||||||
|
background-color: white;
|
||||||
|
box-shadow: 0 0 14px 0 rgba(0, 0, 0, 0.24);
|
||||||
|
}
|
||||||
|
|
||||||
|
.container @media only screen and (max-width: 1920px) {
|
||||||
|
width: 30vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerText {
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-left: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actionButtons {
|
||||||
|
display: flex;
|
||||||
|
margin-left: 16px;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notificationIcon {
|
||||||
|
position: absolute;
|
||||||
|
cursor: pointer;
|
||||||
|
background: transparent;
|
||||||
|
box-shadow: 0 0 0 transparent;
|
||||||
|
border: 0 solid transparent;
|
||||||
|
text-shadow: 0 0 0 transparent;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clearAllButton {
|
||||||
|
margin-top: -16px;
|
||||||
|
margin-left: 8px;
|
||||||
|
background-color: var(--zircon);
|
||||||
|
}
|
||||||
|
|
||||||
|
.notificationsList {
|
||||||
|
height: 90vh;
|
||||||
|
max-height: 100vh;
|
||||||
|
margin-top: 24px;
|
||||||
|
margin-left: 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
background-color: white;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notificationRow {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding-top: 12px;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notificationRow > *:first-child {
|
||||||
|
margin-right: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notificationContent {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unread {
|
||||||
|
background-color: var(--spring3)
|
||||||
|
}
|
||||||
|
|
||||||
|
.notificationRowIcon {
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notificationRowIcon > * {
|
||||||
|
margin-left: 24px
|
||||||
|
}
|
||||||
|
|
||||||
|
.readIconWrapper {
|
||||||
|
flex-grow: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
.unreadIcon {
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-left: 8px;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
background-color: var(--spring);
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.readIcon {
|
||||||
|
margin-left: 8px;
|
||||||
|
margin-top: 5px;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
border: 1px solid var(--comet);
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notificationTitle {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--comet);
|
||||||
|
}
|
||||||
|
|
||||||
|
.notificationBody {
|
||||||
|
margin: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.notificationSubtitle {
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
color: var(--comet);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stripes {
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
opacity: 60%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hasUnread {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 16px;
|
||||||
|
width: 9px;
|
||||||
|
height: 9px;
|
||||||
|
background-color: var(--spring);
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
@ -1,144 +0,0 @@
|
||||||
import {
|
|
||||||
spacer,
|
|
||||||
white,
|
|
||||||
zircon,
|
|
||||||
secondaryColor,
|
|
||||||
spring3,
|
|
||||||
comet
|
|
||||||
} from 'src/styling/variables'
|
|
||||||
|
|
||||||
const styles = {
|
|
||||||
container: {
|
|
||||||
'@media only screen and (max-width: 1920px)': {
|
|
||||||
width: '30vw'
|
|
||||||
},
|
|
||||||
width: '40vw',
|
|
||||||
height: '110vh',
|
|
||||||
right: 0,
|
|
||||||
backgroundColor: white,
|
|
||||||
boxShadow: '0 0 14px 0 rgba(0, 0, 0, 0.24)'
|
|
||||||
},
|
|
||||||
header: {
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'space-between'
|
|
||||||
},
|
|
||||||
headerText: {
|
|
||||||
marginTop: spacer * 2.5,
|
|
||||||
marginLeft: spacer * 3
|
|
||||||
},
|
|
||||||
actionButtons: {
|
|
||||||
display: 'flex',
|
|
||||||
marginLeft: spacer * 2,
|
|
||||||
height: 0
|
|
||||||
},
|
|
||||||
notificationIcon: ({ buttonCoords, xOffset }) => ({
|
|
||||||
position: 'absolute',
|
|
||||||
top: buttonCoords ? buttonCoords.y : 0,
|
|
||||||
left: buttonCoords ? buttonCoords.x - xOffset : 0,
|
|
||||||
cursor: 'pointer',
|
|
||||||
background: 'transparent',
|
|
||||||
boxShadow: '0px 0px 0px transparent',
|
|
||||||
border: '0px solid transparent',
|
|
||||||
textShadow: '0px 0px 0px transparent',
|
|
||||||
outline: 'none'
|
|
||||||
}),
|
|
||||||
clearAllButton: {
|
|
||||||
marginTop: -spacer * 2,
|
|
||||||
marginLeft: spacer,
|
|
||||||
backgroundColor: zircon
|
|
||||||
},
|
|
||||||
notificationsList: {
|
|
||||||
height: '90vh',
|
|
||||||
maxHeight: '100vh',
|
|
||||||
marginTop: spacer * 3,
|
|
||||||
marginLeft: 0,
|
|
||||||
overflowY: 'auto',
|
|
||||||
overflowX: 'hidden',
|
|
||||||
backgroundColor: white,
|
|
||||||
zIndex: 10
|
|
||||||
},
|
|
||||||
notificationRow: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'flex-start',
|
|
||||||
position: 'relative',
|
|
||||||
marginBottom: spacer / 2,
|
|
||||||
paddingTop: spacer * 1.5,
|
|
||||||
'& > *:first-child': {
|
|
||||||
marginRight: 24
|
|
||||||
},
|
|
||||||
'& > *': {
|
|
||||||
marginRight: 10
|
|
||||||
},
|
|
||||||
'& > *:last-child': {
|
|
||||||
marginRight: 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
notificationContent: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
justifyContent: 'center',
|
|
||||||
width: 300
|
|
||||||
},
|
|
||||||
unread: {
|
|
||||||
backgroundColor: spring3
|
|
||||||
},
|
|
||||||
notificationRowIcon: {
|
|
||||||
alignSelf: 'center',
|
|
||||||
'& > *': {
|
|
||||||
marginLeft: spacer * 3
|
|
||||||
}
|
|
||||||
},
|
|
||||||
readIconWrapper: {
|
|
||||||
flexGrow: 1
|
|
||||||
},
|
|
||||||
unreadIcon: {
|
|
||||||
marginTop: 5,
|
|
||||||
marginLeft: spacer,
|
|
||||||
width: '12px',
|
|
||||||
height: '12px',
|
|
||||||
backgroundColor: secondaryColor,
|
|
||||||
borderRadius: '50%',
|
|
||||||
cursor: 'pointer',
|
|
||||||
zIndex: 1
|
|
||||||
},
|
|
||||||
readIcon: {
|
|
||||||
marginLeft: spacer,
|
|
||||||
marginTop: 5,
|
|
||||||
width: '12px',
|
|
||||||
height: '12px',
|
|
||||||
border: [[1, 'solid', comet]],
|
|
||||||
borderRadius: '50%',
|
|
||||||
cursor: 'pointer',
|
|
||||||
zIndex: 1
|
|
||||||
},
|
|
||||||
notificationTitle: {
|
|
||||||
margin: 0,
|
|
||||||
color: comet
|
|
||||||
},
|
|
||||||
notificationBody: {
|
|
||||||
margin: 0
|
|
||||||
},
|
|
||||||
notificationSubtitle: {
|
|
||||||
margin: 0,
|
|
||||||
marginBottom: spacer,
|
|
||||||
color: comet
|
|
||||||
},
|
|
||||||
stripes: {
|
|
||||||
position: 'absolute',
|
|
||||||
height: '100%',
|
|
||||||
top: '0px',
|
|
||||||
opacity: '60%'
|
|
||||||
},
|
|
||||||
hasUnread: {
|
|
||||||
position: 'absolute',
|
|
||||||
top: 0,
|
|
||||||
left: 16,
|
|
||||||
width: '9px',
|
|
||||||
height: '9px',
|
|
||||||
backgroundColor: secondaryColor,
|
|
||||||
borderRadius: '50%'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default styles
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import prettyMs from 'pretty-ms'
|
import prettyMs from 'pretty-ms'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
|
|
@ -8,8 +7,7 @@ import Wrench from 'src/styling/icons/action/wrench/zodiac.svg?react'
|
||||||
import Transaction from 'src/styling/icons/arrow/transaction.svg?react'
|
import Transaction from 'src/styling/icons/arrow/transaction.svg?react'
|
||||||
import WarningIcon from 'src/styling/icons/warning-icon/tomato.svg?react'
|
import WarningIcon from 'src/styling/icons/warning-icon/tomato.svg?react'
|
||||||
|
|
||||||
import styles from './NotificationCenter.styles'
|
import classes from './NotificationCenter.module.css'
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const types = {
|
const types = {
|
||||||
transaction: {
|
transaction: {
|
||||||
|
|
@ -46,8 +44,6 @@ const NotificationRow = ({
|
||||||
valid,
|
valid,
|
||||||
toggleClear
|
toggleClear
|
||||||
}) => {
|
}) => {
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
const typeDisplay = R.path([type, 'display'])(types) ?? null
|
const typeDisplay = R.path([type, 'display'])(types) ?? null
|
||||||
const icon = R.path([type, 'icon'])(types) ?? (
|
const icon = R.path([type, 'icon'])(types) ?? (
|
||||||
<Wrench height={16} width={16} />
|
<Wrench height={16} width={16} />
|
||||||
|
|
|
||||||
|
|
@ -1,60 +1,22 @@
|
||||||
import Checkbox from '@mui/material/Checkbox'
|
import Checkbox from '@mui/material/Checkbox'
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import CheckBoxIcon from '@mui/icons-material/CheckBox'
|
import CheckBoxIcon from '@mui/icons-material/CheckBox'
|
||||||
import CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank'
|
import CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Label2, Info3 } from 'src/components/typography'
|
import { Label2, Info3 } from 'src/components/typography'
|
||||||
import WarningIcon from 'src/styling/icons/warning-icon/comet.svg?react'
|
import WarningIcon from 'src/styling/icons/warning-icon/comet.svg?react'
|
||||||
|
|
||||||
import {
|
import { fontSize2, fontSize3 } from 'src/styling/variables'
|
||||||
fontSize2,
|
|
||||||
fontSize3,
|
|
||||||
secondaryColor,
|
|
||||||
offColor
|
|
||||||
} from 'src/styling/variables'
|
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
|
||||||
root: {
|
|
||||||
color: secondaryColor,
|
|
||||||
'&.Mui-checked': {
|
|
||||||
color: secondaryColor
|
|
||||||
}
|
|
||||||
},
|
|
||||||
checked: {},
|
|
||||||
checkBoxLabel: {
|
|
||||||
display: 'flex'
|
|
||||||
},
|
|
||||||
wrapper: {
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
'& > svg': {
|
|
||||||
marginRight: 10
|
|
||||||
}
|
|
||||||
},
|
|
||||||
message: {
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
color: offColor,
|
|
||||||
margin: 0,
|
|
||||||
whiteSpace: 'break-spaces'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const CheckboxInput = ({ name, onChange, value, settings, ...props }) => {
|
const CheckboxInput = ({ name, onChange, value, settings, ...props }) => {
|
||||||
const { enabled, label, disabledMessage, rightSideLabel } = settings
|
const { enabled, label, disabledMessage, rightSideLabel } = settings
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{enabled ? (
|
{enabled ? (
|
||||||
<div className={classes.checkBoxLabel}>
|
<div className="flex">
|
||||||
{!rightSideLabel && <Label2>{label}</Label2>}
|
{!rightSideLabel && <Label2>{label}</Label2>}
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id={name}
|
id={name}
|
||||||
classes={{
|
|
||||||
root: classes.root,
|
|
||||||
checked: classes.checked
|
|
||||||
}}
|
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
value={value}
|
value={value}
|
||||||
checked={value}
|
checked={value}
|
||||||
|
|
@ -70,9 +32,11 @@ const CheckboxInput = ({ name, onChange, value, settings, ...props }) => {
|
||||||
{rightSideLabel && <Label2>{label}</Label2>}
|
{rightSideLabel && <Label2>{label}</Label2>}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className={classes.wrapper}>
|
<div className="flex items-center gap-2">
|
||||||
<WarningIcon />
|
<WarningIcon />
|
||||||
<Info3 className={classes.message}>{disabledMessage}</Info3>
|
<Info3 className="flex items-center text-comet m-0 whitespace-break-spaces">
|
||||||
|
{disabledMessage}
|
||||||
|
</Info3>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,8 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import OtpInput from 'react-otp-input'
|
import OtpInput from 'react-otp-input'
|
||||||
|
|
||||||
import typographyStyles from 'src/components/typography/styles'
|
import classes from './CodeInput.module.css'
|
||||||
|
|
||||||
import styles from './CodeInput.styles'
|
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
const useTypographyStyles = makeStyles(typographyStyles)
|
|
||||||
|
|
||||||
const CodeInput = ({
|
const CodeInput = ({
|
||||||
name,
|
name,
|
||||||
|
|
@ -19,9 +13,6 @@ const CodeInput = ({
|
||||||
inputStyle,
|
inputStyle,
|
||||||
containerStyle
|
containerStyle
|
||||||
}) => {
|
}) => {
|
||||||
const classes = useStyles()
|
|
||||||
const typographyClasses = useTypographyStyles()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<OtpInput
|
<OtpInput
|
||||||
id={name}
|
id={name}
|
||||||
|
|
@ -30,19 +21,15 @@ const CodeInput = ({
|
||||||
numInputs={numInputs}
|
numInputs={numInputs}
|
||||||
renderSeparator={<span> </span>}
|
renderSeparator={<span> </span>}
|
||||||
shouldAutoFocus
|
shouldAutoFocus
|
||||||
containerStyle={classnames(containerStyle, classes.container)}
|
containerStyle={classnames(containerStyle, 'justify-evenly')}
|
||||||
inputStyle={classnames(
|
inputStyle={classnames(
|
||||||
inputStyle,
|
inputStyle,
|
||||||
classes.input,
|
classes.input,
|
||||||
typographyClasses.confirmationCode,
|
'font-museo font-black text-4xl',
|
||||||
error && classes.error
|
error && 'border-tomato'
|
||||||
)}
|
)}
|
||||||
inputType={'tel'}
|
inputType={'tel'}
|
||||||
renderInput={(props) => (
|
renderInput={props => <input {...props} />}
|
||||||
<input
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
.input {
|
||||||
|
width: 3.5rem !important;
|
||||||
|
height: 5rem;
|
||||||
|
border: 2px solid;
|
||||||
|
border-color: var(--zircon);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input:focus {
|
||||||
|
border: 2px solid;
|
||||||
|
border-color: var(--zodiac);
|
||||||
|
border-radius: 4px;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
import { primaryColor, zircon, errorColor } from 'src/styling/variables'
|
|
||||||
|
|
||||||
const styles = {
|
|
||||||
input: {
|
|
||||||
width: '3.5rem !important',
|
|
||||||
height: '5rem',
|
|
||||||
border: '2px solid',
|
|
||||||
borderColor: zircon,
|
|
||||||
borderRadius: '4px',
|
|
||||||
'&:focus': {
|
|
||||||
border: '2px solid',
|
|
||||||
borderColor: primaryColor,
|
|
||||||
borderRadius: '4px',
|
|
||||||
'&:focus': {
|
|
||||||
outline: 'none'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
error: {
|
|
||||||
borderColor: errorColor
|
|
||||||
},
|
|
||||||
container: {
|
|
||||||
justifyContent: 'space-evenly'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default styles
|
|
||||||
|
|
@ -1,31 +1,10 @@
|
||||||
import Radio from '@mui/material/Radio'
|
import Radio from '@mui/material/Radio'
|
||||||
import MRadioGroup from '@mui/material/RadioGroup'
|
import MRadioGroup from '@mui/material/RadioGroup'
|
||||||
import FormControlLabel from '@mui/material/FormControlLabel'
|
import FormControlLabel from '@mui/material/FormControlLabel'
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Label1 } from 'src/components/typography'
|
import { Label1 } from 'src/components/typography'
|
||||||
|
|
||||||
import { offColor, secondaryColor } from 'src/styling/variables'
|
|
||||||
const styles = {
|
|
||||||
label: {
|
|
||||||
height: 16,
|
|
||||||
lineHeight: '16px',
|
|
||||||
margin: [[0, 0, 4, 0]],
|
|
||||||
paddingLeft: 3
|
|
||||||
},
|
|
||||||
subtitle: {
|
|
||||||
marginTop: -8,
|
|
||||||
marginLeft: 32,
|
|
||||||
color: offColor
|
|
||||||
},
|
|
||||||
radio: {
|
|
||||||
color: secondaryColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const RadioGroup = ({
|
const RadioGroup = ({
|
||||||
name,
|
name,
|
||||||
label,
|
label,
|
||||||
|
|
@ -36,10 +15,11 @@ const RadioGroup = ({
|
||||||
labelClassName,
|
labelClassName,
|
||||||
radioClassName
|
radioClassName
|
||||||
}) => {
|
}) => {
|
||||||
const classes = useStyles()
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{label && <Label1 className={classes.label}>{label}</Label1>}
|
{label && (
|
||||||
|
<Label1 className="h-4 leading-4 m-0 mb-1 pl-1">{label}</Label1>
|
||||||
|
)}
|
||||||
<MRadioGroup
|
<MRadioGroup
|
||||||
name={name}
|
name={name}
|
||||||
value={value}
|
value={value}
|
||||||
|
|
@ -51,12 +31,16 @@ const RadioGroup = ({
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
disabled={option.disabled}
|
disabled={option.disabled}
|
||||||
value={option.code}
|
value={option.code}
|
||||||
control={<Radio className={classnames(classes.radio, radioClassName)} />}
|
control={
|
||||||
|
<Radio
|
||||||
|
className={classnames('text-spring', radioClassName)}
|
||||||
|
/>
|
||||||
|
}
|
||||||
label={option.display}
|
label={option.display}
|
||||||
className={classnames(labelClassName)}
|
className={classnames(labelClassName)}
|
||||||
/>
|
/>
|
||||||
{option.subtitle && (
|
{option.subtitle && (
|
||||||
<Label1 className={classes.subtitle}>{option.subtitle}</Label1>
|
<Label1 className="-mt-2 ml-8">{option.subtitle}</Label1>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,19 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import React, { memo, useState } from 'react'
|
import React, { memo, useState } from 'react'
|
||||||
import { CashOut } from 'src/components/inputs/cashbox/Cashbox'
|
import { CashOut } from 'src/components/inputs/cashbox/Cashbox'
|
||||||
|
|
||||||
import { NumberInput } from '../base'
|
import { NumberInput } from '../base'
|
||||||
const useStyles = makeStyles({
|
|
||||||
flex: {
|
|
||||||
display: 'flex'
|
|
||||||
},
|
|
||||||
cashCassette: {
|
|
||||||
height: 36,
|
|
||||||
marginRight: 14
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const CashCassetteInput = memo(
|
const CashCassetteInput = memo(
|
||||||
({ decimalPlaces, width, threshold, inputClassName, ...props }) => {
|
({ decimalPlaces, width, threshold, inputClassName, ...props }) => {
|
||||||
const classes = useStyles()
|
|
||||||
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 [notes, setNotes] = useState(value)
|
const [notes, setNotes] = useState(value)
|
||||||
const error = !!(touched[name] && errors[name])
|
const error = !!(touched[name] && errors[name])
|
||||||
return (
|
return (
|
||||||
<div className={classes.flex}>
|
<div className="flex">
|
||||||
<CashOut
|
<CashOut
|
||||||
className={classNames(classes.cashCassette, inputClassName)}
|
className={classNames('h-9 mr-4', inputClassName)}
|
||||||
notes={notes}
|
notes={notes}
|
||||||
editingMode={true}
|
editingMode={true}
|
||||||
width={width}
|
width={width}
|
||||||
|
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
import typographyStyles from 'src/components/typography/styles'
|
|
||||||
import {
|
|
||||||
fontColor,
|
|
||||||
offColor,
|
|
||||||
inputFontSize,
|
|
||||||
inputFontWeight
|
|
||||||
} from 'src/styling/variables'
|
|
||||||
|
|
||||||
const { info3 } = typographyStyles
|
|
||||||
|
|
||||||
const styles = {
|
|
||||||
masked: {
|
|
||||||
position: 'absolute',
|
|
||||||
bottom: 5,
|
|
||||||
left: 4,
|
|
||||||
color: fontColor,
|
|
||||||
fontSize: inputFontSize,
|
|
||||||
fontWeight: inputFontWeight
|
|
||||||
},
|
|
||||||
secretSpan: {
|
|
||||||
extend: info3,
|
|
||||||
color: offColor
|
|
||||||
},
|
|
||||||
hideSpan: {
|
|
||||||
display: 'none'
|
|
||||||
},
|
|
||||||
maskedInput: {
|
|
||||||
'& input': {
|
|
||||||
pointerEvents: 'none',
|
|
||||||
backgroundColor: 'transparent',
|
|
||||||
zIndex: -1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export { styles }
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { useQuery, gql } from "@apollo/client";
|
import { useQuery, gql } from '@apollo/client'
|
||||||
import ClickAwayListener from '@mui/material/ClickAwayListener'
|
import ClickAwayListener from '@mui/material/ClickAwayListener'
|
||||||
import Popper from '@mui/material/Popper'
|
import Popper from '@mui/material/Popper'
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { memo, useState, useEffect, useRef } from 'react'
|
import React, { memo, useState, useEffect, useRef } from 'react'
|
||||||
|
|
@ -16,9 +15,7 @@ import NotificationIcon from 'src/styling/icons/menu/notification.svg?react'
|
||||||
import NotificationCenter from 'src/components/NotificationCenter'
|
import NotificationCenter from 'src/components/NotificationCenter'
|
||||||
import AddMachine from 'src/pages/AddMachine'
|
import AddMachine from 'src/pages/AddMachine'
|
||||||
|
|
||||||
import styles from './Header.styles'
|
import styles from './Header.module.css'
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const HAS_UNREAD = gql`
|
const HAS_UNREAD = gql`
|
||||||
query getUnread {
|
query getUnread {
|
||||||
|
|
@ -26,22 +23,22 @@ const HAS_UNREAD = gql`
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const Subheader = ({ item, classes, user }) => {
|
const Subheader = ({ item, user }) => {
|
||||||
const [prev, setPrev] = useState(null)
|
const [prev, setPrev] = useState(null)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.subheader}>
|
<div className={styles.subheader}>
|
||||||
<div className={classes.content}>
|
<div className={styles.content}>
|
||||||
<nav>
|
<nav>
|
||||||
<ul className={classes.subheaderUl}>
|
<ul className={styles.subheaderUl}>
|
||||||
{item.children.map((it, idx) => {
|
{item.children.map((it, idx) => {
|
||||||
if (!R.includes(user.role, it.allowedRoles)) return <></>
|
if (!R.includes(user.role, it.allowedRoles)) return <></>
|
||||||
return (
|
return (
|
||||||
<li key={idx} className={classes.subheaderLi}>
|
<li key={idx} className={styles.subheaderLi}>
|
||||||
<NavLink
|
<NavLink
|
||||||
to={{ pathname: it.route, state: { prev } }}
|
to={{ pathname: it.route, state: { prev } }}
|
||||||
className={classes.subheaderLink}
|
className={styles.subheaderLink}
|
||||||
activeClassName={classes.activeSubheaderLink}
|
activeClassName={styles.activeSubheaderLink}
|
||||||
isActive={match => {
|
isActive={match => {
|
||||||
if (!match) return false
|
if (!match) return false
|
||||||
setPrev(it.route)
|
setPrev(it.route)
|
||||||
|
|
@ -72,7 +69,6 @@ const Header = memo(({ tree, user }) => {
|
||||||
const notifCenterButtonRef = useRef()
|
const notifCenterButtonRef = useRef()
|
||||||
const popperRef = useRef()
|
const popperRef = useRef()
|
||||||
const history = useHistory()
|
const history = useHistory()
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data?.hasUnreadNotifications) return setHasUnread(true)
|
if (data?.hasUnreadNotifications) return setHasUnread(true)
|
||||||
|
|
@ -112,20 +108,20 @@ const Header = memo(({ tree, user }) => {
|
||||||
const popperOpen = Boolean(anchorEl)
|
const popperOpen = Boolean(anchorEl)
|
||||||
const id = popperOpen ? 'notifications-popper' : undefined
|
const id = popperOpen ? 'notifications-popper' : undefined
|
||||||
return (
|
return (
|
||||||
<header className={classes.headerContainer}>
|
<header className={styles.headerContainer}>
|
||||||
<div className={classes.header}>
|
<div className={styles.header}>
|
||||||
<div className={classes.content}>
|
<div className={styles.content}>
|
||||||
<div
|
<div
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setActive(false)
|
setActive(false)
|
||||||
history.push('/dashboard')
|
history.push('/dashboard')
|
||||||
}}
|
}}
|
||||||
className={classnames(classes.logo, classes.logoLink)}>
|
className={classnames(styles.logo, styles.logoLink)}>
|
||||||
<Logo />
|
<Logo />
|
||||||
<H4 className={classes.white}>Lamassu Admin</H4>
|
<H4 className="text-white">Lamassu Admin</H4>
|
||||||
</div>
|
</div>
|
||||||
<nav className={classes.nav}>
|
<nav className={styles.nav}>
|
||||||
<ul className={classes.ul}>
|
<ul className={styles.ul}>
|
||||||
{tree.map((it, idx) => {
|
{tree.map((it, idx) => {
|
||||||
if (!R.includes(user.role, it.allowedRoles)) return <></>
|
if (!R.includes(user.role, it.allowedRoles)) return <></>
|
||||||
return (
|
return (
|
||||||
|
|
@ -137,11 +133,11 @@ const Header = memo(({ tree, user }) => {
|
||||||
setActive(it)
|
setActive(it)
|
||||||
return true
|
return true
|
||||||
}}
|
}}
|
||||||
className={classnames(classes.link, classes.whiteLink)}
|
className={classnames(styles.link)}
|
||||||
activeClassName={classes.activeLink}>
|
activeClassName={styles.activeLink}>
|
||||||
<li className={classes.li}>
|
<li className={styles.li}>
|
||||||
<span
|
<span
|
||||||
className={classes.forceSize}
|
className={styles.forceSize}
|
||||||
data-forcesize={it.label}>
|
data-forcesize={it.label}>
|
||||||
{it.label}
|
{it.label}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -151,7 +147,7 @@ const Header = memo(({ tree, user }) => {
|
||||||
})}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
<div className={classes.actionButtonsContainer}>
|
<div className={styles.actionButtonsContainer}>
|
||||||
<ActionButton
|
<ActionButton
|
||||||
color="secondary"
|
color="secondary"
|
||||||
Icon={AddIcon}
|
Icon={AddIcon}
|
||||||
|
|
@ -163,16 +159,16 @@ const Header = memo(({ tree, user }) => {
|
||||||
<div ref={notifCenterButtonRef}>
|
<div ref={notifCenterButtonRef}>
|
||||||
<button
|
<button
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
className={classes.notificationIcon}>
|
className={styles.notificationIcon}>
|
||||||
<NotificationIcon />
|
<NotificationIcon />
|
||||||
{hasUnread && <div className={classes.hasUnread} />}
|
{hasUnread && <div className={styles.hasUnread} />}
|
||||||
</button>
|
</button>
|
||||||
<Popper
|
<Popper
|
||||||
ref={popperRef}
|
ref={popperRef}
|
||||||
id={id}
|
id={id}
|
||||||
open={popperOpen}
|
open={popperOpen}
|
||||||
anchorEl={anchorEl}
|
anchorEl={anchorEl}
|
||||||
className={classes.popper}
|
className={styles.popper}
|
||||||
disablePortal={false}
|
disablePortal={false}
|
||||||
placement="bottom-end"
|
placement="bottom-end"
|
||||||
modifiers={[
|
modifiers={[
|
||||||
|
|
@ -187,8 +183,8 @@ const Header = memo(({ tree, user }) => {
|
||||||
name: 'preventOverflow',
|
name: 'preventOverflow',
|
||||||
enabled: true,
|
enabled: true,
|
||||||
options: {
|
options: {
|
||||||
rootBoundary: 'viewport',
|
rootBoundary: 'viewport'
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
]}>
|
]}>
|
||||||
<NotificationCenter
|
<NotificationCenter
|
||||||
|
|
@ -204,9 +200,7 @@ const Header = memo(({ tree, user }) => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{active && active.children && (
|
{active && active.children && <Subheader item={active} user={user} />}
|
||||||
<Subheader item={active} classes={classes} user={user} />
|
|
||||||
)}
|
|
||||||
{open && <AddMachine close={() => setOpen(false)} onPaired={onPaired} />}
|
{open && <AddMachine close={() => setOpen(false)} onPaired={onPaired} />}
|
||||||
</header>
|
</header>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
175
new-lamassu-admin/src/components/layout/Header.module.css
Normal file
175
new-lamassu-admin/src/components/layout/Header.module.css
Normal file
|
|
@ -0,0 +1,175 @@
|
||||||
|
.headerContainer {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
background-color: var(--zodiac);
|
||||||
|
color: white;
|
||||||
|
height: 56px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
max-width: 1200px;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ul {
|
||||||
|
display: flex;
|
||||||
|
padding-left: 36px;
|
||||||
|
height: 56px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.li {
|
||||||
|
list-style: none;
|
||||||
|
color: white;
|
||||||
|
margin: 20px 20px 0 20px;
|
||||||
|
position: relative;
|
||||||
|
line-height: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.li:hover {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.li:hover::after {
|
||||||
|
width: 50%;
|
||||||
|
margin-left: -25%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.li::after {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
background: white;
|
||||||
|
width: 0;
|
||||||
|
height: 4px;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: 0;
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 1000px;
|
||||||
|
transition: all 0.2s cubic-bezier(0.95, 0.1, 0.45, 0.94);
|
||||||
|
}
|
||||||
|
|
||||||
|
.link {
|
||||||
|
text-decoration: none;
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.forceSize {
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.forceSize::after {
|
||||||
|
display: block;
|
||||||
|
content: attr(data-forcesize);
|
||||||
|
font-weight: 700;
|
||||||
|
height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activeLink {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activeLink li::after {
|
||||||
|
width: 50%;
|
||||||
|
margin-left: -25%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.addMachine {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subheader {
|
||||||
|
background-color: var(--zircon);
|
||||||
|
color: white;
|
||||||
|
height: 40px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subheaderUl {
|
||||||
|
display: flex;
|
||||||
|
padding-left: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subheaderLi {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subheaderLi:first-child {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subheaderLink {
|
||||||
|
text-decoration: none;
|
||||||
|
border: none;
|
||||||
|
color: var(--comet);
|
||||||
|
}
|
||||||
|
|
||||||
|
.activeSubheaderLink {
|
||||||
|
text-shadow: 0.2px 0 0 currentColor;
|
||||||
|
color: var(--zodiac);
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo > svg {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logoLink {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actionButtonsContainer {
|
||||||
|
z-index: 1;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
min-width: 200px;
|
||||||
|
transform: translateZ(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.notificationIcon {
|
||||||
|
margin-top: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
background: transparent;
|
||||||
|
box-shadow: 0px 0px 0px transparent;
|
||||||
|
border: 0px solid transparent;
|
||||||
|
text-shadow: 0px 0px 0px transparent;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hasUnread {
|
||||||
|
position: absolute;
|
||||||
|
top: 4px;
|
||||||
|
left: 186px;
|
||||||
|
width: 9px;
|
||||||
|
height: 9px;
|
||||||
|
background-color: var(--spring);
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popper {
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
@ -1,182 +0,0 @@
|
||||||
import typographyStyles from 'src/components/typography/styles'
|
|
||||||
import {
|
|
||||||
version,
|
|
||||||
mainWidth,
|
|
||||||
spacer,
|
|
||||||
white,
|
|
||||||
primaryColor,
|
|
||||||
secondaryColor,
|
|
||||||
placeholderColor,
|
|
||||||
subheaderColor,
|
|
||||||
fontColor
|
|
||||||
} from 'src/styling/variables'
|
|
||||||
|
|
||||||
const { p } = typographyStyles
|
|
||||||
|
|
||||||
let headerHeight = spacer * 7
|
|
||||||
let subheaderHeight = spacer * 5
|
|
||||||
|
|
||||||
if (version === 8) {
|
|
||||||
headerHeight = spacer * 8
|
|
||||||
subheaderHeight = spacer * 7
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = {
|
|
||||||
headerContainer: {
|
|
||||||
position: 'relative'
|
|
||||||
},
|
|
||||||
header: {
|
|
||||||
backgroundColor: primaryColor,
|
|
||||||
color: white,
|
|
||||||
height: headerHeight,
|
|
||||||
display: 'flex'
|
|
||||||
},
|
|
||||||
content: {
|
|
||||||
maxWidth: mainWidth,
|
|
||||||
flex: 1,
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
margin: '0 auto'
|
|
||||||
},
|
|
||||||
nav: {
|
|
||||||
flex: 1,
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'space-between'
|
|
||||||
},
|
|
||||||
ul: {
|
|
||||||
display: 'flex',
|
|
||||||
paddingLeft: spacer * 4.5,
|
|
||||||
height: spacer * 7,
|
|
||||||
margin: 0
|
|
||||||
},
|
|
||||||
li: {
|
|
||||||
// extend: tl2,
|
|
||||||
// height: spacer * 7,
|
|
||||||
listStyle: 'none',
|
|
||||||
color: white,
|
|
||||||
margin: [[spacer * 2.5, spacer * 2.5, 0, spacer * 2.5]],
|
|
||||||
'&:hover': {
|
|
||||||
color: white
|
|
||||||
},
|
|
||||||
'&:hover::after': {
|
|
||||||
width: '50%',
|
|
||||||
marginLeft: '-25%'
|
|
||||||
},
|
|
||||||
position: 'relative',
|
|
||||||
'&:after': {
|
|
||||||
content: '""',
|
|
||||||
display: 'block',
|
|
||||||
background: white,
|
|
||||||
width: 0,
|
|
||||||
height: 4,
|
|
||||||
left: '50%',
|
|
||||||
marginLeft: 0,
|
|
||||||
bottom: -8,
|
|
||||||
position: 'absolute',
|
|
||||||
borderRadius: 1000,
|
|
||||||
transition: [['all', '0.2s', 'cubic-bezier(0.95, 0.1, 0.45, 0.94)']]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
link: {
|
|
||||||
extend: p,
|
|
||||||
textDecoration: 'none',
|
|
||||||
border: 'none',
|
|
||||||
color: white,
|
|
||||||
backgroundColor: 'transparent'
|
|
||||||
},
|
|
||||||
forceSize: {
|
|
||||||
display: 'inline-block',
|
|
||||||
textAlign: 'center',
|
|
||||||
'&:after': {
|
|
||||||
display: 'block',
|
|
||||||
content: 'attr(data-forcesize)',
|
|
||||||
fontWeight: 700,
|
|
||||||
height: 0,
|
|
||||||
overflow: 'hidden',
|
|
||||||
visibility: 'hidden'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
activeLink: {
|
|
||||||
color: white,
|
|
||||||
'& li::after': {
|
|
||||||
width: '50%',
|
|
||||||
marginLeft: '-25%'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
addMachine: {
|
|
||||||
marginLeft: 'auto'
|
|
||||||
},
|
|
||||||
subheader: {
|
|
||||||
backgroundColor: subheaderColor,
|
|
||||||
color: white,
|
|
||||||
height: subheaderHeight,
|
|
||||||
display: 'flex'
|
|
||||||
},
|
|
||||||
subheaderUl: {
|
|
||||||
display: 'flex',
|
|
||||||
paddingLeft: 0,
|
|
||||||
margin: 0
|
|
||||||
},
|
|
||||||
subheaderLi: {
|
|
||||||
listStyle: 'none',
|
|
||||||
padding: [[0, spacer * 2.5]],
|
|
||||||
'&:first-child': {
|
|
||||||
paddingLeft: 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
subheaderLink: {
|
|
||||||
extend: p,
|
|
||||||
textDecoration: 'none',
|
|
||||||
border: 'none',
|
|
||||||
color: placeholderColor
|
|
||||||
},
|
|
||||||
activeSubheaderLink: {
|
|
||||||
textShadow: '0.2px 0 0 currentColor',
|
|
||||||
color: fontColor
|
|
||||||
},
|
|
||||||
white: {
|
|
||||||
color: white
|
|
||||||
},
|
|
||||||
logo: {
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
'& > svg': {
|
|
||||||
marginRight: 16
|
|
||||||
}
|
|
||||||
},
|
|
||||||
logoLink: {
|
|
||||||
cursor: 'pointer'
|
|
||||||
},
|
|
||||||
actionButtonsContainer: {
|
|
||||||
zIndex: 1,
|
|
||||||
position: 'relative',
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
minWidth: 200,
|
|
||||||
transform: 'translateZ(0)'
|
|
||||||
},
|
|
||||||
notificationIcon: {
|
|
||||||
marginTop: spacer / 2,
|
|
||||||
cursor: 'pointer',
|
|
||||||
background: 'transparent',
|
|
||||||
boxShadow: '0px 0px 0px transparent',
|
|
||||||
border: '0px solid transparent',
|
|
||||||
textShadow: '0px 0px 0px transparent',
|
|
||||||
outline: 'none'
|
|
||||||
},
|
|
||||||
hasUnread: {
|
|
||||||
position: 'absolute',
|
|
||||||
top: 4,
|
|
||||||
left: 186,
|
|
||||||
width: '9px',
|
|
||||||
height: '9px',
|
|
||||||
backgroundColor: secondaryColor,
|
|
||||||
borderRadius: '50%'
|
|
||||||
},
|
|
||||||
popper: {
|
|
||||||
zIndex: 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default styles
|
|
||||||
|
|
@ -1,19 +1,13 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import ErrorMessage from 'src/components/ErrorMessage'
|
import ErrorMessage from 'src/components/ErrorMessage'
|
||||||
import Subtitle from 'src/components/Subtitle'
|
import Subtitle from 'src/components/Subtitle'
|
||||||
|
|
||||||
import styles from './Section.styles'
|
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const Section = ({ error, children, title }) => {
|
const Section = ({ error, children, title }) => {
|
||||||
const classes = useStyles()
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.section}>
|
<div className="mb-8">
|
||||||
{(title || error) && (
|
{(title || error) && (
|
||||||
<div className={classes.sectionHeader}>
|
<div className="flex items-center">
|
||||||
<Subtitle className={classes.sectionTitle}>{title}</Subtitle>
|
<Subtitle className="mt-4 mr-5 mb-6 ml-0">{title}</Subtitle>
|
||||||
{error && <ErrorMessage>Failed to save changes</ErrorMessage>}
|
{error && <ErrorMessage>Failed to save changes</ErrorMessage>}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
export default {
|
|
||||||
section: {
|
|
||||||
marginBottom: 72
|
|
||||||
},
|
|
||||||
sectionHeader: {
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center'
|
|
||||||
},
|
|
||||||
sectionTitle: {
|
|
||||||
margin: [[16, 20, 23, 0]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { P } from 'src/components/typography'
|
import { P } from 'src/components/typography'
|
||||||
|
|
@ -6,9 +5,7 @@ import CompleteStageIconZodiac from 'src/styling/icons/stage/zodiac/complete.svg
|
||||||
import CurrentStageIconZodiac from 'src/styling/icons/stage/zodiac/current.svg?react'
|
import CurrentStageIconZodiac from 'src/styling/icons/stage/zodiac/current.svg?react'
|
||||||
import EmptyStageIconZodiac from 'src/styling/icons/stage/zodiac/empty.svg?react'
|
import EmptyStageIconZodiac from 'src/styling/icons/stage/zodiac/empty.svg?react'
|
||||||
|
|
||||||
import styles from './Sidebar.styles'
|
import styles from './Sidebar.module.css'
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const Sidebar = ({
|
const Sidebar = ({
|
||||||
data,
|
data,
|
||||||
|
|
@ -19,23 +16,21 @@ const Sidebar = ({
|
||||||
itemRender,
|
itemRender,
|
||||||
loading = false
|
loading = false
|
||||||
}) => {
|
}) => {
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.sidebar}>
|
<div className={styles.sidebar}>
|
||||||
{loading && <P>Loading...</P>}
|
{loading && <P>Loading...</P>}
|
||||||
{!loading &&
|
{!loading &&
|
||||||
data?.map((it, idx) => (
|
data?.map((it, idx) => (
|
||||||
<div
|
<div
|
||||||
key={idx}
|
key={idx}
|
||||||
className={classes.linkWrapper}
|
className={styles.linkWrapper}
|
||||||
onClick={() => onClick(it)}>
|
onClick={() => onClick(it)}>
|
||||||
<div
|
<div
|
||||||
className={classnames({
|
className={classnames({
|
||||||
[classes.activeLink]: isSelected(it),
|
[styles.activeLink]: isSelected(it),
|
||||||
[classes.customRenderActiveLink]: itemRender && isSelected(it),
|
[styles.customRenderActiveLink]: itemRender && isSelected(it),
|
||||||
[classes.customRenderLink]: itemRender,
|
[styles.customRenderLink]: itemRender,
|
||||||
[classes.link]: true
|
[styles.link]: true
|
||||||
})}>
|
})}>
|
||||||
{itemRender ? itemRender(it, isSelected(it)) : displayName(it)}
|
{itemRender ? itemRender(it, isSelected(it)) : displayName(it)}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -49,18 +44,17 @@ const Sidebar = ({
|
||||||
export default Sidebar
|
export default Sidebar
|
||||||
|
|
||||||
const Stepper = ({ step, it, idx, steps }) => {
|
const Stepper = ({ step, it, idx, steps }) => {
|
||||||
const classes = useStyles()
|
|
||||||
const active = step === idx
|
const active = step === idx
|
||||||
const past = idx < step
|
const past = idx < step
|
||||||
const future = idx > step
|
const future = idx > step
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.item}>
|
<div className={styles.item}>
|
||||||
<span
|
<span
|
||||||
className={classnames({
|
className={classnames({
|
||||||
[classes.itemText]: true,
|
[styles.itemText]: true,
|
||||||
[classes.itemTextActive]: active,
|
[styles.itemTextActive]: active,
|
||||||
[classes.itemTextPast]: past
|
[styles.itemTextPast]: past
|
||||||
})}>
|
})}>
|
||||||
{it.label}
|
{it.label}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -70,8 +64,8 @@ const Stepper = ({ step, it, idx, steps }) => {
|
||||||
{idx < steps.length - 1 && (
|
{idx < steps.length - 1 && (
|
||||||
<div
|
<div
|
||||||
className={classnames({
|
className={classnames({
|
||||||
[classes.stepperPath]: true,
|
[styles.stepperPath]: true,
|
||||||
[classes.stepperPast]: past
|
[styles.stepperPast]: past
|
||||||
})}></div>
|
})}></div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
106
new-lamassu-admin/src/components/layout/Sidebar.module.css
Normal file
106
new-lamassu-admin/src/components/layout/Sidebar.module.css
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
:root {
|
||||||
|
--sidebar-color: var(--zircon);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
display: flex;
|
||||||
|
background-color: var(--sidebar-color);
|
||||||
|
width: 520px;
|
||||||
|
margin-left: -300px;
|
||||||
|
box-shadow: -500px 0px 0px 0px var(--sidebar-color);
|
||||||
|
border-radius: 0 20px 0 0;
|
||||||
|
align-items: flex-end;
|
||||||
|
padding: 24px;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1440px) {
|
||||||
|
.sidebar {
|
||||||
|
width: auto;
|
||||||
|
margin-left: 0;
|
||||||
|
min-width: 250px;
|
||||||
|
box-shadow: -200px 0px 0px 0px var(--sidebar-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.linkWrapper {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link {
|
||||||
|
position: relative;
|
||||||
|
color: var(--comet);
|
||||||
|
margin: 12px 24px 12px 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link:hover::after {
|
||||||
|
height: 140%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link::after {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
background: var(--zodiac);
|
||||||
|
width: 4px;
|
||||||
|
height: 0;
|
||||||
|
left: 100%;
|
||||||
|
margin-left: 20px;
|
||||||
|
bottom: -2px;
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 1000px;
|
||||||
|
transition: all 0.2s cubic-bezier(0.95, 0.1, 0.45, 0.94);
|
||||||
|
}
|
||||||
|
|
||||||
|
.activeLink {
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--zodiac);
|
||||||
|
}
|
||||||
|
|
||||||
|
.activeLink::after {
|
||||||
|
height: 140%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.customRenderLink:hover::after {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.customRenderLink::after {
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.customRenderActiveLink::after {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
position: relative;
|
||||||
|
margin: 12px 0 12px 0;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.itemText {
|
||||||
|
color: var(--comet);
|
||||||
|
margin-right: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.itemTextActive {
|
||||||
|
color: var(--zodiac);
|
||||||
|
}
|
||||||
|
|
||||||
|
.itemTextPast {
|
||||||
|
color: var(--zodiac);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stepperPath {
|
||||||
|
position: absolute;
|
||||||
|
height: 25px;
|
||||||
|
width: 1px;
|
||||||
|
border: 1px solid var(--comet);
|
||||||
|
right: 8px;
|
||||||
|
top: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stepperPast {
|
||||||
|
border: 1px solid var(--zodiac);
|
||||||
|
}
|
||||||
|
|
@ -1,107 +0,0 @@
|
||||||
import typographyStyles from 'src/components/typography/styles'
|
|
||||||
import { respondTo } from 'src/styling/helpers'
|
|
||||||
import {
|
|
||||||
primaryColor,
|
|
||||||
spacer,
|
|
||||||
placeholderColor,
|
|
||||||
zircon,
|
|
||||||
xxl
|
|
||||||
} from 'src/styling/variables'
|
|
||||||
|
|
||||||
const { tl2, p } = typographyStyles
|
|
||||||
|
|
||||||
const sidebarColor = zircon
|
|
||||||
|
|
||||||
export default {
|
|
||||||
sidebar: {
|
|
||||||
display: 'flex',
|
|
||||||
backgroundColor: sidebarColor,
|
|
||||||
width: 520,
|
|
||||||
marginLeft: -300,
|
|
||||||
boxShadow: `-500px 0px 0px 0px ${sidebarColor}`,
|
|
||||||
borderRadius: '0 20px 0 0',
|
|
||||||
alignItems: 'flex-end',
|
|
||||||
padding: spacer * 3,
|
|
||||||
flexDirection: 'column',
|
|
||||||
[respondTo(xxl)]: {
|
|
||||||
width: 'auto',
|
|
||||||
marginLeft: 0,
|
|
||||||
minWidth: 250,
|
|
||||||
boxShadow: `-200px 0px 0px 0px ${sidebarColor}`
|
|
||||||
}
|
|
||||||
},
|
|
||||||
linkWrapper: {
|
|
||||||
cursor: 'pointer'
|
|
||||||
},
|
|
||||||
link: {
|
|
||||||
extend: p,
|
|
||||||
position: 'relative',
|
|
||||||
color: placeholderColor,
|
|
||||||
margin: '12px 24px 12px 0',
|
|
||||||
cursor: 'pointer',
|
|
||||||
'&:hover::after': {
|
|
||||||
height: '140%'
|
|
||||||
},
|
|
||||||
'&:after': {
|
|
||||||
content: '""',
|
|
||||||
display: 'block',
|
|
||||||
background: primaryColor,
|
|
||||||
width: 4,
|
|
||||||
height: 0,
|
|
||||||
left: '100%',
|
|
||||||
marginLeft: 20,
|
|
||||||
bottom: -2,
|
|
||||||
position: 'absolute',
|
|
||||||
borderRadius: 1000,
|
|
||||||
transition: 'all 0.2s cubic-bezier(0.95, 0.1, 0.45, 0.94)'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
activeLink: {
|
|
||||||
extend: tl2,
|
|
||||||
color: primaryColor,
|
|
||||||
'&::after': {
|
|
||||||
height: '140%'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
customRenderLink: {
|
|
||||||
'&:hover::after': {
|
|
||||||
height: '100%'
|
|
||||||
},
|
|
||||||
'&:after': {
|
|
||||||
bottom: 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
customRenderActiveLink: {
|
|
||||||
'&::after': {
|
|
||||||
height: '100%'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
item: {
|
|
||||||
position: 'relative',
|
|
||||||
margin: '12px 0 12px 0',
|
|
||||||
display: 'flex'
|
|
||||||
},
|
|
||||||
itemText: {
|
|
||||||
extend: p,
|
|
||||||
color: placeholderColor,
|
|
||||||
marginRight: 24
|
|
||||||
},
|
|
||||||
itemTextActive: {
|
|
||||||
extend: tl2,
|
|
||||||
color: primaryColor
|
|
||||||
},
|
|
||||||
itemTextPast: {
|
|
||||||
color: primaryColor
|
|
||||||
},
|
|
||||||
stepperPath: {
|
|
||||||
position: 'absolute',
|
|
||||||
height: 25,
|
|
||||||
width: 1,
|
|
||||||
border: [[1, 'solid', placeholderColor]],
|
|
||||||
right: 8,
|
|
||||||
top: 18
|
|
||||||
},
|
|
||||||
stepperPast: {
|
|
||||||
border: [[1, 'solid', primaryColor]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
@ -8,10 +7,6 @@ import { Info1, Label1 } from 'src/components/typography'
|
||||||
|
|
||||||
import { SubpageButton } from 'src/components/buttons'
|
import { SubpageButton } from 'src/components/buttons'
|
||||||
|
|
||||||
import styles from './TitleSection.styles'
|
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const TitleSection = ({
|
const TitleSection = ({
|
||||||
className,
|
className,
|
||||||
title,
|
title,
|
||||||
|
|
@ -22,15 +17,16 @@ const TitleSection = ({
|
||||||
appendix,
|
appendix,
|
||||||
appendixRight
|
appendixRight
|
||||||
}) => {
|
}) => {
|
||||||
const classes = useStyles()
|
|
||||||
return (
|
return (
|
||||||
<div className={classnames(classes.titleWrapper, className)}>
|
<div
|
||||||
<div className={classes.titleAndButtonsContainer}>
|
className={classnames(
|
||||||
|
'flex justify-between items-center flex-row',
|
||||||
|
className
|
||||||
|
)}>
|
||||||
|
<div className="flex items-center">
|
||||||
<Title>{title}</Title>
|
<Title>{title}</Title>
|
||||||
{!!appendix && appendix}
|
{!!appendix && appendix}
|
||||||
{error && (
|
{error && <ErrorMessage className="ml-3">Failed to save</ErrorMessage>}
|
||||||
<ErrorMessage className={classes.error}>Failed to save</ErrorMessage>
|
|
||||||
)}
|
|
||||||
{buttons.length > 0 && (
|
{buttons.length > 0 && (
|
||||||
<>
|
<>
|
||||||
{buttons.map((button, idx) =>
|
{buttons.map((button, idx) =>
|
||||||
|
|
@ -39,12 +35,14 @@ const TitleSection = ({
|
||||||
) : (
|
) : (
|
||||||
<SubpageButton
|
<SubpageButton
|
||||||
key={idx}
|
key={idx}
|
||||||
className={classes.subpageButton}
|
className="ml-3"
|
||||||
Icon={button.icon}
|
Icon={button.icon}
|
||||||
InverseIcon={button.inverseIcon}
|
InverseIcon={button.inverseIcon}
|
||||||
toggle={button.toggle}
|
toggle={button.toggle}
|
||||||
forceDisable={button.forceDisable}>
|
forceDisable={button.forceDisable}>
|
||||||
<Info1 className={classes.buttonText}>{button.text}</Info1>
|
<Info1 className="text-ghost font-mont text-base">
|
||||||
|
{button.text}
|
||||||
|
</Info1>
|
||||||
</SubpageButton>
|
</SubpageButton>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
|
|
@ -54,8 +52,8 @@ const TitleSection = ({
|
||||||
<div className="flex flex-row items-center">
|
<div className="flex flex-row items-center">
|
||||||
{(labels ?? []).map(({ icon, label }, idx) => (
|
{(labels ?? []).map(({ icon, label }, idx) => (
|
||||||
<div key={idx} className="flex items-center">
|
<div key={idx} className="flex items-center">
|
||||||
<div className={classes.icon}>{icon}</div>
|
<div className="mr-1">{icon}</div>
|
||||||
<Label1 className={classes.label}>{label}</Label1>
|
<Label1 className="mr-6">{label}</Label1>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
{appendixRight}
|
{appendixRight}
|
||||||
|
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
import { backgroundColor } from 'src/styling/variables'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
titleWrapper: {
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
alignItems: 'center',
|
|
||||||
flexDirection: 'row'
|
|
||||||
},
|
|
||||||
titleAndButtonsContainer: {
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center'
|
|
||||||
},
|
|
||||||
error: {
|
|
||||||
marginLeft: 12
|
|
||||||
},
|
|
||||||
subpageButton: {
|
|
||||||
marginLeft: 12
|
|
||||||
},
|
|
||||||
buttonText: {
|
|
||||||
color: backgroundColor,
|
|
||||||
fontFamily: 'Mont',
|
|
||||||
fontSize: 15
|
|
||||||
},
|
|
||||||
icon: {
|
|
||||||
marginRight: 6
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
marginRight: 24
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { useLazyQuery, useQuery, gql } from "@apollo/client";
|
import { useLazyQuery, useQuery, gql } from '@apollo/client'
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import { subMinutes } from 'date-fns'
|
import { subMinutes } from 'date-fns'
|
||||||
import FileSaver from 'file-saver'
|
import FileSaver from 'file-saver'
|
||||||
import React, { useState, useEffect } from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
|
|
@ -8,10 +7,6 @@ import { H3, P } from 'src/components/typography'
|
||||||
|
|
||||||
import { Button } from 'src/components/buttons'
|
import { Button } from 'src/components/buttons'
|
||||||
|
|
||||||
import { diagnosticsModal } from './MachineActions.styles'
|
|
||||||
|
|
||||||
const useStyles = makeStyles(diagnosticsModal)
|
|
||||||
|
|
||||||
const STATES = {
|
const STATES = {
|
||||||
INITIAL: 'INITIAL',
|
INITIAL: 'INITIAL',
|
||||||
EMPTY: 'EMPTY',
|
EMPTY: 'EMPTY',
|
||||||
|
|
@ -59,7 +54,6 @@ const createCsv = async ({ machineLogsCsv }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const DiagnosticsModal = ({ onClose, deviceId, sendAction }) => {
|
const DiagnosticsModal = ({ onClose, deviceId, sendAction }) => {
|
||||||
const classes = useStyles()
|
|
||||||
const [state, setState] = useState(STATES.INITIAL)
|
const [state, setState] = useState(STATES.INITIAL)
|
||||||
const [timestamp, setTimestamp] = useState(null)
|
const [timestamp, setTimestamp] = useState(null)
|
||||||
let timeout = null
|
let timeout = null
|
||||||
|
|
@ -103,6 +97,8 @@ const DiagnosticsModal = ({ onClose, deviceId, sendAction }) => {
|
||||||
sendAction()
|
sendAction()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const messageClass = 'm-auto flex flex-col items-center justify-center'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
closeOnBackdropClick={true}
|
closeOnBackdropClick={true}
|
||||||
|
|
@ -111,27 +107,27 @@ const DiagnosticsModal = ({ onClose, deviceId, sendAction }) => {
|
||||||
handleClose={onClose}
|
handleClose={onClose}
|
||||||
open={true}>
|
open={true}>
|
||||||
{state === STATES.INITIAL && (
|
{state === STATES.INITIAL && (
|
||||||
<div className={classes.message}>
|
<div className={messageClass}>
|
||||||
<H3>Loading...</H3>
|
<H3>Loading...</H3>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{state === STATES.EMPTY && (
|
{state === STATES.EMPTY && (
|
||||||
<div className={classes.message}>
|
<div className={messageClass}>
|
||||||
<H3>No diagnostics available</H3>
|
<H3>No diagnostics available</H3>
|
||||||
<P>Run diagnostics to generate a report</P>
|
<P>Run diagnostics to generate a report</P>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{state === STATES.RUNNING && (
|
{state === STATES.RUNNING && (
|
||||||
<div className={classes.message}>
|
<div className={messageClass}>
|
||||||
<H3>Running Diagnostics...</H3>
|
<H3>Running Diagnostics...</H3>
|
||||||
<P>This page should refresh automatically</P>
|
<P>This page should refresh automatically</P>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{state === STATES.FAILURE && (
|
{state === STATES.FAILURE && (
|
||||||
<div className={classes.message}>
|
<div className={messageClass}>
|
||||||
<H3>Failed to run diagnostics</H3>
|
<H3>Failed to run diagnostics</H3>
|
||||||
<P>Please try again. If the problem persists, contact support.</P>
|
<P>Please try again. If the problem persists, contact support.</P>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -139,11 +135,11 @@ const DiagnosticsModal = ({ onClose, deviceId, sendAction }) => {
|
||||||
|
|
||||||
{state === STATES.FILLED && (
|
{state === STATES.FILLED && (
|
||||||
<div>
|
<div>
|
||||||
<div className={classes.photoWrapper}>
|
<div className="flex mt-6">
|
||||||
<div>
|
<div>
|
||||||
<H3>Scan</H3>
|
<H3>Scan</H3>
|
||||||
<img
|
<img
|
||||||
className={classes.photo}
|
className="w-88"
|
||||||
src={path + 'scan.jpg'}
|
src={path + 'scan.jpg'}
|
||||||
alt="Failure getting photo"
|
alt="Failure getting photo"
|
||||||
/>
|
/>
|
||||||
|
|
@ -151,7 +147,7 @@ const DiagnosticsModal = ({ onClose, deviceId, sendAction }) => {
|
||||||
<div>
|
<div>
|
||||||
<H3>Front</H3>
|
<H3>Front</H3>
|
||||||
<img
|
<img
|
||||||
className={classes.photo}
|
className="w-88"
|
||||||
src={path + 'front.jpg'}
|
src={path + 'front.jpg'}
|
||||||
alt="Failure getting photo"
|
alt="Failure getting photo"
|
||||||
/>
|
/>
|
||||||
|
|
@ -163,7 +159,7 @@ const DiagnosticsModal = ({ onClose, deviceId, sendAction }) => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className={classes.footer}>
|
<div className="flex flex-row mt-auto ml-auto mr-2 mb-0">
|
||||||
<Button
|
<Button
|
||||||
disabled={state !== STATES.FILLED || !timestamp}
|
disabled={state !== STATES.FILLED || !timestamp}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
@ -176,7 +172,7 @@ const DiagnosticsModal = ({ onClose, deviceId, sendAction }) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
className={classes.downloadLogs}>
|
className="mt-auto ml-auto mr-2 mb-0">
|
||||||
Download Logs
|
Download Logs
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { useMutation, useLazyQuery, gql } from "@apollo/client";
|
import { useMutation, useLazyQuery, gql } from '@apollo/client'
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import React, { memo, useState } from 'react'
|
import React, { memo, useState } from 'react'
|
||||||
import { ConfirmDialog } from 'src/components/ConfirmDialog'
|
import { ConfirmDialog } from 'src/components/ConfirmDialog'
|
||||||
import ActionButton from 'src/components/buttons/ActionButton'
|
import ActionButton from 'src/components/buttons/ActionButton'
|
||||||
|
|
@ -14,9 +13,6 @@ import UnpairReversedIcon from 'src/styling/icons/button/unpair/white.svg?react'
|
||||||
import UnpairIcon from 'src/styling/icons/button/unpair/zodiac.svg?react'
|
import UnpairIcon from 'src/styling/icons/button/unpair/zodiac.svg?react'
|
||||||
|
|
||||||
import DiagnosticsModal from './DiagnosticsModal'
|
import DiagnosticsModal from './DiagnosticsModal'
|
||||||
import { machineActionsStyles } from './MachineActions.styles'
|
|
||||||
|
|
||||||
const useStyles = makeStyles(machineActionsStyles)
|
|
||||||
|
|
||||||
const MACHINE_ACTION = gql`
|
const MACHINE_ACTION = gql`
|
||||||
mutation MachineAction(
|
mutation MachineAction(
|
||||||
|
|
@ -67,10 +63,9 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
|
||||||
const [preflightOptions, setPreflightOptions] = useState({})
|
const [preflightOptions, setPreflightOptions] = useState({})
|
||||||
const [showModal, setShowModal] = useState(false)
|
const [showModal, setShowModal] = useState(false)
|
||||||
const [errorMessage, setErrorMessage] = useState(null)
|
const [errorMessage, setErrorMessage] = useState(null)
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
const warningMessage = (
|
const warningMessage = (
|
||||||
<span className={classes.warning}>
|
<span className="text-tomato">
|
||||||
A user may be in the middle of a transaction and they could lose their
|
A user may be in the middle of a transaction and they could lose their
|
||||||
funds if you continue.
|
funds if you continue.
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -113,10 +108,9 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<H3>Actions</H3>
|
<H3>Actions</H3>
|
||||||
<div className={classes.stack}>
|
<div className="flex flex-row flex-wrap justify-start gap-2">
|
||||||
<ActionButton
|
<ActionButton
|
||||||
color="primary"
|
color="primary"
|
||||||
className={classes.mr}
|
|
||||||
Icon={EditIcon}
|
Icon={EditIcon}
|
||||||
InverseIcon={EditReversedIcon}
|
InverseIcon={EditReversedIcon}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
|
|
@ -131,7 +125,6 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
<ActionButton
|
<ActionButton
|
||||||
color="primary"
|
color="primary"
|
||||||
className={classes.mr}
|
|
||||||
Icon={UnpairIcon}
|
Icon={UnpairIcon}
|
||||||
InverseIcon={UnpairReversedIcon}
|
InverseIcon={UnpairReversedIcon}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
|
|
@ -145,7 +138,6 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
<ActionButton
|
<ActionButton
|
||||||
color="primary"
|
color="primary"
|
||||||
className={classes.mr}
|
|
||||||
Icon={RebootIcon}
|
Icon={RebootIcon}
|
||||||
InverseIcon={RebootReversedIcon}
|
InverseIcon={RebootReversedIcon}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
|
|
@ -159,7 +151,6 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
<ActionButton
|
<ActionButton
|
||||||
color="primary"
|
color="primary"
|
||||||
className={classes.mr}
|
|
||||||
Icon={ShutdownIcon}
|
Icon={ShutdownIcon}
|
||||||
InverseIcon={ShutdownReversedIcon}
|
InverseIcon={ShutdownReversedIcon}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
|
|
@ -175,7 +166,6 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
<ActionButton
|
<ActionButton
|
||||||
color="primary"
|
color="primary"
|
||||||
className={classes.inlineChip}
|
|
||||||
Icon={RebootIcon}
|
Icon={RebootIcon}
|
||||||
InverseIcon={RebootReversedIcon}
|
InverseIcon={RebootReversedIcon}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
|
|
@ -190,7 +180,6 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
|
||||||
{machine.model === 'aveiro' && (
|
{machine.model === 'aveiro' && (
|
||||||
<ActionButton
|
<ActionButton
|
||||||
color="primary"
|
color="primary"
|
||||||
className={classes.mr}
|
|
||||||
Icon={RebootIcon}
|
Icon={RebootIcon}
|
||||||
InverseIcon={RebootReversedIcon}
|
InverseIcon={RebootReversedIcon}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
|
|
@ -208,7 +197,6 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
|
||||||
{machine.model === 'aveiro' && (
|
{machine.model === 'aveiro' && (
|
||||||
<ActionButton
|
<ActionButton
|
||||||
color="primary"
|
color="primary"
|
||||||
className={classes.inlineChip}
|
|
||||||
Icon={RebootIcon}
|
Icon={RebootIcon}
|
||||||
InverseIcon={RebootReversedIcon}
|
InverseIcon={RebootReversedIcon}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
|
|
@ -225,7 +213,6 @@ const MachineActions = memo(({ machine, onActionSuccess }) => {
|
||||||
)}
|
)}
|
||||||
<ActionButton
|
<ActionButton
|
||||||
color="primary"
|
color="primary"
|
||||||
className={classes.mr}
|
|
||||||
Icon={RebootIcon}
|
Icon={RebootIcon}
|
||||||
InverseIcon={RebootReversedIcon}
|
InverseIcon={RebootReversedIcon}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
|
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
||||||
import typographyStyles from 'src/components/typography/styles'
|
|
||||||
import { offColor, spacer, errorColor } from 'src/styling/variables'
|
|
||||||
|
|
||||||
const { label1 } = typographyStyles
|
|
||||||
|
|
||||||
const machineActionsStyles = {
|
|
||||||
label: {
|
|
||||||
extend: label1,
|
|
||||||
color: offColor,
|
|
||||||
marginBottom: 4
|
|
||||||
},
|
|
||||||
inlineChip: {
|
|
||||||
marginInlineEnd: '0.25em'
|
|
||||||
},
|
|
||||||
stack: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
justifyContent: 'start'
|
|
||||||
},
|
|
||||||
mr: {
|
|
||||||
marginRight: spacer,
|
|
||||||
marginBottom: spacer
|
|
||||||
},
|
|
||||||
warning: {
|
|
||||||
color: errorColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const diagnosticsModal = {
|
|
||||||
modal: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
alignItems: 'center',
|
|
||||||
padding: '1em'
|
|
||||||
},
|
|
||||||
photo: {
|
|
||||||
width: 350
|
|
||||||
},
|
|
||||||
photoWrapper: {
|
|
||||||
marginTop: spacer * 3,
|
|
||||||
display: 'flex'
|
|
||||||
},
|
|
||||||
footer: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
margin: [['auto', 0, spacer * 3, 0]]
|
|
||||||
},
|
|
||||||
downloadLogs: {
|
|
||||||
margin: [['auto', spacer, 0, 'auto']]
|
|
||||||
},
|
|
||||||
message: {
|
|
||||||
margin: 'auto',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export { machineActionsStyles, diagnosticsModal }
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classnames from 'classnames'
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
|
|
@ -13,9 +11,7 @@ import EditIcon from 'src/styling/icons/action/edit/white.svg?react'
|
||||||
|
|
||||||
import { IconButton } from 'src/components/buttons'
|
import { IconButton } from 'src/components/buttons'
|
||||||
|
|
||||||
import styles from './SingleRowTable.styles'
|
import { Label1, P } from '../typography/index.jsx'
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const SingleRowTable = ({
|
const SingleRowTable = ({
|
||||||
width = 378,
|
width = 378,
|
||||||
|
|
@ -25,34 +21,44 @@ const SingleRowTable = ({
|
||||||
onEdit,
|
onEdit,
|
||||||
className
|
className
|
||||||
}) => {
|
}) => {
|
||||||
const classes = useStyles({ width, height })
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Table className={classnames(className, classes.table)}>
|
<Table className={className} style={{ width }}>
|
||||||
<THead>
|
<THead>
|
||||||
<Th className={classes.head}>
|
<Th className="flex flex-1 justify-between items-center pr-3">
|
||||||
{title}
|
{title}
|
||||||
<IconButton onClick={onEdit} className={classes.button} size="large">
|
<IconButton onClick={onEdit} className="mb-[1px]" size="large">
|
||||||
<EditIcon />
|
<EditIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Th>
|
</Th>
|
||||||
</THead>
|
</THead>
|
||||||
<TBody>
|
<TBody>
|
||||||
<Tr className={classes.tr}>
|
<Tr className="m-0" style={{ height }}>
|
||||||
<Td width={width}>
|
<Td width={width}>
|
||||||
{items && (
|
{items && (
|
||||||
<>
|
<>
|
||||||
{items[0] && (
|
{items[0] && (
|
||||||
<div className={classes.itemWrapper}>
|
<div className="flex flex-col mt-4 min-h-9">
|
||||||
<div className={classes.label}>{items[0].label}</div>
|
<Label1 noMargin className="color-comet mb-1">
|
||||||
<div className={classes.item}>{items[0].value}</div>
|
{items[0].label}
|
||||||
|
</Label1>
|
||||||
|
<P
|
||||||
|
noMargin
|
||||||
|
className="overflow-hidden text-ellipsis whitespace-nowrap">
|
||||||
|
{items[0].value}
|
||||||
|
</P>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{items[1] && (
|
{items[1] && (
|
||||||
<div className={classes.itemWrapper}>
|
<div className="flex flex-col mt-4 min-h-9">
|
||||||
<div className={classes.label}>{items[1].label}</div>
|
<Label1 noMargin className="color-comet mb-1">
|
||||||
<div className={classes.item}>{items[1].value}</div>
|
{items[1].label}
|
||||||
|
</Label1>
|
||||||
|
<P
|
||||||
|
noMargin
|
||||||
|
className="overflow-hidden text-ellipsis whitespace-nowrap">
|
||||||
|
{items[1].value}
|
||||||
|
</P>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|
@ -62,7 +68,7 @@ const SingleRowTable = ({
|
||||||
</TBody>
|
</TBody>
|
||||||
</Table>
|
</Table>
|
||||||
</>
|
</>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SingleRowTable
|
export default SingleRowTable
|
||||||
|
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
import typographyStyles from 'src/components/typography/styles'
|
|
||||||
import { offColor } from 'src/styling/variables'
|
|
||||||
|
|
||||||
const { label1, p } = typographyStyles
|
|
||||||
|
|
||||||
export default {
|
|
||||||
tr: ({ height }) => ({
|
|
||||||
margin: 0,
|
|
||||||
height
|
|
||||||
}),
|
|
||||||
table: ({ width }) => ({
|
|
||||||
width
|
|
||||||
}),
|
|
||||||
head: {
|
|
||||||
display: 'flex',
|
|
||||||
flex: 1,
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
alignItems: 'center',
|
|
||||||
paddingRight: 12
|
|
||||||
},
|
|
||||||
button: {
|
|
||||||
marginBottom: 1
|
|
||||||
},
|
|
||||||
itemWrapper: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
marginTop: 16,
|
|
||||||
minHeight: 35
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
extend: label1,
|
|
||||||
color: offColor,
|
|
||||||
marginBottom: 4
|
|
||||||
},
|
|
||||||
item: {
|
|
||||||
extend: p,
|
|
||||||
overflow: 'hidden',
|
|
||||||
textOverflow: 'ellipsis',
|
|
||||||
whiteSpace: 'nowrap'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +1,15 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import React, { memo } from 'react'
|
import React, { memo } from 'react'
|
||||||
import { H4 } from 'src/components/typography'
|
import { H4 } from 'src/components/typography'
|
||||||
import EmptyTableIcon from 'src/styling/icons/table/empty-table.svg?react'
|
import EmptyTableIcon from 'src/styling/icons/table/empty-table.svg?react'
|
||||||
|
|
||||||
const styles = {
|
|
||||||
emptyTable: {
|
|
||||||
width: '100%',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
alignItems: 'center',
|
|
||||||
marginTop: 52
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const EmptyTable = memo(({ message, className }) => {
|
const EmptyTable = memo(({ message, className }) => {
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames(className, classes.emptyTable)}>
|
<div
|
||||||
|
className={classNames(
|
||||||
|
className,
|
||||||
|
'flex flex-col items-center w-full mt-13 text-sm font-bold font-museo'
|
||||||
|
)}>
|
||||||
<EmptyTableIcon />
|
<EmptyTableIcon />
|
||||||
<H4>{message}</H4>
|
<H4>{message}</H4>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,14 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import React, { memo } from 'react'
|
import React, { memo } from 'react'
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
|
||||||
table: {
|
|
||||||
// backgroundColor: tableHeaderColor,
|
|
||||||
tableLayout: 'fixed',
|
|
||||||
borderCollapse: 'separate',
|
|
||||||
borderSpacing: '0 0'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const Table = memo(({ className, children, ...props }) => {
|
const Table = memo(({ className, children, ...props }) => {
|
||||||
const classes = useStyles()
|
|
||||||
return (
|
return (
|
||||||
<table {...props} className={classnames(classes.table, className)}>
|
<table
|
||||||
|
{...props}
|
||||||
|
className={classnames(
|
||||||
|
'table-fixed border-separate border-spacing-0',
|
||||||
|
className
|
||||||
|
)}>
|
||||||
{children}
|
{children}
|
||||||
</table>
|
</table>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,11 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import React, { memo } from 'react'
|
import React, { memo } from 'react'
|
||||||
|
|
||||||
import { spacer } from 'src/styling/variables'
|
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
|
||||||
td: {
|
|
||||||
padding: [[0, spacer * 3]]
|
|
||||||
},
|
|
||||||
alignRight: {
|
|
||||||
textAlign: 'right'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const TableCell = memo(
|
const TableCell = memo(
|
||||||
({ colspan, rightAlign, className, children, ...props }) => {
|
({ colspan, rightAlign, className, children, ...props }) => {
|
||||||
const classes = useStyles()
|
|
||||||
const styles = {
|
const styles = {
|
||||||
[classes.td]: true,
|
'py-0 px-6': true,
|
||||||
[classes.alignRight]: rightAlign
|
'text-right': rightAlign
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,8 @@ const TableHeaderCell = memo(
|
||||||
({ rightAlign, children, className, ...props }) => {
|
({ rightAlign, children, className, ...props }) => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const styles = {
|
const styles = {
|
||||||
[classes.th]: true,
|
'bg-zodiac text-white py-0 px-6 h-8 font-': true,
|
||||||
[classes.alignRight]: rightAlign
|
'text-right': rightAlign
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -1,54 +1,18 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import React, { memo } from 'react'
|
import React, { memo } from 'react'
|
||||||
|
|
||||||
import typographyStyles from 'src/components/typography/styles'
|
|
||||||
import {
|
|
||||||
tableCellColor,
|
|
||||||
tableCellHeight,
|
|
||||||
tableSmCellHeight,
|
|
||||||
tableLgCellHeight,
|
|
||||||
tableErrorColor,
|
|
||||||
tableSuccessColor
|
|
||||||
} from 'src/styling/variables'
|
|
||||||
|
|
||||||
const { info2, p } = typographyStyles
|
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
|
||||||
tr: {
|
|
||||||
extend: p,
|
|
||||||
padding: 4,
|
|
||||||
height: tableCellHeight,
|
|
||||||
backgroundColor: tableCellColor
|
|
||||||
},
|
|
||||||
lg: {
|
|
||||||
extend: info2,
|
|
||||||
height: tableLgCellHeight
|
|
||||||
},
|
|
||||||
sm: {
|
|
||||||
height: tableSmCellHeight
|
|
||||||
},
|
|
||||||
error: {
|
|
||||||
backgroundColor: tableErrorColor
|
|
||||||
},
|
|
||||||
success: {
|
|
||||||
backgroundColor: tableSuccessColor
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const TableRow = memo(
|
const TableRow = memo(
|
||||||
({ className, children, header, error, success, size = 'sm', ...props }) => {
|
({ className, children, header, error, success, size = 'sm', ...props }) => {
|
||||||
const classes = useStyles()
|
|
||||||
const classnamesObj = {
|
const classnamesObj = {
|
||||||
[classes.tr]: !header,
|
'p-1 h-12 bg-white': !header,
|
||||||
[classes.sm]: !header && size === 'sm',
|
'h-8': !header && size === 'sm',
|
||||||
[classes.lg]: !header && size === 'lg',
|
'h-9 font-bold text-base ': !header && size === 'lg',
|
||||||
[classes.error]: error,
|
'bg-misty-rose': error,
|
||||||
[classes.success]: success
|
'bg-spring3': success
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr className={classnames(classnamesObj, className)} {...props}>
|
<tr className={classnames(classnamesObj, className, 'text-')} {...props}>
|
||||||
{children}
|
{children}
|
||||||
</tr>
|
</tr>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { makeStyles } from '@mui/styles'
|
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useState, useEffect } from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
|
|
@ -22,10 +21,6 @@ import ExpandOpenIcon from 'src/styling/icons/action/expand/open.svg?react'
|
||||||
|
|
||||||
import { EmptyTable } from 'src/components/table'
|
import { EmptyTable } from 'src/components/table'
|
||||||
|
|
||||||
import styles from './DataTable.styles'
|
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
|
||||||
|
|
||||||
const Row = ({
|
const Row = ({
|
||||||
id,
|
id,
|
||||||
index,
|
index,
|
||||||
|
|
@ -41,20 +36,18 @@ const Row = ({
|
||||||
size,
|
size,
|
||||||
...props
|
...props
|
||||||
}) => {
|
}) => {
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
const hasPointer = onClick || expandable
|
const hasPointer = onClick || expandable
|
||||||
const trClasses = {
|
const trClasses = {
|
||||||
[classes.pointer]: hasPointer,
|
'cursor-pointer': hasPointer,
|
||||||
[classes.row]: true,
|
'border-2 border-transparent': true,
|
||||||
[classes.expanded]: expanded
|
'border-2 border-zircon shadow-xl': expanded
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.rowWrapper}>
|
<div className="p-[1px]">
|
||||||
<div
|
<div
|
||||||
data-cy={id}
|
data-cy={id}
|
||||||
className={classnames({ [classes.before]: expanded && index !== 0 })}>
|
className={classnames({ 'pt-3': expanded && index !== 0 })}>
|
||||||
<Tr
|
<Tr
|
||||||
size={size}
|
size={size}
|
||||||
className={classnames(trClasses)}
|
className={classnames(trClasses)}
|
||||||
|
|
@ -74,7 +67,7 @@ const Row = ({
|
||||||
<Td width={expWidth} textAlign="center">
|
<Td width={expWidth} textAlign="center">
|
||||||
<button
|
<button
|
||||||
onClick={() => expandRow(id, data)}
|
onClick={() => expandRow(id, data)}
|
||||||
className={classes.expandButton}>
|
className="outline-0 border-0 bg-transparent cursor-pointer p-1">
|
||||||
{expanded && <ExpandOpenIcon />}
|
{expanded && <ExpandOpenIcon />}
|
||||||
{!expanded && <ExpandClosedIcon />}
|
{!expanded && <ExpandClosedIcon />}
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -83,8 +76,11 @@ const Row = ({
|
||||||
</Tr>
|
</Tr>
|
||||||
</div>
|
</div>
|
||||||
{expanded && (
|
{expanded && (
|
||||||
<div className={classes.after}>
|
<div className="pb-3">
|
||||||
<Tr className={classnames({ [classes.expanded]: expanded })}>
|
<Tr
|
||||||
|
className={classnames({
|
||||||
|
'border-2 border-zircon shadow-md': expanded
|
||||||
|
})}>
|
||||||
<Td width={width}>
|
<Td width={width}>
|
||||||
<Details it={data} timezone={props.timezone} />
|
<Details it={data} timezone={props.timezone} />
|
||||||
</Td>
|
</Td>
|
||||||
|
|
@ -118,8 +114,6 @@ const DataTable = ({
|
||||||
const expWidth = maxWidth - coreWidth
|
const expWidth = maxWidth - coreWidth
|
||||||
const width = coreWidth + (expandable ? expWidth : 0)
|
const width = coreWidth + (expandable ? expWidth : 0)
|
||||||
|
|
||||||
const classes = useStyles({ width })
|
|
||||||
|
|
||||||
const expandRow = (id, data) => {
|
const expandRow = (id, data) => {
|
||||||
if (data.id) {
|
if (data.id) {
|
||||||
cache.clear(data.id)
|
cache.clear(data.id)
|
||||||
|
|
@ -176,7 +170,12 @@ const DataTable = ({
|
||||||
'flex flex-1 flex-col': true,
|
'flex flex-1 flex-col': true,
|
||||||
[className]: !!className
|
[className]: !!className
|
||||||
})}>
|
})}>
|
||||||
<Table className={classnames(classes.table, tableClassName)}>
|
<Table
|
||||||
|
className={classnames(
|
||||||
|
'mb-12 min-h-50 flex-1 flex flex-col',
|
||||||
|
tableClassName
|
||||||
|
)}
|
||||||
|
style={{ width }}>
|
||||||
<THead>
|
<THead>
|
||||||
{elements.map(({ width, className, textAlign, header }, idx) => (
|
{elements.map(({ width, className, textAlign, header }, idx) => (
|
||||||
<Th
|
<Th
|
||||||
|
|
@ -189,7 +188,7 @@ const DataTable = ({
|
||||||
))}
|
))}
|
||||||
{expandable && <Th width={expWidth}></Th>}
|
{expandable && <Th width={expWidth}></Th>}
|
||||||
</THead>
|
</THead>
|
||||||
<TBody className={classes.body}>
|
<TBody className="flex-auto">
|
||||||
{loading && <H4>Loading...</H4>}
|
{loading && <H4>Loading...</H4>}
|
||||||
{!loading && R.isEmpty(data) && <EmptyTable message={emptyText} />}
|
{!loading && R.isEmpty(data) && <EmptyTable message={emptyText} />}
|
||||||
{!loading && !R.isEmpty(data) && (
|
{!loading && !R.isEmpty(data) && (
|
||||||
|
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
import { zircon } from 'src/styling/variables'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
expandButton: {
|
|
||||||
outline: 'none',
|
|
||||||
border: 'none',
|
|
||||||
backgroundColor: 'transparent',
|
|
||||||
cursor: 'pointer',
|
|
||||||
padding: 4
|
|
||||||
},
|
|
||||||
rowWrapper: {
|
|
||||||
// workaround to shadows cut by r-virtualized when scroll is visible
|
|
||||||
padding: 1
|
|
||||||
},
|
|
||||||
row: {
|
|
||||||
border: [[2, 'solid', 'transparent']],
|
|
||||||
borderRadius: 0
|
|
||||||
},
|
|
||||||
expanded: {
|
|
||||||
border: [[2, 'solid', zircon]],
|
|
||||||
boxShadow: '0 0 8px 0 rgba(0,0,0,0.08)'
|
|
||||||
},
|
|
||||||
before: {
|
|
||||||
paddingTop: 12
|
|
||||||
},
|
|
||||||
after: {
|
|
||||||
paddingBottom: 12
|
|
||||||
},
|
|
||||||
pointer: {
|
|
||||||
cursor: 'pointer'
|
|
||||||
},
|
|
||||||
body: {
|
|
||||||
flex: [[1, 1, 'auto']]
|
|
||||||
},
|
|
||||||
table: ({ width }) => ({
|
|
||||||
marginBottom: 30,
|
|
||||||
minHeight: 200,
|
|
||||||
width,
|
|
||||||
flex: 1,
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column'
|
|
||||||
}),
|
|
||||||
emptyTable: {
|
|
||||||
width: '100%',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
alignItems: 'center',
|
|
||||||
marginTop: 52
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
import { Td } from 'src/components/fake-table/Table'
|
|
||||||
import StripesSvg from 'src/styling/icons/stripes.svg?react'
|
|
||||||
|
|
||||||
const Stripes = ({ width }) => (
|
|
||||||
<Td width={width}>
|
|
||||||
<StripesSvg />
|
|
||||||
</Td>
|
|
||||||
)
|
|
||||||
|
|
||||||
export default Stripes
|
|
||||||
|
|
@ -164,6 +164,16 @@ theme = createTheme(theme, {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
MuiCheckbox: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
color: secondaryColor,
|
||||||
|
'&.Mui-checked': {
|
||||||
|
color: secondaryColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
MuiChip: {
|
MuiChip: {
|
||||||
styleOverrides: {
|
styleOverrides: {
|
||||||
root: {
|
root: {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue