forked from CITKParus/P8-Panels
ЦИТК-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 { 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
|
||||
<P8PEditorSubHeader title={"Аргументы"} />
|
||||
<InspectorQueryArguments query={query} args={args} onOptionsChanged={handleOptionsChanged} />
|
||||
<P8PEditorSubHeader title={"Условия отбора"} />
|
||||
<InspectorQueryConditions query={query} cond={cond} onOptionsChanged={handleOptionsChanged} />
|
||||
<P8PEditorSubHeader title={"Сущности"} />
|
||||
<InspectorQueryEntities query={query} entity={entity} onOptionsChanged={handleOptionsChanged} />
|
||||
{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 };
|
||||
@ -131,6 +131,13 @@ create or replace package PKG_P8PANELS_QE as
|
||||
SNAME in varchar2 -- Имя
|
||||
);
|
||||
|
||||
/* Установка условий отбора запроса */
|
||||
procedure QUERY_OPT_COND_SET
|
||||
(
|
||||
NRN in number, -- Рег. номер запроса
|
||||
SCOND in varchar2 -- Условия отбора
|
||||
);
|
||||
|
||||
end PKG_P8PANELS_QE;
|
||||
/
|
||||
create or replace package body PKG_P8PANELS_QE as
|
||||
@ -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;
|
||||
/
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user