forked from CITKParus/P8-Panels
240 lines
12 KiB
JavaScript
240 lines
12 KiB
JavaScript
/*
|
||
Парус 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 };
|