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:
Liordino Neto 2020-10-02 17:49:11 -03:00 committed by Josh Harvey
parent 79298d5dec
commit bbf98b4d52
5 changed files with 75 additions and 23 deletions

View file

@ -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)

View file

@ -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(),

View file

@ -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))
} }

View file

@ -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>

View file

@ -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>