251 lines
12 KiB
JavaScript
251 lines
12 KiB
JavaScript
/*
|
||
Парус 8 - Панели мониторинга - Редакторы панелей
|
||
Компонент: Редактор действия
|
||
*/
|
||
|
||
//---------------------
|
||
//Подключение библиотек
|
||
//---------------------
|
||
|
||
import React, { useState, useEffect } from "react"; //Классы React
|
||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||
import { TextField, Select, Menu, MenuItem, FormControl, InputLabel, Stack, Box } from "@mui/material"; //Интерфейсные элементы
|
||
import { TITLES } from "../../../../app.text"; //Общие текстовые ресурсы
|
||
import { P8PConfigDialog } from "../p8p_config_dialog"; //Диалог настройки
|
||
import { deepCopyObject } from "../../../core/utils"; //Вспомогательные функции
|
||
import { P8P_CA_DEF_VALUE_TYPES, P8P_CA_TYPE, P8P_CA_SHAPE, P8P_CA_INPUT_PARAM_INITIAL, P8P_CA_OPEN_UNIT_INITIAL, P8P_CA_INITIAL } from "./common"; //Общие ресурсы действий
|
||
import { P8PCAUnitOpenOptions } from "./config_unit_open"; //Компонент редактора действия "Открыть раздел"
|
||
import { P8PCAPanelOpenOptions } from "./config_panel_open"; //Компонент редактора действия "Открыть панель"
|
||
import { P8PCAVarSetOptions } from "./config_var_set"; //Компонент редактора действия "Установить переменную"
|
||
import { isActionOkDisabled, getActionTypeParams } from "./util"; //Вспомогательные ресурсы действий
|
||
|
||
//---------
|
||
//Константы
|
||
//---------
|
||
|
||
//Стили
|
||
const STYLES = {
|
||
CONTAINER: { display: "flex", flexDirection: "column", gap: "10px", minWidth: "300px" }
|
||
};
|
||
|
||
//-----------
|
||
//Тело модуля
|
||
//-----------
|
||
|
||
//Редактор действия
|
||
const P8PCAEditor = ({ areas = [], valueTypes = [], action = null, onOk = null, onCancel = null, valueProviders = {} }) => {
|
||
//Собственное состояние - признак инициализиации
|
||
const [init, setInit] = useState(true);
|
||
|
||
//Собственное состояние - параметры действия
|
||
const [state, setState] = useState({});
|
||
|
||
//Собственное состояние - доступные типы значений компонента
|
||
const [availableValueTypes, setAvailableValueTypes] = useState([]);
|
||
|
||
//Собственное состояние - доступные области компонента
|
||
const [availableAreas, setAvailableAreas] = useState([]);
|
||
|
||
//Собственное состояние - доступность поля "Элемент"
|
||
const [hasElement, setHasElement] = useState(false);
|
||
|
||
//Собственное состояние - элемент привязки меню выбора источника
|
||
const [valueProvidersMenuAnchorEl, setValueProvidersMenuAnchorEl] = useState({
|
||
target: null,
|
||
onChange: null
|
||
});
|
||
|
||
//Открытие/сокрытие меню выбора источника
|
||
const toggleValueProvidersMenu = (target, onChange) =>
|
||
setValueProvidersMenuAnchorEl(target instanceof Element ? { target, onChange } : { target: null, onChange: null });
|
||
|
||
//При отображении меню связывания значения с поставщиком данных
|
||
const handleValueSourceLinkMenuClick = (e, onChange) => setValueProvidersMenuAnchorEl({ target: e.currentTarget, onChange });
|
||
|
||
//При закрытии редактора с сохранением
|
||
const handleOk = () => onOk && onOk({ ...state });
|
||
|
||
//При закрытии редактора с отменой
|
||
const handleCancel = () => onCancel && onCancel();
|
||
|
||
//При изменении типа действия
|
||
const handleTypeChange = e => {
|
||
//Иницилизируем параметры типа
|
||
let newParams = getActionTypeParams(e.target.value);
|
||
//Изменяем тип действия с изменение структуры параметров
|
||
setState(pv => ({
|
||
...pv,
|
||
type: e.target.value,
|
||
params: Array.isArray(newParams) ? [...newParams] : { ...newParams }
|
||
}));
|
||
};
|
||
|
||
//При ручном изменении общего параметра действия
|
||
const handleChange = e => setState(pv => ({ ...pv, [e.target.name]: e.target.value }));
|
||
|
||
//При изменении области действия
|
||
const handleAreaChange = e => {
|
||
//Устанавливаем значение
|
||
setState(pv => ({ ...pv, [e.target.name]: e.target.value, name: "" }));
|
||
//Устанавливаем доступность "Элемент"
|
||
setHasElement(availableAreas.find(item => item.area === e.target.value).hasElement);
|
||
};
|
||
|
||
//При изменении полей параметров действия
|
||
const handleParamsChange = params => {
|
||
setState(pv => ({ ...pv, params: { ...pv.params, ...params } }));
|
||
};
|
||
|
||
//При изменении переменных параметров действия "Установить переменную"
|
||
const handleVariablesParamsChange = variables => {
|
||
setState(pv => ({ ...pv, params: [...variables] }));
|
||
};
|
||
|
||
//Список значений
|
||
const values = Object.keys(valueProviders);
|
||
|
||
//Наличие значений
|
||
const isValues = values && values.length > 0 ? true : false;
|
||
|
||
//Меню привязки к поставщикам значений
|
||
const valueProvidersMenu = isValues && (
|
||
<Menu anchorEl={valueProvidersMenuAnchorEl.target} open={Boolean(valueProvidersMenuAnchorEl.target)} onClose={toggleValueProvidersMenu}>
|
||
{values.map((value, i) => (
|
||
<MenuItem
|
||
key={i}
|
||
onClick={() => {
|
||
//Выполняем выбор параметра
|
||
valueProvidersMenuAnchorEl.onChange(value);
|
||
//Закрываем меню выбора переменной
|
||
toggleValueProvidersMenu();
|
||
}}
|
||
>
|
||
{value}
|
||
</MenuItem>
|
||
))}
|
||
</Menu>
|
||
);
|
||
|
||
//При инициализации действия
|
||
useEffect(() => {
|
||
//Если это иницализация
|
||
if (init) {
|
||
//Если это открытие действия - берем его параметры, иначе - инициализируем изначальными
|
||
const initAction = action
|
||
? action
|
||
: {
|
||
...P8P_CA_INITIAL,
|
||
area: areas[0].area,
|
||
params: { ...P8P_CA_OPEN_UNIT_INITIAL, inputParams: [{ ...P8P_CA_INPUT_PARAM_INITIAL }] }
|
||
};
|
||
//Устанавливаем параметры действия
|
||
setState(deepCopyObject(initAction));
|
||
//Заполняем доступные области
|
||
setAvailableAreas([...areas]);
|
||
//Определяем доступность "Элемент"
|
||
setHasElement(areas.find(item => item.area === initAction.area)?.hasElement || false);
|
||
//Заполняем доступные типы значений
|
||
setAvailableValueTypes([...P8P_CA_DEF_VALUE_TYPES, ...valueTypes]);
|
||
//Сбрасываем признак инициализации
|
||
setInit(false);
|
||
}
|
||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||
}, [init]);
|
||
|
||
//Формирование представления
|
||
return (
|
||
<>
|
||
{!init ? (
|
||
<P8PConfigDialog
|
||
title={`${action ? TITLES.UPDATE : TITLES.INSERT} действия`}
|
||
onOk={handleOk}
|
||
onCancel={handleCancel}
|
||
width={"xl"}
|
||
okDisabled={isActionOkDisabled(state)}
|
||
>
|
||
<Stack direction={"column"} spacing={1}>
|
||
{valueProvidersMenu}
|
||
<Box sx={STYLES.CONTAINER}>
|
||
{availableAreas.length !== 0 ? (
|
||
<FormControl variant={"standard"} fullWidth>
|
||
<InputLabel id={"areaLabel-label"}>Область</InputLabel>
|
||
<Select name={"area"} value={state.area} labelId={"area-label"} label={"Область"} onChange={handleAreaChange}>
|
||
{availableAreas.map((item, index) => (
|
||
<MenuItem value={item.area} key={index}>
|
||
{item.name}
|
||
</MenuItem>
|
||
))}
|
||
</Select>
|
||
</FormControl>
|
||
) : null}
|
||
{hasElement && (
|
||
<TextField
|
||
type={"text"}
|
||
variant={"standard"}
|
||
value={state.element}
|
||
label={"Элемент"}
|
||
name={"element"}
|
||
onChange={handleChange}
|
||
/>
|
||
)}
|
||
<FormControl variant={"standard"} fullWidth>
|
||
<InputLabel id={"type-label"}>Тип</InputLabel>
|
||
<Select name={"type"} value={state.type} labelId={"type-label"} label={"Тип"} onChange={handleTypeChange}>
|
||
{Object.keys(P8P_CA_TYPE).map((item, index) => (
|
||
<MenuItem value={P8P_CA_TYPE[item].code} key={index}>
|
||
{P8P_CA_TYPE[item].name}
|
||
</MenuItem>
|
||
))}
|
||
</Select>
|
||
</FormControl>
|
||
</Box>
|
||
{state.type === P8P_CA_TYPE.openUnit.code && (
|
||
<P8PCAUnitOpenOptions
|
||
unit={state.params}
|
||
valueTypes={availableValueTypes}
|
||
isValues={isValues}
|
||
onStateChange={handleParamsChange}
|
||
onValueSourceMenuClick={handleValueSourceLinkMenuClick}
|
||
/>
|
||
)}
|
||
{state.type === P8P_CA_TYPE.openPanel.code && (
|
||
<P8PCAPanelOpenOptions
|
||
panel={state.params}
|
||
valueTypes={availableValueTypes}
|
||
isValues={isValues}
|
||
onStateChange={handleParamsChange}
|
||
onValueSourceMenuClick={handleValueSourceLinkMenuClick}
|
||
/>
|
||
)}
|
||
{state.type === P8P_CA_TYPE.setVariable.code && (
|
||
<P8PCAVarSetOptions
|
||
variables={state.params}
|
||
valueTypes={availableValueTypes}
|
||
isValues={isValues}
|
||
onStateChange={handleVariablesParamsChange}
|
||
onValueSourceMenuClick={handleValueSourceLinkMenuClick}
|
||
/>
|
||
)}
|
||
</Stack>
|
||
</P8PConfigDialog>
|
||
) : null}
|
||
</>
|
||
);
|
||
};
|
||
|
||
//Контроль свойств - Редактор условия
|
||
P8PCAEditor.propTypes = {
|
||
areas: PropTypes.array,
|
||
valueTypes: PropTypes.array,
|
||
action: P8P_CA_SHAPE,
|
||
onOk: PropTypes.func.isRequired,
|
||
onCancel: PropTypes.func.isRequired,
|
||
valueProviders: PropTypes.object
|
||
};
|
||
|
||
//----------------
|
||
//Интерфейс модуля
|
||
//----------------
|
||
|
||
export { P8PCAEditor };
|