forked from CITKParus/P8-Panels
291 lines
11 KiB
JavaScript
291 lines
11 KiB
JavaScript
/*
|
||
Парус 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 };
|