186 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			186 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /*
 | ||
|     Парус 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"; //Хуки источников данных
 | ||
| 
 | ||
| //-----------
 | ||
| //Тело модуля
 | ||
| //-----------
 | ||
| 
 | ||
| //Диалог настройки источника данных
 | ||
| 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 { 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, "");
 | ||
| 
 | ||
|     //При изменении описания пользовательской процедуры
 | ||
|     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]);
 | ||
| 
 | ||
|     //Список значений
 | ||
|     const values = Object.keys(valueProviders).reduce((res, key) => [...res, ...Object.keys(valueProviders[key])], []);
 | ||
| 
 | ||
|     //Наличие значений
 | ||
|     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>
 | ||
|     );
 | ||
| 
 | ||
|     //Формирование представления
 | ||
|     return (
 | ||
|         <P8PConfigDialog title={TITLES.DATA_SOURCE_CONFIG} onOk={handleOk} onCancel={handleCancel}>
 | ||
|             <Stack direction={"column"} spacing={1}>
 | ||
|                 {valueProvidersMenu}
 | ||
|                 <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}>
 | ||
|                                     <Icon>clear</Icon>
 | ||
|                                 </IconButton>
 | ||
|                                 <IconButton onClick={handleUserProcSelectClick}>
 | ||
|                                     <Icon>list</Icon>
 | ||
|                                 </IconButton>
 | ||
|                             </InputAdornment>
 | ||
|                         )
 | ||
|                     }}
 | ||
|                 />
 | ||
|                 {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 };
 |