P8-Panels/app/panels/query_editor/query_editor.js

204 lines
8.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 React, { useState, useContext } from "react"; //Классы React
import { Box, Grid } from "@mui/material"; //Интерфейсные компоненты MUI
import { ApplicationСtx } from "../../context/application"; //Контекст взаимодействия с приложением
import { APP_BAR_HEIGHT } from "../../components/p8p_app_workspace"; //Компоненты рабочего стола
import { P8PEditorToolBar } from "../../components/editors/p8p_editor_toolbar"; //Панель инструментов редактора
import { QueryDiagram } from "./components/query_diagram/query_diagram"; //Диаграмма запроса
import { Inspector } from "./components/inspector/inspector"; //Инспектор свойств
import { QueriesManager } from "./components/queries_manager/queries_manager"; //Менеджер запросов
import { useQuery } from "./hooks"; //Хуки для работы с метаданными запроса на сервере
import { useQueryRelations } from "./components/inspector_query_rls/hooks"; //Хуки для работы со связями запроса на сервере
import { useQueryEntities } from "./components/inspector_query_ents/hooks"; //Хуки для работы с сущностями запроса на сервере
//---------
//Константы
//---------
//Заголовок панели по умолчанию
const APP_BAR_TITLE_DEFAULT = "Редактор запросов";
//Стили
const STYLES = {
CONTAINER: { display: "flex" },
GRID_CONTAINER: { height: `calc(100vh - ${APP_BAR_HEIGHT})` },
GRID_ITEM_INSPECTOR: { backgroundColor: "#e9ecef" }
};
//-----------
//Тело модуля
//-----------
//Корневой компонент редактора запросов
const QueryEditor = () => {
//Текущий запрос
const [query, setQuery] = useState(null);
//Текущая сущность
const [entity, setEntity] = useState(null);
//Текущая связь
const [relation, setRelation] = useState(null);
//Отображения менеджера запросов
const [openQueriesManager, setOpenQueriesManager] = useState(true);
//Получение метаданных с описанием запроса
const [queryDiagram, queryOption, querySQL, doRefresh] = useQuery(query);
//Работа с сущностями на сервере
const { removeEnt, setEntPosition } = useQueryEntities(query);
//Работа со связями на сервере
const { addRl, removeRl } = useQueryRelations(query);
//Подключение к контексту приложения
const { setAppBarTitle } = useContext(ApplicationСtx);
//Выбор сущности
const selectEntity = ent => {
setRelation(null);
const queryEnt = queryDiagram.entities.find(e => e.id === ent);
if (queryEnt) setEntity({ ...queryEnt });
};
//Выбор связи
const selectRelation = rl => {
setEntity(null);
const queryRl = queryDiagram.relations.find(r => r.id === rl);
if (queryRl) setRelation({ ...queryRl });
};
//Сброс выбора связи и сущности
const cleanupEnRlSelection = () => {
setRelation(null);
setEntity(null);
};
//Обработка изменения положения сущности на диаграмме
const handleEntityPositionChange = (ent, position) => setEntPosition(ent, position.x, position.y);
//Обработка удаления сущности из запроса
const handleEntityRemove = async ent => {
await removeEnt(ent);
if (entity && entity?.id === ent) cleanupEnRlSelection();
doRefresh();
};
//Обработка выделения сущности
const handleEntityClick = ent => selectEntity(ent);
//Обработка выделения тарибута сущности
const handleEntityAttrClick = ent => selectEntity(ent);
//Обработка выделения связи
const handleRelationClick = rl => selectRelation(rl);
//Обработка добавления отношения cущностей
const handleRelationAdd = async (source, target) => {
cleanupEnRlSelection();
await addRl(source, target);
doRefresh();
};
//Обработка удаления отношения cущностей
const handleRelationRemove = async rl => {
await removeRl(rl);
if (relation && relation?.id === rl) cleanupEnRlSelection();
doRefresh();
};
//При нажатии на панели (пустом месте) диаграммы запроса
const handlePaneClick = () => cleanupEnRlSelection();
//Открытие менеджера запросов
const handleOpenQueriesManager = () => setOpenQueriesManager(true);
//Закрытие менеджера запросов
const handleCancelQueriesManager = () => setOpenQueriesManager(false);
//Закрытие запроса
const handleQueryClose = () => {
setAppBarTitle(APP_BAR_TITLE_DEFAULT);
cleanupEnRlSelection();
setQuery(null);
};
//При выборе запроса
const handleQuerySelect = ({ rn, name }) => {
setAppBarTitle(`Запрос [${name}]`);
setQuery(rn);
setOpenQueriesManager(false);
cleanupEnRlSelection();
};
//При изменении свойств запроса
const handleQueryOptionsChanged = () => {
cleanupEnRlSelection();
doRefresh();
};
//Панель инструмментов
const toolBar = (
<P8PEditorToolBar
items={[
{ icon: "file_open", title: "Менеджер запросов", onClick: handleOpenQueriesManager },
{ icon: "close", title: "Закрыть запрос", onClick: handleQueryClose, disabled: !query }
]}
/>
);
//Генерация содержимого
return (
<Box sx={STYLES.CONTAINER}>
{openQueriesManager && <QueriesManager current={query} onQuerySelect={handleQuerySelect} onCancel={handleCancelQueriesManager} />}
<Grid container sx={STYLES.GRID_CONTAINER} columns={25}>
<Grid item xs={20}>
{queryDiagram && (
<QueryDiagram
nodes={queryDiagram?.nodes}
edges={queryDiagram?.edges}
onEntityClick={handleEntityClick}
onEntityAttrClick={handleEntityAttrClick}
onEntityPositionChange={handleEntityPositionChange}
onEntityRemove={handleEntityRemove}
onRelactionClick={handleRelationClick}
onRelationAdd={handleRelationAdd}
onRelationRemove={handleRelationRemove}
onPaneClick={handlePaneClick}
/>
)}
</Grid>
<Grid item xs={5} sx={STYLES.GRID_ITEM_INSPECTOR}>
{toolBar}
{query && (
<Inspector
{...queryOption}
{...querySQL}
query={query}
entity={entity}
relation={relation}
entities={queryDiagram?.entities}
onOptionsChanged={handleQueryOptionsChanged}
/>
)}
</Grid>
</Grid>
</Box>
);
};
//----------------
//Интерфейс модуля
//----------------
export { QueryEditor };