174 lines
7.0 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, 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 }));
//Вернем итоговый результат
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),
loader: true
});
setQueryDiagram(serverQueryData2QueryDiagram(data?.XENTS?.XENT || [], data?.XRLS?.XRL || []));
setQueryOption({ args: data?.XOPT?.XARGS?.XARG || [], cond: data?.XOPT?.XCOND || null });
setQuerySQL({ qry: data?.XQRY, 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 };