P8-Panels/app/components/p8p_data_grid_hooks.js

225 lines
9.6 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 { object2Base64XML } from "../core/utils"; //Вспомогательные функции
//---------
//Константы
//---------
//Константы - значения по умолчанию
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 = {},
executeStoredArgs = {},
allowDataLoad = () => true
}) => {
//Собственное состояние - таблица данных
const [dataGrid, setDataGrid] = useState({
columnsDef: [],
groups: [],
rows: [],
filters: Array.isArray(initFilters) ? [...initFilters] : [],
orders: Array.isArray(initOrders) ? [...initOrders] : [],
pageNumber: 1,
pagesAlign: null,
pagesPosition: null,
pagesCount: 0,
fixedColumns: 0,
fixedHeader: false,
morePages: true
});
//Собственное состояние - признак загрузки данных
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, SERV_DATA_TYPE_CLOB, isRespErr } = useContext(BackEndСtx);
//Загрузка данных таблицы с сервера
const loadData = useCallback(async () => {
try {
setLoading(true);
const data = await executeStored({
stored,
args: {
CFILTERS: { VALUE: object2Base64XML(dataGrid.filters, { arrayNodeName: filtersNodeName }), SDATA_TYPE: SERV_DATA_TYPE_CLOB },
CORDERS: { VALUE: object2Base64XML(dataGrid.orders, { arrayNodeName: ordersNodeName }), SDATA_TYPE: SERV_DATA_TYPE_CLOB },
NPAGE_NUMBER: dataGrid.pageNumber,
NPAGE_SIZE: pageSize,
NINCLUDE_DEF: reloadDef ? 1 : dataGrid.dataLoaded ? 0 : 1,
...refStoredArgs.current
},
respArg,
...refExecuteStoredArgs.current
});
setDataGrid(pv => ({
...pv,
...data[contentNodeName],
columnsDef: data[contentNodeName].columnsDef ? [...data[contentNodeName].columnsDef] : pv.columnsDef || [],
rows:
data[contentNodeName].pagesCount > 0 || pv.pageNumber == 1
? [...(data[contentNodeName].rows || [])]
: [...(pv.rows || []), ...(data[contentNodeName].rows || [])],
groups: data[contentNodeName].groups
? data[contentNodeName].pagesCount > 0 || pv.pageNumber == 1
? [...(data[contentNodeName].groups || [])]
: [...(pv.groups || []), ...data[contentNodeName].groups.filter(g => !pv.groups.find(pg => pg.name == g.name))]
: [...(pv.groups || [])],
morePages: data[contentNodeName].morePages && (data[contentNodeName].rows || []).length >= pageSize
}));
//Устанавливаем признак загрузки данных с учетом возможных ошибок
setIsDataLoaded(!isRespErr(data));
} catch (e) {
//Если произошла ошибка - данные не загружены
setIsDataLoaded(false);
} finally {
//Сбрасываем признаки загрузки и перезагрузки данных
setLoading(false);
setReload(false);
}
}, [
SERV_DATA_TYPE_CLOB,
contentNodeName,
dataGrid.dataLoaded,
dataGrid.filters,
dataGrid.orders,
dataGrid.pageNumber,
executeStored,
filtersNodeName,
isRespErr,
ordersNodeName,
pageSize,
reloadDef,
respArg,
stored
]);
//При изменении состояния фильтра
const handleFilterChanged = useCallback(({ filters }) => {
setDataGrid(pv => ({ ...pv, filters: [...filters], pageNumber: 1 }));
setReload(true);
}, []);
//При изменении состояния сортировки
const handleOrderChanged = useCallback(({ orders }) => {
setDataGrid(pv => ({ ...pv, orders: [...orders], pageNumber: 1 }));
setReload(true);
}, []);
//При изменении количества отображаемых страниц
const handlePagesCountChanged = useCallback(() => {
setDataGrid(pv => ({ ...pv, pageNumber: pv.pageNumber + 1 }));
setReload(true);
}, []);
//При изменении страницы отображения
const handlePageChange = useCallback(({ page }) => {
setDataGrid(pv => ({ ...pv, pageNumber: page }));
setReload(true);
}, []);
//При необходимости обновления таблицы
const doReload = useCallback(
({ returnOnFirstPage = false }) => {
//Если это не страничный вывод или установлен признак возврата на первую страницу
if (dataGrid.pagesCount <= 0 || returnOnFirstPage) {
setDataGrid(pv => ({ ...pv, pageNumber: 1 }));
}
setReload(true);
},
[dataGrid.pagesCount]
);
//Проверка изменений параметров
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 { dataGrid, isDataLoaded, isLoading, handleFilterChanged, handleOrderChanged, handlePagesCountChanged, handlePageChange, doReload };
};
//----------------
//Интерфейс модуля
//----------------
export { useP8PDataGrid };