forked from CITKParus/P8-Panels
488 lines
18 KiB
JavaScript
488 lines
18 KiB
JavaScript
/*
|
||
Парус 8 - Панели мониторинга - УДП - Доски задач
|
||
Компонент панели: Диалог формы события
|
||
*/
|
||
|
||
//---------------------
|
||
//Подключение библиотек
|
||
//---------------------
|
||
|
||
import React, { useState } from "react"; //Классы React
|
||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||
import { Box, Typography, TextField, Dialog, DialogContent, DialogActions, Button, Tabs, Tab, InputAdornment, IconButton, Icon } from "@mui/material"; //Интерфейсные компоненты
|
||
import { useClientEvent } from "../hooks"; //Вспомогательные хуки
|
||
|
||
//---------
|
||
//Константы
|
||
//---------
|
||
|
||
//Стили
|
||
const STYLES = {
|
||
CONTAINER: { margin: "5px 0px", textAlign: "center" },
|
||
DIALOG_CONTENT: {
|
||
paddingBottom: "0px",
|
||
maxHeight: "740px",
|
||
minHeight: "740px",
|
||
"&::-webkit-scrollbar": {
|
||
width: "8px"
|
||
},
|
||
"&::-webkit-scrollbar-track": {
|
||
borderRadius: "8px",
|
||
backgroundColor: "#EBEBEB"
|
||
},
|
||
"&::-webkit-scrollbar-thumb": {
|
||
borderRadius: "8px",
|
||
backgroundColor: "#b4b4b4"
|
||
},
|
||
"&::-webkit-scrollbar-thumb:hover": {
|
||
backgroundColor: "#808080"
|
||
}
|
||
},
|
||
BOX_WITH_LEGEND: { border: "1px solid #939393" },
|
||
BOX_SINGLE_COLUMN: { display: "flex", flexDirection: "column", gap: "10px" },
|
||
BOX_FEW_COLUMNS: { display: "flex", flexWrap: "wrap", justifyContent: "space-between" },
|
||
BOX_LEFT_ALIGN: { display: "flex", justifyContent: "flex-start" },
|
||
LEGEND: { textAlign: "left" },
|
||
TEXT_FIELD: (widthVal, greyDisabled = false) => ({
|
||
margin: "4px",
|
||
...(widthVal ? { width: widthVal } : {}),
|
||
...(greyDisabled
|
||
? {
|
||
"& .MuiInputBase-input.Mui-disabled": {
|
||
WebkitTextFillColor: "rgba(0, 0, 0, 0.87)"
|
||
},
|
||
"& .MuiInputLabel-root.Mui-disabled": {
|
||
WebkitTextFillColor: "rgba(0, 0, 0, 0.6)"
|
||
}
|
||
}
|
||
: {})
|
||
})
|
||
};
|
||
|
||
//------------------------------------
|
||
//Вспомогательные функции и компоненты
|
||
//------------------------------------
|
||
|
||
//Свойства вкладки
|
||
function a11yProps(index) {
|
||
return {
|
||
id: `simple-tab-${index}`,
|
||
"aria-controls": `simple-tabpanel-${index}`
|
||
};
|
||
}
|
||
|
||
//Формирование кнопки для открытия раздела
|
||
const getInputProps = (onClick, disabled = false, icon = "list") => {
|
||
return {
|
||
endAdornment: (
|
||
<InputAdornment position="end">
|
||
<IconButton disabled={disabled} aria-label={`select`} onClick={onClick} edge="end">
|
||
<Icon>{icon}</Icon>
|
||
</IconButton>
|
||
</InputAdornment>
|
||
)
|
||
};
|
||
};
|
||
|
||
//Вкладка информации
|
||
function CustomTabPanel(props) {
|
||
const { children, value, index, ...other } = props;
|
||
|
||
return (
|
||
<Box role="tabpanel" hidden={value !== index} id={`simple-tabpanel-${index}`} aria-labelledby={`simple-tab-${index}`} {...other}>
|
||
{value === index && <Box pt={1}>{children}</Box>}
|
||
</Box>
|
||
);
|
||
}
|
||
|
||
//Контроль свойств - Вкладка информации
|
||
CustomTabPanel.propTypes = {
|
||
children: PropTypes.node,
|
||
index: PropTypes.number.isRequired,
|
||
value: PropTypes.number.isRequired
|
||
};
|
||
|
||
//Вкладка основной информации
|
||
const MainEventInfoTab = ({
|
||
task,
|
||
handleFieldEdit,
|
||
handleTypeOpen,
|
||
handleStatusOpen,
|
||
handleClientClientsOpen,
|
||
handleClientPersonOpen,
|
||
handleCrnOpen,
|
||
handleEventNextNumbGet
|
||
}) => {
|
||
return (
|
||
<Box>
|
||
<Box sx={STYLES.BOX_WITH_LEGEND} component="fieldset">
|
||
<legend style={STYLES.LEGEND}>Событие</legend>
|
||
<Box sx={STYLES.BOX_FEW_COLUMNS}>
|
||
<TextField
|
||
sx={STYLES.TEXT_FIELD()}
|
||
id="scrn"
|
||
label="Каталог"
|
||
variant="outlined"
|
||
fullWidth
|
||
value={task.scrn}
|
||
onChange={handleFieldEdit}
|
||
InputProps={getInputProps(handleCrnOpen)}
|
||
required
|
||
disabled={task.isUpdate}
|
||
></TextField>
|
||
<TextField
|
||
sx={STYLES.TEXT_FIELD("225px")}
|
||
id="sprefix"
|
||
label="Префикс"
|
||
variant="outlined"
|
||
value={task.sprefix}
|
||
onChange={handleFieldEdit}
|
||
required
|
||
disabled={task.isUpdate}
|
||
></TextField>
|
||
<TextField
|
||
sx={STYLES.TEXT_FIELD("225px")}
|
||
id="snumber"
|
||
label="Номер"
|
||
variant="outlined"
|
||
value={task.snumber}
|
||
onChange={handleFieldEdit}
|
||
required
|
||
disabled={task.isUpdate}
|
||
InputProps={getInputProps(handleEventNextNumbGet, !task.sprefix || task.isUpdate, "refresh")}
|
||
></TextField>
|
||
<TextField
|
||
sx={STYLES.TEXT_FIELD("225px", !task.isUpdate)}
|
||
id="stype"
|
||
label="Тип"
|
||
variant="outlined"
|
||
value={task.stype}
|
||
onChange={handleFieldEdit}
|
||
disabled
|
||
required
|
||
InputProps={getInputProps(handleTypeOpen, task.isUpdate)}
|
||
></TextField>
|
||
<TextField
|
||
sx={STYLES.TEXT_FIELD("225px", !task.isUpdate)}
|
||
id="sstatus"
|
||
label="Статус"
|
||
variant="outlined"
|
||
value={task.sstatus}
|
||
disabled
|
||
required
|
||
onChange={handleFieldEdit}
|
||
InputProps={getInputProps(handleStatusOpen, !task.stype || task.isUpdate)}
|
||
></TextField>
|
||
<TextField
|
||
sx={STYLES.TEXT_FIELD()}
|
||
fullWidth
|
||
id="sdescription"
|
||
label="Описание"
|
||
variant="outlined"
|
||
value={task.sdescription}
|
||
onChange={handleFieldEdit}
|
||
disabled={!task.stype}
|
||
required
|
||
multiline
|
||
minRows={7}
|
||
maxRows={7}
|
||
></TextField>
|
||
</Box>
|
||
</Box>
|
||
<Box sx={{ ...STYLES.BOX_WITH_LEGEND, ...STYLES.BOX_SINGLE_COLUMN }} component="fieldset">
|
||
<legend style={STYLES.LEGEND}>Клиент</legend>
|
||
<TextField
|
||
sx={STYLES.TEXT_FIELD()}
|
||
id="sclnt_clnclients"
|
||
label="Организация"
|
||
variant="outlined"
|
||
value={task.sclnt_clnclients}
|
||
onChange={handleFieldEdit}
|
||
disabled={!task.stype}
|
||
InputProps={getInputProps(handleClientClientsOpen, !task.stype)}
|
||
></TextField>
|
||
<TextField
|
||
sx={STYLES.TEXT_FIELD()}
|
||
id="sclnt_clnperson"
|
||
label="Сотрудник"
|
||
variant="outlined"
|
||
value={task.sclnt_clnperson}
|
||
onChange={handleFieldEdit}
|
||
disabled={!task.stype}
|
||
InputProps={getInputProps(() => handleClientPersonOpen(0), !task.stype)}
|
||
></TextField>
|
||
</Box>
|
||
</Box>
|
||
);
|
||
};
|
||
|
||
//Контроль свойств - Вкладка основной информации
|
||
MainEventInfoTab.propTypes = {
|
||
task: PropTypes.object.isRequired,
|
||
handleFieldEdit: PropTypes.func.isRequired,
|
||
handleTypeOpen: PropTypes.func.isRequired,
|
||
handleStatusOpen: PropTypes.func.isRequired,
|
||
handleClientClientsOpen: PropTypes.func.isRequired,
|
||
handleClientPersonOpen: PropTypes.func.isRequired,
|
||
handleCrnOpen: PropTypes.func.isRequired,
|
||
handleEventNextNumbGet: PropTypes.func.isRequired
|
||
};
|
||
|
||
//Вкладка информации об исполнителе
|
||
const ExecutorEventInfoTab = ({ task, handleFieldEdit, handleClientPersonOpen }) => {
|
||
return (
|
||
<Box>
|
||
<Box sx={{ ...STYLES.BOX_WITH_LEGEND, ...STYLES.BOX_LEFT_ALIGN }} component="fieldset">
|
||
<legend style={STYLES.LEGEND}>Планирование</legend>
|
||
<TextField
|
||
id="dstart_date"
|
||
label="Начало работ"
|
||
variant="outlined"
|
||
InputLabelProps={{ shrink: true }}
|
||
type="datetime-local"
|
||
value={task.dstart_date}
|
||
onChange={handleFieldEdit}
|
||
disabled={task.isUpdate}
|
||
></TextField>
|
||
</Box>
|
||
<Box sx={{ ...STYLES.BOX_WITH_LEGEND, ...STYLES.BOX_SINGLE_COLUMN }} component="fieldset">
|
||
<legend style={STYLES.LEGEND}>Инициатор</legend>
|
||
<TextField
|
||
id="sinit_clnperson"
|
||
label="Сотрудник"
|
||
variant="outlined"
|
||
value={task.sinit_clnperson}
|
||
onChange={handleFieldEdit}
|
||
disabled={task.isUpdate}
|
||
InputProps={getInputProps(() => handleClientPersonOpen(1), task.isUpdate)}
|
||
></TextField>
|
||
<TextField
|
||
id="sinit_user"
|
||
label="Пользователь"
|
||
variant="outlined"
|
||
value={task.sinit_user}
|
||
onChange={handleFieldEdit}
|
||
disabled
|
||
></TextField>
|
||
<TextField
|
||
id="sinit_reason"
|
||
label="Основание"
|
||
variant="outlined"
|
||
value={task.sinit_reason}
|
||
onChange={handleFieldEdit}
|
||
disabled={task.isUpdate}
|
||
></TextField>
|
||
</Box>
|
||
<Box sx={{ ...STYLES.BOX_WITH_LEGEND, ...STYLES.BOX_SINGLE_COLUMN }} component="fieldset">
|
||
<legend style={STYLES.LEGEND}>Направить</legend>
|
||
<TextField
|
||
id="sto_company"
|
||
label="Организация"
|
||
variant="outlined"
|
||
value={task.sto_company}
|
||
onChange={handleFieldEdit}
|
||
disabled
|
||
></TextField>
|
||
<TextField
|
||
id="sto_department"
|
||
label="Подразделение"
|
||
variant="outlined"
|
||
value={task.sto_department}
|
||
onChange={handleFieldEdit}
|
||
disabled
|
||
></TextField>
|
||
<TextField
|
||
id="sto_clnpost"
|
||
label="Должность"
|
||
variant="outlined"
|
||
value={task.sto_clnpost}
|
||
onChange={handleFieldEdit}
|
||
disabled
|
||
></TextField>
|
||
<TextField
|
||
id="sto_clnpsdep"
|
||
label="Штатная должность"
|
||
variant="outlined"
|
||
value={task.sto_clnpsdep}
|
||
onChange={handleFieldEdit}
|
||
disabled
|
||
></TextField>
|
||
<TextField
|
||
id="sto_clnperson"
|
||
label="Сотрудник"
|
||
variant="outlined"
|
||
value={task.sto_clnperson}
|
||
onChange={handleFieldEdit}
|
||
disabled
|
||
></TextField>
|
||
<TextField
|
||
id="sto_fcstaffgrp"
|
||
label="Нештатная должность"
|
||
variant="outlined"
|
||
value={task.sto_fcstaffgrp}
|
||
onChange={handleFieldEdit}
|
||
disabled
|
||
></TextField>
|
||
<TextField
|
||
id="sto_user"
|
||
label="Пользователь"
|
||
variant="outlined"
|
||
value={task.sto_user}
|
||
onChange={handleFieldEdit}
|
||
disabled
|
||
></TextField>
|
||
<TextField
|
||
id="sto_usergrp"
|
||
label="Группа пользователей"
|
||
variant="outlined"
|
||
value={task.sto_usergrp}
|
||
onChange={handleFieldEdit}
|
||
disabled
|
||
></TextField>
|
||
</Box>
|
||
</Box>
|
||
);
|
||
};
|
||
|
||
//Контроль свойств - Вкладка информации об исполнителе
|
||
ExecutorEventInfoTab.propTypes = {
|
||
task: PropTypes.object.isRequired,
|
||
handleFieldEdit: PropTypes.func.isRequired,
|
||
handleClientPersonOpen: PropTypes.func.isRequired
|
||
};
|
||
|
||
//-----------
|
||
//Тело модуля
|
||
//-----------
|
||
|
||
//Форма события
|
||
const TaskForm = ({
|
||
task,
|
||
setTask,
|
||
handleTypeOpen,
|
||
handleStatusOpen,
|
||
handleClientClientsOpen,
|
||
handleClientPersonOpen,
|
||
handleCrnOpen,
|
||
handleEventNextNumbGet
|
||
}) => {
|
||
//Состояние вкладки
|
||
const [value, setValue] = useState(0);
|
||
|
||
//При изменении вкладки
|
||
const handleChange = (event, newValue) => {
|
||
setValue(newValue);
|
||
};
|
||
|
||
//При изменении поля
|
||
const handleFieldEdit = e => {
|
||
setTask(pv => ({
|
||
...pv,
|
||
[e.target.id]: e.target.value,
|
||
//Связанные значения, если меняется одно, то необходимо обнулить другое
|
||
...(e.target.id === "sclnt_clnperson" ? { sclnt_clnclients: "" } : {}),
|
||
...(e.target.id === "sclnt_clnclients" ? { sclnt_clnperson: "" } : {})
|
||
}));
|
||
};
|
||
|
||
//Генерация содержимого
|
||
return (
|
||
<Box sx={STYLES.CONTAINER}>
|
||
<Typography pb={1} variant="h6">
|
||
{task.nrn ? "Исправление события" : "Добавление события"}
|
||
</Typography>
|
||
<Tabs value={value} onChange={handleChange} aria-label="tabs of values">
|
||
<Tab label="Событие" {...a11yProps(0)} />
|
||
<Tab label="Исполнитель" {...a11yProps(1)} />
|
||
</Tabs>
|
||
<CustomTabPanel value={value} index={0}>
|
||
<MainEventInfoTab
|
||
task={task}
|
||
handleFieldEdit={handleFieldEdit}
|
||
handleTypeOpen={handleTypeOpen}
|
||
handleStatusOpen={handleStatusOpen}
|
||
handleClientClientsOpen={handleClientClientsOpen}
|
||
handleClientPersonOpen={handleClientPersonOpen}
|
||
handleCrnOpen={handleCrnOpen}
|
||
handleEventNextNumbGet={handleEventNextNumbGet}
|
||
/>
|
||
</CustomTabPanel>
|
||
<CustomTabPanel value={value} index={1}>
|
||
<ExecutorEventInfoTab task={task} handleFieldEdit={handleFieldEdit} handleClientPersonOpen={handleClientPersonOpen} />
|
||
</CustomTabPanel>
|
||
</Box>
|
||
);
|
||
};
|
||
|
||
//Контроль свойств - Форма события
|
||
TaskForm.propTypes = {
|
||
task: PropTypes.object.isRequired,
|
||
setTask: PropTypes.func.isRequired,
|
||
handleTypeOpen: PropTypes.func.isRequired,
|
||
handleStatusOpen: PropTypes.func.isRequired,
|
||
handleClientClientsOpen: PropTypes.func.isRequired,
|
||
handleClientPersonOpen: PropTypes.func.isRequired,
|
||
handleCrnOpen: PropTypes.func.isRequired,
|
||
handleEventNextNumbGet: PropTypes.func.isRequired
|
||
};
|
||
|
||
//Диалог с формой события
|
||
const TaskFormDialog = ({ taskRn, onClose }) => {
|
||
//Собственное состояние
|
||
const [
|
||
task,
|
||
setTask,
|
||
insertEvent,
|
||
updateEvent,
|
||
handleTypeOpen,
|
||
handleStatusOpen,
|
||
handleClientClientsOpen,
|
||
handleClientPersonOpen,
|
||
handleCrnOpen,
|
||
handleEventNextNumbGet
|
||
] = useClientEvent(taskRn);
|
||
|
||
return (
|
||
<Dialog open onClose={onClose ? onClose : null} fullWidth>
|
||
<DialogContent sx={STYLES.DIALOG_CONTENT}>
|
||
<TaskForm
|
||
task={task}
|
||
setTask={setTask}
|
||
handleTypeOpen={handleTypeOpen}
|
||
handleStatusOpen={handleStatusOpen}
|
||
handleClientClientsOpen={handleClientClientsOpen}
|
||
handleClientPersonOpen={handleClientPersonOpen}
|
||
handleCrnOpen={handleCrnOpen}
|
||
handleEventNextNumbGet={handleEventNextNumbGet}
|
||
/>
|
||
</DialogContent>
|
||
{onClose ? (
|
||
<DialogActions>
|
||
{taskRn ? (
|
||
<Button onClick={() => updateEvent(onClose)} disabled={task.updateDisabled}>
|
||
Исправить
|
||
</Button>
|
||
) : (
|
||
<Button onClick={() => insertEvent(onClose)} disabled={task.insertDisabled}>
|
||
Добавить
|
||
</Button>
|
||
)}
|
||
<Button onClick={onClose}>Закрыть</Button>
|
||
</DialogActions>
|
||
) : null}
|
||
</Dialog>
|
||
);
|
||
};
|
||
|
||
//Контроль свойств - Диалог с формой события
|
||
TaskFormDialog.propTypes = {
|
||
taskRn: PropTypes.number,
|
||
onClose: PropTypes.func.isRequired
|
||
};
|
||
|
||
//----------------
|
||
//Интерфейс модуля
|
||
//----------------
|
||
|
||
export { TaskFormDialog };
|