forked from CITKParus/P8-Panels
112 lines
4.8 KiB
JavaScript
112 lines
4.8 KiB
JavaScript
/*
|
||
Парус 8 - Панели мониторинга
|
||
Компонент: Диалог
|
||
*/
|
||
|
||
//---------------------
|
||
//Подключение библиотек
|
||
//---------------------
|
||
|
||
import React, { useEffect, useState } from "react"; //Классы React
|
||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||
import { Dialog, DialogTitle, DialogContent, DialogActions, Button } from "@mui/material"; //Интерфейсные компоненты
|
||
import { BUTTONS } from "../../app.text"; //Общие текстовые ресурсы
|
||
import { P8P_INPUT, P8PInput } from "./p8p_input"; //Поле ввода
|
||
|
||
//---------
|
||
//Константы
|
||
//---------
|
||
|
||
//Типовая ширина диалога
|
||
const P8P_DIALOG_WIDTH = {
|
||
XS: "xs",
|
||
SM: "sm",
|
||
MD: "md",
|
||
LG: "lg",
|
||
XL: "xl"
|
||
};
|
||
|
||
//-----------------------
|
||
//Вспомогательные функции
|
||
//-----------------------
|
||
|
||
//Формирование объекта вида {ключ: значение} из текущего состояния элементов ввода формы
|
||
const buildFormValues = inputsState =>
|
||
inputsState.reduce((res, input) => ({ ...res, [input.name]: input.value == undefined ? null : input.value }), {});
|
||
|
||
//-----------
|
||
//Тело модуля
|
||
//-----------
|
||
|
||
//Диалог
|
||
const P8PDialog = ({ title, width, fullWidth, inputs, children, onOk, onCancel, onClose, onInputChange }) => {
|
||
//Состояние элементов ввода диалога
|
||
const [inputsState, setInputsState] = useState([]);
|
||
|
||
//При изменении элемента ввода
|
||
const handleInputChange = (name, value) => {
|
||
//Если есть функция пересчета формы - вызовем её
|
||
const doNotChangeInputsState = onInputChange ? onInputChange(name, value, inputsState) : false;
|
||
//И ориентируясь на то, пересчитала ли она элементы ввода обновим собственное состояние.
|
||
//Если функция пересчета вернула "true", значит она пересчитала что-то, тогда новые настройки элементов придут через свойство inputs и будут обработаны в useEffect ниже.
|
||
//Следовательно, и нам здесь не надо состояние выставлять, т.к. всё будет перезаписано useEffectом.
|
||
if (!doNotChangeInputsState)
|
||
setInputsState(pv => pv.reduce((accum, cur) => [...accum, { ...cur, value: cur.name === name ? value : cur.value }], []));
|
||
};
|
||
|
||
//При нажатии на "ОК" диалога
|
||
const handleOk = () => onOk && onOk(buildFormValues(inputsState));
|
||
|
||
//При нажатии на "Отмена" диалога
|
||
const handleCancel = () => onCancel && onCancel();
|
||
|
||
//При нажатии на "Закрыть" диалога
|
||
const handleClose = () => (onClose ? onClose() : onCancel ? onCancel() : null);
|
||
|
||
//При изменении полей для ввода
|
||
useEffect(() => {
|
||
if (inputs && Array.isArray(inputs) && inputs.length > 0) setInputsState(inputs.map(input => ({ ...input })));
|
||
}, [inputs]);
|
||
|
||
//Расчет объектного представления текущих значений формы
|
||
const formValues = buildFormValues(inputsState);
|
||
|
||
//Формирование представления
|
||
return (
|
||
<Dialog onClose={handleClose} open {...{ ...(width ? { maxWidth: width } : {}), ...(fullWidth === true ? { fullWidth: true } : {}) }}>
|
||
<DialogTitle>{title}</DialogTitle>
|
||
<DialogContent>
|
||
{inputsState.map((input, i) => (
|
||
<P8PInput key={i} {...input} formValues={formValues} onChange={handleInputChange} />
|
||
))}
|
||
|
||
{children}
|
||
</DialogContent>
|
||
<DialogActions>
|
||
{onOk && <Button onClick={handleOk}>{BUTTONS.OK}</Button>}
|
||
{onCancel && <Button onClick={handleCancel}>{BUTTONS.CANCEL}</Button>}
|
||
{onClose && <Button onClick={handleClose}>{BUTTONS.CLOSE}</Button>}
|
||
</DialogActions>
|
||
</Dialog>
|
||
);
|
||
};
|
||
|
||
//Контроль свойств - Диалог
|
||
P8PDialog.propTypes = {
|
||
title: PropTypes.string.isRequired,
|
||
width: PropTypes.oneOf(Object.values(P8P_DIALOG_WIDTH)),
|
||
fullWidth: PropTypes.bool,
|
||
inputs: PropTypes.arrayOf(PropTypes.shape(P8P_INPUT)),
|
||
children: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)]),
|
||
onOk: PropTypes.func,
|
||
onCancel: PropTypes.func,
|
||
onClose: PropTypes.func,
|
||
onInputChange: PropTypes.func
|
||
};
|
||
|
||
//----------------
|
||
//Интерфейс модуля
|
||
//----------------
|
||
|
||
export { P8PDialog, P8P_DIALOG_WIDTH };
|