diff --git a/app/panels/query_editor/components/inspector/inspector.js b/app/panels/query_editor/components/inspector/inspector.js
index 7ecb070..3a9de4e 100644
--- a/app/panels/query_editor/components/inspector/inspector.js
+++ b/app/panels/query_editor/components/inspector/inspector.js
@@ -13,10 +13,11 @@ 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 { ARGUMENT_SHAPE } from "../argument/argument"; //Описание аргумента запроса
import { InspectorQueryArguments } from "../inspector_query_args/inspector_query_args"; //Управление аргументами запроса
+import { InspectorQueryConditions } from "../inspector_query_cond/inspector_query_cond"; //Управление условиями отбора запроса
import { InspectorQueryEntities } from "../inspector_query_ents/inspector_query_ents"; //Управление сущностями запроса
import { InspectorQueryRelations } from "../inspector_query_rls/inspector_query_rls"; //Управление связями запроса
-import { ARGUMENT_SHAPE } from "../argument/argument"; //Аргументы запроса
//-----------
//Тело модуля
@@ -33,6 +34,7 @@ const Inspector = ({ query, entity, relation, args = [], cond = null, onOptionsC
+
{relation && (
diff --git a/app/panels/query_editor/components/inspector_query_cond/cond_operation_buttons.js b/app/panels/query_editor/components/inspector_query_cond/cond_operation_buttons.js
new file mode 100644
index 0000000..4008995
--- /dev/null
+++ b/app/panels/query_editor/components/inspector_query_cond/cond_operation_buttons.js
@@ -0,0 +1,43 @@
+/*
+ Парус 8 - Панели мониторинга - Редактор запросов
+ Компонент: Кнопки операций условий отбора
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React from "react"; //Классы React
+import PropTypes from "prop-types"; //Контроль свойств компонента
+import { ButtonGroup, Button } from "@mui/material"; //Интерфейсные компоненты MUI
+
+//-----------
+//Тело модуля
+//-----------
+
+//Кнопки операций условий отбора
+const CondOperationButtons = ({ buttons = [], onClick }) => {
+ return (
+
+ {buttons.map((button, i) => (
+
+ ))}
+
+ );
+};
+
+//Контроль свойств - Кнопки операций условий отбора
+CondOperationButtons.propTypes = {
+ buttons: PropTypes.arrayOf(
+ PropTypes.shape({ caption: PropTypes.string.isRequired, title: PropTypes.string.isRequired, value: PropTypes.string.isRequired })
+ ),
+ onClick: PropTypes.func.isRequired
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { CondOperationButtons };
diff --git a/app/panels/query_editor/components/inspector_query_cond/hooks.js b/app/panels/query_editor/components/inspector_query_cond/hooks.js
new file mode 100644
index 0000000..04e06a5
--- /dev/null
+++ b/app/panels/query_editor/components/inspector_query_cond/hooks.js
@@ -0,0 +1,38 @@
+/*
+ Парус 8 - Панели мониторинга - Редактор запросов
+ Пользовательские хуки для работы с условиями отбора запроса
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import { useContext, useCallback } from "react"; //Классы React
+import { BackEndСtx } from "../../../../context/backend"; //Контекст взаимодействия с сервером
+
+//-----------
+//Тело модуля
+//-----------
+
+//Работа с условиями отбора запроса
+const useQueryConditions = query => {
+ //Подключение к контексту взаимодействия с сервером
+ const { executeStored } = useContext(BackEndСtx);
+
+ //Установка условий отбора в запросе
+ const setCond = useCallback(
+ async cond => {
+ await executeStored({ stored: "PKG_P8PANELS_QE.QUERY_OPT_COND_SET", args: { NRN: query, SCOND: cond }, loader: false });
+ },
+ [query, executeStored]
+ );
+
+ //Возвращаем интерфейс хука
+ return { setCond };
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { useQueryConditions };
diff --git a/app/panels/query_editor/components/inspector_query_cond/inspector_query_cond.js b/app/panels/query_editor/components/inspector_query_cond/inspector_query_cond.js
new file mode 100644
index 0000000..acee7e8
--- /dev/null
+++ b/app/panels/query_editor/components/inspector_query_cond/inspector_query_cond.js
@@ -0,0 +1,103 @@
+/*
+ Парус 8 - Панели мониторинга - Редактор запросов
+ Компонент инспектора - Условия отбора запроса
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React, { useState } from "react"; //Классы React
+import PropTypes from "prop-types"; //Контроль свойств компонента
+import { Card, CardActionArea, CardContent, Stack, Chip, Icon, Button } from "@mui/material"; //Интерфейсные элементы
+import { BUTTONS } from "../../../../../app.text"; //Общие текстовые ресурсы
+import { STYLES as COMMON_STYLES } from "../../../../components/editors/p8p_editors_common"; //Общие ресурсы редаторов
+import { useQueryConditions } from "./hooks"; //Хуки для работы с условиями отбора
+import { QueryCondDialog } from "./query_cond_dialog"; //Диалог настройки условий отбора
+
+//---------
+//Константы
+//---------
+
+//Общий стиль многострочного компонента "Chip"
+const COMMON_MULTILINE_CHIP = COMMON_STYLES.CHIP(true, true);
+
+//Стили
+const STYLES = {
+ COND_CHIP: {
+ ...COMMON_MULTILINE_CHIP,
+ "& .MuiChip-label": {
+ ...COMMON_MULTILINE_CHIP["& .MuiChip-label"],
+ paddingTop: "5px",
+ paddingBottom: "5px"
+ }
+ }
+};
+
+//-----------
+//Тело модуля
+//-----------
+
+//Компонент инспектора - Условия отбора запроса
+const InspectorQueryConditions = ({ query, cond, onOptionsChanged }) => {
+ //Собственное состояние - отображение диалога настройки условий отбора
+ const [openQueryCondDialog, setOpenQueryCondDialog] = useState(false);
+
+ //Работа со связями на сервере
+ const { setCond } = useQueryConditions(query);
+
+ //Уведомление родителя об изменении свойств
+ const notifyOptionsChanged = () => onOptionsChanged && onOptionsChanged();
+
+ //При нажатии на кнопку настройки условий отбора
+ const handleSetup = () => setOpenQueryCondDialog(true);
+
+ //При закрытии диалога изменений условий отбора по "ОК"
+ const handleQueryCondDialogOk = async cond => {
+ await setCond(cond);
+ notifyOptionsChanged();
+ setOpenQueryCondDialog(false);
+ };
+
+ //При закрытии диалога изменений условий отбора по "Отмена"
+ const handleQueryCondDialogCancel = () => setOpenQueryCondDialog(false);
+
+ //Расчет флага сконфигурированности
+ const configured = cond ? true : false;
+
+ //Формирование представления
+ return (
+ <>
+ {openQueryCondDialog && }
+ {configured && (
+
+
+
+
+
+
+
+
+
+ )}
+ {!configured && (
+
+ )}
+ >
+ );
+};
+
+//Контроль свойств компонента - Компонент инспектора - Условия отбора запроса
+InspectorQueryConditions.propTypes = {
+ query: PropTypes.number.isRequired,
+ cond: PropTypes.string,
+ onOptionsChanged: PropTypes.func
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { InspectorQueryConditions };
diff --git a/app/panels/query_editor/components/inspector_query_cond/query_cond_dialog.js b/app/panels/query_editor/components/inspector_query_cond/query_cond_dialog.js
new file mode 100644
index 0000000..8874058
--- /dev/null
+++ b/app/panels/query_editor/components/inspector_query_cond/query_cond_dialog.js
@@ -0,0 +1,105 @@
+/*
+ Парус 8 - Панели мониторинга - Редактор запросов
+ Компонент: Диалог настройки условий отбора запроса
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React, { useState, useRef } from "react"; //Классы React
+import PropTypes from "prop-types"; //Контроль свойств компонента
+import { Stack, TextField } from "@mui/material"; //Интерфейсные компоненты MUI
+import { P8PDialog } from "../../../../components/p8p_dialog"; //Типовой диалог
+import { CondOperationButtons } from "./cond_operation_buttons"; //Кнопки операций условия отбора
+
+//-----------
+//Тело модуля
+//-----------
+
+//Диалог настройки условий отбора запроса
+const QueryCondDialog = ({ cond, onOk, onCancel }) => {
+ //Собственное состояние - условия отбора
+ const [conditions, setConditions] = useState(cond || "");
+
+ //Ссылка на элемент ввода условия
+ const condInputRef = useRef(null);
+
+ //Перемещение курсора в конец поля ввода условия
+ const moveCondCursorToEnd = () => {
+ if (condInputRef.current) {
+ const length = condInputRef.current.value.length;
+ condInputRef.current.setSelectionRange(length, length);
+ condInputRef.current.focus();
+ }
+ };
+
+ //Нажатие на кнопку "ОК"
+ const handleOk = () => onOk && onOk(conditions);
+
+ //Нажатие на кнопку "Отмена"
+ const handleCancel = () => onCancel && onCancel();
+
+ //При изменении условия через компонент
+ const handleChange = e => setConditions(e.target.value);
+
+ //При нажатии на кнопку операции
+ const handleOperationButtonClick = value => {
+ setConditions(pv => pv + value);
+ moveCondCursorToEnd();
+ };
+
+ //Генерация содержимого
+ return (
+
+
+ ", title: "Не равно", value: " <> " },
+ { caption: ">", title: "Больше", value: " > " },
+ { caption: ">=", title: "Больше или равно", value: " >= " },
+ { caption: "<", title: "Меньше", value: " < " },
+ { caption: "<=", title: "Меньше или равно", value: " <= " },
+ { caption: "(", title: "Открывающая скобка", value: "(" },
+ { caption: ")", title: "Закрывающая скобка", value: ")" }
+ ]}
+ onClick={handleOperationButtonClick}
+ />
+
+
+
+
+ );
+};
+
+//Контроль свойств - Диалог настройки условий отбора запроса
+QueryCondDialog.propTypes = {
+ cond: PropTypes.string,
+ onOk: PropTypes.func,
+ onCancel: PropTypes.func
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { QueryCondDialog };
diff --git a/db/PKG_P8PANELS_QE.pck b/db/PKG_P8PANELS_QE.pck
index 36c9bc5..f05edf2 100644
--- a/db/PKG_P8PANELS_QE.pck
+++ b/db/PKG_P8PANELS_QE.pck
@@ -130,6 +130,13 @@ create or replace package PKG_P8PANELS_QE as
NRN in number, -- Рег. номер запроса
SNAME in varchar2 -- Имя
);
+
+ /* Установка условий отбора запроса */
+ procedure QUERY_OPT_COND_SET
+ (
+ NRN in number, -- Рег. номер запроса
+ SCOND in varchar2 -- Условия отбора
+ );
end PKG_P8PANELS_QE;
/
@@ -536,5 +543,27 @@ create or replace package body PKG_P8PANELS_QE as
PKG_P8PANELS_QE_BASE.QUERY_OPT_SET(NRN => RQ.RN, ROPT => ROPT);
end QUERY_OPT_ARG_REMOVE;
+ /* Установка условий отбора запроса */
+ procedure QUERY_OPT_COND_SET
+ (
+ NRN in number, -- Рег. номер запроса
+ SCOND in varchar2 -- Условия отбора
+ )
+ is
+ RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса
+ ROPT PKG_P8PANELS_QE_BASE.TOPT; -- Настройка запроса
+ begin
+ /* Провим права доступа */
+ PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER());
+ /* Читаем запись запроса */
+ RQ := PKG_P8PANELS_QE_BASE.QUERY_GET(NRN => NRN);
+ /* Читаем текущую настройку */
+ ROPT := PKG_P8PANELS_QE_BASE.QUERY_OPT_GET(COPT => RQ.OPT);
+ /* Установим новые условия отбора */
+ ROPT.SCOND := SCOND;
+ /* Сохраняем обновленную настройку */
+ PKG_P8PANELS_QE_BASE.QUERY_OPT_SET(NRN => RQ.RN, ROPT => ROPT);
+ end QUERY_OPT_COND_SET;
+
end PKG_P8PANELS_QE;
/