diff --git a/app/components/p8p_dialog.js b/app/components/p8p_dialog.js
new file mode 100644
index 0000000..30ab288
--- /dev/null
+++ b/app/components/p8p_dialog.js
@@ -0,0 +1,76 @@
+/*
+ Парус 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 P8PDialog = ({ title, inputs = [], children, onOk, onCancel, onClose }) => {
+ //Состояние диалога
+ const [state, setState] = useState({});
+
+ //При изменении элемента ввода
+ const handleInputChange = (name, value) => setState(pv => ({ ...pv, [name]: value }));
+
+ //При нажатии на "ОК" диалога
+ const handleOk = () => onOk && onOk(state);
+
+ //При нажатии на "Отмена" диалога
+ const handleCancel = () => onCancel && onCancel();
+
+ //При нажатии на "Закрыть" диалога
+ const handleClose = () => (onClose ? onClose() : onCancel ? onCancel() : null);
+
+ //При подключении к старнице
+ useEffect(() => {
+ setState(inputs.reduce((res, input) => ({ ...res, [input.name]: input.value == undefined ? null : input.value }), {}));
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+
+ //Формирование представления
+ return (
+
+ );
+};
+
+//Контроль свойств - Диалог
+P8PDialog.propTypes = {
+ title: PropTypes.string.isRequired,
+ 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
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { P8PDialog };
diff --git a/app/components/p8p_input.js b/app/components/p8p_input.js
new file mode 100644
index 0000000..2adc568
--- /dev/null
+++ b/app/components/p8p_input.js
@@ -0,0 +1,137 @@
+/*
+ Парус 8 - Панели мониторинга
+ Компонент: Поле ввода
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React, { useState, useEffect } from "react"; //Классы React
+import PropTypes from "prop-types"; //Контроль свойств компонента
+import { Box, Icon, Input, InputAdornment, FormControl, Select, InputLabel, MenuItem, IconButton, Autocomplete, TextField } from "@mui/material"; //Интерфейсные компоненты
+
+//---------
+//Константы
+//---------
+
+//Формат свойств поля ввода
+const P8P_INPUT = {
+ name: PropTypes.string.isRequired,
+ value: PropTypes.oneOfType([PropTypes.number, PropTypes.string, PropTypes.instanceOf(Date)]),
+ label: PropTypes.string.isRequired,
+ onChange: PropTypes.func,
+ dictionary: PropTypes.func,
+ list: PropTypes.array,
+ type: PropTypes.string,
+ freeSolo: PropTypes.bool,
+ disabled: PropTypes.bool,
+ formValues: PropTypes.object
+};
+
+//-----------
+//Тело модуля
+//-----------
+
+//Поле ввода
+const P8PInput = ({ name, value, label, onChange, dictionary, list, type, freeSolo = false, disabled = false, formValues, ...other }) => {
+ //Значение элемента
+ const [currentValue, setCurrentValue] = useState(value);
+
+ //При получении нового значения из вне
+ useEffect(() => {
+ setCurrentValue(value);
+ }, [value]);
+
+ //Выбор значения из словаря
+ const handleDictionaryClick = () => dictionary && dictionary(formValues, res => (res ? res.map(i => handleChangeByName(i.name, i.value)) : null));
+
+ //Изменение значения элемента (по событию)
+ const handleChange = e => {
+ setCurrentValue(e.target.value);
+ if (onChange) onChange(e.target.name, e.target.value);
+ };
+
+ //Изменение значения элемента (по имени и значению)
+ const handleChangeByName = (targetName, value) => {
+ if (targetName === name) setCurrentValue(value);
+ if (onChange) onChange(targetName, value);
+ };
+
+ //Генерация содержимого
+ return (
+
+
+ {list ? (
+ freeSolo ? (
+ handleChangeByName(name, newValue)}
+ onInputChange={(event, newInputValue) => handleChangeByName(name, newInputValue)}
+ options={list}
+ renderInput={params => }
+ />
+ ) : (
+ <>
+
+ {label}
+
+
+ >
+ )
+ ) : (
+ <>
+
+ {label}
+
+
+
+ list
+
+
+ ) : null
+ }
+ {...(type ? { type } : {})}
+ onChange={handleChange}
+ disabled={disabled}
+ />
+ >
+ )}
+
+
+ );
+};
+
+//Контроль свойств - Поле ввода
+P8PInput.propTypes = P8P_INPUT;
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { P8P_INPUT, P8PInput };