forked from CITKParus/P8-Panels
173 lines
8.2 KiB
JavaScript
173 lines
8.2 KiB
JavaScript
/*
|
||
Парус 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])
|
||
};
|