152 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			152 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /*
 | ||
|     Парус 8 - Панели мониторинга - Редакторы панелей
 | ||
|     Пользовательские хуки компонента "Источник данных"
 | ||
| */
 | ||
| 
 | ||
| //---------------------
 | ||
| //Подключение библиотек
 | ||
| //---------------------
 | ||
| 
 | ||
| import { useState, useContext, useEffect, useRef } from "react"; //Классы React
 | ||
| import client from "../../core/client"; //Клиент взаимодействия с сервером приложений
 | ||
| import { ERRORS } from "../../../app.text"; //Общие текстовые ресурсы
 | ||
| import { formatErrorMessage } from "../../core/utils"; //Общие вспомогательные функции
 | ||
| import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
 | ||
| import { P8P_DATA_SOURCE_TYPE, P8P_DATA_SOURCE_ARGUMENT_DATA_TYPE } from "./p8p_data_source_common"; //Общие ресурсы источника данных
 | ||
| 
 | ||
| //-----------
 | ||
| //Тело модуля
 | ||
| //-----------
 | ||
| 
 | ||
| //Описание пользовательской процедуры
 | ||
| const useUserProcDesc = ({ code, refresh }) => {
 | ||
|     //Собственное состояние - флаг загрузки
 | ||
|     const [isLoading, setLoading] = useState(false);
 | ||
| 
 | ||
|     //Собственное состояние - данные
 | ||
|     const [data, setData] = useState(null);
 | ||
| 
 | ||
|     //Подключение к контексту взаимодействия с сервером
 | ||
|     const { executeStored } = useContext(BackEndСtx);
 | ||
| 
 | ||
|     //При необходимости обновить данные компонента
 | ||
|     useEffect(() => {
 | ||
|         //Загрузка данных с сервера
 | ||
|         const loadData = async () => {
 | ||
|             try {
 | ||
|                 setLoading(true);
 | ||
|                 const data = await executeStored({
 | ||
|                     stored: "PKG_P8PANELS_PE.USERPROCS_DESC",
 | ||
|                     args: { SCODE: code },
 | ||
|                     respArg: "COUT",
 | ||
|                     isArray: name => name === "arguments",
 | ||
|                     loader: false
 | ||
|                 });
 | ||
|                 setData(data?.XUSERPROC || null);
 | ||
|             } finally {
 | ||
|                 setLoading(false);
 | ||
|             }
 | ||
|         };
 | ||
|         //Если надо обновить и есть для чего получать данные
 | ||
|         if (refresh > 0)
 | ||
|             if (code) loadData();
 | ||
|             else setData(null);
 | ||
|     }, [refresh, code, executeStored]);
 | ||
| 
 | ||
|     //Возвращаем интерфейс хука
 | ||
|     return [data, isLoading];
 | ||
| };
 | ||
| 
 | ||
| //Получение данных из источника
 | ||
| const useDataSource = ({ dataSource, values }) => {
 | ||
|     //Контроллер для прерывания запросов
 | ||
|     const abortController = useRef(null);
 | ||
| 
 | ||
|     //Собственное состояние - параметры исполнения
 | ||
|     const [state, setState] = useState({ stored: null, storedArgs: [], respArg: null, reqSet: false });
 | ||
| 
 | ||
|     //Собственное состояние - флаг загрузки
 | ||
|     const [isLoading, setLoading] = useState(false);
 | ||
| 
 | ||
|     //Собственное состояние - данные
 | ||
|     const [data, setData] = useState({ init: false });
 | ||
| 
 | ||
|     //Собственное состояние - ошибка получения данных
 | ||
|     const [error, setError] = useState(null);
 | ||
| 
 | ||
|     //Подключение к контексту взаимодействия с сервером
 | ||
|     const { executeStored } = useContext(BackEndСtx);
 | ||
| 
 | ||
|     //При необходимости обновить данные
 | ||
|     useEffect(() => {
 | ||
|         //Загрузка данных с сервера
 | ||
|         const loadData = async () => {
 | ||
|             try {
 | ||
|                 setLoading(true);
 | ||
|                 abortController.current?.abort?.();
 | ||
|                 abortController.current = new AbortController();
 | ||
|                 const data = await executeStored({
 | ||
|                     stored: state.stored,
 | ||
|                     args: { ...(state.storedArgs ? state.storedArgs : {}) },
 | ||
|                     respArg: state.respArg,
 | ||
|                     loader: false,
 | ||
|                     signal: abortController.current.signal,
 | ||
|                     showErrorMessage: false
 | ||
|                 });
 | ||
|                 setError(null);
 | ||
|                 setData({ ...data, init: true });
 | ||
|             } catch (e) {
 | ||
|                 if (e.message !== client.ERR_ABORTED) {
 | ||
|                     setError(formatErrorMessage(e.message).text);
 | ||
|                     setData({ init: false });
 | ||
|                 }
 | ||
|             } finally {
 | ||
|                 setLoading(false);
 | ||
|             }
 | ||
|         };
 | ||
|         if (state.reqSet) {
 | ||
|             if (state.stored) loadData();
 | ||
|         } else setData({ init: false });
 | ||
|         return () => abortController.current?.abort?.();
 | ||
|     }, [state.stored, state.storedArgs, state.respArg, state.reqSet, executeStored]);
 | ||
| 
 | ||
|     //При изменении свойств
 | ||
|     useEffect(() => {
 | ||
|         setState(pv => {
 | ||
|             if (dataSource?.type == P8P_DATA_SOURCE_TYPE.USER_PROC) {
 | ||
|                 const { stored, respArg } = dataSource;
 | ||
|                 let reqSet = true;
 | ||
|                 const storedArgs = {};
 | ||
|                 dataSource.arguments.forEach(argument => {
 | ||
|                     let v = argument.valueSource ? values[argument.valueSource] : argument.value;
 | ||
|                     storedArgs[argument.name] =
 | ||
|                         argument.dataType == P8P_DATA_SOURCE_ARGUMENT_DATA_TYPE.NUMB
 | ||
|                             ? isNaN(parseFloat(v))
 | ||
|                                 ? null
 | ||
|                                 : parseFloat(v)
 | ||
|                             : argument.dataType == P8P_DATA_SOURCE_ARGUMENT_DATA_TYPE.DATE
 | ||
|                             ? new Date(v)
 | ||
|                             : String(v === undefined ? "" : v);
 | ||
|                     if (argument.req === true && [undefined, null, ""].includes(storedArgs[argument.name])) reqSet = false;
 | ||
|                 });
 | ||
|                 if (pv.stored != stored || pv.respArg != respArg || JSON.stringify(pv.storedArgs) != JSON.stringify(storedArgs)) {
 | ||
|                     if (!reqSet) {
 | ||
|                         setError(ERRORS.DATA_SOURCE_NO_REQ_ARGS);
 | ||
|                         setData({ init: false });
 | ||
|                     }
 | ||
|                     return { stored, respArg, storedArgs, reqSet };
 | ||
|                 } else return pv;
 | ||
|             } else return pv;
 | ||
|         });
 | ||
|     }, [dataSource, values]);
 | ||
| 
 | ||
|     //Возвращаем интерфейс хука
 | ||
|     return [data, error, isLoading];
 | ||
| };
 | ||
| 
 | ||
| //----------------
 | ||
| //Интерфейс модуля
 | ||
| //----------------
 | ||
| 
 | ||
| export { useUserProcDesc, useDataSource };
 |