P8-Panels/app/context/settings.js

173 lines
8.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Парус 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])
};