Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hammer/frontend changes #856

Merged
merged 15 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 12 additions & 70 deletions packages/dashboard/src/components/delivery-alert-store.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { base } from 'react-components';
import { AppControllerContext } from './app-contexts';
import { RmfAppContext } from './rmf-app';
import { TaskInspector } from './tasks/task-inspector';
import { TaskCancelButton } from './tasks/task-cancellation';

const useStyles = makeStyles((theme: Theme) =>
createStyles({
Expand Down Expand Up @@ -58,7 +59,6 @@ const DeliveryWarningDialog = React.memo((props: DeliveryWarningDialogProps) =>
const [actionTaken, setActionTaken] = React.useState(!onOverride && !onResume);
const [newTaskState, setNewTaskState] = React.useState<TaskState | null>(null);
const [openTaskInspector, setOpenTaskInspector] = React.useState(false);
const [cancelling, setCancelling] = React.useState(false);
const appController = React.useContext(AppControllerContext);
const rmf = React.useContext(RmfAppContext);
const isScreenHeightLessThan800 = useMediaQuery('(max-height:800px)');
Expand All @@ -81,38 +81,11 @@ const DeliveryWarningDialog = React.memo((props: DeliveryWarningDialogProps) =>
}
const sub = rmf.getTaskStateObs(taskState.booking.id).subscribe((taskStateUpdate) => {
setNewTaskState(taskStateUpdate);
setCancelling((prev) => {
if (
prev &&
deliveryAlert.action === 'waiting' &&
taskStateUpdate.status &&
taskStateUpdate.status === 'canceled'
) {
setCancelling(false);
(async () => {
try {
await rmf.deliveryAlertsApi.updateDeliveryAlertActionDeliveryAlertsDeliveryAlertIdActionPost(
deliveryAlert.id,
'cancelled',
);
} catch (e) {
appController.showAlert(
'error',
`Failed to cancel delivery alert ${deliveryAlert.id}: ${(e as Error).message}`,
);
}
setActionTaken(true);
})();
}
return prev;
});

if (
deliveryAlert.action === 'waiting' &&
taskStateUpdate.status &&
taskStateUpdate.status === 'canceled'
) {
setCancelling(false);
(async () => {
try {
await rmf.deliveryAlertsApi.updateDeliveryAlertActionDeliveryAlertsDeliveryAlertIdActionPost(
Expand All @@ -132,20 +105,6 @@ const DeliveryWarningDialog = React.memo((props: DeliveryWarningDialogProps) =>
return () => sub.unsubscribe();
}, [rmf, deliveryAlert, taskState, appController]);

const cancelTask = React.useCallback(
async (task_id: string) => {
if (!rmf) {
console.error('Tasks api not available for task cancellation.');
return;
}
await rmf.tasksApi.postCancelTaskTasksCancelTaskPost({
type: 'cancel_task_request',
task_id: task_id,
});
},
[rmf],
);

const titleUpdateText = (action: string) => {
switch (action) {
case 'override': {
Expand Down Expand Up @@ -191,7 +150,6 @@ const DeliveryWarningDialog = React.memo((props: DeliveryWarningDialogProps) =>
sx={{
'& .MuiFilledInput-root': {
fontSize: isScreenHeightLessThan800 ? '0.8rem' : '1.15',
height: isScreenHeightLessThan800 ? '2.2rem' : '3rem',
},
}}
InputLabelProps={{ style: { fontSize: isScreenHeightLessThan800 ? 16 : 20 } }}
Expand All @@ -212,7 +170,6 @@ const DeliveryWarningDialog = React.memo((props: DeliveryWarningDialogProps) =>
sx={{
'& .MuiFilledInput-root': {
fontSize: isScreenHeightLessThan800 ? '0.8rem' : '1.15',
height: isScreenHeightLessThan800 ? '2.2rem' : '3rem',
},
}}
InputLabelProps={{ style: { fontSize: isScreenHeightLessThan800 ? 16 : 20 } }}
Expand All @@ -229,7 +186,6 @@ const DeliveryWarningDialog = React.memo((props: DeliveryWarningDialogProps) =>
sx={{
'& .MuiFilledInput-root': {
fontSize: isScreenHeightLessThan800 ? '0.8rem' : '1.15',
height: isScreenHeightLessThan800 ? '2.2rem' : '3rem',
},
}}
InputLabelProps={{ style: { fontSize: isScreenHeightLessThan800 ? 16 : 20 } }}
Expand Down Expand Up @@ -258,34 +214,18 @@ const DeliveryWarningDialog = React.memo((props: DeliveryWarningDialogProps) =>
</Button>
) : newTaskState ? (
<Tooltip title="Cancels the current delivery task.">
<Button
<TaskCancelButton
taskId={newTaskState.booking.id}
size="small"
variant="contained"
disabled={actionTaken || cancelling}
color="secondary"
disabled={actionTaken}
buttonText={'Cancel Delivery'}
sx={{
fontSize: isScreenHeightLessThan800 ? '0.8rem' : '1rem',
padding: isScreenHeightLessThan800 ? '4px 8px' : '6px 12px',
}}
onClick={() => {
setCancelling(true);
if (newTaskState) {
const task_id = newTaskState.booking.id;
try {
cancelTask(task_id);
appController.showAlert('success', `Successfully cancelled task ${task_id}`);
} catch (e) {
appController.showAlert(
'error',
`Failed to cancel task ${task_id}: ${(e as Error).message}`,
);
setCancelling(false);
}
}
}}
autoFocus
>
{cancelling ? 'Cancelling...' : 'Cancel Delivery'}
</Button>
/>
</Tooltip>
) : (
<Button
Expand Down Expand Up @@ -400,7 +340,6 @@ const DeliveryErrorDialog = React.memo((props: DeliveryErrorDialogProps) => {
sx={{
'& .MuiFilledInput-root': {
fontSize: isScreenHeightLessThan800 ? '0.8rem' : '1.15',
height: isScreenHeightLessThan800 ? '2.2rem' : '3rem',
},
}}
InputLabelProps={{ style: { fontSize: isScreenHeightLessThan800 ? 16 : 20 } }}
Expand All @@ -417,7 +356,6 @@ const DeliveryErrorDialog = React.memo((props: DeliveryErrorDialogProps) => {
sx={{
'& .MuiFilledInput-root': {
fontSize: isScreenHeightLessThan800 ? '0.8rem' : '1.15',
height: isScreenHeightLessThan800 ? '2.2rem' : '3rem',
},
}}
InputLabelProps={{ style: { fontSize: isScreenHeightLessThan800 ? 16 : 20 } }}
Expand All @@ -434,7 +372,6 @@ const DeliveryErrorDialog = React.memo((props: DeliveryErrorDialogProps) => {
sx={{
'& .MuiFilledInput-root': {
fontSize: isScreenHeightLessThan800 ? '0.8rem' : '1.15',
height: isScreenHeightLessThan800 ? '2.2rem' : '3rem',
},
}}
InputLabelProps={{ style: { fontSize: isScreenHeightLessThan800 ? 16 : 20 } }}
Expand Down Expand Up @@ -601,6 +538,11 @@ export const DeliveryAlertStore = React.memo(() => {
return;
}
const sub = rmf.deliveryAlertObsStore.subscribe(async (deliveryAlert) => {
// DEBUG
console.log(
`Got a delivery alert [${deliveryAlert.id}] with action [${deliveryAlert.action}]`,
);

let state: TaskState | undefined = undefined;
if (deliveryAlert.task_id) {
try {
Expand Down
21 changes: 19 additions & 2 deletions packages/dashboard/src/components/robots/robot-summary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
TextField,
Theme,
Typography,
useMediaQuery,
} from '@mui/material';
import { makeStyles, createStyles } from '@mui/styles';
import React from 'react';
Expand Down Expand Up @@ -108,6 +109,7 @@ const showBatteryIcon = (robot: RobotState, robotBattery: number) => {
};

export const RobotSummary = React.memo(({ onClose, robot }: RobotSummaryProps) => {
const isScreenHeightLessThan800 = useMediaQuery('(max-height:800px)');
const classes = useStyles();
const rmf = React.useContext(RmfAppContext);

Expand Down Expand Up @@ -228,6 +230,11 @@ export const RobotSummary = React.memo(({ onClose, robot }: RobotSummaryProps) =
maxRows={4}
margin="dense"
value={message.value}
sx={{
'& .MuiFilledInput-root': {
fontSize: isScreenHeightLessThan800 ? '0.8rem' : '1.15',
},
}}
/>
</div>
))}
Expand All @@ -249,12 +256,17 @@ export const RobotSummary = React.memo(({ onClose, robot }: RobotSummaryProps) =
onClose();
}}
fullWidth
maxWidth="sm"
maxWidth={isScreenHeightLessThan800 ? 'xs' : 'sm'}
>
<Grid container mb={1} alignItems="center" spacing={1}>
<Grid item xs={2}></Grid>
<Grid item xs={8}>
<DialogTitle align="center">Robot summary: {robotState?.name}</DialogTitle>
<DialogTitle
align="center"
sx={{ fontSize: isScreenHeightLessThan800 ? '1.2rem' : '1.5rem' }}
>
Robot summary: {robotState?.name}
</DialogTitle>
</Grid>
<Grid item xs={2}>
<Grid container justifyContent="flex-end">
Expand Down Expand Up @@ -284,6 +296,11 @@ export const RobotSummary = React.memo(({ onClose, robot }: RobotSummaryProps) =
taskId={taskState ? taskState.booking.id : null}
size="small"
variant="contained"
color="secondary"
sx={{
fontSize: isScreenHeightLessThan800 ? '0.8rem' : '1rem',
padding: isScreenHeightLessThan800 ? '4px 8px' : '6px 12px',
}}
/>
</DialogActions>
{openTaskDetailsLogs && taskState && (
Expand Down
75 changes: 51 additions & 24 deletions packages/dashboard/src/components/tasks/task-cancellation.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Button, ButtonProps, Theme, Tooltip } from '@mui/material';
import { Button, ButtonProps, Theme, Tooltip, Typography } from '@mui/material';
import { TaskState } from 'api-client';
import React from 'react';
import { AppControllerContext } from '../app-contexts';
Expand All @@ -7,6 +7,7 @@ import { RmfAppContext } from '../rmf-app';
import { UserProfileContext } from 'rmf-auth';
import { Enforcer } from '../permissions';
import { makeStyles, createStyles } from '@mui/styles';
import { ConfirmationDialog } from 'react-components';

const useStyles = makeStyles((theme: Theme) =>
createStyles({
Expand All @@ -20,15 +21,21 @@ const useStyles = makeStyles((theme: Theme) =>

export interface TaskCancelButtonProp extends ButtonProps {
taskId: string | null;
buttonText?: string;
}

export function TaskCancelButton({ taskId, ...otherProps }: TaskCancelButtonProp): JSX.Element {
export function TaskCancelButton({
taskId,
buttonText,
...otherProps
}: TaskCancelButtonProp): JSX.Element {
const classes = useStyles();
const rmf = React.useContext(RmfAppContext);
const appController = React.useContext(AppControllerContext);
const profile = React.useContext(UserProfileContext);

const [taskState, setTaskState] = React.useState<TaskState | null>(null);
const [openConfirmDialog, setOpenConfirmDialog] = React.useState(false);

React.useEffect(() => {
if (!rmf || !taskId) {
Expand Down Expand Up @@ -65,29 +72,49 @@ export function TaskCancelButton({ taskId, ...otherProps }: TaskCancelButtonProp
} catch (e) {
appController.showAlert('error', `Failed to cancel task: ${(e as Error).message}`);
}
setOpenConfirmDialog(false);
}, [appController, taskState, rmf]);

return taskCancellable && userCanCancelTask ? (
<Button onClick={handleCancelTaskClick} autoFocus {...otherProps}>
Cancel Task
</Button>
) : taskCancellable && !userCanCancelTask ? (
<Tooltip title="You don't have permission to cancel tasks.">
<Button disabled className={classes['enableHover']} {...otherProps}>
Cancel Task
</Button>
</Tooltip>
) : (
<Tooltip
title={
taskState && taskState.status
? `${capitalizeFirstLetter(taskState.status)} task cannot be cancelled.`
: `Task cannot be cancelled.`
}
>
<Button disabled className={classes['enableHover']} {...otherProps}>
Cancel Task
</Button>
</Tooltip>
return (
<>
{taskCancellable && userCanCancelTask ? (
<Button onClick={() => setOpenConfirmDialog(true)} autoFocus {...otherProps}>
{buttonText ?? 'Cancel Task'}
</Button>
) : taskCancellable && !userCanCancelTask ? (
<Tooltip title="You don't have permission to cancel tasks.">
<Button disabled className={classes['enableHover']} {...otherProps}>
{buttonText ?? 'Cancel Task'}
</Button>
</Tooltip>
) : (
<Tooltip
title={
taskState && taskState.status
? `${capitalizeFirstLetter(taskState.status)} task cannot be cancelled.`
: `Task cannot be cancelled.`
}
>
<Button disabled className={classes['enableHover']} {...otherProps}>
{buttonText ?? 'Cancel Task'}
</Button>
</Tooltip>
)}
{openConfirmDialog && (
<ConfirmationDialog
confirmText="Confirm"
cancelText="Cancel"
open={openConfirmDialog}
title={`Cancel task [${taskState?.booking.id || 'n/a'}]`}
submitting={undefined}
onClose={() => {
setOpenConfirmDialog(false);
}}
onSubmit={handleCancelTaskClick}
>
<Typography>Are you sure you would like to cancel task?</Typography>
</ConfirmationDialog>
)}
</>
);
}
Loading