144 lines
6.1 KiB
JavaScript
144 lines
6.1 KiB
JavaScript
/*
|
||
Парус 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 };
|