P8-Panels/app/components/p8p_indicator_hooks.js

144 lines
6.1 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 { 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 };