P8-Panels/app/components/editors/p8p_data_source_config_dialog.js

254 lines
13 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, useContext } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Stack, IconButton, Icon, TextField, InputAdornment, MenuItem, Menu } from "@mui/material"; //Интерфейсные элементы
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { TITLES, CAPTIONS } from "../../../app.text"; //Общие текстовые ресурсы
import { P8PConfigDialog } from "./p8p_config_dialog"; //Типовой диалог настройки
import { P8P_DATA_SOURCE_TYPE, P8P_DATA_SOURCE_SHAPE, P8P_DATA_SOURCE_ARGUMENT_INITIAL, P8P_DATA_SOURCE_INITIAL } from "./p8p_data_source_common"; //Общие ресурсы компонента "Источник данных"
import { useUserProcDesc } from "./p8p_data_source_hooks"; //Хуки источников данных
import { P8PDataSourceQuerySelector } from "./p8p_data_source_query_selector"; //Диалог выбора записи редактора запросов
import { hasValue } from "../../core/utils"; //Вспомогательные функции
//-----------
//Тело модуля
//-----------
//Диалог настройки источника данных
const P8PDataSourceConfigDialog = ({ dataSource = null, valueProviders = {}, onOk = null, onCancel = null } = {}) => {
//Собственное состояние - параметры элемента формы
const [state, setState] = useState({ ...P8P_DATA_SOURCE_INITIAL, ...dataSource });
//Собственное состояние - флаги обновление данных
const [refresh, setRefresh] = useState({ userProcDesc: 0 });
//Собственное состояние - элемент привязки меню выбора источника
const [valueProvidersMenuAnchorEl, setValueProvidersMenuAnchorEl] = useState(null);
//Описание выбранной пользовательской процедуры
const [userProcDesc] = useUserProcDesc({ code: state.userProc, refresh: refresh.userProcDesc });
//Собственное состояние - отображение диалога выбора запроса
const [openQuerySelector, setOpenQuerySelector] = useState(false);
//Собственное состояние - доступность полей выбора источника
const [disabledFields, setDisabledFields] = useState({ query: false, userProc: false });
//Подключение к контексту приложения
const { pOnlineShowDictionary } = useContext(ApplicationСtx);
//Установка значения/привязки аргумента
const setArgumentValueSource = (index, value, valueSource) =>
setState(pv => ({
...pv,
arguments: pv.arguments.map((argument, i) => ({ ...argument, ...(i == index ? { value, valueSource } : {}) }))
}));
//Открытие/сокрытие меню выбора источника
const toggleValueProvidersMenu = target => setValueProvidersMenuAnchorEl(target instanceof Element ? target : null);
//При нажатии на очистку наименования пользовательской процедуры
const handleUserProcClearClick = () => setState({ ...P8P_DATA_SOURCE_INITIAL });
//При нажатии на выбор пользовательской процедуры в качестве источника данных
const handleUserProcSelectClick = () => {
pOnlineShowDictionary({
unitCode: "UserProcedures",
showMethod: "main",
inputParameters: [{ name: "in_CODE", value: state.userProc }],
callBack: res => {
if (res.success) {
setState(pv => ({ ...pv, type: P8P_DATA_SOURCE_TYPE.USER_PROC, userProc: res.outParameters.out_CODE }));
setRefresh(pv => ({ ...pv, userProcDesc: pv.userProcDesc + 1 }));
}
}
});
};
//При закрытии дилога с сохранением
const handleOk = () => onOk && onOk({ ...state });
//При закртии диалога отменой
const handleCancel = () => onCancel && onCancel();
//При очистке значения/связывания аргумента
const handleArgumentClearClick = index => setArgumentValueSource(index, "", "");
//При отображении меню связывания аргумента с поставщиком данных
const handleArgumentLinkMenuClick = e => setValueProvidersMenuAnchorEl(e.currentTarget);
//При выборе элемента меню связывания аргумента с поставщиком данных
const handleArgumentLinkClick = valueSource => {
setArgumentValueSource(valueProvidersMenuAnchorEl.id, "", valueSource);
toggleValueProvidersMenu();
};
//При вводе значения аргумента
const handleArgumentChange = (index, value) => setArgumentValueSource(index, value, "");
//Открытие диалога выбора запроса
const handleOpenQuerySelector = () => setOpenQuerySelector(true);
//Закрытие диалога выбора запроса
const handleCancelQuerySelector = () => setOpenQuerySelector(false);
//При нажатии на очистку мнемокода запроса
const handleQueryClearClick = () => setState({ ...P8P_DATA_SOURCE_INITIAL });
//При нажатии на выбор запроса в качестве источника данных
const handleQuerySelectClick = query => {
setState(pv => ({ ...pv, type: P8P_DATA_SOURCE_TYPE.QUERY, query: query.code }));
handleCancelQuerySelector();
};
//При изменении описания пользовательской процедуры
useEffect(() => {
if (userProcDesc)
setState(pv => ({
...pv,
stored: userProcDesc?.stored?.name,
respArg: userProcDesc?.stored?.respArg,
arguments: (userProcDesc?.arguments || []).map(argument => ({ ...P8P_DATA_SOURCE_ARGUMENT_INITIAL, ...argument }))
}));
}, [userProcDesc]);
//При изменении источника
useEffect(() => {
/*
Если выбран запрос - блокируем выбор процедуры
Если выбрана процедура - блокируем выбор запроса
Ничего не выбрано - доступны все варианты
*/
hasValue(state.query)
? setDisabledFields({ query: false, userProc: true })
: hasValue(state.userProc)
? setDisabledFields({ query: true, userProc: false })
: setDisabledFields({ query: false, userProc: false });
}, [state.query, state.userProc]);
//Список значений
const values = Object.keys(valueProviders);
//Наличие значений
const isValues = values && values.length > 0 ? true : false;
//Меню привязки к поставщикам значений
const valueProvidersMenu = isValues && (
<Menu anchorEl={valueProvidersMenuAnchorEl} open={Boolean(valueProvidersMenuAnchorEl)} onClose={toggleValueProvidersMenu}>
{values.map((value, i) => (
<MenuItem key={i} onClick={() => handleArgumentLinkClick(value)}>
{value}
</MenuItem>
))}
</Menu>
);
//Доступность сохранения настройки источника данных
const okDisabled = !state.query && !state.userProc ? true : false;
//Формирование представления
return (
<>
{openQuerySelector ? (
<P8PDataSourceQuerySelector current={state.query} onSelect={handleQuerySelectClick} onCancel={handleCancelQuerySelector} />
) : null}
<P8PConfigDialog title={TITLES.DATA_SOURCE_CONFIG} onOk={handleOk} onCancel={handleCancel} okDisabled={okDisabled}>
<Stack direction={"column"} spacing={1}>
{valueProvidersMenu}
{/* ДОРАБАТЫВАТЬ ПОСЛЕ РЕАЛИЗАЦИИ ЗАПРОСОВ */}
<TextField
type={"text"}
variant={"standard"}
value={state.query}
label={CAPTIONS.QUERY}
InputLabelProps={{ shrink: true }}
InputProps={{
readOnly: true,
endAdornment: (
<InputAdornment position="end">
<IconButton onClick={handleQueryClearClick} disabled={disabledFields.query}>
<Icon>clear</Icon>
</IconButton>
<IconButton onClick={handleOpenQuerySelector} disabled={disabledFields.query}>
<Icon>list</Icon>
</IconButton>
</InputAdornment>
)
}}
disabled={disabledFields.query}
/>
<TextField
type={"text"}
variant={"standard"}
value={state.userProc}
label={CAPTIONS.USER_PROC}
InputLabelProps={{ shrink: true }}
InputProps={{
readOnly: true,
endAdornment: (
<InputAdornment position="end">
<IconButton onClick={handleUserProcClearClick} disabled={disabledFields.userProc}>
<Icon>clear</Icon>
</IconButton>
<IconButton onClick={handleUserProcSelectClick} disabled={disabledFields.userProc}>
<Icon>list</Icon>
</IconButton>
</InputAdornment>
)
}}
disabled={disabledFields.userProc}
/>
{Array.isArray(state?.arguments) &&
state.arguments.map((argument, i) => (
<TextField
key={i}
type={"text"}
variant={"standard"}
value={argument.value || argument.valueSource}
label={argument.caption}
onChange={e => handleArgumentChange(i, e.target.value)}
InputLabelProps={{ shrink: true }}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton onClick={() => handleArgumentClearClick(i)}>
<Icon>clear</Icon>
</IconButton>
{isValues && (
<IconButton id={i} onClick={handleArgumentLinkMenuClick}>
<Icon>settings_ethernet</Icon>
</IconButton>
)}
</InputAdornment>
)
}}
/>
))}
</Stack>
</P8PConfigDialog>
</>
);
};
//Контроль свойств компонента - Диалог настройки источника данных
P8PDataSourceConfigDialog.propTypes = {
dataSource: P8P_DATA_SOURCE_SHAPE,
valueProviders: PropTypes.object,
onOk: PropTypes.func,
onCancel: PropTypes.func
};
//----------------
//Интерфейс модуля
//----------------
export { P8PDataSourceConfigDialog };