forked from CITKParus/P8-Panels
179 lines
7.3 KiB
JavaScript
179 lines
7.3 KiB
JavaScript
/*
|
||
Парус 8 - Панели мониторинга - Редактор запросов
|
||
Пользовательские хуки для работы с метаданными запроса
|
||
*/
|
||
|
||
//---------------------
|
||
//Подключение библиотек
|
||
//---------------------
|
||
|
||
import { useState, useContext, useEffect } from "react"; //Классы React
|
||
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
|
||
import { NODE_TYPE } from "./common"; //Общие ресурсы и константы редактора
|
||
|
||
//---------
|
||
//Константы
|
||
//---------
|
||
|
||
//Ширина элемента диаграммы
|
||
const NODE_WIDTH = 250;
|
||
|
||
//Высота единицы состава группового элемента диаграммы
|
||
const GROUP_NODE_ITEM_HEIGHT = 50;
|
||
|
||
//Стили
|
||
const STYLES = {
|
||
ATTRIBUTE: isLast => ({ borderBottom: isLast ? "none" : "1px solid #dee2e6" })
|
||
};
|
||
|
||
//------------------------------------
|
||
//Вспомогательные функции и компоненты
|
||
//------------------------------------
|
||
|
||
//Конвертация серверного описания сущностей запроса в элементы диаграммы
|
||
const serverEntity2QueryDiagramNodes = entity => {
|
||
//Ссылка на атрибуты
|
||
const attrs = entity.attrs || [];
|
||
//Количество атрибутов
|
||
const attrsCount = attrs.length;
|
||
//Высота группового элемента диаграммы
|
||
const entityNodeHeight = GROUP_NODE_ITEM_HEIGHT + attrsCount * GROUP_NODE_ITEM_HEIGHT;
|
||
//Элемент диаграммы для сущности (групповой элемент)
|
||
const entityNode = {
|
||
id: entity.id,
|
||
type: NODE_TYPE.ENTITY,
|
||
data: { ...entity },
|
||
position: { x: entity.x, y: entity.y },
|
||
style: {
|
||
width: NODE_WIDTH,
|
||
height: entityNodeHeight
|
||
},
|
||
draggable: true
|
||
};
|
||
//Элементы диаграммы для атрибутов сущности (состав группового элемента)
|
||
const attrsNodes = attrs.map((attr, index, attrs) => ({
|
||
id: attr.id,
|
||
type: NODE_TYPE.ATTRIBUTE,
|
||
data: { ...attr },
|
||
position: { x: 1, y: GROUP_NODE_ITEM_HEIGHT * (index + 1) },
|
||
parentId: entity.id,
|
||
extent: "parent",
|
||
style: {
|
||
width: NODE_WIDTH - 2,
|
||
height: GROUP_NODE_ITEM_HEIGHT,
|
||
...STYLES.ATTRIBUTE(index === attrs.length - 1)
|
||
},
|
||
draggable: false,
|
||
selectable: true
|
||
}));
|
||
//Возвращаем элемент для сущности (групповой) и элементы для атрибутов (состав группового)
|
||
return [entityNode, ...attrsNodes];
|
||
};
|
||
|
||
//Конвертация серверного описания запроса в данные для редактора диаграмм
|
||
const serverQueryData2QueryDiagram = (entities, relations) => {
|
||
//Инициализация результата
|
||
const result = { entities: [], relations: [], nodes: [], edges: [] };
|
||
//Сущности (почти как есть на сервере, только массив XATTRS.XATTR перемещается в attrs)
|
||
result.entities = entities.map(e => {
|
||
const tmp = { ...e };
|
||
tmp.attrs = tmp?.XATTRS?.XATTR?.map(a => ({ ...a })) || [];
|
||
delete tmp.XATTRS;
|
||
return tmp;
|
||
});
|
||
//Связи сущностей
|
||
result.relations = relations.map(r => ({ ...r }));
|
||
//Элементы для диаграммы
|
||
result.entities.forEach(entity => {
|
||
const nodes = serverEntity2QueryDiagramNodes(entity);
|
||
result.nodes = [...result.nodes, ...nodes];
|
||
});
|
||
//Грани для диаграммы
|
||
result.edges = relations.map(r => ({ ...r, animated: r.mandatory === 1 ? false : true }));
|
||
//Вернем итоговый результат
|
||
return result;
|
||
};
|
||
|
||
//-----------
|
||
//Тело модуля
|
||
//-----------
|
||
|
||
//Работа с метаданными запроса
|
||
const useQuery = query => {
|
||
//Собственное состояние - флаг инициализированности
|
||
const [isInit, setInit] = useState(false);
|
||
|
||
//Собственное состояние - флаг загрузки
|
||
const [isLoading, setLoading] = useState(false);
|
||
|
||
//Собственное состояние - флаг необходимости обновления
|
||
const [refresh, setRefresh] = useState(true);
|
||
|
||
//Собственное состояние - данные диаграммы
|
||
const [queryDiagram, setQueryDiagram] = useState(null);
|
||
|
||
//Собственное состояние - данные настроек
|
||
const [queryOption, setQueryOption] = useState(null);
|
||
|
||
//Собственное состояние - данные SQL-запроса
|
||
const [querySQL, setQuerySQL] = useState(null);
|
||
|
||
//Подключение к контексту взаимодействия с сервером
|
||
const { executeStored } = useContext(BackEndСtx);
|
||
|
||
//Обновление данных
|
||
const doRefresh = () => setRefresh(true);
|
||
|
||
//При необходимости получить/обновить данные
|
||
useEffect(() => {
|
||
//Загрузка данных с сервера
|
||
const loadData = async () => {
|
||
try {
|
||
setLoading(true);
|
||
const data = await executeStored({
|
||
stored: "PKG_P8PANELS_QE.QUERY",
|
||
args: { NRN: query },
|
||
respArg: "COUT",
|
||
isArray: name => ["XENT", "XATTR", "XRL", "XARG"].includes(name),
|
||
attributeValueProcessor: (name, val) => (["value"].includes(name) ? undefined : val),
|
||
loader: true
|
||
});
|
||
setQueryDiagram(serverQueryData2QueryDiagram(data?.XENTS?.XENT || [], data?.XRLS?.XRL || []));
|
||
setQueryOption({
|
||
args: data?.XOPT?.XARGS?.XARG || [],
|
||
cond: data?.XOPT?.XCOND || null,
|
||
substArgsVals: data?.XOPT?.XSUBST_ARGS_VALS || 0
|
||
});
|
||
setQuerySQL({ qry: data?.XQRY, qryBnd: data?.XQRY_BND, qryMsg: data?.XQRY_MSG });
|
||
setInit(true);
|
||
} finally {
|
||
setRefresh(false);
|
||
setLoading(false);
|
||
}
|
||
};
|
||
//Если надо обновить
|
||
if (refresh)
|
||
if (query)
|
||
//Если есть для чего получать данные
|
||
loadData();
|
||
//Нет идентификатора запроса - нет данных
|
||
else {
|
||
setQueryDiagram(null);
|
||
setQueryOption(null);
|
||
setQuerySQL(null);
|
||
}
|
||
}, [refresh, query, executeStored]);
|
||
|
||
//При изменении входных свойств - поднимаем флаг обновления
|
||
useEffect(() => setRefresh(true), [query]);
|
||
|
||
//Возвращаем интерфейс хука
|
||
return [queryDiagram, queryOption, querySQL, doRefresh, isLoading, isInit];
|
||
};
|
||
|
||
//----------------
|
||
//Интерфейс модуля
|
||
//----------------
|
||
|
||
export { useQuery };
|