diff --git a/striker-ui/components/ServerMenu.tsx b/striker-ui/components/ServerMenu.tsx new file mode 100644 index 00000000..daa09bd8 --- /dev/null +++ b/striker-ui/components/ServerMenu.tsx @@ -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 = (props) => { + const { serverName, serverState, serverUuid } = props; + + const { + confirmDialog, + setConfirmDialogOpen, + setConfirmDialogProps, + finishConfirm, + } = useConfirmDialog(); + + const powerOptions = useMemo( + () => ({ + '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 ( + + { + 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: {description}, + 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 ( + + {label} + + ); + }} + /> + {confirmDialog} + + ); +}; + +export default ServerMenu; diff --git a/striker-ui/types/ServerMenu.d.ts b/striker-ui/types/ServerMenu.d.ts new file mode 100644 index 00000000..b4f29a95 --- /dev/null +++ b/striker-ui/types/ServerMenu.d.ts @@ -0,0 +1,14 @@ +type ServerPowerOption = { + description: import('react').ReactNode; + label: string; + path: string; + colour?: Exclude; +}; + +type MapToServerPowerOption = Record; + +type ServerMenuProps = ButtonWithMenuProps & { + serverName: string; + serverState: string; + serverUuid: string; +};