forked from CITKParus/P8-Panels
ЦИТК-979 - Рефакторинг понятий Сущность, Атрибут, Отношение, Элемент диаграммы, Связь диаграммы
This commit is contained in:
parent
86aa639ca0
commit
7515a9cce3
@ -51,9 +51,9 @@ const STYLES = {
|
||||
const ICONS = { ...DATA_TYPE_ICON, DEFAULT: "category" };
|
||||
|
||||
//Структура данных об атрибуте сущности
|
||||
const ATTRIBUTE_DATA_SHAPE = PropTypes.shape({
|
||||
const ATTRIBUTE_SHAPE = PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
parentEntity: PropTypes.string,
|
||||
parentEntity: PropTypes.string.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
dataType: PropTypes.oneOf(Object.values(DATA_TYPE)),
|
||||
@ -136,11 +136,11 @@ const Attribute = ({ data }) => {
|
||||
|
||||
//Контроль свойств компонента - Атрибут сущности
|
||||
Attribute.propTypes = {
|
||||
data: ATTRIBUTE_DATA_SHAPE
|
||||
data: ATTRIBUTE_SHAPE
|
||||
};
|
||||
|
||||
//----------------
|
||||
//Интерфейс модуля
|
||||
//----------------
|
||||
|
||||
export { Attribute, ATTRIBUTE_DATA_SHAPE, attrGetUse, attrGetShow };
|
||||
export { Attribute, ATTRIBUTE_SHAPE, attrGetUse, attrGetShow };
|
||||
|
||||
@ -10,16 +10,20 @@
|
||||
import React from "react"; //Классы React
|
||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||||
import "./entity.css"; //Стили компомнента
|
||||
import { ATTRIBUTE_SHAPE } from "../attribute/attribute"; //Описание атрибута сущности
|
||||
|
||||
//---------
|
||||
//Константы
|
||||
//---------
|
||||
|
||||
//Структура данных о сущности запроса
|
||||
const ENTITY_DATA_SHAPE = PropTypes.shape({
|
||||
const ENTITY_SHAPE = PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
title: PropTypes.string.isRequired
|
||||
title: PropTypes.string.isRequired,
|
||||
x: PropTypes.number.isRequired,
|
||||
y: PropTypes.number.isRequired,
|
||||
attrs: PropTypes.arrayOf(ATTRIBUTE_SHAPE).isRequired
|
||||
});
|
||||
|
||||
//-----------
|
||||
@ -40,12 +44,12 @@ const Entity = ({ data, selected = false }) => {
|
||||
|
||||
//Контроль свойств компонента - Сущность запроса
|
||||
Entity.propTypes = {
|
||||
data: ENTITY_DATA_SHAPE,
|
||||
selected: PropTypes.bool.isRequired
|
||||
data: ENTITY_SHAPE.isRequired,
|
||||
selected: PropTypes.bool
|
||||
};
|
||||
|
||||
//----------------
|
||||
//Интерфейс модуля
|
||||
//----------------
|
||||
|
||||
export { Entity, ENTITY_DATA_SHAPE };
|
||||
export { Entity, ENTITY_SHAPE };
|
||||
|
||||
@ -11,8 +11,8 @@ import React from "react"; //Классы React
|
||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||||
import { P8PEditorBox } from "../../../../components/editors/p8p_editor_box"; //Контейнер параметров редактора
|
||||
import { P8PEditorSubHeader } from "../../../../components/editors/p8p_editor_sub_header"; //Подзаголовок группы параметров редактора
|
||||
import { ENTITY_DATA_SHAPE } from "../entity/entity"; //Описание сущности
|
||||
import { RELATION_DATA_SHAPE } from "../relation/relation"; //Описание связи
|
||||
import { ENTITY_SHAPE } from "../entity/entity"; //Описание сущности
|
||||
import { RELATION_SHAPE } from "../relation/relation"; //Описание связи
|
||||
import { ARGUMENT_SHAPE } from "../argument/argument"; //Описание аргумента запроса
|
||||
import { InspectorQueryArguments } from "../inspector_query_args/inspector_query_args"; //Управление аргументами запроса
|
||||
import { InspectorQueryConditions } from "../inspector_query_cond/inspector_query_cond"; //Управление условиями отбора запроса
|
||||
@ -24,7 +24,7 @@ import { InspectorQueryRelations } from "../inspector_query_rls/inspector_query_
|
||||
//-----------
|
||||
|
||||
//Инспектор свойств
|
||||
const Inspector = ({ query, entity, relation, args = [], cond = null, onOptionsChanged = null }) => {
|
||||
const Inspector = ({ query, entity, relation, entities = [], args = [], cond = null, onOptionsChanged = null }) => {
|
||||
//При изменении настроек запроса
|
||||
const handleOptionsChanged = () => onOptionsChanged && onOptionsChanged();
|
||||
|
||||
@ -34,7 +34,7 @@ const Inspector = ({ query, entity, relation, args = [], cond = null, onOptionsC
|
||||
<P8PEditorSubHeader title={"Аргументы"} />
|
||||
<InspectorQueryArguments query={query} args={args} onOptionsChanged={handleOptionsChanged} />
|
||||
<P8PEditorSubHeader title={"Условия отбора"} />
|
||||
<InspectorQueryConditions query={query} cond={cond} onOptionsChanged={handleOptionsChanged} />
|
||||
<InspectorQueryConditions query={query} cond={cond} entities={entities} args={args} onOptionsChanged={handleOptionsChanged} />
|
||||
<P8PEditorSubHeader title={"Сущности"} />
|
||||
<InspectorQueryEntities query={query} entity={entity} onOptionsChanged={handleOptionsChanged} />
|
||||
{relation && (
|
||||
@ -50,8 +50,9 @@ const Inspector = ({ query, entity, relation, args = [], cond = null, onOptionsC
|
||||
//Контроль свойств компонента - Инспектор свойств
|
||||
Inspector.propTypes = {
|
||||
query: PropTypes.number.isRequired,
|
||||
entity: ENTITY_DATA_SHAPE,
|
||||
relation: RELATION_DATA_SHAPE,
|
||||
entity: ENTITY_SHAPE,
|
||||
relation: RELATION_SHAPE,
|
||||
entities: PropTypes.arrayOf(ENTITY_SHAPE),
|
||||
args: PropTypes.arrayOf(ARGUMENT_SHAPE),
|
||||
cond: PropTypes.string,
|
||||
onOptionsChanged: PropTypes.func
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
import React from "react"; //Классы React
|
||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||||
import { Stack, List, ListItem, IconButton, Icon, ListItemButton, ListItemText, ListItemIcon, Checkbox, Typography } from "@mui/material"; //Интерфейсные компоненты MUI
|
||||
import { ATTRIBUTE_DATA_SHAPE, attrGetUse, attrGetShow } from "../attribute/attribute"; //Атрибут сущности
|
||||
import { ATTRIBUTE_SHAPE, attrGetUse, attrGetShow } from "../attribute/attribute"; //Атрибут сущности
|
||||
import { APP_STYLES } from "../../../../../app.styles"; //Общие стили приложения
|
||||
|
||||
//---------
|
||||
@ -84,7 +84,7 @@ const AttrsList = ({ attrs = [], filter, onSelect = null, onShow = null } = {})
|
||||
|
||||
//Контроль свойств компонента - Список атрибутов сущности
|
||||
AttrsList.propTypes = {
|
||||
attrs: PropTypes.arrayOf(ATTRIBUTE_DATA_SHAPE),
|
||||
attrs: PropTypes.arrayOf(ATTRIBUTE_SHAPE),
|
||||
filter: PropTypes.string,
|
||||
onSelect: PropTypes.func,
|
||||
onShow: PropTypes.func
|
||||
|
||||
@ -13,7 +13,7 @@ import { Icon, Button } from "@mui/material"; //Интерфейсные эле
|
||||
import { MessagingСtx } from "../../../../context/messaging"; //Контекст сообщений приложения
|
||||
import { P8PEditorSubHeader } from "../../../../components/editors/p8p_editor_sub_header"; //Подзаголовок группы параметров редактора
|
||||
import { BUTTONS } from "../../../../../app.text"; //Общие текстовые ресурсы
|
||||
import { ENTITY_DATA_SHAPE } from "../entity/entity"; //Описание сущности
|
||||
import { ENTITY_SHAPE } from "../entity/entity"; //Описание сущности
|
||||
import { EntityAddDialog } from "./entity_add_dialog"; //Диалог добавления сущности
|
||||
import { EntityAttrsDialog } from "./entity_attrs_dialog"; //Диалог настройки атрибутов сущности
|
||||
import { useQueryEntities } from "./hooks"; //Хуки для работы с сущностями на сервере
|
||||
@ -101,7 +101,7 @@ const InspectorQueryEntities = ({ query, entity, onOptionsChanged }) => {
|
||||
//Контроль свойств компонента - Компонент инспектора - Сущности запроса
|
||||
InspectorQueryEntities.propTypes = {
|
||||
query: PropTypes.number.isRequired,
|
||||
entity: ENTITY_DATA_SHAPE,
|
||||
entity: ENTITY_SHAPE,
|
||||
onOptionsChanged: PropTypes.func
|
||||
};
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ import PropTypes from "prop-types"; //Контроль свойств компо
|
||||
import { Icon, Button } from "@mui/material"; //Интерфейсные элементы
|
||||
import { MessagingСtx } from "../../../../context/messaging"; //Контекст сообщений приложения
|
||||
import { BUTTONS } from "../../../../../app.text"; //Общие текстовые ресурсы
|
||||
import { RELATION_DATA_SHAPE } from "../relation/relation"; //Описание связи
|
||||
import { RELATION_SHAPE } from "../relation/relation"; //Описание связи
|
||||
import { useQueryRelations } from "./hooks"; //Хуки для работы со связями
|
||||
|
||||
//-----------
|
||||
@ -50,7 +50,7 @@ const InspectorQueryRelations = ({ query, relation, onOptionsChanged }) => {
|
||||
//Контроль свойств компонента - Компонент инспектора - Связи запроса
|
||||
InspectorQueryRelations.propTypes = {
|
||||
query: PropTypes.number.isRequired,
|
||||
relation: RELATION_DATA_SHAPE.isRequired,
|
||||
relation: RELATION_SHAPE.isRequired,
|
||||
onOptionsChanged: PropTypes.func
|
||||
};
|
||||
|
||||
|
||||
@ -11,8 +11,8 @@ import React, { useState, useCallback, useEffect } from "react"; //Классы
|
||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||||
import ReactFlow, { addEdge, Controls, getOutgoers, applyNodeChanges, applyEdgeChanges } from "reactflow"; //Библиотека редактора диаграмм
|
||||
import { NODE_TYPE } from "../../common"; //Общие ресурсы и константы редактора
|
||||
import { Entity, ENTITY_DATA_SHAPE } from "../entity/entity"; //Сущность запроса
|
||||
import { Attribute, ATTRIBUTE_DATA_SHAPE } from "../attribute/attribute"; //Атрибут сущности
|
||||
import { Entity, ENTITY_SHAPE } from "../entity/entity"; //Сущность запроса
|
||||
import { Attribute, ATTRIBUTE_SHAPE } from "../attribute/attribute"; //Атрибут сущности
|
||||
import "reactflow/dist/style.css"; //Типовые стили библиотеки редактора диаграмм
|
||||
import "./query_diagram.css"; //Стили компонента
|
||||
|
||||
@ -37,18 +37,18 @@ const NODE_TYPES_COMPONENTS = {
|
||||
[NODE_TYPE.ATTRIBUTE]: Attribute
|
||||
};
|
||||
|
||||
//Структура сущности запроса
|
||||
const ENTITY_SHAPE = PropTypes.shape({
|
||||
//Структура элемента диаграммы
|
||||
const NODE_SHAPE = PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
type: PropTypes.oneOf([NODE_TYPE.ENTITY, NODE_TYPE.ATTRIBUTE]).isRequired,
|
||||
style: PropTypes.object,
|
||||
position: PropTypes.shape({ x: PropTypes.number.isRequired, y: PropTypes.number.isRequired }),
|
||||
draggable: PropTypes.bool.isRequired,
|
||||
data: PropTypes.oneOfType([ENTITY_DATA_SHAPE, ATTRIBUTE_DATA_SHAPE])
|
||||
data: PropTypes.oneOfType([ENTITY_SHAPE, ATTRIBUTE_SHAPE])
|
||||
});
|
||||
|
||||
//Структура связи запроса
|
||||
const RELATION_SHAPE = PropTypes.shape({ id: PropTypes.string.isRequired, source: PropTypes.string.isRequired, target: PropTypes.string.isRequired });
|
||||
//Структура связи диаграммы
|
||||
const EDGE_SHAPE = PropTypes.shape({ id: PropTypes.string.isRequired, source: PropTypes.string.isRequired, target: PropTypes.string.isRequired });
|
||||
|
||||
//------------------------------------
|
||||
//Вспомогательные функции и компоненты
|
||||
@ -88,8 +88,8 @@ const isValidConnection = (connection, nodes, edges) => {
|
||||
|
||||
//Диаграмма запроса
|
||||
const QueryDiagram = ({
|
||||
entities = [],
|
||||
relations = [],
|
||||
nodes = [],
|
||||
edges = [],
|
||||
onEntityClick,
|
||||
onEntityAttrClick,
|
||||
onEntityPositionChange,
|
||||
@ -100,10 +100,10 @@ const QueryDiagram = ({
|
||||
onPaneClick
|
||||
}) => {
|
||||
//Собственное состояние - элементы
|
||||
const [nodes, setNodes] = useState(entities);
|
||||
const [nodesCurrent, setNodesCurrent] = useState(nodes);
|
||||
|
||||
//Собственное состояние - связи
|
||||
const [edges, setEdges] = useState(relations);
|
||||
const [edgesCurrent, setEdgesCurrent] = useState(edges);
|
||||
|
||||
//Собственное состояние - перемещённый элемент
|
||||
const [movedNode, setMovedNode] = useState(null);
|
||||
@ -115,7 +115,7 @@ const QueryDiagram = ({
|
||||
const tmpChanges = changes.reduce((prevChanges, curChanges) => {
|
||||
const tmp = { ...curChanges };
|
||||
if (tmp.type == "select") {
|
||||
const chEnt = entities.find(e => e.id === tmp.id);
|
||||
const chEnt = nodes.find(n => n.id === tmp.id);
|
||||
if (chEnt && chEnt?.data?.parentEntity) {
|
||||
prevChanges.push({ ...curChanges, id: chEnt.data.parentEntity });
|
||||
tmp.selected = false;
|
||||
@ -125,7 +125,7 @@ const QueryDiagram = ({
|
||||
return prevChanges;
|
||||
}, []);
|
||||
//Применим изменения в диаграмме
|
||||
setNodes(nodesSnapshot => applyNodeChanges(tmpChanges, nodesSnapshot));
|
||||
setNodesCurrent(nodesSnapshot => applyNodeChanges(tmpChanges, nodesSnapshot));
|
||||
//Если двигали сущность - запомним начало движения
|
||||
if (changes.length == 1 && changes[0].type == "position" && changes[0].dragging)
|
||||
setMovedNode({ id: changes[0].id, position: { ...changes[0].position } });
|
||||
@ -136,10 +136,10 @@ const QueryDiagram = ({
|
||||
setMovedNode(null);
|
||||
}
|
||||
//Если удалили сущность - вызываем колбэк для удаления
|
||||
if (changes[0].type == "remove" && entities.find(e => e.id == changes[0].id && e.type == NODE_TYPE.ENTITY) && onEntityRemove)
|
||||
if (changes[0].type == "remove" && nodes.find(n => n.id == changes[0].id && n.type == NODE_TYPE.ENTITY) && onEntityRemove)
|
||||
onEntityRemove(changes[0].id);
|
||||
},
|
||||
[movedNode, entities, onEntityClick, onEntityPositionChange, onEntityRemove]
|
||||
[movedNode, nodes, onEntityClick, onEntityPositionChange, onEntityRemove]
|
||||
);
|
||||
|
||||
//При выборе элемента диаграммы
|
||||
@ -153,7 +153,7 @@ const QueryDiagram = ({
|
||||
|
||||
//При связывании элементов на диаграмме
|
||||
const handleConnect = connection => {
|
||||
setEdges(state => addEdge({ ...connection, id: `${connection.source}-${connection.target}` }, state));
|
||||
setEdgesCurrent(state => addEdge({ ...connection, id: `${connection.source}-${connection.target}` }, state));
|
||||
onRelationAdd && onRelationAdd(connection.source, connection.target);
|
||||
};
|
||||
|
||||
@ -163,7 +163,7 @@ const QueryDiagram = ({
|
||||
//При изменении связей на диаграмме
|
||||
const handleEdgesChange = useCallback(
|
||||
changes => {
|
||||
setEdges(edgesSnapshot => applyEdgeChanges(changes, edgesSnapshot));
|
||||
setEdgesCurrent(edgesSnapshot => applyEdgeChanges(changes, edgesSnapshot));
|
||||
if (changes.length == 1 && changes[0].type == "remove" && onRelationRemove) onRelationRemove(changes[0].id);
|
||||
},
|
||||
[onRelationRemove]
|
||||
@ -173,22 +173,22 @@ const QueryDiagram = ({
|
||||
const handlePaneClick = () => onPaneClick && onPaneClick();
|
||||
|
||||
//Валидация связи
|
||||
const validateConnection = connection => isValidConnection(connection, nodes, edges);
|
||||
const validateConnection = connection => isValidConnection(connection, nodesCurrent, edgesCurrent);
|
||||
|
||||
//Подсветка выбранной сущности
|
||||
|
||||
//При изменении состава сущностей
|
||||
useEffect(() => setNodes(entities), [entities]);
|
||||
useEffect(() => setNodesCurrent(nodes), [nodes]);
|
||||
|
||||
//При изменении состава связей
|
||||
useEffect(() => setEdges(relations), [relations]);
|
||||
useEffect(() => setEdgesCurrent(edges), [edges]);
|
||||
|
||||
//Генерация содержимого
|
||||
return (
|
||||
<ReactFlow
|
||||
nodes={nodes}
|
||||
nodes={nodesCurrent}
|
||||
nodeTypes={NODE_TYPES_COMPONENTS}
|
||||
edges={edges}
|
||||
edges={edgesCurrent}
|
||||
onNodeClick={handleNodeClick}
|
||||
onNodesChange={handleNodesChange}
|
||||
onEdgeClick={handleEdgeClick}
|
||||
@ -210,8 +210,8 @@ const QueryDiagram = ({
|
||||
|
||||
//Контроль свойств компонента - Диаграмма запроса
|
||||
QueryDiagram.propTypes = {
|
||||
entities: PropTypes.arrayOf(ENTITY_SHAPE),
|
||||
relations: PropTypes.arrayOf(RELATION_SHAPE),
|
||||
nodes: PropTypes.arrayOf(NODE_SHAPE),
|
||||
edges: PropTypes.arrayOf(EDGE_SHAPE),
|
||||
onEntityClick: PropTypes.func,
|
||||
onEntityAttrClick: PropTypes.func,
|
||||
onEntityPositionChange: PropTypes.func,
|
||||
|
||||
@ -14,7 +14,7 @@ import PropTypes from "prop-types"; //Контроль свойств компо
|
||||
//---------
|
||||
|
||||
//Структура данных о связи сущностей запроса
|
||||
const RELATION_DATA_SHAPE = PropTypes.shape({
|
||||
const RELATION_SHAPE = PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
source: PropTypes.string.isRequired,
|
||||
target: PropTypes.string.isRequired
|
||||
@ -24,4 +24,4 @@ const RELATION_DATA_SHAPE = PropTypes.shape({
|
||||
//Интерфейс модуля
|
||||
//----------------
|
||||
|
||||
export { RELATION_DATA_SHAPE };
|
||||
export { RELATION_SHAPE };
|
||||
|
||||
@ -11,76 +11,86 @@ 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 groupWidth = 250;
|
||||
const nameColumnHeight = 50;
|
||||
const columns = entity?.XATTRS?.XATTR || [];
|
||||
const columnsCount = columns.length;
|
||||
const groupHeight = nameColumnHeight + columnsCount * 50;
|
||||
|
||||
const groupNode = {
|
||||
//Ссылка на атрибуты
|
||||
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: groupWidth,
|
||||
height: groupHeight
|
||||
width: NODE_WIDTH,
|
||||
height: entityNodeHeight
|
||||
},
|
||||
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 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: [...relations] };
|
||||
entities.forEach(entity => {
|
||||
const nodes = serverEntity2QueryDiagramNodes(entity);
|
||||
result.entities = [...result.entities, ...nodes];
|
||||
//Инициализация результата
|
||||
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 }));
|
||||
//Вернем итоговый результат
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
@ -67,7 +67,7 @@ const QueryEditor = () => {
|
||||
const selectEntity = ent => {
|
||||
setRelation(null);
|
||||
const queryEnt = queryDiagram.entities.find(e => e.id === ent);
|
||||
if (queryEnt) setEntity({ ...queryEnt.data });
|
||||
if (queryEnt) setEntity({ ...queryEnt });
|
||||
};
|
||||
|
||||
//Выбор связи
|
||||
@ -137,6 +137,7 @@ const QueryEditor = () => {
|
||||
setAppBarTitle(`Запрос [${name}]`);
|
||||
setQuery(rn);
|
||||
setOpenQueriesManager(false);
|
||||
cleanupEnRlSelection();
|
||||
};
|
||||
|
||||
//При изменении свойств запроса
|
||||
@ -163,7 +164,8 @@ const QueryEditor = () => {
|
||||
<Grid item xs={20}>
|
||||
{queryDiagram && (
|
||||
<QueryDiagram
|
||||
{...queryDiagram}
|
||||
nodes={queryDiagram?.nodes}
|
||||
edges={queryDiagram?.edges}
|
||||
onEntityClick={handleEntityClick}
|
||||
onEntityAttrClick={handleEntityAttrClick}
|
||||
onEntityPositionChange={handleEntityPositionChange}
|
||||
@ -178,7 +180,14 @@ const QueryEditor = () => {
|
||||
<Grid item xs={5} sx={STYLES.GRID_ITEM_INSPECTOR}>
|
||||
{toolBar}
|
||||
{query && (
|
||||
<Inspector {...queryOption} query={query} entity={entity} relation={relation} onOptionsChanged={handleQueryOptionsChanged} />
|
||||
<Inspector
|
||||
{...queryOption}
|
||||
query={query}
|
||||
entity={entity}
|
||||
relation={relation}
|
||||
entities={queryDiagram?.entities}
|
||||
onOptionsChanged={handleQueryOptionsChanged}
|
||||
/>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@ -23,6 +23,7 @@ create or replace package PKG_P8PANELS_QE_BASE as
|
||||
type TATTR is record
|
||||
(
|
||||
SID PKG_STD.TSTRING, -- Уникальный идентификатор в запросе
|
||||
SPARENT_ENTITY PKG_STD.TSTRING, -- Идентификатор родительской сущности
|
||||
SNAME PKG_STD.TSTRING, -- Имя
|
||||
STITLE PKG_STD.TSTRING, -- Заголовок
|
||||
NDATA_TYPE PKG_STD.TNUMBER, -- Тип данных (см. константы PKG_STD.DATA_TYPE_*)
|
||||
@ -310,27 +311,28 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
||||
STAG_COND constant PKG_STD.TSTRING := 'XCOND'; -- Условия запроса
|
||||
|
||||
/* Константы - Атрибуты для сериализации */
|
||||
SATTR_ID constant PKG_STD.TSTRING := 'id'; -- Идентификатор
|
||||
SATTR_RN constant PKG_STD.TSTRING := 'rn'; -- Регистрационный номер
|
||||
SATTR_CODE constant PKG_STD.TSTRING := 'code'; -- Код
|
||||
SATTR_NAME constant PKG_STD.TSTRING := 'name'; -- Имя
|
||||
SATTR_AUTHOR constant PKG_STD.TSTRING := 'author'; -- Автор
|
||||
SATTR_CH_DATE constant PKG_STD.TSTRING := 'chDate'; -- Дата изменения
|
||||
SATTR_READY constant PKG_STD.TSTRING := 'ready'; -- Готовность к использованию
|
||||
SATTR_PBL constant PKG_STD.TSTRING := 'pbl'; -- Публичность
|
||||
SATTR_MODIFY constant PKG_STD.TSTRING := 'modify'; -- Изменяемость
|
||||
SATTR_TITLE constant PKG_STD.TSTRING := 'title'; -- Заголовок
|
||||
SATTR_TYPE constant PKG_STD.TSTRING := 'type'; -- Тип
|
||||
SATTR_DATA_TYPE constant PKG_STD.TSTRING := 'dataType'; -- Тип данных
|
||||
SATTR_MANDATORY constant PKG_STD.TSTRING := 'mandatory'; -- Обязательность
|
||||
SATTR_X constant PKG_STD.TSTRING := 'x'; -- Координата по X
|
||||
SATTR_Y constant PKG_STD.TSTRING := 'y'; -- Координата по Y
|
||||
SATTR_SOURCE constant PKG_STD.TSTRING := 'source'; -- Источник
|
||||
SATTR_TARGET constant PKG_STD.TSTRING := 'target'; -- Приёмник
|
||||
SATTR_AGG constant PKG_STD.TSTRING := 'agg'; -- Агрегатная функция
|
||||
SATTR_ALIAS constant PKG_STD.TSTRING := 'alias'; -- Псевдоним
|
||||
SATTR_USE constant PKG_STD.TSTRING := 'use'; -- Применение в запросе
|
||||
SATTR_SHOW constant PKG_STD.TSTRING := 'show'; -- Отображение в запросе
|
||||
SATTR_ID constant PKG_STD.TSTRING := 'id'; -- Идентификатор
|
||||
SATTR_RN constant PKG_STD.TSTRING := 'rn'; -- Регистрационный номер
|
||||
SATTR_CODE constant PKG_STD.TSTRING := 'code'; -- Код
|
||||
SATTR_NAME constant PKG_STD.TSTRING := 'name'; -- Имя
|
||||
SATTR_AUTHOR constant PKG_STD.TSTRING := 'author'; -- Автор
|
||||
SATTR_CH_DATE constant PKG_STD.TSTRING := 'chDate'; -- Дата изменения
|
||||
SATTR_READY constant PKG_STD.TSTRING := 'ready'; -- Готовность к использованию
|
||||
SATTR_PBL constant PKG_STD.TSTRING := 'pbl'; -- Публичность
|
||||
SATTR_MODIFY constant PKG_STD.TSTRING := 'modify'; -- Изменяемость
|
||||
SATTR_TITLE constant PKG_STD.TSTRING := 'title'; -- Заголовок
|
||||
SATTR_TYPE constant PKG_STD.TSTRING := 'type'; -- Тип
|
||||
SATTR_DATA_TYPE constant PKG_STD.TSTRING := 'dataType'; -- Тип данных
|
||||
SATTR_MANDATORY constant PKG_STD.TSTRING := 'mandatory'; -- Обязательность
|
||||
SATTR_X constant PKG_STD.TSTRING := 'x'; -- Координата по X
|
||||
SATTR_Y constant PKG_STD.TSTRING := 'y'; -- Координата по Y
|
||||
SATTR_SOURCE constant PKG_STD.TSTRING := 'source'; -- Источник
|
||||
SATTR_TARGET constant PKG_STD.TSTRING := 'target'; -- Приёмник
|
||||
SATTR_AGG constant PKG_STD.TSTRING := 'agg'; -- Агрегатная функция
|
||||
SATTR_ALIAS constant PKG_STD.TSTRING := 'alias'; -- Псевдоним
|
||||
SATTR_USE constant PKG_STD.TSTRING := 'use'; -- Применение в запросе
|
||||
SATTR_SHOW constant PKG_STD.TSTRING := 'show'; -- Отображение в запросе
|
||||
SATTR_PARENT_ENTITY constant PKG_STD.TSTRING := 'parentEntity'; -- Идентификатор родительской сущности
|
||||
|
||||
/* Константы - зарезервированные имена рагументов */
|
||||
SARG_NAME_PAGE constant PKG_STD.TSTRING := 'NPAGE'; -- Номер страницы
|
||||
@ -767,6 +769,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
||||
PKG_XFAST.DOWN_NODE(SNAME => STAG_ATTR);
|
||||
/* Атрибут */
|
||||
PKG_XFAST.ATTR(SNAME => SATTR_ID, SVALUE => RATTR.SID);
|
||||
PKG_XFAST.ATTR(SNAME => SATTR_PARENT_ENTITY, SVALUE => RATTR.SPARENT_ENTITY);
|
||||
PKG_XFAST.ATTR(SNAME => SATTR_NAME, SVALUE => RATTR.SNAME);
|
||||
PKG_XFAST.ATTR(SNAME => SATTR_TITLE, SVALUE => RATTR.STITLE);
|
||||
PKG_XFAST.ATTR(SNAME => SATTR_DATA_TYPE, NVALUE => RATTR.NDATA_TYPE);
|
||||
@ -798,14 +801,15 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
||||
XROOT := PKG_XPATH.ROOT_NODE(RDOCUMENT => XDOC);
|
||||
XNODE := PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XROOT, SPATTERN => '/' || STAG_ATTR);
|
||||
/* Получаем значения */
|
||||
RRES.SID := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_ID);
|
||||
RRES.SNAME := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_NAME);
|
||||
RRES.STITLE := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_TITLE);
|
||||
RRES.NDATA_TYPE := PKG_XPATH.ATTRIBUTE_NUM(RNODE => XNODE, SNAME => SATTR_DATA_TYPE);
|
||||
RRES.SAGG := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_AGG);
|
||||
RRES.SALIAS := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_ALIAS);
|
||||
RRES.NUSE := PKG_XPATH.ATTRIBUTE_NUM(RNODE => XNODE, SNAME => SATTR_USE);
|
||||
RRES.NSHOW := PKG_XPATH.ATTRIBUTE_NUM(RNODE => XNODE, SNAME => SATTR_SHOW);
|
||||
RRES.SID := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_ID);
|
||||
RRES.SPARENT_ENTITY := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_PARENT_ENTITY);
|
||||
RRES.SNAME := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_NAME);
|
||||
RRES.STITLE := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_TITLE);
|
||||
RRES.NDATA_TYPE := PKG_XPATH.ATTRIBUTE_NUM(RNODE => XNODE, SNAME => SATTR_DATA_TYPE);
|
||||
RRES.SAGG := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_AGG);
|
||||
RRES.SALIAS := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_ALIAS);
|
||||
RRES.NUSE := PKG_XPATH.ATTRIBUTE_NUM(RNODE => XNODE, SNAME => SATTR_USE);
|
||||
RRES.NSHOW := PKG_XPATH.ATTRIBUTE_NUM(RNODE => XNODE, SNAME => SATTR_SHOW);
|
||||
/* Освободим документ */
|
||||
PKG_XPATH.FREE(RDOCUMENT => XDOC);
|
||||
exception
|
||||
@ -908,6 +912,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
||||
else
|
||||
/* Такого элемента нет - берем из представления */
|
||||
RRES(RRES.LAST).SID := TATTR_ID_MAKE(SENT_ID => RENT.SID, SNAME => RVIEW_FIELD.COLUMN_NAME);
|
||||
RRES(RRES.LAST).SPARENT_ENTITY := RENT.SID;
|
||||
RRES(RRES.LAST).SNAME := RVIEW_FIELD.COLUMN_NAME;
|
||||
RRES(RRES.LAST).STITLE := DMSCLVIEWSATTRS_TITLE_GET(SVIEW_NAME => RENT.SNAME,
|
||||
SATTR_NAME => RRES(RRES.LAST).SNAME);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user