parent
b625161b67
commit
a4f77f8e8e
2 changed files with 142 additions and 0 deletions
@ -0,0 +1,128 @@ |
||||
import { Box } from '@mui/material'; |
||||
import { FC, useMemo } from 'react'; |
||||
|
||||
import api from '../lib/api'; |
||||
import ButtonWithMenu from './ButtonWithMenu'; |
||||
import { MAP_TO_COLOUR } from './ContainedButton'; |
||||
import handleAPIError from '../lib/handleAPIError'; |
||||
import { BodyText } from './Text'; |
||||
import useConfirmDialog from '../hooks/useConfirmDialog'; |
||||
|
||||
const ServerMenu: FC<ServerMenuProps> = (props) => { |
||||
const { serverName, serverState, serverUuid } = props; |
||||
|
||||
const { |
||||
confirmDialog, |
||||
setConfirmDialogOpen, |
||||
setConfirmDialogProps, |
||||
finishConfirm, |
||||
} = useConfirmDialog(); |
||||
|
||||
const powerOptions = useMemo<MapToServerPowerOption>( |
||||
() => ({ |
||||
'force-off': { |
||||
colour: 'red', |
||||
description: ( |
||||
<> |
||||
This is equal to pulling the power cord, which may cause data loss |
||||
or system corruption. |
||||
</> |
||||
), |
||||
label: 'Force off', |
||||
path: `/command/stop-server/${serverUuid}?force=1`, |
||||
}, |
||||
'power-off': { |
||||
description: ( |
||||
<> |
||||
This is equal to pushing the power button. If the server |
||||
doesn't respond to the corresponding signals, you may have to |
||||
manually shut it down. |
||||
</> |
||||
), |
||||
label: 'Power off', |
||||
path: `/command/stop-server/${serverUuid}`, |
||||
}, |
||||
'power-on': { |
||||
description: <>This is equal to pushing the power button.</>, |
||||
label: 'Power on', |
||||
path: `/command/start-server/${serverUuid}`, |
||||
}, |
||||
}), |
||||
[serverUuid], |
||||
); |
||||
|
||||
return ( |
||||
<Box> |
||||
<ButtonWithMenu |
||||
getItemDisabled={(key) => { |
||||
const optionOn = key.includes('on'); |
||||
const serverRunning = serverState === 'running'; |
||||
|
||||
return serverRunning === optionOn; |
||||
}} |
||||
items={powerOptions} |
||||
onItemClick={(key, value) => { |
||||
const { colour, description, label, path } = value; |
||||
|
||||
const op = label.toLocaleLowerCase(); |
||||
|
||||
setConfirmDialogProps({ |
||||
actionProceedText: label, |
||||
content: <BodyText>{description}</BodyText>, |
||||
onProceedAppend: () => { |
||||
setConfirmDialogProps((previous) => ({ |
||||
...previous, |
||||
loading: true, |
||||
})); |
||||
|
||||
api |
||||
.put(path) |
||||
.then(() => { |
||||
finishConfirm('Success', { |
||||
children: ( |
||||
<> |
||||
Successfully registered {op} job on {serverName}. |
||||
</> |
||||
), |
||||
}); |
||||
}) |
||||
.catch((error) => { |
||||
const emsg = handleAPIError(error); |
||||
|
||||
emsg.children = ( |
||||
<> |
||||
Failed to register {op} job on {serverName}; CAUSE:{' '} |
||||
{emsg.children}. |
||||
</> |
||||
); |
||||
|
||||
finishConfirm('Error', emsg); |
||||
}); |
||||
}, |
||||
proceedColour: colour, |
||||
titleText: `${label} server ${serverName}?`, |
||||
}); |
||||
setConfirmDialogOpen(true); |
||||
}} |
||||
renderItem={(key, value) => { |
||||
const { colour, label } = value; |
||||
|
||||
let ccode: string | undefined; |
||||
|
||||
if (colour) { |
||||
ccode = MAP_TO_COLOUR[colour]; |
||||
} |
||||
|
||||
return ( |
||||
<BodyText inheritColour color={ccode}> |
||||
{label} |
||||
</BodyText> |
||||
); |
||||
}} |
||||
/> |
||||
{confirmDialog} |
||||
</Box> |
||||
); |
||||
}; |
||||
|
||||
export default ServerMenu; |
@ -0,0 +1,14 @@ |
||||
type ServerPowerOption = { |
||||
description: import('react').ReactNode; |
||||
label: string; |
||||
path: string; |
||||
colour?: Exclude<ContainedButtonBackground, 'normal'>; |
||||
}; |
||||
|
||||
type MapToServerPowerOption = Record<string, ServerPowerOption>; |
||||
|
||||
type ServerMenuProps = ButtonWithMenuProps & { |
||||
serverName: string; |
||||
serverState: string; |
||||
serverUuid: string; |
||||
}; |
Loading…
Reference in new issue