/* Парус 8 - Панели мониторинга - Редактор запросов Пользовательские хуки */ //--------------------- //Подключение библиотек //--------------------- import { useState, useContext, useEffect, useCallback } from "react"; //Классы React import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером import { NODE_TYPE } from "./common"; //Общие ресурсы и константы редактора //------------------------------------ //Вспомогательные функции и компоненты //------------------------------------ //Конвертация серверного описания сущностей запроса в элементы диаграммы const serverEntity2QueryDiagramNodes = entity => { const groupWidth = 250; const nameColumnHeight = 50; const columns = entity?.XATTRS?.XATTR || []; const columnsCount = columns.length; const groupHeight = nameColumnHeight + columnsCount * 50; const groupNode = { id: entity.id, type: NODE_TYPE.ENTITY, data: { ...entity }, position: { x: entity.x, y: entity.y }, style: { width: groupWidth, height: groupHeight }, draggable: true }; const columnNodes = columns.map((column, index, columns) => { const x = 1; const y = 50 * (index + 1); const width = groupWidth - 2; const height = 50; const isLast = index === columns.length - 1; const defaultColumnStyles = { borderBottom: "1px solid #dee2e6" }; const lastColumnStyles = { borderBottom: "none" }; const otherStyles = isLast ? lastColumnStyles : defaultColumnStyles; return { id: column.id, type: NODE_TYPE.ATTRIBUTE, data: { ...column, included: false, parentEntity: entity.id }, position: { x, y }, parentId: entity.id, extent: "parent", style: { width, height, ...otherStyles }, draggable: false, selectable: true }; }); return [groupNode, ...columnNodes]; }; //Конвертация серверного описания запроса в данные для редактора диаграмм const serverQueryData2QueryDiagram = (entities, relations) => { const result = { entities: [], relations: [...relations] }; entities.forEach(entity => { const nodes = serverEntity2QueryDiagramNodes(entity); result.entities = [...result.entities, ...nodes]; }); return result; }; //----------- //Тело модуля //----------- //Работа с запросами const useQuery = () => { //Собственное состояние - флаг инициализированности const [isInit, setInit] = useState(false); //Собственное состояние - флаг загрузки const [isLoading, setLoading] = useState(false); //Собственное состояние - флаг необходимости обновления const [refresh, setRefresh] = useState(true); //Собственное состояние - данные const [data, setData] = useState(null); //Подключение к контексту взаимодействия с сервером const { executeStored } = useContext(BackEndСtx); //Обновление данных const doRefresh = () => setRefresh(true); //Добавление запроса const insertQuery = useCallback( async (code, name) => { await executeStored({ stored: "PKG_P8PANELS_QE.QUERY_INSERT", args: { SCODE: code, SNAME: name }, loader: false }); setRefresh(true); }, [executeStored] ); //Изменение запроса const updateQuery = useCallback( async (query, code, name) => { await executeStored({ stored: "PKG_P8PANELS_QE.QUERY_UPDATE", args: { NRN: query, SCODE: code, SNAME: name }, loader: false }); setRefresh(true); }, [executeStored] ); //Удаление запроса const deleteQuery = useCallback( async query => { await executeStored({ stored: "PKG_P8PANELS_QE.QUERY_DELETE", args: { NRN: query }, loader: false }); setRefresh(true); }, [executeStored] ); //Установка флага готовности запроса const setQueryReady = useCallback( async (query, ready) => { await executeStored({ stored: "PKG_P8PANELS_QE.QUERY_READY_SET", args: { NRN: query, NREADY: ready }, loader: false }); setRefresh(true); }, [executeStored] ); //Установка флага публичности запроса const setQueryPbl = useCallback( async (query, pbl) => { await executeStored({ stored: "PKG_P8PANELS_QE.QUERY_PBL_SET", args: { NRN: query, NPBL: pbl }, loader: false }); setRefresh(true); }, [executeStored] ); //При необходимости получить/обновить данные useEffect(() => { //Загрузка данных с сервера const loadData = async () => { try { setLoading(true); const data = await executeStored({ stored: "PKG_P8PANELS_QE.QUERY_LIST", respArg: "COUT", isArray: name => ["XQUERY"].includes(name), attributeValueProcessor: (name, val) => (["code", "name"].includes(name) ? undefined : val), loader: true }); setData(data?.XQUERIES?.XQUERY || []); setInit(true); } finally { setRefresh(false); setLoading(false); } }; //Если надо обновить if (refresh) //Получим данные loadData(); }, [refresh, executeStored]); //Возвращаем интерфейс хука return [data, insertQuery, updateQuery, deleteQuery, setQueryReady, setQueryPbl, doRefresh, isLoading, isInit]; }; //Работа с содержимым запроса const useQueryDesc = query => { //Собственное состояние - флаг инициализированности const [isInit, setInit] = useState(false); //Собственное состояние - флаг загрузки const [isLoading, setLoading] = useState(false); //Собственное состояние - флаг необходимости обновления const [refresh, setRefresh] = useState(true); //Собственное состояние - данные const [data, setData] = useState(null); //Подключение к контексту взаимодействия с сервером const { executeStored } = useContext(BackEndСtx); //Обновление данных const doRefresh = () => setRefresh(true); //Добавление сущности в запрос const addEnt = useCallback( async (name, type) => { await executeStored({ stored: "PKG_P8PANELS_QE.QUERY_ENT_ADD", args: { NRN: query, SNAME: name, STYPE: type }, loader: false }); setRefresh(true); }, [query, executeStored] ); //Удаление сущности из запроса const removeEnt = useCallback( async ent => { await executeStored({ stored: "PKG_P8PANELS_QE.QUERY_ENT_REMOVE", args: { NRN: query, SID: ent }, loader: false }); setRefresh(true); }, [query, executeStored] ); //Сохранение координат сущности на диаграммем const setEntPosition = useCallback( async (ent, x, y) => { await executeStored({ stored: "PKG_P8PANELS_QE.QUERY_ENT_POSITION_SET", args: { NRN: query, SID: ent, NX: x, NY: y }, loader: false }); }, [query, executeStored] ); //Добавление отношения сущностей в запрос const addRl = useCallback( async (source, target) => { await executeStored({ stored: "PKG_P8PANELS_QE.QUERY_RL_ADD", args: { NRN: query, SSOURCE: source, STARGET: target }, loader: false }); setRefresh(true); }, [query, executeStored] ); //Удаление отношения сущностей из запроса const removeRl = useCallback( async rl => { await executeStored({ stored: "PKG_P8PANELS_QE.QUERY_RL_REMOVE", args: { NRN: query, SID: rl }, loader: false }); setRefresh(true); }, [query, executeStored] ); //При необходимости получить/обновить данные useEffect(() => { //Загрузка данных с сервера const loadData = async () => { try { setLoading(true); const data = await executeStored({ stored: "PKG_P8PANELS_QE.QUERY_DESC", args: { NRN: query }, respArg: "COUT", isArray: name => ["XENT", "XATTR", "XRL"].includes(name), loader: true }); setData(serverQueryData2QueryDiagram(data?.XENTS?.XENT || [], data?.XRLS?.XRL || [])); setInit(true); } finally { setRefresh(false); setLoading(false); } }; //Если надо обновить if (refresh) if (query) //Если есть для чего получать данные loadData(); //Нет идентификатора запроса - нет данных else setData(null); }, [refresh, query, executeStored]); //При изменении входных свойств - поднимаем флаг обновления useEffect(() => setRefresh(true), [query]); //Возвращаем интерфейс хука return [data, addEnt, removeEnt, setEntPosition, addRl, removeRl, doRefresh, isLoading, isInit]; }; //---------------- //Интерфейс модуля //---------------- export { useQuery, useQueryDesc };