488 lines
18 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Парус 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 };