/* Парус 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 };