291 lines
11 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, 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 };