ЦИТК-979 - Настройка запроса - условия отбора (сервер и клиент)
This commit is contained in:
parent
eef77cbd2d
commit
b09ae4d83b
@ -13,10 +13,11 @@ import { P8PEditorBox } from "../../../../components/editors/p8p_editor_box"; //
|
|||||||
import { P8PEditorSubHeader } from "../../../../components/editors/p8p_editor_sub_header"; //Подзаголовок группы параметров редактора
|
import { P8PEditorSubHeader } from "../../../../components/editors/p8p_editor_sub_header"; //Подзаголовок группы параметров редактора
|
||||||
import { ENTITY_DATA_SHAPE } from "../entity/entity"; //Описание сущности
|
import { ENTITY_DATA_SHAPE } from "../entity/entity"; //Описание сущности
|
||||||
import { RELATION_DATA_SHAPE } from "../relation/relation"; //Описание связи
|
import { RELATION_DATA_SHAPE } from "../relation/relation"; //Описание связи
|
||||||
|
import { ARGUMENT_SHAPE } from "../argument/argument"; //Описание аргумента запроса
|
||||||
import { InspectorQueryArguments } from "../inspector_query_args/inspector_query_args"; //Управление аргументами запроса
|
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 { InspectorQueryEntities } from "../inspector_query_ents/inspector_query_ents"; //Управление сущностями запроса
|
||||||
import { InspectorQueryRelations } from "../inspector_query_rls/inspector_query_rls"; //Управление связями запроса
|
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
|
|||||||
<P8PEditorSubHeader title={"Аргументы"} />
|
<P8PEditorSubHeader title={"Аргументы"} />
|
||||||
<InspectorQueryArguments query={query} args={args} onOptionsChanged={handleOptionsChanged} />
|
<InspectorQueryArguments query={query} args={args} onOptionsChanged={handleOptionsChanged} />
|
||||||
<P8PEditorSubHeader title={"Условия отбора"} />
|
<P8PEditorSubHeader title={"Условия отбора"} />
|
||||||
|
<InspectorQueryConditions query={query} cond={cond} onOptionsChanged={handleOptionsChanged} />
|
||||||
<P8PEditorSubHeader title={"Сущности"} />
|
<P8PEditorSubHeader title={"Сущности"} />
|
||||||
<InspectorQueryEntities query={query} entity={entity} onOptionsChanged={handleOptionsChanged} />
|
<InspectorQueryEntities query={query} entity={entity} onOptionsChanged={handleOptionsChanged} />
|
||||||
{relation && (
|
{relation && (
|
||||||
|
|||||||
@ -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 (
|
||||||
|
<ButtonGroup size={"small"} variant={"outlined"}>
|
||||||
|
{buttons.map((button, i) => (
|
||||||
|
<Button key={i} onClick={() => onClick(button.value)} title={button.title}>
|
||||||
|
{button.caption}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</ButtonGroup>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
//Контроль свойств - Кнопки операций условий отбора
|
||||||
|
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 };
|
||||||
@ -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 };
|
||||||
@ -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 && <QueryCondDialog cond={cond} onOk={handleQueryCondDialogOk} onCancel={handleQueryCondDialogCancel} />}
|
||||||
|
{configured && (
|
||||||
|
<Card variant={"outlined"}>
|
||||||
|
<CardActionArea onClick={handleSetup}>
|
||||||
|
<CardContent>
|
||||||
|
<Stack direction={"column"} spacing={1}>
|
||||||
|
<Chip sx={STYLES.COND_CHIP} label={cond} />
|
||||||
|
</Stack>
|
||||||
|
</CardContent>
|
||||||
|
</CardActionArea>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
|
{!configured && (
|
||||||
|
<Button startIcon={<Icon>build</Icon>} onClick={handleSetup}>
|
||||||
|
{BUTTONS.CONFIG}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
//Контроль свойств компонента - Компонент инспектора - Условия отбора запроса
|
||||||
|
InspectorQueryConditions.propTypes = {
|
||||||
|
query: PropTypes.number.isRequired,
|
||||||
|
cond: PropTypes.string,
|
||||||
|
onOptionsChanged: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
//----------------
|
||||||
|
//Интерфейс модуля
|
||||||
|
//----------------
|
||||||
|
|
||||||
|
export { InspectorQueryConditions };
|
||||||
@ -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 (
|
||||||
|
<P8PDialog title={`Условия отбора запроса`} onOk={handleOk} onCancel={handleCancel}>
|
||||||
|
<Stack sx={{ width: "550px" }} direction={"row"} spacing={1} pb={1}>
|
||||||
|
<CondOperationButtons
|
||||||
|
buttons={[
|
||||||
|
{ caption: "=", title: "Равно", value: " = " },
|
||||||
|
{ caption: "<>", title: "Не равно", value: " <> " },
|
||||||
|
{ caption: ">", title: "Больше", value: " > " },
|
||||||
|
{ caption: ">=", title: "Больше или равно", value: " >= " },
|
||||||
|
{ caption: "<", title: "Меньше", value: " < " },
|
||||||
|
{ caption: "<=", title: "Меньше или равно", value: " <= " },
|
||||||
|
{ caption: "(", title: "Открывающая скобка", value: "(" },
|
||||||
|
{ caption: ")", title: "Закрывающая скобка", value: ")" }
|
||||||
|
]}
|
||||||
|
onClick={handleOperationButtonClick}
|
||||||
|
/>
|
||||||
|
<CondOperationButtons
|
||||||
|
buttons={[
|
||||||
|
{ caption: "И", title: "Логическое умножение (конъюнкция)", value: " and " },
|
||||||
|
{ caption: "ИЛИ", title: "Логическое сложение (дизъюнкция)", value: " or " },
|
||||||
|
{ caption: "НЕ", title: "Отрицание (инверсия)", value: " not " },
|
||||||
|
{ caption: "B", title: "Входит в диапазон", value: " in (0, 1, ...) " }
|
||||||
|
]}
|
||||||
|
onClick={handleOperationButtonClick}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
<TextField
|
||||||
|
inputRef={condInputRef}
|
||||||
|
focused={true}
|
||||||
|
autoFocus
|
||||||
|
value={conditions}
|
||||||
|
placeholder={"Настройте условия отбора..."}
|
||||||
|
multiline
|
||||||
|
minRows={10}
|
||||||
|
fullWidth
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
</P8PDialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
//Контроль свойств - Диалог настройки условий отбора запроса
|
||||||
|
QueryCondDialog.propTypes = {
|
||||||
|
cond: PropTypes.string,
|
||||||
|
onOk: PropTypes.func,
|
||||||
|
onCancel: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
//----------------
|
||||||
|
//Интерфейс модуля
|
||||||
|
//----------------
|
||||||
|
|
||||||
|
export { QueryCondDialog };
|
||||||
@ -130,6 +130,13 @@ create or replace package PKG_P8PANELS_QE as
|
|||||||
NRN in number, -- Рег. номер запроса
|
NRN in number, -- Рег. номер запроса
|
||||||
SNAME in varchar2 -- Имя
|
SNAME in varchar2 -- Имя
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* Установка условий отбора запроса */
|
||||||
|
procedure QUERY_OPT_COND_SET
|
||||||
|
(
|
||||||
|
NRN in number, -- Рег. номер запроса
|
||||||
|
SCOND in varchar2 -- Условия отбора
|
||||||
|
);
|
||||||
|
|
||||||
end PKG_P8PANELS_QE;
|
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);
|
PKG_P8PANELS_QE_BASE.QUERY_OPT_SET(NRN => RQ.RN, ROPT => ROPT);
|
||||||
end QUERY_OPT_ARG_REMOVE;
|
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;
|
end PKG_P8PANELS_QE;
|
||||||
/
|
/
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user