diff --git a/app/panels/query_editor/components/attribute/attribute.js b/app/panels/query_editor/components/attribute/attribute.js
index ff8fc9b..95a7cd8 100644
--- a/app/panels/query_editor/components/attribute/attribute.js
+++ b/app/panels/query_editor/components/attribute/attribute.js
@@ -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 };
diff --git a/app/panels/query_editor/components/entity/entity.js b/app/panels/query_editor/components/entity/entity.js
index 9750ec1..b2503f5 100644
--- a/app/panels/query_editor/components/entity/entity.js
+++ b/app/panels/query_editor/components/entity/entity.js
@@ -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 };
diff --git a/app/panels/query_editor/components/inspector/inspector.js b/app/panels/query_editor/components/inspector/inspector.js
index 3a9de4e..e29b329 100644
--- a/app/panels/query_editor/components/inspector/inspector.js
+++ b/app/panels/query_editor/components/inspector/inspector.js
@@ -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
-
+
{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
diff --git a/app/panels/query_editor/components/inspector_query_ents/attrs_list.js b/app/panels/query_editor/components/inspector_query_ents/attrs_list.js
index 705aac1..08eda21 100644
--- a/app/panels/query_editor/components/inspector_query_ents/attrs_list.js
+++ b/app/panels/query_editor/components/inspector_query_ents/attrs_list.js
@@ -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
diff --git a/app/panels/query_editor/components/inspector_query_ents/inspector_query_ents.js b/app/panels/query_editor/components/inspector_query_ents/inspector_query_ents.js
index 118e014..0e0cea4 100644
--- a/app/panels/query_editor/components/inspector_query_ents/inspector_query_ents.js
+++ b/app/panels/query_editor/components/inspector_query_ents/inspector_query_ents.js
@@ -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
};
diff --git a/app/panels/query_editor/components/inspector_query_rls/inspector_query_rls.js b/app/panels/query_editor/components/inspector_query_rls/inspector_query_rls.js
index 7295c3c..31cb9c3 100644
--- a/app/panels/query_editor/components/inspector_query_rls/inspector_query_rls.js
+++ b/app/panels/query_editor/components/inspector_query_rls/inspector_query_rls.js
@@ -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
};
diff --git a/app/panels/query_editor/components/query_diagram/query_diagram.js b/app/panels/query_editor/components/query_diagram/query_diagram.js
index 71f5b2c..a269c9d 100644
--- a/app/panels/query_editor/components/query_diagram/query_diagram.js
+++ b/app/panels/query_editor/components/query_diagram/query_diagram.js
@@ -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 (
({ 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;
};
diff --git a/app/panels/query_editor/query_editor.js b/app/panels/query_editor/query_editor.js
index a1b0e3e..c95a83e 100644
--- a/app/panels/query_editor/query_editor.js
+++ b/app/panels/query_editor/query_editor.js
@@ -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 = () => {
{queryDiagram && (
{
{toolBar}
{query && (
-
+
)}
diff --git a/db/PKG_P8PANELS_QE_BASE.pck b/db/PKG_P8PANELS_QE_BASE.pck
index a57aa9c..7f2535c 100644
--- a/db/PKG_P8PANELS_QE_BASE.pck
+++ b/db/PKG_P8PANELS_QE_BASE.pck
@@ -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);