P8-Panels/app/components/p8p_data_grid_hooks.js

206 lines
9.3 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 { useReducer, useCallback, useEffect, useContext, useRef, useMemo } from "react"; //Классы React
import { BackEndCtx } from "../context/backend"; //Контекст взаимодействия с сервером
import { object2Base64XML } from "../core/utils"; //Вспомогательные функции
import { DG_AT, INITIAL_STATE, dataGridReducer } from "./p8p_data_grid_reducer"; //Редьюсер состояния
//---------
//Константы
//---------
//Константы - значения по умолчанию
const DG_PAGE_SIZE_DEF = 10; //Размер страницы
const DG_NODE_NAME_DEF = "XDATA_GRID"; //Наименование узла, содержащего информацию о таблице
const FILTERS_NODE_NAME_DEF = "filters"; //Наименование узла отборов
const ORDERS_NODE_NAME_DEF = "orders"; //Наименование узла сортировок
const RESP_ARG_DEF = "COUT"; //Имя параметра, содержащего информацию о таблице
//-----------
//Тело модуля
//-----------
//Хук для P8PDataGrid
const useP8PDataGrid = ({
stored,
respArg = RESP_ARG_DEF,
contentNodeName = DG_NODE_NAME_DEF,
filtersNodeName = FILTERS_NODE_NAME_DEF,
ordersNodeName = ORDERS_NODE_NAME_DEF,
pageSize = DG_PAGE_SIZE_DEF,
reloadDef = false,
initFilters = [],
initOrders = [],
storedArgs = {},
resetPageNumberOnStoredArgsChange = true,
executeStoredArgs = {},
resetPageNumberOnExecuteStoredArgsChange = true,
allowDataLoad = () => true
}) => {
//Подключим редьюсер состояния
const [state, dispatch] = useReducer(dataGridReducer, INITIAL_STATE({ initFilters, initOrders }));
//Установка даных таблицы
const setDataGrid = (dataGridData, pageSize, isError) => dispatch({ type: DG_AT.SET_DATA_GRID, payload: { dataGridData, pageSize, isError } });
//Установка фильтра таблицы
const setDataGridFilter = filters => dispatch({ type: DG_AT.SET_DATA_GRID_FILTER, payload: filters });
//Установка сортировок таблицы
const setDataGridOrder = orders => dispatch({ type: DG_AT.SET_DATA_GRID_ORDER, payload: orders });
//Установка страницы таблицы
const setDataGridPageNumber = pageNumber => dispatch({ type: DG_AT.SET_DATA_GRID_PAGE_NUMBER, payload: pageNumber });
//Установка флага загруженности данных
const setIsDataLoaded = isDataLoaded => dispatch({ type: DG_AT.SET_IS_DATA_LOADED, payload: isDataLoaded });
//Установка флага активности процесса загрузки данных
const setIsLoading = isLoading => dispatch({ type: DG_AT.SET_IS_LOADING, payload: isLoading });
//Установка флага необходимости обновления данных
const setReload = (reload, resetPageNumber = false) => dispatch({ type: DG_AT.SET_RELOAD, payload: { reload, resetPageNumber } });
//Ссылка на актуальные параметры хранимой процедуры
const refStoredArgs = useRef(storedArgs);
//Ссылка на актуальные параметры исполнения хранимой процедуры
const refExecuteStoredArgs = useRef(executeStoredArgs);
//Признак допустимости обновления данных
const isAllowDataLoad = useMemo(() => {
return allowDataLoad();
}, [allowDataLoad]);
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB, isRespErr } = useContext(BackEndCtx);
//Загрузка данных таблицы с сервера
const loadData = useCallback(async () => {
try {
//Начинаем загрузку
setIsLoading(true);
const data = await executeStored({
stored,
args: {
CFILTERS: {
VALUE: object2Base64XML(state.dataGrid.filters, { arrayNodeName: filtersNodeName }),
SDATA_TYPE: SERV_DATA_TYPE_CLOB
},
CORDERS: { VALUE: object2Base64XML(state.dataGrid.orders, { arrayNodeName: ordersNodeName }), SDATA_TYPE: SERV_DATA_TYPE_CLOB },
NPAGE_NUMBER: state.dataGrid.pageNumber,
NPAGE_SIZE: pageSize,
NINCLUDE_DEF: reloadDef ? 1 : state.isDataLoaded ? 0 : 1,
...refStoredArgs.current
},
respArg,
...refExecuteStoredArgs.current
});
//Устанавливаем полученные данные и признак загрузки данных с учетом возможных ошибок
setDataGrid(data[contentNodeName], pageSize, isRespErr(data));
} catch (e) {
//Если произошла ошибка - данные не загружены
setIsDataLoaded(false);
} finally {
//Сбрасываем признаки загрузки и перезагрузки данных
setIsLoading(false);
}
}, [
SERV_DATA_TYPE_CLOB,
contentNodeName,
state.isDataLoaded,
state.dataGrid.filters,
state.dataGrid.orders,
state.dataGrid.pageNumber,
executeStored,
filtersNodeName,
isRespErr,
ordersNodeName,
pageSize,
reloadDef,
respArg,
stored
]);
//При изменении состояния фильтра
const handleFilterChanged = useCallback(({ filters }) => setDataGridFilter(filters), []);
//При изменении состояния сортировки
const handleOrderChanged = useCallback(({ orders }) => setDataGridOrder(orders), []);
//При изменении количества отображаемых страниц
const handlePagesCountChanged = useCallback(() => setDataGridPageNumber(state.dataGrid.pageNumber + 1), [state.dataGrid.pageNumber]);
//При изменении страницы отображения
const handlePageChange = useCallback(({ page }) => setDataGridPageNumber(page), []);
//При необходимости обновления таблицы
const doReload = useCallback(
({ returnOnFirstPage = false }) => setReload(true, state.dataGrid.pagesCount <= 0 || returnOnFirstPage),
[state.dataGrid.pagesCount]
);
//Проверка изменений параметров
const isArgsChanged = useCallback(
(currentArgs, args) => {
//Если дополнительные параметры изменились (и сейчас не происходит загрузка данных с сервера)
return !state.isLoading && JSON.stringify(currentArgs) != JSON.stringify(args);
},
[state.isLoading]
);
//При изменение дополнительных параметров процедуры
useEffect(() => {
//Если параметры изменились
if (isArgsChanged(refStoredArgs.current, storedArgs)) {
//Устанавливаем новые дополнительные параметры
refStoredArgs.current = storedArgs;
//При изменении дополнительных параметров необходимо перезагрузить данные
setReload(true, resetPageNumberOnStoredArgsChange);
}
}, [storedArgs, resetPageNumberOnStoredArgsChange, isArgsChanged]);
//При изменение дополнительных параметров вызова процедуры
useEffect(() => {
//Если параметры изменились
if (isArgsChanged(refExecuteStoredArgs.current, executeStoredArgs)) {
//Устанавливаем новые дополнительные параметры
refExecuteStoredArgs.current = executeStoredArgs;
//При изменении дополнительных параметров необходимо перезагрузить данные
setReload(true, resetPageNumberOnExecuteStoredArgsChange);
}
}, [executeStoredArgs, resetPageNumberOnExecuteStoredArgsChange, isArgsChanged]);
//При необходимости обновить данные таблицы
useEffect(() => {
if (isAllowDataLoad && state.reload) {
loadData();
}
}, [isAllowDataLoad, state.reload, loadData]);
//Возвращаем данные таблицы
return {
dataGrid: state.dataGrid,
isDataLoaded: state.isDataLoaded,
isLoading: state.isLoading,
handleFilterChanged,
handleOrderChanged,
handlePagesCountChanged,
handlePageChange,
doReload
};
};
//----------------
//Интерфейс модуля
//----------------
export { useP8PDataGrid };