fix: machine status layout bugs
fix: reboot icon looks cropped fix: confirm dialog layout fix: Status chip background colors fix: detailed machine status layout fix: machine detailed status layout fix: machine status article links, status chip size fix: confirmDialog for all machine actions fix: confirm dialog on every action. reload when success fix: verbose input label fix: display software version and machine model fix: eslint fixes fix: removed machine version and update button fix: get machines statuses from ping chore: removed the support articles until they're ready fix: reset value and error states when closing the confirm dialog fix: removed unused info from the machine table styles: fixed styles in the machine details card chore: moved styles to another file fix: fixed the version gql property
This commit is contained in:
parent
825a9bfe09
commit
db014a3ed4
9 changed files with 278 additions and 214 deletions
|
|
@ -4,6 +4,8 @@ const axios = require('axios')
|
|||
const logger = require('./logger')
|
||||
const db = require('./db')
|
||||
const pairing = require('./pairing')
|
||||
const notifier = require('./notifier')
|
||||
const dbm = require('./postgresql_interface')
|
||||
const configManager = require('./new-config-manager')
|
||||
const settingsLoader = require('./new-settings-loader')
|
||||
|
||||
|
|
@ -34,15 +36,40 @@ function getConfig (defaultConfig) {
|
|||
}
|
||||
|
||||
function getMachineNames (config) {
|
||||
const fullyFunctionalStatus = {label: 'Fully functional', type: 'success'}
|
||||
const unresponsiveStatus = {label: 'Unresponsive', type: 'error'}
|
||||
const stuckStatus = {label: 'Stuck', type: 'error'}
|
||||
|
||||
return Promise.all([getMachines(), getConfig(config)])
|
||||
.then(([machines, config]) => {
|
||||
.then(([machines, config]) => Promise.all(
|
||||
[machines, notifier.checkPings(machines), dbm.machineEvents(), config]
|
||||
))
|
||||
.then(([machines, pings, events, config]) => {
|
||||
const getPingStatus = (ping) => {
|
||||
if (!ping) return fullyFunctionalStatus
|
||||
|
||||
if (ping.age) return unresponsiveStatus
|
||||
|
||||
return fullyFunctionalStatus
|
||||
}
|
||||
|
||||
const getStuckStatus = (stuck) => {
|
||||
if (!stuck || !stuck.age) return undefined
|
||||
|
||||
return stuckStatus
|
||||
}
|
||||
|
||||
const addName = r => {
|
||||
const cashOutConfig = configManager.getCashOut(r.deviceId, config)
|
||||
|
||||
const cashOut = !!cashOutConfig.active
|
||||
|
||||
// TODO new-admin actually load status based on ping.
|
||||
const statuses = [{label: 'Unknown detailed status', type: 'warning'}]
|
||||
const ping = getPingStatus(_.first(pings[r.deviceId]))
|
||||
const stuck = getStuckStatus(_.first(notifier.checkStuckScreen(events, r.name)))
|
||||
|
||||
const statuses = [ping]
|
||||
|
||||
if (stuck) statuses.push(stuck)
|
||||
|
||||
return _.assign(r, {cashOut, statuses})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -344,4 +344,8 @@ function buildAlertFingerprint (alertRec, notifications) {
|
|||
return crypto.createHash('sha256').update(subject).digest('hex')
|
||||
}
|
||||
|
||||
module.exports = { checkNotification }
|
||||
module.exports = {
|
||||
checkNotification,
|
||||
checkPings,
|
||||
checkStuckScreen
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,51 +2,50 @@ import {
|
|||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogContentText,
|
||||
makeStyles
|
||||
} from '@material-ui/core'
|
||||
import React, { useEffect, useState, memo } from 'react'
|
||||
import React, { memo, useState } from 'react'
|
||||
|
||||
import { Button, IconButton } from 'src/components/buttons'
|
||||
import { TextInput } from 'src/components/inputs'
|
||||
import { H4 } from 'src/components/typography'
|
||||
import { ReactComponent as CloseIcon } from 'src/styling/icons/action/close/zodiac.svg'
|
||||
import { fontSize3 } from 'src/styling/variables'
|
||||
import { spacer } from 'src/styling/variables'
|
||||
|
||||
import { TextInput } from './inputs'
|
||||
import { H4, P } from './typography'
|
||||
import ErrorMessage from './ErrorMessage'
|
||||
|
||||
const useStyles = makeStyles({
|
||||
label: {
|
||||
fontSize: fontSize3
|
||||
dialogContent: {
|
||||
width: 434,
|
||||
padding: spacer * 2,
|
||||
paddingRight: spacer * 3.5
|
||||
},
|
||||
spacing: {
|
||||
padding: 32
|
||||
dialogTitle: {
|
||||
padding: spacer * 2,
|
||||
paddingRight: spacer * 1.5,
|
||||
display: 'flex',
|
||||
'justify-content': 'space-between',
|
||||
'& > h4': {
|
||||
margin: 0
|
||||
},
|
||||
'& > button': {
|
||||
padding: 0,
|
||||
marginTop: -(spacer / 2)
|
||||
}
|
||||
},
|
||||
wrapper: {
|
||||
display: 'flex'
|
||||
},
|
||||
title: {
|
||||
margin: [[20, 0, 24, 16]]
|
||||
},
|
||||
closeButton: {
|
||||
padding: 0,
|
||||
margin: [[12, 12, 'auto', 'auto']]
|
||||
// position: 'absolute',
|
||||
// right: spacer,
|
||||
// top: spacer
|
||||
dialogActions: {
|
||||
padding: spacer * 4,
|
||||
paddingTop: spacer * 2
|
||||
}
|
||||
})
|
||||
|
||||
export const DialogTitle = ({ children, onClose }) => {
|
||||
const classes = useStyles()
|
||||
return (
|
||||
<div className={classes.wrapper}>
|
||||
<div className={classes.dialogTitle}>
|
||||
{children}
|
||||
{onClose && (
|
||||
<IconButton
|
||||
size={16}
|
||||
aria-label="close"
|
||||
className={classes.closeButton}
|
||||
onClick={onClose}>
|
||||
<IconButton size={16} aria-label="close" onClick={onClose}>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
)}
|
||||
|
|
@ -57,50 +56,59 @@ export const DialogTitle = ({ children, onClose }) => {
|
|||
export const ConfirmDialog = memo(
|
||||
({
|
||||
title = 'Confirm action',
|
||||
subtitle = 'This action requires confirmation',
|
||||
errorMessage = 'This action requires confirmation',
|
||||
open,
|
||||
toBeConfirmed,
|
||||
onConfirmed,
|
||||
onDissmised,
|
||||
className,
|
||||
...props
|
||||
}) => {
|
||||
const classes = useStyles()
|
||||
const [value, setValue] = useState('')
|
||||
const [error, setError] = useState(false)
|
||||
useEffect(() => setValue(''), [open])
|
||||
const handleChange = event => {
|
||||
setValue(event.target.value)
|
||||
const handleChange = event => setValue(event.target.value)
|
||||
|
||||
const innerOnClose = () => {
|
||||
setValue('')
|
||||
setError(false)
|
||||
onDissmised()
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={open} aria-labelledby="form-dialog-title" {...props}>
|
||||
<DialogTitle id="customized-dialog-title" onClose={onDissmised}>
|
||||
<H4 className={classes.title}>{title}</H4>
|
||||
{subtitle && (
|
||||
<DialogContentText>
|
||||
<P>{subtitle}</P>
|
||||
</DialogContentText>
|
||||
)}
|
||||
<DialogTitle id="customized-dialog-title" onClose={innerOnClose}>
|
||||
<H4>{title}</H4>
|
||||
</DialogTitle>
|
||||
<DialogContent className={className}>
|
||||
{errorMessage && (
|
||||
<DialogTitle>
|
||||
<ErrorMessage>
|
||||
{errorMessage.split(':').map(error => (
|
||||
<>
|
||||
{error}
|
||||
<br />
|
||||
</>
|
||||
))}
|
||||
</ErrorMessage>
|
||||
</DialogTitle>
|
||||
)}
|
||||
<DialogContent className={classes.dialogContent}>
|
||||
<TextInput
|
||||
label={`Write '${toBeConfirmed}' to confirm`}
|
||||
label={`Write '${toBeConfirmed}' to confirm this action`}
|
||||
name="confirm-input"
|
||||
autoFocus
|
||||
id="confirm-input"
|
||||
type="text"
|
||||
size="lg"
|
||||
size="sm"
|
||||
fullWidth
|
||||
value={value}
|
||||
touched={{}}
|
||||
error={error}
|
||||
InputLabelProps={{ shrink: true, className: classes.label }}
|
||||
InputLabelProps={{ shrink: true }}
|
||||
onChange={handleChange}
|
||||
onBlur={() => setError(toBeConfirmed !== value)}
|
||||
/>
|
||||
</DialogContent>
|
||||
<DialogActions classes={{ spacing: classes.spacing }}>
|
||||
<DialogActions className={classes.dialogActions}>
|
||||
<Button
|
||||
color="green"
|
||||
disabled={toBeConfirmed !== value}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ import {
|
|||
spring3,
|
||||
smallestFontSize,
|
||||
inputFontFamily,
|
||||
spacer
|
||||
spacer,
|
||||
linen
|
||||
} from '../styling/variables'
|
||||
|
||||
const colors = {
|
||||
|
|
@ -22,7 +23,7 @@ const colors = {
|
|||
|
||||
const backgroundColors = {
|
||||
error: mistyRose,
|
||||
warning: mistyRose,
|
||||
warning: linen,
|
||||
success: spring3
|
||||
}
|
||||
|
||||
|
|
@ -40,21 +41,15 @@ const useStyles = makeStyles({
|
|||
fontSize: smallestFontSize,
|
||||
fontWeight: inputFontWeight,
|
||||
fontFamily: inputFontFamily,
|
||||
padding: [[spacer / 2, spacer]],
|
||||
paddingRight: spacer / 2,
|
||||
paddingLeft: spacer / 2,
|
||||
color: ({ type }) => colors[type]
|
||||
}
|
||||
})
|
||||
|
||||
const Status = ({ status, className }) => {
|
||||
const Status = ({ status }) => {
|
||||
const classes = useStyles({ type: status.type })
|
||||
return (
|
||||
<Chip
|
||||
type={status.type}
|
||||
label={status.label}
|
||||
className={className ?? null}
|
||||
classes={classes}
|
||||
/>
|
||||
)
|
||||
return <Chip type={status.type} label={status.label} classes={classes} />
|
||||
}
|
||||
|
||||
const MainStatus = ({ statuses }) => {
|
||||
|
|
@ -65,7 +60,7 @@ const MainStatus = ({ statuses }) => {
|
|||
const plus = { label: `+${statuses.length - 1}`, type: mainStatus.type }
|
||||
|
||||
return (
|
||||
<div style={{ marginLeft: -3 }}>
|
||||
<div>
|
||||
<Status status={mainStatus} />
|
||||
{statuses.length > 1 && <Status status={plus} />}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,20 +1,22 @@
|
|||
import { useMutation } from '@apollo/react-hooks'
|
||||
import { Dialog, DialogContent } from '@material-ui/core'
|
||||
import { Grid, Divider } from '@material-ui/core'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import gql from 'graphql-tag'
|
||||
import moment from 'moment'
|
||||
import React, { useState } from 'react'
|
||||
|
||||
import { DialogTitle, ConfirmDialog } from 'src/components/ConfirmDialog'
|
||||
import { ConfirmDialog } from 'src/components/ConfirmDialog'
|
||||
import { Status } from 'src/components/Status'
|
||||
import ActionButton from 'src/components/buttons/ActionButton'
|
||||
import { Label1, H4 } from 'src/components/typography'
|
||||
import { ReactComponent as LinkIcon } from 'src/styling/icons/button/link/zodiac.svg'
|
||||
import { ReactComponent as RebootReversedIcon } from 'src/styling/icons/button/reboot/white.svg'
|
||||
import { ReactComponent as RebootIcon } from 'src/styling/icons/button/reboot/zodiac.svg'
|
||||
import { ReactComponent as ShutdownReversedIcon } from 'src/styling/icons/button/shut down/white.svg'
|
||||
import { ReactComponent as ShutdownIcon } from 'src/styling/icons/button/shut down/zodiac.svg'
|
||||
import { ReactComponent as UnpairReversedIcon } from 'src/styling/icons/button/unpair/white.svg'
|
||||
import { ReactComponent as UnpairIcon } from 'src/styling/icons/button/unpair/zodiac.svg'
|
||||
|
||||
import styles from './MachineDetailsCard.styles'
|
||||
import { labelStyles, machineDetailsStyles } from './MachineDetailsCard.styles'
|
||||
|
||||
const MACHINE_ACTION = gql`
|
||||
mutation MachineAction($deviceId: ID!, $action: MachineAction!) {
|
||||
|
|
@ -24,150 +26,172 @@ const MACHINE_ACTION = gql`
|
|||
}
|
||||
`
|
||||
|
||||
const useStyles = makeStyles(styles)
|
||||
const supportArtices = [
|
||||
{
|
||||
// Default article for non-maped statuses
|
||||
code: undefined,
|
||||
label: 'Troubleshooting',
|
||||
article:
|
||||
'https://support.lamassu.is/hc/en-us/categories/115000075249-Troubleshooting'
|
||||
}
|
||||
]
|
||||
|
||||
const article = ({ code: status }) =>
|
||||
supportArtices.find(({ code: article }) => article === status)
|
||||
|
||||
const useLStyles = makeStyles(labelStyles)
|
||||
|
||||
const Label = ({ children }) => {
|
||||
const classes = useStyles()
|
||||
return <Label1 className={classes.label}>{children}</Label1>
|
||||
const classes = useLStyles()
|
||||
|
||||
return <div className={classes.label}>{children}</div>
|
||||
}
|
||||
|
||||
const MachineDetailsRow = ({ it: machine }) => {
|
||||
const [errorDialog, setErrorDialog] = useState(false)
|
||||
const [dialogOpen, setOpen] = useState(false)
|
||||
const [actionMessage, setActionMessage] = useState(null)
|
||||
const classes = useStyles()
|
||||
const useMDStyles = makeStyles(machineDetailsStyles)
|
||||
|
||||
const unpairDialog = () => setOpen(true)
|
||||
const Container = ({ children, ...props }) => (
|
||||
<Grid container spacing={4} {...props}>
|
||||
{children}
|
||||
</Grid>
|
||||
)
|
||||
|
||||
const Item = ({ children, ...props }) => (
|
||||
<Grid item xs {...props}>
|
||||
{children}
|
||||
</Grid>
|
||||
)
|
||||
|
||||
const MachineDetailsRow = ({ it: machine, onActionSuccess }) => {
|
||||
const [action, setAction] = useState('')
|
||||
const [dialogOpen, setOpen] = useState(false)
|
||||
const [errorMessage, setErrorMessage] = useState(null)
|
||||
const classes = useMDStyles()
|
||||
|
||||
const confirmDialog = action => setAction(action) || setOpen(true)
|
||||
|
||||
const [machineAction, { loading }] = useMutation(MACHINE_ACTION, {
|
||||
onError: ({ graphQLErrors, message }) => {
|
||||
const errorMessage = graphQLErrors[0] ? graphQLErrors[0].message : message
|
||||
setActionMessage(errorMessage)
|
||||
setErrorDialog(true)
|
||||
onError: ({ message }) => {
|
||||
const errorMessage = message ?? 'An error ocurred'
|
||||
setErrorMessage(errorMessage)
|
||||
},
|
||||
onCompleted: () => {
|
||||
// TODO: custom onActionSuccess needs to be passed down from the machinestatus table
|
||||
onActionSuccess ? onActionSuccess() : window.location.reload()
|
||||
setOpen(false)
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
<Dialog open={errorDialog} aria-labelledby="form-dialog-title">
|
||||
<DialogTitle
|
||||
id="customized-dialog-title"
|
||||
onClose={() => setErrorDialog(false)}>
|
||||
<H4>Error</H4>
|
||||
</DialogTitle>
|
||||
<DialogContent>{actionMessage}</DialogContent>
|
||||
</Dialog>
|
||||
<div className={classes.wrapper}>
|
||||
<div className={classes.column1}>
|
||||
<div className={classes.lastRow}>
|
||||
<div className={classes.status}>
|
||||
<Container className={classes.wrapper}>
|
||||
<Item xs={5}>
|
||||
<Container>
|
||||
<Item>
|
||||
<Label>Statuses</Label>
|
||||
<div>
|
||||
<ul className={classes.list}>
|
||||
{machine.statuses.map((status, index) => (
|
||||
<Status
|
||||
className={classes.chips}
|
||||
status={status}
|
||||
key={index}
|
||||
/>
|
||||
<li key={index}>
|
||||
<Status status={status} />
|
||||
</li>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
</ul>
|
||||
</Item>
|
||||
<Item>
|
||||
<Label>Lamassu Support article</Label>
|
||||
<div>
|
||||
{machine.statuses.map((...[, index]) => (
|
||||
// TODO new-admin: support articles
|
||||
<span key={index}></span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className={classes.separator} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={classes.column2}>
|
||||
<div className={classes.row}>
|
||||
<div className={classes.machineModel}>
|
||||
<ul className={classes.list}>
|
||||
{machine.statuses
|
||||
.map(article)
|
||||
.map(({ label, article }, index) => (
|
||||
<li key={index}>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href={article}>
|
||||
'{label}' <LinkIcon />
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</Item>
|
||||
</Container>
|
||||
</Item>
|
||||
<Divider
|
||||
orientation="vertical"
|
||||
flexItem
|
||||
className={classes.separator}
|
||||
/>
|
||||
<ConfirmDialog
|
||||
open={dialogOpen}
|
||||
title={`${action} this machine?`}
|
||||
errorMessage={errorMessage}
|
||||
toBeConfirmed={machine.name}
|
||||
onConfirmed={() => {
|
||||
setErrorMessage(null)
|
||||
machineAction({
|
||||
variables: {
|
||||
deviceId: machine.deviceId,
|
||||
action: `${action}`.toLowerCase()
|
||||
}
|
||||
})
|
||||
}}
|
||||
onDissmised={() => {
|
||||
setOpen(false)
|
||||
setErrorMessage(null)
|
||||
}}
|
||||
/>
|
||||
<Item xs>
|
||||
<Container className={classes.row}>
|
||||
<Item xs={4}>
|
||||
<Label>Machine Model</Label>
|
||||
<div>{machine.model ?? 'unknown'}</div>
|
||||
</div>
|
||||
<div>
|
||||
<span>{machine.model}</span>
|
||||
</Item>
|
||||
{/* <Item>
|
||||
<Label>Address</Label>
|
||||
<span>{machine.machineLocation}</span>
|
||||
</Item> */}
|
||||
<Item xs={4}>
|
||||
<Label>Paired at</Label>
|
||||
<div>
|
||||
{machine.pairedAt
|
||||
? moment(machine.pairedAt).format('YYYY-MM-DD HH:mm:ss')
|
||||
: 'N/A'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={classes.lastRow}>
|
||||
<div>
|
||||
<span>
|
||||
{moment(machine.pairedAt).format('YYYY-MM-DD HH:mm:ss')}
|
||||
</span>
|
||||
</Item>
|
||||
</Container>
|
||||
<Container>
|
||||
<Item>
|
||||
<Label>Actions</Label>
|
||||
<div className={classes.actionRow}>
|
||||
<div className={classes.stack}>
|
||||
<ActionButton
|
||||
className={classes.action}
|
||||
color="primary"
|
||||
className={classes.mr}
|
||||
Icon={UnpairIcon}
|
||||
InverseIcon={UnpairReversedIcon}
|
||||
disabled={loading}
|
||||
onClick={unpairDialog}>
|
||||
onClick={() => confirmDialog('Unpair')}>
|
||||
Unpair
|
||||
</ActionButton>
|
||||
<ConfirmDialog
|
||||
open={dialogOpen}
|
||||
className={classes.dialog}
|
||||
title="Unpair this machine?"
|
||||
subtitle={false}
|
||||
toBeConfirmed={machine.name}
|
||||
onConfirmed={() => {
|
||||
setOpen(false)
|
||||
machineAction({
|
||||
variables: {
|
||||
deviceId: machine.deviceId,
|
||||
action: 'unpair'
|
||||
}
|
||||
})
|
||||
}}
|
||||
onDissmised={() => {
|
||||
setOpen(false)
|
||||
}}
|
||||
/>
|
||||
<ActionButton
|
||||
className={classes.action}
|
||||
color="primary"
|
||||
className={classes.mr}
|
||||
Icon={RebootIcon}
|
||||
InverseIcon={RebootReversedIcon}
|
||||
disabled={loading}
|
||||
onClick={() => {
|
||||
machineAction({
|
||||
variables: {
|
||||
deviceId: machine.deviceId,
|
||||
action: 'reboot'
|
||||
}
|
||||
})
|
||||
}}>
|
||||
onClick={() => confirmDialog('Reboot')}>
|
||||
Reboot
|
||||
</ActionButton>
|
||||
<ActionButton
|
||||
className={classes.action}
|
||||
className={classes.inlineChip}
|
||||
disabled={loading}
|
||||
color="primary"
|
||||
Icon={RebootIcon}
|
||||
InverseIcon={RebootReversedIcon}
|
||||
onClick={() => {
|
||||
machineAction({
|
||||
variables: {
|
||||
deviceId: machine.deviceId,
|
||||
action: 'restartServices'
|
||||
}
|
||||
})
|
||||
}}>
|
||||
Restart Services
|
||||
Icon={ShutdownIcon}
|
||||
InverseIcon={ShutdownReversedIcon}
|
||||
onClick={() => confirmDialog('Shutdown')}>
|
||||
Shutdown
|
||||
</ActionButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Item>
|
||||
</Container>
|
||||
</Item>
|
||||
</Container>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,53 +1,55 @@
|
|||
import { fade } from '@material-ui/core/styles/colorManipulator'
|
||||
|
||||
import { fontSize4, offColor, comet } from 'src/styling/variables'
|
||||
import {
|
||||
detailsRowStyles,
|
||||
labelStyles
|
||||
} from 'src/pages/Transactions/Transactions.styles'
|
||||
import { spacer, comet, primaryColor, fontSize4 } from 'src/styling/variables'
|
||||
|
||||
export default {
|
||||
const machineDetailsStyles = {
|
||||
...detailsRowStyles,
|
||||
colDivider: {
|
||||
width: 1,
|
||||
margin: [[spacer * 2, spacer * 4]],
|
||||
backgroundColor: comet,
|
||||
border: 'none'
|
||||
},
|
||||
inlineChip: {
|
||||
marginInlineEnd: '0.25em'
|
||||
},
|
||||
stack: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row'
|
||||
},
|
||||
wrapper: {
|
||||
display: 'flex',
|
||||
marginTop: 24,
|
||||
marginBottom: 32,
|
||||
fontSize: fontSize4
|
||||
},
|
||||
column1: {
|
||||
width: 600
|
||||
},
|
||||
column2: {
|
||||
flex: 1
|
||||
},
|
||||
lastRow: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row'
|
||||
},
|
||||
row: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
marginBottom: 36
|
||||
},
|
||||
actionRow: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
marginLeft: -4
|
||||
list: {
|
||||
padding: 0,
|
||||
margin: 0,
|
||||
listStyle: 'none',
|
||||
'& > li': {
|
||||
height: spacer * 3,
|
||||
marginBottom: spacer * 1.5,
|
||||
'& > a, & > a:visited': {
|
||||
color: primaryColor,
|
||||
textDecoration: 'none'
|
||||
}
|
||||
}
|
||||
},
|
||||
action: {
|
||||
marginRight: 4,
|
||||
marginLeft: 4
|
||||
divider: {
|
||||
margin: '0 1rem'
|
||||
},
|
||||
dialog: {
|
||||
width: 434
|
||||
},
|
||||
label: {
|
||||
color: offColor,
|
||||
margin: [[0, 0, 6, 0]]
|
||||
},
|
||||
chips: {
|
||||
marginLeft: -2
|
||||
},
|
||||
status: {
|
||||
width: 248
|
||||
},
|
||||
machineModel: {
|
||||
width: 198
|
||||
mr: {
|
||||
marginRight: spacer
|
||||
},
|
||||
separator: {
|
||||
width: 1,
|
||||
|
|
@ -58,3 +60,5 @@ export default {
|
|||
background: fade(comet, 0.5)
|
||||
}
|
||||
}
|
||||
|
||||
export { labelStyles, machineDetailsStyles }
|
||||
|
|
|
|||
|
|
@ -5,13 +5,12 @@ import moment from 'moment'
|
|||
import * as R from 'ramda'
|
||||
import React from 'react'
|
||||
|
||||
import { MainStatus } from 'src/components/Status'
|
||||
import Title from 'src/components/Title'
|
||||
import DataTable from 'src/components/tables/DataTable'
|
||||
|
||||
import { MainStatus } from '../../components/Status'
|
||||
import Title from '../../components/Title'
|
||||
import { ReactComponent as WarningIcon } from '../../styling/icons/status/pumpkin.svg'
|
||||
import { ReactComponent as ErrorIcon } from '../../styling/icons/status/tomato.svg'
|
||||
import { mainStyles } from '../Transactions/Transactions.styles'
|
||||
import { mainStyles } from 'src/pages/Transactions/Transactions.styles'
|
||||
import { ReactComponent as WarningIcon } from 'src/styling/icons/status/pumpkin.svg'
|
||||
import { ReactComponent as ErrorIcon } from 'src/styling/icons/status/tomato.svg'
|
||||
|
||||
import MachineDetailsRow from './MachineDetailsCard'
|
||||
|
||||
|
|
@ -22,10 +21,13 @@ const GET_MACHINES = gql`
|
|||
deviceId
|
||||
lastPing
|
||||
pairedAt
|
||||
version
|
||||
paired
|
||||
cashbox
|
||||
cassette1
|
||||
cassette2
|
||||
version
|
||||
model
|
||||
statuses {
|
||||
label
|
||||
type
|
||||
|
|
@ -68,7 +70,7 @@ const MachineStatus = () => {
|
|||
width: 200,
|
||||
size: 'sm',
|
||||
textAlign: 'left',
|
||||
view: m => m.softwareVersion || 'unknown'
|
||||
view: m => m.version || 'unknown'
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="12px" height="12px" viewBox="0 0 12 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<svg width="12px" height="12px" viewBox="-0.493 -0.5 12.993 13" 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 -->
|
||||
<desc>Created with Sketch.</desc>
|
||||
<g id="icon/button/reboot/white" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="12px" height="12px" viewBox="0 0 12 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<svg width="12px" height="12px" viewBox="-0.493 -0.5 12.993 13" 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 -->
|
||||
<desc>Created with Sketch.</desc>
|
||||
<g id="icon/button/reboot/zodiac" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Loading…
Add table
Add a link
Reference in a new issue