feat: created the rename action on the machine status page
fix: added missing 'shutdown' action on the MachineActions enum of the gql schema style: set the Edit icon for the rename action style: fixed first and last action buttons spacing
This commit is contained in:
parent
79298d5dec
commit
bbf98b4d52
5 changed files with 75 additions and 23 deletions
|
|
@ -88,6 +88,11 @@ function getMachineName (machineId) {
|
||||||
.then(it => it.name)
|
.then(it => it.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renameMachine (rec) {
|
||||||
|
const sql = 'update devices set name=$1 where device_id=$2'
|
||||||
|
return db.none(sql, [rec.newName, rec.deviceId])
|
||||||
|
}
|
||||||
|
|
||||||
function resetCashOutBills (rec) {
|
function resetCashOutBills (rec) {
|
||||||
const sql = 'update devices set cassette1=$1, cassette2=$2 where device_id=$3'
|
const sql = 'update devices set cassette1=$1, cassette2=$2 where device_id=$3'
|
||||||
return db.none(sql, [rec.cassettes[0], rec.cassettes[1], rec.deviceId])
|
return db.none(sql, [rec.cassettes[0], rec.cassettes[1], rec.deviceId])
|
||||||
|
|
@ -112,6 +117,7 @@ function restartServices (rec) {
|
||||||
|
|
||||||
function setMachine (rec) {
|
function setMachine (rec) {
|
||||||
switch (rec.action) {
|
switch (rec.action) {
|
||||||
|
case 'rename': return renameMachine(rec)
|
||||||
case 'emptyCashInBills': return emptyCashInBills(rec)
|
case 'emptyCashInBills': return emptyCashInBills(rec)
|
||||||
case 'resetCashOutBills': return resetCashOutBills(rec)
|
case 'resetCashOutBills': return resetCashOutBills(rec)
|
||||||
case 'unpair': return unpair(rec)
|
case 'unpair': return unpair(rec)
|
||||||
|
|
|
||||||
|
|
@ -212,15 +212,17 @@ const typeDefs = gql`
|
||||||
}
|
}
|
||||||
|
|
||||||
enum MachineAction {
|
enum MachineAction {
|
||||||
|
rename
|
||||||
emptyCashInBills
|
emptyCashInBills
|
||||||
resetCashOutBills
|
resetCashOutBills
|
||||||
unpair
|
unpair
|
||||||
reboot
|
reboot
|
||||||
|
shutdown
|
||||||
restartServices
|
restartServices
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
machineAction(deviceId:ID!, action: MachineAction!, cassette1: Int, cassette2: Int): Machine
|
machineAction(deviceId:ID!, action: MachineAction!, cassette1: Int, cassette2: Int, newName: String): Machine
|
||||||
machineSupportLogs(deviceId: ID!): SupportLogsResponse
|
machineSupportLogs(deviceId: ID!): SupportLogsResponse
|
||||||
serverSupportLogs: SupportLogsResponse
|
serverSupportLogs: SupportLogsResponse
|
||||||
setCustomer(customerId: ID!, customerInput: CustomerInput): Customer
|
setCustomer(customerId: ID!, customerInput: CustomerInput): Customer
|
||||||
|
|
@ -262,7 +264,7 @@ const resolvers = {
|
||||||
accounts: () => settingsLoader.loadAccounts()
|
accounts: () => settingsLoader.loadAccounts()
|
||||||
},
|
},
|
||||||
Mutation: {
|
Mutation: {
|
||||||
machineAction: (...[, { deviceId, action, cassette1, cassette2 }]) => machineAction({ deviceId, action, cassette1, cassette2 }),
|
machineAction: (...[, { deviceId, action, cassette1, cassette2, newName }]) => machineAction({ deviceId, action, cassette1, cassette2, newName }),
|
||||||
machineSupportLogs: (...[, { deviceId }]) => supportLogs.insert(deviceId),
|
machineSupportLogs: (...[, { deviceId }]) => supportLogs.insert(deviceId),
|
||||||
createPairingTotem: (...[, { name }]) => pairing.totem(name),
|
createPairingTotem: (...[, { name }]) => pairing.totem(name),
|
||||||
serverSupportLogs: () => serverLogs.insert(),
|
serverSupportLogs: () => serverLogs.insert(),
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,13 @@ function getMachine (machineId) {
|
||||||
.then(machines => machines.find(({ deviceId }) => deviceId === machineId))
|
.then(machines => machines.find(({ deviceId }) => deviceId === machineId))
|
||||||
}
|
}
|
||||||
|
|
||||||
function machineAction ({ deviceId, action, cassette1, cassette2 }) {
|
function machineAction ({ deviceId, action, cassette1, cassette2, newName }) {
|
||||||
return getMachine(deviceId)
|
return getMachine(deviceId)
|
||||||
.then(machine => {
|
.then(machine => {
|
||||||
if (!machine) throw new UserInputError(`machine:${deviceId} not found`, { deviceId })
|
if (!machine) throw new UserInputError(`machine:${deviceId} not found`, { deviceId })
|
||||||
return machine
|
return machine
|
||||||
})
|
})
|
||||||
.then(machineLoader.setMachine({ deviceId, action, cassettes: [cassette1, cassette2] }))
|
.then(machineLoader.setMachine({ deviceId, action, cassettes: [cassette1, cassette2], newName }))
|
||||||
.then(getMachine(deviceId))
|
.then(getMachine(deviceId))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,12 +59,15 @@ export const ConfirmDialog = memo(
|
||||||
errorMessage = 'This action requires confirmation',
|
errorMessage = 'This action requires confirmation',
|
||||||
open,
|
open,
|
||||||
toBeConfirmed,
|
toBeConfirmed,
|
||||||
|
saveButtonAlwaysEnabled = false,
|
||||||
|
confirmationMessage = `Write '${toBeConfirmed}' to confirm this action`,
|
||||||
onConfirmed,
|
onConfirmed,
|
||||||
onDissmised,
|
onDissmised,
|
||||||
|
initialValue = '',
|
||||||
...props
|
...props
|
||||||
}) => {
|
}) => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const [value, setValue] = useState('')
|
const [value, setValue] = useState(initialValue)
|
||||||
const [error, setError] = useState(false)
|
const [error, setError] = useState(false)
|
||||||
const handleChange = event => setValue(event.target.value)
|
const handleChange = event => setValue(event.target.value)
|
||||||
|
|
||||||
|
|
@ -74,6 +77,9 @@ export const ConfirmDialog = memo(
|
||||||
onDissmised()
|
onDissmised()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isOnErrorState =
|
||||||
|
(!saveButtonAlwaysEnabled && toBeConfirmed !== value) || value === ''
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={open} aria-labelledby="form-dialog-title" {...props}>
|
<Dialog open={open} aria-labelledby="form-dialog-title" {...props}>
|
||||||
<DialogTitle id="customized-dialog-title" onClose={innerOnClose}>
|
<DialogTitle id="customized-dialog-title" onClose={innerOnClose}>
|
||||||
|
|
@ -93,7 +99,7 @@ export const ConfirmDialog = memo(
|
||||||
)}
|
)}
|
||||||
<DialogContent className={classes.dialogContent}>
|
<DialogContent className={classes.dialogContent}>
|
||||||
<TextInput
|
<TextInput
|
||||||
label={`Write '${toBeConfirmed}' to confirm this action`}
|
label={confirmationMessage}
|
||||||
name="confirm-input"
|
name="confirm-input"
|
||||||
autoFocus
|
autoFocus
|
||||||
id="confirm-input"
|
id="confirm-input"
|
||||||
|
|
@ -105,14 +111,14 @@ export const ConfirmDialog = memo(
|
||||||
error={error}
|
error={error}
|
||||||
InputLabelProps={{ shrink: true }}
|
InputLabelProps={{ shrink: true }}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
onBlur={() => setError(toBeConfirmed !== value)}
|
onBlur={() => setError(isOnErrorState)}
|
||||||
/>
|
/>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions className={classes.dialogActions}>
|
<DialogActions className={classes.dialogActions}>
|
||||||
<Button
|
<Button
|
||||||
color="green"
|
color="green"
|
||||||
disabled={toBeConfirmed !== value}
|
disabled={isOnErrorState}
|
||||||
onClick={onConfirmed}>
|
onClick={() => onConfirmed(value)}>
|
||||||
Confirm
|
Confirm
|
||||||
</Button>
|
</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ import React, { useState } from 'react'
|
||||||
import { ConfirmDialog } from 'src/components/ConfirmDialog'
|
import { ConfirmDialog } from 'src/components/ConfirmDialog'
|
||||||
import { Status } from 'src/components/Status'
|
import { Status } from 'src/components/Status'
|
||||||
import ActionButton from 'src/components/buttons/ActionButton'
|
import ActionButton from 'src/components/buttons/ActionButton'
|
||||||
|
import { ReactComponent as EditReversedIcon } from 'src/styling/icons/button/edit/white.svg'
|
||||||
|
import { ReactComponent as EditIcon } from 'src/styling/icons/button/edit/zodiac.svg'
|
||||||
import { ReactComponent as LinkIcon } from 'src/styling/icons/button/link/zodiac.svg'
|
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 RebootReversedIcon } from 'src/styling/icons/button/reboot/white.svg'
|
||||||
import { ReactComponent as RebootIcon } from 'src/styling/icons/button/reboot/zodiac.svg'
|
import { ReactComponent as RebootIcon } from 'src/styling/icons/button/reboot/zodiac.svg'
|
||||||
|
|
@ -19,8 +21,12 @@ import { ReactComponent as UnpairIcon } from 'src/styling/icons/button/unpair/zo
|
||||||
import { labelStyles, machineDetailsStyles } from './MachineDetailsCard.styles'
|
import { labelStyles, machineDetailsStyles } from './MachineDetailsCard.styles'
|
||||||
|
|
||||||
const MACHINE_ACTION = gql`
|
const MACHINE_ACTION = gql`
|
||||||
mutation MachineAction($deviceId: ID!, $action: MachineAction!) {
|
mutation MachineAction(
|
||||||
machineAction(deviceId: $deviceId, action: $action) {
|
$deviceId: ID!
|
||||||
|
$action: MachineAction!
|
||||||
|
$newName: String
|
||||||
|
) {
|
||||||
|
machineAction(deviceId: $deviceId, action: $action, newName: $newName) {
|
||||||
deviceId
|
deviceId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -63,11 +69,16 @@ const Item = ({ children, ...props }) => (
|
||||||
|
|
||||||
const MachineDetailsRow = ({ it: machine, onActionSuccess }) => {
|
const MachineDetailsRow = ({ it: machine, onActionSuccess }) => {
|
||||||
const [action, setAction] = useState('')
|
const [action, setAction] = useState('')
|
||||||
const [dialogOpen, setOpen] = useState(false)
|
const [renameActionDialogOpen, setRenameActionDialogOpen] = useState(false)
|
||||||
|
const [confirmActionDialogOpen, setConfirmActionDialogOpen] = useState(false)
|
||||||
const [errorMessage, setErrorMessage] = useState(null)
|
const [errorMessage, setErrorMessage] = useState(null)
|
||||||
const classes = useMDStyles()
|
const classes = useMDStyles()
|
||||||
|
|
||||||
const confirmDialog = action => setAction(action) || setOpen(true)
|
const confirmActionDialog = action =>
|
||||||
|
setAction(action) || setConfirmActionDialogOpen(true)
|
||||||
|
|
||||||
|
const renameActionDialog = () =>
|
||||||
|
setAction('Rename') || setRenameActionDialogOpen(true)
|
||||||
|
|
||||||
const [machineAction, { loading }] = useMutation(MACHINE_ACTION, {
|
const [machineAction, { loading }] = useMutation(MACHINE_ACTION, {
|
||||||
onError: ({ message }) => {
|
onError: ({ message }) => {
|
||||||
|
|
@ -77,7 +88,7 @@ const MachineDetailsRow = ({ it: machine, onActionSuccess }) => {
|
||||||
onCompleted: () => {
|
onCompleted: () => {
|
||||||
// TODO: custom onActionSuccess needs to be passed down from the machinestatus table
|
// TODO: custom onActionSuccess needs to be passed down from the machinestatus table
|
||||||
onActionSuccess ? onActionSuccess() : window.location.reload()
|
onActionSuccess ? onActionSuccess() : window.location.reload()
|
||||||
setOpen(false)
|
setConfirmActionDialogOpen(false)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -121,7 +132,29 @@ const MachineDetailsRow = ({ it: machine, onActionSuccess }) => {
|
||||||
className={classes.separator}
|
className={classes.separator}
|
||||||
/>
|
/>
|
||||||
<ConfirmDialog
|
<ConfirmDialog
|
||||||
open={dialogOpen}
|
open={renameActionDialogOpen}
|
||||||
|
title={`Rename this machine?`}
|
||||||
|
initialValue={machine.name}
|
||||||
|
errorMessage={errorMessage}
|
||||||
|
confirmationMessage={`Write the new name for this machine`}
|
||||||
|
saveButtonAlwaysEnabled={true}
|
||||||
|
onConfirmed={value => {
|
||||||
|
setErrorMessage(null)
|
||||||
|
machineAction({
|
||||||
|
variables: {
|
||||||
|
deviceId: machine.deviceId,
|
||||||
|
action: `${action}`.toLowerCase(),
|
||||||
|
newName: value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
onDissmised={() => {
|
||||||
|
setRenameActionDialogOpen(false)
|
||||||
|
setErrorMessage(null)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ConfirmDialog
|
||||||
|
open={confirmActionDialogOpen}
|
||||||
title={`${action} this machine?`}
|
title={`${action} this machine?`}
|
||||||
errorMessage={errorMessage}
|
errorMessage={errorMessage}
|
||||||
toBeConfirmed={machine.name}
|
toBeConfirmed={machine.name}
|
||||||
|
|
@ -135,7 +168,7 @@ const MachineDetailsRow = ({ it: machine, onActionSuccess }) => {
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
onDissmised={() => {
|
onDissmised={() => {
|
||||||
setOpen(false)
|
setConfirmActionDialogOpen(false)
|
||||||
setErrorMessage(null)
|
setErrorMessage(null)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
@ -145,10 +178,6 @@ const MachineDetailsRow = ({ it: machine, onActionSuccess }) => {
|
||||||
<Label>Machine Model</Label>
|
<Label>Machine Model</Label>
|
||||||
<span>{machine.model}</span>
|
<span>{machine.model}</span>
|
||||||
</Item>
|
</Item>
|
||||||
{/* <Item>
|
|
||||||
<Label>Address</Label>
|
|
||||||
<span>{machine.machineLocation}</span>
|
|
||||||
</Item> */}
|
|
||||||
<Item xs={4}>
|
<Item xs={4}>
|
||||||
<Label>Paired at</Label>
|
<Label>Paired at</Label>
|
||||||
<span>
|
<span>
|
||||||
|
|
@ -160,13 +189,22 @@ const MachineDetailsRow = ({ it: machine, onActionSuccess }) => {
|
||||||
<Item>
|
<Item>
|
||||||
<Label>Actions</Label>
|
<Label>Actions</Label>
|
||||||
<div className={classes.stack}>
|
<div className={classes.stack}>
|
||||||
|
<ActionButton
|
||||||
|
className={classes.mr}
|
||||||
|
disabled={loading}
|
||||||
|
color="primary"
|
||||||
|
Icon={EditIcon}
|
||||||
|
InverseIcon={EditReversedIcon}
|
||||||
|
onClick={() => renameActionDialog()}>
|
||||||
|
Rename
|
||||||
|
</ActionButton>
|
||||||
<ActionButton
|
<ActionButton
|
||||||
color="primary"
|
color="primary"
|
||||||
className={classes.mr}
|
className={classes.mr}
|
||||||
Icon={UnpairIcon}
|
Icon={UnpairIcon}
|
||||||
InverseIcon={UnpairReversedIcon}
|
InverseIcon={UnpairReversedIcon}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
onClick={() => confirmDialog('Unpair')}>
|
onClick={() => confirmActionDialog('Unpair')}>
|
||||||
Unpair
|
Unpair
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
<ActionButton
|
<ActionButton
|
||||||
|
|
@ -175,7 +213,7 @@ const MachineDetailsRow = ({ it: machine, onActionSuccess }) => {
|
||||||
Icon={RebootIcon}
|
Icon={RebootIcon}
|
||||||
InverseIcon={RebootReversedIcon}
|
InverseIcon={RebootReversedIcon}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
onClick={() => confirmDialog('Reboot')}>
|
onClick={() => confirmActionDialog('Reboot')}>
|
||||||
Reboot
|
Reboot
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
<ActionButton
|
<ActionButton
|
||||||
|
|
@ -184,7 +222,7 @@ const MachineDetailsRow = ({ it: machine, onActionSuccess }) => {
|
||||||
color="primary"
|
color="primary"
|
||||||
Icon={ShutdownIcon}
|
Icon={ShutdownIcon}
|
||||||
InverseIcon={ShutdownReversedIcon}
|
InverseIcon={ShutdownReversedIcon}
|
||||||
onClick={() => confirmDialog('Shutdown')}>
|
onClick={() => confirmActionDialog('Shutdown')}>
|
||||||
Shutdown
|
Shutdown
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue