/* Парус 8 - Панели мониторинга Хуки для индикаторов */ //--------------------- //Подключение библиотек //--------------------- import { useState, useCallback, useEffect, useContext, useRef, useMemo } from "react"; //Классы React import { BackEndСtx } from "../context/backend"; //Контекст взаимодействия с сервером import { P8P_INDICATOR_STATE, P8P_INDICATOR_VARIANT } from "./p8p_indicator"; //--------- //Константы //--------- //Константы - значения по умолчанию const RESP_ARG_DEF = "COUT"; //Имя параметра, содержащего информацию об индикаторе const INDICATOR_NODE_NAME_DEF = "XINDICATOR"; //Наименование узла, содержащего информацию об индикаторе const ELEVATION_DEF = 3; //Высота парения //----------- //Тело модуля //----------- //Хук для P8PIndicator const useP8PIndicator = ({ stored, respArg = RESP_ARG_DEF, contentNodeName = INDICATOR_NODE_NAME_DEF, storedArgs = {}, executeStoredArgs = {}, allowDataLoad = () => true }) => { //Собственное состояние - индикатор const [indicator, setIndicator] = useState({ caption: null, value: null, icon: null, state: P8P_INDICATOR_STATE.UNDEFINED, square: false, elevation: ELEVATION_DEF, variant: P8P_INDICATOR_VARIANT.ELEVATION, hint: null, backgroundColor: null, color: null }); //Собственное состояние - признак загрузки данных const [isDataLoaded, setIsDataLoaded] = useState(false); //Собственное состояние - флаг загрузки const [isLoading, setLoading] = useState(false); //Собственное состояние - необходимость обновления данных const [reload, setReload] = useState(true); //Собственное состояние - дополнительные агрументы const refStoredArgs = useRef(storedArgs); //Собственное состояние - дополнительные параметры вызова процедуры const refExecuteStoredArgs = useRef(executeStoredArgs); //Признак допустимости обновления данных const isAllowDataLoad = useMemo(() => { return allowDataLoad(); }, [allowDataLoad]); //Подключение к контексту взаимодействия с сервером const { executeStored, isRespErr } = useContext(BackEndСtx); //Загрузка данных индикатора с сервера const loadData = useCallback(async () => { try { setLoading(true); const data = await executeStored({ stored, respArg, args: { ...refStoredArgs.current }, ...refExecuteStoredArgs.current }); setIndicator(pv => ({ ...pv, ...data[contentNodeName] })); //Устанавливаем признак загрузки данных с учетом возможных ошибок setIsDataLoaded(!isRespErr(data)); } catch (e) { //Если произошла ошибка - данные не загружены setIsDataLoaded(false); } finally { //Сбрасываем признаки загрузки и перезагрузки данных setLoading(false); setReload(false); } }, [contentNodeName, executeStored, isRespErr, respArg, stored]); //При необходимости обновления индикатора const doReload = useCallback(() => { setReload(true); }, []); //Проверка изменений параметров const isArgsChanged = useCallback( (currentArgs, args) => { //Если дополнительные параметры изменились (и сейчас не происходит загрузка данных с сервера) return !isLoading && JSON.stringify(currentArgs) != JSON.stringify(args); }, [isLoading] ); //При изменение дополнительных параметров процедуры useEffect(() => { //Если параметры изменились if (isArgsChanged(refStoredArgs.current, storedArgs)) { //Устанавливаем новые дополнительные параметры refStoredArgs.current = storedArgs; //При изменении дополнительных параметров необходимо перезагрузить данные setReload(true); } }, [storedArgs, isArgsChanged]); //При изменение дополнительных параметров вызова процедуры useEffect(() => { //Если параметры изменились if (isArgsChanged(refExecuteStoredArgs.current, executeStoredArgs)) { //Устанавливаем новые дополнительные параметры refExecuteStoredArgs.current = executeStoredArgs; //При изменении дополнительных параметров необходимо перезагрузить данные setReload(true); } }, [executeStoredArgs, isArgsChanged]); //При необходимости обновить данные индикатора useEffect(() => { //Если необходимо перезагрузить данные и это допустимо if (isAllowDataLoad && reload) { loadData(); } }, [isAllowDataLoad, reload, loadData]); //Возвращаем данные индикатора return { indicator, isDataLoaded, isLoading, doReload }; }; //---------------- //Интерфейс модуля //---------------- export { useP8PIndicator };