240 lines
12 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, useEffect } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { TextField, Select, MenuItem, FormControl, InputLabel, Stack, Box } from "@mui/material"; //Интерфейсные элементы
import { TITLES } from "../../../../app.text"; //Общие текстовые ресурсы
import { P8PConfigDialog } from "../p8p_config_dialog"; //Диалог настройки
import { P8P_CC_INITIAL, P8P_CC_SHAPE, P8P_CC_OPERATORS, P8P_CC_FIELD_PRM_SHAPE } from "./common"; //Общие ресурсы условий
import { deepCopyObject } from "../../../core/utils"; //Вспомогательные функции
import { isConditionOkDisabled } from "./util"; //Вспомогательные ресурсы условий
//---------
//Константы
//---------
//Стили
const STYLES = {
BOX_COND_GROUP: { display: "flex", flexDirection: "row", gap: "10px", paddingBottom: "10px" },
BOX_COND_ELEMENT: width => ({ minWidth: width })
};
//-----------
//Тело модуля
//-----------
//Редактор условия
const P8PCCEditor = ({ condition = null, onOk = null, onCancel = null, condFields = [], resFields = [] }) => {
//Собственное состояние - признак инициализиации
const [init, setInit] = useState(true);
//Собственное состояние - параметры элемента формы
const [state, setState] = useState({});
//При закрытии редактора с сохранением
const handleOk = () => onOk && onOk({ ...state });
//Собственное состояние - доступность поля "Элемент условия"
const [hasCondElement, setHasCondElement] = useState(false);
//Собственное состояние - доступность поля "Элемент результата"
const [hasResElement, setHasResElement] = useState(false);
//При закрытии редактора с отменой
const handleCancel = () => onCancel && onCancel();
//При изменении параметра элемента
const handleChange = e => setState(pv => ({ ...pv, [e.target.name]: e.target.value }));
//При изменении поля условия
const handleCondFieldChange = e => {
//Считываем нужный элемент
const newCondField = condFields.find(item => item.name === e.target.value);
//Обновляем поле (объект)
setState(pv => ({ ...pv, [e.target.name]: { name: newCondField.name, value: newCondField.value } }));
//Определяем доступность поля "Элемент условия"
setHasCondElement(newCondField?.hasElement || false);
};
//При изменении поля результата
const handleResFieldChange = e => {
//Считываем нужный элемент
const newResField = resFields.find(item => item.name === e.target.value);
//Обновляем поле результата
setState(pv => ({ ...pv, [e.target.name]: { name: newResField.name, value: newResField.value } }));
//Определяем доступность поля "Элемент результата"
setHasResElement(newResField?.hasElement || false);
};
//При изменении оператора условия
const handleOperatorChange = e => {
//Считываем нужный элемент
const newOperator = P8P_CC_OPERATORS.find(item => item.name === e.target.value);
//Обновляем оператор
setState(pv => ({ ...pv, [e.target.name]: { ...newOperator } }));
};
//При инициализации условия
useEffect(() => {
//Если это иницализация
if (init) {
//Если это открытие условия - берем его параметры, иначе - инициализируем изначальными
const initCondition = condition
? condition
: {
...P8P_CC_INITIAL,
condField: { name: condFields[0].name, value: condFields[0].value },
resField: { name: resFields[0].name, value: resFields[0].value }
};
//Устанавливаем параметры действия
setState(deepCopyObject(initCondition));
//Определяем доступность "Элемент условия"
setHasCondElement(condFields.find(item => item.name === initCondition.condField.name)?.hasElement || false);
//Определяем доступность "Элемент результата"
setHasResElement(resFields.find(item => item.name === initCondition.resField.name)?.hasElement || false);
//Сбрасываем признак инициализации
setInit(false);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [init]);
//Формирование представления
return (
<>
{!init ? (
<P8PConfigDialog
title={`${condition ? TITLES.UPDATE : TITLES.INSERT} условия`}
onOk={handleOk}
onCancel={handleCancel}
okDisabled={isConditionOkDisabled(state)}
>
<Stack direction={"column"} spacing={1}>
<Box>
<Box sx={STYLES.BOX_COND_GROUP}>
<FormControl variant={"standard"} sx={STYLES.BOX_COND_ELEMENT("160px")}>
<InputLabel id={"condField-label"}>Поле</InputLabel>
<Select
name={"condField"}
value={state.condField.name}
labelId={"condField-label"}
label={"Поле"}
onChange={handleCondFieldChange}
>
{condFields.map((item, index) => (
<MenuItem value={item.name} key={index}>
{item.name}
</MenuItem>
))}
</Select>
</FormControl>
<FormControl variant={"standard"} sx={STYLES.BOX_COND_ELEMENT("70px")}>
<InputLabel id={"condOperator-label"}>Оператор</InputLabel>
<Select
name={"condOperator"}
value={state.condOperator.name}
labelId={"condOperator-label"}
label={"Оператор"}
onChange={handleOperatorChange}
>
{P8P_CC_OPERATORS.map((item, index) => (
<MenuItem value={item.name} key={index}>
{item.name}
</MenuItem>
))}
</Select>
</FormControl>
<TextField
InputLabelProps={{ shrink: true }}
type={"text"}
variant={"standard"}
value={state.condValue}
label={"Значение"}
name={"condValue"}
onChange={handleChange}
sx={STYLES.BOX_COND_ELEMENT("160px")}
/>
</Box>
{hasCondElement ? (
<TextField
InputLabelProps={{ shrink: true }}
sx={{ pb: 1.25 }}
type={"text"}
variant={"standard"}
value={state.condElement}
label={"Элемент условия"}
name={"condElement"}
onChange={handleChange}
fullWidth
/>
) : null}
<Box sx={STYLES.BOX_COND_GROUP}>
<FormControl variant={"standard"} sx={STYLES.BOX_COND_ELEMENT("160px")}>
<InputLabel id={"resField-label"}>Поле результата</InputLabel>
<Select
name={"resField"}
value={state.resField.name}
labelId={"resField-label"}
label={"Поле результата"}
onChange={handleResFieldChange}
>
{resFields.map((item, index) => (
<MenuItem value={item.name} key={index}>
{item.name}
</MenuItem>
))}
</Select>
</FormControl>
<TextField
InputLabelProps={{ shrink: true }}
type={"text"}
variant={"standard"}
value={state.resValue}
label={"Результат"}
name={"resValue"}
onChange={handleChange}
fullWidth
/>
</Box>
{hasResElement ? (
<TextField
InputLabelProps={{ shrink: true }}
sx={{ pb: 1.25 }}
type={"text"}
variant={"standard"}
value={state.resElement}
label={"Элемент результата"}
name={"resElement"}
onChange={handleChange}
fullWidth
/>
) : null}
</Box>
</Stack>
</P8PConfigDialog>
) : null}
</>
);
};
//Контроль свойств - Редактор условия
P8PCCEditor.propTypes = {
condition: P8P_CC_SHAPE,
onOk: PropTypes.func.isRequired,
onCancel: PropTypes.func.isRequired,
condFields: PropTypes.arrayOf(P8P_CC_FIELD_PRM_SHAPE).isRequired,
resFields: PropTypes.arrayOf(P8P_CC_FIELD_PRM_SHAPE).isRequired
};
//----------------
//Интерфейс модуля
//----------------
export { P8PCCEditor };