Compare commits

..

18 Commits

Author SHA1 Message Date
Mim
e1c77731be ЦИТК-979 - Редактор запросов - Исполнение запроса (серверная процедура) 2026-04-15 12:31:21 +03:00
Mim
1c110a25d7 WEBAPP: Свежая сборка 2026-04-15 12:29:36 +03:00
Mim
d67c338651 Документация: обновленный курс, исправлена опечатка в "readme.md" 2026-04-10 23:48:03 +03:00
Mim
4bf3bfb3fa WEBAPP: Флаг "isDataFound" для хуков высокоуровневых компонентов (Гант, Циклограмма, Индикатор, Таблица, График) 2026-04-09 19:04:25 +03:00
Mim
5483e5c39f WEBAPP: Свежая сборка 2026-04-08 12:31:44 +03:00
Mim
f6b16983f5 WEBAPP: Изменен заголовок примера для взаимодействия с ApplicationCtx 2026-04-08 12:31:15 +03:00
Mim
cf8d6d44ae Документация: setAppBarTitle, setAppBarShow, findPanelByName описаны и добавлены в пример 2026-04-08 12:30:04 +03:00
Mim
7d6f1283bb Документация: в хуке P8PDataGrid описаны "resetPageNumberOnStoredArgsChange" и "resetPageNumberOnExecuteStoredArgsChange", косметика в описании хуков компонент верхнего уровня 2026-04-08 11:25:47 +03:00
Mim
9b9c4143e9 WEBAPP: Пример P8PDataGrid дополнен переключателем "Кнопка догрузки/старницы" 2026-04-08 10:34:13 +03:00
Mim
9bdd44f8fc БД: TDG - Флаг отображения кнопки догрузки "false" по умолчанию 2026-04-08 10:28:05 +03:00
Mim
63751700b4 WEBAPP: P8PDataGrid - управление состоянием хука переписано на редьюсер для обеспечения атомарности обновления связанных состояний 2026-04-08 10:23:35 +03:00
Mim
3e6afa284d WEBAPP: Свежая сборка 2026-04-02 18:17:22 +03:00
Mim
96dc129f24 WEBAPP: обновлены настройки WebPack для корректной загрузки изображений из CSS подключаемых как модули (import) 2026-04-02 17:54:22 +03:00
Mim
e441d940ba WEBAPP: Функция сокрытия заголовка приложения ("ApplicationCtx.appBarShow") 2026-04-02 17:45:41 +03:00
Mikhail Chechnev
a5f46513ca WEBAPP: Свежая сборка 2026-03-28 18:14:47 +03:00
Mikhail Chechnev
a5cf661fe6 WEBAPP: Исправлена кириллическая "с" в "Ctx" 2026-03-28 18:13:28 +03:00
Mikhail Chechnev
85d5a5756c Документация: Ссылки на v5.mui.com и косметика 2026-03-28 01:07:54 +03:00
Mim
9e6739af52 ЦИТК-1037 - Хуки для компонентов высокого уровня
Reviewed-on: CITKParus/P8-Panels#43
2026-03-28 00:35:56 +03:00
276 changed files with 2096 additions and 1190 deletions

553
README.md
View File

@ -36,28 +36,28 @@
В фреймворк входят:
- [Библиотека расширения "P8-Panels-ParusOnlineExt.dll"](https://git.citpb.ru/CITKParus/P8-Panels-ParusOnlineExt) для сервера приложений "ПАРУС 8 Онлайн" - обеспечивает низкоуровневое взаимодействие разрабатываемых панелей с Системой
- Хранимые объекты сервера БД Системы, обеспечивающие обмен данными между панелями и учётными регистрами Системы
- API для высокоуровневого взаимодействия с сервером БД Системы
- API для взаимодействия разрабатываемых панелей с WEB-приложением "ПАРУС 8 Онлайн"
- WEB-приложение "Парус 8 - Панели мониторинга", являющееся "точкой входа" для подключения реализуемых панелей, включающее в себя:
- Подключенные и настроенные библиотеки ["React"](https://react.dev/), ["React-Router"](https://reactrouter.com/), ["MUI"](https://mui.com/)
- Настроенный транспайлер ["Babel"](https://babeljs.io/)
- Настроенный сборщик WEB-приложений ["WebPack"](https://webpack.js.org/)
- Настроенный статический анализатор кода ["ESLint"]()
- Настройки среды разработки ["Visual Studio Code"](https://code.visualstudio.com/)
- Готовый контекст React-приложения
- Компоненты для отображения единого бокового меню подключенных панелей, галереи подключенных панелей, интеграции в рабочий стол WEB-приложения "ПАРУС 8 Онлайн"
- Готовые панели мониторинга для ряда прикланых приложений Системы
- [Библиотека расширения "P8-Panels-ParusOnlineExt.dll"](https://git.citpb.ru/CITKParus/P8-Panels-ParusOnlineExt) для сервера приложений "ПАРУС 8 Онлайн" - обеспечивает низкоуровневое взаимодействие разрабатываемых панелей с Системой
- Хранимые объекты сервера БД Системы, обеспечивающие обмен данными между панелями и учётными регистрами Системы
- API для высокоуровневого взаимодействия с сервером БД Системы
- API для взаимодействия разрабатываемых панелей с WEB-приложением "ПАРУС 8 Онлайн"
- WEB-приложение "Парус 8 - Панели мониторинга", являющееся "точкой входа" для подключения реализуемых панелей, включающее в себя:
- Подключенные и настроенные библиотеки ["React"](https://react.dev/), ["React-Router"](https://reactrouter.com/), ["MUI5"](https://v5.mui.com/)
- Настроенный транспайлер ["Babel"](https://babeljs.io/)
- Настроенный сборщик WEB-приложений ["WebPack"](https://webpack.js.org/)
- Настроенный статический анализатор кода ["ESLint"]()
- Настройки среды разработки ["Visual Studio Code"](https://code.visualstudio.com/)
- Готовый контекст React-приложения
- Компоненты для отображения единого бокового меню подключенных панелей, галереи подключенных панелей, интеграции в рабочий стол WEB-приложения "ПАРУС 8 Онлайн"
- Готовые панели мониторинга для ряда прикланых приложений Системы
## III. Требования к разработчику
Для успешной разработки собственных панелей с применением описываемого фреймворка, потребуются знания следующих технологий:
- HTML, CSS, JS, JSX
- Разработка SPA WEB-приложений
- Знакомство с основами работы перечисленных выше библиотек и системных средств (в первую очередь "React")
- Знание архитектуры Системы, принципов работы и организации её серверной части
- HTML, CSS, JS, JSX
- Разработка SPA WEB-приложений
- Знакомство с основами работы перечисленных выше библиотек и системных средств (в первую очередь "React")
- Знание архитектуры Системы, принципов работы и организации её серверной части
На видеохостинге YouTube можно ознакомиться с уроками и обучающими курсами по большинству из перечисленных технологий. Например, с [этими](https://www.youtube.com/results?search_query=%D0%BF%D0%BE%D0%BB%D0%BD%D1%8B%D0%B9+%D0%BA%D1%83%D1%80%D1%81+react).
@ -68,11 +68,11 @@
> **Внимание:**
>
> - **Проверьте версию "ПАРУС 8 Онлайн"**
> - **Проверьте версию "ПАРУС 8 Онлайн"**
>
> Перед копированием расширения из репозитория убедитесь, что в [релизах расширения](https://git.citpb.ru/CITKParus/P8-Panels-ParusOnlineExt/releases) нет специальной сборки для Вашей версии "ПАРУС 8 Онлайн". **Если таковая есть - необходимо устанавливать именно её, а не актуальную сборку из основной ветки репозитория!**
>
> - **Для релиза "ПАРУС 8 Онлайн" от 30.08.2024**
> - **Для релиза "ПАРУС 8 Онлайн" от 30.08.2024**
>
> Требуется [патч для "ПАРУС 8 Онлайн" до промежуточной сборки 02.09.2024](https://cloud.mail.ru/public/nEZb/y4oQa1N6D). Установка расширения на данный релиз не рекомендуется, по возможности - пропустите его.
@ -89,8 +89,8 @@
Где:
- `rootPath="c:\p8web20\Ext\"` - атрибут, указывающий на корневой каталог хранения расширений для сервера приложений "ПАРУС 8 Онлайн"
- `path="P8-Panels-ParusOnlineExt\bin\P8-Panels-ParusOnlineExt.dll"` - атрибут, указывающий на каталог размещения библиотеки расширения "Панели" относительного коревого `rootPath`
- `rootPath="c:\p8web20\Ext\"` - атрибут, указывающий на корневой каталог хранения расширений для сервера приложений "ПАРУС 8 Онлайн"
- `path="P8-Panels-ParusOnlineExt\bin\P8-Panels-ParusOnlineExt.dll"` - атрибут, указывающий на каталог размещения библиотеки расширения "Панели" относительного коревого `rootPath`
4. Установите в файле конфигурации "PrecompiledApp.config" сервера приложений атрибут `updatable` в `true`:
@ -111,30 +111,25 @@ git clone https://git.citpb.ru/CITKParus/P8-Panels.git
При компиляции учитывайте следующее:
- объекты `PKG_P8PANELS`, `PKG_P8PANELS_BASE`, `PKG_P8PANELS_VISUAL` и `P8PNL_SELECTLIST` - обязательны к компиляции. **Это ядро серверной части расширения. Без этих объектов его работа невозможна. Все остальные, перечисленные ниже объекты серверной части - прикладные, не обязательны к компиляции и на функционирование непосредственно фреймворка влияния не оказывают.**
- объекты `PKG_P8PANELS_SAMPLES`, `P8PNL_SMPL_CYCLOGRAM` и `P8PNL_SMPL_GANTT` - обеспечивают работу панели "Samples" ("Примеры для разработчиков"). Это абстрактный набор примеров применения фреймворка, не привязанный жестко к комплектации Системы. Должен откомпилироваться практически в любой комплектации Системы (единственное требование - наличие словаря "Контрагенты").
- объекты `PKG_P8PANELS_PROJECTS`, `P8PNL_JB_JOBS`, `P8PNL_JB_JOBSPREV`, `P8PNL_JB_PERIODS`, `P8PNL_JB_PRJCTS` и `P8PNL_JB_PRMS` - могут быть откомпилированы в Системе, имеющей в комлектации приложения "Планирование и учёт в проектах" и "Управление закупками, складом и реализацией". Эти объекты отвечают за работу панелей группы "Планирование и учёт в проектах" ("PrjFin" - "Экономика проектов", "PrjJobs" - "Работы проектов", "PrjGraph" - "Графики проектов", "PrjInfo" - "Информация о проектах"). Компилируйте только если комлектация Системы включает указанные приложения.
- объект `PKG_P8PANELS_CLNTTSKBRD` - может быть откомпилирован в Системе, имеющей в комлектации приложение "Управление деловыми процессами". Этот объект отвечает за работу панелей группы "Управление деловыми процессами" ("ClntTaskBoard" - "Доски задач"). Компилируйте только если комлектация Системы включает указанное приложение.
- объект `PKG_P8PANELS_MECHREC` - может быть откомпилирован в Системе, имеющей в комлектации приложение "Планирование и учёт в дискретном производстве". Этот объект отвечает за работу панелей группы "Планирование и учёт в дискретном производстве" ("MechRecCostProdPlans" - "Производственная программа", "MechRecDeptCostProdPlans" - "Производственный план цеха", "MechRecCostJobsManage" - "Выдача сменного задания", "MechRecCostJobsManageMP" - "Выдача сменного задания на участок", "MechRecDeptCostJobs" - "Загрузка цеха", "MechRecAssemblyMon" - "Мониторинг сборки изделий"). Компилируйте только если комлектация Системы включает указанное приложение.
- объект `PKG_P8PANELS_EQUIPSRV` - может быть откомпилирован в Системе, имеющей в комлектации приложение "Управление техническим обслуживанием и ремонтами". Этот объект отвечает за работу панелей группы "Управление техническим обслуживанием и ремонтами" ("EqsPrfrm" - "Выполнение работ по ТОиР"). Компилируйте только если комлектация Системы включает указанное приложение.
- объект `PKG_P8PANELS_RRPCONFED` - может быть откомпилирован в Системе, имеющей в комлектации приложение "Сервис регламентированной и управленческой отчётности". Этот объект отвечает за работу панели "RrpConfEditor" ("Редактор настройки регламентированного отчёта"). Компилируйте только если комлектация Системы включает указанное приложение.
- объекты `PKG_P8PANELS`, `PKG_P8PANELS_BASE`, `PKG_P8PANELS_VISUAL` и `P8PNL_SELECTLIST` - обязательны к компиляции. **Это ядро серверной части расширения. Без этих объектов его работа невозможна. Все остальные, перечисленные ниже объекты серверной части - прикладные, не обязательны к компиляции и на функционирование непосредственно фреймворка влияния не оказывают.**
- объекты `PKG_P8PANELS_SAMPLES`, `P8PNL_SMPL_CYCLOGRAM` и `P8PNL_SMPL_GANTT` - обеспечивают работу панели "Samples" ("Примеры для разработчиков"). Это абстрактный набор примеров применения фреймворка, не привязанный жестко к комплектации Системы. Должен откомпилироваться практически в любой комплектации Системы (единственное требование - наличие словаря "Контрагенты").
- объекты `PKG_P8PANELS_PROJECTS`, `P8PNL_JB_JOBS`, `P8PNL_JB_JOBSPREV`, `P8PNL_JB_PERIODS`, `P8PNL_JB_PRJCTS` и `P8PNL_JB_PRMS` - могут быть откомпилированы в Системе, имеющей в комлектации приложения "Планирование и учёт в проектах" и "Управление закупками, складом и реализацией". Эти объекты отвечают за работу панелей группы "Планирование и учёт в проектах" ("PrjFin" - "Экономика проектов", "PrjJobs" - "Работы проектов", "PrjGraph" - "Графики проектов", "PrjInfo" - "Информация о проектах"). Компилируйте только если комлектация Системы включает указанные приложения.
- объект `PKG_P8PANELS_CLNTTSKBRD` - может быть откомпилирован в Системе, имеющей в комлектации приложение "Управление деловыми процессами". Этот объект отвечает за работу панелей группы "Управление деловыми процессами" ("ClntTaskBoard" - "Доски задач"). Компилируйте только если комлектация Системы включает указанное приложение.
- объект `PKG_P8PANELS_MECHREC` - может быть откомпилирован в Системе, имеющей в комлектации приложение "Планирование и учёт в дискретном производстве". Этот объект отвечает за работу панелей группы "Планирование и учёт в дискретном производстве" ("MechRecCostProdPlans" - "Производственная программа", "MechRecDeptCostProdPlans" - "Производственный план цеха", "MechRecCostJobsManage" - "Выдача сменного задания", "MechRecCostJobsManageMP" - "Выдача сменного задания на участок", "MechRecDeptCostJobs" - "Загрузка цеха", "MechRecAssemblyMon" - "Мониторинг сборки изделий"). Компилируйте только если комлектация Системы включает указанное приложение.
- объект `PKG_P8PANELS_EQUIPSRV` - может быть откомпилирован в Системе, имеющей в комлектации приложение "Управление техническим обслуживанием и ремонтами". Этот объект отвечает за работу панелей группы "Управление техническим обслуживанием и ремонтами" ("EqsPrfrm" - "Выполнение работ по ТОиР"). Компилируйте только если комлектация Системы включает указанное приложение.
- объект `PKG_P8PANELS_RRPCONFED` - может быть откомпилирован в Системе, имеющей в комлектации приложение "Сервис регламентированной и управленческой отчётности". Этот объект отвечает за работу панели "RrpConfEditor" ("Редактор настройки регламентированного отчёта"). Компилируйте только если комлектация Системы включает указанное приложение.
7. Перезапустите сервер приложений "ПАРУС 8 Онлайн"
> **Внимание:** при установке учитывайте следующее:
>
> - **Для Linux/Unix**
>
> - Чувствительность к регистру - обращайте внимание на регистр в именах каталогов и файлов операционной системы и регистр в котором упоминаете их в конфигурационных файлах, несовпадение приводит к неработоспособности настроек
> - Права доступа - файлы конфигурации и файлы дистрибутива фреймворка должны быть доступны процессу WEB-сервера
>
> - **Для Windows 7 и прочих устаревших версий Windows**
>
> - Версия IIS, доступная для этих ОС, зачастую не имеет автоматической поддержки шрифтов в формате "WOFF2", применяемых фреймворком. Это может вызывать некорректное отображение панелей, иконок, некоторых элементов пользовательского интерфейса. Добавте в файл "web.config", сервера приложений "ПАРУС 8 Онлайн", строку для определения формата: `<mimeMap fileExtension=".woff2" mimeType="application/font-woff2" />`. Путь для добавления данной настройки в файл "web.config": `configuration/system.webServer/staticContent/<mimeMap fileExtension=".woff2" mimeType="application/font-woff2" />`
>
> - **Для всех**
>
> - Если после установки фреймворка, при открытии панелей появляется ошибка `Internal server error` (HTTP-статус ответа сервера - 500), и Вы уверены, что перепроверили всё описанное выше в интрукции и не нашли ошибок установки, то: остановите сервер приложений "ПАРУС 8 Онлайн", сделайте резервную копию его каталога "bin" и удалите каталог, затем скачайте "web.zip" из дистрибутива Вашего релиза "ПАРУС 8 Онлайн" и восстановите удалённый каталог "bin", распаковав его из архива. Затем - запустите сервер приложений "ПАРУС 8 Онлайн".
> - **Для Linux/Unix**
> - Чувствительность к регистру - обращайте внимание на регистр в именах каталогов и файлов операционной системы и регистр в котором упоминаете их в конфигурационных файлах, несовпадение приводит к неработоспособности настроек
> - Права доступа - файлы конфигурации и файлы дистрибутива фреймворка должны быть доступны процессу WEB-сервера
> - **Для Windows 7 и прочих устаревших версий Windows**
> - Версия IIS, доступная для этих ОС, зачастую не имеет автоматической поддержки шрифтов в формате "WOFF2", применяемых фреймворком. Это может вызывать некорректное отображение панелей, иконок, некоторых элементов пользовательского интерфейса. Добавте в файл "web.config", сервера приложений "ПАРУС 8 Онлайн", строку для определения формата: `<mimeMap fileExtension=".woff2" mimeType="application/font-woff2" />`. Путь для добавления данной настройки в файл "web.config": `configuration/system.webServer/staticContent/<mimeMap fileExtension=".woff2" mimeType="application/font-woff2" />`
> - **Для всех**
> - Если после установки фреймворка, при открытии панелей появляется ошибка `Internal server error` (HTTP-статус ответа сервера - 500), и Вы уверены, что перепроверили всё описанное выше в интрукции и не нашли ошибок установки, то: остановите сервер приложений "ПАРУС 8 Онлайн", сделайте резервную копию его каталога "bin" и удалите каталог, затем скачайте "web.zip" из дистрибутива Вашего релиза "ПАРУС 8 Онлайн" и восстановите удалённый каталог "bin", распаковав его из архива. Затем - запустите сервер приложений "ПАРУС 8 Онлайн".
## V. Подключение панелей
@ -180,29 +175,29 @@ git clone https://git.citpb.ru/CITKParus/P8-Panels.git
Настройки хранятся в формате XML. Корневым тэгом документа должен быть `CITK.P8Panels`. Дочерними для него могут быть две ветки конфигурации:
- `MenuItems` - настройка пунктов главного меню WEB-приложения "ПАРУС 8 Онлайн"
- `Panels` - общий список панелей, подключаемых к приложению (не все панели обязательно выводить в виде пунктов меню)
- `MenuItems` - настройка пунктов главного меню WEB-приложения "ПАРУС 8 Онлайн"
- `Panels` - общий список панелей, подключаемых к приложению (не все панели обязательно выводить в виде пунктов меню)
`MenuItems` состоит из элементов `App`, каждый из которых определяет для какого из приложений Системы описываются пункты меню. `MenuItems` может содержать несколько элементов `App`. Каждый элемент `App` должен иметь обязательный атрибут `name`, определяющий код приложения Системы (см. колонку `APPCODE` в таблице `APPLIST`), в которое будут добавлены пункты меню. Дочерними для элемента `App` являются элементы `MenuItem`, каждый из которых описывает создаваемый расширением пункт меню. `App` может содержать несколько `MenuItem`. Каждый из `MenuItem` может иметь следующие атрибуты:
- `parent` - обязательный, содержит GUID родительского пункта меню, к которому будет добавлен описываемый дочерний пункт (см. `P_MENUS_CREATE_*_MENU`, где `*` - код приложения Системы)
- `separator` - необязательный, принимает значения "true" или "false", если "true" - создаваемый пункт меню будет разделителем, остальные атрибуты, описанные ниже будут проигнорированы
- `name` - необязательный для `separator="true"`, в прочих случаях - обязательный, уникальное имя пункта меню
- `caption` - необязательный для `separator="true"`, в прочих случаях - обязательный, видимый текст пункта меню
- `panelName` - необязательный для `separator="true"` или если указан атрибут `url`, в прочих случаях - обязательный, определяет код панели, открываемой при выборе данного пункта меню конечным пользователем (коды панелей объявляются в секции `Panels` данного файла конфигурации, описана ниже)
- `url` - необязательный для `separator="true"` или если указан атрибут `panelName`, в прочих случаях - обязательный, определяет URL, который будет открыт в отдельной закладке "ПАРУС 8 Онлайн" при выборе данного пункта меню конечным пользователем (в приведённом примере, для пункта меню "ShowPrjPanelsRoot" открывает домашнюю страницу WEB-приложения "Парус 8 - Панели мониторинга", отображающую галерею доступных панелей, см. ниже описание атрибута `urlBase` элемента `Panels`)
- `parent` - обязательный, содержит GUID родительского пункта меню, к которому будет добавлен описываемый дочерний пункт (см. `P_MENUS_CREATE_*_MENU`, где `*` - код приложения Системы)
- `separator` - необязательный, принимает значения "true" или "false", если "true" - создаваемый пункт меню будет разделителем, остальные атрибуты, описанные ниже будут проигнорированы
- `name` - необязательный для `separator="true"`, в прочих случаях - обязательный, уникальное имя пункта меню
- `caption` - необязательный для `separator="true"`, в прочих случаях - обязательный, видимый текст пункта меню
- `panelName` - необязательный для `separator="true"` или если указан атрибут `url`, в прочих случаях - обязательный, определяет код панели, открываемой при выборе данного пункта меню конечным пользователем (коды панелей объявляются в секции `Panels` данного файла конфигурации, описана ниже)
- `url` - необязательный для `separator="true"` или если указан атрибут `panelName`, в прочих случаях - обязательный, определяет URL, который будет открыт в отдельной закладке "ПАРУС 8 Онлайн" при выборе данного пункта меню конечным пользователем (в приведённом примере, для пункта меню "ShowPrjPanelsRoot" открывает домашнюю страницу WEB-приложения "Парус 8 - Панели мониторинга", отображающую галерею доступных панелей, см. ниже описание атрибута `urlBase` элемента `Panels`)
`Panels` - содержит список элементов `Panel`, описывающих подключенные панели. Элемент `Panels` имеет атрибут `urlBase`, определяющий корневой URL WEB-приложения "Парус 8 - Панели мониторинга", относительно него формируются URL панелей. Значение `urlBase` определяется физическим расположением WEB-приложения "Парус 8 - Панели мониторинга" на диске сервера приложений (см. пункт 5 в главе "IV. Установка"). В данном примеры, файлы WEB-приложения распологаются в каталоге "Modules/p8-panels" сервера приложений. Каждый из элементов `Panel`, дочерних для `Panels`, описывает одну панель и имеет следующие атрибуты:
- `name` - обязательный, строка, указывается латиницей, определяет уникальное имя панели
- `group` - необязательный, строка, указывается кириллицей, определяет имя группы, в которую входит панель (применяется при формировании галереи панелей, главного меню панелей и ссылок на рабочем столе)
- `caption` - обязательный, строка, видимое наименование панели (применяется в галереи панелей, главном меню панелей, ссылках на рабочем столе, заголовках закладок)
- `desc` - необязательный, строка,
- `url` - обязательный, строка, указывается латиницей, относительй URL панели (по адресу `Panel.urlBase` + `Panel.Panels.url` сервер приложений "ПАРУС 8 Онлайн" будет выдавать HTML-страницу панели), для простоты навигации может повторять значение атрибута `path`
- `path` - обязательный, строка, путь к исходному коду панели в структуре каталогов WEB-приложения "Парус 8 - Панели мониторинга" (панели должны размещаться в "app/panels", в данном атрибуте указыватся только имя каталога, созданного для панели в "app/panels")
- `icon` - обязательный, строка, код иконки панели из символов шрифта [Google Material Icons](https://fonts.google.com/icons?icon.set=Material+Icons) (применяется при формировании галереи панелей, главного меню панелей и ссылок на рабочем столе)
- `showInPanelsList` - обязательный, принимает значения "true" или "false", определяет отображение ссылки на панель в галереи панелей, главном меню панелей, виджете рабочего стола
- `preview` - полный путь и имя файла из каталога "img" WEB-приложения "Парус 8 - Панели мониторинга" (в каталог могут быть добавлены пользовательские изображения), служит в качестве изображения панели в галерее панелей
- `name` - обязательный, строка, указывается латиницей, определяет уникальное имя панели
- `group` - необязательный, строка, указывается кириллицей, определяет имя группы, в которую входит панель (применяется при формировании галереи панелей, главного меню панелей и ссылок на рабочем столе)
- `caption` - обязательный, строка, видимое наименование панели (применяется в галерее панелей, главном меню панелей, ссылках на рабочем столе, заголовках закладок)
- `desc` - необязательный, строка,
- `url` - обязательный, строка, указывается латиницей, относительй URL панели (по адресу `Panel.urlBase` + `Panel.Panels.url` сервер приложений "ПАРУС 8 Онлайн" будет выдавать HTML-страницу панели), для простоты навигации может повторять значение атрибута `path`
- `path` - обязательный, строка, путь к исходному коду панели в структуре каталогов WEB-приложения "Парус 8 - Панели мониторинга" (панели должны размещаться в "app/panels", в данном атрибуте указыватся только имя каталога, созданного для панели в "app/panels")
- `icon` - обязательный, строка, код иконки панели из символов шрифта [Google Material Icons](https://fonts.google.com/icons?icon.set=Material+Icons) (применяется при формировании галереи панелей, главного меню панелей и ссылок на рабочем столе)
- `showInPanelsList` - обязательный, принимает значения "true" или "false", определяет отображение ссылки на панель в галерее панелей, главном меню панелей, виджете рабочего стола
- `preview` - полный путь и имя файла из каталога "img" WEB-приложения "Парус 8 - Панели мониторинга" (в каталог могут быть добавлены пользовательские изображения), служит в качестве изображения панели в галерее панелей
На рисунках ниже проиллюстрировано применение атрибутов элемента `Panel`.
@ -229,9 +224,9 @@ WEB-приложение "ПАРУС 8 Онлайн" поддерживает в
Где:
- `Modules/p8-panels/#/` - путь к домашней странице WEB-приложения "Парус 8 - Панели мониторинга", указанный в атрибуте `Panels.urlBase` файла конфигурации "p8panels.config"
- `mode=DESKTOP` - параметр вызова домашней страниы WEB-приложения "Парус 8 - Панели мониторинга", обязывающий сформировать меню панелей в специальном формате, для интеграции в рабочий стол
- `group=ИМЯ_ГРУППЫ` - параметр вызова домашней страниы WEB-приложения "Парус 8 - Панели мониторинга", позволяющий ограничить набор формируемых ссылок на панели только одной их группой (см. выше описание атрибута `Panel.group` файла конфигурации "p8panels.config")
- `Modules/p8-panels/#/` - путь к домашней странице WEB-приложения "Парус 8 - Панели мониторинга", указанный в атрибуте `Panels.urlBase` файла конфигурации "p8panels.config"
- `mode=DESKTOP` - параметр вызова домашней страниы WEB-приложения "Парус 8 - Панели мониторинга", обязывающий сформировать меню панелей в специальном формате, для интеграции в рабочий стол
- `group=ИМЯ_ГРУППЫ` - параметр вызова домашней страниы WEB-приложения "Парус 8 - Панели мониторинга", позволяющий ограничить набор формируемых ссылок на панели только одной их группой (см. выше описание атрибута `Panel.group` файла конфигурации "p8panels.config")
Место элемента `Frame` в структуре XML-конфигурации рабочего стола зависит от его текущего содержимого. Например, для рабочего стола по-умолчанию приложения "Планирование и учёт в проектах" это `Desktop\ContentContainer\Frame`:
@ -268,9 +263,9 @@ WEB-приложение "ПАРУС 8 Онлайн" поддерживает в
Панель может быть вызвана из действия раздела Системы (только для WEB-клиента). Для это необходимо зарегистрировать (здесь и далее - настройка выполняется в приложении "Контрусктор отраслевых расширений" для соответствующих классов Системы) в разделе метод с кодом "P8PANELS_OPEN", при этом метод обязательно должен иметь "Тип метода" - "Встроенный", а "Доступность" - "Клиентский". Для метода необходимо настроить параметры:
- `SPANEL` - строка, обязательный, уникальное имя (`name`) той панели из "p8panels.config", которая должна быть открыта действием
- `SCAPTION` - строка, необязательный, заголовок вкладки WEB-приложения "ПАРУС 8 Онлайн", в которой будет открыта панель, если не задан - будет использовано видимое наименование панели (`caption`) из "p8panels.config"
- `NIDENT` - число, необязательный, но требуется если предполагается, что панель должна работать со списком отмеченных документов, параметр следует привязать к контексту "Идентификатор отмеченных записей"
- `SPANEL` - строка, обязательный, уникальное имя (`name`) той панели из "p8panels.config", которая должна быть открыта действием
- `SCAPTION` - строка, необязательный, заголовок вкладки WEB-приложения "ПАРУС 8 Онлайн", в которой будет открыта панель, если не задан - будет использовано видимое наименование панели (`caption`) из "p8panels.config"
- `NIDENT` - число, необязательный, но требуется если предполагается, что панель должна работать со списком отмеченных документов, параметр следует привязать к контексту "Идентификатор отмеченных записей"
Указанные параметры - зарезервированы и могут выполнять только указанную функцию. Тем не менее, метод может иметь произвольный набор прочих параметров, необходимых для работы панели. Все параметры (кроме `SPANEL` и `SCAPTION` - они системные и требуется непосредственно для корректного откытия панели, но не для её работы) будут переданы в панель в виде GET-запроса. Получить их значения в коде панели можно применив специальный API фреймворка, реализованный в `NavigationCtx`:
@ -298,9 +293,9 @@ const MyPanel = () => {
В настоящий момент в Системе можно зарегистрировать сколь угодно много методов с кодом "P8PANELS_OPEN", но не более одного в каждом разделе. Если есть необходимость открытия из одного раздела нескольких различных панелей, то рекомендуется:
- Реализовать дополнительную навигацию в открываемой панели
- Реализовать в КОР-действии параметр с выпадающим списком (или иным интерфейсным элементом), позволяющим пользователю выбрать какую именно панель ему необходимо открыть сейчас
- Определять значение параметра `SPANEL` КОР-метода "P8PANELS_OPEN" из контекста (документа, атрибута, каталога и т.п.), таким образом автоматически определяя открываемую панель
- Реализовать дополнительную навигацию в открываемой панели
- Реализовать в КОР-действии параметр с выпадающим списком (или иным интерфейсным элементом), позволяющим пользователю выбрать какую именно панель ему необходимо открыть сейчас
- Определять значение параметра `SPANEL` КОР-метода "P8PANELS_OPEN" из контекста (документа, атрибута, каталога и т.п.), таким образом автоматически определяя открываемую панель
#### Настройка КОР-действия для вызова панели "Выдача сменного задания" из раздела "Сменные задания"
@ -312,10 +307,10 @@ const MyPanel = () => {
2. В дереве классов выберите "Сменные задания", а в списке классов - класс с кодом "CostJobs"
3. В спецификации "Методы", выбранного класса, зарегистрируйте новый метод со следующими атрибутами:
- `Мнемокод` - P8PANELS_OPEN
- `Наименование` - P8PANELS_OPEN
- `Тип метода` - Встроенный
- `Доступность` - Клиентский
- `Мнемокод` - P8PANELS_OPEN
- `Наименование` - P8PANELS_OPEN
- `Тип метода` - Встроенный
- `Доступность` - Клиентский
4. Для добавленного метода `P8PANELS_OPEN` в спецификации "Параметры" зарегистрируйте следующий набор параметров:
@ -327,14 +322,14 @@ const MyPanel = () => {
5. В спецификации "Действия", выбранного класса, зарегистрируйте новое действие со следующими атрибутами:
- `Тип` - Нестандартное
- `Код` - FCJOBS_OPEN_JOBS_MANAGE
- `Наименование` - Открытие панели "Выдача сменного задания"
- `Технология производства` - Конструктор
- `Реализующий метод` - P8PANELS_OPEN
- `Обработка записей` - Для одной текущей записи
- `Завершение транзакции` - После каждого вызова действия
- `Обновление выборки` - Не обновлять
- `Тип` - Нестандартное
- `Код` - FCJOBS_OPEN_JOBS_MANAGE
- `Наименование` - Открытие панели "Выдача сменного задания"
- `Технология производства` - Конструктор
- `Реализующий метод` - P8PANELS_OPEN
- `Обработка записей` - Для одной текущей записи
- `Завершение транзакции` - После каждого вызова действия
- `Обновление выборки` - Не обновлять
6. Для добавленного действия `FCJOBS_OPEN_JOBS_MANAGE` в спецификации "Параметры" зарегистрируйте следующий набор параметров:
@ -349,7 +344,7 @@ const MyPanel = () => {
В открывшемся редакторе формы перейдите в режим редактирования всплывающего меню заголовка (закладка "Таблицы", таблица "CostJobs", затем кнопка "Редактор источника", установить фокус на форме представления данных щелчком мыши, затем пункт "Всплывающее меню" в "Инспекторе объектов"). Найдите в меню пункт, созданный Системой для действия, зарегистрированного на шаге 5 (как правило имеет метку, совпадающую с наименованием действия). Расположите (перетаскиванием) этот пункт меню сразу после пункта "Отработать исполнение по штрих-кодам". Укажите для этого пункта следующие параметры в "Инспекторе объектов":
- `Заголовок` - Выдать сменное задание…
- `Заголовок` - Выдать сменное задание…
Закройте окна редакторов с сохранением изменений.
@ -365,10 +360,10 @@ const MyPanel = () => {
2. В дереве классов выберите "Сменные задания", а в списке классов - класс с кодом "CostJobs"
3. В спецификации "Методы", выбранного класса, зарегистрируйте новый метод со следующими атрибутами:
- `Мнемокод` - P8PANELS_OPEN
- `Наименование` - P8PANELS_OPEN
- `Тип метода` - Встроенный
- `Доступность` - Клиентский
- `Мнемокод` - P8PANELS_OPEN
- `Наименование` - P8PANELS_OPEN
- `Тип метода` - Встроенный
- `Доступность` - Клиентский
4. Для добавленного метода `P8PANELS_OPEN` в спецификации "Параметры" зарегистрируйте следующий набор параметров:
@ -380,14 +375,14 @@ const MyPanel = () => {
5. В спецификации "Действия", выбранного класса, зарегистрируйте новое действие со следующими атрибутами:
- `Тип` - Нестандартное
- `Код` - FCJOBS_OPEN_JOBS_MANAGE_MP
- `Наименование` - Открытие панели "Выдача сменного задания на участок"
- `Технология производства` - Конструктор
- `Реализующий метод` - P8PANELS_OPEN
- `Обработка записей` - Для одной текущей записи
- `Завершение транзакции` - После каждого вызова действия
- `Обновление выборки` - Не обновлять
- `Тип` - Нестандартное
- `Код` - FCJOBS_OPEN_JOBS_MANAGE_MP
- `Наименование` - Открытие панели "Выдача сменного задания на участок"
- `Технология производства` - Конструктор
- `Реализующий метод` - P8PANELS_OPEN
- `Обработка записей` - Для одной текущей записи
- `Завершение транзакции` - После каждого вызова действия
- `Обновление выборки` - Не обновлять
6. Для добавленного действия `FCJOBS_OPEN_JOBS_MANAGE_MP` в спецификации "Параметры" зарегистрируйте следующий набор параметров:
@ -402,7 +397,7 @@ const MyPanel = () => {
В открывшемся редакторе формы перейдите в режим редактирования всплывающего меню заголовка (закладка "Таблицы", таблица "CostJobs", затем кнопка "Редактор источника", установить фокус на форме представления данных щелчком мыши, затем пункт "Всплывающее меню" в "Инспекторе объектов"). Найдите в меню пункт, созданный Системой для действия, зарегистрированного на шаге 5 (как правило имеет метку, совпадающую с наименованием действия). Расположите (перетаскиванием) этот пункт меню сразу после пункта "Отработать исполнение по штрих-кодам". Укажите для этого пункта следующие параметры в "Инспекторе объектов":
- `Заголовок` - Выдать сменное задание на участок…
- `Заголовок` - Выдать сменное задание на участок…
Закройте окна редакторов с сохранением изменений.
@ -418,10 +413,10 @@ const MyPanel = () => {
2. В дереве классов выберите "Планы и отчеты производства изделий (спецификация)", а в списке классов - класс с кодом "CostProductPlansSpecs"
3. В спецификации "Методы", выбранного класса, зарегистрируйте новый метод со следующими атрибутами:
- `Мнемокод` - P8PANELS_OPEN
- `Наименование` - P8PANELS_OPEN
- `Тип метода` - Встроенный
- `Доступность` - Клиентский
- `Мнемокод` - P8PANELS_OPEN
- `Наименование` - P8PANELS_OPEN
- `Тип метода` - Встроенный
- `Доступность` - Клиентский
4. Для добавленного метода `P8PANELS_OPEN` в спецификации "Параметры" зарегистрируйте следующий набор параметров:
@ -433,14 +428,14 @@ const MyPanel = () => {
5. В спецификации "Действия", выбранного класса, зарегистрируйте новое действие со следующими атрибутами:
- `Тип` - Нестандартное
- `Код` - FCPRODPLANSP_OPEN_COST_PROD_PLANS
- `Наименование` - Открытие панели "Производственная программа"
- `Технология производства` - Конструктор
- `Реализующий метод` - P8PANELS_OPEN
- `Обработка записей` - Для одной текущей записи
- `Завершение транзакции` - После каждого вызова действия
- `Обновление выборки` - Не обновлять
- `Тип` - Нестандартное
- `Код` - FCPRODPLANSP_OPEN_COST_PROD_PLANS
- `Наименование` - Открытие панели "Производственная программа"
- `Технология производства` - Конструктор
- `Реализующий метод` - P8PANELS_OPEN
- `Обработка записей` - Для одной текущей записи
- `Завершение транзакции` - После каждого вызова действия
- `Обновление выборки` - Не обновлять
6. Для добавленного действия `FCPRODPLANSP_OPEN_COST_PROD_PLANS` в спецификации "Параметры" зарегистрируйте следующий набор параметров:
@ -455,8 +450,8 @@ const MyPanel = () => {
В открывшемся редакторе формы перейдите в режим редактирования всплывающего меню спецификации (закладка "Таблицы", таблица "CostProductPlansSpecs", затем кнопка "Редактор источника", установить фокус на форме представления данных щелчком мыши, затем пункт "Всплывающее меню" в "Инспекторе объектов"). Найдите в меню пункт, созданный Системой для действия, зарегистрированного на шаге 5 (как правило имеет метку, совпадающую с наименованием действия). Расположите (перетаскиванием) этот пункт меню сразу после пункта "Формирование". Укажите для этого пункта следующие параметры в "Инспекторе объектов":
- `Заголовок` - Открыть диаграмму…
- `Правило доступности` - @nCATEGORY = 1 and @nSTATUS = 2
- `Заголовок` - Открыть диаграмму…
- `Правило доступности` - @nCATEGORY = 1 and @nSTATUS = 2
Закройте окна редакторов с сохранением изменений.
@ -478,9 +473,9 @@ const MyPanel = () => {
С точки зрения клиенсткой части, Панели представляют собой функциональные компоненты React, автоматически (благодаря описанному выше файлу конфигурации) встраиваемые в систему маршрутизации WEB-приложения "Парус 8 - Панели мониторинга" (далее "приложения" или "WEB-приложения", если контекст явно не указывает на иное). Каждая панель состоит из:
- Набора JS-объектов и функций, управляющих состоянием панели
- Функций для обмена данными с сервером БД Системы и выполнения бизнес-процедур в ней
- JSX разметки, отражающей смену состояния панели
- Набора JS-объектов и функций, управляющих состоянием панели
- Функций для обмена данными с сервером БД Системы и выполнения бизнес-процедур в ней
- JSX разметки, отражающей смену состояния панели
Такая структура исходного кода панели продиктована архитектурными требованиями к функциональным React-компонентам. Каждая панель (и все необходимые для её функционирования JS-модули и вспомогательный файлы) размещается в отдельном каталоге (см. выше - "app/panels", здесь и далее каталоги указаны относительно корневого каталога размещения приложения, если явно не указано иное) WEB-приложения "Парус 8 - Панели мониторинга".
@ -520,19 +515,19 @@ c:\inetpub\p8web20\WebClient\Modules\P8-Panels>npm run build
> **Обратите внимание:** Здесь и далее - описываемый API (как клиентский, так и серверный) не является финальным и может быть изменён с целью развития фреймворка. В этой связи, необходимо закладывать дополнительное время на обновления расширения "Панели", связанное с возможной необходимостью приведения разработанных самостоятельно интерфейсов (их клиентских и серверных частей) к доработанному API.
Для исполнения хранимых процедур/функций БД Системы в составе расширения предусмотрен специальный API. Его подключение к компоненте панели осуществляется через контекст `BackEndСtx` ("app/context/backend.js").
Для исполнения хранимых процедур/функций БД Системы в составе расширения предусмотрен специальный API. Его подключение к компоненте панели осуществляется через контекст `BackEndCtx` ("app/context/backend.js").
В состав API входят:
- `SERV_DATA_TYPE_STR` - константа для типа данных "строка", при описании параметров исполняемых хранимых объектов
- `SERV_DATA_TYPE_NUMB` - константа для типа данных "число", при описании параметров исполняемых хранимых объектов
- `SERV_DATA_TYPE_DATE` - константа для типа данных "дата", при описании параметров исполняемых хранимых объектов
- `SERV_DATA_TYPE_CLOB` - константа для типа данных "текст", при описании параметров исполняемых хранимых объектов
- `isRespErr` - функция, проверка результата исполнения серверного объекта на наличие ошибок
- `getRespErrMessage` - функция, получение ошибки исполнения серверного объекта
- `getRespPayload` - функция, получение выходных значений, полученных после успешного исполнения
- `executeStored` - функция, асинхронное исполнение хранимой процедуры/функции БД Системы
- `getConfig` - функция, асинхронное считывание параметров конфигурации, определённых в "p8panels.config" (возвращает их JSON-представление)
- `SERV_DATA_TYPE_STR` - константа для типа данных "строка", при описании параметров исполняемых хранимых объектов
- `SERV_DATA_TYPE_NUMB` - константа для типа данных "число", при описании параметров исполняемых хранимых объектов
- `SERV_DATA_TYPE_DATE` - константа для типа данных "дата", при описании параметров исполняемых хранимых объектов
- `SERV_DATA_TYPE_CLOB` - константа для типа данных "текст", при описании параметров исполняемых хранимых объектов
- `isRespErr` - функция, проверка результата исполнения серверного объекта на наличие ошибок
- `getRespErrMessage` - функция, получение ошибки исполнения серверного объекта
- `getRespPayload` - функция, получение выходных значений, полученных после успешного исполнения
- `executeStored` - функция, асинхронное исполнение хранимой процедуры/функции БД Системы
- `getConfig` - функция, асинхронное считывание параметров конфигурации, определённых в "p8panels.config" (возвращает их JSON-представление)
При формировании ответов, функции, получающие данные с сервера, возвращают типовые значения:
@ -552,9 +547,9 @@ c:\inetpub\p8web20\WebClient\Modules\P8-Panels>npm run build
Где:
- `SSTATUS` - строка, состояние исполнения (`"OK"` - успех или `"ERR"` - ошибка)
- `XPAYLOAD` - объект, полезная нагрузка, данные полученные от серверного объекта (отсутствует, если `SSTATUS = "ERR"`)
- `SMESSAGE` - строка, текст сообщения об ошибке (отсутствует, если `SSTATUS = "OK"`)
- `SSTATUS` - строка, состояние исполнения (`"OK"` - успех или `"ERR"` - ошибка)
- `XPAYLOAD` - объект, полезная нагрузка, данные полученные от серверного объекта (отсутствует, если `SSTATUS = "ERR"`)
- `SMESSAGE` - строка, текст сообщения об ошибке (отсутствует, если `SSTATUS = "OK"`)
#### `boolean isRespErr(Object)`
@ -622,7 +617,7 @@ c:\inetpub\p8web20\WebClient\Modules\P8-Panels>npm run build
```
import React, { useState, useContext } from "react"; //Классы React
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
//Функциональный компонент панели (или её части)
const MyPanel = () => {
@ -630,7 +625,7 @@ const MyPanel = () => {
const [state, setState] = useState({ dataLoaded: false, data: [], filters: null, orders: null });
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//Загрузка данных проектов с сервера
const loadProjects = async (agentName) => {
@ -713,18 +708,21 @@ const MyPanel = () => {
}
```
### API для взаимодействия с WEB-приложением "ПАРУС 8 Онлайн"
### API для взаимодействия с WEB-приложением "ПАРУС 8 Онлайн" и ядром фреймворка
Для взаимодействия панелей с пользовательским интерфейсом "ПАРУС 8 Онлайн" в составе расширения предусмотрен специальный API. Его подключение к компоненте панели осуществляется через контекст `ApplicationСtx` ("app/context/application.js").
Для взаимодействия панелей с пользовательским интерфейсом "ПАРУС 8 Онлайн" в составе расширения предусмотрен специальный API. Его подключение к компоненте панели осуществляется через контекст `ApplicationCtx` ("app/context/application.js"). Данный контекст так же позволяет управлять некоторыми базовыми функциями приложения фреймворка и получать сведения о зарегистрированных панелях.
В состав API входят:
- `pOnlineShowTab` - функция, отображение типовой закладки "ПАРУС 8 Онлайн"
- `pOnlineShowUnit` - функция, отображение раздела "ПАРУС 8 Онлайн" в модальном режиме или на закладке
- `pOnlineShowDocument` - функция, отображение раздела "ПАРУС 8 Онлайн" в модальном режиме (или на закладке) с позиционированием/отбором по документу
- `pOnlineShowDictionary` - функция, отображение раздела "ПАРУС 8 Онлайн" в режиме словаря
- `pOnlineUserProcedure` - функция, исполнение "Пользовательской процедуры"
- `pOnlineUserReport` - функция, печать "Пользовательского отчёта"
- `pOnlineShowTab` - функция, отображение типовой закладки "ПАРУС 8 Онлайн"
- `pOnlineShowUnit` - функция, отображение раздела "ПАРУС 8 Онлайн" в модальном режиме или на закладке
- `pOnlineShowDocument` - функция, отображение раздела "ПАРУС 8 Онлайн" в модальном режиме (или на закладке) с позиционированием/отбором по документу
- `pOnlineShowDictionary` - функция, отображение раздела "ПАРУС 8 Онлайн" в режиме словаря
- `pOnlineUserProcedure` - функция, исполнение "Пользовательской процедуры"
- `pOnlineUserReport` - функция, печать "Пользовательского отчёта"
- `setAppBarTitle` - функция, установка текста заголовка панели
- `setAppBarShow` - функция, установка флага отображения системного заголовка панели
- `findPanelByName` - функция, поиск зарегистрированной в файле конфигурации фреймвора (`p8panels.config`) панели по уникальному имени
#### `String pOnlineShowTab(Object)`
@ -853,12 +851,42 @@ const MyPanel = () => {
**Результат:** функция не возвращает значимого результата
#### `undefined setAppBarTitle(appBarTitle)`
Изменяет текст заголовка панели.
**Входные параметры:**
`appBarTitle` - необязательный, строка, текст заголовка панели (если не указан - используется заголовок панели `Panels\Panel\caption` из файла конфигурации `p8panels.config`)
**Результат:** функция не возвращает значимого результата
#### `undefined setAppBarShow(appBarShow)`
Скрывает/отображает заголовок панели.
**Входные параметры:**
`appBarShow` - обязательный, логический, флаг отображения заголовка панели (`false` - скрыть заголовок, `true` - отобразить заголовок)
**Результат:** функция не возвращает значимого результата
#### `object findPanelByName(name)`
Возвращает сведения (XML элемент `Panels\Panel` в JSON-интерпретации) о панели из файла конфигурации фреймворка (`p8panels.config`) по её уникальному наименованию (`Panels\Panel\name`).
**Входные параметры:**
`name` - обязательный, строка, уникальное имя панели (указывается в атрибуте `name` XML-элемента `Panels\Panel` файла конфигурации фреймворка `p8panels.config`)
**Результат:** функция возвращает объект, содержащий JSON-интерпретацию XML-элемента `Panel` файла конфигурации `p8panels.config`, соответствующего переданному имени панели (`undefined` - если сведения о панели не были найдены)
Примеры (см. "app/panels/samples/p8online.js"):
```
import React, { useState, useContext } from "react"; //Классы React
import { Typography, Button, Divider } from "@mui/material"; //Интерфейсные элементы
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
//Стили
const STYLES = {
@ -867,13 +895,20 @@ const STYLES = {
DIVIDER: { margin: "15px" }
};
//Пример: API для взаимодействия с "ПАРУС 8 Онлайн"
//Пример: API для взаимодействия с "ПАРУС 8 Онлайн" и ядром фреймворка
const P8Online = ({ title }) => {
//Собственное состояние
//Собственное состояние - флаг отображения пользовательского текста заголовка
const [titleCustom, setTitleCustom] = useState(false);
//Собственное состояние - отображение заголовка
const [titleVisible, setTitleVisible] = useState(true);
//Собственное состояние - выбранный контрагент
const [agent, setAgent] = useState("");
//Подключение к контексту приложения
const { pOnlineShowUnit, pOnlineShowTab, pOnlineShowDocument, pOnlineShowDictionary } = useContext(ApplicationСtx);
const { pOnlineShowUnit, pOnlineShowTab, pOnlineShowDocument, pOnlineShowDictionary, setAppBarTitle, setAppBarShow, findPanelByName } =
useContext(ApplicationCtx);
//Генерация содержимого
return (
@ -881,20 +916,44 @@ const P8Online = ({ title }) => {
<Typography sx={STYLES.TITLE} variant={"h6"}>
{title}
</Typography>
{/* Изменение текста заголовка */}
{titleVisible && (
<>
<Button
variant="contained"
onClick={() => {
setAppBarTitle(titleCustom ? "" : "Пользовательский текст");
setTitleCustom(!titleCustom);
}}
>
{`${titleCustom ? "Восстановить" : "Изменить"} текст заголовка`}
</Button>
<Divider sx={STYLES.DIVIDER} />
</>
)}
{/* Сокрытие/отображение заголовка */}
<Button
variant="contained"
onClick={() => {
setAppBarShow(!titleVisible);
setTitleVisible(!titleVisible);
}}
>
{`${titleVisible ? "Скрыть" : "Отобразить"} заголовок`}
</Button>
<Divider sx={STYLES.DIVIDER} />
{/* Поиск панели */}
<Button variant="contained" onClick={() => console.log(findPanelByName("Samples"))}>
Вывести в консоль сведения о данной панели
</Button>
<Divider sx={STYLES.DIVIDER} />
{/* Открыть новую закладку */}
<Button variant="contained" onClick={() => pOnlineShowTab({ caption: "PARUS.COM", url: "https://www.parus.com" })}>
Открыть закладку
</Button>
<Divider sx={STYLES.DIVIDER} />
{/* Открыть раздел */}
<Button
variant="contained"
onClick={() => {
pOnlineShowUnit({
unitCode: "Contracts"
});
}}
>
<Button variant="contained" onClick={() => pOnlineShowUnit({ unitCode: "Contracts" })}>
Открыть раздел Договоры
</Button>
<Divider sx={STYLES.DIVIDER} />
@ -904,12 +963,7 @@ const P8Online = ({ title }) => {
onClick={() => {
pOnlineShowDictionary({
unitCode: "AGNLIST",
inputParameters: [
{
name: "in_AGNABBR",
value: agent
}
],
inputParameters: [{ name: "in_AGNABBR", value: agent }],
callBack: res => (res.success === true ? setAgent(res.outParameters.out_AGNABBR) : null)
});
}}
@ -922,13 +976,7 @@ const P8Online = ({ title }) => {
<Divider sx={STYLES.DIVIDER} />
<Button
variant="contained"
onClick={() => {
pOnlineShowDocument({
unitCode: "AGNLIST",
document: agent,
inRnParameter: "in_AGNABBR"
});
}}
onClick={() => pOnlineShowDocument({ unitCode: "AGNLIST", document: agent, inRnParameter: "in_AGNABBR" })}
>{`Показать контрагента "${agent}"`}</Button>
</>
) : null}
@ -944,11 +992,11 @@ const P8Online = ({ title }) => {
##### Компоненты MUI
В состав фреймворка включена библиотека [MUI](https://mui.com/) версии 5. При разработке панелей могут быть использованы интерфейсные компоненты и разметка, поставляемые с ней.
В состав фреймворка включена библиотека [MUI](https://v5.mui.com/) версии 5 (далее - `MUI5`). При разработке панелей могут быть использованы интерфейсные компоненты и разметка, поставляемые с ней.
![Компоненты MUI](docs/img/61.png)
Сочетая компоненты библиотеки [MUI](https://mui.com/) и описанный выше API для взаимодействия с Системой можно реализовать пользовательский интерфейс любой сложности. Для подключения компонента к панели достаточно импортировать его из модуля `"@mui/material"`.
Сочетая компоненты библиотеки [MUI5](https://v5.mui.com/) и описанный выше API для взаимодействия с Системой можно реализовать пользовательский интерфейс любой сложности. Для подключения компонента к панели достаточно импортировать его из модуля `"@mui/material"`.
![Пример использования MUI](docs/img/62.png)
@ -957,9 +1005,9 @@ const P8Online = ({ title }) => {
```
import React, { useEffect, useContext, useCallback, useState } from "react"; //Классы React
import { Typography, Grid, List, ListItemButton, ListItem, ListItemText, IconButton, Icon, Button, TextField, Box } from "@mui/material"; //Интерфейсные элементы MUI
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { MessagingCtx } from "../../context/messaging"; //Контекст сообщений
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
//Стили
const STYLES = {
@ -977,13 +1025,13 @@ const Mui = ({ title }) => {
const [agentForm, setAgentForm] = useState({ agnAbbr: "", agnName: "" });
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Подключение к контексту сообщений
const { showMsgWarn } = useContext(MessagingСtx);
const { showMsgWarn } = useContext(MessagingCtx);
//Подключение к контексту приложения
const { pOnlineShowDocument } = useContext(ApplicationСtx);
const { pOnlineShowDocument } = useContext(ApplicationCtx);
//Загрузка списка контрагентов
const agentsGet = useCallback(async () => {
@ -1096,7 +1144,7 @@ const Mui = ({ title }) => {
```
Более подробно ознакомиться с исходным кодом примера можно в "app/panels/samples/mui.js". Документация по интерфейсным компонентам, включённым в [MUI](https://mui.com/) доступна на официальном сайте библиотеки.
Более подробно ознакомиться с исходным кодом примера можно в "app/panels/samples/mui.js". Документация по интерфейсным компонентам, включённым в [MUI5](https://v5.mui.com/) доступна на официальном сайте библиотеки.
> **Обратите внимание:** описываемые далее высокоуровневые компоненты фреймворка "Панели" построены, в том числе, с применением интерфейсных примитивов MUI. Как правило, они имеют префикс `P8P*` в имени: `P8PAppMessage`, `P8PAppInlineMessage`, `P8PAppProgress`, `P8PDataGrid` и т.д.
@ -1104,7 +1152,7 @@ const Mui = ({ title }) => {
При необходимости отображения сообщения пользователю панель может использовать компоненты `P8PAppMessage<TYPE>`, `P8PAppInlineMessage<TYPE>`, где `<TYPE> in ["Err", "Info", "Warn"]`, для сообщения об ошибке, информации или предупреждения соответственно. Их исходный код расположен в "app/components/p8p_app_message". Для подключения компонент к панели достаточно импортировать этот модуль.
Для удобства применения компонент реализованы функции-обёртки и компоненты-обёртки (декораторы), доступные через специальный контекст приложения - `MessagingСtx` ("app/context/messaging"). Их описание дано ниже.
Для удобства применения компонент реализованы функции-обёртки и компоненты-обёртки (декораторы), доступные через специальный контекст приложения - `MessagingCtx` ("app/context/messaging"). Их описание дано ниже.
![Примеры модальных сообщений](docs/img/63.png)
@ -1190,7 +1238,7 @@ const Mui = ({ title }) => {
```
import React, { useContext, useState } from "react"; //Классы React
import { Typography, Divider, Button } from "@mui/material"; //Интерфейсные элементы
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { MessagingCtx } from "../../context/messaging"; //Контекст сообщений
//Стили
const STYLES = {
@ -1205,7 +1253,7 @@ const Messages = ({ title }) => {
const [state, setState] = useState({ inlineErr: true, inlineWarn: true, inlineInfo: true });
//Подключение к контексту сообщений
const { showMsgErr, showMsgWarn, showMsgInfo, InlineMsgErr, InlineMsgInfo, InlineMsgWarn } = useContext(MessagingСtx);
const { showMsgErr, showMsgWarn, showMsgInfo, InlineMsgErr, InlineMsgInfo, InlineMsgWarn } = useContext(MessagingCtx);
//Генерация содержимого
return (
@ -1278,7 +1326,7 @@ const Messages = ({ title }) => {
Для информирования пользователя о выполнении панелью асинхронных действий (например, обращений к серверу Системы), как правило, используются различные индикаторы выполнения процессов. Для этих целей в фреймворк "Панели" включен типовой индикатор процесса `P8PAppProgress` (исходный код компонента доступен в "app/components/p8p_app_progress").
Для удобства использования компонента в контексте приложения `MessagingСtx` ("app/context/messaging") реализованы декораторы `showLoader` и `hideLoader` (отображение и сокрытие индикатора процесса соответственно).
Для удобства использования компонента в контексте приложения `MessagingCtx` ("app/context/messaging") реализованы декораторы `showLoader` и `hideLoader` (отображение и сокрытие индикатора процесса соответственно).
![Пример индикатора процесса](docs/img/65.png)
@ -1305,7 +1353,7 @@ const Messages = ({ title }) => {
```
import React, { useContext } from "react"; //Классы React
import { Typography, Button } from "@mui/material"; //Интерфейсные элементы
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { MessagingCtx } from "../../context/messaging"; //Контекст сообщений
//Стили
const STYLES = {
@ -1316,7 +1364,7 @@ const STYLES = {
//Функциональный компонент с примером использования индикатора процесса
const Loader = ({ title }) => {
//Подключение к контексту сообщений
const { showLoader, hideLoader } = useContext(MessagingСtx);
const { showLoader, hideLoader } = useContext(MessagingCtx);
//Генерация содержимого
return (
@ -1346,8 +1394,8 @@ const Loader = ({ title }) => {
В отличие от рассмотренных выше, компоненты данного класса предназначены для решения специфических прикладных задач и, как правило:
- состоят из значительного числа интерфейсных примитивов
- имеют специальный API на стороне сервера БД Системы для управления их содержимым
- состоят из значительного числа интерфейсных примитивов
- имеют специальный API на стороне сервера БД Системы для управления их содержимым
Необходимо понимать, что с одной стороны, наличие серверного API в БД значительно упрощает взаимодействие с компонентом, с другой стороны - ограничивает возможности его применения только теми прикладными задачами и функциональными возможностями, которые заложены в него. При этом "примитивы" HTML и MUI, хоть и сложнее в применении, но позволяют "собирать" практически любые интерфейсные решения на вкус разработчика.
@ -1355,13 +1403,13 @@ const Loader = ({ title }) => {
Предназначена для формирования табличных представлений данных с поддержкой:
- постраничного вывода данных
- сортировки и отбора данных по колонкам на стороне сервера БД
- сложных заголовков с возможностью отображения/сокрытия уровней
- разворачивающихся строк (accordion)
- группировки строк с возможностью отображения/сокрытия содержимого группы
- фиксации заголовка
- фиксацией колонок слева
- постраничного вывода данных
- сортировки и отбора данных по колонкам на стороне сервера БД
- сложных заголовков с возможностью отображения/сокрытия уровней
- разворачивающихся строк (accordion)
- группировки строк с возможностью отображения/сокрытия содержимого группы
- фиксации заголовка
- фиксацией колонок слева
![Пример P8PDataGrid](docs/img/66.png)
@ -1478,25 +1526,28 @@ const MyPanel = () => {
`stored` - обязательный, строка, имя исполняемого хранимого объекта (для пакетных - "ПАКЕТ.ОБЪЕКТ")\
`respArg` - необязательный, строка, имя выходного параметра исполняемого объекта, значение которого необходимо вернуть как данные ответа, по умолчанию - `COUT`\
`contentNodeName` - необязательный, строка, имя узла, содержащего информацию о таблице, по умолчанию `XDATA_GRID`\
`filtersNodeName` - необязательный, строка, имя узла, содержащего информацию о фильтрах, отправляемых на сервер, по умолчанию `filters`. При использовании в хранимом объекте стандартной функции `PKG_P8PANELS_VISUAL.TDG_FILTERS_FROM_XML` для десериализации данных важно, чтобы данный параметр имел значение `filters`\
`ordersNodeName` - необязательный, строка, имя узла, содержащего информацию о сортировках, отправляемых на сервер, по умолчанию `orders`. При использовании в хранимом объекте стандартной функции `PKG_P8PANELS_VISUAL.TDG_ORDERS_FROM_XML` для десериализации данных важно, чтобы данный параметр имел значение `orders`\
`pageSize` - необязательный, число, объем выборки данных на страницу или на догрузку, по умолчанию `10`. Передается в параметр `NPAGE_SIZE` хранимого объекта из переданного свойства `stored`\
`reloadDef` - необязательный, булево, определяет необходимость включения описания колонок таблицы в ответ, по умолчанию `false`. Передается в параметр `NINCLUDE_DEF` хранимого объекта из переданного свойства `stored`. При значении `true` соответствующий параметр `NINCLUDE_DEF` будет всегда равен `1`, в ином случае при первом обращении к хранимому объекту передается `1`, а в последующих `0`\
`filtersNodeName` - необязательный, строка, имя узла, содержащего информацию о фильтрах, отправляемых на сервер, по умолчанию `filters`, при использовании в хранимом объекте стандартной функции `PKG_P8PANELS_VISUAL.TDG_FILTERS_FROM_XML` для десериализации данных важно, чтобы данный параметр имел значение `filters`\
`ordersNodeName` - необязательный, строка, имя узла, содержащего информацию о сортировках, отправляемых на сервер, по умолчанию `orders`, при использовании в хранимом объекте стандартной функции `PKG_P8PANELS_VISUAL.TDG_ORDERS_FROM_XML` для десериализации данных важно, чтобы данный параметр имел значение `orders`\
`pageSize` - необязательный, число, объем выборки данных на страницу или на догрузку, по умолчанию `10`, передается в параметр `NPAGE_SIZE` хранимого объекта из переданного свойства `stored`\
`reloadDef` - необязательный, логический, определяет необходимость включения описания колонок таблицы в ответ, по умолчанию `false`, передается в параметр `NINCLUDE_DEF` хранимого объекта из переданного свойства `stored`, при значении `true` соответствующий параметр `NINCLUDE_DEF` будет всегда равен `1`, в ином случае при первом обращении к хранимому объекту передается `1`, а в последующих `0`\
`initFilters` - необязательный, массив, начальное состояние фильтров таблицы, содержит объекты вида `{name: <НАИМЕНОВАНИЕ_КОЛОНКИ>, from: <НАЧАЛО_ДИАПАЗОНА_ЗНАЧЕНИЙ_ФИЛЬТРА>, to: <ОКОНЧАНИЕ_ДИАПАЗОНА_ЗНАЧЕНИЙ_ФИЛЬТРА>}`\
`initOrders` - необязательный, массив, начальное состояние сортировок таблицы, содержит объекты вида `{name: <НАИМЕНОВАНИЕ_КОЛОНКИ>, direction: <ASC|DESC>}`\
`storedArgs` - необязательный, объект, описание параметров исполняемого хранимого объекта вида `{"ПАРАМЕТР": "ЗНАЧЕНИЕ"|{VALUE: "ЗНАЧЕНИЕ", SDATA_TYPE: SERV_DATA_TYPE_*}}` (если тип данных параметров не указан явно - произойдёт попытка их автоматического определения, с CLOB-параметрами это не всегда может произойти корректно)\
`storedArgs` - необязательный, объект, описание параметров исполняемого хранимого объекта вида `{"ПАРАМЕТР": "ЗНАЧЕНИЕ"|{VALUE: "ЗНАЧЕНИЕ", SDATA_TYPE: SERV_DATA_TYPE_*}}` (если тип данных параметров не указан явно - произойдёт попытка их автоматического определения, для CLOB-параметров явное указание типа обязательно)\
`resetPageNumberOnStoredArgsChange` - необязательный, логический, по умолчанию - `true`, признак сброса номера страницы при изменении значений параметров хранимого объекта\
`executeStoredArgs` - необязательный, объект, описание параметров функции `executeStored` (исполняющей хранимый объект) вида `{"ПАРАМЕТР": "ЗНАЧЕНИЕ"}`\
`allowDataLoad` - необязательный, функция, определяет игнорирование исполнения хранимой процедуры. Должна возвращать булево. Если возвращает `false`, то исполнение хранимой процедуры, независимо от необходимости, полностью игнорируется
`resetPageNumberOnExecuteStoredArgsChange` - необязательный, логический, по умолчанию - `true`, признак сброса номера страницы при изменении значений параметров параметров функции `executeStored` (исполняющей хранимый объект)\
`allowDataLoad` - необязательный, функция, определяет игнорирование исполнения хранимой процедуры, должна возвращать логическое значение (`false` - исполнение хранимой процедуры, независимо от необходимости, полностью игнорируется)
**Результат:** объект для работы с компонентом `P8PDataGrid`. Возвращаемый объект имеет следующие свойства:\
`dataGrid` - объект, хранит информацию о таблице, загруженной с помощью хранимой процедуры\
`isDataLoaded` - булево, признак успешной загрузки и обработки данных из хранимой процедуры\
`isLoading` - булево, признак выполнения загрузки данных из хранимой процедуры\
`isDataLoaded` - логический, признак успешной загрузки и обработки данных из хранимой процедуры\
`isDataFound` - логический, признак наличия значимых сведений (бизнес-даных) в данных, полученных из хранимой процедуры\
`isLoading` - логический, признак выполнения загрузки данных из хранимой процедуры\
`handleFilterChanged` - функция, изменение состояния фильтров таблицы. Сигнатура функции `f({filters})`, результат функции не интерпретируется\
`handleOrderChanged` - функция, изменение состояния сортировок таблицы. Сигнатура функции `f({orders})`, результат функции не интерпретируется\
`handlePagesCountChanged` - функция, изменение количества отображаемых страниц данных таблицы. Сигнатура функции `f()`, результат функции не интерпретируется\
`handlePageChange` - функция, изменение номера отображаемой страницы таблицы. Сигнатура функции `f({page})`, результат функции не интерпретируется\
`doReload` - функция, принудительное обновление данных таблицы. Сигнатура функции `f()`, результат функции не интерпретируется
`doReload` - функция, принудительное обновление данных таблицы, сигнатура функции `f()`, результат функции не интерпретируется
**Особенности хранимых объектов**\
При использовании универсального хука для хранимой процедуры существуют параметры "по умолчанию", в которые отправляются соответствующие данные:\
@ -1721,8 +1772,8 @@ import { Typography, Grid, Stack, Icon, Box, Button } from "@mui/material"; //И
import { object2Base64XML } from "../../core/utils"; //Вспомогательные процедуры и функции
import { P8PDataGrid, P8P_DATA_GRID_SIZE } from "../../components/p8p_data_grid"; //Таблица данных
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
//Размер страницы данных
const DATA_GRID_PAGE_SIZE = 5;
@ -1793,10 +1844,10 @@ const DataGrid = ({ title }) => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//Подключение к контексту приложения
const { pOnlineShowDocument } = useContext(ApplicationСtx);
const { pOnlineShowDocument } = useContext(ApplicationCtx);
//Загрузка данных таблицы с сервера
const loadData = useCallback(async () => {
@ -1913,7 +1964,7 @@ const MyPanel = () => {
`options` - необязательный, объект, дополнительные параметры графика, формат и допустимый состав атрибутов определены в документации к библиотеке [ChartJS](https://www.chartjs.org/docs/latest/), будет объединён с параметрами графика уже зафиксированными в компоненте `P8PChart` (см. `useEffect` при подключении компонента к старице в его исходном коде, параметры графика, зафиксированные в компоненте, имеют более высокий приоритет по сравнению с данным свойством)
`labels` - необязательный, массив строк, список меток для значений графика\
`datasets` - необязательный, массив объектов, данные для отображения на диаграмме, каждый элемент массива - серия данных для отображения, содержит объекты вида `{label: <ЗАГОЛОВОК_СЕРИИ>, borderColor: <ЦВЕТРАНИЦЫ_СЕРИИ_НАРАФИКЕ>, backgroundColor: <ЦВЕТ_ЗАЛИВКИ_СЕРИИ_НАРАФИКЕ>, data: <МАССИВ_ЗНАЧЕНИЙ_СЕРИИ_ДАННЫХ>, items: <МАССИВ_ОБЪЕКТОВРОИЗВОЛЬНОЙ_СТРУКТУРЫ_ДЛЯ_ОПИСАНИЯ_СЕРИИ_ДАННЫХ>}`\
`onClick` - необязательный, функция, будет вызвана при нажатии на элемент графика, сигнатура функции `f({datasetIndex, itemIndex, item})`, результат функции не интерпретируется. Функции будет передан объект, поле `datasetIndex` которого, будет содержать индекс серии данных, `itemIndex` - индекс элемента серии данных, а `item` - описание элмента данных серии, на котором было зафиксировано нажатие.\
`onClick` - необязательный, функция, будет вызвана при нажатии на элемент графика, сигнатура функции `f({datasetIndex, itemIndex, item})`, результат функции не интерпретируется. Функции будет передан объект, поле `datasetIndex` которого, будет содержать индекс серии данных, `itemIndex` - индекс элемента серии данных, а `item` - описание элмента данных серии, на котором было зафиксировано нажатие\
`style` - необязательный, объект, стили, которые будут применены к контейнеру `div` графика
**API на сервере БД**
@ -1948,15 +1999,16 @@ const MyPanel = () => {
`stored` - обязательный, строка, имя исполняемого хранимого объекта (для пакетных - "ПАКЕТ.ОБЪЕКТ")\
`respArg` - необязательный, строка, имя выходного параметра исполняемого объекта, значение которого необходимо вернуть как данные ответа, по умолчанию - `COUT`\
`contentNodeName` - необязательный, строка, имя узла, содержащего информацию о графике, по умолчанию `XCHART`\
`storedArgs` - необязательный, объект, описание параметров исполняемого хранимого объекта вида `{"ПАРАМЕТР": "ЗНАЧЕНИЕ"|{VALUE: "ЗНАЧЕНИЕ", SDATA_TYPE: SERV_DATA_TYPE_*}}` (если тип данных параметров не указан явно - произойдёт попытка их автоматического определения, с CLOB-параметрами это не всегда может произойти корректно)\
`storedArgs` - необязательный, объект, описание параметров исполняемого хранимого объекта вида `{"ПАРАМЕТР": "ЗНАЧЕНИЕ"|{VALUE: "ЗНАЧЕНИЕ", SDATA_TYPE: SERV_DATA_TYPE_*}}` (если тип данных параметров не указан явно - произойдёт попытка их автоматического определения, для CLOB-параметров явное указание типа обязательно)\
`executeStoredArgs` - необязательный, объект, описание параметров функции `executeStored` (исполняющей хранимый объект) вида `{"ПАРАМЕТР": "ЗНАЧЕНИЕ"}`\
`allowDataLoad` - необязательный, функция, определяет игнорирование исполнения хранимой процедуры. Должна возвращать булево. Если возвращает `false`, то исполнение хранимой процедуры, независимо от необходимости, полностью игнорируется
`allowDataLoad` - необязательный, функция, определяет игнорирование исполнения хранимой процедуры, должна возвращать логическое значение (`false` - исполнение хранимой процедуры, независимо от необходимости, полностью игнорируется)
**Результат:** объект для работы с компонентом `P8PChart`. Возвращаемый объект имеет следующие свойства:\
`chart` - объект, хранит информацию о графике, загруженном с помощью хранимой процедуры\
`isDataLoaded` - булево, признак успешной загрузки и обработки данных из хранимой процедуры\
`isLoading` - булево, признак выполнения загрузки данных из хранимой процедуры\
`doReload` - функция, принудительное обновление данных графика. Сигнатура функции `f()`, результат функции не интерпретируется
`isDataLoaded` - логический, признак успешной загрузки и обработки данных из хранимой процедуры\
`isDataFound` - логический, признак наличия значимых сведений (бизнес-даных) в данных, полученных из хранимой процедуры\
`isLoading` - логический, признак выполнения загрузки данных из хранимой процедуры\
`doReload` - функция, принудительное обновление данных графика, сигнатура функции `f()`, результат функции не интерпретируется
**Пример**
@ -2019,7 +2071,7 @@ import React, { useContext } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Typography, Grid, Paper } from "@mui/material"; //Интерфейсные элементы
import { P8PChart, useP8PChart } from "../../components/p8p_chart"; //График
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
//---------
//Константы
@ -2043,7 +2095,7 @@ const Chart = ({ title }) => {
const { chart, isDataLoaded } = useP8PChart({ stored: "PKG_P8PANELS_SAMPLES.CHART" });
//Подключение к контексту приложения
const { pOnlineShowUnit } = useContext(ApplicationСtx);
const { pOnlineShowUnit } = useContext(ApplicationCtx);
//Отработка нажатия на график
const handleChartClick = ({ item }) => {
@ -2077,14 +2129,14 @@ const Chart = ({ title }) => {
Компонент предназначен для отображения данных в виде диаграммы Ганта. Основан на библиотеке [Frappe-Gantt](https://frappe.io/gantt). Поддерживается:
- Редактирование сроков задачи перетаскиванием
- Отображение и редактирование прогресса задачи
- Установка признаков "только для чтения" для всей диаграммы и отдельной задачи (для сроков и прогресса задачи - независимо)
- Форматирование цвета заливки и текста задачи
- Дополнение задачи произвольными учётными атрибутами
- Диалоговый редактор задачи, отображающий её дополнительные атрибуты с возможностью настройки их форматирования
- Отображение связей между задачами
- Отображение произвольного пользовательского диалога в качестве карточки задачи/редактора задачи
- Редактирование сроков задачи перетаскиванием
- Отображение и редактирование прогресса задачи
- Установка признаков "только для чтения" для всей диаграммы и отдельной задачи (для сроков и прогресса задачи - независимо)
- Форматирование цвета заливки и текста задачи
- Дополнение задачи произвольными учётными атрибутами
- Диалоговый редактор задачи, отображающий её дополнительные атрибуты с возможностью настройки их форматирования
- Отображение связей между задачами
- Отображение произвольного пользовательского диалога в качестве карточки задачи/редактора задачи
![Пример P8PGantt](docs/img/68.png)
![Пример P8PGantt (редактор)](docs/img/69.png)
@ -2183,15 +2235,16 @@ const MyPanel = () => {
`stored` - обязательный, строка, имя исполняемого хранимого объекта (для пакетных - "ПАКЕТ.ОБЪЕКТ")\
`respArg` - необязательный, строка, имя выходного параметра исполняемого объекта, значение которого необходимо вернуть как данные ответа, по умолчанию - `COUT`\
`contentNodeName` - необязательный, строка, имя узла, содержащего информацию о диаграмме Ганта, по умолчанию `XGANTT`\
`storedArgs` - необязательный, объект, описание параметров исполняемого хранимого объекта вида `{"ПАРАМЕТР": "ЗНАЧЕНИЕ"|{VALUE: "ЗНАЧЕНИЕ", SDATA_TYPE: SERV_DATA_TYPE_*}}` (если тип данных параметров не указан явно - произойдёт попытка их автоматического определения, с CLOB-параметрами это не всегда может произойти корректно)\
`storedArgs` - необязательный, объект, описание параметров исполняемого хранимого объекта вида `{"ПАРАМЕТР": "ЗНАЧЕНИЕ"|{VALUE: "ЗНАЧЕНИЕ", SDATA_TYPE: SERV_DATA_TYPE_*}}` (если тип данных параметров не указан явно - произойдёт попытка их автоматического определения, для CLOB-параметров явное указание типа обязательно)\
`executeStoredArgs` - необязательный, объект, описание параметров функции `executeStored` (исполняющей хранимый объект) вида `{"ПАРАМЕТР": "ЗНАЧЕНИЕ"}`\
`allowDataLoad` - необязательный, функция, определяет игнорирование исполнения хранимой процедуры. Должна возвращать булево. Если возвращает `false`, то исполнение хранимой процедуры, независимо от необходимости, полностью игнорируется
`allowDataLoad` - необязательный, функция, определяет игнорирование исполнения хранимой процедуры, должна возвращать логическое значение (`false` - исполнение хранимой процедуры, независимо от необходимости, полностью игнорируется)
**Результат:** объект для работы с компонентом `P8PGantt`. Возвращаемый объект имеет следующие свойства:\
`gantt` - объект, хранит информацию о диаграмме Ганта, загруженной с помощью хранимой процедуры\
`isDataLoaded` - булево, признак успешной загрузки и обработки данных из хранимой процедуры\
`isLoading` - булево, признак выполнения загрузки данных из хранимой процедуры\
`doReload` - функция, принудительное обновление данных диаграммы Ганта. Сигнатура функции `f()`, результат функции не интерпретируется
`isDataLoaded` - логический, признак успешной загрузки и обработки данных из хранимой процедуры\
`isDataFound` - логический, признак наличия значимых сведений (бизнес-даных) в данных, полученных из хранимой процедуры\
`isLoading` - логический, признак выполнения загрузки данных из хранимой процедуры\
`doReload` - функция, принудительное обновление данных диаграммы Ганта, сигнатура функции `f()`, результат функции не интерпретируется
**Пример**
@ -2269,7 +2322,7 @@ import { formatDateRF, hasValue } from "../../core/utils"; //Вспомогат
import { APP_BAR_HEIGHT } from "../../components/p8p_app_workspace"; //Заголовок страницы
import { P8PGantt, useP8PGantt } from "../../components/p8p_gantt"; //Диаграмма Ганта
import { P8P_GANTT_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
//---------
//Константы
@ -2365,7 +2418,7 @@ const Gantt = ({ title }) => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Изменение данных диаграммы
const modifyData = useCallback(
@ -2434,9 +2487,9 @@ const Gantt = ({ title }) => {
Компонент предназначен для отображения изображений в формате SVG. Поддерживается:
- Режим галереи с зацикленным переключением между несколькими переданными компоненту изображениями
- Обработка событий `onClick` для изображения в целом и `onItemClick` для отдельных замкнутых контуров и групп, имеющих атрибут `id`
- Управление цветом и прозрачностью заливки отдельных замкнутых контуров и их групп
- Режим галереи с зацикленным переключением между несколькими переданными компоненту изображениями
- Обработка событий `onClick` для изображения в целом и `onItemClick` для отдельных замкнутых контуров и групп, имеющих атрибут `id`
- Управление цветом и прозрачностью заливки отдельных замкнутых контуров и их групп
![Пример P8PSVG](docs/img/71.png)
@ -2577,12 +2630,12 @@ const Svg = ({ title }) => {
Компонент предназначен для отображения данных в виде циклограммы. Поддерживается:
- Группировка задач с отображением описания группы при наведении
- Форматирование цвета заливки задачи, текста задачи и цвета при наведении на задачу/группу
- Дополнение задачи произвольными учётными атрибутами
- Диалоговый редактор задачи, отображающий её дополнительные атрибуты с возможностью настройки их форматирования
- Отображение произвольного пользовательского диалога в качестве карточки задачи/редактора задачи
- Масштабирование визуального представления
- Группировка задач с отображением описания группы при наведении
- Форматирование цвета заливки задачи, текста задачи и цвета при наведении на задачу/группу
- Дополнение задачи произвольными учётными атрибутами
- Диалоговый редактор задачи, отображающий её дополнительные атрибуты с возможностью настройки их форматирования
- Отображение произвольного пользовательского диалога в качестве карточки задачи/редактора задачи
- Масштабирование визуального представления
![Пример P8PCyclogram](docs/img/72.png)
![Пример P8PCyclogram](docs/img/73.png)
@ -2676,13 +2729,14 @@ const MyPanel = () => {
`contentNodeName` - необязательный, строка, имя узла, содержащего информацию о циклограмме, по умолчанию `XCYCLOGRAM`\
`storedArgs` - необязательный, объект, описание параметров исполняемого хранимого объекта вида `{"ПАРАМЕТР": "ЗНАЧЕНИЕ"|{VALUE: "ЗНАЧЕНИЕ", SDATA_TYPE: SERV_DATA_TYPE_*}}` (если тип данных параметров не указан явно - произойдёт попытка их автоматического определения, с CLOB-параметрами это не всегда может произойти корректно)\
`executeStoredArgs` - необязательный, объект, описание параметров функции `executeStored` (исполняющей хранимый объект) вида `{"ПАРАМЕТР": "ЗНАЧЕНИЕ"}`\
`allowDataLoad` - необязательный, функция, определяет игнорирование исполнения хранимой процедуры. Должна возвращать булево. Если возвращает `false`, то исполнение хранимой процедуры, независимо от необходимости, полностью игнорируется
`allowDataLoad` - необязательный, функция, определяет игнорирование исполнения хранимой процедуры, должна возвращать логическое значение (`false` - исполнение хранимой процедуры, независимо от необходимости, полностью игнорируется)
**Результат:** объект для работы с компонентом `P8PCyclogram`. Возвращаемый объект имеет следующие свойства:\
`cyclogram` - объект, хранит информацию о циклограмме, загруженной с помощью хранимой процедуры\
`isDataLoaded` - булево, признак успешной загрузки и обработки данных из хранимой процедуры\
`isLoading` - булево, признак выполнения загрузки данных из хранимой процедуры\
`doReload` - функция, принудительное обновление данных циклограммы. Сигнатура функции `f()`, результат функции не интерпретируется
`isDataLoaded` - логический, признак успешной загрузки и обработки данных из хранимой процедуры\
`isDataFound` - логический, признак наличия значимых сведений (бизнес-даных) в данных, полученных из хранимой процедуры\
`isLoading` - логический, признак выполнения загрузки данных из хранимой процедуры\
`doReload` - функция, принудительное обновление данных циклограммы, сигнатура функции `f()`, результат функции не интерпретируется
**Пример**
@ -2936,7 +2990,7 @@ import { formatDateJSONDateOnly, formatDateRF } from "../../core/utils"; //Вс
import { APP_BAR_HEIGHT } from "../../components/p8p_app_workspace"; //Заголовок страницы
import { P8PCyclogram } from "../../components/p8p_cyclogram"; //Циклограмма
import { P8P_CYCLOGRAM_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
//---------
//Константы
@ -3022,7 +3076,7 @@ const Cyclogram = ({ title }) => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//При подключении компонента к странице
useEffect(() => {
@ -3081,12 +3135,12 @@ export { Cyclogram };
Компонент предназначен для отображения данных в виде индикатора. Поддерживается:
- Цветовая индикация предопределёнными цветами в зависимости от состояния (не определено, позитивное, негативное, пограничное)
- Цветовая индикация пользовательскими цветами
- Обработка нажатий
- Отображение иконки
- Упрвление внешним видом (парение, рамка)
- Интерактивные подсказки
- Цветовая индикация предопределёнными цветами в зависимости от состояния (не определено, позитивное, негативное, пограничное)
- Цветовая индикация пользовательскими цветами
- Обработка нажатий
- Отображение иконки
- Управление внешним видом (парение, рамка)
- Интерактивные подсказки
![Пример P8PIndicator](docs/img/74.png)
@ -3147,15 +3201,16 @@ const MyPanel = () => {
`stored` - обязательный, строка, имя исполняемого хранимого объекта (для пакетных - "ПАКЕТ.ОБЪЕКТ")\
`respArg` - необязательный, строка, имя выходного параметра исполняемого объекта, значение которого необходимо вернуть как данные ответа, по умолчанию - `COUT`\
`contentNodeName` - необязательный, строка, имя узла, содержащего информацию об индикаторе, по умолчанию `XINDICATOR`\
`storedArgs` - необязательный, объект, описание параметров исполняемого хранимого объекта вида `{"ПАРАМЕТР": "ЗНАЧЕНИЕ"|{VALUE: "ЗНАЧЕНИЕ", SDATA_TYPE: SERV_DATA_TYPE_*}}` (если тип данных параметров не указан явно - произойдёт попытка их автоматического определения, с CLOB-параметрами это не всегда может произойти корректно)\
`storedArgs` - необязательный, объект, описание параметров исполняемого хранимого объекта вида `{"ПАРАМЕТР": "ЗНАЧЕНИЕ"|{VALUE: "ЗНАЧЕНИЕ", SDATA_TYPE: SERV_DATA_TYPE_*}}` (если тип данных параметров не указан явно - произойдёт попытка их автоматического определения, для CLOB-параметров явное указание типа обязательно)\
`executeStoredArgs` - необязательный, объект, описание параметров функции `executeStored` (исполняющей хранимый объект) вида `{"ПАРАМЕТР": "ЗНАЧЕНИЕ"}`\
`allowDataLoad` - необязательный, функция, определяет игнорирование исполнения хранимой процедуры. Должна возвращать булево. Если возвращает `false`, то исполнение хранимой процедуры, независимо от необходимости, полностью игнорируется
`allowDataLoad` - необязательный, функция, определяет игнорирование исполнения хранимой процедуры, должна возвращать логическое значение (`false` - исполнение хранимой процедуры, независимо от необходимости, полностью игнорируется)
**Результат:** объект для работы с компонентом `P8PIndicator`. Возвращаемый объект имеет следующие свойства:\
`indicator` - объект, хранит информацию об индикаторе, загруженном с помощью хранимой процедуры\
`isDataLoaded` - булево, признак успешной загрузки и обработки данных из хранимой процедуры\
`isLoading` - булево, признак выполнения загрузки данных из хранимой процедуры\
`doReload` - функция, принудительное обновление данных индикатора. Сигнатура функции `f()`, результат функции не интерпретируется
`isDataLoaded` - логический, признак успешной загрузки и обработки данных из хранимой процедуры\
`isDataFound` - логический, признак наличия значимых сведений (бизнес-даных) в данных, полученных из хранимой процедуры\
`isLoading` - логический, признак выполнения загрузки данных из хранимой процедуры\
`doReload` - функция, принудительное обновление данных индикатора, сигнатура функции `f()`, результат функции не интерпретируется
**Пример**
@ -3165,9 +3220,9 @@ const MyPanel = () => {
Фреймворк позволяет реализовать любые пользовательские интерфейсы, вёрстка которых не противоречит возможностям современного HTML. Тем не менее, при разработке пользовательских интерфейсов панелей важно придерживаться предложенных ниже правил. Это позволит создавать их в едином ключе и упростит работу конечного пользователя при их освоении.
- Избегайте нестандартных реакций элементов пользовательского интерфейса на действия пользователя. Например, выпадающий список, при активации, должен отображать состав своих элементов, а не вызывать бизнес-функцию отработки документа.
- Избегайте прямого применения HTML-тэгов. В библиотеке [MUI](https://mui.com/), включенной в состав фреймворка, есть всё необходимое для сборки интерфейса.
- Старайтесь не применять `<div>` для всёрстки - для этого в [MUI](https://mui.com/) есть группа компонентов разметки ("Layout"), используйте их (`Grid`, `Box`, `Container`, `Stack`, `Paper` и пр.).
- Старайтесь не использовать, без острой необходимости, атрибуты `sx` и `style` - всё необходимое для стилизации как правило есть в типовых атрибутах компонента [MUI](https://mui.com/), изучите его документацию. Если применение собственного стиля неизбежно - старайтесь выносить стили в единое место в коде, переиспользовать их, и импортировать там, где это необходимо.
- Придерживайтесь единой цветовой гаммы при реализации всех панелей (в идеале) или, если не удаётся, панелей, отнесённых к одному прикладному участку (ПУДП, УЗСР, БУ, ПУП и т.п.).
- Изучите и применяйте `ThemeProvider` из состава инструментов стилизации библиотеки [MUI](https://mui.com/) для придания индивидуальности панелям и их компонентам.
- Избегайте нестандартных реакций элементов пользовательского интерфейса на действия пользователя. Например, выпадающий список, при активации, должен отображать состав своих элементов, а не вызывать бизнес-функцию отработки документа.
- Избегайте прямого применения HTML-тэгов. В библиотеке [MUI5](https://v5.mui.com/), включенной в состав фреймворка, есть всё необходимое для сборки интерфейса.
- Старайтесь не применять `<div>` для всёрстки - для этого в [MUI5](https://v5.mui.com/) есть группа компонентов разметки ("Layout"), используйте их (`Grid`, `Box`, `Container`, `Stack`, `Paper` и пр.).
- Старайтесь не использовать, без острой необходимости, атрибуты `sx` и `style` - всё необходимое для стилизации как правило есть в типовых атрибутах компонента [MUI5](https://v5.mui.com/), изучите его документацию. Если применение собственного стиля неизбежно - старайтесь выносить стили в единое место в коде, переиспользовать их, и импортировать там, где это необходимо.
- Придерживайтесь единой цветовой гаммы при реализации всех панелей (в идеале) или, если не удаётся, панелей, отнесённых к одному прикладному участку (ПУДП, УЗСР, БУ, ПУП и т.п.).
- Изучите и применяйте `ThemeProvider` из состава инструментов стилизации библиотеки [MUI5](https://v5.mui.com/) для придания индивидуальности панелям и их компонентам.

View File

@ -10,7 +10,7 @@
import React, { useState, useContext, useEffect } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { createHashRouter, RouterProvider, useRouteError } from "react-router-dom"; //Роутер
import { ApplicationСtx } from "./context/application"; //Контекст приложения
import { ApplicationCtx } from "./context/application"; //Контекст приложения
import { NavigationContext, NavigationCtx, getRootLocation } from "./context/navigation"; //Контекст навигации
import { P8PAppErrorPage } from "./components/p8p_app_error_page"; //Страница с ошибкой
import { P8PAppWorkspace } from "./components/p8p_app_workspace"; //Рабочее пространство панели
@ -54,7 +54,7 @@ const MainMenu = ({ panels = [] } = {}) => {
const { navigatePanel, isNavigationSearch, getNavigationSearch } = useContext(NavigationCtx);
//Подключение к контексту приложения
const { configUrlBase, pOnlineShowTab } = useContext(ApplicationСtx);
const { configUrlBase, pOnlineShowTab } = useContext(ApplicationCtx);
//Получим параметры запроса из адресной строки
const qS = isNavigationSearch() ? getNavigationSearch() : null;
@ -87,7 +87,7 @@ const Workspace = ({ panels = [], selectedPanel, children } = {}) => {
const { navigateRoot, navigatePanel } = useContext(NavigationCtx);
//Подключение к контексту приложения
const { appState } = useContext(ApplicationСtx);
const { appState } = useContext(ApplicationCtx);
//Отработка действия навигации домой
const handleHomeNavigate = () => navigateRoot();
@ -102,6 +102,7 @@ const Workspace = ({ panels = [], selectedPanel, children } = {}) => {
panels={panels}
selectedPanel={selectedPanel}
caption={appState.appBarTitle}
showAppBar={appState.appBarShow}
onHomeNavigate={handleHomeNavigate}
onItemNavigate={handleItemNavigate}
>
@ -130,7 +131,7 @@ const App = () => {
const [routes, setRoutes] = useState([]);
//Подключение к контексту приложения
const { appState } = useContext(ApplicationСtx);
const { appState } = useContext(ApplicationCtx);
//Инициализация роутера
const content = routes.length > 0 ? <RouterProvider router={createHashRouter(routes)}></RouterProvider> : null;

View File

@ -10,7 +10,7 @@
import React, { useContext } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { TextField, Box, InputAdornment, IconButton, Icon, FormControlLabel, Checkbox } from "@mui/material"; //Интерфейсные элементы
import { ApplicationСtx } from "../../../context/application"; //Контекст приложения
import { ApplicationCtx } from "../../../context/application"; //Контекст приложения
import { P8P_CA_OPEN_UNIT_PARAMS_SHAPE, P8P_CA_INPUT_PARAM_INITIAL, P8P_CA_DEF_TYPE_VALUE } from "./common"; //Общие ресурсы действий
import { P8PCAFieldWithType } from "./field_with_type"; //Поле с выбором типа значения
import { P8PCATablePropValues } from "./table_prop_values"; //Таблица значений свойств действия
@ -31,7 +31,7 @@ const STYLES = {
//Редактор действия "Открыть раздел"
const P8PCAUnitOpenOptions = ({ unit, valueTypes, isValues, onStateChange, onValueSourceMenuClick }) => {
//Подключение к контексту приложения
const { pOnlineShowDictionary } = useContext(ApplicationСtx);
const { pOnlineShowDictionary } = useContext(ApplicationCtx);
//При изменении параметра открытия
const handleModalChange = () => onStateChange({ modal: !unit.modal });

View File

@ -10,7 +10,7 @@
import React, { useState, useEffect, useContext } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Stack, IconButton, Icon, TextField, InputAdornment, MenuItem, Menu } from "@mui/material"; //Интерфейсные элементы
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
import { TITLES, CAPTIONS } from "../../../app.text"; //Общие текстовые ресурсы
import { P8PConfigDialog } from "./p8p_config_dialog"; //Типовой диалог настройки
import { P8P_DATA_SOURCE_TYPE, P8P_DATA_SOURCE_SHAPE, P8P_DATA_SOURCE_ARGUMENT_INITIAL, P8P_DATA_SOURCE_INITIAL } from "./p8p_data_source_common"; //Общие ресурсы компонента "Источник данных"
@ -43,7 +43,7 @@ const P8PDataSourceConfigDialog = ({ dataSource = null, valueProviders = {}, onO
const [disabledFields, setDisabledFields] = useState({ query: false, userProc: false });
//Подключение к контексту приложения
const { pOnlineShowDictionary } = useContext(ApplicationСtx);
const { pOnlineShowDictionary } = useContext(ApplicationCtx);
//Установка значения/привязки аргумента
const setArgumentValueSource = (index, value, valueSource) =>
@ -130,8 +130,8 @@ const P8PDataSourceConfigDialog = ({ dataSource = null, valueProviders = {}, onO
hasValue(state.query)
? setDisabledFields({ query: false, userProc: true })
: hasValue(state.userProc)
? setDisabledFields({ query: true, userProc: false })
: setDisabledFields({ query: false, userProc: false });
? setDisabledFields({ query: true, userProc: false })
: setDisabledFields({ query: false, userProc: false });
}, [state.query, state.userProc]);
//Список значений

View File

@ -11,11 +11,11 @@ import { useState, useContext, useEffect, useRef } from "react"; //Классы
import client from "../../core/client"; //Клиент взаимодействия с сервером приложений
import { ERRORS } from "../../../app.text"; //Общие текстовые ресурсы
import { formatErrorMessage } from "../../core/utils"; //Общие вспомогательные функции
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { P8P_DATA_SOURCE_TYPE, P8P_DATA_SOURCE_ARGUMENT_DATA_TYPE } from "./p8p_data_source_common"; //Общие ресурсы источника данных
import { getConditionsValues } from "./p8p_component_condition/util"; //Вспомогательные ресурсы условий
import { getHandlersByActions } from "./p8p_component_action/util"; //Вспомогательные ресурсы действий
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
//-----------
//Тело модуля
@ -30,7 +30,7 @@ const useUserProcDesc = ({ code, refresh }) => {
const [data, setData] = useState(null);
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//При необходимости обновить данные компонента
useEffect(() => {
@ -84,7 +84,7 @@ const useDataSource = ({ dataSource, values, componentRespArg = "" }) => {
const [haveData, setHaveData] = useState(false);
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//При необходимости обновление информации о наличии данных
useEffect(() => {
@ -142,8 +142,8 @@ const useDataSource = ({ dataSource, values, componentRespArg = "" }) => {
? null
: parseFloat(v)
: argument.dataType == P8P_DATA_SOURCE_ARGUMENT_DATA_TYPE.DATE
? new Date(v)
: String(v === undefined ? "" : v);
? new Date(v)
: String(v === undefined ? "" : v);
if (argument.req === true && [undefined, null, ""].includes(storedArgs[argument.name])) reqSet = false;
});
if (pv.stored != stored || pv.respArg != respArg || JSON.stringify(pv.storedArgs) != JSON.stringify(storedArgs)) {
@ -204,7 +204,7 @@ const useComponentHandlers = ({ actions = [], onValuesChange = null, getCustomTy
const [handlers, setHandlers] = useState({});
//Подключение к контексту приложения
const { configUrlBase, pOnlineShowTab, pOnlineShowUnit } = useContext(ApplicationСtx);
const { configUrlBase, pOnlineShowTab, pOnlineShowUnit } = useContext(ApplicationCtx);
//При необходимости обновления информации об обработчиках
useEffect(() => {

View File

@ -47,7 +47,17 @@ const STYLES = {
//-----------
//Рабочее пространство
const P8PAppWorkspace = ({ children, panels = [], selectedPanel, caption, closeCaption, homeCaption, onHomeNavigate, onItemNavigate } = {}) => {
const P8PAppWorkspace = ({
children,
panels = [],
selectedPanel,
caption,
showAppBar = true,
closeCaption,
homeCaption,
onHomeNavigate,
onItemNavigate
} = {}) => {
//Собственное состояния
const [open, setOpen] = useState(false);
@ -73,42 +83,46 @@ const P8PAppWorkspace = ({ children, panels = [], selectedPanel, caption, closeC
//Генерация содержимого
return (
<Box sx={STYLES.ROOT_BOX}>
<CssBaseline />
<AppBar sx={STYLES.APP_BAR}>
<Toolbar>
<IconButton
color="inherit"
aria-label="open drawer"
onClick={open ? handleDrawerClose : handleDrawerOpen}
edge="start"
sx={STYLES.APP_BAR_BUTTON}
>
<Icon>{open ? "chevron_left" : "menu"}</Icon>
</IconButton>
<Typography variant="h6" noWrap component="div">
{caption || selectedPanel?.caption}
</Typography>
</Toolbar>
</AppBar>
<Drawer anchor="left" open={open} onClose={handleDrawerClose} sx={STYLES.DRAWER}>
<List>
<ListItemButton onClick={handleDrawerClose}>
<ListItemIcon>
<Icon>close</Icon>
</ListItemIcon>
<ListItemText primary={closeCaption} />
</ListItemButton>
<ListItemButton onClick={handleHomeClick}>
<ListItemIcon>
<Icon>home</Icon>
</ListItemIcon>
<ListItemText primary={homeCaption} />
</ListItemButton>
</List>
<P8PPanelsMenuDrawer panels={panels} selectedPanel={selectedPanel} onItemNavigate={handleItemNavigate} />
</Drawer>
{showAppBar && (
<>
<CssBaseline />
<AppBar sx={STYLES.APP_BAR}>
<Toolbar>
<IconButton
color="inherit"
aria-label="open drawer"
onClick={open ? handleDrawerClose : handleDrawerOpen}
edge="start"
sx={STYLES.APP_BAR_BUTTON}
>
<Icon>{open ? "chevron_left" : "menu"}</Icon>
</IconButton>
<Typography variant="h6" noWrap component="div">
{caption || selectedPanel?.caption}
</Typography>
</Toolbar>
</AppBar>
<Drawer anchor="left" open={open} onClose={handleDrawerClose} sx={STYLES.DRAWER}>
<List>
<ListItemButton onClick={handleDrawerClose}>
<ListItemIcon>
<Icon>close</Icon>
</ListItemIcon>
<ListItemText primary={closeCaption} />
</ListItemButton>
<ListItemButton onClick={handleHomeClick}>
<ListItemIcon>
<Icon>home</Icon>
</ListItemIcon>
<ListItemText primary={homeCaption} />
</ListItemButton>
</List>
<P8PPanelsMenuDrawer panels={panels} selectedPanel={selectedPanel} onItemNavigate={handleItemNavigate} />
</Drawer>
</>
)}
<main style={STYLES.MAIN}>
<Toolbar />
{showAppBar && <Toolbar />}
{children}
</main>
</Box>
@ -121,6 +135,7 @@ P8PAppWorkspace.propTypes = {
panels: PropTypes.arrayOf(P8P_PANELS_MENU_PANEL_SHAPE).isRequired,
selectedPanel: P8P_PANELS_MENU_PANEL_SHAPE,
caption: PropTypes.string,
showAppBar: PropTypes.bool,
closeCaption: PropTypes.string.isRequired,
homeCaption: PropTypes.string.isRequired,
onHomeNavigate: PropTypes.func,

View File

@ -8,7 +8,7 @@
//---------------------
import { useState, useCallback, useEffect, useContext, useRef, useMemo } from "react"; //Классы React
import { BackEndСtx } from "../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../context/backend"; //Контекст взаимодействия с сервером
//---------
//Константы
@ -43,6 +43,9 @@ const useP8PChart = ({
//Собственное состояние - признак загрузки данных
const [isDataLoaded, setIsDataLoaded] = useState(false);
//Собственное состояние - признак наличия бизнес-данных в загруженных
const [isDataFound, setIsDataFound] = useState(false);
//Собственное состояние - флаг загрузки
const [isLoading, setLoading] = useState(false);
@ -61,13 +64,18 @@ const useP8PChart = ({
}, [allowDataLoad]);
//Подключение к контексту взаимодействия с сервером
const { executeStored, isRespErr } = useContext(BackEndСtx);
const { executeStored, isRespErr } = useContext(BackEndCtx);
//Загрузка данных графика с сервера
const loadData = useCallback(async () => {
try {
//Поднимаем флаг начала загрузки данных
setLoading(true);
//Получаем данные с сервера БД
const data = await executeStored({ stored, respArg, args: { ...refStoredArgs.current }, ...refExecuteStoredArgs.current });
//Устанавливаем флаг наличия бизнес-данных
setIsDataFound(data[contentNodeName]?.datasets?.[0]?.data?.length > 0);
//Устанавливаем бизнес-данные
setChart(pv => ({ ...pv, ...data[contentNodeName] }));
//Устанавливаем признак загрузки данных с учетом возможных ошибок
setIsDataLoaded(!isRespErr(data));
@ -126,7 +134,7 @@ const useP8PChart = ({
}, [isAllowDataLoad, reload, loadData]);
//Возвращаем данные графика
return { chart, isDataLoaded, isLoading, doReload };
return { chart, isDataLoaded, isDataFound, isLoading, doReload };
};
//----------------

View File

@ -8,7 +8,7 @@
//---------------------
import { useState, useCallback, useEffect, useContext, useRef, useMemo } from "react"; //Классы React
import { BackEndСtx } from "../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../context/backend"; //Контекст взаимодействия с сервером
import { formatDateJSONDateOnly } from "../core/utils"; //Вспомогательные функции
//---------
@ -47,6 +47,9 @@ const useP8PCyclogram = ({
//Собственное состояние - признак загрузки данных
const [isDataLoaded, setIsDataLoaded] = useState(false);
//Собственное состояние - признак наличия бизнес-данных в загруженных
const [isDataFound, setIsDataFound] = useState(false);
//Собственное состояние - флаг загрузки
const [isLoading, setLoading] = useState(false);
@ -65,12 +68,14 @@ const useP8PCyclogram = ({
}, [allowDataLoad]);
//Подключение к контексту взаимодействия с сервером
const { executeStored, isRespErr } = useContext(BackEndСtx);
const { executeStored, isRespErr } = useContext(BackEndCtx);
//Загрузка данных циклограммы с сервера
const loadData = useCallback(async () => {
try {
//Поднимаем флаг начала загрузки данных
setLoading(true);
//Получаем данные с сервера БД
const data = await executeStored({
stored,
args: { ...refStoredArgs.current },
@ -78,6 +83,9 @@ const useP8PCyclogram = ({
respArg,
...refExecuteStoredArgs.current
});
//Устанавливаем флаг наличия бизнес-данных
setIsDataFound(data[contentNodeName]?.tasks?.length > 0);
//Устанавливаем бизнес-данные
setCyclogram(pv => ({ ...pv, ...data[contentNodeName] }));
//Устанавливаем признак загрузки данных с учетом возможных ошибок
setIsDataLoaded(!isRespErr(data));
@ -135,7 +143,7 @@ const useP8PCyclogram = ({
}, [isAllowDataLoad, reload, loadData]);
//Возвращаем данные циклограммы
return { cyclogram, isDataLoaded, isLoading, doReload };
return { cyclogram, isDataLoaded, isDataFound, isLoading, doReload };
};
//----------------

View File

@ -7,16 +7,18 @@
//Подключение библиотек
//---------------------
import { useState, useCallback, useEffect, useContext, useRef, useMemo } from "react"; //Классы React
import { BackEndСtx } from "../context/backend"; //Контекст взаимодействия с сервером
import { useReducer, useCallback, useEffect, useContext, useRef, useMemo } from "react"; //Классы React
import { BackEndCtx } from "../context/backend"; //Контекст взаимодействия с сервером
import { object2Base64XML } from "../core/utils"; //Вспомогательные функции
import config from "../../app.config"; //Настройки приложения
import { DG_AT, INITIAL_STATE, dataGridReducer } from "./p8p_data_grid_reducer"; //Редьюсер состояния
//---------
//Константы
//---------
//Константы - значения по умолчанию
const DG_PAGE_SIZE_DEF = 10; //Размер страницы
const DG_PAGE_SIZE_DEF = config.SYSTEM.PAGE_SIZE; //Размер страницы
const DG_NODE_NAME_DEF = "XDATA_GRID"; //Наименование узла, содержащего информацию о таблице
const FILTERS_NODE_NAME_DEF = "filters"; //Наименование узла отборов
const ORDERS_NODE_NAME_DEF = "orders"; //Наименование узла сортировок
@ -38,38 +40,39 @@ const useP8PDataGrid = ({
initFilters = [],
initOrders = [],
storedArgs = {},
resetPageNumberOnStoredArgsChange = true,
executeStoredArgs = {},
resetPageNumberOnExecuteStoredArgsChange = true,
allowDataLoad = () => true
}) => {
//Собственное состояние - таблица данных
const [dataGrid, setDataGrid] = useState({
columnsDef: [],
groups: [],
rows: [],
filters: Array.isArray(initFilters) ? [...initFilters] : [],
orders: Array.isArray(initOrders) ? [...initOrders] : [],
pageNumber: 1,
pagesAlign: null,
pagesPosition: null,
pagesCount: 0,
fixedColumns: 0,
fixedHeader: false,
morePages: true
});
//Подключим редьюсер состояния
const [state, dispatch] = useReducer(dataGridReducer, INITIAL_STATE({ initFilters, initOrders }));
//Собственное состояние - признак загрузки данных
const [isDataLoaded, setIsDataLoaded] = useState(false);
//Установка даных таблицы
const setDataGrid = (dataGridData, pageSize, isError) => dispatch({ type: DG_AT.SET_DATA_GRID, payload: { dataGridData, pageSize, isError } });
//Собственное состояние - флаг загрузки
const [isLoading, setLoading] = useState(false);
//Установка фильтра таблицы
const setDataGridFilter = filters => dispatch({ type: DG_AT.SET_DATA_GRID_FILTER, payload: filters });
//Собственное состояние - необходимость обновления данных
const [reload, setReload] = useState(true);
//Установка сортировок таблицы
const setDataGridOrder = orders => dispatch({ type: DG_AT.SET_DATA_GRID_ORDER, payload: orders });
//Собственное состояние - дополнительные параметры процедуры
//Установка страницы таблицы
const setDataGridPageNumber = pageNumber => dispatch({ type: DG_AT.SET_DATA_GRID_PAGE_NUMBER, payload: pageNumber });
//Установка флага загруженности данных
const setIsDataLoaded = isDataLoaded => dispatch({ type: DG_AT.SET_IS_DATA_LOADED, payload: isDataLoaded });
//Установка флага активности процесса загрузки данных
const setIsLoading = isLoading => dispatch({ type: DG_AT.SET_IS_LOADING, payload: isLoading });
//Установка флага необходимости обновления данных
const setReload = (reload, resetPageNumber = false) => dispatch({ type: DG_AT.SET_RELOAD, payload: { reload, resetPageNumber } });
//Ссылка на актуальные параметры хранимой процедуры
const refStoredArgs = useRef(storedArgs);
//Собственное состояние - дополнительные параметры вызова процедуры
//Ссылка на актуальные параметры исполнения хранимой процедуры
const refExecuteStoredArgs = useRef(executeStoredArgs);
//Признак допустимости обновления данных
@ -78,57 +81,46 @@ const useP8PDataGrid = ({
}, [allowDataLoad]);
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB, isRespErr } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB, isRespErr } = useContext(BackEndCtx);
//Загрузка данных таблицы с сервера
const loadData = useCallback(async () => {
try {
setLoading(true);
//Поднимаем флаг начала загрузки данных
setIsLoading(true);
//Получаем данные с сервера БД
const data = await executeStored({
stored,
args: {
CFILTERS: { VALUE: object2Base64XML(dataGrid.filters, { arrayNodeName: filtersNodeName }), SDATA_TYPE: SERV_DATA_TYPE_CLOB },
CORDERS: { VALUE: object2Base64XML(dataGrid.orders, { arrayNodeName: ordersNodeName }), SDATA_TYPE: SERV_DATA_TYPE_CLOB },
NPAGE_NUMBER: dataGrid.pageNumber,
CFILTERS: {
VALUE: object2Base64XML(state.dataGrid.filters, { arrayNodeName: filtersNodeName }),
SDATA_TYPE: SERV_DATA_TYPE_CLOB
},
CORDERS: { VALUE: object2Base64XML(state.dataGrid.orders, { arrayNodeName: ordersNodeName }), SDATA_TYPE: SERV_DATA_TYPE_CLOB },
NPAGE_NUMBER: state.dataGrid.pageNumber,
NPAGE_SIZE: pageSize,
NINCLUDE_DEF: reloadDef ? 1 : dataGrid.dataLoaded ? 0 : 1,
NINCLUDE_DEF: reloadDef ? 1 : state.isDataLoaded ? 0 : 1,
...refStoredArgs.current
},
respArg,
...refExecuteStoredArgs.current
});
setDataGrid(pv => ({
...pv,
...data[contentNodeName],
columnsDef: data[contentNodeName].columnsDef ? [...data[contentNodeName].columnsDef] : pv.columnsDef || [],
rows:
data[contentNodeName].pagesCount > 0 || pv.pageNumber == 1
? [...(data[contentNodeName].rows || [])]
: [...(pv.rows || []), ...(data[contentNodeName].rows || [])],
groups: data[contentNodeName].groups
? data[contentNodeName].pagesCount > 0 || pv.pageNumber == 1
? [...(data[contentNodeName].groups || [])]
: [...(pv.groups || []), ...data[contentNodeName].groups.filter(g => !pv.groups.find(pg => pg.name == g.name))]
: [...(pv.groups || [])],
morePages: data[contentNodeName].morePages && (data[contentNodeName].rows || []).length >= pageSize
}));
//Устанавливаем признак загрузки данных с учетом возможных ошибок
setIsDataLoaded(!isRespErr(data));
//Устанавливаем полученные бизнес-данные, признак загрузки данных с учетом возможных ошибок, признак наличия бизнес-данных
setDataGrid(data[contentNodeName], pageSize, isRespErr(data));
} catch (e) {
//Если произошла ошибка - данные не загружены
setIsDataLoaded(false);
} finally {
//Сбрасываем признаки загрузки и перезагрузки данных
setLoading(false);
setReload(false);
setIsLoading(false);
}
}, [
SERV_DATA_TYPE_CLOB,
contentNodeName,
dataGrid.dataLoaded,
dataGrid.filters,
dataGrid.orders,
dataGrid.pageNumber,
state.isDataLoaded,
state.dataGrid.filters,
state.dataGrid.orders,
state.dataGrid.pageNumber,
executeStored,
filtersNodeName,
isRespErr,
@ -140,48 +132,30 @@ const useP8PDataGrid = ({
]);
//При изменении состояния фильтра
const handleFilterChanged = useCallback(({ filters }) => {
setDataGrid(pv => ({ ...pv, filters: [...filters], pageNumber: 1 }));
setReload(true);
}, []);
const handleFilterChanged = useCallback(({ filters }) => setDataGridFilter(filters), []);
//При изменении состояния сортировки
const handleOrderChanged = useCallback(({ orders }) => {
setDataGrid(pv => ({ ...pv, orders: [...orders], pageNumber: 1 }));
setReload(true);
}, []);
const handleOrderChanged = useCallback(({ orders }) => setDataGridOrder(orders), []);
//При изменении количества отображаемых страниц
const handlePagesCountChanged = useCallback(() => {
setDataGrid(pv => ({ ...pv, pageNumber: pv.pageNumber + 1 }));
setReload(true);
}, []);
const handlePagesCountChanged = useCallback(() => setDataGridPageNumber(state.dataGrid.pageNumber + 1), [state.dataGrid.pageNumber]);
//При изменении страницы отображения
const handlePageChange = useCallback(({ page }) => {
setDataGrid(pv => ({ ...pv, pageNumber: page }));
setReload(true);
}, []);
const handlePageChange = useCallback(({ page }) => setDataGridPageNumber(page), []);
//При необходимости обновления таблицы
const doReload = useCallback(
({ returnOnFirstPage = false }) => {
//Если это не страничный вывод или установлен признак возврата на первую страницу
if (dataGrid.pagesCount <= 0 || returnOnFirstPage) {
setDataGrid(pv => ({ ...pv, pageNumber: 1 }));
}
setReload(true);
},
[dataGrid.pagesCount]
({ returnOnFirstPage = false }) => setReload(true, state.dataGrid.pagesCount <= 0 || returnOnFirstPage),
[state.dataGrid.pagesCount]
);
//Проверка изменений параметров
const isArgsChanged = useCallback(
(currentArgs, args) => {
//Если дополнительные параметры изменились (и сейчас не происходит загрузка данных с сервера)
return !isLoading && JSON.stringify(currentArgs) != JSON.stringify(args);
return !state.isLoading && JSON.stringify(currentArgs) != JSON.stringify(args);
},
[isLoading]
[state.isLoading]
);
//При изменение дополнительных параметров процедуры
@ -191,9 +165,9 @@ const useP8PDataGrid = ({
//Устанавливаем новые дополнительные параметры
refStoredArgs.current = storedArgs;
//При изменении дополнительных параметров необходимо перезагрузить данные
setReload(true);
setReload(true, resetPageNumberOnStoredArgsChange);
}
}, [storedArgs, isArgsChanged]);
}, [storedArgs, resetPageNumberOnStoredArgsChange, isArgsChanged]);
//При изменение дополнительных параметров вызова процедуры
useEffect(() => {
@ -202,19 +176,29 @@ const useP8PDataGrid = ({
//Устанавливаем новые дополнительные параметры
refExecuteStoredArgs.current = executeStoredArgs;
//При изменении дополнительных параметров необходимо перезагрузить данные
setReload(true);
setReload(true, resetPageNumberOnExecuteStoredArgsChange);
}
}, [executeStoredArgs, isArgsChanged]);
}, [executeStoredArgs, resetPageNumberOnExecuteStoredArgsChange, isArgsChanged]);
//При необходимости обновить данные таблицы
useEffect(() => {
if (isAllowDataLoad && reload) {
if (isAllowDataLoad && state.reload) {
loadData();
}
}, [isAllowDataLoad, reload, loadData]);
}, [isAllowDataLoad, state.reload, loadData]);
//Возвращаем данные таблицы
return { dataGrid, isDataLoaded, isLoading, handleFilterChanged, handleOrderChanged, handlePagesCountChanged, handlePageChange, doReload };
return {
dataGrid: state.dataGrid,
isDataLoaded: state.isDataLoaded,
isDataFound: state.isDataFound,
isLoading: state.isLoading,
handleFilterChanged,
handleOrderChanged,
handlePagesCountChanged,
handlePageChange,
doReload
};
};
//----------------

View File

@ -0,0 +1,116 @@
/*
Парус 8 - Панели мониторинга
Таблица данных - редьюсер состояния
*/
//---------
//Константы
//---------
//Типы действий
const DG_AT = {
SET_DATA_GRID: "SET_DATA_GRID", //Установка даных таблицы
SET_DATA_GRID_FILTER: "SET_DATA_GRID_FILTER", //Установка фильтра таблицы
SET_DATA_GRID_ORDER: "SET_DATA_GRID_ORDER", //Установка сортировок таблицы
SET_DATA_GRID_PAGE_NUMBER: "SET_DATA_GRID_PAGE_NUMBER", //Установка страницы таблицы
SET_IS_DATA_LOADED: "SET_IS_DATA_LOADED", //Установка флага загруженности данных
SET_IS_LOADING: "SET_IS_LOADING", //Установка флага активности процесса загрузки данных
SET_RELOAD: "SET_RELOAD" //Установка флага необходимости обновления данных
};
//Состояние приложения по умолчанию
const INITIAL_STATE = ({ initFilters, initOrders }) => ({
dataGrid: {
columnsDef: [],
groups: [],
rows: [],
filters: Array.isArray(initFilters) ? [...initFilters] : [],
orders: Array.isArray(initOrders) ? [...initOrders] : [],
pageNumber: 1,
pagesAlign: null,
pagesPosition: null,
pagesCount: 0,
fixedColumns: 0,
fixedHeader: false,
morePages: false
},
isDataLoaded: false,
isDataFound: false,
isLoading: false,
reload: true
});
//-----------
//Тело модуля
//-----------
//Обработчики действий
const handlers = {
//Установка даных таблицы
[DG_AT.SET_DATA_GRID]: (state, { payload }) => {
const { dataGridData, pageSize, isError } = payload;
return {
...state,
dataGrid: {
...state.dataGrid,
...dataGridData,
columnsDef: dataGridData.columnsDef ? [...dataGridData.columnsDef] : state.dataGrid.columnsDef || [],
rows:
dataGridData.pagesCount > 0 || state.dataGrid.pageNumber == 1
? [...(dataGridData.rows || [])]
: [...(state.dataGrid.rows || []), ...(dataGridData.rows || [])],
groups: dataGridData.groups
? dataGridData.pagesCount > 0 || state.dataGrid.pageNumber == 1
? [...(dataGridData.groups || [])]
: [...(state.dataGrid.groups || []), ...dataGridData.groups.filter(g => !state.dataGrid.groups.find(pg => pg.name == g.name))]
: [...(state.dataGrid.groups || [])],
morePages: dataGridData.morePages && (dataGridData.rows || []).length >= pageSize
},
isDataLoaded: isError === true ? false : true,
isDataFound:
(state.dataGrid.pageNumber == 1 && dataGridData?.rows?.length > 0) ||
(state.dataGrid.pageNumber != 1 && state.dataGrid.rows.length > 0)
};
},
//Установка фильтра таблицы
[DG_AT.SET_DATA_GRID_FILTER]: (state, { payload }) => ({
...state,
dataGrid: { ...state.dataGrid, filters: [...payload], pageNumber: 1 },
reload: true
}),
//Установка сортировок таблицы
[DG_AT.SET_DATA_GRID_ORDER]: (state, { payload }) => ({
...state,
dataGrid: { ...state.dataGrid, orders: [...payload], pageNumber: 1 },
reload: true
}),
//Установка страницы таблицы
[DG_AT.SET_DATA_GRID_PAGE_NUMBER]: (state, { payload }) => ({ ...state, dataGrid: { ...state.dataGrid, pageNumber: payload }, reload: true }),
//Установка флага загруженности данных
[DG_AT.SET_IS_DATA_LOADED]: (state, { payload }) => ({ ...state, isDataLoaded: payload }),
//Установка флага активности процесса загрузки данных
[DG_AT.SET_IS_LOADING]: (state, { payload }) => ({ ...state, isLoading: payload, reload: payload === false ? false : state.reload }),
//Установка флага необходимости обновления данных
[DG_AT.SET_RELOAD]: (state, { payload }) => ({
...state,
reload: payload.reload,
...(payload.resetPageNumber ? { dataGrid: { ...state.dataGrid, pageNumber: 1 } } : {})
}),
//Обработчик по умолчанию
DEFAULT: state => state
};
//----------------
//Интерфейс модуля
//----------------
//Константы
export { DG_AT, INITIAL_STATE };
//Редьюсер состояния
export const dataGridReducer = (state, action) => {
//Подберём обработчик
const handle = handlers[action.type] || handlers.DEFAULT;
//Исполним его
return handle(state, action);
};

View File

@ -8,7 +8,7 @@
//---------------------
import { useState, useCallback, useEffect, useContext, useRef, useMemo } from "react"; //Классы React
import { BackEndСtx } from "../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../context/backend"; //Контекст взаимодействия с сервером
import { formatDateJSONDateOnly } from "../core/utils"; //Вспомогательные функции
//---------
@ -48,6 +48,9 @@ const useP8PGantt = ({
//Собственное состояние - признак загрузки данных
const [isDataLoaded, setIsDataLoaded] = useState(false);
//Собственное состояние - признак наличия бизнес-данных в загруженных
const [isDataFound, setIsDataFound] = useState(false);
//Собственное состояние - флаг загрузки
const [isLoading, setLoading] = useState(false);
@ -66,12 +69,14 @@ const useP8PGantt = ({
}, [allowDataLoad]);
//Подключение к контексту взаимодействия с сервером
const { executeStored, isRespErr } = useContext(BackEndСtx);
const { executeStored, isRespErr } = useContext(BackEndCtx);
//Загрузка данных диаграммы ганта с сервера
const loadData = useCallback(async () => {
try {
//Поднимаем флаг начала загрузки данных
setLoading(true);
//Получаем данные с сервера БД
const data = await executeStored({
stored,
args: { ...refStoredArgs.current },
@ -80,6 +85,9 @@ const useP8PGantt = ({
respArg,
...refExecuteStoredArgs.current
});
//Устанавливаем флаг наличия бизнес-данных
setIsDataFound(data[contentNodeName]?.tasks?.length > 0);
//Устанавливаем бизнес-данные
setGantt(pv => ({ ...pv, ...data[contentNodeName] }));
//Устанавливаем признак загрузки данных с учетом возможных ошибок
setIsDataLoaded(!isRespErr(data));
@ -138,7 +146,7 @@ const useP8PGantt = ({
}, [isAllowDataLoad, reload, loadData]);
//Возвращаем данные диаграммы ганта
return { gantt, isDataLoaded, isLoading, doReload };
return { gantt, isDataLoaded, isDataFound, isLoading, doReload };
};
//----------------

View File

@ -8,7 +8,7 @@
//---------------------
import { useState, useCallback, useEffect, useContext, useRef, useMemo } from "react"; //Классы React
import { BackEndСtx } from "../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../context/backend"; //Контекст взаимодействия с сервером
import { P8P_INDICATOR_STATE, P8P_INDICATOR_VARIANT } from "./p8p_indicator";
//---------
@ -50,6 +50,9 @@ const useP8PIndicator = ({
//Собственное состояние - признак загрузки данных
const [isDataLoaded, setIsDataLoaded] = useState(false);
//Собственное состояние - признак наличия бизнес-данных в загруженных
const [isDataFound, setIsDataFound] = useState(false);
//Собственное состояние - флаг загрузки
const [isLoading, setLoading] = useState(false);
@ -68,13 +71,18 @@ const useP8PIndicator = ({
}, [allowDataLoad]);
//Подключение к контексту взаимодействия с сервером
const { executeStored, isRespErr } = useContext(BackEndСtx);
const { executeStored, isRespErr } = useContext(BackEndCtx);
//Загрузка данных индикатора с сервера
const loadData = useCallback(async () => {
try {
//Поднимаем флаг начала загрузки данных
setLoading(true);
//Получаем данные с сервера БД
const data = await executeStored({ stored, respArg, args: { ...refStoredArgs.current }, ...refExecuteStoredArgs.current });
//Устанавливаем флаг наличия бизнес-данных
setIsDataFound(data[contentNodeName]?.caption && data[contentNodeName]?.value != undefined);
//Устанавливаем бизнес-данные
setIndicator(pv => ({ ...pv, ...data[contentNodeName] }));
//Устанавливаем признак загрузки данных с учетом возможных ошибок
setIsDataLoaded(!isRespErr(data));
@ -133,7 +141,7 @@ const useP8PIndicator = ({
}, [isAllowDataLoad, reload, loadData]);
//Возвращаем данные индикатора
return { indicator, isDataLoaded, isLoading, doReload };
return { indicator, isDataLoaded, isDataFound, isLoading, doReload };
};
//----------------

View File

@ -10,8 +10,8 @@
import React, { useReducer, createContext, useEffect, useContext, useCallback, useMemo } from "react"; //ReactJS
import PropTypes from "prop-types"; //Контроль свойств компонента
import { APP_AT, INITIAL_STATE, applicationReducer } from "./application_reducer"; //Редьюсер состояния
import { MessagingСtx } from "./messaging"; //Контекст отображения сообщений
import { BackEndСtx } from "./backend"; //Контекст взаимодействия с сервером
import { MessagingCtx } from "./messaging"; //Контекст отображения сообщений
import { BackEndCtx } from "./backend"; //Контекст взаимодействия с сервером
//---------
//Константы
@ -31,7 +31,7 @@ const APPLICATION_CONTEXT_ERRORS_SHAPE = PropTypes.shape({
//----------------
//Контекст приложения
export const ApplicationСtx = createContext();
export const ApplicationCtx = createContext();
//Провайдер контекста приложения
export const ApplicationContext = ({ errors, displaySizeGetter, guidGenerator, config, children }) => {
@ -39,10 +39,10 @@ export const ApplicationContext = ({ errors, displaySizeGetter, guidGenerator, c
const [state, dispatch] = useReducer(applicationReducer, INITIAL_STATE(displaySizeGetter));
//Подключение к контексту взаимодействия с сервером
const { getConfig, getRespPayload } = useContext(BackEndСtx);
const { getConfig, getRespPayload } = useContext(BackEndCtx);
//Подключение к контексту отображения сообщений
const { showMsgErr } = useContext(MessagingСtx);
const { showMsgErr } = useContext(MessagingCtx);
//Установка флага инициализированности приложения
const setInitialized = () => dispatch({ type: APP_AT.SET_INITIALIZED });
@ -59,6 +59,9 @@ export const ApplicationContext = ({ errors, displaySizeGetter, guidGenerator, c
//Установка заголовка в шапке приложения
const setAppBarTitle = useCallback(appBarTitle => dispatch({ type: APP_AT.SET_APP_BAR_TITLE, payload: appBarTitle }), []);
//Установка флага отображения шапки приложения
const setAppBarShow = useCallback(appBarShow => dispatch({ type: APP_AT.SET_APP_BAR_SHOW, payload: appBarShow }), []);
//Поиск раздела по имени
const findPanelByName = name => state.panels.find(panel => panel.name == name);
@ -81,8 +84,8 @@ export const ApplicationContext = ({ errors, displaySizeGetter, guidGenerator, c
modal
? P8O_API.fn.openDocumentModal({ unitcode: unitCode, method: showMethod, inputParameters })
: P8O_API.fn.openDocument
? P8O_API.fn.openDocument({ unitcode: unitCode, method: showMethod, inputParameters })
: showMsgErr(errors.P8O_API_UNSUPPORTED);
? P8O_API.fn.openDocument({ unitcode: unitCode, method: showMethod, inputParameters })
: showMsgErr(errors.P8O_API_UNSUPPORTED);
else showMsgErr(errors.P8O_API_UNAVAILABLE);
},
[showMsgErr, errors.P8O_API_UNAVAILABLE, errors.P8O_API_UNSUPPORTED]
@ -99,12 +102,12 @@ export const ApplicationContext = ({ errors, displaySizeGetter, guidGenerator, c
inputParameters: [{ name: inRnParameter, value: document }]
})
: P8O_API.fn.openDocument
? P8O_API.fn.openDocument({
unitcode: unitCode,
method: showMethod,
inputParameters: [{ name: inRnParameter, value: document }]
})
: showMsgErr(errors.P8O_API_UNSUPPORTED);
? P8O_API.fn.openDocument({
unitcode: unitCode,
method: showMethod,
inputParameters: [{ name: inRnParameter, value: document }]
})
: showMsgErr(errors.P8O_API_UNSUPPORTED);
else showMsgErr(errors.P8O_API_UNAVAILABLE);
},
[showMsgErr, errors.P8O_API_UNAVAILABLE, errors.P8O_API_UNSUPPORTED]
@ -170,9 +173,10 @@ export const ApplicationContext = ({ errors, displaySizeGetter, guidGenerator, c
//Вернём компонент провайдера
return (
<ApplicationСtx.Provider
<ApplicationCtx.Provider
value={{
setAppBarTitle,
setAppBarShow,
findPanelByName,
pOnlineShowTab,
pOnlineShowUnit,
@ -186,7 +190,7 @@ export const ApplicationContext = ({ errors, displaySizeGetter, guidGenerator, c
}}
>
{children}
</ApplicationСtx.Provider>
</ApplicationCtx.Provider>
);
};

View File

@ -13,13 +13,15 @@ const APP_AT = {
LOAD_PANELS: "LOAD_PANELS", //Загрузка списка панелей
SET_INITIALIZED: "SET_INITIALIZED", //Установка флага инициализированности приложения
SET_DISPLAY_SIZE: "SET_DISPLAY_SIZE", //Установка текущего типового размера экрана
SET_APP_BAR_TITLE: "SET_APP_BAR_TITLE" //Установка заголовка в шапке приложения
SET_APP_BAR_TITLE: "SET_APP_BAR_TITLE", //Установка заголовка в шапке приложения
SET_APP_BAR_SHOW: "SET_APP_BAR_SHOW" //Установка флага отображения шапки приложения
};
//Состояние приложения по умолчанию
const INITIAL_STATE = displaySizeGetter => ({
displaySize: displaySizeGetter(),
appBarTitle: "",
appBarShow: true,
urlBase: "",
panels: [],
panelsLoaded: false,
@ -50,6 +52,8 @@ const handlers = {
[APP_AT.SET_DISPLAY_SIZE]: (state, { payload }) => ({ ...state, displaySize: payload }),
//Установка заголовка в шапке приложения
[APP_AT.SET_APP_BAR_TITLE]: (state, { payload }) => ({ ...state, appBarTitle: payload }),
//Установка флага отображения шапки приложения
[APP_AT.SET_APP_BAR_SHOW]: (state, { payload }) => ({ ...state, appBarShow: payload }),
//Обработчик по умолчанию
DEFAULT: state => state
};

View File

@ -9,7 +9,7 @@
import React, { createContext, useContext, useCallback } from "react"; //ReactJS
import PropTypes from "prop-types"; //Контроль свойств компонента
import { MessagingСtx } from "./messaging"; //Контекст сообщений
import { MessagingCtx } from "./messaging"; //Контекст сообщений
import { formatErrorMessage } from "../core/utils"; //Вспомогательные функции
//---------
@ -34,12 +34,12 @@ const BACKEND_CONTEXT_CLIENT_SHAPE = PropTypes.shape({
//----------------
//Контекст взаимодействия с серверным API
export const BackEndСtx = createContext();
export const BackEndCtx = createContext();
//Провайдер контекста взаимодействия с серверным API
export const BackEndContext = ({ client, children }) => {
//Подключение к контексту сообщений
const { showLoader, hideLoader, showMsgErr } = useContext(MessagingСtx);
const { showLoader, hideLoader, showMsgErr } = useContext(MessagingCtx);
//Проверка ответа на наличие ошибки
const isRespErr = useCallback(resp => client.isRespErr(resp), [client]);
@ -116,7 +116,7 @@ export const BackEndContext = ({ client, children }) => {
//Вернём компонент провайдера
return (
<BackEndСtx.Provider
<BackEndCtx.Provider
value={{
SERV_DATA_TYPE_STR: client.SERV_DATA_TYPE_STR,
SERV_DATA_TYPE_NUMB: client.SERV_DATA_TYPE_NUMB,
@ -130,7 +130,7 @@ export const BackEndContext = ({ client, children }) => {
}}
>
{children}
</BackEndСtx.Provider>
</BackEndCtx.Provider>
);
};

View File

@ -43,7 +43,7 @@ const MESSAGING_CONTEXT_BUTTONS_SHAPE = PropTypes.shape({
//----------------
//Контекст сообщений
export const MessagingСtx = createContext();
export const MessagingCtx = createContext();
//Провайдер контекста сообщений
export const MessagingContext = ({ titles, texts, buttons, children }) => {
@ -109,7 +109,7 @@ export const MessagingContext = ({ titles, texts, buttons, children }) => {
//Вернём компонент провайдера
return (
<MessagingСtx.Provider
<MessagingCtx.Provider
value={{
MSG_TYPE,
showLoader,
@ -146,7 +146,7 @@ export const MessagingContext = ({ titles, texts, buttons, children }) => {
/>
) : null}
{children}
</MessagingСtx.Provider>
</MessagingCtx.Provider>
);
};

View File

@ -11,7 +11,7 @@ import React, { createContext, useContext } from "react"; //ReactJS
import PropTypes from "prop-types"; //Контроль свойств компонента
import { useLocation, useNavigate } from "react-router-dom"; //Роутер приложения
import queryString from "query-string"; //Работа со строкой запроса
import { ApplicationСtx } from "./application"; //Контекст приложения
import { ApplicationCtx } from "./application"; //Контекст приложения
//---------
//Константы
@ -41,7 +41,7 @@ export const NavigationContext = ({ children }) => {
const navigate = useNavigate();
//Подключение к контексту приложения
const { findPanelByName, setAppBarTitle } = useContext(ApplicationСtx);
const { findPanelByName, setAppBarTitle } = useContext(ApplicationCtx);
//Проверка наличия параметров запроса
const isNavigationSearch = () => (location.search ? true : false);

View File

@ -8,7 +8,7 @@
//---------------------
import React, { useState, useContext, useEffect, useCallback } from "react"; //Классы React
import { BackEndСtx } from "../../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../../context/backend"; //Контекст взаимодействия с сервером
import PropTypes from "prop-types"; //Контроль свойств компонента
import {
Dialog,
@ -56,7 +56,7 @@ const FilterDialog = ({ initial, onFilterChange, onFilterClose, onDocLinksLoad }
const { handleCatalogTreeOpen, handleEventTypesOpen, handleAgnlistOpen, handleInsDepartmentOpen, handleCostStaffGroupsOpen } = useDictionary();
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//При изменении типа события фильтра
const handleTypeChange = callBack =>

View File

@ -12,9 +12,9 @@ import PropTypes from "prop-types"; //Контроль свойств компо
import { Draggable } from "react-beautiful-dnd"; //Работа с drag&drop
import { Card, CardHeader, Typography, IconButton, Icon, Box, Menu, MenuItem, CardContent, Avatar, Stack } from "@mui/material"; //Интерфейсные компоненты
import { TaskDialog } from "../task_dialog"; //Форма события
import { ApplicationСtx } from "../../../context/application"; //Контекст приложения
import { BackEndСtx } from "../../../context/backend"; //Контекст взаимодействия с сервером
import { MessagingСtx } from "../../../context/messaging"; //Контекст сообщений
import { ApplicationCtx } from "../../../context/application"; //Контекст приложения
import { BackEndCtx } from "../../../context/backend"; //Контекст взаимодействия с сервером
import { MessagingCtx } from "../../../context/messaging"; //Контекст сообщений
import { TASK_COLORS, getTaskExpiredColor, getTaskBgColorByRule, makeCardActionsArray } from "../layouts"; //Дополнительная разметка и вёрстка клиентских элементов
import { useDictionary } from "../hooks/dict_hooks"; //Состояние открытия разделов
import { useTasksFunctions } from "../hooks/tasks_hooks"; //Состояние вспомогательных функций событий
@ -141,13 +141,13 @@ const TaskCard = ({ task, index, onTasksReload, colorRule, pointSettings, onOpen
const { handleTaskStateChange, handleTaskSend } = useTasksFunctions();
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Подключение к контексту сообщений
const { showMsgWarn } = useContext(MessagingСtx);
const { showMsgWarn } = useContext(MessagingCtx);
//Подключение к контексту приложения
const { pOnlineShowDocument } = useContext(ApplicationСtx);
const { pOnlineShowDocument } = useContext(ApplicationCtx);
//По нажатию на открытие меню действий
const handleMethodsMenuButtonClick = useCallback(event => {

View File

@ -8,7 +8,7 @@
//---------------------
import { useContext, useCallback } from "react"; //Классы React
import { ApplicationСtx } from "../../../context/application"; //Контекст приложения
import { ApplicationCtx } from "../../../context/application"; //Контекст приложения
//-----------
//Тело модуля
@ -17,7 +17,7 @@ import { ApplicationСtx } from "../../../context/application"; //Контекс
//Состояние открытия разделов
const useDictionary = () => {
//Подключение к контексту приложения
const { pOnlineShowDictionary } = useContext(ApplicationСtx);
const { pOnlineShowDictionary } = useContext(ApplicationCtx);
//Отображение раздела "Сотрудники"
const handleClientPersonOpen = useCallback(

View File

@ -8,7 +8,7 @@
//---------------------
import { useState, useContext, useEffect, useCallback } from "react"; //Классы React
import { BackEndСtx } from "../../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../../context/backend"; //Контекст взаимодействия с сервером
import { getRandomColor, getLocalStorageValue } from "../layouts"; //Вспомогательные функции
//-----------
@ -29,7 +29,7 @@ const useExtraData = filtersType => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Считывание учётных документов
const handleDocLinksLoad = useCallback(
@ -99,7 +99,7 @@ const useColorRules = () => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//При необходимости загрузки заливок
useEffect(() => {
@ -165,7 +165,7 @@ const useStatuses = filterType => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//При необходимости сортировки статусов
useEffect(() => {

View File

@ -8,7 +8,7 @@
//---------------------
import { useState, useContext, useEffect } from "react"; //Классы React
import { BackEndСtx } from "../../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../../context/backend"; //Контекст взаимодействия с сервером
//-----------
//Тело модуля
@ -48,7 +48,7 @@ const useClientEvent = (taskRn, taskType = "") => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//При инициализации события
useEffect(() => {
@ -161,7 +161,7 @@ const useDocsProps = taskType => {
const [docProps, setDocsProps] = useState({ loaded: false, props: [] });
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
useEffect(() => {
//Загрузка доп. свойств

View File

@ -8,7 +8,7 @@
//---------------------
import { useState, useContext, useEffect, useCallback } from "react"; //Классы React
import { BackEndСtx } from "../../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../../context/backend"; //Контекст взаимодействия с сервером
import { object2Base64XML } from "../../../core/utils"; //Вспомогательные функции
import { convertFilterValuesToArray } from "../layouts"; //Вспомогательные функции
import { useDictionary } from "./dict_hooks"; //Состояние открытия разделов
@ -23,7 +23,7 @@ const useTasksFunctions = () => {
const { handleEventRoutesPointExecutersOpen, handleEventRoutesPointsPassessOpen } = useDictionary();
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Выполнение направления события
const handleSendExec = useCallback(
@ -310,7 +310,7 @@ const useTasks = (filterValues, ordersValues) => {
const { handleTaskStateChange } = useTasksFunctions();
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//Инициализация параметров события
const initTask = (id, task, avatar = null) => {

View File

@ -12,7 +12,7 @@ import PropTypes from "prop-types"; //Контроль свойств компо
import { useClientEvent } from "./hooks/task_dialog_hooks"; //Хук для события
import { useDocsProps } from "./hooks/task_dialog_hooks"; //Хук для получения доп. свойств раздела "События"
import { TaskForm } from "./components/task_form"; //Форма события
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { object2Base64XML } from "../../core/utils"; //Вспомогательные функции
import { hasValue } from "../../core/utils"; //Вспомогательные процедуры и функции
import { P8PDialog } from "../../components/p8p_dialog"; //Типовой диалог
@ -37,7 +37,7 @@ const TaskDialog = ({ taskRn, taskType, editable, onTasksReload, onClose }) => {
const [docPropsReady, setDocPropsReady] = useState(false);
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//При изменении информации о задаче
const handleTaskChange = useCallback(

View File

@ -11,9 +11,9 @@ import React, { useState, useContext, useCallback, useEffect } from "react"; //
import { Box } from "@mui/material"; //Интерфейсные компоненты
import { P8PDataGrid, P8P_DATA_GRID_SIZE } from "../../components/p8p_data_grid"; //Таблица данных
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
import { MessagingCtx } from "../../context/messaging"; //Контекст сообщений
import { headCellRender, dataCellRender, groupCellRender, DIGITS_REG_EXP, MONTH_NAME_REG_EXP, DAY_NAME_REG_EXP } from "./layouts"; //Дополнительная разметка и вёрстка клиентских элементов
import { TEXTS } from "../../../app.text"; //Тектовые ресурсы и константы
import { Filter } from "./filter"; //Компонент фильтра
@ -88,13 +88,13 @@ const EqsPrfrm = () => {
const [refIsDeprecated, setRidFlag] = useState(true);
//Подключение к контексту приложения
const { pOnlineShowUnit } = useContext(ApplicationСtx);
const { pOnlineShowUnit } = useContext(ApplicationCtx);
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Подключение к контексту сообщений
const { showMsgErr } = useContext(MessagingСtx);
const { showMsgErr } = useContext(MessagingCtx);
//Загрузка данных таблицы с сервера
const loadData = useCallback(async () => {

View File

@ -11,7 +11,7 @@ import React, { useState, useContext } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Dialog, DialogTitle, IconButton, Icon, DialogContent, DialogActions, Button, Box, Grid } from "@mui/material"; //Интерфейсные компоненты
import { FilterInputField } from "./filter_input_field"; //Компонент поля ввода
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
//---------
//Константы
@ -77,7 +77,7 @@ const FilterDialog = ({ initial, onCancel, onOk }) => {
const [filter, setFilter] = useState({ ...initial });
//Подключение к контексту приложения
const { pOnlineShowDictionary } = useContext(ApplicationСtx);
const { pOnlineShowDictionary } = useContext(ApplicationCtx);
//При закрытии диалога без изменения фильтра
const handleCancel = () => (onCancel ? onCancel() : null);

View File

@ -8,7 +8,7 @@
//---------------------
import React, { useState, useCallback, useEffect, useContext } from "react"; //Классы React
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { object2Base64XML } from "../../core/utils"; //Вспомогательные функции
//---------
@ -50,7 +50,7 @@ const useMechRecAssemblyMon = () => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Инициализация каталогов планов
const initPlanCtlgs = useCallback(async () => {
@ -134,7 +134,7 @@ const useCostProductComposition = planSpec => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//При подключении компонента к странице
useEffect(() => {
@ -174,7 +174,7 @@ const useProductDetailsTable = (planSpec, product, orders, pageNumber, stored) =
});
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//Загрузка данных при изменении зависимостей
useEffect(() => {

View File

@ -8,7 +8,7 @@
//---------------------
import React, { useState, useCallback, useEffect, useContext } from "react"; //Классы React
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { NavigationCtx } from "../../context/navigation"; //Контекст навигации
import { object2Base64XML } from "../../core/utils"; //Вспомогательные функции
@ -49,7 +49,7 @@ const useCostJobs = () => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Подключение к контексту навигации
const { getNavigationSearch } = useContext(NavigationCtx);
@ -100,7 +100,7 @@ const useCostJobsSpecs = task => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//Выдача задания
const issueCostJobsSpecs = useCallback(
@ -192,7 +192,7 @@ const useEquipConfiguration = (task, fromAction) => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//Включение станка в строку сменного задания
const includeEquipConfiguration = useCallback(

View File

@ -11,7 +11,7 @@ import React, { useContext, useState } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Drawer, Fab, Box, List, ListItemButton, ListItemText, Typography, TextField } from "@mui/material"; //Интерфейсные элементы
import { APP_STYLES } from "../../../app.styles"; //Типовые стили
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { MessagingCtx } from "../../context/messaging"; //Контекст сообщений
import { CostJobsSpecsDataGrid } from "./fcjobssp"; //Собственные хуки таблиц
import { useCostJobs, useFilteredFcjobs } from "./hooks"; //Вспомогательные хуки
@ -97,7 +97,7 @@ const MechRecCostJobs = () => {
const filteredJobs = useFilteredFcjobs(state.jobList, filter);
//Подключение к контексту сообщений
const { InlineMsgInfo } = useContext(MessagingСtx);
const { InlineMsgInfo } = useContext(MessagingCtx);
//Выбор плана
const selectJob = job => {

View File

@ -8,7 +8,7 @@
//---------------------
import { useState, useCallback, useEffect, useContext } from "react"; //Классы React
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { NavigationCtx } from "../../context/navigation"; //Контекст навигации
import { object2Base64XML } from "../../core/utils"; //Вспомогательные функции
@ -39,7 +39,7 @@ const useCostJobs = () => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Подключение к контексту навигации
const { getNavigationSearch } = useContext(NavigationCtx);
@ -89,7 +89,7 @@ const useCostJobsSpecs = task => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//Выдача задания
const issueCostJobsSpecs = useCallback(
@ -181,7 +181,7 @@ const useCostJobsWorkers = task => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//Включение рабочего в строку сменного задания
const includeWorker = useCallback(

View File

@ -3,7 +3,7 @@
//---------------------
import { useState, useCallback, useEffect, useContext } from "react";
import { BackEndСtx } from "../../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../../context/backend"; //Контекст взаимодействия с сервером
import { object2Base64XML, formatDateRF } from "../../../core/utils"; //Вспомогательные функции
//---------
@ -33,7 +33,7 @@ const useCostRouteLists = (task, taskType) => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//Загрузка данных таблицы с сервера
const loadData = useCallback(async () => {
@ -104,7 +104,7 @@ const useIncomFromDeps = (task, taskType) => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//Загрузка данных таблицы с сервера
const loadData = useCallback(async () => {
@ -157,7 +157,7 @@ const useGoodsParties = mainRowRN => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//Загрузка данных таблицы с сервера
const loadData = useCallback(async () => {
@ -208,7 +208,7 @@ const useCostDeliveryLists = mainRowRN => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//Загрузка данных таблицы строк комплектации с сервера
const loadData = useCallback(async () => {

View File

@ -39,8 +39,8 @@ import {
CardActions,
Tooltip
} from "@mui/material"; //Интерфейсные элементы
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { MessagingCtx } from "../../context/messaging"; //Контекст сообщений
import { NavigationCtx } from "../../context/navigation"; //Контекст навигации
import { P8P_GANTT_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { APP_BAR_HEIGHT } from "../../components/p8p_app_workspace"; //Заголовок страницы
@ -255,10 +255,10 @@ const PlanCtlgsList = ({
!selectedPlanCtlg
? "Не выбран каталог планов"
: selectedPlans.length === 0
? "Не выбраны планы каталога"
: selectedPlansElements > MAX_TASKS
? `Выбранные планы превышают максимум элементов (выбрано: ${selectedPlansElements}, максимум: ${MAX_TASKS})`
: null
? "Не выбраны планы каталога"
: selectedPlansElements > MAX_TASKS
? `Выбранные планы превышают максимум элементов (выбрано: ${selectedPlansElements}, максимум: ${MAX_TASKS})`
: null
}
>
<Box>
@ -384,16 +384,16 @@ const MechRecCostProdPlans = () => {
const filteredPlanCtgls = useFilteredPlanCtlgs(state.planCtlgs, filter);
//Подключение к контексту сообщений
const { InlineMsgInfo } = useContext(MessagingСtx);
const { InlineMsgInfo } = useContext(MessagingCtx);
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//Подключение к контексту навигации
const { getNavigationSearch } = useContext(NavigationCtx);
//Подключение к контексту сообщений
const { showMsgInfo } = useContext(MessagingСtx);
const { showMsgInfo } = useContext(MessagingCtx);
//Инициализация каталогов планов
const initPlanCtlgs = useCallback(async () => {

View File

@ -8,7 +8,7 @@
//---------------------
import { useState, useCallback, useEffect, useContext } from "react"; //Классы React
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { object2Base64XML, formatDateRF } from "../../core/utils"; //Вспомогательные функции
//---------
@ -40,7 +40,7 @@ const useMechRecDeptCostJobs = (subdiv, fullDate, workHours) => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//При необходимости обновить данные таблицы
useEffect(() => {
@ -91,7 +91,7 @@ const useInsDepartment = fullDate => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//При необходимости обновить данные таблицы
useEffect(() => {
@ -142,7 +142,7 @@ const useFilter = (currentMonth, currentYear) => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Считываем количества рабочих дней
const getWorkDays = useCallback(

View File

@ -12,7 +12,7 @@ import PropTypes from "prop-types"; //Контроль свойств компо
import { Typography, Box, Paper, Dialog, DialogContent, DialogActions, Button, TextField, IconButton, Icon } from "@mui/material"; //Интерфейсные элементы
import { P8PDataGrid, P8P_DATA_GRID_SIZE } from "../../components/p8p_data_grid"; //Таблица данных
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { CostRouteListsSpecsDataGrid } from "./fcroutlstsp"; //Состояние таблицы заказов маршрутных листов
import { useCostRouteLists } from "./hooks.js"; //Хук состояния таблицы маршрутных листов
@ -142,7 +142,7 @@ const CostRouteListsDataGrid = ({ task }) => {
const [costRouteLists, setCostRouteLists] = useCostRouteLists(task);
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//При изменении состояния сортировки
const handleOrderChanged = ({ orders }) => setCostRouteLists(pv => ({ ...pv, orders: [...orders], pageNumber: 1, reload: true }));

View File

@ -8,7 +8,7 @@
//---------------------
import React, { useState, useEffect, useContext, useCallback } from "react"; //Классы React
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { object2Base64XML, formatDateRF } from "../../core/utils"; //Вспомогательные функции
//---------
@ -46,7 +46,7 @@ const useDeptCostProdPlans = month => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//При подключении компонента к странице
useEffect(() => {
@ -98,7 +98,7 @@ const useDeptCostProdPlanInfo = plan => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//При необходимости очистки данных о плане
const handleClear = useCallback(
@ -187,7 +187,7 @@ const useCostRouteLists = task => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//При необходимости обновить данные таблицы
useEffect(() => {
@ -244,7 +244,7 @@ const useCostRouteListsSpecs = mainRowRN => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//При необходимости обновить данные таблицы
useEffect(() => {
@ -304,7 +304,7 @@ const useIncomFromDeps = task => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//При необходимости обновить данные таблицы
useEffect(() => {

View File

@ -15,7 +15,7 @@ import { APP_BAR_HEIGHT } from "../../components/p8p_app_workspace"; //Заго
import { useDeptCostProdPlans, useFilteredPlans, useDeptCostProdPlanInfo } from "./hooks"; //Вспомогательные хуки
import { P8PDataGrid, P8P_DATA_GRID_SIZE } from "../../components/p8p_data_grid"; //Таблица данных
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { MessagingCtx } from "../../context/messaging"; //Контекст сообщений
import { IncomFromDepsDataGridDialog } from "./incomefromdeps"; //Диалог сдачи продукции
import { CostRouteListsDataGridDialog } from "./fcroutlst"; //Диалог маршрутных листов
@ -229,7 +229,7 @@ const MechRecDeptCostProdPlans = () => {
const filteredPlanCtgls = useFilteredPlans(plans.rows, filter);
//Подключение к контексту сообщений
const { InlineMsgInfo } = useContext(MessagingСtx);
const { InlineMsgInfo } = useContext(MessagingCtx);
//Выбор плана
const selectPlan = plan => {

View File

@ -11,7 +11,7 @@ import React, { useContext, useState } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Box, Grid, Typography, Link, List, ListItem, ListItemButton, ListItemText, Divider, Fab, Icon } from "@mui/material"; //Интерфейсные элементы
import { BUTTONS } from "../../../app.text"; //Текстовые ресурсы
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
import img1_1 from "./img/1_1.png"; //Изображение
import img1_2 from "./img/1_2.png"; //Изображение
import img1_3 from "./img/1_3.png"; //Изображение
@ -252,7 +252,7 @@ Img.propTypes = {
//Ссылка на раздел Системы
const UnitLink = ({ unitCode, children }) => {
//Подключение к контексту приложения
const { pOnlineShowUnit } = useContext(ApplicationСtx);
const { pOnlineShowUnit } = useContext(ApplicationCtx);
//Генерация содержимого
return (
@ -299,7 +299,7 @@ ChapterLink.propTypes = {
//Ссылка на информационную панель
const PanelLink = ({ panelName, children }) => {
//Подключение к контексту приложения
const { configUrlBase, findPanelByName, pOnlineShowTab } = useContext(ApplicationСtx);
const { configUrlBase, findPanelByName, pOnlineShowTab } = useContext(ApplicationCtx);
//Генерация содержимого
return (

View File

@ -8,8 +8,8 @@
//---------------------
import { useState, useEffect, useContext, useCallback, useLayoutEffect } from "react"; //Классы React
import { BackEndСtx } from "../../../context/backend"; //Контекст взаимодействия с сервером
import { MessagingСtx } from "../../../context/messaging"; //Контекст сообщений
import { BackEndCtx } from "../../../context/backend"; //Контекст взаимодействия с сервером
import { MessagingCtx } from "../../../context/messaging"; //Контекст сообщений
import { object2Base64XML, genUID, xml2JSON } from "../../../core/utils"; //Вспомогательные функции
import { exportXMLFile } from "../layouts"; //Дополнительная разметка и вёрстка клиентских элементов
import { P8P_COMPONENT_SETTINGS_PATHS } from "../../../components/editors/p8p_component_settings"; //Дополнительные настройки источников
@ -57,8 +57,8 @@ const tagValueProcessorPanelDesc = (name, val, jPath) =>
["condValue", "resValue", "description"].includes(name)
? undefined
: /(.*)dataSource.arguments.value$/.test(jPath) || /(.*)XVALUE_PROVIDERS(.*)$/.test(jPath)
? undefined
: val;
? undefined
: val;
//Конвертация серверного описания компонентов в данные для редактора панелей
const convertServerData2Components = components => {
@ -184,7 +184,7 @@ const usePanel = () => {
const [editMode, setEditMode] = useState(true);
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//При необходимости загрузки информации о панели
const loadPanel = async panel => {
@ -244,7 +244,7 @@ const usePanelManager = () => {
const [data, setData] = useState(null);
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//Добавление панели
const insertPanel = useCallback(
@ -354,10 +354,10 @@ const usePanelDesc = panel => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//Подключение к контексту сообщений
const { showMsgErr } = useContext(MessagingСtx);
const { showMsgErr } = useContext(MessagingCtx);
//Считывание базовой информации о панели
const getPanelInfo = useCallback(async () => {

View File

@ -27,7 +27,7 @@ import {
InputAdornment,
IconButton
} from "@mui/material"; //Интерфейсные элементы
import { ApplicationСtx } from "../../../../context/application"; //Контекст приложения
import { ApplicationCtx } from "../../../../context/application"; //Контекст приложения
import { P8PEditorBox } from "../../../../components/editors/p8p_editor_box"; //Контейнер редактора
import { P8PEditorSubHeader } from "../../../../components/editors/p8p_editor_sub_header"; //Заголовок раздела редактора
import { P8PConfigDialog } from "../../../../components/editors/p8p_config_dialog"; //Диалог настройки
@ -57,7 +57,7 @@ const ItemEditor = ({ item = null, valueProviders = {}, onOk = null, onCancel =
const [valueProvidersMenuAnchorEl, setValueProvidersMenuAnchorEl] = useState(null);
//Подключение к контексту приложения
const { pOnlineShowDictionary } = useContext(ApplicationСtx);
const { pOnlineShowDictionary } = useContext(ApplicationCtx);
//При закрытии редактора с сохранением
const handleOk = () => onOk && onOk({ ...state });

View File

@ -10,7 +10,7 @@
import React, { useEffect, useState, useContext } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Paper, Stack, Typography, Icon, TextField, IconButton, InputAdornment } from "@mui/material"; //Интерфейсные элементы
import { ApplicationСtx } from "../../../../context/application"; //Контекст приложения
import { ApplicationCtx } from "../../../../context/application"; //Контекст приложения
import { P8P_COMPONENT_INLINE_MESSAGE, P8PComponentInlineMessage } from "../../../../components/editors/p8p_component_inline_message"; //Информационное сообщение внутри компонента
import { ITEM_SHAPE, ITEMS_INITIAL, ORIENTATION } from "./common"; //Общие ресурсы и константы формы
import { APP_STYLES } from "../../../../../app.styles";
@ -37,7 +37,7 @@ const COMPONENT_NAME = "Форма";
//Элемент формы
const FormItem = ({ item = null, fullWidth = false, value = "", onChange = null } = {}) => {
//Подключение к контексту приложения
const { pOnlineShowDictionary } = useContext(ApplicationСtx);
const { pOnlineShowDictionary } = useContext(ApplicationCtx);
//При изменении значения элемента
const handleChange = e => onChange && onChange(e.target.id, e.target.value);

View File

@ -10,7 +10,7 @@
import React, { useState, useContext } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Box, Button, Icon } from "@mui/material"; //Интерфейсные компоненты MUI
import { MessagingСtx } from "../../../../context/messaging"; //Контекст сообщений
import { MessagingCtx } from "../../../../context/messaging"; //Контекст сообщений
import { BUTTONS } from "../../../../../app.text"; //Общие текстовые ресурсы приложения
import { P8PConfigDialog } from "../../../../components/editors/p8p_config_dialog"; //Типовой диалог настройки
import { usePanelManager } from "../components_hooks"; //Пользовательские хуки
@ -31,7 +31,7 @@ const PanelsManager = ({ current = null, isEditable = true, onPanelSelect = null
const [panels, insertPanel, updatePanel, deletePanel, setPanelReady, setPanelPbl, importPanel] = usePanelManager();
//Подключение к контексту сообщений
const { showMsgWarn } = useContext(MessagingСtx);
const { showMsgWarn } = useContext(MessagingCtx);
//При добавлении панели
const handlePanelAdd = () => setModPanel(true);

View File

@ -11,7 +11,7 @@ import React, { useState, useContext, useEffect } from "react"; //Классы R
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Responsive, WidthProvider } from "react-grid-layout"; //Адаптивный макет
import { Box, Grid, Menu, MenuItem, Popover } from "@mui/material"; //Интерфейсные элементы
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { MessagingCtx } from "../../context/messaging"; //Контекст сообщений
import { APP_BAR_HEIGHT } from "../../components/p8p_app_workspace"; //Рабочая область приложения
import { P8PEditorToolBar } from "../../components/editors/p8p_editor_toolbar"; //Панель инструментов редактора
import { LayoutItem } from "./layout_item"; //Элемент макета
@ -89,7 +89,7 @@ const PanelEditor = ({
const [rowHeight] = useWindowResize();
//Подключение к контексту сообщений
const { showMsgWarn } = useContext(MessagingСtx);
const { showMsgWarn } = useContext(MessagingCtx);
//При перемещении макета
const handleOnDrag = layout => {

View File

@ -14,7 +14,7 @@ import { P8PConfigDialog } from "../../components/editors/p8p_config_dialog"; //
import { isElementNameCorrect } from "../../components/editors/p8p_editors_common"; //Общие ресурсы редакторов
import { P8PEditorSubHeader } from "../../components/editors/p8p_editor_sub_header"; //Заголовок раздела редактора
import { P8PEditorBox } from "../../components/editors/p8p_editor_box"; //Контейнер редактора
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { MessagingCtx } from "../../context/messaging"; //Контекст сообщений
import { APP_STYLES } from "../../../app.styles"; //Типовые стили
import { STYLES as COMMON_STYLES } from "../../components/editors/p8p_editors_common"; //Общие ресурсы редакторов
import { P8PChipList } from "../../components/editors/p8p_chip_list"; //Дополнительные настройки редактора
@ -127,7 +127,7 @@ const PanelPropsEditor = ({ valueProviders = {}, onSettingsChange, onDependencyC
const [variableEditor, setVariableEditor] = useState({ display: false, item: null });
//Подключение к контексту сообщений
const { showMsgErr } = useContext(MessagingСtx);
const { showMsgErr } = useContext(MessagingCtx);
//При добавлении новой переменной
const handleVariableAdd = () => setVariableEditor({ display: true, item: null });

View File

@ -9,8 +9,8 @@
import React, { useState, useContext, useEffect } from "react"; //Классы React
import { Box, Icon, Fab } from "@mui/material"; //Интерфейсные элементы
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
import { MessagingCtx } from "../../context/messaging"; //Контекст сообщений
import { PanelsManager } from "./components/panels_manager/panels_manager"; //Менеджер панелей
import { usePanel } from "./components/components_hooks"; //Вспомогательные хуки
import { NavigationCtx } from "../../context/navigation"; //Контекст навигации
@ -57,9 +57,9 @@ const PanelsEditor = () => {
//Подключение к контексту навигации
const { getNavigationSearch } = useContext(NavigationCtx);
//Подключение к контексту сообщений
const { showMsgWarn } = useContext(MessagingСtx);
const { showMsgWarn } = useContext(MessagingCtx);
//Подключение к контексту приложения
const { setAppBarTitle } = useContext(ApplicationСtx);
const { setAppBarTitle } = useContext(ApplicationCtx);
//При выборе панели
const handlePanelSelect = panel => {

View File

@ -21,9 +21,9 @@ import {
} from "../../components/p8p_data_grid"; //Таблица данных
import { P8PFullScreenDialog } from "../../components/p8p_fullscreen_dialog"; //Полноэкранный диалог
import { P8PChart, useP8PChart } from "../../components/p8p_chart"; //График
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
import { MessagingCtx } from "../../context/messaging"; //Контекст сообщений
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { COMMON_PROJECTS_STYLES, PANEL_UNITS, headCellRender, dataCellRender, valueFormatter, rowExpandRender } from "./layouts"; //Дополнительная разметка и вёрстка клиентских элементов
import { Stages } from "./stages"; //Список этапов проекта
@ -61,7 +61,7 @@ const Projects = () => {
const [stagesFilters, setStagesFilters] = useState([]);
//Подключение к контексту приложения
const { pOnlineShowDocument, pOnlineShowUnit, configSystemPageSize } = useContext(ApplicationСtx);
const { pOnlineShowDocument, pOnlineShowUnit, configSystemPageSize } = useContext(ApplicationCtx);
//Собственное состояние
const {
@ -83,10 +83,10 @@ const Projects = () => {
const { chart: costNotesChart, isDataLoaded: isCostNotesLoaded } = useP8PChart({ stored: "PKG_P8PANELS_PROJECTS.CHART_FCCOSTNOTES" });
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Подключение к контексту сообщений
const { showMsgErr } = useContext(MessagingСtx);
const { showMsgErr } = useContext(MessagingCtx);
//Отображение журнала платежей по этапу проекта
const showPayNotes = async ({ sender, direction }) => {

View File

@ -20,9 +20,9 @@ import {
P8P_DATA_GRID_FILTERS_HEIGHT,
useP8PDataGrid
} from "../../components/p8p_data_grid"; //Таблица данных
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
import { MessagingCtx } from "../../context/messaging"; //Контекст сообщений
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { PANEL_UNITS, dataCellRender, valueFormatter } from "./layouts"; //Дополнительная разметка и вёрстка клиентских элементов
@ -56,13 +56,13 @@ const StageArts = ({ stage, filters }) => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Подключение к контексту приложения
const { pOnlineShowUnit } = useContext(ApplicationСtx);
const { pOnlineShowUnit } = useContext(ApplicationCtx);
//Подключение к контексту сообщений
const { showMsgErr } = useContext(MessagingСtx);
const { showMsgErr } = useContext(MessagingCtx);
//Отображение журнала затрат по статье калькуляции
const showCostNotes = async ({ sender }) => {

View File

@ -21,9 +21,9 @@ import {
P8P_DATA_GRID_FILTERS_HEIGHT,
useP8PDataGrid
} from "../../components/p8p_data_grid"; //Таблица данных
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
import { MessagingCtx } from "../../context/messaging"; //Контекст сообщений
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { PANEL_UNITS, dataCellRender, valueFormatter, rowExpandRender } from "./layouts"; //Дополнительная разметка и вёрстка клиентских элементов
@ -48,7 +48,7 @@ const STYLES = {
//Договоры с соисполнителями этапа проекта
const StageContracts = ({ stage, filters }) => {
//Подключение к контексту приложения
const { pOnlineShowDocument, pOnlineShowUnit, configSystemPageSize } = useContext(ApplicationСtx);
const { pOnlineShowDocument, pOnlineShowUnit, configSystemPageSize } = useContext(ApplicationCtx);
//Собственное состояние
const {
@ -65,10 +65,10 @@ const StageContracts = ({ stage, filters }) => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Подключение к контексту сообщений
const { showMsgErr } = useContext(MessagingСtx);
const { showMsgErr } = useContext(MessagingCtx);
//Отображение выходящих счетов на оплату от соисполнителя этапа
const showPaymentAccountsIn = async ({ sender }) => {

View File

@ -24,9 +24,9 @@ import {
import { P8PFullScreenDialog } from "../../components/p8p_fullscreen_dialog"; //Полноэкранный диалог
import { StageArts } from "./stage_arts"; //Калькуляция этапа проекта
import { StageContracts } from "./stage_contracts"; //Договоры с соисполнителями этапа проекта
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
import { MessagingCtx } from "../../context/messaging"; //Контекст сообщений
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { COMMON_PROJECTS_STYLES, PANEL_UNITS, headCellRender, dataCellRender, valueFormatter, rowExpandRender } from "./layouts"; //Дополнительная разметка и вёрстка клиентских элементов
@ -60,7 +60,7 @@ const Stages = ({ project, projectName, filters }) => {
});
//Подключение к контексту приложения
const { pOnlineShowDocument, pOnlineShowUnit, configSystemPageSize } = useContext(ApplicationСtx);
const { pOnlineShowDocument, pOnlineShowUnit, configSystemPageSize } = useContext(ApplicationCtx);
//Собственное состояние
const {
@ -77,10 +77,10 @@ const Stages = ({ project, projectName, filters }) => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Подключение к контексту сообщений
const { showMsgErr } = useContext(MessagingСtx);
const { showMsgErr } = useContext(MessagingCtx);
//Отображение журнала платежей по этапу проекта
const showPayNotes = async ({ sender, direction }) => {

View File

@ -13,8 +13,8 @@ import { APP_BAR_HEIGHT } from "../../components/p8p_app_workspace"; //Заго
import { APP_STYLES } from "../../../app.styles"; //Типовые стили
import { P8PDataGrid, P8P_DATA_GRID_SIZE } from "../../components/p8p_data_grid"; //Таблица данных
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { dataCellRender, groupCellRender } from "./layouts"; //Дополнительная разметка и вёрстка клиентских элементов
//---------
@ -44,10 +44,10 @@ const PrjGraph = () => {
});
//Подключение к контексту приложения
const { pOnlineShowDocument } = useContext(ApplicationСtx);
const { pOnlineShowDocument } = useContext(ApplicationCtx);
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Загрузка данных таблицы с сервера
const loadData = useCallback(async () => {

View File

@ -28,7 +28,7 @@ import {
Icon
} from "@mui/material"; //Интерфейсные элементы
import { BUTTONS } from "../../../app.text"; //Текстовые ресурсы
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
import img21_1 from "./img/21_1.png"; //Изображение
import img21_2 from "./img/21_2.png"; //Изображение
import img21_3 from "./img/21_3.png"; //Изображение
@ -171,7 +171,7 @@ Img.propTypes = {
//Ссылка на раздел Системы
const UnitLink = ({ unitCode, children }) => {
//Подключение к контексту приложения
const { pOnlineShowUnit } = useContext(ApplicationСtx);
const { pOnlineShowUnit } = useContext(ApplicationCtx);
//Генерация содержимого
return (
@ -218,7 +218,7 @@ ChapterLink.propTypes = {
//Ссылка на информационную панель
const PanelLink = ({ panelName, children }) => {
//Подключение к контексту приложения
const { configUrlBase, findPanelByName, pOnlineShowTab } = useContext(ApplicationСtx);
const { configUrlBase, findPanelByName, pOnlineShowTab } = useContext(ApplicationCtx);
//Генерация содержимого
return (

View File

@ -10,7 +10,7 @@
import React, { useState, useContext } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Button, Dialog, DialogTitle, DialogContent, DialogActions } from "@mui/material"; //Интерфейсные элементы
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
import { BUTTONS } from "../../../app.text"; //Типовые тексты
import { APP_STYLES } from "../../../app.styles"; //Типовые стили
import { FormField } from "./layouts"; //Общие компоненты панели
@ -60,7 +60,7 @@ const FilterDialog = ({ valuesInitial, onOk, onCancel }) => {
const [values, setValues] = useState({ ...valuesInitial });
//Подключение к контексту приложения
const { pOnlineShowDictionary } = useContext(ApplicationСtx);
const { pOnlineShowDictionary } = useContext(ApplicationCtx);
//Изменение элемента формы фильтра
const handleValueChanged = (name, value) => setValues(pv => ({ ...pv, [name]: value }));

View File

@ -10,7 +10,7 @@
import React, { useState, useContext } from "react"; //Классы React
import { P8PDataGrid } from "../../components/p8p_data_grid"; //Таблица данных
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
import { useProjectsDataGrid } from "./projects_hooks"; //Хуки списка проектов
import { FILTER_INITIAL, Filter } from "./filter"; //Компонент "Фильтр"
import { PROJECTS_STYLES, projectDataCellRender, projectRowExpandRender } from "./projects_layouts"; //Дополнительная разметка и вёрстка клиентских элементов
@ -28,7 +28,7 @@ const Projects = () => {
const [projectsDataGrid] = useProjectsDataGrid({ ...projects.filter, pageNumber: projects.pageNumber, orders: projects.orders });
//Подключение к контексту приложения
const { pOnlineShowDocument } = useContext(ApplicationСtx);
const { pOnlineShowDocument } = useContext(ApplicationCtx);
//Отображение записи проекта в штатном разделе
const showProject = async rn => pOnlineShowDocument({ unitCode: "Projects", document: rn, modal: false });

View File

@ -8,7 +8,7 @@
//---------------------
import { useState, useContext, useEffect } from "react"; //Классы React
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { object2Base64XML, formatDateRF } from "../../core/utils"; //Вспомогательные функции
import config from "../../../app.config"; //Настройки приложения
@ -32,7 +32,7 @@ const useProjectsDataGrid = ({ prjType, insDep, priceStructStatus, prjState, sea
const [data, setData] = useState({ init: false, morePages: true });
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//При необходимости обновить данные таблицы
useEffect(() => {

View File

@ -10,9 +10,9 @@
import React, { useState, useContext } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Grid, Box, Typography, Paper, Drawer, IconButton, Icon } from "@mui/material"; //Интерфейсные элементы
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { MessagingCtx } from "../../context/messaging"; //Контекст сообщений
import { TEXTS } from "../../../app.text"; //Тектовые ресурсы и константы
import { P8PDataGrid, P8P_DATA_GRID_SIZE } from "../../components/p8p_data_grid"; //Таблица данных
import { P8PChart } from "../../components/p8p_chart"; //График
@ -38,13 +38,13 @@ const StageDetailData = ({ stageRn }) => {
const [state, setState] = useState({ artsDisplayType: 0, artsChartType: 0 });
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Подключение к контексту приложения
const { pOnlineShowUnit } = useContext(ApplicationСtx);
const { pOnlineShowUnit } = useContext(ApplicationCtx);
//Подключение к контексту сообщений
const { showMsgErr } = useContext(MessagingСtx);
const { showMsgErr } = useContext(MessagingCtx);
//Отображение журнала затрат (фактического, по рег. номеру ЛС и статьи затрат)
const showCostNotesFact = async ({ faceAccRn, artclRn }) => {

View File

@ -8,7 +8,7 @@
//---------------------
import { useState, useContext, useEffect } from "react"; //Классы React
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
//-----------
//Тело модуля
@ -23,7 +23,7 @@ const useStageDetailInfoDataGrid = ({ stageRn }) => {
const [data, setData] = useState({ init: false });
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//При необходимости обновить данные таблицы
useEffect(() => {
@ -58,7 +58,7 @@ const useStageDetailArtsDataGrid = ({ stageRn }) => {
const [data, setData] = useState({ init: false });
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//При необходимости обновить данные таблицы
useEffect(() => {
@ -93,7 +93,7 @@ const useStageDetailArtsChart = ({ stageRn, display, type }) => {
const [data, setData] = useState({ init: false, currentType: null });
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//При необходимости обновить данные таблицы
useEffect(() => {

View File

@ -10,7 +10,7 @@
import React, { useState, useContext } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Typography } from "@mui/material"; //Интерфейсные элементы
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
import { P8PDataGrid } from "../../components/p8p_data_grid"; //Таблица данных
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { useStagesDataGrid } from "./stages_hooks"; //Хуки списка этапов проекта
@ -33,7 +33,7 @@ const Stages = ({ projectRn, projectCode }) => {
const [stageInfo, setStageInfo] = useState({ showInfo: false, stage: null, sFaceAcc: null });
//Подключение к контексту приложения
const { pOnlineShowUnit } = useContext(ApplicationСtx);
const { pOnlineShowUnit } = useContext(ApplicationCtx);
//Отображение записи этапа проекта в штатном разделе
const showProjectStage = (prn, rn) => {

View File

@ -8,7 +8,7 @@
//---------------------
import { useState, useContext, useEffect } from "react"; //Классы React
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { object2Base64XML, formatDateRF } from "../../core/utils"; //Вспомогательные функции
import config from "../../../app.config"; //Настройки приложения
@ -32,7 +32,7 @@ const useStagesDataGrid = ({ projectRn, pageNumber, orders }) => {
const [data, setData] = useState({ init: false, morePages: true });
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//При необходимости обновить данные таблицы
useEffect(() => {

View File

@ -10,8 +10,8 @@
import React, { useContext, useState, useCallback, useEffect } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Dialog, DialogContent, DialogActions, Button, DialogTitle } from "@mui/material"; //Интерфейсные элементы
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
import { object2Base64XML } from "../../core/utils"; //Вспомогательные функции
import { BUTTONS } from "../../../app.text"; //Текстовые ресурсы
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
@ -36,10 +36,10 @@ const LabFactRptDtl = ({ periodId, title, onHide }) => {
});
//Подключение к контексту приложения
const { configSystemPageSize } = useContext(ApplicationСtx);
const { configSystemPageSize } = useContext(ApplicationCtx);
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//Загрузка детализации фактической трудоёмкости по отчетам для ресурса
const loadFactRptDtl = useCallback(async () => {

View File

@ -10,8 +10,8 @@
import React, { useContext, useState, useCallback, useEffect } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Dialog, DialogContent, DialogActions, Button, DialogTitle } from "@mui/material"; //Интерфейсные элементы
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
import { object2Base64XML } from "../../core/utils"; //Вспомогательные функции
import { BUTTONS } from "../../../app.text"; //Текстовые ресурсы
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
@ -35,10 +35,10 @@ const LabPlanFOTDtl = ({ periodId, title, onHide }) => {
});
//Подключение к контексту приложения
const { configSystemPageSize } = useContext(ApplicationСtx);
const { configSystemPageSize } = useContext(ApplicationCtx);
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//Загрузка детализации плановой трудоёмкости по ФОТ для ресурса
const loadPlanFOTDtl = useCallback(async () => {

View File

@ -10,8 +10,8 @@
import React, { useContext, useState, useCallback, useEffect } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Dialog, DialogContent, DialogActions, Button, DialogTitle } from "@mui/material"; //Интерфейсные элементы
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
import { object2Base64XML } from "../../core/utils"; //Вспомогательные функции
import { BUTTONS } from "../../../app.text"; //Текстовые ресурсы
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
@ -40,10 +40,10 @@ const LabPlanJobsDtl = ({ periodId, title, onHide, onProjectClick }) => {
});
//Подключение к контексту приложения
const { configSystemPageSize } = useContext(ApplicationСtx);
const { configSystemPageSize } = useContext(ApplicationCtx);
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//Загрузка детализации плановой трудоёмкости по графику для ресурса
const loadPlanJobsDtl = useCallback(async () => {

View File

@ -29,9 +29,9 @@ import {
TextField,
DialogTitle
} from "@mui/material"; //Интерфейсные элементы
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { MessagingCtx } from "../../context/messaging"; //Контекст сообщений
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
import { formatDateJSONDateOnly } from "../../core/utils"; //Вспомогательные функции
import { APP_BAR_HEIGHT } from "../../components/p8p_app_workspace"; //Заголовок страницы
import { APP_STYLES } from "../../../app.styles"; //Типовые стили
@ -185,7 +185,7 @@ SaveChangesArea.propTypes = {
//Список проектов
const ProjectsList = ({ projects = [], selectedProject, onClick } = {}) => {
//Подключение к контексту сообщений
const { InlineMsgErr } = useContext(MessagingСtx);
const { InlineMsgErr } = useContext(MessagingCtx);
//Генерация содержимого
return projects.length > 0 ? (
@ -211,8 +211,8 @@ const ProjectsList = ({ projects = [], selectedProject, onClick } = {}) => {
...(p.NJOBS == 0
? STYLES.PROJECTS_LIST_ITEM_SECONDARY_NOJOBS
: p.NCHANGED == 1
? STYLES.PROJECTS_LIST_ITEM_SECONDARY_CHANGED
: STYLES.PROJECTS_LIST_ITEM_SECONDARY_NOEDIT)
? STYLES.PROJECTS_LIST_ITEM_SECONDARY_CHANGED
: STYLES.PROJECTS_LIST_ITEM_SECONDARY_NOEDIT)
}}
>
{p.NJOBS == 1
@ -270,13 +270,13 @@ const PrjJobs = () => {
});
//Подключение к контексту приложения
const { pOnlineShowDocument } = useContext(ApplicationСtx);
const { pOnlineShowDocument } = useContext(ApplicationCtx);
//Подключение к контексту сообщений
const { InlineMsgInfo } = useContext(MessagingСtx);
const { InlineMsgInfo } = useContext(MessagingCtx);
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Загрузка списка проектов
const loadProjects = useCallback(

View File

@ -10,8 +10,8 @@
import React, { useContext, useState, useCallback, useEffect } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { APP_STYLES } from "../../../app.styles"; //Типовые стили
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
import { object2Base64XML } from "../../core/utils"; //Вспомогательные функции
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { P8PDataGrid, P8P_DATA_GRID_SIZE, P8P_DATA_GRID_MORE_HEIGHT } from "../../components/p8p_data_grid"; //Таблица данных
@ -57,10 +57,10 @@ const ResMon = ({ ident, onPlanJobsDtlProjectClick }) => {
});
//Подключение к контексту приложения
const { configSystemPageSize } = useContext(ApplicationСtx);
const { configSystemPageSize } = useContext(ApplicationCtx);
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//Загрузка данных монитора балансировки периодов с сервера
const loadPeriods = useCallback(async () => {

View File

@ -8,7 +8,7 @@
//---------------------
import { useContext, useCallback } from "react"; //Классы React
import { BackEndСtx } from "../../../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../../../context/backend"; //Контекст взаимодействия с сервером
//-----------
//Тело модуля
@ -17,7 +17,7 @@ import { BackEndСtx } from "../../../../context/backend"; //Контекст в
//Работа с областью SQL-выражения
const useQuerySQLExpr = query => {
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Установка флага сокрытия/отображения значений аргументов в SQL-выражении запроса
const toggleSubstArgsVals = useCallback(async () => {

View File

@ -8,7 +8,7 @@
//---------------------
import { useContext, useCallback } from "react"; //Классы React
import { BackEndСtx } from "../../../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../../../context/backend"; //Контекст взаимодействия с сервером
//------------------------------------
//Вспомогательные функции и компоненты
@ -21,7 +21,7 @@ import { BackEndСtx } from "../../../../context/backend"; //Контекст в
//Работа с аргументами запроса
const useQueryArgs = query => {
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Добавление аргумента запроса
const addArg = useCallback(

View File

@ -10,7 +10,7 @@
import React, { useState, useContext } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Button, Icon } from "@mui/material"; //Интерфейсные компоненты MUI
import { MessagingСtx } from "../../../../context/messaging"; //Контекст сообщений
import { MessagingCtx } from "../../../../context/messaging"; //Контекст сообщений
import { BUTTONS } from "../../../../../app.text"; //Общие текстовые ресурсы приложения
import { P8PDialog } from "../../../../components/p8p_dialog"; //Типовой диалог
import { ARGUMENT_SHAPE } from "../argument/argument"; //Аргумент запроса
@ -27,7 +27,7 @@ const QueryArgsDialog = ({ args, onArgAdd, onArgEdit, onArgRemove, onClose }) =>
const [modArg, setModArg] = useState(null);
//Подключение к контексту сообщений
const { showMsgWarn } = useContext(MessagingСtx);
const { showMsgWarn } = useContext(MessagingCtx);
//Нажатие на кнопку "Закрыть"
const handleClose = () => onClose && onClose();

View File

@ -8,7 +8,7 @@
//---------------------
import { useContext, useCallback } from "react"; //Классы React
import { BackEndСtx } from "../../../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../../../context/backend"; //Контекст взаимодействия с сервером
//-----------
//Тело модуля
@ -17,7 +17,7 @@ import { BackEndСtx } from "../../../../context/backend"; //Контекст в
//Работа с условиями отбора запроса
const useQueryConditions = query => {
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Установка условий отбора в запросе
const setCond = useCallback(

View File

@ -8,7 +8,7 @@
//---------------------
import { useRef, useContext, useCallback, useEffect, useState } from "react"; //Классы React
import { BackEndСtx } from "../../../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../../../context/backend"; //Контекст взаимодействия с сервером
import { object2Base64XML } from "../../../../core/utils"; //Вспомогательные функции
//-----------
@ -30,7 +30,7 @@ const useEntities = (filter, minFilterLen) => {
const [data, setData] = useState(null);
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Обновление данных
const doRefresh = () => setRefresh(true);
@ -81,7 +81,7 @@ const useEntities = (filter, minFilterLen) => {
//Работа с сущностями запроса
const useQueryEntities = query => {
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Добавление сущности в запрос
const addEnt = useCallback(
@ -123,7 +123,7 @@ const useEntityAttrs = (query, entity) => {
const [data, setData] = useState(null);
//Подключение к контексту взаимодействия с сервером
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndСtx);
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
//Обновление данных
const doRefresh = () => setRefresh(true);

View File

@ -10,7 +10,7 @@
import React, { useContext, useState } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Icon, Button } from "@mui/material"; //Интерфейсные элементы
import { MessagingСtx } from "../../../../context/messaging"; //Контекст сообщений приложения
import { MessagingCtx } from "../../../../context/messaging"; //Контекст сообщений приложения
import { P8PEditorSubHeader } from "../../../../components/editors/p8p_editor_sub_header"; //Подзаголовок группы параметров редактора
import { BUTTONS } from "../../../../../app.text"; //Общие текстовые ресурсы
import { ENTITY_SHAPE } from "../entity/entity"; //Описание сущности
@ -34,7 +34,7 @@ const InspectorQueryEntities = ({ query, entity, onOptionsChanged }) => {
const { addEnt, removeEnt } = useQueryEntities(query);
//Подключение к контексту сообщений
const { showMsgWarn } = useContext(MessagingСtx);
const { showMsgWarn } = useContext(MessagingCtx);
//Уведомление родителя об изменении свойств
const notifyOptionsChanged = () => onOptionsChanged && onOptionsChanged();

View File

@ -8,7 +8,7 @@
//---------------------
import { useContext, useCallback } from "react"; //Классы React
import { BackEndСtx } from "../../../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../../../context/backend"; //Контекст взаимодействия с сервером
//-----------
//Тело модуля
@ -17,7 +17,7 @@ import { BackEndСtx } from "../../../../context/backend"; //Контекст в
//Работа со связами запроса
const useQueryRelations = query => {
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Добавление отношения сущностей в запрос
const addRl = useCallback(

View File

@ -10,7 +10,7 @@
import React, { useContext } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Icon, Button, FormControlLabel, Checkbox } from "@mui/material"; //Интерфейсные элементы
import { MessagingСtx } from "../../../../context/messaging"; //Контекст сообщений приложения
import { MessagingCtx } from "../../../../context/messaging"; //Контекст сообщений приложения
import { BUTTONS } from "../../../../../app.text"; //Общие текстовые ресурсы
import { RELATION_SHAPE } from "../relation/relation"; //Описание связи
import { useQueryRelations } from "./hooks"; //Хуки для работы со связями
@ -36,7 +36,7 @@ const STYLES = {
//Компонент инспектора - Связи запроса
const InspectorQueryRelations = ({ query, relation, onOptionsChanged }) => {
//Подключение к контексту сообщений
const { showMsgWarn } = useContext(MessagingСtx);
const { showMsgWarn } = useContext(MessagingCtx);
//Работа со связями на сервере
const { removeRl, setRlMandatory } = useQueryRelations(query);

View File

@ -8,7 +8,7 @@
//---------------------
import { useState, useContext, useEffect, useCallback } from "react"; //Классы React
import { BackEndСtx } from "../../../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../../../context/backend"; //Контекст взаимодействия с сервером
//-----------
//Тело модуля
@ -29,7 +29,7 @@ const useQueries = () => {
const [data, setData] = useState(null);
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Обновление данных
const doRefresh = () => setRefresh(true);

View File

@ -10,7 +10,7 @@
import React, { useState, useContext } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Button, Icon } from "@mui/material"; //Интерфейсные компоненты MUI
import { MessagingСtx } from "../../../../context/messaging"; //Контекст сообщений
import { MessagingCtx } from "../../../../context/messaging"; //Контекст сообщений
import { BUTTONS } from "../../../../../app.text"; //Общие текстовые ресурсы приложения
import { P8PConfigDialog } from "../../../../components/editors/p8p_config_dialog"; //Типовой диалог настройки
import { useQueries } from "./hooks"; //Хуки для работы с запросами
@ -30,7 +30,7 @@ const QueriesManager = ({ current = null, onQuerySelect = null, onCancel = null
const [queries, insertQuery, updateQuery, deleteQuery, setQueryReady, setQueryPbl] = useQueries();
//Подключение к контексту сообщений
const { showMsgWarn } = useContext(MessagingСtx);
const { showMsgWarn } = useContext(MessagingCtx);
//При добавлении запроса
const handleQueryAdd = () => setModQuery(true);

View File

@ -8,7 +8,7 @@
//---------------------
import { useState, useContext, useEffect } from "react"; //Классы React
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { NODE_TYPE } from "./common"; //Общие ресурсы и константы редактора
//---------
@ -119,7 +119,7 @@ const useQuery = query => {
const [querySQL, setQuerySQL] = useState(null);
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Обновление данных
const doRefresh = () => setRefresh(true);

View File

@ -9,7 +9,7 @@
import React, { useState, useContext } from "react"; //Классы React
import { Box, Grid } from "@mui/material"; //Интерфейсные компоненты MUI
import { ApplicationСtx } from "../../context/application"; //Контекст взаимодействия с приложением
import { ApplicationCtx } from "../../context/application"; //Контекст взаимодействия с приложением
import { APP_BAR_HEIGHT } from "../../components/p8p_app_workspace"; //Компоненты рабочего стола
import { P8PEditorToolBar } from "../../components/editors/p8p_editor_toolbar"; //Панель инструментов редактора
import { QueryDiagram } from "./components/query_diagram/query_diagram"; //Диаграмма запроса
@ -61,7 +61,7 @@ const QueryEditor = () => {
const { addRl, removeRl } = useQueryRelations(query);
//Подключение к контексту приложения
const { setAppBarTitle } = useContext(ApplicationСtx);
const { setAppBarTitle } = useContext(ApplicationCtx);
//Выбор сущности
const selectEntity = ent => {

View File

@ -10,7 +10,7 @@
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 { MessagingCtx } 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"; //Типовые стили
@ -56,7 +56,7 @@ const Marks = ({ marks, order, marksLoading, marksInit, onRefresh, onMarkInsert,
const [modMark, setModMark] = useState(null);
//Подключение к контексту сообщений
const { showMsgWarn } = useContext(MessagingСtx);
const { showMsgWarn } = useContext(MessagingCtx);
//Подключение к словарям
const { showMark, showMarkCn, showMarkCnAdd } = useDictionary();

View File

@ -10,7 +10,7 @@
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 { BackEndCtx } from "../../../context/backend"; //Контекст взаимодействия с сервером
import { useConfSectionMarks } from "../hooks"; //Кастомные хуки
import { ActionMessage } from "./action_message"; //Сообщение с действиями
import { Marks } from "./marks"; //Показатели раздела
@ -41,7 +41,7 @@ const Section = ({ section = null }) => {
const [marks, refreshMarks, marksLoading, marksInit] = useConfSectionMarks(section, order.rowOrder, order.columnOrder);
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Добавление показателя
const insertMark = async ({ code, name, row, rowCode, rowVersion, column, columnCode, columnVersion }, cb) => {

View File

@ -11,9 +11,9 @@ import React, { useState, useEffect, useContext, useCallback } from "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 { ApplicationCtx } from "../../../context/application"; //Контекст взаимодействия с приложением
import { BackEndCtx } from "../../../context/backend"; //Контекст взаимодействия с сервером
import { MessagingCtx } from "../../../context/messaging"; //Контекст сообщений
import { useConfSections } from "../hooks"; //Кастомные хуки
import { ActionMessage } from "./action_message"; //Сообщение с действиями
import { SectionTab } from "./section_tab"; //Закладка раздела
@ -57,13 +57,13 @@ const Sections = ({ conf, onSectionChange, onSectionCountChange }) => {
const [confDesc, sections, refreshSections, sectionsLoading, sectionsInit] = useConfSections(conf);
//Подключение к контексту приложения
const { setAppBarTitle } = useContext(ApplicationСtx);
const { setAppBarTitle } = useContext(ApplicationCtx);
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Подключение к контексту сообщений
const { showMsgWarn } = useContext(MessagingСtx);
const { showMsgWarn } = useContext(MessagingCtx);
//Выбор раздела
const selectSection = useCallback(

View File

@ -9,8 +9,8 @@
import { useState, useContext, useEffect } from "react"; //Классы React
import { xml2JSON } from "../../core/utils"; //Вспомогательные функции
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
//-----------
//Тело модуля
@ -34,7 +34,7 @@ const useConfSections = conf => {
const [dataSections, setDataSections] = useState([]);
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Обновление данных
const doRefresh = () => setRefresh(true);
@ -95,7 +95,7 @@ const useConfSectionMarks = (section, rowOrder = 0, columnOrder = 0) => {
const [data, setData] = useState(null);
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Обновление данных
const doRefresh = () => setRefresh(true);
@ -152,7 +152,7 @@ const useConfSectionMarks = (section, rowOrder = 0, columnOrder = 0) => {
//Работа со словарями
const useDictionary = () => {
//Подключение к контексту приложения
const { pOnlineShowDictionary } = useContext(ApplicationСtx);
const { pOnlineShowDictionary } = useContext(ApplicationCtx);
//Выбор строки
const selectRRPRow = (code, version, callBack) => {

View File

@ -11,7 +11,7 @@ import React, { useContext } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Typography, Grid, Paper } from "@mui/material"; //Интерфейсные элементы
import { P8PChart, useP8PChart } from "../../components/p8p_chart"; //График
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
//---------
//Константы
@ -35,7 +35,7 @@ const Chart = ({ title }) => {
const { chart, isDataLoaded } = useP8PChart({ stored: "PKG_P8PANELS_SAMPLES.CHART" });
//Подключение к контексту приложения
const { pOnlineShowUnit } = useContext(ApplicationСtx);
const { pOnlineShowUnit } = useContext(ApplicationCtx);
//Отработка нажатия на график
const handleChartClick = ({ item }) => {

View File

@ -28,7 +28,7 @@ import { formatDateRF, hasValue } from "../../core/utils"; //Вспомогат
import { APP_BAR_HEIGHT } from "../../components/p8p_app_workspace"; //Заголовок страницы
import { P8PCyclogram, useP8PCyclogram } from "../../components/p8p_cyclogram"; //Циклограмма
import { P8P_CYCLOGRAM_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
//---------
//Константы
@ -78,7 +78,7 @@ const CustomTaskDialog = ({ task, ident, onReload, close }) => {
const textType = task.type === 0 ? "Задачи проекта" : task.type === 1 ? "Этап проекта" : "Работа проекта";
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//При необходимости перезагрузить данные
const handleReload = useCallback(() => onReload && onReload(), [onReload]);
@ -230,7 +230,7 @@ const Cyclogram = ({ title }) => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//При подключении компонента к странице
useEffect(() => {

View File

@ -7,12 +7,12 @@
//Подключение библиотек
//---------------------
import React, { useContext } from "react"; //Классы React
import React, { useContext, useState } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Typography, Grid, Stack, Icon, Box, Button } from "@mui/material"; //Интерфейсные элементы
import { Typography, Grid, Stack, Icon, Box, Button, FormControlLabel, Checkbox } from "@mui/material"; //Интерфейсные элементы
import { P8PDataGrid, P8P_DATA_GRID_SIZE, useP8PDataGrid } from "../../components/p8p_data_grid"; //Таблица данных
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
import { APP_STYLES } from "../../../app.styles"; //Типовые стили
//---------
@ -84,14 +84,18 @@ export const groupCellRender = () => ({ cellStyle: { padding: "2px" } });
//Пример: Таблица данных "P8PDataGrid"
const DataGrid = ({ title }) => {
//Собственное состояние - использование кнопки догрузки данных
const [useMoreButton, setUseMoreButton] = useState(false);
//Собственное состояние - таблица данных
const { dataGrid, isDataLoaded, handleFilterChanged, handleOrderChanged, handlePageChange } = useP8PDataGrid({
const { dataGrid, isDataLoaded, handleFilterChanged, handleOrderChanged, handlePageChange, handlePagesCountChanged } = useP8PDataGrid({
stored: "PKG_P8PANELS_SAMPLES.DATA_GRID",
pageSize: DATA_GRID_PAGE_SIZE
pageSize: DATA_GRID_PAGE_SIZE,
storedArgs: { NUSE_MORE_BUTTON: useMoreButton ? 1 : 0 }
});
//Подключение к контексту приложения
const { pOnlineShowDocument } = useContext(ApplicationСtx);
const { pOnlineShowDocument } = useContext(ApplicationCtx);
//При нажатии на копку контрагента
const handleAgnButtonClicked = agnCode => pOnlineShowDocument({ unitCode: "AGNLIST", document: agnCode, inRnParameter: "in_AGNABBR" });
@ -102,6 +106,11 @@ const DataGrid = ({ title }) => {
<Typography sx={STYLES.TITLE} variant={"h6"}>
{title}
</Typography>
<FormControlLabel
sx={STYLES.CONTROL}
control={<Checkbox onChange={() => setUseMoreButton(!useMoreButton)} />}
label="Отображать кнопку догрузки"
/>
<Grid container spacing={1} pt={5}>
<Grid item xs={12}>
<Box p={5} display="flex" justifyContent="center" alignItems="center">
@ -121,6 +130,7 @@ const DataGrid = ({ title }) => {
<Button onClick={() => handleAgnButtonClicked(row.SAGNABBR)}>Показать в разделе</Button>
)}
onPageChanged={handlePageChange}
onPagesCountChanged={handlePagesCountChanged}
/>
) : null}
</Box>

View File

@ -14,7 +14,7 @@ import { formatDateRF, hasValue } from "../../core/utils"; //Вспомогат
import { APP_BAR_HEIGHT } from "../../components/p8p_app_workspace"; //Заголовок страницы
import { P8PGantt, useP8PGantt } from "../../components/p8p_gantt"; //Диаграмма Ганта
import { P8P_GANTT_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
//---------
//Константы
@ -110,7 +110,7 @@ const Gantt = ({ title }) => {
});
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Изменение данных диаграммы
const modifyData = useCallback(

View File

@ -10,7 +10,7 @@
import React, { useContext } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Typography, Stack, Divider } from "@mui/material"; //Интерфейсные элементы
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { MessagingCtx } from "../../context/messaging"; //Контекст сообщений
import { P8P_INDICATOR_VARIANT, P8P_INDICATOR_STATE, P8PIndicator, useP8PIndicator } from "../../components/p8p_indicator"; //Индикатор
//---------
@ -34,7 +34,7 @@ const Indicator = ({ title }) => {
const { indicator, isDataLoaded } = useP8PIndicator({ stored: "PKG_P8PANELS_SAMPLES.INDICATOR" });
//Подключение к контексту сообщений
const { showMsgInfo } = useContext(MessagingСtx);
const { showMsgInfo } = useContext(MessagingCtx);
//Генерация содержимого
return (

View File

@ -10,7 +10,7 @@
import React, { useContext } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Typography, Button } from "@mui/material"; //Интерфейсные элементы
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { MessagingCtx } from "../../context/messaging"; //Контекст сообщений
//---------
//Константы
@ -29,7 +29,7 @@ const STYLES = {
//Пример: Индикатор процесса
const Loader = ({ title }) => {
//Подключение к контексту сообщений
const { showLoader, hideLoader } = useContext(MessagingСtx);
const { showLoader, hideLoader } = useContext(MessagingCtx);
//Генерация содержимого
return (

View File

@ -10,7 +10,7 @@
import React, { useContext, useState } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Typography, Divider, Button } from "@mui/material"; //Интерфейсные элементы
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { MessagingCtx } from "../../context/messaging"; //Контекст сообщений
//---------
//Константы
@ -33,7 +33,7 @@ const Messages = ({ title }) => {
const [state, setState] = useState({ inlineErr: true, inlineWarn: true, inlineInfo: true });
//Подключение к контексту сообщений
const { showMsgErr, showMsgWarn, showMsgInfo, InlineMsgErr, InlineMsgInfo, InlineMsgWarn } = useContext(MessagingСtx);
const { showMsgErr, showMsgWarn, showMsgInfo, InlineMsgErr, InlineMsgInfo, InlineMsgWarn } = useContext(MessagingCtx);
//Генерация содержимого
return (

View File

@ -10,9 +10,9 @@
import React, { useEffect, useContext, useCallback, useState } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Typography, Grid, List, ListItemButton, ListItem, ListItemText, IconButton, Icon, Button, TextField, Box } from "@mui/material"; //Интерфейсные элементы
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { BackEndCtx } from "../../context/backend"; //Контекст взаимодействия с сервером
import { MessagingCtx } from "../../context/messaging"; //Контекст сообщений
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
//---------
//Константы
@ -41,13 +41,13 @@ const Mui = ({ title }) => {
const [agentForm, setAgentForm] = useState({ agnAbbr: "", agnName: "" });
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
const { executeStored } = useContext(BackEndCtx);
//Подключение к контексту сообщений
const { showMsgWarn } = useContext(MessagingСtx);
const { showMsgWarn } = useContext(MessagingCtx);
//Подключение к контексту приложения
const { pOnlineShowDocument } = useContext(ApplicationСtx);
const { pOnlineShowDocument } = useContext(ApplicationCtx);
//Загрузка списка контрагентов
const agentsGet = useCallback(async () => {

View File

@ -1,6 +1,6 @@
/*
Парус 8 - Панели мониторинга - Примеры для разработчиков
Пример: API для взаимодействия с "ПАРУС 8 Онлайн"
Пример: API для взаимодействия с "ПАРУС 8 Онлайн" и ядром фреймворка
*/
//---------------------
@ -10,7 +10,7 @@
import React, { useState, useContext } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Typography, Button, Divider } from "@mui/material"; //Интерфейсные элементы
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
//---------
//Константы
@ -27,13 +27,20 @@ const STYLES = {
//Тело модуля
//-----------
//Пример: API для взаимодействия с "ПАРУС 8 Онлайн"
//Пример: API для взаимодействия с "ПАРУС 8 Онлайн" и ядром фреймворка
const P8Online = ({ title }) => {
//Собственное состояние
//Собственное состояние - флаг отображения пользовательского текста заголовка
const [titleCustom, setTitleCustom] = useState(false);
//Собственное состояние - флаг отображения заголовка
const [titleVisible, setTitleVisible] = useState(true);
//Собственное состояние - выбранный контрагент
const [agent, setAgent] = useState("");
//Подключение к контексту приложения
const { pOnlineShowUnit, pOnlineShowTab, pOnlineShowDocument, pOnlineShowDictionary } = useContext(ApplicationСtx);
const { pOnlineShowUnit, pOnlineShowTab, pOnlineShowDocument, pOnlineShowDictionary, setAppBarTitle, setAppBarShow, findPanelByName } =
useContext(ApplicationCtx);
//Генерация содержимого
return (
@ -41,20 +48,44 @@ const P8Online = ({ title }) => {
<Typography sx={STYLES.TITLE} variant={"h6"}>
{title}
</Typography>
{/* Изменение текста заголовка */}
{titleVisible && (
<>
<Button
variant="contained"
onClick={() => {
setAppBarTitle(titleCustom ? "" : "Пользовательский текст");
setTitleCustom(!titleCustom);
}}
>
{`${titleCustom ? "Восстановить" : "Изменить"} текст заголовка`}
</Button>
<Divider sx={STYLES.DIVIDER} />
</>
)}
{/* Сокрытие/отображение заголовка */}
<Button
variant="contained"
onClick={() => {
setAppBarShow(!titleVisible);
setTitleVisible(!titleVisible);
}}
>
{`${titleVisible ? "Скрыть" : "Отобразить"} заголовок`}
</Button>
<Divider sx={STYLES.DIVIDER} />
{/* Поиск панели */}
<Button variant="contained" onClick={() => console.log(findPanelByName("Samples"))}>
Вывести в консоль сведения о данной панели
</Button>
<Divider sx={STYLES.DIVIDER} />
{/* Открыть новую закладку */}
<Button variant="contained" onClick={() => pOnlineShowTab({ caption: "PARUS.COM", url: "https://www.parus.com" })}>
Открыть закладку
</Button>
<Divider sx={STYLES.DIVIDER} />
{/* Открыть раздел */}
<Button
variant="contained"
onClick={() => {
pOnlineShowUnit({
unitCode: "Contracts"
});
}}
>
<Button variant="contained" onClick={() => pOnlineShowUnit({ unitCode: "Contracts" })}>
Открыть раздел Договоры
</Button>
<Divider sx={STYLES.DIVIDER} />
@ -64,12 +95,7 @@ const P8Online = ({ title }) => {
onClick={() => {
pOnlineShowDictionary({
unitCode: "AGNLIST",
inputParameters: [
{
name: "in_AGNABBR",
value: agent
}
],
inputParameters: [{ name: "in_AGNABBR", value: agent }],
callBack: res => (res.success === true ? setAgent(res.outParameters.out_AGNABBR) : null)
});
}}
@ -82,13 +108,7 @@ const P8Online = ({ title }) => {
<Divider sx={STYLES.DIVIDER} />
<Button
variant="contained"
onClick={() => {
pOnlineShowDocument({
unitCode: "AGNLIST",
document: agent,
inRnParameter: "in_AGNABBR"
});
}}
onClick={() => pOnlineShowDocument({ unitCode: "AGNLIST", document: agent, inRnParameter: "in_AGNABBR" })}
>{`Показать контрагента "${agent}"`}</Button>
</>
) : null}

View File

@ -27,7 +27,7 @@ import { Indicator } from "./indicator"; //Пример: Индикатор "P8P
//Режимы
const MODES = {
P8ONLINE: { name: "P8ONLINE", caption: 'API для взаимодействия с "ПАРУС 8 Онлайн"', component: P8Online },
P8ONLINE: { name: "P8ONLINE", caption: 'API для взаимодействия с "ПАРУС 8 Онлайн" и ядром фреймворка', component: P8Online },
MUI: { name: "MUI", caption: "Компоненты MUI", component: Mui },
MESSAGES: { name: "MESSAGES", caption: "Сообщения", component: Messages },
LOADER: { name: "LOADER", caption: "Индикатор процесса", component: Loader },

View File

@ -343,7 +343,15 @@ create or replace package PKG_P8PANELS_QE_BASE as
SQRY out varchar2, -- SQL-выражение
SQRY_BND out varchar2, -- SQL-выражение с подставленными значениями аргументов
SQRY_MSG out varchar2 -- Сообщение при формировании SQL-выражения (предупреждения и ошибки формирования)
);
);
/* Исполнение запроса */
procedure QUERY_EXECUTE
(
NRN in number, -- Рег. номер запроса
CARGS in clob, -- Значения аргументов
CDATA out clob -- Данные
);
end PKG_P8PANELS_QE_BASE;
/
@ -492,7 +500,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
if (NDATA_TYPE is null) then
P_EXCEPTION(0, 'Не указан тип данных аргумента.');
end if;
if (NDATA_TYPE not in (PKG_STD.DATA_TYPE_STR, PKG_STD.DATA_TYPE_NUM, PKG_STD.DATA_TYPE_DATE)) then
if (NDATA_TYPE not in (PKG_STD.DATA_TYPE_STR(), PKG_STD.DATA_TYPE_NUM(), PKG_STD.DATA_TYPE_DATE())) then
P_EXCEPTION(0,
'Аргументы типа "%s" не поддерживаются.',
COALESCE(TO_CHAR(NDATA_TYPE), '<НЕ УКАЗАН>'));
@ -2792,7 +2800,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
'" отсутствует в составе его аргументов.',
BCLEAR_QRY => false);
end if;
/* Ищем следующу */
/* Ищем следующую */
SCOND_VAR := PKG_CONTVARLOC.NEXT_(RCONTAINER => RCOND_VARS, SNAME => SCOND_VAR);
end loop;
end if;
@ -2873,7 +2881,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
if (RENTS(I).RATTRS(J).NSHOW = 1) then
if (RENTS(I).RATTRS(J).SALIAS is null) then
P_EXCEPTION(0,
'Для атрибута ("%s") не задан севдоним.',
'Для атрибута ("%s") не задан псевдоним.',
RENTS(I).RATTRS(J).SID);
end if;
SFIELD := RENTS(I).RATTRS(J).SID || ' "' || RENTS(I).RATTRS(J).SALIAS || '", ';
@ -2991,15 +2999,15 @@ create or replace package body PKG_P8PANELS_QE_BASE as
loop
begin
case
when ROPT.RARGS(I).NDATA_TYPE = PKG_STD.DATA_TYPE_STR then
when ROPT.RARGS(I).NDATA_TYPE = PKG_STD.DATA_TYPE_STR() then
SQRY_BND := PKG_SQL_BUILD.VAR_REPLACE_TO_STR(SSQL => SQRY_BND,
SNAME => ROPT.RARGS(I).SNAME,
SVALUE => ROPT.RARGS(I).SVALUE);
when ROPT.RARGS(I).NDATA_TYPE = PKG_STD.DATA_TYPE_NUM then
when ROPT.RARGS(I).NDATA_TYPE = PKG_STD.DATA_TYPE_NUM() then
SQRY_BND := PKG_SQL_BUILD.VAR_REPLACE_TO_NUM(SSQL => SQRY_BND,
SNAME => ROPT.RARGS(I).SNAME,
NVALUE => TO_NUMBER(ROPT.RARGS(I).SVALUE));
when ROPT.RARGS(I).NDATA_TYPE = PKG_STD.DATA_TYPE_DATE then
when ROPT.RARGS(I).NDATA_TYPE = PKG_STD.DATA_TYPE_DATE() then
SQRY_BND := PKG_SQL_BUILD.VAR_REPLACE_TO_DATE(SSQL => SQRY_BND,
SNAME => ROPT.RARGS(I).SNAME,
DVALUE => TO_DATE(ROPT.RARGS(I).SVALUE, 'yyyy-mm-dd'));
@ -3053,6 +3061,191 @@ create or replace package body PKG_P8PANELS_QE_BASE as
PKG_STATE.DIAGNOSTICS_STACKED();
ADD_QRY_MSG(SMESSAGE => PKG_STATE.SQL_ERRM(), BCLEAR_QRY => false);
end QUERY_QRY_BUILD;
/* Исполнение запроса */
procedure QUERY_EXECUTE
(
NRN in number, -- Рег. номер запроса
CARGS in clob, -- Значения аргументов
CDATA out clob -- Данные
)
is
RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса
ICURSOR integer; -- Курсор для исполнения запроса
ROPT TOPT; --
RARGS TARGS; -- Полученные аргументы
NARG PKG_STD.TNUMBER; --
SARG_VALUE PKG_STD.TLSTRING; --
RCUR_COLS PKG_CONTUNVLOC.TCONTAINER; -- Описание колонок запроса
SCOL_VALUE PKG_STD.TLSTRING; --
NCOL_VALUE PKG_STD.TLNUMBER; --
DCOL_VALUE PKG_STD.TLDATE; --
TSCOL_VALUE timestamp; --
TZCOL_VALUE timestamp with time zone; --
NROW PKG_STD.TNUMBER := 0; --
begin
/* Читаем описание запроса */
RQ := QUERY_GET(NRN => NRN);
/* Проверим, что существует SQL-выражение */
if (RQ.QRY is null) then
P_EXCEPTION(0, 'Для запроса не сформировано SQL-выражение.');
end if;
/* Читаем настройки запроса */
ROPT := QUERY_OPT_FROM_XML(CXML => RQ.OPT);
/* Читаем полученные аргументы */
RARGS := TARGS_FROM_XML(CXML => CARGS);
if (RARGS.COUNT > 0) then
for I in RARGS.FIRST .. RARGS.LAST
loop
DBMS_OUTPUT.PUT_LINE(RARGS(I).SNAME || ' = ' || RARGS(I).SVALUE);
end loop;
else
DBMS_OUTPUT.PUT_LINE('Нет аргументов');
end if;
/* Если для запроса заявлены аргументы, то проверим, что переданы значения для обязательных */
if (ROPT.RARGS.COUNT > 0) then
for I in ROPT.RARGS.FIRST .. ROPT.RARGS.LAST
loop
if (ROPT.RARGS(I).NMANDATORY = 1) then
NARG := TARGS_INDEX_BY_NAME(RARGS => RARGS, SNAME => ROPT.RARGS(I).SNAME);
if ((NARG is null) or (RARGS(NARG).SVALUE is null)) then
P_EXCEPTION(0,
'Не указано значение обязательного аргумента запроса "%s".',
ROPT.RARGS(I).SNAME);
end if;
end if;
end loop;
end if;
/* Разбираем его */
ICURSOR := PKG_SQL_DML.OPEN_CURSOR(SWHAT => 'SELECT');
PKG_SQL_DML.PARSE(ICURSOR => ICURSOR, SQUERY => RQ.QRY);
/* Получим описание колонок */
PKG_SQL_DML.DESCRIBE_COLUMNS(ICURSOR => ICURSOR, RDESC_CONTAINER => RCUR_COLS);
if (PKG_CONTUNVLOC.COUNT_(RCONTAINER => RCUR_COLS) > 0) then
/* Обходим их */
for I in PKG_CONTUNVLOC.FIRST_(RCONTAINER => RCUR_COLS) .. PKG_CONTUNVLOC.LAST_(RCONTAINER => RCUR_COLS)
loop
/* Определяем типы данных колонок курсора */
case PKG_CONTUNVLOC.GETN(RCONTAINER => RCUR_COLS, IROWID => I, SCOLUMN_NAME => 'DATA_TYPE')
when PKG_STD.DATA_TYPE_STR() then
PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR, IPOSITION => I);
when PKG_STD.DATA_TYPE_NUM() then
PKG_SQL_DML.DEFINE_COLUMN_NUM(ICURSOR => ICURSOR, IPOSITION => I);
when PKG_STD.DATA_TYPE_DATE() then
PKG_SQL_DML.DEFINE_COLUMN_DATE(ICURSOR => ICURSOR, IPOSITION => I);
when PKG_STD.DATA_TYPE_TS() then
PKG_SQL_DML.DEFINE_COLUMN_TS(ICURSOR => ICURSOR, IPOSITION => I);
when PKG_STD.DATA_TYPE_TZ() then
PKG_SQL_DML.DEFINE_COLUMN_TZ(ICURSOR => ICURSOR, IPOSITION => I);
else
P_EXCEPTION(0,
'Тип данных "%s" не поддерживается.',
TO_CHAR(PKG_CONTUNVLOC.GETN(RCONTAINER => RCUR_COLS, IROWID => I, SCOLUMN_NAME => 'DATA_TYPE')));
end case;
DBMS_OUTPUT.PUT_LINE(I || ' - ' ||
PKG_CONTUNVLOC.GETS(RCONTAINER => RCUR_COLS, IROWID => I, SCOLUMN_NAME => 'COLUMN_NAME') ||
' - ' ||
PKG_CONTUNVLOC.GETS(RCONTAINER => RCUR_COLS, IROWID => I, SCOLUMN_NAME => 'NATIVE_NAME') ||
' - ' ||
PKG_CONTUNVLOC.GETN(RCONTAINER => RCUR_COLS, IROWID => I, SCOLUMN_NAME => 'DATA_TYPE'));
end loop;
else
P_EXCEPTION(0, 'Для запроса не определен набор полей.');
end if;
/* Делаем подстановку значений аргументов, если они заявлены в запросе */
if (ROPT.RARGS.COUNT > 0) then
/* Обходим формальные аргументы запроса */
for I in ROPT.RARGS.FIRST .. ROPT.RARGS.LAST
loop
begin
/* Ищем значение соответствующего фактического аргумента */
NARG := TARGS_INDEX_BY_NAME(RARGS => RARGS, SNAME => ROPT.RARGS(I).SNAME);
if (NARG is not null) then
SARG_VALUE := RARGS(NARG).SVALUE;
else
SARG_VALUE := null;
end if;
/* Подставляем в запрос */
case ROPT.RARGS(I).NDATA_TYPE
when PKG_STD.DATA_TYPE_STR() then
PKG_SQL_DML.BIND_VARIABLE_STR(ICURSOR => ICURSOR, SNAME => ROPT.RARGS(I).SNAME, SVALUE => SARG_VALUE);
when PKG_STD.DATA_TYPE_NUM() then
PKG_SQL_DML.BIND_VARIABLE_NUM(ICURSOR => ICURSOR,
SNAME => ROPT.RARGS(I).SNAME,
NVALUE => TO_NUMBER(SARG_VALUE));
when PKG_STD.DATA_TYPE_DATE() then
PKG_SQL_DML.BIND_VARIABLE_DATE(ICURSOR => ICURSOR,
SNAME => ROPT.RARGS(I).SNAME,
DVALUE => TO_DATE(SARG_VALUE, 'yyyy-mm-dd'));
else
P_EXCEPTION(0,
'Тип данных "%s" не поддерживается.',
TO_CHAR(ROPT.RARGS(I).NDATA_TYPE));
end case;
exception
when others then
PKG_STATE.DIAGNOSTICS_STACKED();
P_EXCEPTION(0, 'Ошибка подстановки аргументов: %s.', PKG_STATE.SQL_ERRM());
end;
end loop;
end if;
/* Делаем выборку */
if (PKG_SQL_DML.EXECUTE(ICURSOR => ICURSOR) = 0) then
null;
end if;
/* Обходим выборку */
while (PKG_SQL_DML.FETCH_ROWS(ICURSOR => ICURSOR) > 0)
loop
/* Инкремент счетчика строк */
NROW := NROW + 1;
DBMS_OUTPUT.PUT_LINE('===== СТРОКА # ' || TO_CHAR(NROW) || '=====');
/* Обходим колонки */
for I in PKG_CONTUNVLOC.FIRST_(RCONTAINER => RCUR_COLS) .. PKG_CONTUNVLOC.LAST_(RCONTAINER => RCUR_COLS)
loop
/* Сброс значений предыдущей колонки */
SCOL_VALUE := null;
NCOL_VALUE := null;
DCOL_VALUE := null;
TSCOL_VALUE := null;
TZCOL_VALUE := null;
/* Определяем типы данных колонок курсора */
case PKG_CONTUNVLOC.GETN(RCONTAINER => RCUR_COLS, IROWID => I, SCOLUMN_NAME => 'DATA_TYPE')
when PKG_STD.DATA_TYPE_STR() then
PKG_SQL_DML.COLUMN_VALUE_STR(ICURSOR => ICURSOR, IPOSITION => I, SVALUE => SCOL_VALUE);
when PKG_STD.DATA_TYPE_NUM() then
PKG_SQL_DML.COLUMN_VALUE_NUM(ICURSOR => ICURSOR, IPOSITION => I, NVALUE => NCOL_VALUE);
when PKG_STD.DATA_TYPE_DATE() then
PKG_SQL_DML.COLUMN_VALUE_DATE(ICURSOR => ICURSOR, IPOSITION => I, DVALUE => DCOL_VALUE);
when PKG_STD.DATA_TYPE_TS() then
PKG_SQL_DML.COLUMN_VALUE_TS(ICURSOR => ICURSOR, IPOSITION => I, TSVALUE => TSCOL_VALUE);
when PKG_STD.DATA_TYPE_TZ() then
PKG_SQL_DML.COLUMN_VALUE_TZ(ICURSOR => ICURSOR, IPOSITION => I, TZVALUE => TZCOL_VALUE);
else
P_EXCEPTION(0,
'Тип данных "%s" не поддерживается.',
TO_CHAR(PKG_CONTUNVLOC.GETN(RCONTAINER => RCUR_COLS, IROWID => I, SCOLUMN_NAME => 'DATA_TYPE')));
end case;
DBMS_OUTPUT.PUT_LINE(I || ' - ' ||
PKG_CONTUNVLOC.GETS(RCONTAINER => RCUR_COLS, IROWID => I, SCOLUMN_NAME => 'COLUMN_NAME') ||
' - ' ||
PKG_CONTUNVLOC.GETS(RCONTAINER => RCUR_COLS, IROWID => I, SCOLUMN_NAME => 'NATIVE_NAME') ||
' - ' ||
PKG_CONTUNVLOC.GETN(RCONTAINER => RCUR_COLS, IROWID => I, SCOLUMN_NAME => 'DATA_TYPE') ||
' - ' ||
NVL(SCOL_VALUE,
NVL(TO_CHAR(NCOL_VALUE),
NVL(TO_CHAR(DCOL_VALUE), NVL(TO_CHAR(TSCOL_VALUE), TO_CHAR(TZCOL_VALUE))))));
end loop;
end loop;
/* Освобождаем курсор */
PKG_SQL_DML.CLOSE_CURSOR(ICURSOR => ICURSOR);
exception
when others then
if (PKG_SQL_DML.IS_OPEN(ICURSOR => ICURSOR)) then
PKG_SQL_DML.CLOSE_CURSOR(ICURSOR => ICURSOR);
end if;
raise;
end QUERY_EXECUTE;
end PKG_P8PANELS_QE_BASE;
/

View File

@ -25,6 +25,7 @@ create or replace package PKG_P8PANELS_SAMPLES as
(
NPAGE_NUMBER in number, -- Номер страницы (игнорируется при NPAGE_SIZE=0)
NPAGE_SIZE in number, -- Количество записей на странице (0 - все)
NUSE_MORE_BUTTON in number, -- Использовать кнопку догрузки данных (0 - нет, 1 - да)
CFILTERS in clob, -- Фильтры
CORDERS in clob, -- Сортировки
NINCLUDE_DEF in number, -- Признак включения описания колонок таблицы в ответ
@ -257,6 +258,7 @@ create or replace package body PKG_P8PANELS_SAMPLES as
(
NPAGE_NUMBER in number, -- Номер страницы (игнорируется при NPAGE_SIZE=0)
NPAGE_SIZE in number, -- Количество записей на странице (0 - все)
NUSE_MORE_BUTTON in number, -- Использовать кнопку догрузки данных (0 - нет, 1 - да)
CFILTERS in clob, -- Фильтры
CORDERS in clob, -- Сортировки
NINCLUDE_DEF in number, -- Признак включения описания колонок таблицы в ответ
@ -360,9 +362,9 @@ create or replace package body PKG_P8PANELS_SAMPLES as
/* Инициализируем таблицу данных */
RDG := PKG_P8PANELS_VISUAL.TDG_MAKE(BFIXED_HEADER => true,
NFIXED_COLUMNS => 2,
NPAGES_COUNT => 10,
SPAGES_POSITION => PKG_P8PANELS_VISUAL.STABLE_PAGES_POSITION_BOTTOM,
SPAGES_ALIGN => PKG_P8PANELS_VISUAL.STABLE_PAGES_ALIGN_RIGHT);
SPAGES_ALIGN => PKG_P8PANELS_VISUAL.STABLE_PAGES_ALIGN_RIGHT,
BMORE_PAGES => case NUSE_MORE_BUTTON when 1 then true else false end);
/* Описываем колонки таблицы данных */
PKG_P8PANELS_VISUAL.TDG_ADD_COL_DEF(RDATA_GRID => RDG,
SNAME => 'SAGNABBR',
@ -522,11 +524,13 @@ create or replace package body PKG_P8PANELS_SAMPLES as
raise;
end;
/* Определяем количество отображаемых страниц */
NPAGES_COUNT := PAGES_COUNT_GET(NCOMPANY => NCOMPANY, RDG => RDG, RFILTERS => RF, NPAGE_SIZE => NPAGE_SIZE);
/* Если количество страниц определено */
if (NPAGES_COUNT is not null) then
/* Устанавливаем количество отображаемых страниц */
PKG_P8PANELS_VISUAL.TDG_PAGES_COUNT_SET(RDATA_GRID => RDG, NPAGES_COUNT => NPAGES_COUNT);
if (NUSE_MORE_BUTTON = 0) then
NPAGES_COUNT := PAGES_COUNT_GET(NCOMPANY => NCOMPANY, RDG => RDG, RFILTERS => RF, NPAGE_SIZE => NPAGE_SIZE);
/* Если количество страниц определено */
if (NPAGES_COUNT is not null) then
/* Устанавливаем количество отображаемых страниц */
PKG_P8PANELS_VISUAL.TDG_PAGES_COUNT_SET(RDATA_GRID => RDG, NPAGES_COUNT => NPAGES_COUNT);
end if;
end if;
/* Сериализуем описание */
COUT := PKG_P8PANELS_VISUAL.TDG_TO_XML(RDATA_GRID => RDG, NINCLUDE_DEF => NINCLUDE_DEF);

View File

@ -458,7 +458,7 @@ create or replace package PKG_P8PANELS_VISUAL as
NPAGES_COUNT in number := 0, -- Количество страниц
SPAGES_ALIGN in varchar2 := null, -- Область блока страниц по вертикали (см. константы STABLE_PAGES_ALIGN_*)
SPAGES_POSITION in varchar2 := null, -- Область блока страниц по горизонтали (см. константы STABLE_PAGES_POSITION_*)
BMORE_PAGES in boolean := true -- Отображение кнопки догрузки данных (true - отображать, false - не отображать)
BMORE_PAGES in boolean := false -- Отображение кнопки догрузки данных (true - отображать, false - не отображать)
) return TDG; -- Результат работы
/* Установка количества страниц таблицы данных */
@ -1453,7 +1453,7 @@ create or replace package body PKG_P8PANELS_VISUAL as
NPAGES_COUNT in number := 0, -- Количество страниц
SPAGES_ALIGN in varchar2 := null, -- Область блока страниц по вертикали (см. константы STABLE_PAGES_ALIGN_*)
SPAGES_POSITION in varchar2 := null, -- Область блока страниц по горизонтали (см. константы STABLE_PAGES_POSITION_*)
BMORE_PAGES in boolean := true -- Отображение кнопки догрузки данных (true - отображать, false - не отображать)
BMORE_PAGES in boolean := false -- Отображение кнопки догрузки данных (true - отображать, false - не отображать)
) return TDG -- Результат работы
is
RRES TDG; -- Буфер для результата
@ -1470,7 +1470,7 @@ create or replace package body PKG_P8PANELS_VISUAL as
RRES.SPAGES_ALIGN := COALESCE(SPAGES_ALIGN, STABLE_PAGES_ALIGN_RIGHT);
RRES.SPAGES_POSITION := COALESCE(SPAGES_POSITION, STABLE_PAGES_POSITION_BOTTOM);
else
RRES.BMORE_PAGES := COALESCE(BMORE_PAGES, true);
RRES.BMORE_PAGES := COALESCE(BMORE_PAGES, false);
RRES.SPAGES_ALIGN := SPAGES_ALIGN;
RRES.SPAGES_POSITION := SPAGES_POSITION;
end if;
@ -1491,11 +1491,6 @@ create or replace package body PKG_P8PANELS_VISUAL as
begin
/* Обновляем значение количества страниц */
RDATA_GRID.NPAGES_COUNT := COALESCE(NPAGES_COUNT, 0);
/* Если количество страниц меньше или равно нулю */
if (RDATA_GRID.NPAGES_COUNT <= 0) then
/* Обновляем доступность загрузку по кнопке */
RDATA_GRID.BMORE_PAGES := true;
end if;
end TDG_PAGES_COUNT_SET;
/* Поиск описания колонки в таблице данных по наименованию */

View File

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 86 KiB

View File

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 101 KiB

View File

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

View File

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

View File

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 114 KiB

View File

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

View File

Before

Width:  |  Height:  |  Size: 172 KiB

After

Width:  |  Height:  |  Size: 172 KiB

View File

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Some files were not shown because too many files have changed in this diff Show More