import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
|
import {
|
useTranslate,
|
ShowBase,
|
useDataProvider,
|
useNotify,
|
useRecordContext,
|
useRedirect,
|
useRefresh,
|
} from 'react-admin';
|
import {
|
Box,
|
Button,
|
Chip,
|
Dialog,
|
DialogContent,
|
Divider,
|
Stack,
|
Typography,
|
Avatar,
|
useTheme,
|
TableContainer,
|
Table,
|
TableBody,
|
TableCell,
|
TableHead,
|
TableRow,
|
Paper,
|
Toolbar,
|
Tooltip,
|
Checkbox,
|
IconButton,
|
} from '@mui/material';
|
import { alpha } from '@mui/material/styles';
|
import { Link } from 'react-router-dom';
|
import DialogCloseButton from "../components/DialogCloseButton";
|
import { format } from 'date-fns';
|
import ArrowBackIosNewIcon from '@mui/icons-material/ArrowBackIosNew';
|
import request from '@/utils/request';
|
|
const MissionResend = ({ open, id }) => {
|
const redirect = useRedirect();
|
const handleClose = () => {
|
redirect('list', 'mission');
|
};
|
|
return (
|
<Dialog
|
open={open}
|
onClose={handleClose}
|
fullWidth
|
maxWidth="md"
|
sx={{
|
'& .MuiDialog-container': {
|
alignItems: 'flex-start',
|
},
|
}}
|
>
|
<DialogContent sx={{ padding: 0 }}>
|
{!!id ? (
|
<ShowBase id={id}>
|
<MissionResendContent handleClose={handleClose} />
|
</ShowBase>
|
) : null}
|
</DialogContent>
|
</Dialog>
|
)
|
}
|
|
const MissionResendContent = ({ handleClose }) => {
|
const theme = useTheme();
|
const record = useRecordContext();
|
const translate = useTranslate();
|
if (!record) return null;
|
|
return (
|
<>
|
<DialogCloseButton
|
onClose={handleClose}
|
top={12}
|
/>
|
<Stack gap={1}>
|
<Box display="flex" p={2}>
|
<Box flex="1">
|
<Stack
|
direction="row"
|
justifyContent="space-between"
|
mb={4}
|
>
|
<Stack direction="row" alignItems="center" gap={2}>
|
<Avatar
|
sx={{
|
width: 30,
|
height: 30,
|
bgcolor: theme.palette.primary.main,
|
}}
|
>
|
{record.agv}
|
</Avatar>
|
<Typography variant="h5">
|
{record.groupNo}
|
</Typography>
|
</Stack>
|
<Stack
|
gap={1}
|
direction="row"
|
pr={6}
|
>
|
<Button
|
component={Link}
|
to={`/mission/${record.id}/show`}
|
size="small"
|
startIcon={<ArrowBackIosNewIcon />}
|
>
|
{translate('page.mission.backToMission')}
|
</Button>
|
</Stack>
|
</Stack>
|
|
{!!record.codeList?.length && (
|
<Box m={2} sx={{ whiteSpace: 'pre-line' }}>
|
<Typography
|
color="textSecondary"
|
variant="caption"
|
>
|
{translate('table.field.mission.runPath')}
|
</Typography>
|
<Typography variant="body2" sx={{ whiteSpace: 'normal', overflow: 'hidden', display: 'flex', flexWrap: 'wrap' }}>
|
[ {record.codeList.map((code, index) => (
|
<span key={index} style={{
|
color: record.currCode === code ? theme.palette.primary.main : 'inherit',
|
}}>
|
{code}{index < record.codeList.length - 1 && ','}
|
</span>
|
))} ]
|
</Typography>
|
</Box>
|
)}
|
|
<ActionTable actionIds={record?.actionIds} currCode={record.currCode} handleClose={handleClose} />
|
</Box>
|
</Box>
|
</Stack>
|
</>
|
)
|
};
|
|
const headCells = [
|
{
|
id: 'actionType',
|
numeric: false,
|
disablePadding: true,
|
label: 'table.field.action.actionType',
|
},
|
{
|
id: 'code',
|
numeric: true,
|
disablePadding: false,
|
label: 'table.field.action.code',
|
},
|
{
|
id: 'taskId',
|
numeric: true,
|
disablePadding: false,
|
label: 'table.field.action.taskId',
|
},
|
{
|
id: 'val',
|
numeric: true,
|
disablePadding: false,
|
label: 'table.field.action.val',
|
},
|
{
|
id: 'params',
|
numeric: true,
|
disablePadding: false,
|
label: 'table.field.action.params',
|
},
|
];
|
|
const ActionTable = ({ actionIds, currCode, handleClose }) => {
|
const dataProvider = useDataProvider();
|
const translate = useTranslate();
|
const notify = useNotify();
|
const [actions, setActions] = useState([]);
|
const [selected, setSelected] = React.useState([]);
|
|
useEffect(() => {
|
if (actionIds?.length > 0) {
|
dataProvider.getMany('action', { ids: actionIds }).then(res => {
|
if (res.data?.length > 0) {
|
setActions(res.data);
|
|
// init selected
|
const indexOfCurrCode = res.data.findIndex(item => item.code === currCode);
|
if (indexOfCurrCode !== -1) {
|
const selectedIds = res.data.slice(indexOfCurrCode).map(item => item.id);
|
setSelected(selectedIds);
|
}
|
}
|
})
|
}
|
}, [actionIds])
|
|
const handleSelectAllClick = (event) => {
|
if (event.target.checked) {
|
const newSelected = actions.map((n) => n.id);
|
setSelected(newSelected);
|
return;
|
}
|
setSelected([]);
|
};
|
|
const handleClick = (event, id) => {
|
const selectedIndex = selected.indexOf(id);
|
let newSelected = [];
|
|
if (selectedIndex === -1) {
|
newSelected = newSelected.concat(selected, id);
|
} else if (selectedIndex === 0) {
|
newSelected = newSelected.concat(selected.slice(1));
|
} else if (selectedIndex === selected.length - 1) {
|
newSelected = newSelected.concat(selected.slice(0, -1));
|
} else if (selectedIndex > 0) {
|
newSelected = newSelected.concat(
|
selected.slice(0, selectedIndex),
|
selected.slice(selectedIndex + 1),
|
);
|
}
|
setSelected(newSelected);
|
};
|
|
const resendSubmit = () => {
|
if (!!selected?.length) {
|
request.post("/mission/resend", selected.map(id => ({ id }))).then(res => {
|
const { code, msg, data } = res.data;
|
if (code === 200) {
|
notify(msg || 'common.response.success', { type: 'success', messageArgs: { _: msg } });
|
handleClose();
|
} else {
|
notify(msg || 'common.response.fail', { type: 'error', messageArgs: { _: msg } });
|
}
|
}).catch(error => {
|
notify(error.message || 'common.response.fail', { type: 'error', messageArgs: { _: error.message } });
|
})
|
}
|
}
|
|
return (
|
<>
|
<Box sx={{ width: '100%' }}>
|
<Paper sx={{
|
width: '100%',
|
mb: 2,
|
}}>
|
<Toolbar
|
sx={[
|
{
|
pl: { sm: 2 },
|
pr: { xs: 1, sm: 1 },
|
minHeight: '52.5px !important',
|
},
|
selected.length > 0 && {
|
bgcolor: (theme) =>
|
alpha(theme.palette.primary.main, theme.palette.action.activatedOpacity),
|
},
|
]}
|
>
|
{selected.length > 0 ? (
|
<Typography
|
sx={{ flex: '1 1 100%' }}
|
color="inherit"
|
variant="subtitle1"
|
component="div"
|
>
|
{selected.length} {translate('common.action.selected')}
|
</Typography>
|
) : (
|
<Typography
|
sx={{ flex: '1 1 100%' }}
|
variant="subtitle1"
|
id="tableTitle"
|
component="div"
|
>
|
{translate('table.field.mission.actions')}
|
</Typography>
|
)}
|
{selected.length > 0 && (
|
<Tooltip title="Resend">
|
<Button
|
onClick={resendSubmit}
|
>
|
{translate('ra.action.confirm')}
|
</Button>
|
</Tooltip>
|
)}
|
</Toolbar>
|
<TableContainer>
|
<Table
|
sx={{ minWidth: 750 }}
|
aria-labelledby="tableTitle"
|
// size={dense ? 'small' : 'medium'}
|
size="small"
|
>
|
<TableHead>
|
<TableRow>
|
<TableCell padding="checkbox">
|
<Checkbox
|
color="primary"
|
indeterminate={selected.length > 0 && selected.length < actions.length}
|
checked={actions.length > 0 && selected.length === actions.length}
|
onChange={handleSelectAllClick}
|
inputProps={{
|
'aria-label': 'select all desserts',
|
}}
|
/>
|
</TableCell>
|
{headCells.map((headCell) => (
|
<TableCell
|
key={headCell.id}
|
align={headCell.numeric ? 'right' : 'left'}
|
padding={headCell.disablePadding ? 'none' : 'normal'}
|
>
|
{translate(headCell.label)}
|
</TableCell>
|
))}
|
</TableRow>
|
</TableHead>
|
<TableBody>
|
{actions?.map((row, index) => {
|
const isItemSelected = selected.includes(row.id);
|
const labelId = `action-table-checkbox-${index}`;
|
|
return (
|
<TableRow
|
hover
|
onClick={(event) => handleClick(event, row.id)}
|
role="checkbox"
|
aria-checked={isItemSelected}
|
tabIndex={-1}
|
key={row.id}
|
selected={isItemSelected}
|
sx={{ cursor: 'pointer' }}
|
>
|
<TableCell padding="checkbox">
|
<Checkbox
|
color="primary"
|
checked={isItemSelected}
|
inputProps={{
|
'aria-labelledby': labelId,
|
}}
|
/>
|
</TableCell>
|
<TableCell
|
component="th"
|
id={labelId}
|
scope="row"
|
padding="none"
|
>
|
[ {row.priority} ]
|
|
{row.actionType$}
|
</TableCell>
|
<TableCell align="right">{row.code}</TableCell>
|
<TableCell align="right">{row.taskId$}</TableCell>
|
<TableCell align="right">{row.val}</TableCell>
|
<TableCell align="right">{row.params}</TableCell>
|
</TableRow>
|
);
|
})}
|
</TableBody>
|
</Table>
|
</TableContainer>
|
</Paper>
|
</Box>
|
</>
|
)
|
}
|
|
export default MissionResend;
|