forked from CITKParus/P8-Panels
Compare commits
No commits in common. "7c515f7ebb8b333e7f8745c7af554a5b9533a60e" and "47d6b0cdb1f7c1b212bff189965ae3e54a5f7cf9" have entirely different histories.
7c515f7ebb
...
47d6b0cdb1
@ -1369,7 +1369,6 @@ const MyPanel = () => {
|
|||||||
**Свойства**
|
**Свойства**
|
||||||
|
|
||||||
`style` - необязательный, объект, если задан, то будет применён в качестве атрибута `style` коневого контейнера (`div`) компонента\
|
`style` - необязательный, объект, если задан, то будет применён в качестве атрибута `style` коневого контейнера (`div`) компонента\
|
||||||
`tableStyle` - необязательный, объект, если задан, то будет применён в качестве атрибута `sx` компонента `Table`\
|
|
||||||
`columnsDef` - необязательный, массив, описание колонок таблицы, содержит объекты вида `{caption: <ЗАГОЛОВОК_КОЛОНКИ>, dataType: <ТИП_ДАННЫХ - NUMB|STR|DATE>, filter: <ПРИЗНАК_ВОЗМОЖНОСТИ_ОТБОРА - true|false>, hint: <ОПИСАНИЕ_КОЛОНКИ_МОЖЕТ_СОДЕРЖАТЬ_HTML_РАЗМЕТКУ>, name: <НАИМЕНОВАНИЕ_КОЛОНКИ>, order: <ПРИЗНАК_ВОЗМОЖНОСТИ_СОРТИРОВКИ - true|false>, values: <МАССИВ_ПРЕДОПРЕДЕЛЁННЫХ_ЗНАЧЕНИЙ>, visible: <ПРИЗНАК_ВИДИМОСТИ_КОЛОНКИ - true|false>,expandable: <ПРИЗНАК_РАЗВОРАЧИВАЕМОСТИ_ГРУППОВОГО_ЗАГОЛОВКА - true|false>, expanded: <ПРИЗНАК_РАЗВЕРНУТОСТИ_ГРУППОВОГО_ЗАГОЛОВКА - true|false>, parent: <НАИМЕНОВАНИЕ_РОДИТЕЛЬСКОЙ_КОЛОНКИ_В_ГРУППОВОМ_ЗАГОЛОВКЕ>, width: <ШИРИНА_КОЛОНКИ>}`\
|
`columnsDef` - необязательный, массив, описание колонок таблицы, содержит объекты вида `{caption: <ЗАГОЛОВОК_КОЛОНКИ>, dataType: <ТИП_ДАННЫХ - NUMB|STR|DATE>, filter: <ПРИЗНАК_ВОЗМОЖНОСТИ_ОТБОРА - true|false>, hint: <ОПИСАНИЕ_КОЛОНКИ_МОЖЕТ_СОДЕРЖАТЬ_HTML_РАЗМЕТКУ>, name: <НАИМЕНОВАНИЕ_КОЛОНКИ>, order: <ПРИЗНАК_ВОЗМОЖНОСТИ_СОРТИРОВКИ - true|false>, values: <МАССИВ_ПРЕДОПРЕДЕЛЁННЫХ_ЗНАЧЕНИЙ>, visible: <ПРИЗНАК_ВИДИМОСТИ_КОЛОНКИ - true|false>,expandable: <ПРИЗНАК_РАЗВОРАЧИВАЕМОСТИ_ГРУППОВОГО_ЗАГОЛОВКА - true|false>, expanded: <ПРИЗНАК_РАЗВЕРНУТОСТИ_ГРУППОВОГО_ЗАГОЛОВКА - true|false>, parent: <НАИМЕНОВАНИЕ_РОДИТЕЛЬСКОЙ_КОЛОНКИ_В_ГРУППОВОМ_ЗАГОЛОВКЕ>, width: <ШИРИНА_КОЛОНКИ>}`\
|
||||||
`filtersInitial` - необязательныей, массив, начальное состояние фильтров таблицы, содержит объекты вида `{name: <НАИМЕНОВАНИЕ_КОЛОНКИ>, from: <НАЧАЛО_ДИАПАЗОНА_ЗНАЧЕНИЙ_ФИЛЬТРА>, to: <ОКОНЧАНИЕ_ДИАПАЗОНА_ЗНАЧЕНИЙ_ФИЛЬТРА>}`\
|
`filtersInitial` - необязательныей, массив, начальное состояние фильтров таблицы, содержит объекты вида `{name: <НАИМЕНОВАНИЕ_КОЛОНКИ>, from: <НАЧАЛО_ДИАПАЗОНА_ЗНАЧЕНИЙ_ФИЛЬТРА>, to: <ОКОНЧАНИЕ_ДИАПАЗОНА_ЗНАЧЕНИЙ_ФИЛЬТРА>}`\
|
||||||
`groups` - необязательный, массив групп данных, содержит объекты вида `{name: <ИМЯ_ГРУППЫ>, caption: <ЗАГОЛОВОК_ГРУППЫ>, expandable: <ПРИЗНАК_РАЗВОРАЧИВАЕМОСТИ_ГРУППЫ - true|false>, expanded: <ПРИЗНАК_РАЗВЕРНУТОСТИ_ГРУППЫ - true|false>}`\
|
`groups` - необязательный, массив групп данных, содержит объекты вида `{name: <ИМЯ_ГРУППЫ>, caption: <ЗАГОЛОВОК_ГРУППЫ>, expandable: <ПРИЗНАК_РАЗВОРАЧИВАЕМОСТИ_ГРУППЫ - true|false>, expanded: <ПРИЗНАК_РАЗВЕРНУТОСТИ_ГРУППЫ - true|false>}`\
|
||||||
@ -1398,7 +1397,7 @@ const MyPanel = () => {
|
|||||||
`rowExpandRender` - необязательный, функция формирования представления развёрнутой строки таблицы (если не указана - интерфейсный элемент для "разворачивания" строки не будет отображён, даже при `expandable=true`). Сигнатура функции `f({row, columnsDef})`. Будет вызвана в момент "развёртывания" строки таблицы пользователем, в функцию будет передан объект, поле `row` которого будет содержать данные текущей "разворачиваемой" строки таблицы, а поле `columnsDef` - описание колонок таблицы. Должна возвращать представление "развёрнутой" строки таблицы в виде значения или Rect-компонента.\
|
`rowExpandRender` - необязательный, функция формирования представления развёрнутой строки таблицы (если не указана - интерфейсный элемент для "разворачивания" строки не будет отображён, даже при `expandable=true`). Сигнатура функции `f({row, columnsDef})`. Будет вызвана в момент "развёртывания" строки таблицы пользователем, в функцию будет передан объект, поле `row` которого будет содержать данные текущей "разворачиваемой" строки таблицы, а поле `columnsDef` - описание колонок таблицы. Должна возвращать представление "развёрнутой" строки таблицы в виде значения или Rect-компонента.\
|
||||||
`valueFormatter` - необязательный, функция форматирования значений колонки (если не указана - форматирование согласно `columnsDef`). Сигнатура функции `f({value, columnDef})`. Будет вызвана в момент формирования ячейки таблицы (если ранее для ячейки `dataCellRender` не вернул специального представления) и в моммент формирования фильтра для ячейки. Должна возвращать отформатированное значение ячейки или React-компонент для её представления.\
|
`valueFormatter` - необязательный, функция форматирования значений колонки (если не указана - форматирование согласно `columnsDef`). Сигнатура функции `f({value, columnDef})`. Будет вызвана в момент формирования ячейки таблицы (если ранее для ячейки `dataCellRender` не вернул специального представления) и в моммент формирования фильтра для ячейки. Должна возвращать отформатированное значение ячейки или React-компонент для её представления.\
|
||||||
`containerComponent` - необязательный, функциональный React-компонент или строка с именем HTML-тэга, будет применён для формирования в иерархии DOM элемента-обёртки (контейнера) таблицы (по умолчанию используется компонет библиотеки MUI - Paper)\
|
`containerComponent` - необязательный, функциональный React-компонент или строка с именем HTML-тэга, будет применён для формирования в иерархии DOM элемента-обёртки (контейнера) таблицы (по умолчанию используется компонет библиотеки MUI - Paper)\
|
||||||
`containerComponentProps` - необязательный, объект, содержит свойства, которые будут переданы компоненту-контейнеру (`TableContainer`) таблицы (является дочерним для корневого `div`, контейнера всего компонента)\
|
`containerComponentProps` - необязательный, объект, содержит свойства, которые будут переданы компоненту-контейнеру таблицы\
|
||||||
`onOrderChanged` - необязательный, функция, будет вызвана при изменении пользователем состояния сортировок таблицы. Сигнатура функции `f({orders})`, результат функции не интерпретируется. В функцию передаётся объект, поле `orders` которого, содержит текущее состояние сортировок таблицы. Объект `orders` - массив, содержащий элементы вида `{name: <НАИМЕНОВАНИЕ_КОЛОНКИ>, direction: <ASC|DESC>}`. Функция применяется для инициации обновления данных в таблице.\
|
`onOrderChanged` - необязательный, функция, будет вызвана при изменении пользователем состояния сортировок таблицы. Сигнатура функции `f({orders})`, результат функции не интерпретируется. В функцию передаётся объект, поле `orders` которого, содержит текущее состояние сортировок таблицы. Объект `orders` - массив, содержащий элементы вида `{name: <НАИМЕНОВАНИЕ_КОЛОНКИ>, direction: <ASC|DESC>}`. Функция применяется для инициации обновления данных в таблице.\
|
||||||
`onFilterChanged` - необязательный, функция, будет вызвана при изменении пользователем состояния фильтров таблицы. Сигнатура функции `f({filters})`, результат функции не интерпретируется. В функцию передаётся объект, поле `filters` которого, содержит текущее состояние фильтров таблицы. Объект `filters` - массив, содержащий элементы вида `{name: <НАИМЕНОВАНИЕ_КОЛОНКИ>, from: <ЗНАЧЕНИЕ_НАЧАЛА_ДИАПАЗОНА_ОТБОРА>, to: <ЗНАЧЕНИЕ_ОКОНЧАНИЯ_ДИАПАЗОНА_ОТБОРА>}`. Функция применяется для инициации обновления данных в таблице.\
|
`onFilterChanged` - необязательный, функция, будет вызвана при изменении пользователем состояния фильтров таблицы. Сигнатура функции `f({filters})`, результат функции не интерпретируется. В функцию передаётся объект, поле `filters` которого, содержит текущее состояние фильтров таблицы. Объект `filters` - массив, содержащий элементы вида `{name: <НАИМЕНОВАНИЕ_КОЛОНКИ>, from: <ЗНАЧЕНИЕ_НАЧАЛА_ДИАПАЗОНА_ОТБОРА>, to: <ЗНАЧЕНИЕ_ОКОНЧАНИЯ_ДИАПАЗОНА_ОТБОРА>}`. Функция применяется для инициации обновления данных в таблице.\
|
||||||
`onPagesCountChanged` - необязательный, функция, будет вызвана при изменении пользователем количества отображаемых страниц данных таблицы. Сигнатура функции `f()`, результат функции не интерпретируется. Функция применяется для инициации обновления данных в таблице.\
|
`onPagesCountChanged` - необязательный, функция, будет вызвана при изменении пользователем количества отображаемых страниц данных таблицы. Сигнатура функции `f()`, результат функции не интерпретируется. Функция применяется для инициации обновления данных в таблице.\
|
||||||
|
@ -37,7 +37,6 @@ const P8P_DATA_GRID_FILTERS_HEIGHT = P8P_TABLE_FILTERS_HEIGHT;
|
|||||||
//Таблица данных
|
//Таблица данных
|
||||||
const P8PDataGrid = ({
|
const P8PDataGrid = ({
|
||||||
style = {},
|
style = {},
|
||||||
tableStyle = {},
|
|
||||||
columnsDef = [],
|
columnsDef = [],
|
||||||
filtersInitial,
|
filtersInitial,
|
||||||
groups = [],
|
groups = [],
|
||||||
@ -117,7 +116,6 @@ const P8PDataGrid = ({
|
|||||||
return (
|
return (
|
||||||
<P8PTable
|
<P8PTable
|
||||||
style={style}
|
style={style}
|
||||||
tableStyle={tableStyle}
|
|
||||||
columnsDef={columnsDef}
|
columnsDef={columnsDef}
|
||||||
groups={groups}
|
groups={groups}
|
||||||
rows={rows}
|
rows={rows}
|
||||||
@ -159,7 +157,6 @@ const P8PDataGrid = ({
|
|||||||
//Контроль свойств - Таблица данных
|
//Контроль свойств - Таблица данных
|
||||||
P8PDataGrid.propTypes = {
|
P8PDataGrid.propTypes = {
|
||||||
style: PropTypes.object,
|
style: PropTypes.object,
|
||||||
tableStyle: PropTypes.object,
|
|
||||||
columnsDef: PropTypes.array,
|
columnsDef: PropTypes.array,
|
||||||
filtersInitial: PropTypes.arrayOf(P8P_DATA_GRID_FILTER_SHAPE),
|
filtersInitial: PropTypes.arrayOf(P8P_DATA_GRID_FILTER_SHAPE),
|
||||||
groups: PropTypes.array,
|
groups: PropTypes.array,
|
||||||
|
@ -465,7 +465,6 @@ P8PTableFiltersChips.propTypes = {
|
|||||||
//Таблица
|
//Таблица
|
||||||
const P8PTable = ({
|
const P8PTable = ({
|
||||||
style = {},
|
style = {},
|
||||||
tableStyle = {},
|
|
||||||
columnsDef = [],
|
columnsDef = [],
|
||||||
groups = [],
|
groups = [],
|
||||||
rows = [],
|
rows = [],
|
||||||
@ -711,7 +710,7 @@ const P8PTable = ({
|
|||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
<TableContainer component={containerComponent ? containerComponent : Paper} {...(containerComponentProps ? containerComponentProps : {})}>
|
<TableContainer component={containerComponent ? containerComponent : Paper} {...(containerComponentProps ? containerComponentProps : {})}>
|
||||||
<Table stickyHeader={fixedHeader} sx={{ ...STYLES.TABLE, ...(tableStyle || {}) }} size={size || P8P_TABLE_SIZE.MEDIUM}>
|
<Table stickyHeader={fixedHeader} sx={STYLES.TABLE} size={size || P8P_TABLE_SIZE.MEDIUM}>
|
||||||
<TableHead sx={fixedHeader ? STYLES.TABLE_HEAD_STICKY : {}}>
|
<TableHead sx={fixedHeader ? STYLES.TABLE_HEAD_STICKY : {}}>
|
||||||
{header.displayLevels.map((level, i) => (
|
{header.displayLevels.map((level, i) => (
|
||||||
<TableRow key={level}>
|
<TableRow key={level}>
|
||||||
@ -877,7 +876,6 @@ const P8PTable = ({
|
|||||||
//Контроль свойств - Таблица
|
//Контроль свойств - Таблица
|
||||||
P8PTable.propTypes = {
|
P8PTable.propTypes = {
|
||||||
style: PropTypes.object,
|
style: PropTypes.object,
|
||||||
tableStyle: PropTypes.object,
|
|
||||||
columnsDef: PropTypes.arrayOf(
|
columnsDef: PropTypes.arrayOf(
|
||||||
PropTypes.shape({
|
PropTypes.shape({
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
|
@ -57,7 +57,7 @@ export const ApplicationContext = ({ errors, displaySizeGetter, guidGenerator, c
|
|||||||
const setPanels = panels => dispatch({ type: APP_AT.LOAD_PANELS, payload: panels });
|
const setPanels = panels => dispatch({ type: APP_AT.LOAD_PANELS, payload: panels });
|
||||||
|
|
||||||
//Установка заголовка в шапке приложения
|
//Установка заголовка в шапке приложения
|
||||||
const setAppBarTitle = useCallback(appBarTitle => dispatch({ type: APP_AT.SET_APP_BAR_TITLE, payload: appBarTitle }), []);
|
const setAppBarTitle = appBarTitle => dispatch({ type: APP_AT.SET_APP_BAR_TITLE, payload: appBarTitle });
|
||||||
|
|
||||||
//Поиск раздела по имени
|
//Поиск раздела по имени
|
||||||
const findPanelByName = name => state.panels.find(panel => panel.name == name);
|
const findPanelByName = name => state.panels.find(panel => panel.name == name);
|
||||||
|
358
app/panels/rrp_conf_editor/IUD/iud_form_dialog.js
Normal file
358
app/panels/rrp_conf_editor/IUD/iud_form_dialog.js
Normal file
@ -0,0 +1,358 @@
|
|||||||
|
/*
|
||||||
|
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
|
||||||
|
Панель мониторинга: Диалог добавления/исправления/удаления компонентов настройки регламентированного отчёта
|
||||||
|
*/
|
||||||
|
|
||||||
|
//---------------------
|
||||||
|
//Подключение библиотек
|
||||||
|
//---------------------
|
||||||
|
|
||||||
|
import React, { useState, useContext, useCallback, useEffect } from "react"; //Классы React
|
||||||
|
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||||||
|
import { Dialog, DialogTitle, IconButton, Icon, DialogContent, Typography, DialogActions, Button } from "@mui/material"; //Интерфейсные компоненты
|
||||||
|
import { ApplicationСtx } from "../../../context/application"; //Контекст приложения
|
||||||
|
import { BackEndСtx } from "../../../context/backend"; //Контекст взаимодействия с сервером
|
||||||
|
import { IUDFormTextField } from "./iud_form_text_field"; //Компонент поля ввода
|
||||||
|
|
||||||
|
//---------
|
||||||
|
//Константы
|
||||||
|
//---------
|
||||||
|
|
||||||
|
//Стили
|
||||||
|
const STYLES = {
|
||||||
|
CLOSE_BUTTON: {
|
||||||
|
position: "absolute",
|
||||||
|
right: 8,
|
||||||
|
top: 8,
|
||||||
|
color: theme => theme.palette.grey[500]
|
||||||
|
},
|
||||||
|
PADDING_DIALOG_BUTTONS_RIGHT: { paddingRight: "32px" }
|
||||||
|
};
|
||||||
|
|
||||||
|
//Статусы диалогового окна
|
||||||
|
export const STATUSES = { CREATE: 0, EDIT: 1, DELETE: 2, RRPCONFSCTNMRK_CREATE: 3, RRPCONFSCTNMRK_EDIT: 4, RRPCONFSCTNMRK_DELETE: 5 };
|
||||||
|
|
||||||
|
//---------------
|
||||||
|
//Тело компонента
|
||||||
|
//---------------
|
||||||
|
|
||||||
|
const IUDFormDialog = ({ initial, onClose, onReload }) => {
|
||||||
|
//Собственное состояние
|
||||||
|
const [formData, setFormData] = useState({ ...initial });
|
||||||
|
|
||||||
|
//Подключение к контексту приложения
|
||||||
|
const { pOnlineShowDictionary } = useContext(ApplicationСtx);
|
||||||
|
|
||||||
|
//Подключение к контексту взаимодействия с сервером
|
||||||
|
const { executeStored } = useContext(BackEndСtx);
|
||||||
|
|
||||||
|
//При закрытии диалога без изменений
|
||||||
|
const handleCancel = () => (onClose ? onClose() : null);
|
||||||
|
|
||||||
|
//При закрытии диалога с изменениями
|
||||||
|
const handleOK = () => {
|
||||||
|
if (onClose) {
|
||||||
|
changeSections();
|
||||||
|
onClose();
|
||||||
|
} else null;
|
||||||
|
};
|
||||||
|
|
||||||
|
//Отработка добавления/изсправления/удаления элемента
|
||||||
|
const handleReload = () => {
|
||||||
|
if (onReload) {
|
||||||
|
onReload();
|
||||||
|
} else null;
|
||||||
|
};
|
||||||
|
|
||||||
|
//При изменении значения элемента
|
||||||
|
const handleDialogItemChange = (item, value) => {
|
||||||
|
setFormData(pv => ({ ...pv, [item]: value }));
|
||||||
|
};
|
||||||
|
|
||||||
|
//Отработка изменений в разделе или показателе раздела
|
||||||
|
const changeSections = useCallback(async () => {
|
||||||
|
switch (formData.status) {
|
||||||
|
case STATUSES.CREATE:
|
||||||
|
await insertSections();
|
||||||
|
break;
|
||||||
|
case STATUSES.EDIT:
|
||||||
|
await updateSections();
|
||||||
|
break;
|
||||||
|
case STATUSES.DELETE:
|
||||||
|
await deleteSections();
|
||||||
|
break;
|
||||||
|
case STATUSES.RRPCONFSCTNMRK_CREATE:
|
||||||
|
await addRRPCONFSCTNMRK();
|
||||||
|
break;
|
||||||
|
case STATUSES.RRPCONFSCTNMRK_EDIT:
|
||||||
|
await editRRPCONFSCTNMRK();
|
||||||
|
break;
|
||||||
|
case STATUSES.RRPCONFSCTNMRK_DELETE:
|
||||||
|
await deleteRRPCONFSCTNMRK();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
handleReload();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [formData]);
|
||||||
|
|
||||||
|
//Добавление раздела
|
||||||
|
const insertSections = useCallback(async () => {
|
||||||
|
const data = await executeStored({
|
||||||
|
stored: "PKG_P8PANELS_RRPCONFED.RRPCONFSCTN_INSERT",
|
||||||
|
args: {
|
||||||
|
NPRN: formData.prn,
|
||||||
|
SCODE: formData.code,
|
||||||
|
SNAME: formData.name
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setFormData(pv => ({
|
||||||
|
...pv,
|
||||||
|
rn: Number(data.NRN)
|
||||||
|
}));
|
||||||
|
}, [formData.prn, formData.code, formData.name, executeStored]);
|
||||||
|
|
||||||
|
//Исправление раздела
|
||||||
|
const updateSections = useCallback(async () => {
|
||||||
|
await executeStored({
|
||||||
|
stored: "PKG_P8PANELS_RRPCONFED.RRPCONFSCTN_UPDATE",
|
||||||
|
args: {
|
||||||
|
NRN: formData.rn,
|
||||||
|
SCODE: formData.code,
|
||||||
|
SNAME: formData.name
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [formData.name, formData.code, formData.rn, executeStored]);
|
||||||
|
|
||||||
|
//Удаление раздела
|
||||||
|
const deleteSections = useCallback(async () => {
|
||||||
|
await executeStored({
|
||||||
|
stored: "PKG_P8PANELS_RRPCONFED.RRPCONFSCTN_DELETE",
|
||||||
|
args: {
|
||||||
|
NRN: formData.rn
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [formData.rn, executeStored]);
|
||||||
|
|
||||||
|
//Добавление показателя раздела
|
||||||
|
const addRRPCONFSCTNMRK = useCallback(async () => {
|
||||||
|
await executeStored({
|
||||||
|
stored: "PKG_P8PANELS_RRPCONFED.RRPCONFSCTNMRK_INSERT",
|
||||||
|
args: {
|
||||||
|
NPRN: formData.prn,
|
||||||
|
SCODE: formData.code,
|
||||||
|
SNAME: formData.name,
|
||||||
|
NRRPROW: formData.rowRn,
|
||||||
|
NRRPCOLUMN: formData.colRn
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [executeStored, formData.code, formData.colRn, formData.name, formData.prn, formData.rowRn]);
|
||||||
|
|
||||||
|
//Исправление показателя раздела
|
||||||
|
const editRRPCONFSCTNMRK = useCallback(async () => {
|
||||||
|
await executeStored({
|
||||||
|
stored: "PKG_P8PANELS_RRPCONFED.RRPCONFSCTNMRK_UPDATE",
|
||||||
|
args: { NRN: formData.rn, SNAME: formData.name }
|
||||||
|
});
|
||||||
|
}, [executeStored, formData.name, formData.rn]);
|
||||||
|
|
||||||
|
//Удаление показателя раздела
|
||||||
|
const deleteRRPCONFSCTNMRK = useCallback(async () => {
|
||||||
|
await executeStored({ stored: "PKG_P8PANELS_RRPCONFED.RRPCONFSCTNMRK_DELETE", args: { NRN: formData.rn } });
|
||||||
|
}, [executeStored, formData.rn]);
|
||||||
|
|
||||||
|
//Формирование заголовка диалогового окна
|
||||||
|
const formTitle = () => {
|
||||||
|
switch (formData.status) {
|
||||||
|
case STATUSES.CREATE:
|
||||||
|
return "Добавление раздела";
|
||||||
|
case STATUSES.EDIT:
|
||||||
|
return "Исправление раздела";
|
||||||
|
case STATUSES.DELETE:
|
||||||
|
return "Удаление раздела";
|
||||||
|
case STATUSES.RRPCONFSCTNMRK_CREATE:
|
||||||
|
return "Добавление показателя раздела";
|
||||||
|
case STATUSES.RRPCONFSCTNMRK_EDIT:
|
||||||
|
return "Исправление показателя раздела";
|
||||||
|
case STATUSES.RRPCONFSCTNMRK_DELETE:
|
||||||
|
return "Удаление показателя раздела";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//Отрисовка диалогового окна
|
||||||
|
const renderSwitch = () => {
|
||||||
|
let btnText = "";
|
||||||
|
switch (formData.status) {
|
||||||
|
case STATUSES.CREATE:
|
||||||
|
case STATUSES.RRPCONFSCTNMRK_CREATE:
|
||||||
|
btnText = "Добавить";
|
||||||
|
break;
|
||||||
|
case STATUSES.EDIT:
|
||||||
|
case STATUSES.RRPCONFSCTNMRK_EDIT:
|
||||||
|
btnText = "Исправить";
|
||||||
|
break;
|
||||||
|
case STATUSES.DELETE:
|
||||||
|
case STATUSES.RRPCONFSCTNMRK_DELETE:
|
||||||
|
btnText = "Удалить";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
handleOK({ formData });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{btnText}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
//Выбор строки
|
||||||
|
const selectRow = (showDictionary, callBack) => {
|
||||||
|
showDictionary({
|
||||||
|
unitCode: "RRPRow",
|
||||||
|
inputParameters: [{ name: "in_RN", value: formData.rowRn }],
|
||||||
|
callBack: res => {
|
||||||
|
if (res.success === true) {
|
||||||
|
callBack(res.outParameters.out_CODE, res.outParameters.out_RN);
|
||||||
|
setFormData(pv => ({
|
||||||
|
...pv,
|
||||||
|
reload: true,
|
||||||
|
rowCode: res.outParameters.out_CODE,
|
||||||
|
rowRn: res.outParameters.out_RN
|
||||||
|
}));
|
||||||
|
} else callBack(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
//Выбор графы
|
||||||
|
const selectColumn = (showDictionary, callBack) => {
|
||||||
|
showDictionary({
|
||||||
|
unitCode: "RRPColumn",
|
||||||
|
inputParameters: [{ name: "in_RN", value: formData.colRn }],
|
||||||
|
callBack: res => {
|
||||||
|
if (res.success === true) {
|
||||||
|
callBack(res.outParameters.out_CODE, res.outParameters.out_RN);
|
||||||
|
setFormData(pv => ({
|
||||||
|
...pv,
|
||||||
|
reload: true,
|
||||||
|
colCode: res.outParameters.out_CODE,
|
||||||
|
colRn: res.outParameters.out_RN
|
||||||
|
}));
|
||||||
|
} else callBack(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
//Получение мнемокода и наименования показателя раздела
|
||||||
|
const getSctnMrkCodeName = useCallback(async () => {
|
||||||
|
const data = await executeStored({
|
||||||
|
stored: "PKG_P8PANELS_RRPCONFED.RRPCONFSCTNMRK_GET_CODE_NAME",
|
||||||
|
args: {
|
||||||
|
NRRPCONFSCTN: formData.prn,
|
||||||
|
NRRPROW: formData.rowRn,
|
||||||
|
NRRPCOLUMN: formData.colRn
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setFormData(pv => ({
|
||||||
|
...pv,
|
||||||
|
reload: false,
|
||||||
|
code: data.SCODE,
|
||||||
|
name: data.SNAME
|
||||||
|
}));
|
||||||
|
}, [executeStored, formData.colRn, formData.prn, formData.rowRn]);
|
||||||
|
|
||||||
|
//Считывание наименования показателя
|
||||||
|
const getMarkName = useCallback(async () => {
|
||||||
|
const data = await executeStored({
|
||||||
|
stored: "PKG_P8PANELS_RRPCONFED.RRPCONFSCTNMRK_GET_NAME",
|
||||||
|
args: {
|
||||||
|
NRRPCONFSCTNMRK: formData.rn
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setFormData(pv => ({
|
||||||
|
...pv,
|
||||||
|
reload: false,
|
||||||
|
name: data.SNAME
|
||||||
|
}));
|
||||||
|
}, [executeStored, formData.rn]);
|
||||||
|
|
||||||
|
//Получение наименования и мнемокода показателя раздела при заполнении необходимых полей
|
||||||
|
useEffect(() => {
|
||||||
|
//Если это добавление показателя и требуется сформировать мнемокод и наименование
|
||||||
|
formData.status == STATUSES.RRPCONFSCTNMRK_CREATE && formData.reload && formData.rowRn && formData.colRn ? getSctnMrkCodeName() : null;
|
||||||
|
//Если это исправление и требуется инициализировать наименование показателя
|
||||||
|
formData.status == STATUSES.RRPCONFSCTNMRK_EDIT && formData.reload ? getMarkName() : null;
|
||||||
|
}, [formData.status, formData.reload, formData.rowRn, formData.colRn, getSctnMrkCodeName, getMarkName]);
|
||||||
|
|
||||||
|
//Генерация содержимого
|
||||||
|
return (
|
||||||
|
<Dialog open onClose={handleCancel}>
|
||||||
|
<DialogTitle>{formTitle()}</DialogTitle>
|
||||||
|
<IconButton aria-label="close" onClick={handleCancel} sx={STYLES.CLOSE_BUTTON}>
|
||||||
|
<Icon>close</Icon>
|
||||||
|
</IconButton>
|
||||||
|
<DialogContent>
|
||||||
|
{formData.status == STATUSES.DELETE || formData.status == STATUSES.RRPCONFSCTNMRK_DELETE ? (
|
||||||
|
formData.status == STATUSES.DELETE ? (
|
||||||
|
<Typography>Вы хотите удалить раздел {formData.name}?</Typography>
|
||||||
|
) : (
|
||||||
|
<Typography>Вы хотите удалить показатель раздела {formData.name}?</Typography>
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
<div>
|
||||||
|
{formData.status != STATUSES.RRPCONFSCTNMRK_EDIT ? (
|
||||||
|
<IUDFormTextField
|
||||||
|
elementCode="code"
|
||||||
|
elementValue={formData.code}
|
||||||
|
labelText="Мнемокод"
|
||||||
|
onChange={handleDialogItemChange}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
<IUDFormTextField
|
||||||
|
elementCode="name"
|
||||||
|
elementValue={formData.name}
|
||||||
|
labelText="Наименование"
|
||||||
|
onChange={handleDialogItemChange}
|
||||||
|
/>
|
||||||
|
{formData.status == STATUSES.RRPCONFSCTNMRK_CREATE ? (
|
||||||
|
<div>
|
||||||
|
<IUDFormTextField
|
||||||
|
elementCode="row"
|
||||||
|
elementValue={formData.rowCode}
|
||||||
|
labelText="Строка"
|
||||||
|
onChange={handleDialogItemChange}
|
||||||
|
dictionary={callBack => selectRow(pOnlineShowDictionary, callBack)}
|
||||||
|
/>
|
||||||
|
<IUDFormTextField
|
||||||
|
elementCode="column"
|
||||||
|
elementValue={formData.colCode}
|
||||||
|
labelText="Графа"
|
||||||
|
onChange={handleDialogItemChange}
|
||||||
|
dictionary={callBack => selectColumn(pOnlineShowDictionary, callBack)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions sx={STYLES.PADDING_DIALOG_BUTTONS_RIGHT}>
|
||||||
|
{renderSwitch()}
|
||||||
|
<Button onClick={handleCancel}>Отмена</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
//Контроль свойств - Диалог
|
||||||
|
IUDFormDialog.propTypes = {
|
||||||
|
initial: PropTypes.object.isRequired,
|
||||||
|
onClose: PropTypes.func,
|
||||||
|
onReload: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
//--------------------
|
||||||
|
//Интерфейс компонента
|
||||||
|
//--------------------
|
||||||
|
|
||||||
|
export { IUDFormDialog };
|
87
app/panels/rrp_conf_editor/IUD/iud_form_text_field.js
Normal file
87
app/panels/rrp_conf_editor/IUD/iud_form_text_field.js
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
|
||||||
|
Панель мониторинга: Компонент поля ввода
|
||||||
|
*/
|
||||||
|
|
||||||
|
//---------------------
|
||||||
|
//Подключение библиотек
|
||||||
|
//---------------------
|
||||||
|
|
||||||
|
import React, { useState, useEffect } from "react"; //Классы React
|
||||||
|
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||||||
|
import { Box, FormControl, InputLabel, Input, InputAdornment, IconButton, Icon } from "@mui/material"; //Интерфейсные компоненты
|
||||||
|
|
||||||
|
//---------
|
||||||
|
//Константы
|
||||||
|
//---------
|
||||||
|
|
||||||
|
//Стили
|
||||||
|
const STYLES = {
|
||||||
|
DIALOG_WINDOW_WIDTH: { width: 400 }
|
||||||
|
};
|
||||||
|
|
||||||
|
//---------------
|
||||||
|
//Тело компонента
|
||||||
|
//---------------
|
||||||
|
|
||||||
|
//Поле ввода
|
||||||
|
const IUDFormTextField = ({ elementCode, elementValue, labelText, onChange, dictionary, ...other }) => {
|
||||||
|
//Значение элемента
|
||||||
|
const [value, setValue] = useState(elementValue);
|
||||||
|
|
||||||
|
//При получении нового значения из вне
|
||||||
|
useEffect(() => {
|
||||||
|
setValue(elementValue);
|
||||||
|
}, [elementValue]);
|
||||||
|
|
||||||
|
//Выбор значения из словаря
|
||||||
|
const handleDictionaryClick = () =>
|
||||||
|
dictionary ? dictionary(res => (res ? handleChange({ target: { name: elementCode, value: res } }) : null)) : null;
|
||||||
|
|
||||||
|
//Изменение значения элемента
|
||||||
|
const handleChange = e => {
|
||||||
|
setValue(e.target.value);
|
||||||
|
if (onChange) onChange(e.target.name, e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
//Генерация содержимого
|
||||||
|
return (
|
||||||
|
<Box p={1}>
|
||||||
|
<FormControl variant="standard" sx={STYLES.DIALOG_WINDOW_WIDTH} {...other}>
|
||||||
|
<InputLabel htmlFor={elementCode}>{labelText}</InputLabel>
|
||||||
|
<Input
|
||||||
|
id={elementCode}
|
||||||
|
name={elementCode}
|
||||||
|
value={value ? value : ""}
|
||||||
|
endAdornment={
|
||||||
|
dictionary ? (
|
||||||
|
<InputAdornment position="end">
|
||||||
|
<IconButton aria-label={`${elementCode} select`} onClick={handleDictionaryClick} edge="end">
|
||||||
|
<Icon>list</Icon>
|
||||||
|
</IconButton>
|
||||||
|
</InputAdornment>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
onChange={handleChange}
|
||||||
|
multiline
|
||||||
|
maxRows={4}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
//Контроль свойств - Поле ввода
|
||||||
|
IUDFormTextField.propTypes = {
|
||||||
|
elementCode: PropTypes.string.isRequired,
|
||||||
|
elementValue: PropTypes.string,
|
||||||
|
labelText: PropTypes.string.isRequired,
|
||||||
|
onChange: PropTypes.func,
|
||||||
|
dictionary: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
//--------------------
|
||||||
|
//Интерфейс компонента
|
||||||
|
//--------------------
|
||||||
|
|
||||||
|
export { IUDFormTextField };
|
@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
|
|
||||||
Обще стили и константы
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---------
|
|
||||||
//Константы
|
|
||||||
//---------
|
|
||||||
|
|
||||||
//Допустимые варианты сортировки строк/граф
|
|
||||||
const COL_ROW_ORDER = [
|
|
||||||
{ name: "Номер", value: 0 },
|
|
||||||
{ name: "Код", value: 1 },
|
|
||||||
{ name: "Мнемокод", value: 2 }
|
|
||||||
];
|
|
||||||
|
|
||||||
//Типовые цвета
|
|
||||||
const BG_GRAY = "#e3e3e3";
|
|
||||||
const BG_BLUE = "#1976d210";
|
|
||||||
|
|
||||||
//Типовые размеры шрифтов
|
|
||||||
const FONT_SIZE_LARGE = "0.85rem";
|
|
||||||
const FONT_SIZE_SMALL = "0.75rem";
|
|
||||||
|
|
||||||
//Стили
|
|
||||||
const STYLES = {
|
|
||||||
TOOLBAR: { position: "absolute", right: 0, backgroundColor: BG_BLUE },
|
|
||||||
LINK: { component: "button", cursor: "pointer", width: "-webkit-fill-available" },
|
|
||||||
FONT_DATA_GRID: { fontSize: FONT_SIZE_SMALL },
|
|
||||||
FONT_MARK_CARD_HEAD: { fontSize: FONT_SIZE_LARGE },
|
|
||||||
FONT_MARK_CARD_BODY: { fontSize: FONT_SIZE_SMALL },
|
|
||||||
BG_DATA_GRID_HEAD_CELL: { backgroundColor: BG_GRAY },
|
|
||||||
BG_DATA_GRID_DATA_CELL: { backgroundColor: BG_GRAY },
|
|
||||||
BG_MARK_CARD: { backgroundColor: BG_BLUE },
|
|
||||||
BORDER_DATA_GRID_HEAD_CELL: { border: "1px solid white" },
|
|
||||||
BORDER_DATA_GRID_DATA_CELL: { borderBottom: `1px solid ${BG_GRAY}` }
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------
|
|
||||||
//Интерфейс модуля
|
|
||||||
//----------------
|
|
||||||
|
|
||||||
export { COL_ROW_ORDER, STYLES };
|
|
@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
|
|
||||||
Компонент панели: Сообщение с действиями
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---------------------
|
|
||||||
//Подключение библиотек
|
|
||||||
//---------------------
|
|
||||||
|
|
||||||
import React from "react"; //Классы React
|
|
||||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
|
||||||
import { Icon, Stack, Typography } from "@mui/material"; //Интерфейсные элементы
|
|
||||||
|
|
||||||
//---------
|
|
||||||
//Константы
|
|
||||||
//---------
|
|
||||||
|
|
||||||
//Стили
|
|
||||||
const STYLES = {
|
|
||||||
CONTAINER: { height: "100%", width: "100%" }
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------
|
|
||||||
//Тело модуля
|
|
||||||
//-----------
|
|
||||||
|
|
||||||
//Сообщение с действиями
|
|
||||||
const ActionMessage = ({ icon, title, desc, children }) => {
|
|
||||||
return (
|
|
||||||
<Stack direction={"column"} justifyContent={"center"} sx={STYLES.CONTAINER}>
|
|
||||||
<Stack direction={"row"} justifyContent={"center"} alignItems={"center"}>
|
|
||||||
<Icon color={"disabled"}>{icon}</Icon>
|
|
||||||
<Typography align={"center"} color={"text.secondary"} variant={"button"}>
|
|
||||||
{title}
|
|
||||||
</Typography>
|
|
||||||
</Stack>
|
|
||||||
<Typography align={"center"} variant={"caption"}>
|
|
||||||
{desc}
|
|
||||||
</Typography>
|
|
||||||
<Stack direction={"row"} justifyContent={"center"} alignItems={"center"}>
|
|
||||||
{children}
|
|
||||||
</Stack>
|
|
||||||
</Stack>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Контроль свойств - Сообщение с действиями
|
|
||||||
ActionMessage.propTypes = {
|
|
||||||
icon: PropTypes.string.isRequired,
|
|
||||||
title: PropTypes.string.isRequired,
|
|
||||||
desc: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
|
|
||||||
children: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)])
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------
|
|
||||||
//Интерфейс модуля
|
|
||||||
//----------------
|
|
||||||
|
|
||||||
export { ActionMessage };
|
|
@ -1,87 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
|
|
||||||
Компонент панели: Диалог дополнительной информации
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---------------------
|
|
||||||
//Подключение библиотек
|
|
||||||
//---------------------
|
|
||||||
|
|
||||||
import React from "react"; //Классы React
|
|
||||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
|
||||||
import { Typography, List, ListItem } from "@mui/material"; //Интерфейсные элементы
|
|
||||||
import { Form } from "./form"; //Типовая форма
|
|
||||||
|
|
||||||
//---------
|
|
||||||
//Константы
|
|
||||||
//---------
|
|
||||||
|
|
||||||
//Стили
|
|
||||||
const STYLES = {
|
|
||||||
HELP_LIST_ITEM: { padding: "0px 0px 0px 5px", whiteSpace: "pre" },
|
|
||||||
HELP_LIST_ITEM_NAME: { fontWeight: "bold", minWidth: "45px" }
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------
|
|
||||||
//Вспомогательные функции и компоненты
|
|
||||||
//------------------------------------
|
|
||||||
|
|
||||||
//Элемент списка расшифровки состава
|
|
||||||
const HelpListItem = ({ name, desc }) => {
|
|
||||||
return (
|
|
||||||
<ListItem sx={STYLES.HELP_LIST_ITEM}>
|
|
||||||
<Typography sx={STYLES.HELP_LIST_ITEM_NAME}>{name}</Typography>
|
|
||||||
<Typography>{` - ${desc}`}</Typography>
|
|
||||||
</ListItem>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Контроль свойств - Элемент списка расшифровки состава
|
|
||||||
HelpListItem.propTypes = {
|
|
||||||
name: PropTypes.string.isRequired,
|
|
||||||
desc: PropTypes.string.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------
|
|
||||||
//Тело модуля
|
|
||||||
//-----------
|
|
||||||
|
|
||||||
//Диалог дополнительной информации
|
|
||||||
const DialogHelp = ({ onClose }) => {
|
|
||||||
//При закрытии диалога
|
|
||||||
const handleClose = () => onClose && onClose();
|
|
||||||
|
|
||||||
//Генерация содержимого
|
|
||||||
return (
|
|
||||||
<Form title={"Информация"} onClose={handleClose}>
|
|
||||||
<Typography>Карточки показателей содержат сокращенную информацию о типе состава показателя. Список сокращений:</Typography>
|
|
||||||
<List disablePadding={true}>
|
|
||||||
<HelpListItem name={"fx"} desc={"формула"} />
|
|
||||||
<HelpListItem name={"СЗ"} desc={"статическое значение"} />
|
|
||||||
<HelpListItem name={"ХП"} desc={"хранимая процедура"} />
|
|
||||||
<HelpListItem name={"РП"} desc={"расчетный показатель"} />
|
|
||||||
<HelpListItem name={"ХО"} desc={"хозяйственные операции"} />
|
|
||||||
<HelpListItem name={"РСДК"} desc={"расчёты с дебиторами/кредиторами"} />
|
|
||||||
<HelpListItem name={"ОС"} desc={"остатки средств по счетам"} />
|
|
||||||
<HelpListItem name={"ТМЦ"} desc={"остатки товарно-материальных ценностей"} />
|
|
||||||
<HelpListItem name={"ДКЗ"} desc={"дебиторская/кредиторская задолженность"} />
|
|
||||||
<HelpListItem name={"ИК"} desc={"инвентарная картотека"} />
|
|
||||||
<HelpListItem name={"МБП"} desc={"картотека МБП"} />
|
|
||||||
<HelpListItem name={"КОБП"} desc={"картотека операций будущих периодов"} />
|
|
||||||
<HelpListItem name={"ДПНП"} desc={"декларация по налогу на прибыль"} />
|
|
||||||
<HelpListItem name={"РО"} desc={"регламентированный отчет"} />
|
|
||||||
</List>
|
|
||||||
</Form>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Контроль свойств - Диалог дополнительной информации
|
|
||||||
DialogHelp.propTypes = {
|
|
||||||
onClose: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------
|
|
||||||
//Интерфейс модуля
|
|
||||||
//----------------
|
|
||||||
|
|
||||||
export { DialogHelp };
|
|
@ -1,103 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
|
|
||||||
Компонент панели: Диалог добавления/исправления показателя
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---------------------
|
|
||||||
//Подключение библиотек
|
|
||||||
//---------------------
|
|
||||||
|
|
||||||
import React from "react"; //Классы React
|
|
||||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
|
||||||
import { useDictionary } from "../hooks"; //Кастомные хуки
|
|
||||||
import { Form } from "./form"; //Типовая форма
|
|
||||||
|
|
||||||
//-----------
|
|
||||||
//Тело модуля
|
|
||||||
//-----------
|
|
||||||
|
|
||||||
//Диалог добавления/исправления показателя
|
|
||||||
const DialogMarkIU = ({
|
|
||||||
code = "",
|
|
||||||
name = "",
|
|
||||||
rowCode = "",
|
|
||||||
rowVersion = "",
|
|
||||||
columnCode = "",
|
|
||||||
columnVersion = "",
|
|
||||||
insert = true,
|
|
||||||
onOk,
|
|
||||||
onCancel
|
|
||||||
}) => {
|
|
||||||
//Нажатие на кнопку "Ok"
|
|
||||||
const handleOk = values => onOk && onOk({ ...values });
|
|
||||||
|
|
||||||
//Нажатие на кнопку "Отмена"
|
|
||||||
const handleCancel = () => onCancel && onCancel();
|
|
||||||
|
|
||||||
//Хуки для работы со словарями
|
|
||||||
const { selectRRPRow, selectRRPColumn } = useDictionary();
|
|
||||||
|
|
||||||
//Выбор строки из словаря
|
|
||||||
const selectRow = (currentFormValues, setFormValues) => {
|
|
||||||
selectRRPRow(
|
|
||||||
currentFormValues.rowCode,
|
|
||||||
currentFormValues.rowVersion,
|
|
||||||
selectResult =>
|
|
||||||
selectResult &&
|
|
||||||
setFormValues([
|
|
||||||
{ name: "rowCode", value: selectResult.code },
|
|
||||||
{ name: "rowVersion", value: selectResult.version }
|
|
||||||
])
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Выбор графы из словаря
|
|
||||||
const selectColumn = (currentFormValues, setFormValues) => {
|
|
||||||
selectRRPColumn(
|
|
||||||
currentFormValues.columnCode,
|
|
||||||
currentFormValues.columnVersion,
|
|
||||||
selectResult =>
|
|
||||||
selectResult &&
|
|
||||||
setFormValues([
|
|
||||||
{ name: "columnCode", value: selectResult.code },
|
|
||||||
{ name: "columnVersion", value: selectResult.version }
|
|
||||||
])
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Генерация содержимого
|
|
||||||
return (
|
|
||||||
<Form
|
|
||||||
title={`${insert === true ? "Добавление" : "Исправление"} показателя`}
|
|
||||||
fields={[
|
|
||||||
{ elementCode: "code", elementValue: code, labelText: "Мнемокод" },
|
|
||||||
{ elementCode: "name", elementValue: name, labelText: "Наименование" },
|
|
||||||
{ elementCode: "rowCode", elementValue: rowCode, labelText: "Строка", dictionary: selectRow },
|
|
||||||
{ elementCode: "rowVersion", elementValue: rowVersion, labelText: "Редакция строки", disabled: true },
|
|
||||||
{ elementCode: "columnCode", elementValue: columnCode, labelText: "Графа", dictionary: selectColumn },
|
|
||||||
{ elementCode: "columnVersion", elementValue: columnVersion, labelText: "Редакция графы", disabled: true }
|
|
||||||
]}
|
|
||||||
onOk={handleOk}
|
|
||||||
onCancel={handleCancel}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Контроль свойств - Диалог добавления/исправления показателя
|
|
||||||
DialogMarkIU.propTypes = {
|
|
||||||
code: PropTypes.string,
|
|
||||||
name: PropTypes.string,
|
|
||||||
rowCode: PropTypes.string,
|
|
||||||
rowVersion: PropTypes.string,
|
|
||||||
columnCode: PropTypes.string,
|
|
||||||
columnVersion: PropTypes.string,
|
|
||||||
insert: PropTypes.bool,
|
|
||||||
onOk: PropTypes.func,
|
|
||||||
onCancel: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------
|
|
||||||
//Интерфейс модуля
|
|
||||||
//----------------
|
|
||||||
|
|
||||||
export { DialogMarkIU };
|
|
@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
|
|
||||||
Компонент панели: Диалог сортировки
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---------------------
|
|
||||||
//Подключение библиотек
|
|
||||||
//---------------------
|
|
||||||
|
|
||||||
import React from "react"; //Классы React
|
|
||||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
|
||||||
import { Form } from "./form"; //Типовая форма
|
|
||||||
import { COL_ROW_ORDER } from "../common"; //Обще стили и константы
|
|
||||||
|
|
||||||
//-----------
|
|
||||||
//Тело модуля
|
|
||||||
//-----------
|
|
||||||
|
|
||||||
//Диалог сортировки
|
|
||||||
const DialogOrder = ({ rowOrder = 0, columnOrder = 0, onOk, onCancel }) => {
|
|
||||||
//Нажатие на кнопку "Ok"
|
|
||||||
const handleOk = values => onOk && onOk({ ...values });
|
|
||||||
|
|
||||||
//Нажатие на кнопку "Отмена"
|
|
||||||
const handleCancel = () => onCancel && onCancel();
|
|
||||||
|
|
||||||
//Генерация содержимого
|
|
||||||
return (
|
|
||||||
<Form
|
|
||||||
title={"Сортировка"}
|
|
||||||
fields={[
|
|
||||||
{ elementCode: "rowOrder", elementValue: rowOrder, labelText: "Строки", list: COL_ROW_ORDER },
|
|
||||||
{ elementCode: "columnOrder", elementValue: columnOrder, labelText: "Графы", list: COL_ROW_ORDER }
|
|
||||||
]}
|
|
||||||
onOk={handleOk}
|
|
||||||
onCancel={handleCancel}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Контроль свойств - Диалог сортировки
|
|
||||||
DialogOrder.propTypes = {
|
|
||||||
rowOrder: PropTypes.number,
|
|
||||||
columnOrder: PropTypes.number,
|
|
||||||
onOk: PropTypes.func,
|
|
||||||
onCancel: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------
|
|
||||||
//Интерфейс модуля
|
|
||||||
//----------------
|
|
||||||
|
|
||||||
export { DialogOrder };
|
|
@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
|
|
||||||
Компонент панели: Диалог добавления/исправления раздела
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---------------------
|
|
||||||
//Подключение библиотек
|
|
||||||
//---------------------
|
|
||||||
|
|
||||||
import React from "react"; //Классы React
|
|
||||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
|
||||||
import { Form } from "./form"; //Типовая форма
|
|
||||||
|
|
||||||
//-----------
|
|
||||||
//Тело модуля
|
|
||||||
//-----------
|
|
||||||
|
|
||||||
//Диалог добавления/исправления раздела
|
|
||||||
const DialogSectionIU = ({ code = "", name = "", insert = true, onOk, onCancel }) => {
|
|
||||||
//Нажатие на кнопку "Ok"
|
|
||||||
const handleOk = values => onOk && onOk({ ...values });
|
|
||||||
|
|
||||||
//Нажатие на кнопку "Отмена"
|
|
||||||
const handleCancel = () => onCancel && onCancel();
|
|
||||||
|
|
||||||
//Генерация содержимого
|
|
||||||
return (
|
|
||||||
<Form
|
|
||||||
title={`${insert === true ? "Добавление" : "Исправление"} раздела`}
|
|
||||||
fields={[
|
|
||||||
{ elementCode: "code", elementValue: code, labelText: "Мнемокод" },
|
|
||||||
{ elementCode: "name", elementValue: name, labelText: "Наименование" }
|
|
||||||
]}
|
|
||||||
onOk={handleOk}
|
|
||||||
onCancel={handleCancel}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Контроль свойств - Диалог добавления/исправления раздела
|
|
||||||
DialogSectionIU.propTypes = {
|
|
||||||
code: PropTypes.string,
|
|
||||||
name: PropTypes.string,
|
|
||||||
insert: PropTypes.bool,
|
|
||||||
onOk: PropTypes.func,
|
|
||||||
onCancel: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------
|
|
||||||
//Интерфейс модуля
|
|
||||||
//----------------
|
|
||||||
|
|
||||||
export { DialogSectionIU };
|
|
@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
|
|
||||||
Компонент панели: Форма
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---------------------
|
|
||||||
//Подключение библиотек
|
|
||||||
//---------------------
|
|
||||||
|
|
||||||
import React, { useEffect, useState } from "react"; //Классы React
|
|
||||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
|
||||||
import { Dialog, DialogTitle, DialogContent, DialogActions, Button } from "@mui/material"; //Интерфейсные компоненты
|
|
||||||
import { BUTTONS } from "../../../../app.text"; //Общие текстовые ресурсы
|
|
||||||
import { FORM_FILED, FormField } from "./form_field"; //Элемент формы
|
|
||||||
|
|
||||||
//-----------
|
|
||||||
//Тело модуля
|
|
||||||
//-----------
|
|
||||||
|
|
||||||
//Форма
|
|
||||||
const Form = ({ title, fields = [], children, onOk, onCancel, onClose }) => {
|
|
||||||
//Состояние формы
|
|
||||||
const [state, setState] = useState({});
|
|
||||||
|
|
||||||
//При изменении элемента формы
|
|
||||||
const handleFieldChange = (name, value) => setState(pv => ({ ...pv, [name]: value }));
|
|
||||||
|
|
||||||
//При нажатии на "ОК" формы
|
|
||||||
const handleOk = () => onOk && onOk(state);
|
|
||||||
|
|
||||||
//При нажатии на "Отмена" формы
|
|
||||||
const handleCancel = () => onCancel && onCancel();
|
|
||||||
|
|
||||||
//При нажатии на "Закрыть" формы
|
|
||||||
const handleClose = () => (onClose ? onClose() : onCancel ? onCancel() : null);
|
|
||||||
|
|
||||||
//При подключении к старнице
|
|
||||||
useEffect(() => {
|
|
||||||
setState(fields.reduce((res, f) => ({ ...res, [f.elementCode]: f.elementValue == undefined ? null : f.elementValue }), {}));
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
//Формирование представления
|
|
||||||
return (
|
|
||||||
<Dialog onClose={handleClose} open>
|
|
||||||
<DialogTitle>{title}</DialogTitle>
|
|
||||||
<DialogContent>
|
|
||||||
{fields.map((f, i) => (
|
|
||||||
<FormField key={i} {...f} elementValue={state[f.elementCode]} formValues={state} onChange={handleFieldChange} />
|
|
||||||
))}
|
|
||||||
{children}
|
|
||||||
</DialogContent>
|
|
||||||
<DialogActions>
|
|
||||||
{onOk && <Button onClick={handleOk}>{BUTTONS.OK}</Button>}
|
|
||||||
{onCancel && <Button onClick={handleCancel}>{BUTTONS.CANCEL}</Button>}
|
|
||||||
{onClose && <Button onClick={handleClose}>{BUTTONS.CLOSE}</Button>}
|
|
||||||
</DialogActions>
|
|
||||||
</Dialog>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Контроль свойств - Форма
|
|
||||||
Form.propTypes = {
|
|
||||||
title: PropTypes.string.isRequired,
|
|
||||||
fields: PropTypes.arrayOf(PropTypes.shape(FORM_FILED)),
|
|
||||||
children: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)]),
|
|
||||||
onOk: PropTypes.func,
|
|
||||||
onCancel: PropTypes.func,
|
|
||||||
onClose: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------
|
|
||||||
//Интерфейс модуля
|
|
||||||
//----------------
|
|
||||||
|
|
||||||
export { Form };
|
|
@ -1,149 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
|
|
||||||
Компонент панели: Поле ввода формы
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---------------------
|
|
||||||
//Подключение библиотек
|
|
||||||
//---------------------
|
|
||||||
|
|
||||||
import React, { useState, useEffect } from "react"; //Классы React
|
|
||||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
|
||||||
import { Box, Icon, Input, InputAdornment, FormControl, Select, InputLabel, MenuItem, IconButton, Autocomplete, TextField } from "@mui/material"; //Интерфейсные компоненты
|
|
||||||
|
|
||||||
//---------
|
|
||||||
//Константы
|
|
||||||
//---------
|
|
||||||
|
|
||||||
//Формат свойств поля формы
|
|
||||||
const FORM_FILED = {
|
|
||||||
elementCode: PropTypes.string.isRequired,
|
|
||||||
elementValue: PropTypes.oneOfType([PropTypes.number, PropTypes.string, PropTypes.instanceOf(Date)]),
|
|
||||||
labelText: PropTypes.string.isRequired,
|
|
||||||
onChange: PropTypes.func,
|
|
||||||
dictionary: PropTypes.func,
|
|
||||||
list: PropTypes.array,
|
|
||||||
type: PropTypes.string,
|
|
||||||
freeSolo: PropTypes.bool,
|
|
||||||
disabled: PropTypes.bool,
|
|
||||||
formValues: PropTypes.object
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------
|
|
||||||
//Тело модуля
|
|
||||||
//-----------
|
|
||||||
|
|
||||||
//Поле ввода формы
|
|
||||||
const FormField = ({
|
|
||||||
elementCode,
|
|
||||||
elementValue,
|
|
||||||
labelText,
|
|
||||||
onChange,
|
|
||||||
dictionary,
|
|
||||||
list,
|
|
||||||
type,
|
|
||||||
freeSolo = false,
|
|
||||||
disabled = false,
|
|
||||||
formValues,
|
|
||||||
...other
|
|
||||||
}) => {
|
|
||||||
//Значение элемента
|
|
||||||
const [value, setValue] = useState(elementValue);
|
|
||||||
|
|
||||||
//При получении нового значения из вне
|
|
||||||
useEffect(() => {
|
|
||||||
setValue(elementValue);
|
|
||||||
}, [elementValue]);
|
|
||||||
|
|
||||||
//Выбор значения из словаря
|
|
||||||
const handleDictionaryClick = () => dictionary && dictionary(formValues, res => (res ? res.map(i => handleChangeByName(i.name, i.value)) : null));
|
|
||||||
|
|
||||||
//Изменение значения элемента (по событию)
|
|
||||||
const handleChange = e => {
|
|
||||||
setValue(e.target.value);
|
|
||||||
if (onChange) onChange(e.target.name, e.target.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Изменение значения элемента (по имени и значению)
|
|
||||||
const handleChangeByName = (name, value) => {
|
|
||||||
if (name === elementCode) setValue(value);
|
|
||||||
if (onChange) onChange(name, value);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Генерация содержимого
|
|
||||||
return (
|
|
||||||
<Box p={1}>
|
|
||||||
<FormControl variant="standard" fullWidth {...other}>
|
|
||||||
{list ? (
|
|
||||||
freeSolo ? (
|
|
||||||
<Autocomplete
|
|
||||||
id={elementCode}
|
|
||||||
name={elementCode}
|
|
||||||
freeSolo
|
|
||||||
disabled={disabled}
|
|
||||||
inputValue={value ? value : ""}
|
|
||||||
onChange={(event, newValue) => handleChangeByName(elementCode, newValue)}
|
|
||||||
onInputChange={(event, newInputValue) => handleChangeByName(elementCode, newInputValue)}
|
|
||||||
options={list}
|
|
||||||
renderInput={params => <TextField {...params} label={labelText} name={elementCode} variant={"standard"} />}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<InputLabel id={`${elementCode}Lable`} shrink>
|
|
||||||
{labelText}
|
|
||||||
</InputLabel>
|
|
||||||
<Select
|
|
||||||
labelId={`${elementCode}Lable`}
|
|
||||||
id={elementCode}
|
|
||||||
name={elementCode}
|
|
||||||
label={labelText}
|
|
||||||
value={[undefined, null].includes(value) ? "" : value}
|
|
||||||
onChange={handleChange}
|
|
||||||
disabled={disabled}
|
|
||||||
displayEmpty
|
|
||||||
>
|
|
||||||
{list.map((item, i) => (
|
|
||||||
<MenuItem key={i} value={[undefined, null].includes(item.value) ? "" : item.value}>
|
|
||||||
{item.name}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<InputLabel {...(type == "date" ? { shrink: true } : {})} htmlFor={elementCode}>
|
|
||||||
{labelText}
|
|
||||||
</InputLabel>
|
|
||||||
<Input
|
|
||||||
id={elementCode}
|
|
||||||
name={elementCode}
|
|
||||||
value={value ? value : ""}
|
|
||||||
endAdornment={
|
|
||||||
dictionary ? (
|
|
||||||
<InputAdornment position="end">
|
|
||||||
<IconButton aria-label={`${elementCode} select`} onClick={handleDictionaryClick} edge="end">
|
|
||||||
<Icon>list</Icon>
|
|
||||||
</IconButton>
|
|
||||||
</InputAdornment>
|
|
||||||
) : null
|
|
||||||
}
|
|
||||||
{...(type ? { type } : {})}
|
|
||||||
onChange={handleChange}
|
|
||||||
disabled={disabled}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</FormControl>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Контроль свойств - Поле ввода формы
|
|
||||||
FormField.propTypes = FORM_FILED;
|
|
||||||
|
|
||||||
//----------------
|
|
||||||
//Интерфейс модуля
|
|
||||||
//----------------
|
|
||||||
|
|
||||||
export { FORM_FILED, FormField };
|
|
343
app/panels/rrp_conf_editor/components/layouts.js
Normal file
343
app/panels/rrp_conf_editor/components/layouts.js
Normal file
@ -0,0 +1,343 @@
|
|||||||
|
/*
|
||||||
|
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
|
||||||
|
Дополнительная разметка и вёрстка клиентских элементов
|
||||||
|
*/
|
||||||
|
|
||||||
|
//---------------------
|
||||||
|
//Подключение библиотек
|
||||||
|
//---------------------
|
||||||
|
|
||||||
|
import React, { useState } from "react"; //Классы React
|
||||||
|
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||||||
|
import {
|
||||||
|
IconButton,
|
||||||
|
Icon,
|
||||||
|
Link,
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardHeader,
|
||||||
|
Menu,
|
||||||
|
MenuItem,
|
||||||
|
Table,
|
||||||
|
TableRow,
|
||||||
|
TableCell,
|
||||||
|
TableBody,
|
||||||
|
Box,
|
||||||
|
Typography
|
||||||
|
} from "@mui/material"; //Интерфейсные компоненты
|
||||||
|
|
||||||
|
//---------
|
||||||
|
//Константы
|
||||||
|
//---------
|
||||||
|
|
||||||
|
//Стили
|
||||||
|
export const STYLES = {
|
||||||
|
BOX_ROW: { display: "flex", justifyContent: "center", alignItems: "center" },
|
||||||
|
LINK_STYLE: { component: "button", cursor: "pointer", width: "-webkit-fill-available" },
|
||||||
|
DATA_CELL: columnDef => ({
|
||||||
|
padding: "5px 5px",
|
||||||
|
fontSize: "0.775rem",
|
||||||
|
letterSpacing: "0.005em",
|
||||||
|
textAlign: "center",
|
||||||
|
wordBreak: "break-all",
|
||||||
|
backgroundColor: columnDef.name === "SROW_NAME" ? "#b4b4b4" : "trasparent"
|
||||||
|
}),
|
||||||
|
DATA_CELL_CARD: {
|
||||||
|
padding: "0px 3px 3px 0px",
|
||||||
|
border: "1px solid lightgrey"
|
||||||
|
},
|
||||||
|
DATA_CELL_CARD_HEADER: {
|
||||||
|
padding: "0px"
|
||||||
|
},
|
||||||
|
DATA_CELL_CARD_SUBHEADER: {
|
||||||
|
textAlign: "left",
|
||||||
|
paddingLeft: "10px",
|
||||||
|
fontSize: "1rem",
|
||||||
|
fontWeight: "450"
|
||||||
|
},
|
||||||
|
DATA_CELL_CARD_CONTENT: listLength => {
|
||||||
|
return {
|
||||||
|
fontSize: "0.75rem",
|
||||||
|
padding: "5px 0px",
|
||||||
|
minHeight: "105px",
|
||||||
|
maxHeight: "105px",
|
||||||
|
overflowY: "auto",
|
||||||
|
"&::-webkit-scrollbar": {
|
||||||
|
width: "8px"
|
||||||
|
},
|
||||||
|
"&::-webkit-scrollbar-track": {
|
||||||
|
borderRadius: "8px",
|
||||||
|
backgroundColor: "#EBEBEB"
|
||||||
|
},
|
||||||
|
"&::-webkit-scrollbar-thumb": {
|
||||||
|
borderRadius: "8px",
|
||||||
|
backgroundColor: "#b4b4b4"
|
||||||
|
},
|
||||||
|
"&::-webkit-scrollbar-thumb:hover": {
|
||||||
|
backgroundColor: "#808080"
|
||||||
|
},
|
||||||
|
"&:last-child": {
|
||||||
|
paddingBottom: "0px"
|
||||||
|
},
|
||||||
|
...(listLength === 0 ? { display: "flex", justifyContent: "center", alignItems: "center" } : null)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
DATA_CELL_CARD_CONTEXT_FONT: {
|
||||||
|
fontSize: "0.75rem"
|
||||||
|
},
|
||||||
|
DATA_CELL_CARD_CONTEXT_MARK: {
|
||||||
|
padding: "0px 0px 0px 10px",
|
||||||
|
borderBottom: "1px solid #EBEBEB"
|
||||||
|
},
|
||||||
|
DATA_CELL_CN: {
|
||||||
|
textOverflow: "ellipsis",
|
||||||
|
overflow: "hidden",
|
||||||
|
whiteSpace: "pre",
|
||||||
|
padding: "0px 5px",
|
||||||
|
maxWidth: "100px",
|
||||||
|
border: "none"
|
||||||
|
},
|
||||||
|
GRID_PANEL_CARD: { maxWidth: 400, flexDirection: "column", display: "flex" },
|
||||||
|
MARK_INFO: {
|
||||||
|
fontSize: "0.8rem",
|
||||||
|
textAlign: "left",
|
||||||
|
textOverflow: "ellipsis",
|
||||||
|
overflow: "hidden",
|
||||||
|
whiteSpace: "pre",
|
||||||
|
maxWidth: "max-content",
|
||||||
|
width: "-webkit-fill-available"
|
||||||
|
},
|
||||||
|
BUTTON_CN_INSERT: {
|
||||||
|
padding: "0px 8px",
|
||||||
|
marginBottom: "2px",
|
||||||
|
"& .MuiIcon-root": {
|
||||||
|
fontWeight: "bold",
|
||||||
|
fontSize: "1rem"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
HEAD_CELL: {
|
||||||
|
backgroundColor: "#b4b4b4",
|
||||||
|
textAlign: "center"
|
||||||
|
},
|
||||||
|
HEAD_CELL_STACK: {
|
||||||
|
justifyContent: "space-around"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
//Вспомогательные функции и компоненты
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
//Действия карты показателя
|
||||||
|
const DataCellCardActions = ({ columnDef, menuItems, cellData, markRn }) => {
|
||||||
|
//Собственное состояние
|
||||||
|
const [cardActions, setCardActions] = useState({ anchorMenuMethods: null, openMethods: false });
|
||||||
|
|
||||||
|
//По нажатию на открытие меню действий
|
||||||
|
const handleMethodsMenuButtonClick = event => {
|
||||||
|
setCardActions(pv => ({ ...pv, anchorMenuMethods: event.currentTarget, openMethods: true }));
|
||||||
|
};
|
||||||
|
|
||||||
|
//При закрытии меню
|
||||||
|
const handleMethodsMenuClose = () => {
|
||||||
|
setCardActions(pv => ({ ...pv, anchorMenuMethods: null, openMethods: false }));
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Box sx={STYLES.BOX_ROW}>
|
||||||
|
<IconButton id={`${columnDef.name}_menu_button`} aria-haspopup="true" onClick={handleMethodsMenuButtonClick}>
|
||||||
|
<Icon>more_vert</Icon>
|
||||||
|
</IconButton>
|
||||||
|
<Menu
|
||||||
|
id={`${columnDef.name}_menu`}
|
||||||
|
anchorEl={cardActions.anchorMenuMethods}
|
||||||
|
open={cardActions.openMethods}
|
||||||
|
onClose={handleMethodsMenuClose}
|
||||||
|
>
|
||||||
|
{menuItems.map(el => {
|
||||||
|
return (
|
||||||
|
<MenuItem
|
||||||
|
key={`${cellData}_${el.method}`}
|
||||||
|
onClick={() => {
|
||||||
|
el.func(markRn);
|
||||||
|
handleMethodsMenuClose();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Icon>{el.icon}</Icon>
|
||||||
|
{el.name}
|
||||||
|
</MenuItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Menu>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
//Контроль свойств - Действия карты показателя
|
||||||
|
DataCellCardActions.propTypes = {
|
||||||
|
columnDef: PropTypes.object.isRequired,
|
||||||
|
menuItems: PropTypes.array,
|
||||||
|
cellData: PropTypes.any,
|
||||||
|
markRn: PropTypes.number
|
||||||
|
};
|
||||||
|
|
||||||
|
//Таблица составов показателя
|
||||||
|
const MarkCnList = ({ markRn, list, handleMarkCnOpen }) => {
|
||||||
|
return (
|
||||||
|
<Table>
|
||||||
|
<TableBody>
|
||||||
|
{list.map((el, index) => {
|
||||||
|
return (
|
||||||
|
<TableRow key={index}>
|
||||||
|
<TableCell
|
||||||
|
sx={{ ...STYLES.DATA_CELL_CN, ...STYLES.DATA_CELL_CARD_CONTEXT_FONT }}
|
||||||
|
title={el.SDESC}
|
||||||
|
align="left"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<Link sx={STYLES.LINK_STYLE} onClick={() => handleMarkCnOpen(markRn, el.NRN)}>
|
||||||
|
{el.SDESC}
|
||||||
|
</Link>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
//Контроль свойств - Таблица составов показателя
|
||||||
|
MarkCnList.propTypes = {
|
||||||
|
markRn: PropTypes.number.isRequired,
|
||||||
|
list: PropTypes.array.isRequired,
|
||||||
|
handleMarkCnOpen: PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
//Ячейка таблицы строки
|
||||||
|
const DataCellContent = ({ row, columnDef, menuItems, sectionRn, handleMarkAdd, handleMarkOpen, handleMarkCnOpen, handleMarkCnInsert }) => {
|
||||||
|
//Считываем информацию о показателе
|
||||||
|
let mark = {
|
||||||
|
sectionRn: sectionRn,
|
||||||
|
data: row[columnDef.name],
|
||||||
|
nRn: row["NMARK_RN_" + columnDef.name.substring(5)],
|
||||||
|
sCode: row["SMARK_CODE_" + columnDef.name.substring(5)],
|
||||||
|
sRowCode: row["SROW_CODE"],
|
||||||
|
nRowRn: row["NROW_RN"],
|
||||||
|
sColCode: columnDef.name.substring(5),
|
||||||
|
nColRn: row["NCOL_RN_" + columnDef.name.substring(5)],
|
||||||
|
rCnList: row["MARK_CNS_" + columnDef.name.substring(5)] ? [...row["MARK_CNS_" + columnDef.name.substring(5)]] : []
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{mark.nRn ? (
|
||||||
|
<Card variant={"plain"} sx={STYLES.DATA_CELL_CARD}>
|
||||||
|
<CardHeader
|
||||||
|
sx={STYLES.DATA_CELL_CARD_HEADER}
|
||||||
|
subheader={
|
||||||
|
<Box>
|
||||||
|
<Link sx={STYLES.LINK_STYLE} onClick={() => (handleMarkOpen ? handleMarkOpen(mark.nRn) : null)}>
|
||||||
|
Состав
|
||||||
|
</Link>
|
||||||
|
{mark.rCnList.length !== 0 ? (
|
||||||
|
<IconButton sx={STYLES.BUTTON_CN_INSERT} aria-haspopup="true" onClick={() => handleMarkCnInsert(mark.nRn)}>
|
||||||
|
<Icon>add</Icon>
|
||||||
|
</IconButton>
|
||||||
|
) : null}
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
subheaderTypographyProps={STYLES.DATA_CELL_CARD_SUBHEADER}
|
||||||
|
action={<DataCellCardActions columnDef={columnDef} menuItems={menuItems} cellData={mark.data} markRn={mark.nRn} />}
|
||||||
|
></CardHeader>
|
||||||
|
<CardContent sx={STYLES.DATA_CELL_CARD_CONTEXT_MARK}>
|
||||||
|
<Typography sx={STYLES.MARK_INFO} title={mark.sCode}>
|
||||||
|
{mark.sCode}
|
||||||
|
</Typography>
|
||||||
|
</CardContent>
|
||||||
|
<CardContent sx={STYLES.DATA_CELL_CARD_CONTENT(mark.rCnList.length)}>
|
||||||
|
{mark.rCnList.length !== 0 ? (
|
||||||
|
<MarkCnList markRn={mark.nRn} list={mark.rCnList} handleMarkCnOpen={handleMarkCnOpen} />
|
||||||
|
) : (
|
||||||
|
<Box>
|
||||||
|
<Typography sx={STYLES.DATA_CELL_CARD_CONTEXT_FONT}>Показатель не имеет состава</Typography>
|
||||||
|
<Link sx={STYLES.LINK_STYLE} onClick={() => (handleMarkCnInsert ? handleMarkCnInsert(mark.nRn) : null)}>
|
||||||
|
Добавить
|
||||||
|
</Link>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
) : (
|
||||||
|
<Box>
|
||||||
|
<Typography sx={STYLES.DATA_CELL_CARD_CONTEXT_FONT}>Показатель отсутствует</Typography>
|
||||||
|
<Link
|
||||||
|
sx={STYLES.LINK_STYLE}
|
||||||
|
onClick={() =>
|
||||||
|
handleMarkOpen ? handleMarkAdd(mark.sectionRn, mark.nRowRn, mark.sRowCode, mark.nColRn, mark.sColCode) : null
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Добавить
|
||||||
|
</Link>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
//Контроль свойств - Ячейка таблицы строки
|
||||||
|
DataCellContent.propTypes = {
|
||||||
|
row: PropTypes.object.isRequired,
|
||||||
|
columnDef: PropTypes.object.isRequired,
|
||||||
|
menuItems: PropTypes.array,
|
||||||
|
sectionRn: PropTypes.number.isRequired,
|
||||||
|
handleMarkAdd: PropTypes.func,
|
||||||
|
handleMarkOpen: PropTypes.func,
|
||||||
|
handleMarkCnOpen: PropTypes.func,
|
||||||
|
handleMarkCnInsert: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------
|
||||||
|
//Тело модуля
|
||||||
|
//-----------
|
||||||
|
|
||||||
|
//Генерация представления ячейки c данными показателя раздела регламентированного отчета
|
||||||
|
export const confSctnMrkCellRender = ({
|
||||||
|
row,
|
||||||
|
columnDef,
|
||||||
|
sectionRn,
|
||||||
|
handleMarkAdd,
|
||||||
|
handleMarkOpen,
|
||||||
|
handleMarkCnOpen,
|
||||||
|
handleMarkCnInsert,
|
||||||
|
menuItems
|
||||||
|
}) => {
|
||||||
|
//Иницализируем стили
|
||||||
|
let cellStyle = STYLES.DATA_CELL(columnDef);
|
||||||
|
//Считываем значение
|
||||||
|
let data = row[columnDef.name];
|
||||||
|
//Если это не наименование строки и есть значение
|
||||||
|
columnDef.name != "SROW_NAME" && data != undefined && columnDef.visible == true
|
||||||
|
? (data = (
|
||||||
|
<DataCellContent
|
||||||
|
row={row}
|
||||||
|
columnDef={columnDef}
|
||||||
|
menuItems={menuItems}
|
||||||
|
sectionRn={sectionRn}
|
||||||
|
handleMarkAdd={handleMarkAdd}
|
||||||
|
handleMarkOpen={handleMarkOpen}
|
||||||
|
handleMarkCnOpen={handleMarkCnOpen}
|
||||||
|
handleMarkCnInsert={handleMarkCnInsert}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
: null;
|
||||||
|
return { cellStyle: { ...cellStyle }, data: data };
|
||||||
|
};
|
||||||
|
|
||||||
|
//Генерация представления ячейки заголовка группы c данными показателя раздела регламентированного отчета
|
||||||
|
export const confSctnMrkHeadCellRender = ({ columnDef }) => {
|
||||||
|
return {
|
||||||
|
cellStyle: STYLES.HEAD_CELL,
|
||||||
|
stackStyle: STYLES.HEAD_CELL_STACK,
|
||||||
|
data: columnDef.caption
|
||||||
|
};
|
||||||
|
};
|
@ -1,122 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
|
|
||||||
Компонент панели: Карточка показателя
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---------------------
|
|
||||||
//Подключение библиотек
|
|
||||||
//---------------------
|
|
||||||
|
|
||||||
import React, { useState } from "react"; //Классы React
|
|
||||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
|
||||||
import { Box, Card, CardContent, Typography, Link, Divider } from "@mui/material"; //Интерфейсные компоненты
|
|
||||||
import { APP_STYLES } from "../../../../app.styles"; //Общие стили приложения
|
|
||||||
import { MarkCnList } from "./mark_cn_list"; //Состав показателя
|
|
||||||
import { MarkCardToolbar } from "./mark_card_toolbar"; //Панель инструментов карточки
|
|
||||||
import { STYLES as COMMON_STYLES } from "../common"; //Общие стили и константы
|
|
||||||
|
|
||||||
//---------
|
|
||||||
//Константы
|
|
||||||
//---------
|
|
||||||
|
|
||||||
//Стили
|
|
||||||
const STYLES = {
|
|
||||||
CARD: hovered => ({
|
|
||||||
padding: "0px 0px 0px 0px",
|
|
||||||
border: "1px solid lightgrey",
|
|
||||||
position: "relative",
|
|
||||||
...(hovered ? COMMON_STYLES.BG_MARK_CARD : null)
|
|
||||||
}),
|
|
||||||
CARD_CONTENT_MARK_TITLE: { padding: "0px 0px 0px 0px" },
|
|
||||||
CARD_CONTENT_MARK_CONSTITUTION: constitutionExists => ({
|
|
||||||
padding: "8px",
|
|
||||||
height: "105px",
|
|
||||||
"&:last-child": { paddingBottom: "10px" },
|
|
||||||
...COMMON_STYLES.FONT_MARK_CARD_BODY,
|
|
||||||
...(!constitutionExists ? { display: "flex", justifyContent: "center", alignItems: "center" } : null)
|
|
||||||
}),
|
|
||||||
BOX_MARK_CONSTITUTION: {
|
|
||||||
height: "100%",
|
|
||||||
width: "100%",
|
|
||||||
overflowY: "auto",
|
|
||||||
...APP_STYLES.SCROLL
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------
|
|
||||||
//Тело модуля
|
|
||||||
//-----------
|
|
||||||
|
|
||||||
//Карточка показателя
|
|
||||||
const MarkCard = ({ mark, code, name, constitution = [], onMarkAdd, onMarkUpdate, onMarkDelete, onMarkOpen, onMarkCnOpen, onMarkCnAdd }) => {
|
|
||||||
//Флаг нахождения указателя мыши в карточке
|
|
||||||
const [hovered, setHovered] = useState(false);
|
|
||||||
|
|
||||||
//При попадании мыши на закладку раздела
|
|
||||||
const handleCardMouseIn = () => setHovered(true);
|
|
||||||
|
|
||||||
//При выходе мыши из закладки раздела
|
|
||||||
const handleCardMouseOut = () => setHovered(false);
|
|
||||||
|
|
||||||
//Флаг наличия данных в составе показателя
|
|
||||||
const constitutionExists = constitution?.length > 0;
|
|
||||||
|
|
||||||
//Формирование представления
|
|
||||||
return mark ? (
|
|
||||||
<Card variant={"plain"} sx={STYLES.CARD(hovered)} onMouseEnter={handleCardMouseIn} onMouseLeave={handleCardMouseOut}>
|
|
||||||
<CardContent sx={STYLES.CARD_CONTENT_MARK_TITLE}>
|
|
||||||
<MarkCardToolbar
|
|
||||||
title={code}
|
|
||||||
desc={name}
|
|
||||||
onOpen={onMarkOpen}
|
|
||||||
onEdit={onMarkUpdate}
|
|
||||||
onDelete={onMarkDelete}
|
|
||||||
onCnAdd={onMarkCnAdd}
|
|
||||||
showButtons={hovered}
|
|
||||||
/>
|
|
||||||
</CardContent>
|
|
||||||
<Divider />
|
|
||||||
<CardContent sx={STYLES.CARD_CONTENT_MARK_CONSTITUTION(constitutionExists)}>
|
|
||||||
{constitutionExists ? (
|
|
||||||
<Box sx={STYLES.BOX_MARK_CONSTITUTION}>
|
|
||||||
<MarkCnList constitution={constitution} onMarkCnOpen={constitutionRn => onMarkCnOpen && onMarkCnOpen(constitutionRn)} />
|
|
||||||
</Box>
|
|
||||||
) : (
|
|
||||||
<Box>
|
|
||||||
<Typography sx={COMMON_STYLES.FONT_MARK_CARD_BODY}>Показатель не имеет состава</Typography>
|
|
||||||
<Link sx={COMMON_STYLES.LINK} onClick={onMarkCnAdd}>
|
|
||||||
Добавить
|
|
||||||
</Link>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
) : (
|
|
||||||
<Box>
|
|
||||||
<Typography sx={COMMON_STYLES.FONT_MARK_CARD_BODY}>Показатель отсутствует</Typography>
|
|
||||||
<Link sx={COMMON_STYLES.LINK} onClick={onMarkAdd}>
|
|
||||||
Добавить
|
|
||||||
</Link>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Контроль свойств - Карточка показателя
|
|
||||||
MarkCard.propTypes = {
|
|
||||||
mark: PropTypes.number,
|
|
||||||
code: PropTypes.string,
|
|
||||||
name: PropTypes.string,
|
|
||||||
constitution: PropTypes.arrayOf(PropTypes.object),
|
|
||||||
onMarkAdd: PropTypes.func.isRequired,
|
|
||||||
onMarkUpdate: PropTypes.func.isRequired,
|
|
||||||
onMarkDelete: PropTypes.func.isRequired,
|
|
||||||
onMarkOpen: PropTypes.func.isRequired,
|
|
||||||
onMarkCnOpen: PropTypes.func.isRequired,
|
|
||||||
onMarkCnAdd: PropTypes.func.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------
|
|
||||||
//Интерфейс модуля
|
|
||||||
//----------------
|
|
||||||
|
|
||||||
export { MarkCard };
|
|
@ -1,73 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
|
|
||||||
Компонент панели: Панель инструментов карточки показателя
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---------------------
|
|
||||||
//Подключение библиотек
|
|
||||||
//---------------------
|
|
||||||
|
|
||||||
import React from "react"; //Классы React
|
|
||||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
|
||||||
import { Stack, IconButton, Icon, Typography, Link } from "@mui/material"; //Интерфейсные компоненты
|
|
||||||
import { STYLES as COMMON_STYLES } from "../common"; //Общие стили и константы
|
|
||||||
|
|
||||||
//---------
|
|
||||||
//Константы
|
|
||||||
//---------
|
|
||||||
|
|
||||||
//Стили
|
|
||||||
const STYLES = {
|
|
||||||
CONTAINER: { ...COMMON_STYLES.TOOLBAR, width: "100%", position: "unset", right: "unset", height: "40px" }
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------
|
|
||||||
//Тело модуля
|
|
||||||
//-----------
|
|
||||||
|
|
||||||
//Панель инструментов карточки показателя
|
|
||||||
const MarkCardToolbar = ({ title, desc, onOpen, onEdit, onDelete, onCnAdd, showButtons = false }) => {
|
|
||||||
return (
|
|
||||||
<Stack direction={"row"} alignItems={"center"} justifyContent={"space-between"} sx={STYLES.CONTAINER} title={desc}>
|
|
||||||
<Typography noWrap p={1} textAlign={"left"} variant={"subtitle1"} component={"div"} sx={COMMON_STYLES.FONT_MARK_CARD_HEAD}>
|
|
||||||
{showButtons ? (
|
|
||||||
<Link sx={COMMON_STYLES.LINK} onClick={onOpen}>
|
|
||||||
{title}
|
|
||||||
</Link>
|
|
||||||
) : (
|
|
||||||
title
|
|
||||||
)}
|
|
||||||
</Typography>
|
|
||||||
{showButtons && (
|
|
||||||
<Stack direction={"row"}>
|
|
||||||
<IconButton title={"Исправить показатель"} onClick={onEdit}>
|
|
||||||
<Icon>edit</Icon>
|
|
||||||
</IconButton>
|
|
||||||
<IconButton title={"Добавить элемент состава"} onClick={onCnAdd}>
|
|
||||||
<Icon>library_add</Icon>
|
|
||||||
</IconButton>
|
|
||||||
<IconButton title={"Удалить показатель"} onClick={onDelete}>
|
|
||||||
<Icon>delete</Icon>
|
|
||||||
</IconButton>
|
|
||||||
</Stack>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Контроль свойств - Панель инструментов карточки показателя
|
|
||||||
MarkCardToolbar.propTypes = {
|
|
||||||
title: PropTypes.string,
|
|
||||||
desc: PropTypes.string,
|
|
||||||
onOpen: PropTypes.func.isRequired,
|
|
||||||
onEdit: PropTypes.func.isRequired,
|
|
||||||
onDelete: PropTypes.func.isRequired,
|
|
||||||
onCnAdd: PropTypes.func.isRequired,
|
|
||||||
showButtons: PropTypes.bool
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------
|
|
||||||
//Интерфейс модуля
|
|
||||||
//----------------
|
|
||||||
|
|
||||||
export { MarkCardToolbar };
|
|
@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
|
|
||||||
Компонент панели: Состав показателя
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---------------------
|
|
||||||
//Подключение библиотек
|
|
||||||
//---------------------
|
|
||||||
|
|
||||||
import React from "react"; //Классы React
|
|
||||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
|
||||||
import { Table, TableBody, TableRow, TableCell, Link } from "@mui/material"; //Интерфейсные компоненты
|
|
||||||
import { STYLES as COMMON_STYLES } from "../common"; //Общие стили и константы
|
|
||||||
|
|
||||||
//---------
|
|
||||||
//Константы
|
|
||||||
//---------
|
|
||||||
|
|
||||||
//Стили
|
|
||||||
const STYLES = {
|
|
||||||
DATA_CELL_CN: {
|
|
||||||
textOverflow: "ellipsis",
|
|
||||||
overflow: "hidden",
|
|
||||||
whiteSpace: "pre",
|
|
||||||
padding: "0px",
|
|
||||||
maxWidth: "100px",
|
|
||||||
border: "none",
|
|
||||||
...COMMON_STYLES.FONT_MARK_CARD_BODY
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------
|
|
||||||
//Тело модуля
|
|
||||||
//-----------
|
|
||||||
|
|
||||||
//Состав показателя
|
|
||||||
const MarkCnList = ({ constitution, onMarkCnOpen }) => {
|
|
||||||
return (
|
|
||||||
<Table>
|
|
||||||
<TableBody>
|
|
||||||
{constitution.map((el, index) => {
|
|
||||||
return (
|
|
||||||
<TableRow key={index}>
|
|
||||||
<TableCell sx={STYLES.DATA_CELL_CN} title={el.SDESC} align={"left"} size={"small"}>
|
|
||||||
<Link sx={COMMON_STYLES.LINK} onClick={() => onMarkCnOpen && onMarkCnOpen(el.NRN)}>
|
|
||||||
{el.SDESC}
|
|
||||||
</Link>
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Контроль свойств - Состав показателя
|
|
||||||
MarkCnList.propTypes = {
|
|
||||||
constitution: PropTypes.array.isRequired,
|
|
||||||
onMarkCnOpen: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------
|
|
||||||
//Интерфейс модуля
|
|
||||||
//----------------
|
|
||||||
|
|
||||||
export { MarkCnList };
|
|
@ -1,182 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
|
|
||||||
Компонент панели: Показатели раздела
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---------------------
|
|
||||||
//Подключение библиотек
|
|
||||||
//---------------------
|
|
||||||
|
|
||||||
import React, { useState, useContext } from "react"; //Классы React
|
|
||||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
|
||||||
import { Icon, Button } from "@mui/material"; //Интерфейсные элементы
|
|
||||||
import { MessagingСtx } from "../../../context/messaging"; //Контекст сообщений
|
|
||||||
import { P8PDataGrid, P8P_DATA_GRID_SIZE } from "../../../components/p8p_data_grid"; //Таблица данных
|
|
||||||
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../../config_wrapper"; //Подключение компонентов к настройкам приложения
|
|
||||||
import { APP_STYLES } from "../../../../app.styles"; //Типовые стили
|
|
||||||
import { confSctnMrkCellRender, confSctnMrkHeadCellRender } from "../layouts"; //Дополнительная разметка и вёрстка клиентских элементов
|
|
||||||
import { ActionMessage } from "./action_message"; //Сообщение с действиями
|
|
||||||
import { DialogMarkIU } from "./dialog_mark_iu"; //Диалог добавления/исправления показателя
|
|
||||||
import { DialogHelp } from "./dialog_help"; //Диалог помощи
|
|
||||||
import { DialogOrder } from "./dialog_order"; //Диалог сортировки
|
|
||||||
import { useDictionary } from "../hooks"; //Кастомные хуки
|
|
||||||
|
|
||||||
//---------
|
|
||||||
//Константы
|
|
||||||
//---------
|
|
||||||
|
|
||||||
//Стили
|
|
||||||
const STYLES = {
|
|
||||||
MARKS_DG_CONTAINER: {
|
|
||||||
position: "absolute",
|
|
||||||
top: 0,
|
|
||||||
bottom: 0,
|
|
||||||
width: "100%",
|
|
||||||
height: "100%",
|
|
||||||
overflow: "auto",
|
|
||||||
border: "unset",
|
|
||||||
...APP_STYLES.SCROLL
|
|
||||||
},
|
|
||||||
MARKS_DG_TABLE: { tableLayout: "fixed", width: "auto" }
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------
|
|
||||||
//Тело модуля
|
|
||||||
//-----------
|
|
||||||
|
|
||||||
//Показатели раздела
|
|
||||||
const Marks = ({ marks, order, marksLoading, marksInit, onRefresh, onMarkInsert, onMarkUpdate, onMarkDelete, onOrderChange }) => {
|
|
||||||
//Состояние - диалог сортировки
|
|
||||||
const [dialogOrder, setDialogOrder] = useState(false);
|
|
||||||
|
|
||||||
//Состояние - диалог помощи
|
|
||||||
const [dialogHelp, setDialogHelp] = useState(false);
|
|
||||||
|
|
||||||
//Состояние - Редактируемый показатель
|
|
||||||
const [modMark, setModMark] = useState(null);
|
|
||||||
|
|
||||||
//Подключение к контексту сообщений
|
|
||||||
const { showMsgWarn } = useContext(MessagingСtx);
|
|
||||||
|
|
||||||
//Подключение к словарям
|
|
||||||
const { showMark, showMarkCn, showMarkCnAdd } = useDictionary();
|
|
||||||
|
|
||||||
//Изменение состояния диалога информации
|
|
||||||
const toggleHelpDialog = () => setDialogHelp(pv => !pv);
|
|
||||||
|
|
||||||
//Изменение состояния диалога сортировки
|
|
||||||
const toggleOrderDialog = () => setDialogOrder(pv => !pv);
|
|
||||||
|
|
||||||
//При необходимости обновления
|
|
||||||
const handleRefresh = () => onRefresh && onRefresh();
|
|
||||||
|
|
||||||
//При вызове сортировки
|
|
||||||
const handleOrder = () => toggleOrderDialog();
|
|
||||||
|
|
||||||
//При вызове помощи
|
|
||||||
const handleHelp = () => toggleHelpDialog();
|
|
||||||
|
|
||||||
//Изменение состояния сортировки строк и граф
|
|
||||||
const handleOrderChange = order => {
|
|
||||||
onOrderChange && onOrderChange(order);
|
|
||||||
toggleOrderDialog();
|
|
||||||
};
|
|
||||||
|
|
||||||
//При добавлении показателя
|
|
||||||
const handleMarkAdd = () => setModMark(true);
|
|
||||||
|
|
||||||
//При добавлении показателя по указанным строке/графе
|
|
||||||
const handleMarkAddByRowCol = (row, column) => onMarkInsert({ row, column });
|
|
||||||
|
|
||||||
//При исправлении показателя
|
|
||||||
const handleMarkUpdate = markDesc => setModMark({ ...markDesc });
|
|
||||||
|
|
||||||
//При удалении показателя
|
|
||||||
const handleMarkDelete = mark => showMsgWarn("Удалить показатель?", () => onMarkDelete && onMarkDelete(mark));
|
|
||||||
|
|
||||||
//При переходе к показателю
|
|
||||||
const handleMarkOpen = mark => showMark(mark, res => res.success && handleRefresh());
|
|
||||||
|
|
||||||
//При добавлении состава показателя
|
|
||||||
const handleMarkCnAdd = mark => showMarkCnAdd(mark, res => res.success && handleRefresh());
|
|
||||||
|
|
||||||
//При переходе к составу показателя
|
|
||||||
const handleMarkCnOpen = (mark, constitution) => showMarkCn(mark, constitution, res => res.success && handleRefresh());
|
|
||||||
|
|
||||||
//При закрытии формы добавления/исправления по "ОК"
|
|
||||||
const handleIUFormOk = values => {
|
|
||||||
if (modMark === true) onMarkInsert && onMarkInsert(values, res => res && setModMark(null));
|
|
||||||
else onMarkUpdate && onMarkUpdate({ ...modMark, ...values }, res => res && setModMark(null));
|
|
||||||
};
|
|
||||||
|
|
||||||
//При закрытии формы добавления/исправления по "Отмена"
|
|
||||||
const handleIUFormCancel = () => setModMark(null);
|
|
||||||
|
|
||||||
//Формирование представления
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{dialogOrder && <DialogOrder {...order} onOk={handleOrderChange} onCancel={toggleOrderDialog} />}
|
|
||||||
{dialogHelp && <DialogHelp onClose={toggleHelpDialog} />}
|
|
||||||
{modMark && (
|
|
||||||
<DialogMarkIU {...(modMark === true ? {} : modMark)} insert={modMark === true} onOk={handleIUFormOk} onCancel={handleIUFormCancel} />
|
|
||||||
)}
|
|
||||||
{marksInit &&
|
|
||||||
(marks ? (
|
|
||||||
<P8PDataGrid
|
|
||||||
{...P8P_DATA_GRID_CONFIG_PROPS}
|
|
||||||
{...marks}
|
|
||||||
tableStyle={STYLES.MARKS_DG_TABLE}
|
|
||||||
containerComponentProps={{ elevation: 0, square: true, variant: "outlined", sx: STYLES.MARKS_DG_CONTAINER }}
|
|
||||||
size={P8P_DATA_GRID_SIZE.SMALL}
|
|
||||||
dataCellRender={prms =>
|
|
||||||
confSctnMrkCellRender({
|
|
||||||
...prms,
|
|
||||||
onMarkAdd: handleMarkAddByRowCol,
|
|
||||||
onMarkUpdate: handleMarkUpdate,
|
|
||||||
onMarkDelete: handleMarkDelete,
|
|
||||||
onMarkOpen: handleMarkOpen,
|
|
||||||
onMarkCnOpen: handleMarkCnOpen,
|
|
||||||
onMarkCnAdd: handleMarkCnAdd
|
|
||||||
})
|
|
||||||
}
|
|
||||||
headCellRender={prms =>
|
|
||||||
confSctnMrkHeadCellRender({
|
|
||||||
...prms,
|
|
||||||
onAdd: handleMarkAdd,
|
|
||||||
onRefresh: handleRefresh,
|
|
||||||
onOrder: handleOrder,
|
|
||||||
onHelp: handleHelp
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
!marksLoading && (
|
|
||||||
<ActionMessage icon={"info"} title={"В разделе нет показателей"} desc={"Добавьте новый"}>
|
|
||||||
<Button startIcon={<Icon>add</Icon>} onClick={handleMarkAdd}>
|
|
||||||
Показатель
|
|
||||||
</Button>
|
|
||||||
</ActionMessage>
|
|
||||||
)
|
|
||||||
))}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Контроль свойств - Показатели раздела
|
|
||||||
Marks.propTypes = {
|
|
||||||
marks: PropTypes.object,
|
|
||||||
order: PropTypes.object.isRequired,
|
|
||||||
marksLoading: PropTypes.bool.isRequired,
|
|
||||||
marksInit: PropTypes.bool.isRequired,
|
|
||||||
onRefresh: PropTypes.func,
|
|
||||||
onMarkInsert: PropTypes.func,
|
|
||||||
onMarkUpdate: PropTypes.func,
|
|
||||||
onMarkDelete: PropTypes.func,
|
|
||||||
onOrderChange: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------
|
|
||||||
//Интерфейс модуля
|
|
||||||
//----------------
|
|
||||||
|
|
||||||
export { Marks };
|
|
@ -1,60 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
|
|
||||||
Компонент панели: Панель инструментов показателей
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---------------------
|
|
||||||
//Подключение библиотек
|
|
||||||
//---------------------
|
|
||||||
|
|
||||||
import React from "react"; //Классы React
|
|
||||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
|
||||||
import { Stack, Icon, IconButton } from "@mui/material"; //Интерфейсные компоненты
|
|
||||||
|
|
||||||
//---------
|
|
||||||
//Константы
|
|
||||||
//---------
|
|
||||||
|
|
||||||
//Стили
|
|
||||||
const STYLES = {
|
|
||||||
CONTAINER: { width: "100%" }
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------
|
|
||||||
//Тело модуля
|
|
||||||
//-----------
|
|
||||||
|
|
||||||
//Панель инструментов показателей
|
|
||||||
const MarksToolbar = ({ onAdd, onRefresh, onOrder, onHelp }) => {
|
|
||||||
//Формирование представления
|
|
||||||
return (
|
|
||||||
<Stack direction={"row"} alignItems={"center"} justifyContent={"center"} sx={STYLES.CONTAINER}>
|
|
||||||
<IconButton title={"Добавить показатель"} onClick={onAdd}>
|
|
||||||
<Icon>add</Icon>
|
|
||||||
</IconButton>
|
|
||||||
<IconButton title={"Обновить показатели"} onClick={onRefresh}>
|
|
||||||
<Icon>refresh</Icon>
|
|
||||||
</IconButton>
|
|
||||||
<IconButton title={"Порядок сортировки показателей"} onClick={onOrder}>
|
|
||||||
<Icon>sort</Icon>
|
|
||||||
</IconButton>
|
|
||||||
<IconButton title={"Легенда"} onClick={onHelp}>
|
|
||||||
<Icon>help</Icon>
|
|
||||||
</IconButton>
|
|
||||||
</Stack>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Контроль свойств - Панель инструментов показателей
|
|
||||||
MarksToolbar.propTypes = {
|
|
||||||
onAdd: PropTypes.func.isRequired,
|
|
||||||
onRefresh: PropTypes.func.isRequired,
|
|
||||||
onOrder: PropTypes.func.isRequired,
|
|
||||||
onHelp: PropTypes.func.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------
|
|
||||||
//Интерфейс модуля
|
|
||||||
//----------------
|
|
||||||
|
|
||||||
export { MarksToolbar };
|
|
359
app/panels/rrp_conf_editor/components/rrp_section.js
Normal file
359
app/panels/rrp_conf_editor/components/rrp_section.js
Normal file
@ -0,0 +1,359 @@
|
|||||||
|
/*
|
||||||
|
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
|
||||||
|
Компонент панели: Раздел настройки
|
||||||
|
*/
|
||||||
|
|
||||||
|
//---------------------
|
||||||
|
//Подключение библиотек
|
||||||
|
//---------------------
|
||||||
|
|
||||||
|
import React, { useState } from "react"; //Классы React
|
||||||
|
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
IconButton,
|
||||||
|
Icon,
|
||||||
|
Dialog,
|
||||||
|
DialogTitle,
|
||||||
|
DialogContent,
|
||||||
|
Button,
|
||||||
|
Typography,
|
||||||
|
List,
|
||||||
|
ListItem,
|
||||||
|
Select,
|
||||||
|
FormControl,
|
||||||
|
InputLabel,
|
||||||
|
MenuItem,
|
||||||
|
DialogActions
|
||||||
|
} from "@mui/material"; //Интерфейсные элементы
|
||||||
|
import { P8PDataGrid, P8P_DATA_GRID_SIZE } from "../../../components/p8p_data_grid"; //Таблица данных
|
||||||
|
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../../config_wrapper"; //Подключение компонентов к настройкам приложения
|
||||||
|
import { SectionTabPanel } from "./section_tab_panel"; //Компонент вкладки раздела
|
||||||
|
import { confSctnMrkCellRender, confSctnMrkHeadCellRender } from "./layouts"; //Дополнительная разметка и вёрстка клиентских элементов
|
||||||
|
|
||||||
|
//---------
|
||||||
|
//Константы
|
||||||
|
//---------
|
||||||
|
|
||||||
|
//Стили
|
||||||
|
const STYLES = {
|
||||||
|
GRID_SIZES: (height, pxOuterMenuH, pxPanelHeaderH, pxTabsH) => ({
|
||||||
|
padding: 0,
|
||||||
|
minWidth: "98vw",
|
||||||
|
minHeight: (height - pxOuterMenuH - pxPanelHeaderH - pxTabsH) * 0.93,
|
||||||
|
maxWidth: "98vw",
|
||||||
|
maxHeight: (height - pxOuterMenuH - pxPanelHeaderH - pxTabsH) * 0.93
|
||||||
|
}),
|
||||||
|
TABLE_CONTAINER: {
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
paddingTop: 1,
|
||||||
|
paddingBottom: 1
|
||||||
|
},
|
||||||
|
SECTION_ACTIONS: { display: "flex", justifyContent: "space-between", padding: "0px 5px" },
|
||||||
|
TABLE_SCROLL: {
|
||||||
|
"&::-webkit-scrollbar": {
|
||||||
|
width: "12px",
|
||||||
|
height: "12px"
|
||||||
|
},
|
||||||
|
"&::-webkit-scrollbar-track": {
|
||||||
|
borderRadius: "88px",
|
||||||
|
backgroundColor: "#EBEBEB"
|
||||||
|
},
|
||||||
|
"&::-webkit-scrollbar-thumb": {
|
||||||
|
borderRadius: "88px",
|
||||||
|
backgroundColor: "#b4b4b4",
|
||||||
|
backgroundClip: "padding-box",
|
||||||
|
border: "3px solid #EBEBEB"
|
||||||
|
},
|
||||||
|
"&::-webkit-scrollbar-thumb:hover": {
|
||||||
|
backgroundColor: "#808080"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
HELP_LIST_ITEM: {
|
||||||
|
padding: "0px 0px 0px 5px",
|
||||||
|
whiteSpace: "pre",
|
||||||
|
fontSize: "0.95rem"
|
||||||
|
},
|
||||||
|
HELP_LIST_ITEM_NAME: {
|
||||||
|
fontWeight: "bold",
|
||||||
|
fontSize: "inherit",
|
||||||
|
minWidth: "45px"
|
||||||
|
},
|
||||||
|
HELP_LIST_ITEM_DESC: {
|
||||||
|
fontSize: "inherit"
|
||||||
|
},
|
||||||
|
DIALOG_ACTIONS: { justifyContent: "end", paddingRight: "24px", paddingLeft: "24px" }
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
//Вспомогательные функции и компоненты
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
//Элемент списка расшифровки состава
|
||||||
|
const HelpListItem = ({ name, desc }) => {
|
||||||
|
return (
|
||||||
|
<ListItem sx={STYLES.HELP_LIST_ITEM}>
|
||||||
|
<Typography sx={STYLES.HELP_LIST_ITEM_NAME}>{name}</Typography>
|
||||||
|
<Typography sx={STYLES.HELP_LIST_ITEM_DESC}>{` - ${desc}`}</Typography>
|
||||||
|
</ListItem>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
//Контроль свойств - Элемент списка расшифровки состава
|
||||||
|
HelpListItem.propTypes = {
|
||||||
|
name: PropTypes.string.isRequired,
|
||||||
|
desc: PropTypes.string.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
//Диалог дополнительной информации
|
||||||
|
const HelpDialog = ({ handleOpenHelpChange }) => {
|
||||||
|
//Генерация содержимого
|
||||||
|
return (
|
||||||
|
<Dialog open onClose={handleOpenHelpChange}>
|
||||||
|
<DialogTitle>
|
||||||
|
<Box display="flex" alignItems="center">
|
||||||
|
<Box flexGrow={1} textAlign="center">
|
||||||
|
Информация
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<IconButton aria-label="close" onClick={handleOpenHelpChange}>
|
||||||
|
<Icon>close</Icon>
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<Typography>Карточки показателей содержат сокращенную информацию о типе состава показателя.</Typography>
|
||||||
|
<Typography>Список сокращений:</Typography>
|
||||||
|
<List disablePadding={true}>
|
||||||
|
<HelpListItem name="fx" desc="формула" />
|
||||||
|
<HelpListItem name="СЗ" desc="статическое значение" />
|
||||||
|
<HelpListItem name="ХП" desc="хранимая процедура" />
|
||||||
|
<HelpListItem name="РП" desc="расчетный показатель" />
|
||||||
|
<HelpListItem name="ХО" desc="хозяйственные операции" />
|
||||||
|
<HelpListItem name="РСДК" desc="расчёты с дебиторами/кредиторами" />
|
||||||
|
<HelpListItem name="ОС" desc="остатки средств по счетам" />
|
||||||
|
<HelpListItem name="ТМЦ" desc="остатки товарно-материальных ценностей" />
|
||||||
|
<HelpListItem name="ДКЗ" desc="дебиторская/кредиторская задолженность" />
|
||||||
|
<HelpListItem name="ИК" desc="инвентарная картотека" />
|
||||||
|
<HelpListItem name="МБП" desc="картотека МБП" />
|
||||||
|
<HelpListItem name="КОБП" desc="картотека операций будущих периодов" />
|
||||||
|
<HelpListItem name="ДПНП" desc="декларация по налогу на прибыль" />
|
||||||
|
<HelpListItem name="РО" desc="регламентированный отчет" />
|
||||||
|
</List>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
//Контроль свойств - Диалог дополнительной информации
|
||||||
|
HelpDialog.propTypes = {
|
||||||
|
handleOpenHelpChange: PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
//Диалог сортировки
|
||||||
|
const SortDialog = ({ init, handleOpenSortChange, onOrderChange }) => {
|
||||||
|
//Собственное состояние сортировки
|
||||||
|
const [order, setOrder] = useState({ row: init.rowOrder ? init.rowOrder : 0, column: init.columnOrder ? init.columnOrder : 0 });
|
||||||
|
|
||||||
|
//Изменеие сортировки
|
||||||
|
const handleOrderChange = e => setOrder(pv => ({ ...pv, [e.target.name]: e.target.value }));
|
||||||
|
|
||||||
|
//Нажатие на кнопку Ok
|
||||||
|
const handleOk = () => {
|
||||||
|
onOrderChange({ rowOrder: order.row, columnOrder: order.column });
|
||||||
|
handleOpenSortChange();
|
||||||
|
};
|
||||||
|
|
||||||
|
//Кнопка "Очистить", значения по умолчанию
|
||||||
|
const handleClear = () => {
|
||||||
|
setOrder({ row: 0, column: 0 });
|
||||||
|
};
|
||||||
|
|
||||||
|
//Кнопка "Отмена"
|
||||||
|
const handleCancel = () => {
|
||||||
|
handleOpenSortChange();
|
||||||
|
};
|
||||||
|
|
||||||
|
//Генерация содержимого
|
||||||
|
return (
|
||||||
|
<Dialog open onClose={handleOpenSortChange}>
|
||||||
|
<DialogTitle>
|
||||||
|
<Box display="flex" alignItems="center">
|
||||||
|
<Box flexGrow={1} textAlign="center">
|
||||||
|
Сортировка
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<IconButton aria-label="close" onClick={handleCancel}>
|
||||||
|
<Icon>close</Icon>
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<Box component="section" p={1}>
|
||||||
|
<FormControl variant="standard" fullWidth>
|
||||||
|
<InputLabel id="row-label">Строки</InputLabel>
|
||||||
|
<Select labelId="row-label" id="row" name="row" value={order.row} label="Строки" onChange={handleOrderChange}>
|
||||||
|
<MenuItem value={0}>Номер</MenuItem>
|
||||||
|
<MenuItem value={1}>Код</MenuItem>
|
||||||
|
<MenuItem value={2}>Мнемокод</MenuItem>
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
</Box>
|
||||||
|
<Box component="section" p={1}>
|
||||||
|
<FormControl variant="standard" fullWidth>
|
||||||
|
<InputLabel id="column-label">Графы</InputLabel>
|
||||||
|
<Select labelId="column-label" id="column" name="column" value={order.column} label="Графы" onChange={handleOrderChange}>
|
||||||
|
<MenuItem value={0}>Номер</MenuItem>
|
||||||
|
<MenuItem value={1}>Код</MenuItem>
|
||||||
|
<MenuItem value={2}>Мнемокод</MenuItem>
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
</Box>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions sx={STYLES.DIALOG_ACTIONS}>
|
||||||
|
<Button variant="text" onClick={handleOk}>
|
||||||
|
ОК
|
||||||
|
</Button>
|
||||||
|
<Button variant="text" onClick={handleClear}>
|
||||||
|
Очистить
|
||||||
|
</Button>
|
||||||
|
<Button variant="text" onClick={handleCancel}>
|
||||||
|
Отмена
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
//Контроль свойств - Диалог сортировки
|
||||||
|
SortDialog.propTypes = {
|
||||||
|
init: PropTypes.object.isRequired,
|
||||||
|
handleOpenSortChange: PropTypes.func.isRequired,
|
||||||
|
onOrderChange: PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------
|
||||||
|
//Тело модуля
|
||||||
|
//-----------
|
||||||
|
|
||||||
|
//Раздел настройки
|
||||||
|
const SectionTab = ({
|
||||||
|
section,
|
||||||
|
tabValue,
|
||||||
|
index,
|
||||||
|
order,
|
||||||
|
onOrderChange,
|
||||||
|
containerProps,
|
||||||
|
handleMarkAdd,
|
||||||
|
handleReload,
|
||||||
|
handleMarkOpen,
|
||||||
|
handleMarkCnOpen,
|
||||||
|
handleMarkCnInsert,
|
||||||
|
menuItems
|
||||||
|
}) => {
|
||||||
|
//Состояние - диалог информации
|
||||||
|
const [openHelp, setOpenHelp] = useState(false);
|
||||||
|
|
||||||
|
//Изменение состояния диалога информации
|
||||||
|
const handleOpenHelpChange = () => {
|
||||||
|
setOpenHelp(!openHelp);
|
||||||
|
};
|
||||||
|
|
||||||
|
//Состояние - диалог сортировки
|
||||||
|
const [openSort, setOpenSort] = useState(false);
|
||||||
|
|
||||||
|
//Изменение состояния диалога сортировки
|
||||||
|
const handleOpenSortChange = () => {
|
||||||
|
setOpenSort(!openSort);
|
||||||
|
};
|
||||||
|
|
||||||
|
//Генерация содержимого
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<SectionTabPanel key={section.rn} value={tabValue} index={index}>
|
||||||
|
<Box sx={STYLES.SECTION_ACTIONS}>
|
||||||
|
<Box>
|
||||||
|
<IconButton onClick={() => handleMarkAdd(section.rn)}>
|
||||||
|
<Icon>add</Icon>
|
||||||
|
</IconButton>
|
||||||
|
<IconButton onClick={() => handleReload()}>
|
||||||
|
<Icon>refresh</Icon>
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<IconButton onClick={() => handleOpenSortChange()}>
|
||||||
|
<Icon>sort</Icon>
|
||||||
|
</IconButton>
|
||||||
|
<IconButton onClick={() => handleOpenHelpChange()}>
|
||||||
|
<Icon>help</Icon>
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
{section.dataLoaded && section.columnsDef.length > 3 ? (
|
||||||
|
<Box sx={STYLES.TABLE_CONTAINER}>
|
||||||
|
<P8PDataGrid
|
||||||
|
{...P8P_DATA_GRID_CONFIG_PROPS}
|
||||||
|
containerComponentProps={{
|
||||||
|
elevation: 6,
|
||||||
|
sx: { ...STYLES.TABLE_SCROLL },
|
||||||
|
style: STYLES.GRID_SIZES(
|
||||||
|
containerProps.height,
|
||||||
|
containerProps.pxOuterMenuH,
|
||||||
|
containerProps.pxPanelHeaderH,
|
||||||
|
containerProps.pxTabsH
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
columnsDef={section.columnsDef}
|
||||||
|
groups={section.groups}
|
||||||
|
rows={section.rows}
|
||||||
|
fixedHeader={section.fixedHeader}
|
||||||
|
fixedColumns={section.fixedColumns}
|
||||||
|
size={P8P_DATA_GRID_SIZE.LARGE}
|
||||||
|
reloading={section.reload}
|
||||||
|
dataCellRender={prms =>
|
||||||
|
confSctnMrkCellRender({
|
||||||
|
...prms,
|
||||||
|
sectionRn: section.rn,
|
||||||
|
handleMarkAdd: handleMarkAdd,
|
||||||
|
handleMarkOpen: handleMarkOpen,
|
||||||
|
handleMarkCnOpen: handleMarkCnOpen,
|
||||||
|
handleMarkCnInsert: handleMarkCnInsert,
|
||||||
|
menuItems: menuItems
|
||||||
|
})
|
||||||
|
}
|
||||||
|
headCellRender={confSctnMrkHeadCellRender}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
) : null}
|
||||||
|
</SectionTabPanel>
|
||||||
|
{openSort ? <SortDialog init={order} handleOpenSortChange={handleOpenSortChange} onOrderChange={onOrderChange} /> : null}
|
||||||
|
{openHelp ? <HelpDialog handleOpenHelpChange={handleOpenHelpChange} /> : null}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
//Контроль свойств - Раздел настройки
|
||||||
|
SectionTab.propTypes = {
|
||||||
|
section: PropTypes.object.isRequired,
|
||||||
|
tabValue: PropTypes.number,
|
||||||
|
index: PropTypes.number,
|
||||||
|
order: PropTypes.object.isRequired,
|
||||||
|
onOrderChange: PropTypes.func.isRequired,
|
||||||
|
containerProps: PropTypes.object,
|
||||||
|
handleMarkAdd: PropTypes.func,
|
||||||
|
handleReload: PropTypes.func,
|
||||||
|
handleMarkOpen: PropTypes.func,
|
||||||
|
handleMarkCnOpen: PropTypes.func,
|
||||||
|
handleMarkCnInsert: PropTypes.func,
|
||||||
|
menuItems: PropTypes.array
|
||||||
|
};
|
||||||
|
|
||||||
|
//----------------
|
||||||
|
//Интерфейс модуля
|
||||||
|
//----------------
|
||||||
|
|
||||||
|
export { SectionTab };
|
@ -1,152 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
|
|
||||||
Компонент панели: Раздел настройки
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---------------------
|
|
||||||
//Подключение библиотек
|
|
||||||
//---------------------
|
|
||||||
|
|
||||||
import React, { useState, useContext, useEffect } from "react"; //Классы React
|
|
||||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
|
||||||
import { Box } from "@mui/material"; //Интерфейсные элементы
|
|
||||||
import { BackEndСtx } from "../../../context/backend"; //Контекст взаимодействия с сервером
|
|
||||||
import { useConfSectionMarks } from "../hooks"; //Кастомные хуки
|
|
||||||
import { ActionMessage } from "./action_message"; //Сообщение с действиями
|
|
||||||
import { Marks } from "./marks"; //Показатели раздела
|
|
||||||
|
|
||||||
//---------
|
|
||||||
//Константы
|
|
||||||
//---------
|
|
||||||
|
|
||||||
//Стили
|
|
||||||
const STYLES = {
|
|
||||||
CONTAINER: { width: "100%", height: "100%" },
|
|
||||||
BOX_MARKS: { position: "relative", display: "flex", height: "100%", width: "100%" }
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------
|
|
||||||
//Тело модуля
|
|
||||||
//-----------
|
|
||||||
|
|
||||||
//Раздел настройки
|
|
||||||
const Section = ({ section = null }) => {
|
|
||||||
//Состояние сортировки строк и граф
|
|
||||||
const [order, setOrder] = useState({ rowOrder: 0, columnOrder: 0 });
|
|
||||||
|
|
||||||
//Состояние - флаг "сокрытия" (на самом деле - отмонтирования) компонента с показателями
|
|
||||||
const [hideMarksThenLoading, setHideMarksThenLoading] = useState(false);
|
|
||||||
|
|
||||||
//Данные раздела (показатели)
|
|
||||||
const [marks, refreshMarks, marksLoading, marksInit] = useConfSectionMarks(section, order.rowOrder, order.columnOrder);
|
|
||||||
|
|
||||||
//Подключение к контексту взаимодействия с сервером
|
|
||||||
const { executeStored } = useContext(BackEndСtx);
|
|
||||||
|
|
||||||
//Добавление показателя
|
|
||||||
const insertMark = async ({ code, name, row, rowCode, rowVersion, column, columnCode, columnVersion }, cb) => {
|
|
||||||
try {
|
|
||||||
await executeStored({
|
|
||||||
stored: "PKG_P8PANELS_RRPCONFED.RRPCONFSCTNMRK_INSERT",
|
|
||||||
args: {
|
|
||||||
NPRN: section,
|
|
||||||
SCODE: code,
|
|
||||||
SNAME: name,
|
|
||||||
NRRPROW: row,
|
|
||||||
SRRPROW: rowCode,
|
|
||||||
SRRPVERSION_ROW: rowVersion,
|
|
||||||
NRRPCOLUMN: column,
|
|
||||||
SRRPCOLUMN: columnCode,
|
|
||||||
SRRPVERSION_COLUMN: columnVersion
|
|
||||||
},
|
|
||||||
loader: false
|
|
||||||
});
|
|
||||||
cb && cb(true);
|
|
||||||
refreshMarks();
|
|
||||||
} catch {
|
|
||||||
cb && cb(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//Исправление показателя
|
|
||||||
const updateMark = async ({ rn, code, name, rowCode, rowVersion, columnCode, columnVersion }, cb) => {
|
|
||||||
try {
|
|
||||||
await executeStored({
|
|
||||||
stored: "PKG_P8PANELS_RRPCONFED.RRPCONFSCTNMRK_UPDATE",
|
|
||||||
args: {
|
|
||||||
NRN: rn,
|
|
||||||
SCODE: code,
|
|
||||||
SNAME: name,
|
|
||||||
SRRPROW: rowCode,
|
|
||||||
SRRPVERSION_ROW: rowVersion,
|
|
||||||
SRRPCOLUMN: columnCode,
|
|
||||||
SRRPVERSION_COLUMN: columnVersion
|
|
||||||
},
|
|
||||||
loader: false
|
|
||||||
});
|
|
||||||
cb && cb(true);
|
|
||||||
refreshMarks();
|
|
||||||
} catch {
|
|
||||||
cb && cb(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//Удаление показателя
|
|
||||||
const deleteMark = async mark => {
|
|
||||||
await executeStored({
|
|
||||||
stored: "PKG_P8PANELS_RRPCONFED.RRPCONFSCTNMRK_DELETE",
|
|
||||||
args: { NRN: mark },
|
|
||||||
loader: false
|
|
||||||
});
|
|
||||||
refreshMarks();
|
|
||||||
};
|
|
||||||
|
|
||||||
//Изменение сортировки
|
|
||||||
const changeOrder = order => setOrder(order);
|
|
||||||
|
|
||||||
//Сброс ранее выставленного флага "сокрытия" (отмонтирования) компонента с показателями (так он не "мигает", когда происходит не смена раздела, в работа внутри него с показателями)
|
|
||||||
useEffect(() => {
|
|
||||||
if (hideMarksThenLoading) setHideMarksThenLoading(false);
|
|
||||||
}, [hideMarksThenLoading]);
|
|
||||||
|
|
||||||
//При смене раздела - выставим флаг "спрятать" (отмонтировать) компонент с показателями (так он корректно полностью обновляется)
|
|
||||||
useEffect(() => {
|
|
||||||
if (section) setHideMarksThenLoading(true);
|
|
||||||
}, [section]);
|
|
||||||
|
|
||||||
//Формирование представления
|
|
||||||
return (
|
|
||||||
<Box sx={STYLES.CONTAINER}>
|
|
||||||
{section ? (
|
|
||||||
<Box sx={STYLES.BOX_MARKS}>
|
|
||||||
{((hideMarksThenLoading && !marksLoading) || !hideMarksThenLoading) && (
|
|
||||||
<Marks
|
|
||||||
marks={marks}
|
|
||||||
order={order}
|
|
||||||
marksLoading={marksLoading}
|
|
||||||
marksInit={marksInit}
|
|
||||||
onRefresh={refreshMarks}
|
|
||||||
onMarkInsert={insertMark}
|
|
||||||
onMarkUpdate={updateMark}
|
|
||||||
onMarkDelete={deleteMark}
|
|
||||||
onOrderChange={changeOrder}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
) : (
|
|
||||||
<ActionMessage icon={"info"} title={"Раздел настройки не выбран"} desc={"Укажите его, выбрав закладку сверху"} />
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Контроль свойств - Раздел настройки
|
|
||||||
Section.propTypes = {
|
|
||||||
section: PropTypes.number
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------
|
|
||||||
//Интерфейс модуля
|
|
||||||
//----------------
|
|
||||||
|
|
||||||
export { Section };
|
|
@ -1,89 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
|
|
||||||
Компонент панели: Закладка раздела
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---------------------
|
|
||||||
//Подключение библиотек
|
|
||||||
//---------------------
|
|
||||||
|
|
||||||
import React, { useState } from "react"; //Классы React
|
|
||||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
|
||||||
import { Tab, IconButton, Icon, Stack } from "@mui/material"; //Интерфейсные компоненты
|
|
||||||
import { STYLES as COMMON_STYLES } from "../common"; //Общие стили и константы
|
|
||||||
|
|
||||||
//---------
|
|
||||||
//Константы
|
|
||||||
//---------
|
|
||||||
|
|
||||||
//Стили
|
|
||||||
const STYLES = {
|
|
||||||
SECTION_TAB: { minWidth: "150px" },
|
|
||||||
SECTION_TAB_LABEL: { width: "100%", height: "100%" },
|
|
||||||
SECTION_TAB_TOOLBAR_STACK: { ...COMMON_STYLES.TOOLBAR, height: "100%", width: "100%" }
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------
|
|
||||||
//Тело модуля
|
|
||||||
//-----------
|
|
||||||
|
|
||||||
//Закладка раздела
|
|
||||||
const SectionTab = ({ value = false, section, sectionDesc, onSectionEdit, onSectionDelete, ...other }) => {
|
|
||||||
//Флаг нахождения указателя мыши в закладке
|
|
||||||
const [hoveredSection, setHoveredSection] = useState(false);
|
|
||||||
|
|
||||||
//При попадании мыши на закладку раздела
|
|
||||||
const handleSectionTabMouseIn = () => setHoveredSection(true);
|
|
||||||
|
|
||||||
//При выходе мыши из закладки раздела
|
|
||||||
const handleSectionTabMouseOut = () => setHoveredSection(false);
|
|
||||||
|
|
||||||
//При редактировании раздела настройки
|
|
||||||
const handleSectionEdit = () => onSectionEdit && onSectionEdit(sectionDesc.NRN);
|
|
||||||
|
|
||||||
//При удалении раздела настройки
|
|
||||||
const handleSectionDelete = () => onSectionDelete && onSectionDelete(sectionDesc.NRN);
|
|
||||||
|
|
||||||
//Формирование представления
|
|
||||||
return (
|
|
||||||
<Tab
|
|
||||||
component={"div"}
|
|
||||||
wrapped
|
|
||||||
value={value}
|
|
||||||
onMouseEnter={handleSectionTabMouseIn}
|
|
||||||
onMouseLeave={handleSectionTabMouseOut}
|
|
||||||
sx={STYLES.SECTION_TAB}
|
|
||||||
label={
|
|
||||||
<Stack direction={"row"} alignItems={"center"} textAlign={"left"} sx={STYLES.SECTION_TAB_LABEL} title={sectionDesc.SNAME}>
|
|
||||||
{`${sectionDesc.SCODE} - ${sectionDesc.SNAME_SHORT}`}
|
|
||||||
{section === sectionDesc.NRN && hoveredSection && (
|
|
||||||
<Stack direction={"row"} alignItems={"center"} justifyContent={"right"} sx={STYLES.SECTION_TAB_TOOLBAR_STACK} p={1}>
|
|
||||||
<IconButton onClick={handleSectionEdit} title={"Редактировать раздел"}>
|
|
||||||
<Icon>edit</Icon>
|
|
||||||
</IconButton>
|
|
||||||
<IconButton disabled={sectionDesc.NDELETE_ALLOW === 0} onClick={handleSectionDelete} title={"Удалить раздел"}>
|
|
||||||
<Icon>delete</Icon>
|
|
||||||
</IconButton>
|
|
||||||
</Stack>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
}
|
|
||||||
{...other}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Контроль свойств - Закладка раздела
|
|
||||||
SectionTab.propTypes = {
|
|
||||||
value: PropTypes.any,
|
|
||||||
section: PropTypes.number,
|
|
||||||
sectionDesc: PropTypes.object.isRequired,
|
|
||||||
onSectionEdit: PropTypes.func,
|
|
||||||
onSectionDelete: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------
|
|
||||||
//Интерфейс модуля
|
|
||||||
//----------------
|
|
||||||
|
|
||||||
export { SectionTab };
|
|
50
app/panels/rrp_conf_editor/components/section_tab_panel.js
Normal file
50
app/panels/rrp_conf_editor/components/section_tab_panel.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
|
||||||
|
Панель мониторинга: Компонент вкладки раздела
|
||||||
|
*/
|
||||||
|
|
||||||
|
//---------------------
|
||||||
|
//Подключение библиотек
|
||||||
|
//---------------------
|
||||||
|
|
||||||
|
import React from "react"; //Классы React
|
||||||
|
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||||||
|
import { Box } from "@mui/material"; //Интерфейсные компоненты
|
||||||
|
|
||||||
|
//---------
|
||||||
|
//Константы
|
||||||
|
//---------
|
||||||
|
|
||||||
|
const STYLES = {
|
||||||
|
SECTION_INFO: {
|
||||||
|
padding: "24px 5px 0px 5px"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//---------------
|
||||||
|
//Тело компонента
|
||||||
|
//---------------
|
||||||
|
|
||||||
|
const SectionTabPanel = props => {
|
||||||
|
const { children, value, index, ...other } = props;
|
||||||
|
|
||||||
|
//Генерация содержимого
|
||||||
|
return (
|
||||||
|
<div role="tabpanel" hidden={value !== index} id={`tabpanel-${index}`} aria-labelledby={`tab-${index}`} {...other}>
|
||||||
|
{value === index && <Box sx={STYLES.SECTION_INFO}>{children}</Box>}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
//Контроль свойств - Вкладка раздела
|
||||||
|
SectionTabPanel.propTypes = {
|
||||||
|
children: PropTypes.node,
|
||||||
|
index: PropTypes.number.isRequired,
|
||||||
|
value: PropTypes.number.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
//--------------------
|
||||||
|
//Интерфейс компонента
|
||||||
|
//--------------------
|
||||||
|
|
||||||
|
export { SectionTabPanel };
|
@ -1,207 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
|
|
||||||
Компонент панели: Разделы настройки
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---------------------
|
|
||||||
//Подключение библиотек
|
|
||||||
//---------------------
|
|
||||||
|
|
||||||
import React, { useState, useEffect, useContext, useCallback } from "react"; //Классы React
|
|
||||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
|
||||||
import { Box, Tabs, IconButton, Icon, Stack, Button } from "@mui/material"; //Интерфейсные компоненты
|
|
||||||
import { tabsClasses } from "@mui/material/Tabs"; //Классы закладок
|
|
||||||
import { ApplicationСtx } from "../../../context/application"; //Контекст взаимодействия с приложением
|
|
||||||
import { BackEndСtx } from "../../../context/backend"; //Контекст взаимодействия с сервером
|
|
||||||
import { MessagingСtx } from "../../../context/messaging"; //Контекст сообщений
|
|
||||||
import { useConfSections } from "../hooks"; //Кастомные хуки
|
|
||||||
import { ActionMessage } from "./action_message"; //Сообщение с действиями
|
|
||||||
import { SectionTab } from "./section_tab"; //Закладка раздела
|
|
||||||
import { DialogSectionIU } from "./dialog_section_iu"; //Диалог добавления/исправления раздела
|
|
||||||
|
|
||||||
//---------
|
|
||||||
//Константы
|
|
||||||
//---------
|
|
||||||
|
|
||||||
//Стили
|
|
||||||
const STYLES = {
|
|
||||||
CONTAINER: { borderBottom: 1, borderColor: "divider", width: "100%", height: "100%" },
|
|
||||||
TABS_SECTIONS: { width: "100%", [`& .${tabsClasses.scrollButtons}`]: { "&.Mui-disabled": { opacity: 0.3 } } }
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------------------
|
|
||||||
//Вспомогательные функции
|
|
||||||
//-----------------------
|
|
||||||
|
|
||||||
//Поиск активного раздела после удаления текущего
|
|
||||||
const getNextSectionAfterDelete = (sections, deletedSection) => {
|
|
||||||
//Находим индекс удаляемого раздела
|
|
||||||
const delInd = sections.findIndex(s => s.NRN === deletedSection);
|
|
||||||
//Возвращаем рег. номер либо предыдущего раздела, либо следующего, либо ничего
|
|
||||||
return delInd === -1 ? null : sections[delInd - 1]?.NRN || sections[delInd + 1]?.NRN || null;
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------
|
|
||||||
//Тело модуля
|
|
||||||
//-----------
|
|
||||||
|
|
||||||
//Разделы настройки
|
|
||||||
const Sections = ({ conf, onSectionChange, onSectionCountChange }) => {
|
|
||||||
//Текущий раздел настройки
|
|
||||||
const [section, setSection] = useState(-1);
|
|
||||||
|
|
||||||
//Редактируемый раздел настройки
|
|
||||||
const [modSection, setModSection] = useState(null);
|
|
||||||
|
|
||||||
//Список разделов и просто описание настройки
|
|
||||||
const [confDesc, sections, refreshSections, sectionsLoading, sectionsInit] = useConfSections(conf);
|
|
||||||
|
|
||||||
//Подключение к контексту приложения
|
|
||||||
const { setAppBarTitle } = useContext(ApplicationСtx);
|
|
||||||
|
|
||||||
//Подключение к контексту взаимодействия с сервером
|
|
||||||
const { executeStored } = useContext(BackEndСtx);
|
|
||||||
|
|
||||||
//Подключение к контексту сообщений
|
|
||||||
const { showMsgWarn } = useContext(MessagingСtx);
|
|
||||||
|
|
||||||
//Выбор раздела
|
|
||||||
const selectSection = useCallback(
|
|
||||||
section => {
|
|
||||||
if (onSectionChange) onSectionChange(section);
|
|
||||||
setSection(section);
|
|
||||||
},
|
|
||||||
[onSectionChange]
|
|
||||||
);
|
|
||||||
|
|
||||||
//Добавление раздела
|
|
||||||
const insertSection = async ({ conf, code, name }) => {
|
|
||||||
const data = await executeStored({
|
|
||||||
stored: "PKG_P8PANELS_RRPCONFED.RRPCONFSCTN_INSERT",
|
|
||||||
args: { NPRN: conf, SCODE: code, SNAME: name },
|
|
||||||
loader: false
|
|
||||||
});
|
|
||||||
selectSection(data.NRN);
|
|
||||||
refreshSections();
|
|
||||||
};
|
|
||||||
|
|
||||||
//Исправление раздела
|
|
||||||
const updateSection = async ({ rn, code, name }) => {
|
|
||||||
await executeStored({
|
|
||||||
stored: "PKG_P8PANELS_RRPCONFED.RRPCONFSCTN_UPDATE",
|
|
||||||
args: { NRN: rn, SCODE: code, SNAME: name },
|
|
||||||
loader: false
|
|
||||||
});
|
|
||||||
refreshSections();
|
|
||||||
};
|
|
||||||
|
|
||||||
//Удаление раздела
|
|
||||||
const deleteSection = async section => {
|
|
||||||
await executeStored({
|
|
||||||
stored: "PKG_P8PANELS_RRPCONFED.RRPCONFSCTN_DELETE",
|
|
||||||
args: { NRN: section },
|
|
||||||
loader: false
|
|
||||||
});
|
|
||||||
selectSection(getNextSectionAfterDelete(sections, section));
|
|
||||||
refreshSections();
|
|
||||||
};
|
|
||||||
|
|
||||||
//При измении закладки текущего раздела
|
|
||||||
const handleSectionTabChange = (event, section) => selectSection(section);
|
|
||||||
|
|
||||||
//При добавлении раздела настройки
|
|
||||||
const handleSectionAdd = () => setModSection(true);
|
|
||||||
|
|
||||||
//При редактировании раздела настройки
|
|
||||||
const handleSectionEdit = section => setModSection(sections.find(s => s.NRN === section) || null);
|
|
||||||
|
|
||||||
//При удалении раздела настройки
|
|
||||||
const handleSectionDelete = section => showMsgWarn("Удалить раздел?", () => deleteSection(section));
|
|
||||||
|
|
||||||
//При закрытии формы добавления/исправления по "ОК"
|
|
||||||
const handleIUFormOk = async values => {
|
|
||||||
if (modSection === true) await insertSection({ conf, ...values });
|
|
||||||
else await updateSection({ rn: modSection.NRN, ...values });
|
|
||||||
setModSection(null);
|
|
||||||
};
|
|
||||||
|
|
||||||
//При закрытии формы добавления/исправления по "Отмена"
|
|
||||||
const handleIUFormCancel = () => setModSection(null);
|
|
||||||
|
|
||||||
//При изменении состава разделов
|
|
||||||
useEffect(() => {
|
|
||||||
//Если ещё не инициализировали выбранный раздел и есть чем
|
|
||||||
if (section === -1 && sections.length > 0) selectSection(sections[0].NRN);
|
|
||||||
}, [section, sections, selectSection]);
|
|
||||||
|
|
||||||
//При изменении количества разделов
|
|
||||||
useEffect(() => {
|
|
||||||
onSectionCountChange && onSectionCountChange(sections.length);
|
|
||||||
}, [sections.length, onSectionCountChange]);
|
|
||||||
|
|
||||||
//При изменении описания раздела
|
|
||||||
useEffect(() => {
|
|
||||||
if (confDesc?.SNAME) setAppBarTitle(confDesc.SNAME);
|
|
||||||
}, [confDesc, setAppBarTitle]);
|
|
||||||
|
|
||||||
//Вычисление подсвеченной закладки раздела
|
|
||||||
const hlSection = sections.find(s => s.NRN === section)?.NRN || false;
|
|
||||||
|
|
||||||
//Формирование представления
|
|
||||||
return (
|
|
||||||
<Stack direction={"row"} sx={STYLES.CONTAINER}>
|
|
||||||
{modSection && (
|
|
||||||
<DialogSectionIU
|
|
||||||
code={modSection?.SCODE}
|
|
||||||
name={modSection?.SNAME}
|
|
||||||
insert={modSection === true}
|
|
||||||
onOk={handleIUFormOk}
|
|
||||||
onCancel={handleIUFormCancel}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{sections.length > 0 ? (
|
|
||||||
<>
|
|
||||||
<Box display={"flex"} justifyContent={"center"} alignItems={"center"} sx={STYLES.PANELS_MAIN_COLOR} title={"Добавить раздел"}>
|
|
||||||
<IconButton onClick={handleSectionAdd}>
|
|
||||||
<Icon>add</Icon>
|
|
||||||
</IconButton>
|
|
||||||
</Box>
|
|
||||||
<Tabs value={hlSection} onChange={handleSectionTabChange} variant={"scrollable"} scrollButtons sx={STYLES.TABS_SECTIONS}>
|
|
||||||
{sections.map((s, i) => (
|
|
||||||
<SectionTab
|
|
||||||
key={i}
|
|
||||||
value={s.NRN}
|
|
||||||
section={section}
|
|
||||||
sectionDesc={s}
|
|
||||||
onSectionEdit={handleSectionEdit}
|
|
||||||
onSectionDelete={handleSectionDelete}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</Tabs>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
sectionsInit &&
|
|
||||||
!sectionsLoading && (
|
|
||||||
<ActionMessage icon={"info"} title={"В настройке нет разделов"} desc={"Добавьте первый..."}>
|
|
||||||
<Button startIcon={<Icon>add</Icon>} onClick={handleSectionAdd}>
|
|
||||||
Раздел
|
|
||||||
</Button>
|
|
||||||
</ActionMessage>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Контроль свойств - Разделы настройки
|
|
||||||
Sections.propTypes = {
|
|
||||||
conf: PropTypes.number,
|
|
||||||
onSectionChange: PropTypes.func,
|
|
||||||
onSectionCountChange: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------
|
|
||||||
//Интерфейс модуля
|
|
||||||
//----------------
|
|
||||||
|
|
||||||
export { Sections };
|
|
@ -7,209 +7,403 @@
|
|||||||
//Подключение библиотек
|
//Подключение библиотек
|
||||||
//---------------------
|
//---------------------
|
||||||
|
|
||||||
import { useState, useContext, useEffect } from "react"; //Классы React
|
import { useState, useContext, useEffect, useCallback, useLayoutEffect } from "react"; //Классы React
|
||||||
import { xml2JSON } from "../../core/utils"; //Вспомогательные функции
|
|
||||||
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
|
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
|
||||||
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
|
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
|
||||||
|
import { NavigationCtx } from "../../context/navigation"; //Контекст навигации
|
||||||
|
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
|
||||||
|
import { STATUSES } from "./IUD/iud_form_dialog"; //Статусы диалогов
|
||||||
|
import { TEXTS } from "../../../app.text"; //Тексты для ошибок
|
||||||
|
|
||||||
//-----------
|
//-----------
|
||||||
//Тело модуля
|
//Тело модуля
|
||||||
//-----------
|
//-----------
|
||||||
|
|
||||||
//Получение данных о разделах настройки РО
|
//Хук для отработки изменений ширины и высоты рабочей области окна
|
||||||
const useConfSections = conf => {
|
const useWindowResize = () => {
|
||||||
//Собственное состояние - флаг инициализированности
|
//Состояние размера рабочей области
|
||||||
const [isInit, setInit] = useState(false);
|
const [size, setSize] = useState([0, 0]);
|
||||||
|
|
||||||
//Собственное состояние - флаг загрузки
|
//При изменении размера
|
||||||
const [isLoading, setLoading] = useState(false);
|
useLayoutEffect(() => {
|
||||||
|
const updateSize = () => {
|
||||||
//Собственное состояние - флаг необходимости обновления
|
setSize([document.documentElement.clientWidth, document.documentElement.clientHeight]);
|
||||||
const [refresh, setRefresh] = useState(true);
|
|
||||||
|
|
||||||
//Собственное состояние - данные настройки
|
|
||||||
const [dataConf, setDataConf] = useState(null);
|
|
||||||
|
|
||||||
//Собственное состояние - данные разделов
|
|
||||||
const [dataSections, setDataSections] = useState([]);
|
|
||||||
|
|
||||||
//Подключение к контексту взаимодействия с сервером
|
|
||||||
const { executeStored } = useContext(BackEndСtx);
|
|
||||||
|
|
||||||
//Обновление данных
|
|
||||||
const doRefresh = () => setRefresh(true);
|
|
||||||
|
|
||||||
//При необходимости получить/обновить данные
|
|
||||||
useEffect(() => {
|
|
||||||
//Загрузка данных с сервера
|
|
||||||
const loadData = async () => {
|
|
||||||
try {
|
|
||||||
setLoading(true);
|
|
||||||
const data = await executeStored({
|
|
||||||
stored: "PKG_P8PANELS_RRPCONFED.RRPCONF_GET",
|
|
||||||
args: { NRRPCONF: conf },
|
|
||||||
respArg: "COUT",
|
|
||||||
isArray: name => name === "XSECTIONS",
|
|
||||||
attributeValueProcessor: (name, val) => (name.startsWith("S") ? undefined : val),
|
|
||||||
loader: false
|
|
||||||
});
|
|
||||||
setDataConf(data?.XCONF || null);
|
|
||||||
setDataSections(data?.XSECTIONS || []);
|
|
||||||
setInit(true);
|
|
||||||
} finally {
|
|
||||||
setRefresh(false);
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
//Если надо обновить
|
window.addEventListener("resize", updateSize);
|
||||||
if (refresh)
|
updateSize();
|
||||||
if (conf)
|
return () => window.removeEventListener("resize", updateSize);
|
||||||
//Если есть для чего получать данные
|
}, []);
|
||||||
loadData();
|
|
||||||
//Нет идентификатора настройки - нет данных
|
|
||||||
else {
|
|
||||||
setDataConf(null);
|
|
||||||
setDataSections([]);
|
|
||||||
}
|
|
||||||
}, [refresh, conf, executeStored]);
|
|
||||||
|
|
||||||
//При изменении входных свойств - поднимаем флаг обновления
|
//Вернём размеры
|
||||||
useEffect(() => setRefresh(true), [conf]);
|
return size;
|
||||||
|
|
||||||
//Возвращаем интерфейс хука
|
|
||||||
return [dataConf, dataSections, doRefresh, isLoading, isInit];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//Получение данных о показателях раздела настройки РО
|
//Хук для настройки регламентированного отчета
|
||||||
const useConfSectionMarks = (section, rowOrder = 0, columnOrder = 0) => {
|
const useConf = (currentTab, handleSectionChange, order) => {
|
||||||
//Собственное состояние - флаг инициализированности
|
//Собственное состояние - таблица данных
|
||||||
const [isInit, setInit] = useState(false);
|
const dataGrid = {
|
||||||
|
rn: 0,
|
||||||
|
code: "",
|
||||||
|
name: "",
|
||||||
|
dataLoaded: false,
|
||||||
|
columnsDef: [],
|
||||||
|
groups: [],
|
||||||
|
rows: [],
|
||||||
|
fixedHeader: false,
|
||||||
|
fixedColumns: 0,
|
||||||
|
reload: false
|
||||||
|
};
|
||||||
|
|
||||||
//Собственное состояние - флаг загрузки
|
//Собственное состояние
|
||||||
const [isLoading, setLoading] = useState(false);
|
const [rrpConf, setRrpConf] = useState({
|
||||||
|
docLoaded: false,
|
||||||
|
sections: [],
|
||||||
|
orderChanged: false,
|
||||||
|
reload: true
|
||||||
|
});
|
||||||
|
|
||||||
//Собственное состояние - флаг необходимости обновления
|
//Состояние массива данных разделов
|
||||||
const [refresh, setRefresh] = useState(true);
|
const [dataGrids] = useState([]);
|
||||||
|
|
||||||
//Собственное состояние - данные
|
|
||||||
const [data, setData] = useState(null);
|
|
||||||
|
|
||||||
//Подключение к контексту взаимодействия с сервером
|
//Подключение к контексту взаимодействия с сервером
|
||||||
const { executeStored } = useContext(BackEndСtx);
|
const { executeStored } = useContext(BackEndСtx);
|
||||||
|
|
||||||
//Обновление данных
|
//Подключение к контексту навигации
|
||||||
const doRefresh = () => setRefresh(true);
|
const { getNavigationSearch } = useContext(NavigationCtx);
|
||||||
|
|
||||||
//При необходимости получить/обновить данные
|
//При необходимости обновить
|
||||||
useEffect(() => {
|
const handleReload = useCallback(async () => {
|
||||||
//Загрузка данных с сервера
|
setRrpConf(pv => ({ ...pv, reload: true }));
|
||||||
const loadData = async () => {
|
}, []);
|
||||||
try {
|
|
||||||
setLoading(true);
|
//Загрузка данных разделов регламентированного отчёта
|
||||||
|
const loadData = useCallback(
|
||||||
|
async () => {
|
||||||
|
if (rrpConf.reload) {
|
||||||
|
//Переменная номера раздела с фокусом
|
||||||
|
let tabFocus = currentTab ? currentTab : 0;
|
||||||
const data = await executeStored({
|
const data = await executeStored({
|
||||||
stored: "PKG_P8PANELS_RRPCONFED.RRPCONFSCTN_GET",
|
stored: "PKG_P8PANELS_RRPCONFED.RRPCONF_GET_SECTIONS",
|
||||||
args: { NRRPCONFSCTN: section, NROW_ORDER: rowOrder, NCOL_ORDER: columnOrder },
|
args: {
|
||||||
|
NRN_RRPCONF: Number(getNavigationSearch().NRN),
|
||||||
|
NROW_ORDER: Number(order.rowOrder),
|
||||||
|
NCOL_ORDER: Number(order.columnOrder)
|
||||||
|
},
|
||||||
respArg: "COUT"
|
respArg: "COUT"
|
||||||
});
|
});
|
||||||
if (data) {
|
//Флаг первой загрузки данных
|
||||||
for (let i = 0; i < data?.XDATA_GRID?.rows?.length; i++)
|
let firstLoad = dataGrids.length == 0 ? true : false;
|
||||||
for (const key of Object.keys(data.XDATA_GRID.rows[i]))
|
//Копирование массива уже загруженных разделов
|
||||||
if (key.startsWith("SCOL_"))
|
let cloneDGs = dataGrids.slice();
|
||||||
data.XDATA_GRID.rows[i][key] = (
|
//Массив из нескольких разделов и из одного
|
||||||
await xml2JSON({
|
const sections = data.SECTIONS ? (data.SECTIONS.length ? data.SECTIONS : [data.SECTIONS]) : [];
|
||||||
xmlDoc: data.XDATA_GRID.rows[i][key],
|
//Заполнение очередного раздела по шаблону
|
||||||
isArray: name => name === "CONSTITUTION",
|
sections
|
||||||
attributeValueProcessor: (name, val) => (name.startsWith("S") ? undefined : val)
|
.sort((a, b) => a.SCODE - b.SCODE)
|
||||||
})
|
.map(s => {
|
||||||
).XMARK;
|
let dg = {};
|
||||||
setData(data?.XDATA_GRID || null);
|
Object.assign(dg, dataGrid, {
|
||||||
} else setData(null);
|
...s.XDATA.XDATA_GRID,
|
||||||
setInit(true);
|
rn: s.NRN,
|
||||||
} finally {
|
code: s.SCODE,
|
||||||
setRefresh(false);
|
name: s.SNAME,
|
||||||
setLoading(false);
|
delete_allow: s.NDELETE_ALLOW,
|
||||||
|
dataLoaded: true,
|
||||||
|
columnsDef: [...(s.XDATA.XDATA_GRID.columnsDef || [])],
|
||||||
|
groups: [...(s.XDATA.XDATA_GRID.groups || [])],
|
||||||
|
rows: [...(s.XDATA.XDATA_GRID.rows || [])],
|
||||||
|
reload: false
|
||||||
|
});
|
||||||
|
//Если раздел имеет составы показателей
|
||||||
|
if (s.MARK_CNS.MARK_CN) {
|
||||||
|
//Обходим строки раздела
|
||||||
|
dg.rows.map(row => {
|
||||||
|
//Цикл по ключам строки
|
||||||
|
for (let key in row) {
|
||||||
|
//Если это ключ для группы составов показателей
|
||||||
|
if (key.match(/MARK_CNS_.*/)) {
|
||||||
|
//Считываем рег. номер показателя
|
||||||
|
let markRn = key.substring(9);
|
||||||
|
//Переносим из раздела
|
||||||
|
row[key] = Array.isArray(s.MARK_CNS.MARK_CN)
|
||||||
|
? [...s.MARK_CNS.MARK_CN].filter(el => el.NPRN === row[`NMARK_RN_${markRn}`])
|
||||||
|
: s.MARK_CNS.MARK_CN.NPRN === row[`NMARK_RN_${markRn}`]
|
||||||
|
? [s.MARK_CNS.MARK_CN]
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//Ищем загружен ли уже раздел с таким же ид.
|
||||||
|
const dgItem = dataGrids.find(x => x.rn === dg.rn);
|
||||||
|
//Его индекс, если нет соответствия, то -1
|
||||||
|
let index = dataGrids.indexOf(dgItem);
|
||||||
|
//Если было соответствие
|
||||||
|
if (dgItem) {
|
||||||
|
//Если в нём не найдено изменений
|
||||||
|
if (JSON.stringify(dgItem, null, 4) === JSON.stringify(dg, null, 4)) {
|
||||||
|
//То из копированного массива его удаляем
|
||||||
|
cloneDGs.splice(cloneDGs.indexOf(cloneDGs.find(x => x.rn === dgItem.rn)), 1);
|
||||||
|
} else {
|
||||||
|
//Иначе обновляем раздел в массиве
|
||||||
|
dataGrids[index] = dg;
|
||||||
|
//Удаляем из копированного массива
|
||||||
|
cloneDGs.splice(cloneDGs.indexOf(cloneDGs.find(x => x.rn === dg.rn)), 1);
|
||||||
|
//Устанавливаем фокус на обновлённый раздел, если был добавлен
|
||||||
|
tabFocus = rrpConf.orderChanged ? 0 : index;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Если раздел новый, то добавляем его в массив данных
|
||||||
|
dataGrids.push(dg);
|
||||||
|
//И устанавливаем на него фокус, если флаг первой загрузки = false
|
||||||
|
tabFocus = !firstLoad ? dataGrids.length - 1 : 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//Обходим разделы, что остались в копированном массиве (на удаление)
|
||||||
|
cloneDGs.map(s => {
|
||||||
|
let curIndex = dataGrids.indexOf(dataGrids.find(x => x.rn === s.rn));
|
||||||
|
//Устаревший раздел удаляем из массива данных
|
||||||
|
dataGrids.splice(curIndex, 1);
|
||||||
|
//Фокус на предшествующий раздел
|
||||||
|
if (curIndex > 0) tabFocus = curIndex - 1;
|
||||||
|
//Иначе фокус на следующий, если был удалён первый раздел
|
||||||
|
else tabFocus = curIndex;
|
||||||
|
});
|
||||||
|
setRrpConf(pv => ({
|
||||||
|
...pv,
|
||||||
|
docLoaded: true,
|
||||||
|
orderChanged: false,
|
||||||
|
reload: false,
|
||||||
|
sections: dataGrids
|
||||||
|
}));
|
||||||
|
handleSectionChange(tabFocus);
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
//Если надо обновить
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
if (refresh)
|
[rrpConf.reload, rrpConf.docLoaded, dataGrid.reload, dataGrid.docLoaded, executeStored]
|
||||||
if (section)
|
);
|
||||||
//Если есть для чего получать данные
|
|
||||||
loadData();
|
|
||||||
//Нет идентификатора раздела настройки - нет данных
|
|
||||||
else setData(null);
|
|
||||||
}, [refresh, section, rowOrder, columnOrder, executeStored]);
|
|
||||||
|
|
||||||
//При изменении входных свойств - поднимаем флаг обновления
|
//При изменении сортировок
|
||||||
useEffect(() => setRefresh(true), [section, rowOrder, columnOrder]);
|
useEffect(() => {
|
||||||
|
setRrpConf(pv => ({ ...pv, orderChanged: true, reload: true }));
|
||||||
|
}, [order]);
|
||||||
|
|
||||||
//При изменении раздела - сбрасываем флаг инициализированности (так карточки показателей грузятся красивее - таблица исчезает и появляется уже загруженная)
|
//При необходимости обновить данные таблицы
|
||||||
useEffect(() => setInit(false), [section]);
|
useEffect(() => {
|
||||||
|
loadData();
|
||||||
|
}, [rrpConf.reload, dataGrid.reload, loadData]);
|
||||||
|
|
||||||
//Возвращаем интерфейс хука
|
return [rrpConf, handleReload];
|
||||||
return [data, doRefresh, isLoading, isInit];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//Работа со словарями
|
//Хук для вкладки
|
||||||
const useDictionary = () => {
|
const useTab = () => {
|
||||||
|
//Состояние раздела
|
||||||
|
const [tabValue, setTabValue] = useState("");
|
||||||
|
|
||||||
|
//Переключение раздела
|
||||||
|
const handleSectionChange = useCallback(newValue => {
|
||||||
|
setTabValue(newValue);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return [tabValue, handleSectionChange];
|
||||||
|
};
|
||||||
|
|
||||||
|
//Хук для функций открытия записей
|
||||||
|
const useRecOpen = handleReload => {
|
||||||
|
//Подключение к контексту взаимодействия с сервером
|
||||||
|
const { executeStored } = useContext(BackEndСtx);
|
||||||
|
|
||||||
//Подключение к контексту приложения
|
//Подключение к контексту приложения
|
||||||
const { pOnlineShowDictionary } = useContext(ApplicationСtx);
|
const { pOnlineShowDictionary } = useContext(ApplicationСtx);
|
||||||
|
|
||||||
//Выбор строки
|
//Подключение к контексту сообщений
|
||||||
const selectRRPRow = (code, version, callBack) => {
|
const { showMsgErr } = useContext(MessagingСtx);
|
||||||
pOnlineShowDictionary({
|
|
||||||
unitCode: "RRPRow",
|
|
||||||
inputParameters: [
|
|
||||||
{ name: "in_CODE", value: code },
|
|
||||||
{ name: "in_RRPVERSION_CODE", value: version }
|
|
||||||
],
|
|
||||||
callBack: res =>
|
|
||||||
callBack(res.success === true ? { code: res.outParameters.out_CODE, version: res.outParameters.out_RRPVERSION_CODE } : null)
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
//Выбор графы
|
|
||||||
const selectRRPColumn = (code, version, callBack) => {
|
|
||||||
pOnlineShowDictionary({
|
|
||||||
unitCode: "RRPColumn",
|
|
||||||
inputParameters: [
|
|
||||||
{ name: "in_CODE", value: code },
|
|
||||||
{ name: "in_RRPVERSION_CODE", value: version }
|
|
||||||
],
|
|
||||||
callBack: res =>
|
|
||||||
callBack(res.success === true ? { code: res.outParameters.out_CODE, version: res.outParameters.out_RRPVERSION_CODE } : null)
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
//Отображение показателя раздела
|
//Отображение показателя раздела
|
||||||
const showMark = (mark, callBack) => showMarkCn(mark, null, callBack);
|
const handleMarkOpen = useCallback(
|
||||||
|
async nRrpConfSctnMrk => {
|
||||||
|
const data = await executeStored({
|
||||||
|
stored: "PKG_P8PANELS_RRPCONFED.RRPCONFSCTNMRK_GET_CODES",
|
||||||
|
args: {
|
||||||
|
NRN: nRrpConfSctnMrk
|
||||||
|
},
|
||||||
|
tagValueProcessor: () => undefined
|
||||||
|
});
|
||||||
|
if (data) {
|
||||||
|
pOnlineShowDictionary({
|
||||||
|
unitCode: "RRPConfig",
|
||||||
|
showMethod: "main_mrk_settings",
|
||||||
|
inputParameters: [
|
||||||
|
{ name: "in_CODE", value: data.SRRPCONF },
|
||||||
|
{ name: "in_SCTN_CODE", value: data.SRRPCONFSCTN },
|
||||||
|
{ name: "in_MRK_CODE", value: data.SRRPCONFSCTNMRK }
|
||||||
|
],
|
||||||
|
callBack: res => {
|
||||||
|
res.success ? handleReload() : null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else showMsgErr(TEXTS.NO_DATA_FOUND);
|
||||||
|
},
|
||||||
|
[executeStored, handleReload, pOnlineShowDictionary, showMsgErr]
|
||||||
|
);
|
||||||
|
|
||||||
//Отображение состава показателя раздела
|
//Отображение показателя раздела
|
||||||
const showMarkCn = (mark, constitution, callBack) =>
|
const handleMarkCnOpen = useCallback(
|
||||||
pOnlineShowDictionary({
|
async (nRrpConfSctnMrk, nRrpConfSctnMrkCn) => {
|
||||||
unitCode: "RRPConfigSectionMark",
|
pOnlineShowDictionary({
|
||||||
showMethod: "link_cn",
|
unitCode: "RRPConfigSectionMark",
|
||||||
inputParameters: [
|
showMethod: "link_cn",
|
||||||
{ name: "in_RN", value: mark },
|
inputParameters: [
|
||||||
{ name: "in_RRPCONFSCTNMRKCN", value: constitution }
|
{ name: "in_RN", value: nRrpConfSctnMrk },
|
||||||
],
|
{ name: "in_RRPCONFSCTNMRKCN", value: nRrpConfSctnMrkCn }
|
||||||
callBack
|
],
|
||||||
|
callBack: res => {
|
||||||
|
res.success ? handleReload() : null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[handleReload, pOnlineShowDictionary]
|
||||||
|
);
|
||||||
|
|
||||||
|
//Отображение показателя раздела
|
||||||
|
const handleMarkCnInsert = useCallback(
|
||||||
|
async nRrpConfSctnMrk => {
|
||||||
|
pOnlineShowDictionary({
|
||||||
|
unitCode: "RRPConfigSectionMarkConstitution",
|
||||||
|
showMethod: "link_add",
|
||||||
|
inputParameters: [{ name: "in_PRN", value: nRrpConfSctnMrk }],
|
||||||
|
callBack: res => {
|
||||||
|
res.success ? handleReload() : null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[handleReload, pOnlineShowDictionary]
|
||||||
|
);
|
||||||
|
|
||||||
|
return [handleMarkOpen, handleMarkCnOpen, handleMarkCnInsert];
|
||||||
|
};
|
||||||
|
|
||||||
|
//Хук для форм диалогового окна
|
||||||
|
const useFormDialog = () => {
|
||||||
|
//Состояние открытия диалогового окна
|
||||||
|
const [formOpen, setForm] = useState(false);
|
||||||
|
|
||||||
|
//Состояние диалогового окна
|
||||||
|
const [formData, setFormData] = useState({
|
||||||
|
reload: false,
|
||||||
|
rn: "",
|
||||||
|
prn: "",
|
||||||
|
sctnName: "",
|
||||||
|
sctnCode: "",
|
||||||
|
status: "",
|
||||||
|
code: "",
|
||||||
|
name: "",
|
||||||
|
colCode: "",
|
||||||
|
colRn: null,
|
||||||
|
rowCode: "",
|
||||||
|
rowRn: null
|
||||||
|
});
|
||||||
|
|
||||||
|
//Подключение к контексту навигации
|
||||||
|
const { getNavigationSearch } = useContext(NavigationCtx);
|
||||||
|
|
||||||
|
//Открытие диалогового окна
|
||||||
|
const openForm = () => {
|
||||||
|
setForm(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
//Очистка диалогового окна
|
||||||
|
const clearFormData = () => {
|
||||||
|
setFormData({
|
||||||
|
reload: false,
|
||||||
|
rn: "",
|
||||||
|
prn: "",
|
||||||
|
sctnName: "",
|
||||||
|
sctnCode: "",
|
||||||
|
status: "",
|
||||||
|
code: "",
|
||||||
|
name: "",
|
||||||
|
colCode: "",
|
||||||
|
colRn: null,
|
||||||
|
rowCode: "",
|
||||||
|
rowRn: null
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
//Отображение состава показателя раздела с добавлением
|
//Отработка нажатия на кнопку добавления секции
|
||||||
const showMarkCnAdd = (mark, callBack) =>
|
const handleSectionAdd = () => {
|
||||||
pOnlineShowDictionary({
|
setFormData({ status: STATUSES.CREATE, prn: Number(getNavigationSearch().NRN) });
|
||||||
unitCode: "RRPConfigSectionMarkConstitution",
|
openForm();
|
||||||
showMethod: "link_add",
|
};
|
||||||
inputParameters: [{ name: "in_PRN", value: mark }],
|
|
||||||
callBack
|
//Отработка нажатия на кнопку исправления секции
|
||||||
|
const handleSectionEdit = (rn, code, name) => {
|
||||||
|
setFormData({ rn: rn, code: code, name: name, status: STATUSES.EDIT });
|
||||||
|
openForm();
|
||||||
|
};
|
||||||
|
|
||||||
|
//Отработка нажатия на кнопку удаления секции
|
||||||
|
const handleSectionDelete = (rn, code, name) => {
|
||||||
|
setFormData({ rn: rn, code: code, name: name, status: STATUSES.DELETE });
|
||||||
|
openForm();
|
||||||
|
};
|
||||||
|
|
||||||
|
//Отработка нажатия на кнопку добавления показателя раздела
|
||||||
|
const handleMarkAdd = (prn, rowRn = null, rowCode = "", colRn = null, colCode = "") => {
|
||||||
|
setFormData({
|
||||||
|
reload: rowRn && colRn ? true : false,
|
||||||
|
prn: prn,
|
||||||
|
rowRn: rowRn,
|
||||||
|
rowCode: rowCode,
|
||||||
|
colRn: colRn,
|
||||||
|
colCode: colCode,
|
||||||
|
status: STATUSES.RRPCONFSCTNMRK_CREATE
|
||||||
});
|
});
|
||||||
|
openForm();
|
||||||
|
};
|
||||||
|
|
||||||
//Возвращаем интерфейс хука
|
//Отработка нажатия на кнопку исправления показателя раздела
|
||||||
return { selectRRPRow, selectRRPColumn, showMark, showMarkCn, showMarkCnAdd };
|
const handleMarkEdit = rn => {
|
||||||
|
setFormData({ reload: true, rn: rn, status: STATUSES.RRPCONFSCTNMRK_EDIT });
|
||||||
|
openForm();
|
||||||
|
};
|
||||||
|
|
||||||
|
//Отработка нажатия на кнопку удаления показателя раздела
|
||||||
|
const handleMarkDelete = rn => {
|
||||||
|
setFormData({ rn: rn, status: STATUSES.RRPCONFSCTNMRK_DELETE });
|
||||||
|
openForm();
|
||||||
|
};
|
||||||
|
|
||||||
|
//При закрытии диалога
|
||||||
|
const handleDialogClose = () => {
|
||||||
|
setForm(false);
|
||||||
|
clearFormData();
|
||||||
|
};
|
||||||
|
|
||||||
|
return [
|
||||||
|
formOpen,
|
||||||
|
formData,
|
||||||
|
handleSectionAdd,
|
||||||
|
handleSectionEdit,
|
||||||
|
handleSectionDelete,
|
||||||
|
handleMarkAdd,
|
||||||
|
handleMarkEdit,
|
||||||
|
handleMarkDelete,
|
||||||
|
handleDialogClose
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
//Формирование разделов
|
||||||
|
const a11yProps = index => {
|
||||||
|
return {
|
||||||
|
id: `simple-tab-${index}`,
|
||||||
|
"aria-controls": `simple-tabpanel-${index}`
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------------
|
//----------------
|
||||||
//Интерфейс модуля
|
//Интерфейс модуля
|
||||||
//----------------
|
//----------------
|
||||||
|
|
||||||
export { useConfSections, useConfSectionMarks, useDictionary };
|
export { useWindowResize, useConf, useTab, useRecOpen, useFormDialog, a11yProps };
|
||||||
|
@ -1,91 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
|
|
||||||
Дополнительная разметка и вёрстка клиентских элементов
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---------------------
|
|
||||||
//Подключение библиотек
|
|
||||||
//---------------------
|
|
||||||
|
|
||||||
import React from "react"; //Классы React
|
|
||||||
import { MarksToolbar } from "./components/marks_toolbar"; //Панель инструментов показателей
|
|
||||||
import { MarkCard } from "./components/mark_card"; //Карточка показателя
|
|
||||||
import { STYLES as COMMON_STYLES } from "./common"; //Общие стили и константы
|
|
||||||
|
|
||||||
//---------
|
|
||||||
//Константы
|
|
||||||
//---------
|
|
||||||
|
|
||||||
//Стили
|
|
||||||
export const STYLES = {
|
|
||||||
HEAD_CELL: {
|
|
||||||
textAlign: "center",
|
|
||||||
fontWeight: "bold",
|
|
||||||
lineHeight: "unset",
|
|
||||||
...COMMON_STYLES.FONT_DATA_GRID,
|
|
||||||
...COMMON_STYLES.BG_DATA_GRID_HEAD_CELL,
|
|
||||||
...COMMON_STYLES.BORDER_DATA_GRID_HEAD_CELL
|
|
||||||
},
|
|
||||||
HEAD_CELL_STACK: { justifyContent: "center" },
|
|
||||||
DATA_CELL: isMarkRowHead => ({
|
|
||||||
padding: "5px 5px",
|
|
||||||
textAlign: "center",
|
|
||||||
...COMMON_STYLES.FONT_DATA_GRID,
|
|
||||||
...(isMarkRowHead
|
|
||||||
? { ...COMMON_STYLES.BG_DATA_GRID_DATA_CELL, ...COMMON_STYLES.BORDER_DATA_GRID_HEAD_CELL, fontWeight: "bold" }
|
|
||||||
: COMMON_STYLES.BORDER_DATA_GRID_DATA_CELL)
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------
|
|
||||||
//Тело модуля
|
|
||||||
//-----------
|
|
||||||
|
|
||||||
//Генерация представления ячейки c данными показателя раздела регламентированного отчета
|
|
||||||
export const confSctnMrkCellRender = ({ row, columnDef, onMarkAdd, onMarkUpdate, onMarkDelete, onMarkOpen, onMarkCnOpen, onMarkCnAdd }) => {
|
|
||||||
//Считываем информацию о показателе
|
|
||||||
const mark = {
|
|
||||||
rn: row[columnDef.name]?.NRN,
|
|
||||||
code: row[columnDef.name]?.SCODE,
|
|
||||||
name: row[columnDef.name]?.SNAME,
|
|
||||||
row: row[columnDef.name]?.NRRPROW,
|
|
||||||
rowCode: row[columnDef.name]?.SRRPROW,
|
|
||||||
rowVersion: row[columnDef.name]?.SRRPVERSION_ROW,
|
|
||||||
column: row[columnDef.name]?.NRRPCOLUMN,
|
|
||||||
columnCode: row[columnDef.name]?.SRRPCOLUMN,
|
|
||||||
columnVersion: row[columnDef.name]?.SRRPVERSION_COLUMN,
|
|
||||||
constitution: row[columnDef.name]?.CONSTITUTION
|
|
||||||
};
|
|
||||||
//Вернём представление ячейки
|
|
||||||
return {
|
|
||||||
cellStyle: STYLES.DATA_CELL(columnDef.name === "SROW_NAME"),
|
|
||||||
data: columnDef.name != "SROW_NAME" && (
|
|
||||||
<MarkCard
|
|
||||||
mark={mark.rn}
|
|
||||||
code={mark.code}
|
|
||||||
name={mark.name}
|
|
||||||
constitution={mark.constitution}
|
|
||||||
onMarkAdd={() => onMarkAdd && onMarkAdd(mark.row, mark.column)}
|
|
||||||
onMarkUpdate={() => onMarkUpdate && onMarkUpdate({ ...mark })}
|
|
||||||
onMarkDelete={() => onMarkDelete && onMarkDelete(mark.rn)}
|
|
||||||
onMarkOpen={() => onMarkOpen && onMarkOpen(mark.rn)}
|
|
||||||
onMarkCnOpen={constitutionRn => onMarkCnOpen && onMarkCnOpen(mark.rn, constitutionRn)}
|
|
||||||
onMarkCnAdd={() => onMarkCnAdd && onMarkCnAdd(mark.rn)}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
//Генерация представления ячейки заголовка таблицы показателей
|
|
||||||
export const confSctnMrkHeadCellRender = ({ columnDef, onAdd, onRefresh, onOrder, onHelp }) => {
|
|
||||||
return {
|
|
||||||
cellStyle: STYLES.HEAD_CELL,
|
|
||||||
stackStyle: STYLES.HEAD_CELL_STACK,
|
|
||||||
data:
|
|
||||||
columnDef.name === "SROW_NAME" ? (
|
|
||||||
<MarksToolbar onAdd={onAdd} onRefresh={onRefresh} onOrder={onOrder} onHelp={onHelp} />
|
|
||||||
) : (
|
|
||||||
columnDef.caption
|
|
||||||
)
|
|
||||||
};
|
|
||||||
};
|
|
@ -7,23 +7,32 @@
|
|||||||
//Подключение библиотек
|
//Подключение библиотек
|
||||||
//---------------------
|
//---------------------
|
||||||
|
|
||||||
import React, { useState, useEffect, useContext } from "react"; //Классы React
|
import React, { useState, useEffect } from "react"; //Классы React
|
||||||
import { Grid } from "@mui/material"; //Интерфейсные компоненты
|
import { Box, Tab, Tabs, IconButton, Icon, Stack } from "@mui/material"; //Интерфейсные компоненты
|
||||||
import { APP_BAR_HEIGHT } from "../../components/p8p_app_workspace"; //Рабочая область приложения
|
import { IUDFormDialog } from "./IUD/iud_form_dialog"; //Диалог добавления/исправления/удаления компонентов настройки регламентированного отчёта
|
||||||
import { NavigationCtx } from "../../context/navigation"; //Контекст навигации
|
import { useWindowResize, useTab, useConf, useRecOpen, useFormDialog, a11yProps } from "./hooks"; //Пользовательские хуки
|
||||||
import { Sections } from "./components/sections"; //Список разделов настройки
|
import { SectionTab } from "./components/rrp_section"; //Компонент раздела настройки
|
||||||
import { Section } from "./components/section"; //Раздел настройки
|
|
||||||
|
|
||||||
//---------
|
//---------
|
||||||
//Константы
|
//Константы
|
||||||
//---------
|
//---------
|
||||||
|
|
||||||
|
//Высота меню Парус (пиксели)
|
||||||
|
const pxOuterMenuH = 53;
|
||||||
|
//Высота заголовка панели (пиксели)
|
||||||
|
const pxPanelHeaderH = 64;
|
||||||
|
//Ширина кнопки добавления раздела (пиксели)
|
||||||
|
const pxSectionAddButtonW = 40;
|
||||||
|
|
||||||
//Стили
|
//Стили
|
||||||
const STYLES = {
|
const STYLES = {
|
||||||
GRID_MAIN_CONTAINER: { height: `calc(100vh - ${APP_BAR_HEIGHT})` },
|
CONTAINER: { width: "100%", minHeight: `calc(100vh - ${pxPanelHeaderH})`, maxHeight: `calc(100vh - ${pxPanelHeaderH})` },
|
||||||
GRID_MAIN_SECTIONS_ITEM: fullHeight => ({ ...(fullHeight ? { height: "100%" } : {}) }),
|
PANELS_MAIN_COLOR: { backgroundColor: "#1976d2" },
|
||||||
GRID_SECTIONS_CONTAINER: { width: "100vw", height: "100%" },
|
ICON_WHITE: { color: "white" },
|
||||||
GRID_SECTION_CONTAINER: { height: "100%" }
|
TABS_BOTTOM_LINE: { borderBottom: 1, borderColor: "divider" },
|
||||||
|
TABS_PADDING: { padding: "5px" },
|
||||||
|
TABS_SIZES: (width, pxSectionAddButtonW) => ({ maxHeight: 150, maxWidth: width - pxSectionAddButtonW }),
|
||||||
|
SECTION_ACTIONS: { display: "flex", justifyContent: "center", alignItems: "center" }
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------
|
//-----------
|
||||||
@ -32,46 +41,122 @@ const STYLES = {
|
|||||||
|
|
||||||
//Редактор настройки регламентированного отчёта
|
//Редактор настройки регламентированного отчёта
|
||||||
const RrpConfEditor = () => {
|
const RrpConfEditor = () => {
|
||||||
//Редактируемая настройка
|
//Состояние вкладки
|
||||||
const [conf, setConf] = useState(null);
|
const [tabValue, handleSectionChange] = useTab("");
|
||||||
|
|
||||||
//Текущий раздел настройки
|
//Состояние сортировки строк и граф
|
||||||
const [section, setSection] = useState(null);
|
const [order, setOrder] = useState({ rowOrder: 0, columnOrder: 0 });
|
||||||
|
|
||||||
//Текущее количество разделов настройки
|
//Изменение состояния сортировки строк и граф
|
||||||
const [sectionsCount, setSectionsCount] = useState(0);
|
const handleOrder = newOrder => setOrder(newOrder);
|
||||||
|
|
||||||
//Подключение к контексту навигации
|
//Состояние настройки
|
||||||
const { getNavigationSearch } = useContext(NavigationCtx);
|
const [rrpConf, handleReload] = useConf(tabValue, handleSectionChange, order);
|
||||||
|
|
||||||
//Изменение текущего раздела настройки
|
//Функции открытия разделов
|
||||||
const handleSectionChange = section => setSection(section);
|
const [handleMarkOpen, handleMarkCnOpen, handleMarkCnInsert] = useRecOpen(handleReload);
|
||||||
|
|
||||||
//Изменение количества разделов настройки
|
//Состояние форм диалога
|
||||||
const handleSectionsCountChange = sectionsCount => setSectionsCount(sectionsCount);
|
const [
|
||||||
|
formOpen,
|
||||||
|
formData,
|
||||||
|
handleSectionAdd,
|
||||||
|
handleSectionEdit,
|
||||||
|
handleSectionDelete,
|
||||||
|
handleMarkAdd,
|
||||||
|
handleMarkEdit,
|
||||||
|
handleMarkDelete,
|
||||||
|
handleDialogClose
|
||||||
|
] = useFormDialog();
|
||||||
|
|
||||||
//При подключении к странице
|
//Состояние ширины и высоты рабочей области окна
|
||||||
|
const [width, height] = useWindowResize();
|
||||||
|
|
||||||
|
//Состояние высоты вкладок с разделами
|
||||||
|
const [pxTabsH, setPxTabsH] = useState(0);
|
||||||
|
|
||||||
|
//При рендере данных
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setConf(Number(getNavigationSearch().NRN));
|
rrpConf.docLoaded ? setPxTabsH(document.getElementById("sectionTabs").offsetHeight) : null;
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
}, [rrpConf.docLoaded]);
|
||||||
}, []);
|
|
||||||
|
//Формируем меню показателей
|
||||||
|
const markMenuItems = [
|
||||||
|
{ method: "EDIT", name: "Исправить", icon: "edit", func: handleMarkEdit },
|
||||||
|
{ method: "DELETE", name: "Удалить", icon: "delete", func: handleMarkDelete }
|
||||||
|
];
|
||||||
|
|
||||||
//Генерация содержимого
|
//Генерация содержимого
|
||||||
return (
|
return (
|
||||||
<Grid container direction={"column"} sx={STYLES.GRID_MAIN_CONTAINER}>
|
<Box sx={STYLES.CONTAINER}>
|
||||||
<Grid item sx={STYLES.GRID_MAIN_SECTIONS_ITEM(sectionsCount === 0)}>
|
{formOpen ? <IUDFormDialog initial={formData} onClose={handleDialogClose} onReload={handleReload} /> : null}
|
||||||
<Grid container sx={STYLES.GRID_SECTIONS_CONTAINER}>
|
{rrpConf.docLoaded ? (
|
||||||
<Sections conf={conf} onSectionChange={handleSectionChange} onSectionCountChange={handleSectionsCountChange} />
|
<Box>
|
||||||
</Grid>
|
<Stack direction="row" sx={STYLES.TABS_BOTTOM_LINE}>
|
||||||
</Grid>
|
<Tabs
|
||||||
{sectionsCount > 0 && (
|
id="sectionTabs"
|
||||||
<Grid item xs>
|
value={tabValue}
|
||||||
<Grid container direction={"row"} sx={STYLES.GRID_SECTION_CONTAINER}>
|
onChange={(event, newValue) => handleSectionChange(newValue)}
|
||||||
<Section section={section} />
|
variant="scrollable"
|
||||||
</Grid>
|
scrollButtons={false}
|
||||||
</Grid>
|
visibleScrollbar
|
||||||
)}
|
aria-label="section tab"
|
||||||
</Grid>
|
sx={STYLES.TABS_SIZES(width, pxSectionAddButtonW)}
|
||||||
|
>
|
||||||
|
{rrpConf.sections.map((s, i) => {
|
||||||
|
return (
|
||||||
|
<Tab
|
||||||
|
key={s.rn}
|
||||||
|
{...a11yProps(i)}
|
||||||
|
sx={STYLES.TABS_PADDING}
|
||||||
|
label={
|
||||||
|
<Box sx={STYLES.SECTION_ACTIONS}>
|
||||||
|
{s.name}
|
||||||
|
<IconButton component="span" onClick={() => handleSectionEdit(s.rn, s.code, s.name)}>
|
||||||
|
<Icon>edit</Icon>
|
||||||
|
</IconButton>
|
||||||
|
<IconButton
|
||||||
|
disabled={s.delete_allow === 0}
|
||||||
|
component="span"
|
||||||
|
onClick={() => handleSectionDelete(s.rn, s.code, s.name)}
|
||||||
|
>
|
||||||
|
<Icon>delete</Icon>
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
wrapped
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Tabs>
|
||||||
|
<Box display="flex" justifyContent="center" alignItems="center" sx={STYLES.PANELS_MAIN_COLOR}>
|
||||||
|
<IconButton onClick={handleSectionAdd}>
|
||||||
|
<Icon sx={STYLES.ICON_WHITE}>add</Icon>
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
</Stack>
|
||||||
|
{rrpConf.sections.map((s, i) => {
|
||||||
|
return (
|
||||||
|
<SectionTab
|
||||||
|
key={s.rn}
|
||||||
|
section={s}
|
||||||
|
tabValue={tabValue}
|
||||||
|
index={i}
|
||||||
|
order={order}
|
||||||
|
onOrderChange={handleOrder}
|
||||||
|
containerProps={{ height, pxOuterMenuH, pxPanelHeaderH, pxTabsH }}
|
||||||
|
handleReload={handleReload}
|
||||||
|
handleMarkOpen={handleMarkOpen}
|
||||||
|
handleMarkAdd={handleMarkAdd}
|
||||||
|
handleMarkCnOpen={handleMarkCnOpen}
|
||||||
|
handleMarkCnInsert={handleMarkCnInsert}
|
||||||
|
menuItems={markMenuItems}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Box>
|
||||||
|
) : null}
|
||||||
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -837,7 +837,7 @@ create or replace package body PKG_P8PANELS_BASE as
|
|||||||
LCVALUE => PKG_CONTPRMLOC.GETLC(RCONTAINER => ARGS_VALS,
|
LCVALUE => PKG_CONTPRMLOC.GETLC(RCONTAINER => ARGS_VALS,
|
||||||
SNAME => RARG_VAL.NAME));
|
SNAME => RARG_VAL.NAME));
|
||||||
if ((SRQ_RESP_ARG is not null) and (RARG_VAL.NAME = SRQ_RESP_ARG)) then
|
if ((SRQ_RESP_ARG is not null) and (RARG_VAL.NAME = SRQ_RESP_ARG)) then
|
||||||
COUT := COALESCE(PKG_CONTPRMLOC.GETLC(RCONTAINER => ARGS_VALS, SNAME => RARG_VAL.NAME), '<XDATA/>');
|
COUT := PKG_CONTPRMLOC.GETLC(RCONTAINER => ARGS_VALS, SNAME => RARG_VAL.NAME);
|
||||||
BRESP_ARG_FOUND := true;
|
BRESP_ARG_FOUND := true;
|
||||||
exit;
|
exit;
|
||||||
end if;
|
end if;
|
||||||
|
File diff suppressed because it is too large
Load Diff
315
dist/p8-panels.js
vendored
315
dist/p8-panels.js
vendored
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user