forked from CITKParus/P8-Panels
Compare commits
No commits in common. "main" and "main" have entirely different histories.
394
README.md
394
README.md
@ -111,10 +111,9 @@ git clone https://git.citpb.ru/CITKParus/P8-Panels.git
|
|||||||
|
|
||||||
При компиляции учитывайте следующее:
|
При компиляции учитывайте следующее:
|
||||||
|
|
||||||
- объекты `PKG_P8PANELS`, `PKG_P8PANELS_BASE`, `PKG_P8PANELS_VISUAL`, `PKG_P8PANELS_SETTINGS`, `P8PNL_SETTINGS` и `P8PNL_SELECTLIST` и - обязательны к компиляции. **Это ядро серверной части расширения. Без этих объектов его работа невозможна. Все остальные, перечисленные ниже объекты серверной части - прикладные, не обязательны к компиляции и на функционирование непосредственно фреймворка влияния не оказывают.**
|
- объекты `PKG_P8PANELS`, `PKG_P8PANELS_BASE`, `PKG_P8PANELS_VISUAL` и `P8PNL_SELECTLIST` - обязательны к компиляции. **Это ядро серверной части расширения. Без этих объектов его работа невозможна. Все остальные, перечисленные ниже объекты серверной части - прикладные, не обязательны к компиляции и на функционирование непосредственно фреймворка влияния не оказывают.**
|
||||||
- объекты `PKG_P8PANELS_SAMPLES`, `P8PNL_SMPL_CYCLOGRAM` и `P8PNL_SMPL_GANTT` - обеспечивают работу панели "Samples" ("Примеры для разработчиков"). Это абстрактный набор примеров применения фреймворка, не привязанный жестко к комплектации Системы. Должен откомпилироваться практически в любой комплектации Системы (единственное требование - наличие словаря "Контрагенты").
|
- объекты `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_PROJECTS`, `P8PNL_JB_JOBS`, `P8PNL_JB_JOBSPREV`, `P8PNL_JB_PERIODS`, `P8PNL_JB_PRJCTS` и `P8PNL_JB_PRMS` - могут быть откомпилированы в Системе, имеющей в комлектации приложения "Планирование и учёт в проектах" и "Управление закупками, складом и реализацией". Эти объекты отвечают за работу панелей группы "Планирование и учёт в проектах" ("PrjFin" - "Экономика проектов", "PrjJobs" - "Работы проектов", "PrjGraph" - "Графики проектов", "PrjInfo" - "Информация о проектах"). Компилируйте только если комлектация Системы включает указанные приложения.
|
||||||
- объекты `I_P8PNL_*` - содержат индексы для загружаемых таблиц, **перед созданием индексов необходимо заменить в тексте файла шаблон `<ИМЯ_ИНДЕКСНОГО_ТАБЛИЧНОГО_ПРОСТРАНСТВА>` на имя индексного табличного пространства экземпляра БД**.
|
|
||||||
- объект `PKG_P8PANELS_CLNTTSKBRD` - может быть откомпилирован в Системе, имеющей в комлектации приложение "Управление деловыми процессами". Этот объект отвечает за работу панелей группы "Управление деловыми процессами" ("ClntTaskBoard" - "Доски задач"). Компилируйте только если комлектация Системы включает указанное приложение.
|
- объект `PKG_P8PANELS_CLNTTSKBRD` - может быть откомпилирован в Системе, имеющей в комлектации приложение "Управление деловыми процессами". Этот объект отвечает за работу панелей группы "Управление деловыми процессами" ("ClntTaskBoard" - "Доски задач"). Компилируйте только если комлектация Системы включает указанное приложение.
|
||||||
- объект `PKG_P8PANELS_MECHREC` - может быть откомпилирован в Системе, имеющей в комлектации приложение "Планирование и учёт в дискретном производстве". Этот объект отвечает за работу панелей группы "Планирование и учёт в дискретном производстве" ("MechRecCostProdPlans" - "Производственная программа", "MechRecDeptCostProdPlans" - "Производственный план цеха", "MechRecCostJobsManage" - "Выдача сменного задания", "MechRecCostJobsManageMP" - "Выдача сменного задания на участок", "MechRecDeptCostJobs" - "Загрузка цеха", "MechRecAssemblyMon" - "Мониторинг сборки изделий"). Компилируйте только если комлектация Системы включает указанное приложение.
|
- объект `PKG_P8PANELS_MECHREC` - может быть откомпилирован в Системе, имеющей в комлектации приложение "Планирование и учёт в дискретном производстве". Этот объект отвечает за работу панелей группы "Планирование и учёт в дискретном производстве" ("MechRecCostProdPlans" - "Производственная программа", "MechRecDeptCostProdPlans" - "Производственный план цеха", "MechRecCostJobsManage" - "Выдача сменного задания", "MechRecCostJobsManageMP" - "Выдача сменного задания на участок", "MechRecDeptCostJobs" - "Загрузка цеха", "MechRecAssemblyMon" - "Мониторинг сборки изделий"). Компилируйте только если комлектация Системы включает указанное приложение.
|
||||||
- объект `PKG_P8PANELS_EQUIPSRV` - может быть откомпилирован в Системе, имеющей в комлектации приложение "Управление техническим обслуживанием и ремонтами". Этот объект отвечает за работу панелей группы "Управление техническим обслуживанием и ремонтами" ("EqsPrfrm" - "Выполнение работ по ТОиР"). Компилируйте только если комлектация Системы включает указанное приложение.
|
- объект `PKG_P8PANELS_EQUIPSRV` - может быть откомпилирован в Системе, имеющей в комлектации приложение "Управление техническим обслуживанием и ремонтами". Этот объект отвечает за работу панелей группы "Управление техническим обслуживанием и ремонтами" ("EqsPrfrm" - "Выполнение работ по ТОиР"). Компилируйте только если комлектация Системы включает указанное приложение.
|
||||||
@ -987,397 +986,6 @@ const P8Online = ({ title }) => {
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### API для взаимодействия с параметрами фреймворка
|
|
||||||
|
|
||||||
Для работы с параметрами панелей в составе расширения предусмотрен специальный API. Его подключение к компоненте панели осуществляется через контекст `SettingsCtx` ("app/context/settings.js"). Данный контекст обеспечивает инициализацию, считывание и обновление параметров различных видов (системные, панельные, пользовательские).
|
|
||||||
|
|
||||||
В состав API входят:
|
|
||||||
|
|
||||||
- `SETTINGS_KINDS` - объект с константами видов параметров
|
|
||||||
- `initSettings` - функция, инициализация параметров панелей
|
|
||||||
- `getSettings` - функция, считывание параметров
|
|
||||||
- `putSettings` - функция, добавление/обновление параметров
|
|
||||||
- `showSettingsDialog` - функция, отображение диалога настройки параметров
|
|
||||||
|
|
||||||
#### `SETTINGS_KINDS`
|
|
||||||
|
|
||||||
Объект, содержащий константы видов параметров:
|
|
||||||
|
|
||||||
```
|
|
||||||
{
|
|
||||||
SYSTEM: 0,
|
|
||||||
PANEL: 1,
|
|
||||||
USER: 2
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- `SYSTEM` - Системные параметры, общие для всех панелей. Не требуют указания панели при работе.
|
|
||||||
- `PANEL` - Параметры конкретной панели. Требуют указания панели (`panel`).
|
|
||||||
- `USER` - Пользовательские параметры. Требуют указания панели (`panel`).
|
|
||||||
|
|
||||||
#### `async Object initSettings(Object)`
|
|
||||||
|
|
||||||
Инициализирует параметры панелей в БД Системы. Если параметры с указанными ключами уже существуют - будут перезаписаны.
|
|
||||||
|
|
||||||
**Входные параметры:**
|
|
||||||
|
|
||||||
```
|
|
||||||
{
|
|
||||||
kind,
|
|
||||||
settings,
|
|
||||||
panel = null,
|
|
||||||
full = false,
|
|
||||||
loader = true
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
`kind` - обязательный, число, вид параметров (`SETTINGS_KINDS.SYSTEM`, `SETTINGS_KINDS.PANEL` или `SETTINGS_KINDS.USER`)\
|
|
||||||
`settings` - обязательный, объект, параметры для инициализации вида `{ "МНЕМОКОД_ПАРАМЕТРА": { name: <НАИМЕНОВАНИЕ>, dataType: <ТИП_ДАННЫХ>, value: <ЗНАЧЕНИЕ>, desc: <ОПИСАНИЕ>, options: {...} }, ... }`\
|
|
||||||
`panel` - необязательный, строка, имя панели (требуется для `PANEL` и `USER`, игнорируется для `SYSTEM`)\
|
|
||||||
`full` - необязательный, логический, признак возврата полного ответа сервера (по умолчанию `false`)\
|
|
||||||
`loader` - необязательный, логический, признак отображения типового индикатора процесса
|
|
||||||
|
|
||||||
**Результат:** объект с инициализированными параметрами (если `full = false`) или полный типовой ответ сервера (если `full = true`).
|
|
||||||
|
|
||||||
**Особенности:**
|
|
||||||
|
|
||||||
- Для вида `SYSTEM` параметр `panel` не требуется и игнорируется
|
|
||||||
- Для видов `PANEL` и `USER` параметр `panel` обязателен, иначе будет выведена ошибка
|
|
||||||
- Параметр `options` является необязательным, но если указан, то должен быть объект вида `{<КЛЮЧ>:<ЗНАЧЕНИЕ>, ...}`. Параметры поддерживают привязку к разделам системы, для этого требуется указать следующие `options` `{unitcode: <МНЕМОКОД_РАЗДЕЛА>, showMethod: <МЕТОД_РАЗДЕЛА>, inParameter: <ИМЯ_ВХОДНОГО_ПАРАМЕТРА>, outParameter: <ИМЯ_ВЫХОДНОГО_ПАРАМЕТРА>}`, все параметры являются обязательными
|
|
||||||
- Функция выполняет обновление существующих параметров, обновляемые значения: `options`, `name`, `desc` и анализирует необходимость обновления значения, если `dataType` не соответствует инициализируемому - обновляет значение `value`, в ином случае значение не обновляется
|
|
||||||
|
|
||||||
**Пример:**
|
|
||||||
|
|
||||||
```
|
|
||||||
import React, { useContext } from "react";
|
|
||||||
import { SettingsCtx } from "../../context/settings";
|
|
||||||
import { P8P_DATA_TYPES } from "../../core/data_types";
|
|
||||||
|
|
||||||
//Инициализируемые параметры
|
|
||||||
const INIT_SETTINGS = {
|
|
||||||
INFO: {
|
|
||||||
name: "Дополнительная информация",
|
|
||||||
dataType: P8P_DATA_TYPES.STR,
|
|
||||||
value: "Необходима проверка документов.",
|
|
||||||
desc: "Дополнительная информация для контрагента"
|
|
||||||
},
|
|
||||||
COUNT_DOCS: {
|
|
||||||
name: "Количество отображаемых документов",
|
|
||||||
dataType: P8P_DATA_TYPES.NUMB,
|
|
||||||
value: 10,
|
|
||||||
desc: ""
|
|
||||||
},
|
|
||||||
START_DATE: {
|
|
||||||
name: "Дата начала",
|
|
||||||
dataType: P8P_DATA_TYPES.DATE,
|
|
||||||
value: "2026-02-15",
|
|
||||||
desc: "Дата начала по умолчанию"
|
|
||||||
},
|
|
||||||
AGENT: {
|
|
||||||
name: "Выбранный контрагент",
|
|
||||||
dataType: P8P_DATA_TYPES.STR,
|
|
||||||
value: "",
|
|
||||||
desc: "Мнемокод выбранного контрагента",
|
|
||||||
options: {
|
|
||||||
unitcode: "AGNLIST",
|
|
||||||
showMethod: "main",
|
|
||||||
inParameter: "in_AGNABBR",
|
|
||||||
outParameter: "out_AGNABBR"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const MyPanel = () => {
|
|
||||||
//Собственное состояние - параметры
|
|
||||||
const [state, setState] = useState({});
|
|
||||||
//Подключение к контексту параметров
|
|
||||||
const { initSettings, SETTINGS_KINDS } = useContext(SettingsCtx);
|
|
||||||
|
|
||||||
//Инициализация параметров
|
|
||||||
const initializeSettings = async () => {
|
|
||||||
// Инициализация пользовательских параметров
|
|
||||||
const res = await initSettings({
|
|
||||||
kind: SETTINGS_KINDS.USER,
|
|
||||||
panel: "PanelName",
|
|
||||||
settings: INIT_SETTINGS
|
|
||||||
});
|
|
||||||
//Устанавливаем параметры
|
|
||||||
setState({ ...res });
|
|
||||||
};
|
|
||||||
|
|
||||||
return <div>...</div>;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `async Object getSettings(Object)`
|
|
||||||
|
|
||||||
Считывает параметры панелей из БД Системы.
|
|
||||||
|
|
||||||
**Входные параметры:**
|
|
||||||
|
|
||||||
```
|
|
||||||
{
|
|
||||||
kind,
|
|
||||||
code = null,
|
|
||||||
panel = null,
|
|
||||||
full = false,
|
|
||||||
loader = true
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
`kind` - обязательный, число, вид параметров (`SETTINGS_KINDS.SYSTEM`, `SETTINGS_KINDS.PANEL` или `SETTINGS_KINDS.USER`)\
|
|
||||||
`code` - необязательный, строка, мнемокод параметра для отбора, при пустом значении считывает все доступные параметры\
|
|
||||||
`panel` - необязательный, строка, имя панели (требуется для `PANEL` и `USER`, игнорируется для `SYSTEM`)\
|
|
||||||
`full` - необязательный, логический, признак возврата полного ответа сервера с информацией о параметре (по умолчанию `false`)\
|
|
||||||
`loader` - необязательный, логический, признак отображения типового индикатора процесса
|
|
||||||
|
|
||||||
**Результат:** объект с считанными параметрами вида `{ <МНЕМОКОД_ПАРАМЕТРА>: <ЗНАЧЕНИЕ>, ... }` (если `full = false`) или полный ответ сервера (если `full = true`).
|
|
||||||
|
|
||||||
**Особенности:**
|
|
||||||
|
|
||||||
- Для вида `SYSTEM` параметр `panel` не требуется и игнорируется
|
|
||||||
- Для видов `PANEL` и `USER` параметр `panel` рекомендуется указать для получения параметров конкретной панели
|
|
||||||
- Возвращает только значения параметров, без метаданных (если `full = false`)
|
|
||||||
|
|
||||||
**Пример:**
|
|
||||||
|
|
||||||
```
|
|
||||||
import React, { useContext, useState, useEffect } from "react";
|
|
||||||
import { SettingsCtx } from "../../context/settings";
|
|
||||||
|
|
||||||
const MyPanel = () => {
|
|
||||||
//Собственное состояние - параметры
|
|
||||||
const [state, setState] = useState({});
|
|
||||||
//Подключение к контексту параметров
|
|
||||||
const { getSettings, SETTINGS_KINDS } = useContext(SettingsCtx);
|
|
||||||
|
|
||||||
//Загрузка параметров пользователя
|
|
||||||
const handleLoadSettings = async () => {
|
|
||||||
// Считывание параметров панели
|
|
||||||
const settings = await getSettings({
|
|
||||||
kind: SETTINGS_KINDS.USER,
|
|
||||||
panel: "PanelName"
|
|
||||||
});
|
|
||||||
//Устанавливаем параметры
|
|
||||||
setState({ ...settings });
|
|
||||||
};
|
|
||||||
|
|
||||||
return <div>...</div>;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `async Object putSettings(Object)`
|
|
||||||
|
|
||||||
Добавляет или обновляет параметры панелей в БД Системы.
|
|
||||||
|
|
||||||
**Входные параметры:**
|
|
||||||
|
|
||||||
```
|
|
||||||
{
|
|
||||||
kind,
|
|
||||||
settings,
|
|
||||||
panel = null,
|
|
||||||
loader = true
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
`kind` - обязательный, число, вид параметров (`SETTINGS_KINDS.SYSTEM`, `SETTINGS_KINDS.PANEL` или `SETTINGS_KINDS.USER`)\
|
|
||||||
`settings` - обязательный, объект, параметры для добавления/обновления вида `{ <МНЕМОКОД_ПАРАМЕТРА>: { name: <НАИМЕНОВАНИЕ>, dataType: <ТИП_ДАННЫХ>, value: <ЗНАЧЕНИЕ>, desc: <ОПИСАНИЕ>, options: {...} }, ... }`\
|
|
||||||
`panel` - необязательный, строка, имя панели (требуется для `PANEL` и `USER`, игнорируется для `SYSTEM`)\
|
|
||||||
`loader` - необязательный, логический, признак отображения типового индикатора процесса
|
|
||||||
|
|
||||||
**Результат:** функция не возвращает значимого результата.
|
|
||||||
|
|
||||||
**Особенности:**
|
|
||||||
|
|
||||||
- Для вида `SYSTEM` параметр `panel` не требуется и игнорируется
|
|
||||||
- Для видов `PANEL` и `USER` параметр `panel` обязателен, иначе будет выведена ошибка и функция вернётся без выполнения
|
|
||||||
- При обновлении параметра обновляются следующие значения: `options`, `name`, `desc`, `dataType`, `value`
|
|
||||||
|
|
||||||
**Пример:**
|
|
||||||
|
|
||||||
```
|
|
||||||
import React, { useContext } from "react";
|
|
||||||
import { SettingsCtx } from "../../context/settings";
|
|
||||||
import { formatDateJSONDateOnly } from "../../core/utils";
|
|
||||||
|
|
||||||
//Инициализируемые параметры
|
|
||||||
const PUT_SETTINGS = {
|
|
||||||
LAST_UPDATE: {
|
|
||||||
name: "Дата последнего обновления",
|
|
||||||
dataType: "DATE",
|
|
||||||
value: formatDateJSONDateOnly(new Date()),
|
|
||||||
desc: ""
|
|
||||||
},
|
|
||||||
COUNT_DOCS: {
|
|
||||||
name: "Количество отображаемых документов",
|
|
||||||
dataType: P8P_DATA_TYPES.NUMB,
|
|
||||||
value: 15,
|
|
||||||
desc: ""
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const MyPanel = () => {
|
|
||||||
//Собственное состояние - параметры
|
|
||||||
const [state, setState] = useState({});
|
|
||||||
//Подключение к контексту параметров
|
|
||||||
const { putSettings, SETTINGS_KINDS } = useContext(SettingsCtx);
|
|
||||||
|
|
||||||
//Добавление/обновление параметров пользователя
|
|
||||||
const handlePutSettings = async () => {
|
|
||||||
//Обновление системных параметров
|
|
||||||
await putSettings({
|
|
||||||
kind: SETTINGS_KINDS.USER,
|
|
||||||
panel: "PanelName",
|
|
||||||
settings: PUT_SETTINGS
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return <div>...</div>;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `async undefined showSettingsDialog(Object)`
|
|
||||||
|
|
||||||
Отображает диалог настройки параметров пользователя. Диалог позволяет пользователю изменить значения параметров.
|
|
||||||
|
|
||||||
**Входные параметры:**
|
|
||||||
|
|
||||||
```
|
|
||||||
{
|
|
||||||
panel = null,
|
|
||||||
onOk = null,
|
|
||||||
onCancel = null
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
`panel` - необязательный, строка, имя панели (если не указан - открываются все параметры с разделением по панелям)\
|
|
||||||
`onOk` - необязательный, функция вида `f({ settings })`, будет вызвана при нажатии "ОК" в диалоге. В параметр `settings` передаются изменённые параметры\
|
|
||||||
`onCancel` - необязательный, функция вида `f()`, будет вызвана при нажатии "Отмена" или закрытии диалога
|
|
||||||
|
|
||||||
**Результат:** функция возвращает следующие объекты:\
|
|
||||||
|
|
||||||
- `settings` - объект, содержащий информацию о всех параметрах с учетом изменений
|
|
||||||
- `isChanged` - признак изменений данных (`true` - параметры были изменены, `false` - изменений не было)
|
|
||||||
|
|
||||||
**Особенности:**
|
|
||||||
|
|
||||||
- Диалог реализован компонентом `P8PSettingsDialog` ("app/components/p8p_settings_dialog.js")
|
|
||||||
- При нажатии "ОК" параметры автоматически сохраняются через `putSettings`
|
|
||||||
- При нажатии "Отмена" параметры не сохраняются
|
|
||||||
- Диалог закрывается автоматически после обработки нажатий
|
|
||||||
|
|
||||||
**Пример:**
|
|
||||||
|
|
||||||
```
|
|
||||||
import React, { useContext } from "react";
|
|
||||||
import { SettingsCtx } from "../../context/settings";
|
|
||||||
import { Button } from "@mui/material";
|
|
||||||
|
|
||||||
const MyPanel = () => {
|
|
||||||
//Подключение к контексту параметров
|
|
||||||
const { showSettingsDialog, SETTINGS_KINDS } = useContext(SettingsCtx);
|
|
||||||
|
|
||||||
//При отображении параметров панели
|
|
||||||
const handleSettingsDialog = async () => {
|
|
||||||
//Отображаем параметры панели
|
|
||||||
showSettingsDialog({
|
|
||||||
panel: "PanelName",
|
|
||||||
onOk: ({ settings }) => {
|
|
||||||
console.log("Параметры сохранены:", { settings, isChanged });
|
|
||||||
},
|
|
||||||
onCancel: () => {
|
|
||||||
console.log("Изменения отменены");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Button variant="contained" onClick={handleSettingsDialog}>
|
|
||||||
Настроить параметры
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Формат параметров
|
|
||||||
|
|
||||||
Параметры имеют следующую структуру:
|
|
||||||
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"МНЕМОКОД_ПАРАМЕТРА": {
|
|
||||||
name: <НАИМЕНОВАНИЕ>,
|
|
||||||
dataType: <ТИП_ДАННЫХ>,
|
|
||||||
value: <ЗНАЧЕНИЕ>,
|
|
||||||
desc: <ОПИСАНИЕ>,
|
|
||||||
options: { ... } // необязательный
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Поля параметра:**
|
|
||||||
|
|
||||||
- `name` - обязательный, строка, наименование параметра
|
|
||||||
- `dataType` - обязательный, строка, тип данных параметра (`STR` - строка, `NUMB` - число, `DATE` - дата)
|
|
||||||
- `value` - необязательный, значение параметра (тип должен соответствовать `dataType`)
|
|
||||||
- `desc` - необязательный, строка, описание параметра (может использоваться в диалоге настроек как подсказка)
|
|
||||||
- `options` - необязательный, объект, дополнительные настройки параметра
|
|
||||||
|
|
||||||
**Настройки привязки к разделу (`options`):**
|
|
||||||
|
|
||||||
Параметр может быть привязан к разделу Системы для автоматического заполнения значения через словарь. Для этого в `options` указываются:
|
|
||||||
|
|
||||||
- `unitcode` - строка, код раздела Системы (например, `"AGNLIST"` для словаря "Контрагенты")
|
|
||||||
- `showMethod` - строка, метод вызова раздела
|
|
||||||
- `inParameter` - строка, имя входного параметра метода вызова для отбора/позиционирования (например, `"in_AGNABBR"`)
|
|
||||||
- `outParameter` - строка, имя выходного параметра метода вызова для получения значения (например, `"out_AGNABBR"`)
|
|
||||||
|
|
||||||
**Пример параметра с привязкой к словарю:**
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
{
|
|
||||||
AGENT: {
|
|
||||||
name: "Выбранный контрагент",
|
|
||||||
dataType: "STR",
|
|
||||||
value: "",
|
|
||||||
desc: "Мнемокод контрагента для отчёта",
|
|
||||||
options: {
|
|
||||||
unitcode: "AGNLIST",
|
|
||||||
showMethod: "main",
|
|
||||||
inParameter: "in_AGNABBR",
|
|
||||||
outParameter: "out_AGNABBR"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
При использовании такого параметра в диалоге настроек (`showSettingsDialog`) будет автоматически предложен выбор из словаря "Контрагенты", и значение параметра будет заполнено после выбора записи.
|
|
||||||
|
|
||||||
**Пример:**
|
|
||||||
|
|
||||||
Полный актуальный исходный код примера можно увидеть в "app/panels/samples/settings.js" данного репозитория.
|
|
||||||
|
|
||||||
#### Примечания
|
|
||||||
|
|
||||||
1. **Наименование панели:** при использовании параметра `panel` в него необходимо передавать соответствующее наименование панели из `p8panels.config`.
|
|
||||||
|
|
||||||
2. **Формат параметров:** каждый параметр должен быть объектом со структурой `{ name, dataType, value, desc, options }`.
|
|
||||||
|
|
||||||
3. **Типы данных (`dataType`):** поддерживаются следующие типы:
|
|
||||||
- `STR` - строка
|
|
||||||
- `NUMB` - число
|
|
||||||
- `DATE` - дата (в формате ISO 8601, например `"2024-01-15"`)
|
|
||||||
- `BOOL` - логическое (`true`/`false`)
|
|
||||||
|
|
||||||
4. **Имена параметров:** мнемокоды параметров должны быть уникальными в рамках одной панели/системы.
|
|
||||||
|
|
||||||
5. **Привязка к разделу:** для параметров, которые должны заполняться через выбор из словаря/раздела Системы, обязательно заполняется `options` с полями `unitcode`, `showMethod`, `inParameter`, `outParameter`.
|
|
||||||
|
|
||||||
6. **Метаданные:** параметр `full = true` возвращает не только значения параметров, но и все метаданные (`name`, `dataType`, `desc`, `options`), что полезно для построения динамических форм редактирования.
|
|
||||||
|
|
||||||
### Компоненты пользовательского интерфейса
|
### Компоненты пользовательского интерфейса
|
||||||
|
|
||||||
#### Типовые интерфейсные примитивы
|
#### Типовые интерфейсные примитивы
|
||||||
|
|||||||
@ -33,7 +33,6 @@ export const TEXTS = {
|
|||||||
export const BUTTONS = {
|
export const BUTTONS = {
|
||||||
NAVIGATE_HOME: "Домой", //Переход к домашней странице
|
NAVIGATE_HOME: "Домой", //Переход к домашней странице
|
||||||
NAVIGATE_BACK: "Назад", //Возврат назад по навигации
|
NAVIGATE_BACK: "Назад", //Возврат назад по навигации
|
||||||
NAVIGATE_SETTINGS: "Параметры", //Переход к параметрам панелей
|
|
||||||
NAVIGATE: "Перейти", //Переход к разделу/панели/адресу
|
NAVIGATE: "Перейти", //Переход к разделу/панели/адресу
|
||||||
OK: "ОК", //Ок
|
OK: "ОК", //Ок
|
||||||
CANCEL: "Отмена", //Отмена
|
CANCEL: "Отмена", //Отмена
|
||||||
|
|||||||
@ -11,7 +11,6 @@ import React, { useState, useContext, useEffect } from "react"; //Классы R
|
|||||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||||||
import { createHashRouter, RouterProvider, useRouteError } from "react-router-dom"; //Роутер
|
import { createHashRouter, RouterProvider, useRouteError } from "react-router-dom"; //Роутер
|
||||||
import { ApplicationCtx } from "./context/application"; //Контекст приложения
|
import { ApplicationCtx } from "./context/application"; //Контекст приложения
|
||||||
import { SettingsCtx } from "./context/settings"; //Контекст параметров
|
|
||||||
import { NavigationContext, NavigationCtx, getRootLocation } from "./context/navigation"; //Контекст навигации
|
import { NavigationContext, NavigationCtx, getRootLocation } from "./context/navigation"; //Контекст навигации
|
||||||
import { P8PAppErrorPage } from "./components/p8p_app_error_page"; //Страница с ошибкой
|
import { P8PAppErrorPage } from "./components/p8p_app_error_page"; //Страница с ошибкой
|
||||||
import { P8PAppWorkspace } from "./components/p8p_app_workspace"; //Рабочее пространство панели
|
import { P8PAppWorkspace } from "./components/p8p_app_workspace"; //Рабочее пространство панели
|
||||||
@ -90,12 +89,6 @@ const Workspace = ({ panels = [], selectedPanel, children } = {}) => {
|
|||||||
//Подключение к контексту приложения
|
//Подключение к контексту приложения
|
||||||
const { appState } = useContext(ApplicationCtx);
|
const { appState } = useContext(ApplicationCtx);
|
||||||
|
|
||||||
//Подключение к контексту параметров
|
|
||||||
const { showSettingsDialog } = useContext(SettingsCtx);
|
|
||||||
|
|
||||||
//При открытии диалога параметров панели
|
|
||||||
const handleSettingsDialog = panel => showSettingsDialog({ panel });
|
|
||||||
|
|
||||||
//Отработка действия навигации домой
|
//Отработка действия навигации домой
|
||||||
const handleHomeNavigate = () => navigateRoot();
|
const handleHomeNavigate = () => navigateRoot();
|
||||||
|
|
||||||
@ -110,10 +103,8 @@ const Workspace = ({ panels = [], selectedPanel, children } = {}) => {
|
|||||||
selectedPanel={selectedPanel}
|
selectedPanel={selectedPanel}
|
||||||
caption={appState.appBarTitle}
|
caption={appState.appBarTitle}
|
||||||
showAppBar={appState.appBarShow}
|
showAppBar={appState.appBarShow}
|
||||||
showAppBarSettings={appState.appBarSettingsShow}
|
|
||||||
onHomeNavigate={handleHomeNavigate}
|
onHomeNavigate={handleHomeNavigate}
|
||||||
onItemNavigate={handleItemNavigate}
|
onItemNavigate={handleItemNavigate}
|
||||||
onSettingsDialog={handleSettingsDialog}
|
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</P8PAppWorkspace>
|
</P8PAppWorkspace>
|
||||||
|
|||||||
@ -21,8 +21,7 @@ import {
|
|||||||
List,
|
List,
|
||||||
ListItemButton,
|
ListItemButton,
|
||||||
ListItemIcon,
|
ListItemIcon,
|
||||||
ListItemText,
|
ListItemText
|
||||||
Divider
|
|
||||||
} from "@mui/material"; //Интерфейсные компоненты
|
} from "@mui/material"; //Интерфейсные компоненты
|
||||||
import { P8PPanelsMenuDrawer, P8P_PANELS_MENU_PANEL_SHAPE } from "./p8p_panels_menu"; //Меню
|
import { P8PPanelsMenuDrawer, P8P_PANELS_MENU_PANEL_SHAPE } from "./p8p_panels_menu"; //Меню
|
||||||
import { APP_STYLES } from "../../app.styles"; //Типовые стили
|
import { APP_STYLES } from "../../app.styles"; //Типовые стили
|
||||||
@ -39,9 +38,6 @@ const STYLES = {
|
|||||||
DRAWER: { [`& .MuiDrawer-paper`]: { ...APP_STYLES.SCROLL } },
|
DRAWER: { [`& .MuiDrawer-paper`]: { ...APP_STYLES.SCROLL } },
|
||||||
ROOT_BOX: { display: "flex" },
|
ROOT_BOX: { display: "flex" },
|
||||||
APP_BAR: { position: "fixed" },
|
APP_BAR: { position: "fixed" },
|
||||||
APP_BAR_MAIN_BOX: { display: "flex", width: "100vw", alignItems: "center", justifyContent: "space-between" },
|
|
||||||
APP_BAR_LEFT_SIDE: { display: "flex", alignItems: "center", justifyContent: "flex-start" },
|
|
||||||
APP_BAR_RIGHT_SIDE: { display: "flex", alignItems: "center", justifyContent: "flex-end" },
|
|
||||||
APP_BAR_BUTTON: { mr: 2 },
|
APP_BAR_BUTTON: { mr: 2 },
|
||||||
MAIN: { flexGrow: 1 }
|
MAIN: { flexGrow: 1 }
|
||||||
};
|
};
|
||||||
@ -57,13 +53,10 @@ const P8PAppWorkspace = ({
|
|||||||
selectedPanel,
|
selectedPanel,
|
||||||
caption,
|
caption,
|
||||||
showAppBar = true,
|
showAppBar = true,
|
||||||
showAppBarSettings = true,
|
|
||||||
closeCaption,
|
closeCaption,
|
||||||
homeCaption,
|
homeCaption,
|
||||||
settingsCaption,
|
|
||||||
onHomeNavigate,
|
onHomeNavigate,
|
||||||
onItemNavigate,
|
onItemNavigate
|
||||||
onSettingsDialog
|
|
||||||
} = {}) => {
|
} = {}) => {
|
||||||
//Собственное состояния
|
//Собственное состояния
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
@ -87,9 +80,6 @@ const P8PAppWorkspace = ({
|
|||||||
onItemNavigate ? onItemNavigate(panel) : null;
|
onItemNavigate ? onItemNavigate(panel) : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
//Отработка нажатия на элемент открытия параметров
|
|
||||||
const handleSettingsDialog = (panel = null) => onSettingsDialog(panel);
|
|
||||||
|
|
||||||
//Генерация содержимого
|
//Генерация содержимого
|
||||||
return (
|
return (
|
||||||
<Box sx={STYLES.ROOT_BOX}>
|
<Box sx={STYLES.ROOT_BOX}>
|
||||||
@ -98,8 +88,6 @@ const P8PAppWorkspace = ({
|
|||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<AppBar sx={STYLES.APP_BAR}>
|
<AppBar sx={STYLES.APP_BAR}>
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<Box sx={STYLES.APP_BAR_MAIN_BOX}>
|
|
||||||
<Box sx={STYLES.APP_BAR_LEFT_SIDE}>
|
|
||||||
<IconButton
|
<IconButton
|
||||||
color="inherit"
|
color="inherit"
|
||||||
aria-label="open drawer"
|
aria-label="open drawer"
|
||||||
@ -112,21 +100,6 @@ const P8PAppWorkspace = ({
|
|||||||
<Typography variant="h6" noWrap component="div">
|
<Typography variant="h6" noWrap component="div">
|
||||||
{caption || selectedPanel?.caption}
|
{caption || selectedPanel?.caption}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
|
||||||
<Box sx={STYLES.APP_BAR_RIGHT_SIDE}>
|
|
||||||
{showAppBarSettings && selectedPanel.showUserSettings ? (
|
|
||||||
<IconButton
|
|
||||||
color="inherit"
|
|
||||||
aria-label="open drawer"
|
|
||||||
onClick={() => handleSettingsDialog(selectedPanel.name)}
|
|
||||||
edge="end"
|
|
||||||
sx={STYLES.APP_BAR_BUTTON}
|
|
||||||
>
|
|
||||||
<Icon>settings</Icon>
|
|
||||||
</IconButton>
|
|
||||||
) : null}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
</AppBar>
|
</AppBar>
|
||||||
<Drawer anchor="left" open={open} onClose={handleDrawerClose} sx={STYLES.DRAWER}>
|
<Drawer anchor="left" open={open} onClose={handleDrawerClose} sx={STYLES.DRAWER}>
|
||||||
@ -143,13 +116,6 @@ const P8PAppWorkspace = ({
|
|||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<ListItemText primary={homeCaption} />
|
<ListItemText primary={homeCaption} />
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
<Divider component="li" />
|
|
||||||
<ListItemButton onClick={() => handleSettingsDialog()}>
|
|
||||||
<ListItemIcon>
|
|
||||||
<Icon>settings</Icon>
|
|
||||||
</ListItemIcon>
|
|
||||||
<ListItemText primary={settingsCaption} />
|
|
||||||
</ListItemButton>
|
|
||||||
</List>
|
</List>
|
||||||
<P8PPanelsMenuDrawer panels={panels} selectedPanel={selectedPanel} onItemNavigate={handleItemNavigate} />
|
<P8PPanelsMenuDrawer panels={panels} selectedPanel={selectedPanel} onItemNavigate={handleItemNavigate} />
|
||||||
</Drawer>
|
</Drawer>
|
||||||
@ -170,13 +136,10 @@ P8PAppWorkspace.propTypes = {
|
|||||||
selectedPanel: P8P_PANELS_MENU_PANEL_SHAPE,
|
selectedPanel: P8P_PANELS_MENU_PANEL_SHAPE,
|
||||||
caption: PropTypes.string,
|
caption: PropTypes.string,
|
||||||
showAppBar: PropTypes.bool,
|
showAppBar: PropTypes.bool,
|
||||||
showAppBarSettings: PropTypes.bool,
|
|
||||||
closeCaption: PropTypes.string.isRequired,
|
closeCaption: PropTypes.string.isRequired,
|
||||||
homeCaption: PropTypes.string.isRequired,
|
homeCaption: PropTypes.string.isRequired,
|
||||||
settingsCaption: PropTypes.string.isRequired,
|
|
||||||
onHomeNavigate: PropTypes.func,
|
onHomeNavigate: PropTypes.func,
|
||||||
onItemNavigate: PropTypes.func,
|
onItemNavigate: PropTypes.func
|
||||||
onSettingsDialog: PropTypes.func
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------------
|
//----------------
|
||||||
|
|||||||
@ -1,153 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга
|
|
||||||
Компонент: Диалог отображения параметров
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---------------------
|
|
||||||
//Подключение библиотек
|
|
||||||
//---------------------
|
|
||||||
|
|
||||||
import React, { useState, useContext, useMemo } from "react"; //Классы React
|
|
||||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
|
||||||
import { Stack, List, ListItem, ListItemButton, ListItemText, Typography, Box, Divider } from "@mui/material"; //Интерфейсные элементы
|
|
||||||
import { P8PDialog, P8P_DIALOG_WIDTH } from "./p8p_dialog"; //Типовой диалог
|
|
||||||
import { APP_STYLES } from "../../app.styles"; //Типовые стили
|
|
||||||
import { P8PSettingsList } from "./p8p_settings_list"; //Список параметров
|
|
||||||
import { ApplicationCtx } from "../context/application"; //Контекст приложения
|
|
||||||
import { deepCopyObject, hasValue } from "../core/utils"; //Вспомогательные функции
|
|
||||||
|
|
||||||
//---------
|
|
||||||
//Константы
|
|
||||||
//---------
|
|
||||||
|
|
||||||
//Стили
|
|
||||||
const STYLES = {
|
|
||||||
CONTAINER: { display: "flex", flexDirection: "row", alignItems: "flex-start" },
|
|
||||||
BOX_PANELS: { width: "300px", height: "500px", overflow: "auto", ...APP_STYLES.SCROLL },
|
|
||||||
BOX_SETTINGS: { width: "520px", height: "500px", overflow: "auto", ...APP_STYLES.SCROLL }
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------
|
|
||||||
//Тело модуля
|
|
||||||
//-----------
|
|
||||||
|
|
||||||
//Диалог отображения параметров
|
|
||||||
const P8PSettingsDialog = ({ settings, panel = null, onOk, onClose }) => {
|
|
||||||
//Собственное состояние - параметры панелей
|
|
||||||
const [panelSettings, setPanelSettings] = useState(settings);
|
|
||||||
|
|
||||||
//Собственное состояние - мнемокод выбранной панели
|
|
||||||
const [selectedPanel, setSelectedPanel] = useState(panel);
|
|
||||||
|
|
||||||
//Собственное состояние - наличие отображаемых данных
|
|
||||||
const isSettingsExists = useMemo(() => {
|
|
||||||
return selectedPanel
|
|
||||||
? panelSettings && Object.keys(panelSettings).length > 0 && Object.keys(panelSettings[selectedPanel]).length > 0
|
|
||||||
: Object.keys(panelSettings).length > 0;
|
|
||||||
}, [selectedPanel, panelSettings]);
|
|
||||||
|
|
||||||
//Подключение к контексту приложения
|
|
||||||
const { appState } = useContext(ApplicationCtx);
|
|
||||||
|
|
||||||
//При нажатии на "ОК"
|
|
||||||
const handleOk = () => onOk && onOk(panelSettings);
|
|
||||||
|
|
||||||
//При нажатии на "Отменить"
|
|
||||||
const handleCancel = () => onClose && onClose();
|
|
||||||
|
|
||||||
//При изменении параметра
|
|
||||||
const handleSettingChange = (settingCode, newSettings) => {
|
|
||||||
//Определяем панели
|
|
||||||
const newPanelSettings = deepCopyObject(panelSettings);
|
|
||||||
//Изменяем настройку у панели
|
|
||||||
newPanelSettings[selectedPanel][settingCode] = deepCopyObject(newSettings);
|
|
||||||
//Обновляем панели
|
|
||||||
setPanelSettings(newPanelSettings);
|
|
||||||
};
|
|
||||||
|
|
||||||
//При нажатии на панель
|
|
||||||
const handlePanelSelect = panelName => setSelectedPanel(selectedPanel === panelName ? null : panelName);
|
|
||||||
|
|
||||||
//Генерация области выбора панели
|
|
||||||
const panelsListRender = () => {
|
|
||||||
//Генерация содержимого
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Box sx={STYLES.BOX_PANELS}>
|
|
||||||
<List>
|
|
||||||
{Object.keys(panelSettings).map((panel, i) => {
|
|
||||||
//Считываем информацию о панели
|
|
||||||
const panelInfo = appState.panels.find(appPanel => appPanel.name == panel);
|
|
||||||
//Элемент панели
|
|
||||||
return (
|
|
||||||
<ListItem key={i}>
|
|
||||||
<ListItemButton onClick={() => handlePanelSelect(panel)} selected={panel === selectedPanel}>
|
|
||||||
<ListItemText
|
|
||||||
primary={panelInfo.name}
|
|
||||||
secondaryTypographyProps={{ component: "div" }}
|
|
||||||
secondary={
|
|
||||||
<Stack direction={"row"} justifyContent={"space-between"} gap={2}>
|
|
||||||
<Typography
|
|
||||||
variant={"caption"}
|
|
||||||
noWrap={true}
|
|
||||||
title={panelInfo.desc ? panelInfo.desc : "Описание отсутствует"}
|
|
||||||
>{`${panelInfo.desc ? panelInfo.desc : "Описание отсутствует"}`}</Typography>
|
|
||||||
</Stack>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ListItemButton>
|
|
||||||
</ListItem>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</List>
|
|
||||||
</Box>
|
|
||||||
<Divider orientation="vertical" flexItem />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Формирование представления
|
|
||||||
return (
|
|
||||||
<P8PDialog
|
|
||||||
title={`Параметры ${panel ? `"${appState.panels.find(appPanel => appPanel.name == panel).caption}"` : "панелей"}`}
|
|
||||||
width={P8P_DIALOG_WIDTH.LG}
|
|
||||||
onCancel={handleCancel}
|
|
||||||
onOk={handleOk}
|
|
||||||
scrollContent={false}
|
|
||||||
okDisabled={Object.keys(panelSettings).length === 0}
|
|
||||||
>
|
|
||||||
{isSettingsExists ? (
|
|
||||||
<Box sx={STYLES.CONTAINER}>
|
|
||||||
{!hasValue(panel) ? panelsListRender() : null}
|
|
||||||
<Box sx={STYLES.BOX_SETTINGS}>
|
|
||||||
{hasValue(selectedPanel) ? (
|
|
||||||
<P8PSettingsList settings={panelSettings[selectedPanel]} onSettingChange={handleSettingChange} />
|
|
||||||
) : (
|
|
||||||
<Typography align="center" variant="subtitle1">
|
|
||||||
Выберите панель для отображения параметров
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
) : (
|
|
||||||
<Typography align="center" variant="subtitle1">
|
|
||||||
Отсутствуют доступные параметры
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
</P8PDialog>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Контроль свойств компонента - Диалог отображения параметров
|
|
||||||
P8PSettingsDialog.propTypes = {
|
|
||||||
settings: PropTypes.object.isRequired,
|
|
||||||
panel: PropTypes.string,
|
|
||||||
onOk: PropTypes.func,
|
|
||||||
onClose: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------
|
|
||||||
//Интерфейс модуля
|
|
||||||
//----------------
|
|
||||||
|
|
||||||
export { P8PSettingsDialog };
|
|
||||||
@ -1,178 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга
|
|
||||||
Компонент: Список параметров
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---------------------
|
|
||||||
//Подключение библиотек
|
|
||||||
//---------------------
|
|
||||||
|
|
||||||
import React, { useState, useContext, useMemo } from "react"; //Классы React
|
|
||||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
|
||||||
import { Stack, List, ListItem, ListItemButton, ListItemText, Typography } from "@mui/material"; //Интерфейсные элементы
|
|
||||||
import { P8PDialog } from "./p8p_dialog"; //Типовой диалог
|
|
||||||
import { deepCopyObject } from "../core/utils"; //Вспомогательные функции
|
|
||||||
import { ApplicationCtx } from "../context/application"; //Контекст приложения
|
|
||||||
import { P8P_DATA_TYPES } from "../core/data_types"; //Типы данных
|
|
||||||
|
|
||||||
//---------
|
|
||||||
//Константы
|
|
||||||
//---------
|
|
||||||
|
|
||||||
//Стили
|
|
||||||
const STYLES = {
|
|
||||||
LIST: { width: "510px", bgcolor: "background.paper", overflowY: "auto" },
|
|
||||||
TYPOGRAPHY_VALUE: { maxWidth: "200px" },
|
|
||||||
TEXT_FIELD_STR_VALUE: { minWidth: "400px" }
|
|
||||||
};
|
|
||||||
|
|
||||||
//--------------------------------
|
|
||||||
//Вспомогательные классы и функции
|
|
||||||
//--------------------------------
|
|
||||||
|
|
||||||
//Диалог изменения параметра
|
|
||||||
const P8PSettingChangeDialog = ({ initSetting, onSave, onClose }) => {
|
|
||||||
//Собственное состояние - параметр
|
|
||||||
const [setting, setSetting] = useState(deepCopyObject(initSetting));
|
|
||||||
|
|
||||||
//Собственное состояние - доступность выбора из словаря
|
|
||||||
const isDictionary = useMemo(() => {
|
|
||||||
//Проверяем наличие обязательных настроек
|
|
||||||
return (
|
|
||||||
setting.options &&
|
|
||||||
setting.options?.unitcode &&
|
|
||||||
setting.options?.showMethod &&
|
|
||||||
setting.options?.inParameter &&
|
|
||||||
setting.options?.outParameter
|
|
||||||
);
|
|
||||||
}, [setting.options]);
|
|
||||||
|
|
||||||
//Подключение к контексту приложения
|
|
||||||
const { pOnlineShowDictionary } = useContext(ApplicationCtx);
|
|
||||||
|
|
||||||
//При закрытии диалога
|
|
||||||
const handleClose = () => onClose && onClose();
|
|
||||||
|
|
||||||
//При нажатии "ОК"
|
|
||||||
const handleOk = () => onSave && onSave(setting);
|
|
||||||
|
|
||||||
//При изменении значения параметра
|
|
||||||
const handleSettingChange = (name, value) => {
|
|
||||||
setSetting(pv => ({ ...pv, [name]: value }));
|
|
||||||
};
|
|
||||||
|
|
||||||
//При выборе значения из справочника
|
|
||||||
const handleDictionarySelect = (currentFormValues, setFormValues) => {
|
|
||||||
//Открываем справочник с учетом параметров
|
|
||||||
pOnlineShowDictionary({
|
|
||||||
unitCode: initSetting.options.unitcode,
|
|
||||||
showMethod: initSetting.options.showMethod,
|
|
||||||
inputParameters: [{ name: initSetting.options.inParameter, value: currentFormValues.value }],
|
|
||||||
callBack: res => {
|
|
||||||
res.success === true ? setFormValues([{ name: "value", value: res.outParameters[initSetting.options.outParameter] }]) : null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
//Формирование представления
|
|
||||||
return (
|
|
||||||
<P8PDialog
|
|
||||||
title={setting.name}
|
|
||||||
width="xs"
|
|
||||||
fullWidth
|
|
||||||
onCancel={handleClose}
|
|
||||||
onOk={handleOk}
|
|
||||||
inputs={[
|
|
||||||
{
|
|
||||||
name: "value",
|
|
||||||
value: setting.value,
|
|
||||||
label: "Значение",
|
|
||||||
dictionary: isDictionary ? handleDictionarySelect : null,
|
|
||||||
type: setting.dataType === P8P_DATA_TYPES.NUMB ? "number" : setting.dataType === P8P_DATA_TYPES.DATE ? "date" : "text"
|
|
||||||
}
|
|
||||||
]}
|
|
||||||
onInputChange={handleSettingChange}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Контроль свойств компонента - Диалог изменения параметра
|
|
||||||
P8PSettingChangeDialog.propTypes = {
|
|
||||||
initSetting: PropTypes.object,
|
|
||||||
onSave: PropTypes.func,
|
|
||||||
onClose: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------
|
|
||||||
//Тело модуля
|
|
||||||
//-----------
|
|
||||||
|
|
||||||
//Список параметров
|
|
||||||
const P8PSettingsList = ({ settings, onSettingChange }) => {
|
|
||||||
//Собственное состояние - изменяемый параметр
|
|
||||||
const [changingSetting, setChangingSetting] = useState(null);
|
|
||||||
|
|
||||||
//При нажатии на параметр
|
|
||||||
const handleSettingClick = settingCode => setChangingSetting(settingCode);
|
|
||||||
|
|
||||||
//При очистки изменяемого параметра
|
|
||||||
const handleChangingSettingClear = () => setChangingSetting(null);
|
|
||||||
|
|
||||||
//При изменении значения параметра
|
|
||||||
const handleSettingChange = newSetting => {
|
|
||||||
//Вызываем изменение параметра
|
|
||||||
onSettingChange && onSettingChange(changingSetting, newSetting);
|
|
||||||
//Очищаем изменяемый параметр
|
|
||||||
handleChangingSettingClear();
|
|
||||||
};
|
|
||||||
|
|
||||||
//Формирование представления
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<List sx={STYLES.LIST}>
|
|
||||||
{Object.keys(settings).map((setting, i) => {
|
|
||||||
return (
|
|
||||||
<ListItem key={i}>
|
|
||||||
<ListItemButton onClick={() => handleSettingClick(setting)}>
|
|
||||||
<ListItemText
|
|
||||||
primary={settings[setting].name}
|
|
||||||
secondaryTypographyProps={{ component: "div" }}
|
|
||||||
secondary={
|
|
||||||
<Stack direction={"row"} justifyContent={"space-between"} gap={2}>
|
|
||||||
<Typography
|
|
||||||
variant={"caption"}
|
|
||||||
noWrap={true}
|
|
||||||
title={settings[setting].desc ? settings[setting].desc : "Описание отсутствует"}
|
|
||||||
>{`${settings[setting].desc ? settings[setting].desc : "Описание отсутствует"}`}</Typography>
|
|
||||||
<Typography
|
|
||||||
variant={"caption"}
|
|
||||||
sx={STYLES.TYPOGRAPHY_VALUE}
|
|
||||||
noWrap={true}
|
|
||||||
title={settings[setting].value}
|
|
||||||
>{`${settings[setting].value}`}</Typography>
|
|
||||||
</Stack>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ListItemButton>
|
|
||||||
</ListItem>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</List>
|
|
||||||
{changingSetting ? (
|
|
||||||
<P8PSettingChangeDialog initSetting={settings[changingSetting]} onSave={handleSettingChange} onClose={handleChangingSettingClear} />
|
|
||||||
) : null}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Контроль свойств компонента - Список параметров
|
|
||||||
P8PSettingsList.propTypes = {
|
|
||||||
settings: PropTypes.object,
|
|
||||||
onSettingChange: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------
|
|
||||||
//Интерфейс модуля
|
|
||||||
//----------------
|
|
||||||
|
|
||||||
export { P8PSettingsList };
|
|
||||||
@ -37,7 +37,6 @@ import {
|
|||||||
import { useTheme } from "@mui/material/styles"; //Взаимодействие со стилями MUI
|
import { useTheme } from "@mui/material/styles"; //Взаимодействие со стилями MUI
|
||||||
import { P8PAppInlineError, P8PHintDialog } from "./p8p_app_message"; //Встраиваемое сообщение об ошибке
|
import { P8PAppInlineError, P8PHintDialog } from "./p8p_app_message"; //Встраиваемое сообщение об ошибке
|
||||||
import { P8P_TABLE_AT, HEADER_INITIAL_STATE, hasValue, p8pTableReducer } from "./p8p_table_reducer"; //Редьюсер состояния
|
import { P8P_TABLE_AT, HEADER_INITIAL_STATE, hasValue, p8pTableReducer } from "./p8p_table_reducer"; //Редьюсер состояния
|
||||||
import { P8P_DATA_TYPES } from "../core/data_types"; //Типы данных
|
|
||||||
|
|
||||||
//---------
|
//---------
|
||||||
//Константы
|
//Константы
|
||||||
@ -51,9 +50,9 @@ const P8P_TABLE_SIZE = {
|
|||||||
|
|
||||||
//Типы данных
|
//Типы данных
|
||||||
const P8P_TABLE_DATA_TYPE = {
|
const P8P_TABLE_DATA_TYPE = {
|
||||||
STR: P8P_DATA_TYPES.STR,
|
STR: "STR",
|
||||||
NUMB: P8P_DATA_TYPES.NUMB,
|
NUMB: "NUMB",
|
||||||
DATE: P8P_DATA_TYPES.DATE
|
DATE: "DATE"
|
||||||
};
|
};
|
||||||
|
|
||||||
//Направления сортировки
|
//Направления сортировки
|
||||||
|
|||||||
@ -30,8 +30,7 @@ const P8P_PANELS_MENU_GRID_CONFIG_PROPS = {
|
|||||||
//Конфигурируемые свойства "Рабочего пространства" (P8PAppWorkspace)
|
//Конфигурируемые свойства "Рабочего пространства" (P8PAppWorkspace)
|
||||||
const P8P_APP_WORKSPACE_CONFIG_PROPS = {
|
const P8P_APP_WORKSPACE_CONFIG_PROPS = {
|
||||||
closeCaption: BUTTONS.CLOSE,
|
closeCaption: BUTTONS.CLOSE,
|
||||||
homeCaption: BUTTONS.NAVIGATE_HOME,
|
homeCaption: BUTTONS.NAVIGATE_HOME
|
||||||
settingsCaption: BUTTONS.NAVIGATE_SETTINGS
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//Конфигурируемые свойства "Таблицы" (P8PTable)
|
//Конфигурируемые свойства "Таблицы" (P8PTable)
|
||||||
|
|||||||
@ -39,7 +39,7 @@ export const ApplicationContext = ({ errors, displaySizeGetter, guidGenerator, c
|
|||||||
const [state, dispatch] = useReducer(applicationReducer, INITIAL_STATE(displaySizeGetter));
|
const [state, dispatch] = useReducer(applicationReducer, INITIAL_STATE(displaySizeGetter));
|
||||||
|
|
||||||
//Подключение к контексту взаимодействия с сервером
|
//Подключение к контексту взаимодействия с сервером
|
||||||
const { getConfig, getRespPayload, executeStored } = useContext(BackEndCtx);
|
const { getConfig, getRespPayload } = useContext(BackEndCtx);
|
||||||
|
|
||||||
//Подключение к контексту отображения сообщений
|
//Подключение к контексту отображения сообщений
|
||||||
const { showMsgErr } = useContext(MessagingCtx);
|
const { showMsgErr } = useContext(MessagingCtx);
|
||||||
@ -54,7 +54,7 @@ export const ApplicationContext = ({ errors, displaySizeGetter, guidGenerator, c
|
|||||||
const setUrlBase = urlBase => dispatch({ type: APP_AT.SET_URL_BASE, payload: urlBase });
|
const setUrlBase = urlBase => dispatch({ type: APP_AT.SET_URL_BASE, payload: urlBase });
|
||||||
|
|
||||||
//Установка списка панелей
|
//Установка списка панелей
|
||||||
const setPanels = (panels, panelsSettings) => dispatch({ type: APP_AT.LOAD_PANELS, payload: { panels, panelsSettings } });
|
const setPanels = panels => dispatch({ type: APP_AT.LOAD_PANELS, payload: panels });
|
||||||
|
|
||||||
//Установка заголовка в шапке приложения
|
//Установка заголовка в шапке приложения
|
||||||
const setAppBarTitle = useCallback(appBarTitle => dispatch({ type: APP_AT.SET_APP_BAR_TITLE, payload: appBarTitle }), []);
|
const setAppBarTitle = useCallback(appBarTitle => dispatch({ type: APP_AT.SET_APP_BAR_TITLE, payload: appBarTitle }), []);
|
||||||
@ -62,12 +62,6 @@ export const ApplicationContext = ({ errors, displaySizeGetter, guidGenerator, c
|
|||||||
//Установка флага отображения шапки приложения
|
//Установка флага отображения шапки приложения
|
||||||
const setAppBarShow = useCallback(appBarShow => dispatch({ type: APP_AT.SET_APP_BAR_SHOW, payload: appBarShow }), []);
|
const setAppBarShow = useCallback(appBarShow => dispatch({ type: APP_AT.SET_APP_BAR_SHOW, payload: appBarShow }), []);
|
||||||
|
|
||||||
//Установка флага отображения настройки параметров в шапке приложения
|
|
||||||
const setAppBarSettingsShow = useCallback(
|
|
||||||
appBarSettingsShow => dispatch({ type: APP_AT.SET_APP_BAR_SETTINGS_SHOW, payload: appBarSettingsShow }),
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
//Поиск раздела по имени
|
//Поиск раздела по имени
|
||||||
const findPanelByName = name => state.panels.find(panel => panel.name == name);
|
const findPanelByName = name => state.panels.find(panel => panel.name == name);
|
||||||
|
|
||||||
@ -153,36 +147,17 @@ export const ApplicationContext = ({ errors, displaySizeGetter, guidGenerator, c
|
|||||||
//Получение базового URL приложения
|
//Получение базового URL приложения
|
||||||
const configUrlBase = useMemo(() => state.urlBase, [state.urlBase]);
|
const configUrlBase = useMemo(() => state.urlBase, [state.urlBase]);
|
||||||
|
|
||||||
//Инициализация информации о параметрах панелей
|
|
||||||
const initPanelsParams = useCallback(async () => {
|
|
||||||
//Инициализируем параметры панелей
|
|
||||||
try {
|
|
||||||
const res = await executeStored({
|
|
||||||
stored: "PKG_P8PANELS_SETTINGS.PANELS_INIT",
|
|
||||||
respArg: "COUT",
|
|
||||||
loader: false
|
|
||||||
});
|
|
||||||
return res;
|
|
||||||
} catch (e) {
|
|
||||||
showMsgErr(`Ошибка инициализации параметров панелей.`, null, e.message);
|
|
||||||
}
|
|
||||||
}, [executeStored, showMsgErr]);
|
|
||||||
|
|
||||||
//Инициализация приложения
|
//Инициализация приложения
|
||||||
const initApp = useCallback(async () => {
|
const initApp = useCallback(async () => {
|
||||||
//Читаем конфигурацию с сервера
|
//Читаем конфигурацию с сервера
|
||||||
let res = await getConfig();
|
let res = await getConfig();
|
||||||
//Сохраняем базовый URL приложения
|
//Сохраняем базовый URL приложения
|
||||||
setUrlBase(getRespPayload(res)?.Panels?.urlBase);
|
setUrlBase(getRespPayload(res)?.Panels?.urlBase);
|
||||||
//Инициализируем панели
|
|
||||||
const panels = getRespPayload(res)?.Panels?.Panel;
|
|
||||||
//Инициализируем информацию о параметрах панелей
|
|
||||||
const panelsSettings = await initPanelsParams();
|
|
||||||
//Сохраняем список панелей
|
//Сохраняем список панелей
|
||||||
setPanels(panels, panelsSettings);
|
setPanels(getRespPayload(res)?.Panels?.Panel);
|
||||||
//Установим флаг завершения инициализации
|
//Установим флаг завершения инициализации
|
||||||
setInitialized();
|
setInitialized();
|
||||||
}, [getConfig, getRespPayload, initPanelsParams]);
|
}, [getConfig, getRespPayload]);
|
||||||
|
|
||||||
//Обработка подключения контекста к странице
|
//Обработка подключения контекста к странице
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -202,7 +177,6 @@ export const ApplicationContext = ({ errors, displaySizeGetter, guidGenerator, c
|
|||||||
value={{
|
value={{
|
||||||
setAppBarTitle,
|
setAppBarTitle,
|
||||||
setAppBarShow,
|
setAppBarShow,
|
||||||
setAppBarSettingsShow,
|
|
||||||
findPanelByName,
|
findPanelByName,
|
||||||
pOnlineShowTab,
|
pOnlineShowTab,
|
||||||
pOnlineShowUnit,
|
pOnlineShowUnit,
|
||||||
|
|||||||
@ -14,8 +14,7 @@ const APP_AT = {
|
|||||||
SET_INITIALIZED: "SET_INITIALIZED", //Установка флага инициализированности приложения
|
SET_INITIALIZED: "SET_INITIALIZED", //Установка флага инициализированности приложения
|
||||||
SET_DISPLAY_SIZE: "SET_DISPLAY_SIZE", //Установка текущего типового размера экрана
|
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", //Установка флага отображения шапки приложения
|
SET_APP_BAR_SHOW: "SET_APP_BAR_SHOW" //Установка флага отображения шапки приложения
|
||||||
SET_APP_BAR_SETTINGS_SHOW: "SET_APP_BAR_SETTINGS_SHOW" //Установка флага отображения настройки параметров в шапке приложения
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//Состояние приложения по умолчанию
|
//Состояние приложения по умолчанию
|
||||||
@ -23,7 +22,6 @@ const INITIAL_STATE = displaySizeGetter => ({
|
|||||||
displaySize: displaySizeGetter(),
|
displaySize: displaySizeGetter(),
|
||||||
appBarTitle: "",
|
appBarTitle: "",
|
||||||
appBarShow: true,
|
appBarShow: true,
|
||||||
appBarSettingsShow: true,
|
|
||||||
urlBase: "",
|
urlBase: "",
|
||||||
panels: [],
|
panels: [],
|
||||||
panelsLoaded: false,
|
panelsLoaded: false,
|
||||||
@ -41,8 +39,7 @@ const handlers = {
|
|||||||
//Загрузка списка панелей
|
//Загрузка списка панелей
|
||||||
[APP_AT.LOAD_PANELS]: (state, { payload }) => {
|
[APP_AT.LOAD_PANELS]: (state, { payload }) => {
|
||||||
let panels = [];
|
let panels = [];
|
||||||
if (payload && Array.isArray(payload.panels))
|
if (payload && Array.isArray(payload)) for (let p of payload) panels.push({ ...p });
|
||||||
for (let p of payload.panels) panels.push({ ...p, showUserSettings: payload?.panelsSettings?.[p.name]?.userSettings === 1 ? true : false });
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
panels,
|
panels,
|
||||||
@ -57,8 +54,6 @@ const handlers = {
|
|||||||
[APP_AT.SET_APP_BAR_TITLE]: (state, { payload }) => ({ ...state, appBarTitle: payload }),
|
[APP_AT.SET_APP_BAR_TITLE]: (state, { payload }) => ({ ...state, appBarTitle: payload }),
|
||||||
//Установка флага отображения шапки приложения
|
//Установка флага отображения шапки приложения
|
||||||
[APP_AT.SET_APP_BAR_SHOW]: (state, { payload }) => ({ ...state, appBarShow: payload }),
|
[APP_AT.SET_APP_BAR_SHOW]: (state, { payload }) => ({ ...state, appBarShow: payload }),
|
||||||
//Установка флага отображения настройки параметров в шапке приложения
|
|
||||||
[APP_AT.SET_APP_BAR_SETTINGS_SHOW]: (state, { payload }) => ({ ...state, appBarSettingsShow: payload }),
|
|
||||||
//Обработчик по умолчанию
|
//Обработчик по умолчанию
|
||||||
DEFAULT: state => state
|
DEFAULT: state => state
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,172 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга
|
|
||||||
Контекст: Взаимодействие с API параметров
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---------------------
|
|
||||||
//Подключение библиотек
|
|
||||||
//---------------------
|
|
||||||
|
|
||||||
import React, { createContext, useContext, useCallback, useState, useRef } from "react"; //ReactJS
|
|
||||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
|
||||||
import { MessagingCtx } from "./messaging"; //Контекст сообщений
|
|
||||||
import { P8PSettingsDialog } from "../components/p8p_settings_dialog"; //Диалог отображения параметров
|
|
||||||
import { useSettingsContext } from "./settings_hooks"; //Вспомогательные хуки параметров
|
|
||||||
|
|
||||||
//---------
|
|
||||||
//Константы
|
|
||||||
//---------
|
|
||||||
|
|
||||||
//Доступные виды параметров
|
|
||||||
const SETTINGS_KINDS = {
|
|
||||||
SYSTEM: 0,
|
|
||||||
PANEL: 1,
|
|
||||||
USER: 2
|
|
||||||
};
|
|
||||||
|
|
||||||
//Доступные действия параметров
|
|
||||||
const SETTINGS_ACTIONS = {
|
|
||||||
INIT: "INIT",
|
|
||||||
GET: "GET",
|
|
||||||
PUT: "PUT"
|
|
||||||
};
|
|
||||||
|
|
||||||
//Псевдокод панели для системных параметров
|
|
||||||
const SETTINGS_SYSTEM_PSEUDO = "__P8_SYSTEM";
|
|
||||||
|
|
||||||
//----------------
|
|
||||||
//Интерфейс модуля
|
|
||||||
//----------------
|
|
||||||
|
|
||||||
//Контекст взаимодействия с API параметров
|
|
||||||
export const SettingsCtx = createContext();
|
|
||||||
|
|
||||||
//Провайдер контекста взаимодействия с API параметров
|
|
||||||
export const SettingsContext = ({ children }) => {
|
|
||||||
//Подключение к контексту сообщений
|
|
||||||
const { showMsgErr } = useContext(MessagingCtx);
|
|
||||||
|
|
||||||
//Собственное состояние - действия параметров
|
|
||||||
const { putPanelSettings, getPanelSettings, initPanelSettings } = useSettingsContext(showMsgErr);
|
|
||||||
//Собственное состояние - отображаемые параметры
|
|
||||||
const [settings, setSettings] = useState({ isOpen: false, data: {}, panel: null });
|
|
||||||
//Собственное состояние - колбэки для обработки событий
|
|
||||||
const settingsCallbacks = useRef({ onOk: null, onCancel: null });
|
|
||||||
|
|
||||||
//Формирование структуры параметров панели
|
|
||||||
const buildPanelSettings = (kind, panel, settings) =>
|
|
||||||
kind === SETTINGS_KINDS.SYSTEM ? { [SETTINGS_SYSTEM_PSEUDO]: { ...settings } } : { [panel]: { ...settings } };
|
|
||||||
|
|
||||||
//Извлечение настроек из ответа сервера
|
|
||||||
const extractSettings = (res, kind, panel) =>
|
|
||||||
kind === SETTINGS_KINDS.SYSTEM ? { ...(res[SETTINGS_SYSTEM_PSEUDO] || {}) } : { ...(panel ? res[panel] : res) };
|
|
||||||
|
|
||||||
//Валидация параметров настройки
|
|
||||||
const validateSettingsParams = useCallback(
|
|
||||||
({ action, kind, panel }) => {
|
|
||||||
if ([SETTINGS_KINDS.PANEL, SETTINGS_KINDS.USER].includes(kind) && !panel) {
|
|
||||||
//Формируем текст ошибки
|
|
||||||
const errMsg = `Ошибка ${
|
|
||||||
action === SETTINGS_ACTIONS.INIT ? "инициализации" : action === SETTINGS_ACTIONS.PUT ? "добавления" : "действия"
|
|
||||||
} параметров. Для панельных/пользовательских параметров необходимо указать панель.`;
|
|
||||||
//Отображаем ошибку
|
|
||||||
showMsgErr(errMsg);
|
|
||||||
throw new Error(errMsg);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[showMsgErr]
|
|
||||||
);
|
|
||||||
|
|
||||||
//Добавление параметров панелей
|
|
||||||
const putSettings = useCallback(
|
|
||||||
async ({ kind, settings, panel = null, loader = true }) => {
|
|
||||||
//Проверка корректности параметров
|
|
||||||
validateSettingsParams({ action: SETTINGS_ACTIONS.PUT, kind, panel });
|
|
||||||
//Оборачиваем параметры в панель
|
|
||||||
const panelSettings = buildPanelSettings(kind, panel, settings);
|
|
||||||
//Добавляем параметры панели
|
|
||||||
const res = await putPanelSettings({ kind, panelSettings, loader });
|
|
||||||
//Возвращаем результат
|
|
||||||
return res;
|
|
||||||
},
|
|
||||||
[putPanelSettings, validateSettingsParams]
|
|
||||||
);
|
|
||||||
|
|
||||||
//Считывание параметров
|
|
||||||
const getSettings = useCallback(
|
|
||||||
async ({ kind, code = null, panel = null, full = false, loader = true }) => {
|
|
||||||
//Считываем параметры панели
|
|
||||||
const res = await getPanelSettings({ kind, code, panel, full, loader });
|
|
||||||
//Возвращаем результат
|
|
||||||
return extractSettings(res, kind, panel);
|
|
||||||
},
|
|
||||||
[getPanelSettings]
|
|
||||||
);
|
|
||||||
|
|
||||||
//Инициализация параметров
|
|
||||||
const initSettings = useCallback(
|
|
||||||
async ({ kind, settings, panel = null, full = false, loader = true }) => {
|
|
||||||
//Проверка корректности параметров
|
|
||||||
validateSettingsParams({ action: SETTINGS_ACTIONS.INIT, kind, panel });
|
|
||||||
//Оборачиваем параметры в панель
|
|
||||||
const panelSettings = buildPanelSettings(kind, panel, settings);
|
|
||||||
//Добавляем параметры панели
|
|
||||||
const res = await initPanelSettings({ kind, panelSettings, full, loader });
|
|
||||||
//Возвращаем результат
|
|
||||||
return extractSettings(res, kind, panel);
|
|
||||||
},
|
|
||||||
[initPanelSettings, validateSettingsParams]
|
|
||||||
);
|
|
||||||
|
|
||||||
//При нажатии "ОК" диалога параметров
|
|
||||||
const handleOk = async newSettings => {
|
|
||||||
//Признак наличия изменений параметров
|
|
||||||
const isChanged = JSON.stringify(newSettings) !== JSON.stringify(settings.data);
|
|
||||||
//Если параметры изменились - обновляем на сервере
|
|
||||||
if (isChanged) await putPanelSettings({ kind: SETTINGS_KINDS.USER, panelSettings: newSettings });
|
|
||||||
//Если есть колбэк на нажатие "ОК" - вызываем его
|
|
||||||
if (settingsCallbacks.current.onOk)
|
|
||||||
settingsCallbacks.current.onOk({ settings: settings.panel ? newSettings[settings.panel] : newSettings, isChanged });
|
|
||||||
//Сбрасываем отображаемые данные
|
|
||||||
setSettings({ isOpen: false, data: {}, panel: null });
|
|
||||||
};
|
|
||||||
|
|
||||||
//При нажатии "Отменить" диалога параметров
|
|
||||||
const handleClose = () => {
|
|
||||||
//Если есть колбэк на нажатие "Отменить" - вызываем его
|
|
||||||
if (settingsCallbacks.current.onCancel) settingsCallbacks.current.onCancel();
|
|
||||||
//Сбрасываем отображаемые данные
|
|
||||||
setSettings({ isOpen: false, data: {}, panel: null });
|
|
||||||
};
|
|
||||||
|
|
||||||
//Открытие диалога параметров
|
|
||||||
const showSettingsDialog = async ({ panel = null, onOk = null, onCancel = null } = {}) => {
|
|
||||||
//Загружаем информацию о параметрах
|
|
||||||
const panelSettings = await getPanelSettings({ kind: SETTINGS_KINDS.USER, panel, full: true });
|
|
||||||
//Устанавливаем отображаемые данные
|
|
||||||
setSettings({ isOpen: true, data: panelSettings, panel });
|
|
||||||
//Устанавливаем колбэки
|
|
||||||
settingsCallbacks.current = { onOk, onCancel };
|
|
||||||
};
|
|
||||||
|
|
||||||
//Вернём компонент провайдера
|
|
||||||
return (
|
|
||||||
<SettingsCtx.Provider
|
|
||||||
value={{
|
|
||||||
SETTINGS_KINDS,
|
|
||||||
initSettings,
|
|
||||||
getSettings,
|
|
||||||
putSettings,
|
|
||||||
showSettingsDialog
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{settings.isOpen ? <P8PSettingsDialog settings={settings.data} panel={settings.panel} onOk={handleOk} onClose={handleClose} /> : null}
|
|
||||||
{children}
|
|
||||||
</SettingsCtx.Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Контроль свойств - Провайдер контекста взаимодействия с API параметров
|
|
||||||
SettingsContext.propTypes = {
|
|
||||||
children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node])
|
|
||||||
};
|
|
||||||
@ -1,120 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга
|
|
||||||
Контекст: Параметры - вспомогательные хуки
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---------------------
|
|
||||||
//Подключение библиотек
|
|
||||||
//---------------------
|
|
||||||
|
|
||||||
import { useCallback, useContext } from "react"; //Классы React
|
|
||||||
import { BackEndCtx } from "./backend"; //Контекст взаимодействия с сервером
|
|
||||||
import { object2Base64XML, formatErrorMessage } from "../core/utils"; //Вспомогательные функции
|
|
||||||
|
|
||||||
//-----------
|
|
||||||
//Тело модуля
|
|
||||||
//-----------
|
|
||||||
|
|
||||||
//Хук для SettingsContext
|
|
||||||
const useSettingsContext = showMsgErr => {
|
|
||||||
//Подключение к контексту взаимодействия с сервером
|
|
||||||
const { executeStored, SERV_DATA_TYPE_CLOB } = useContext(BackEndCtx);
|
|
||||||
|
|
||||||
//Добавление параметров панели
|
|
||||||
const putPanelSettings = useCallback(
|
|
||||||
async ({ kind, panelSettings, loader = true }) => {
|
|
||||||
//Добавляем параметры
|
|
||||||
try {
|
|
||||||
await executeStored({
|
|
||||||
stored: "PKG_P8PANELS_SETTINGS.PUT",
|
|
||||||
args: {
|
|
||||||
NKIND: kind,
|
|
||||||
CPANELS: {
|
|
||||||
VALUE: object2Base64XML({
|
|
||||||
XPANELS: panelSettings
|
|
||||||
}),
|
|
||||||
SDATA_TYPE: SERV_DATA_TYPE_CLOB
|
|
||||||
}
|
|
||||||
},
|
|
||||||
loader
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
//Разбираем текст ошибки
|
|
||||||
let errMsg = formatErrorMessage(e.message);
|
|
||||||
//Отображаем ошибку
|
|
||||||
showMsgErr(errMsg.text, null, errMsg.fullErrorText);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[SERV_DATA_TYPE_CLOB, executeStored, showMsgErr]
|
|
||||||
);
|
|
||||||
|
|
||||||
//Считывание параметров
|
|
||||||
const getPanelSettings = useCallback(
|
|
||||||
async ({ kind, code = null, panel = null, full = false, loader = true }) => {
|
|
||||||
//Считываем параметры
|
|
||||||
try {
|
|
||||||
const res = await executeStored({
|
|
||||||
stored: "PKG_P8PANELS_SETTINGS.GET",
|
|
||||||
args: {
|
|
||||||
NKIND: kind,
|
|
||||||
SCODE: code,
|
|
||||||
SPANEL: panel,
|
|
||||||
NFULL: full ? 1 : 0
|
|
||||||
},
|
|
||||||
loader,
|
|
||||||
respArg: "COUT"
|
|
||||||
});
|
|
||||||
return res || {};
|
|
||||||
} catch (e) {
|
|
||||||
//Разбираем текст ошибки
|
|
||||||
let errMsg = formatErrorMessage(e.message);
|
|
||||||
//Отображаем ошибку
|
|
||||||
showMsgErr(errMsg.text, null, errMsg.fullErrorText);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[executeStored, showMsgErr]
|
|
||||||
);
|
|
||||||
|
|
||||||
//Инициализация параметров панелей
|
|
||||||
const initPanelSettings = useCallback(
|
|
||||||
async ({ kind, panelSettings, full = false, loader = true }) => {
|
|
||||||
//Инициализируем параметры
|
|
||||||
try {
|
|
||||||
const res = await executeStored({
|
|
||||||
stored: "PKG_P8PANELS_SETTINGS.INIT",
|
|
||||||
args: {
|
|
||||||
NKIND: kind,
|
|
||||||
CPANELS: {
|
|
||||||
VALUE: object2Base64XML({
|
|
||||||
XPANELS: panelSettings
|
|
||||||
}),
|
|
||||||
SDATA_TYPE: SERV_DATA_TYPE_CLOB
|
|
||||||
},
|
|
||||||
NFULL: full ? 1 : 0
|
|
||||||
},
|
|
||||||
loader,
|
|
||||||
respArg: "COUT"
|
|
||||||
});
|
|
||||||
return res;
|
|
||||||
} catch (e) {
|
|
||||||
//Разбираем текст ошибки
|
|
||||||
let errMsg = formatErrorMessage(e.message);
|
|
||||||
//Отображаем ошибку
|
|
||||||
showMsgErr(errMsg.text, null, errMsg.fullErrorText);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[SERV_DATA_TYPE_CLOB, executeStored, showMsgErr]
|
|
||||||
);
|
|
||||||
|
|
||||||
//Возвращаем результат
|
|
||||||
return { putPanelSettings, getPanelSettings, initPanelSettings };
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------
|
|
||||||
//Интерфейс модуля
|
|
||||||
//----------------
|
|
||||||
|
|
||||||
export { useSettingsContext };
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга
|
|
||||||
Ядро: Типы данных
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---------
|
|
||||||
//Константы
|
|
||||||
//---------
|
|
||||||
|
|
||||||
//Типы данных
|
|
||||||
export const P8P_DATA_TYPES = {
|
|
||||||
STR: "STR",
|
|
||||||
NUMB: "NUMB",
|
|
||||||
DATE: "DATE"
|
|
||||||
};
|
|
||||||
@ -7,7 +7,7 @@
|
|||||||
//Подключение библиотек
|
//Подключение библиотек
|
||||||
//---------------------
|
//---------------------
|
||||||
|
|
||||||
import React, { useState, useEffect, useContext } from "react"; //Классы React
|
import React, { useState } from "react"; //Классы React
|
||||||
import { Button, Fab, Icon } from "@mui/material"; //Интерфейсные элементы
|
import { Button, Fab, Icon } from "@mui/material"; //Интерфейсные элементы
|
||||||
import { BUTTONS } from "../../../app.text"; //Текстовые ресурсы и константы
|
import { BUTTONS } from "../../../app.text"; //Текстовые ресурсы и константы
|
||||||
import { P8Online } from "./p8online"; //Пример: API для взаимодействия с "ПАРУС 8 Онлайн"
|
import { P8Online } from "./p8online"; //Пример: API для взаимодействия с "ПАРУС 8 Онлайн"
|
||||||
@ -20,8 +20,6 @@ import { Gantt } from "./gantt"; //Пример: Диаграмма Ганта "
|
|||||||
import { Svg } from "./svg"; //Пример: Интерактивные изображения "P8PSVG"
|
import { Svg } from "./svg"; //Пример: Интерактивные изображения "P8PSVG"
|
||||||
import { Cyclogram } from "./cyclogram"; //Пример: Циклограмма "P8PCyclogram"
|
import { Cyclogram } from "./cyclogram"; //Пример: Циклограмма "P8PCyclogram"
|
||||||
import { Indicator } from "./indicator"; //Пример: Индикатор "P8PIndicator"
|
import { Indicator } from "./indicator"; //Пример: Индикатор "P8PIndicator"
|
||||||
import { Settings } from "./settings"; //Пример: Параметры панелей
|
|
||||||
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
|
|
||||||
|
|
||||||
//---------
|
//---------
|
||||||
//Константы
|
//Константы
|
||||||
@ -38,8 +36,7 @@ const MODES = {
|
|||||||
GANTT: { name: "GANTT", caption: 'Диаграмма Ганта "P8PGantt"', component: Gantt },
|
GANTT: { name: "GANTT", caption: 'Диаграмма Ганта "P8PGantt"', component: Gantt },
|
||||||
SVG: { name: "SVG", caption: 'Интерактивные изображения "P8PSVG"', component: Svg },
|
SVG: { name: "SVG", caption: 'Интерактивные изображения "P8PSVG"', component: Svg },
|
||||||
CYCLOGRAM: { name: "CYCLOGRAM", caption: 'Циклограмма "P8PCyclogram"', component: Cyclogram },
|
CYCLOGRAM: { name: "CYCLOGRAM", caption: 'Циклограмма "P8PCyclogram"', component: Cyclogram },
|
||||||
INDICATOR: { name: "INDICATOR", caption: 'Индикатор "P8PIndicator"', component: Indicator },
|
INDICATOR: { name: "INDICATOR", caption: 'Индикатор "P8PIndicator"', component: Indicator }
|
||||||
SETTINGS: { name: "SETTINGS", caption: "Параметры панелей", component: Settings }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//Стили
|
//Стили
|
||||||
@ -58,15 +55,6 @@ const Samples = () => {
|
|||||||
//Собственное состояние
|
//Собственное состояние
|
||||||
const [mode, setMode] = useState("");
|
const [mode, setMode] = useState("");
|
||||||
|
|
||||||
//Подключение к контексту приложения
|
|
||||||
const { setAppBarSettingsShow } = useContext(ApplicationCtx);
|
|
||||||
|
|
||||||
//При загрузке/открытии режима
|
|
||||||
useEffect(() => {
|
|
||||||
if (mode === MODES.SETTINGS.name) setAppBarSettingsShow(true);
|
|
||||||
else setAppBarSettingsShow(false);
|
|
||||||
}, [mode, setAppBarSettingsShow]);
|
|
||||||
|
|
||||||
//Генерация содержимого
|
//Генерация содержимого
|
||||||
return (
|
return (
|
||||||
<div style={STYLES.ROOT}>
|
<div style={STYLES.ROOT}>
|
||||||
|
|||||||
@ -1,235 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга - Примеры для разработчиков
|
|
||||||
Пример: Сообщения
|
|
||||||
*/
|
|
||||||
|
|
||||||
//---------------------
|
|
||||||
//Подключение библиотек
|
|
||||||
//---------------------
|
|
||||||
|
|
||||||
import React, { useContext, useState, useEffect } from "react"; //Классы React
|
|
||||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
|
||||||
import { Typography, Divider, Button, Box } from "@mui/material"; //Интерфейсные элементы
|
|
||||||
import { SettingsCtx } from "../../context/settings"; //Контекст параметров
|
|
||||||
import { P8P_DATA_TYPES } from "../../core/data_types"; //Типы данных
|
|
||||||
import { formatDateJSONDateOnly } from "../../core/utils"; //Вспомогательные функции
|
|
||||||
import { ApplicationCtx } from "../../context/application"; //Контекст приложения
|
|
||||||
|
|
||||||
//---------
|
|
||||||
//Константы
|
|
||||||
//---------
|
|
||||||
|
|
||||||
//Стили
|
|
||||||
const STYLES = {
|
|
||||||
CONTAINER: { textAlign: "center", paddingTop: "20px" },
|
|
||||||
TITLE: { paddingBottom: "15px" },
|
|
||||||
DIVIDER: { margin: "15px" },
|
|
||||||
BOX_SETTINGS_VALUES: { display: "flex", justifyContent: "space-around" },
|
|
||||||
SETTING_CARD: {
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
alignItems: "center",
|
|
||||||
padding: "12px 16px",
|
|
||||||
borderRadius: 1,
|
|
||||||
border: "1px solid",
|
|
||||||
borderColor: "divider"
|
|
||||||
},
|
|
||||||
SETTING_NAME: {
|
|
||||||
fontWeight: 500,
|
|
||||||
color: "text.primary"
|
|
||||||
},
|
|
||||||
SETTING_VALUE: {
|
|
||||||
fontWeight: 600,
|
|
||||||
color: "primary.main",
|
|
||||||
marginLeft: 2
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//Наименование панели
|
|
||||||
const PANEL_NAME = "Samples";
|
|
||||||
|
|
||||||
//Параметры панели
|
|
||||||
const PANEL_PARAMS = {
|
|
||||||
STR_PARAM: {
|
|
||||||
name: "Строковый параметр",
|
|
||||||
dataType: P8P_DATA_TYPES.STR,
|
|
||||||
//value: "Строковое значение",
|
|
||||||
desc: "Описание строкового параметра"
|
|
||||||
},
|
|
||||||
NUM_PARAM: {
|
|
||||||
name: "Числовой параметр",
|
|
||||||
dataType: P8P_DATA_TYPES.NUMB,
|
|
||||||
value: 10,
|
|
||||||
desc: "Описание числового параметра"
|
|
||||||
},
|
|
||||||
DATE_PARAM: {
|
|
||||||
name: "Параметр дата",
|
|
||||||
dataType: P8P_DATA_TYPES.DATE,
|
|
||||||
value: "2026-02-15",
|
|
||||||
desc: ""
|
|
||||||
},
|
|
||||||
AGENT: {
|
|
||||||
name: "Привязка к контрагенту",
|
|
||||||
dataType: P8P_DATA_TYPES.STR,
|
|
||||||
value: "",
|
|
||||||
desc: "Мнемокод выбранного контрагента",
|
|
||||||
options: {
|
|
||||||
unitcode: "AGNLIST",
|
|
||||||
showMethod: "main",
|
|
||||||
inParameter: "in_AGNABBR",
|
|
||||||
outParameter: "out_AGNABBR"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//Параметр "Дата последнего обновления"
|
|
||||||
const LAST_UPDATE_PARAM = {
|
|
||||||
LAST_UPDATE: {
|
|
||||||
name: "Дата последнего обновления",
|
|
||||||
dataType: "DATE",
|
|
||||||
value: formatDateJSONDateOnly(new Date()),
|
|
||||||
desc: ""
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------
|
|
||||||
//Тело модуля
|
|
||||||
//-----------
|
|
||||||
|
|
||||||
//Пример: Параметры
|
|
||||||
const Settings = ({ title }) => {
|
|
||||||
//Собственное состояние - параметры
|
|
||||||
const [state, setState] = useState({});
|
|
||||||
//Собственное состояние - отображение кнопки параметров панели
|
|
||||||
const [showPanelSettings, setShowPanelSettings] = useState(true);
|
|
||||||
|
|
||||||
//Подключение к контексту параметров
|
|
||||||
const { getSettings, initSettings, putSettings, showSettingsDialog, SETTINGS_KINDS } = useContext(SettingsCtx);
|
|
||||||
//Подключение к контексту приложения
|
|
||||||
const { setAppBarSettingsShow } = useContext(ApplicationCtx);
|
|
||||||
|
|
||||||
//Инициализация параметров пользователя
|
|
||||||
const handleInitSettings = async () => {
|
|
||||||
// Инициализация пользовательских параметров
|
|
||||||
const settings = await initSettings({
|
|
||||||
kind: SETTINGS_KINDS.USER,
|
|
||||||
panel: PANEL_NAME,
|
|
||||||
settings: PANEL_PARAMS
|
|
||||||
});
|
|
||||||
//Устанавливаем параметры
|
|
||||||
setState({ ...settings });
|
|
||||||
};
|
|
||||||
|
|
||||||
//Загрузка параметров пользователя
|
|
||||||
const handleLoadSettings = async () => {
|
|
||||||
// Считывание параметров панели
|
|
||||||
const settings = await getSettings({
|
|
||||||
kind: SETTINGS_KINDS.USER,
|
|
||||||
panel: PANEL_NAME
|
|
||||||
});
|
|
||||||
//Устанавливаем параметры
|
|
||||||
setState({ ...settings });
|
|
||||||
};
|
|
||||||
|
|
||||||
//Добавление/обновление параметров пользователя
|
|
||||||
const handlePutSettings = async () => {
|
|
||||||
//Добавляем параметр
|
|
||||||
await putSettings({
|
|
||||||
kind: SETTINGS_KINDS.USER,
|
|
||||||
panel: PANEL_NAME,
|
|
||||||
settings: LAST_UPDATE_PARAM
|
|
||||||
});
|
|
||||||
//Перечитываем параметры
|
|
||||||
handleLoadSettings();
|
|
||||||
};
|
|
||||||
|
|
||||||
//При отображении параметров панели
|
|
||||||
const handleSettingsDialog = async () => {
|
|
||||||
//Отображаем параметры панели
|
|
||||||
showSettingsDialog({
|
|
||||||
panel: PANEL_NAME,
|
|
||||||
onOk: ({ settings, isChanged }) => {
|
|
||||||
console.log("Параметры сохранены:", { settings, isChanged });
|
|
||||||
},
|
|
||||||
onCancel: () => {
|
|
||||||
console.log("Изменения отменены");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
//Отображение/сокрытие кнопки открытия параметров панели
|
|
||||||
const handleShowPanelSettingsToggle = () => {
|
|
||||||
//Переключаем состояние
|
|
||||||
setShowPanelSettings(!showPanelSettings);
|
|
||||||
//Скрываем/отображаем кнопку параметров
|
|
||||||
setAppBarSettingsShow(!showPanelSettings);
|
|
||||||
};
|
|
||||||
|
|
||||||
//При открытии панели
|
|
||||||
useEffect(() => {
|
|
||||||
//Инициализируем параметры
|
|
||||||
handleInitSettings();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
//Генерация содержимого
|
|
||||||
return (
|
|
||||||
<div style={STYLES.CONTAINER}>
|
|
||||||
<Typography sx={STYLES.TITLE} variant={"h6"}>
|
|
||||||
{title}
|
|
||||||
</Typography>
|
|
||||||
<Box sx={STYLES.BOX_BUTTON_GROUP}>
|
|
||||||
<Button variant="contained" onClick={handleInitSettings}>
|
|
||||||
Инициализация
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
<Divider sx={STYLES.DIVIDER} />
|
|
||||||
<Button variant="contained" onClick={handleLoadSettings}>
|
|
||||||
Считывание
|
|
||||||
</Button>
|
|
||||||
<Divider sx={STYLES.DIVIDER} />
|
|
||||||
<Button variant="contained" onClick={handlePutSettings}>
|
|
||||||
Добавление
|
|
||||||
</Button>
|
|
||||||
<Divider sx={STYLES.DIVIDER} />
|
|
||||||
<Button variant="contained" onClick={handleSettingsDialog}>
|
|
||||||
Диалог параметров панели
|
|
||||||
</Button>
|
|
||||||
<Divider sx={STYLES.DIVIDER} />
|
|
||||||
<Button variant="contained" onClick={handleShowPanelSettingsToggle}>
|
|
||||||
{`${showPanelSettings ? "Скрыть" : "Отобразить"} кнопку открытия параметров в шапке`}
|
|
||||||
</Button>
|
|
||||||
{Object.keys(state).length > 0 ? (
|
|
||||||
<>
|
|
||||||
<Divider sx={STYLES.DIVIDER} />
|
|
||||||
<Typography pt={2} sx={STYLES.TITLE} variant={"h6"}>
|
|
||||||
Значения параметров
|
|
||||||
</Typography>
|
|
||||||
<Box sx={STYLES.BOX_SETTINGS_VALUES}>
|
|
||||||
{Object.keys(state).map((item, index) => (
|
|
||||||
<Box key={index} sx={STYLES.SETTING_CARD}>
|
|
||||||
<Typography variant="body2" sx={STYLES.SETTING_NAME}>
|
|
||||||
{`${Object.keys(PANEL_PARAMS).includes(item) ? PANEL_PARAMS[item].name : LAST_UPDATE_PARAM[item].name}:`}
|
|
||||||
</Typography>
|
|
||||||
<Typography variant="body2" sx={STYLES.SETTING_VALUE}>
|
|
||||||
{state[item]}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
))}
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Контроль свойств - Пример: параметры
|
|
||||||
Settings.propTypes = {
|
|
||||||
title: PropTypes.string.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------
|
|
||||||
//Интерфейс модуля
|
|
||||||
//----------------
|
|
||||||
|
|
||||||
export { Settings };
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
Парус 8 - Панели мониторинга
|
|
||||||
Параметры панелей
|
|
||||||
*/
|
|
||||||
create table P8PNL_SETTINGS
|
|
||||||
(
|
|
||||||
RN number(17) not null, -- Рег. номер записи
|
|
||||||
CODE varchar2(40) not null, -- Мнемокод параметра
|
|
||||||
NAME varchar2(240) not null, -- Наименование параметра
|
|
||||||
KIND number(1) not null -- Вид параметра
|
|
||||||
constraint C_P8PNL_SETTINGS_KIND_VAL check ( KIND in (0,1,2) ),
|
|
||||||
PANEL varchar2(100) default null, -- Код панели
|
|
||||||
COMPANY number(17) default null, -- Рег. номер организации
|
|
||||||
AUTHID varchar2(30) default null, -- Пользователь
|
|
||||||
OPTIONS clob, -- Дополнительные параметры
|
|
||||||
DATA_TYPE number(1) default 0 -- Тип данных
|
|
||||||
constraint C_P8PNL_SETTINGS_DT_VAL check ( DATA_TYPE in (0,1,2) ),
|
|
||||||
VALUE_STR varchar2(4000) default null, -- Значение (строка)
|
|
||||||
VALUE_NUM number default null, -- Значение (число)
|
|
||||||
VALUE_DATE date default null, -- Значение (дата)
|
|
||||||
DESCRIPTION varchar2(240) default null, -- Примечание
|
|
||||||
constraint C_P8PNL_SETTINGS_PK primary key (RN),
|
|
||||||
constraint C_P8PNL_SETTINGS_UK unique (CODE, PANEL, COMPANY, AUTHID),
|
|
||||||
constraint C_P8PNL_SETTINGS_DATA_TYPE_CH check (((DATA_TYPE = 0) and ((VALUE_NUM is null) and (VALUE_DATE is null)))
|
|
||||||
or ((DATA_TYPE = 1) and ((VALUE_STR is null) and (VALUE_DATE is null)))
|
|
||||||
or ((DATA_TYPE = 2) and ((VALUE_STR is null) and (VALUE_NUM is null)))),
|
|
||||||
constraint C_P8PNL_SETTINGS_KIND_CH check (((KIND = 0) and ((PANEL is null) and (COMPANY is null) and (AUTHID is null)))
|
|
||||||
or ((KIND = 1) and ((PANEL is not null) and (COMPANY is null) and (AUTHID is not null)))
|
|
||||||
or ((KIND = 2) and ((PANEL is not null) and (COMPANY is not null) and (AUTHID is not null))))
|
|
||||||
);
|
|
||||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user