169 lines
6.8 KiB
JavaScript
169 lines
6.8 KiB
JavaScript
/*
|
||
Парус 8 - Панели мониторинга - Редактор панелей
|
||
Компоненты: Форма (представление)
|
||
*/
|
||
|
||
//---------------------
|
||
//Подключение библиотек
|
||
//---------------------
|
||
|
||
import React, { useEffect, useState, useContext } from "react"; //Классы React
|
||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||
import { Paper, Stack, Typography, Icon, TextField, IconButton, InputAdornment } from "@mui/material"; //Интерфейсные элементы
|
||
import { ApplicationСtx } from "../../../../context/application"; //Контекст приложения
|
||
import { COMPONENT_MESSAGES, ComponentInlineMessage } from "../views_common"; //Общие компоненты представлений
|
||
import { ITEM_SHAPE, ITEMS_INITIAL, ORIENTATION } from "./common"; //Общие ресурсы и константы формы
|
||
import "../../panels_editor.css"; //Стили редактора
|
||
|
||
//---------
|
||
//Константы
|
||
//---------
|
||
|
||
//Иконка компонента
|
||
const COMPONENT_ICON = "fact_check";
|
||
|
||
//Наименование компонента
|
||
const COMPONENT_NAME = "Форма";
|
||
|
||
//------------------------------------
|
||
//Вспомогательные функции и компоненты
|
||
//------------------------------------
|
||
|
||
//Элемент формы
|
||
const FormItem = ({ item = null, fullWidth = false, value = "", onChange = null } = {}) => {
|
||
//Подключение к контексту приложения
|
||
const { pOnlineShowDictionary } = useContext(ApplicationСtx);
|
||
|
||
//При изменении значения элемента
|
||
const handleChange = e => onChange && onChange(e.target.id, e.target.value);
|
||
|
||
//При очистке значения элемента
|
||
const handleClear = () => onChange(item.name, "");
|
||
|
||
//При выборе значения из словаря
|
||
const handleDictionary = () =>
|
||
item.unitCode &&
|
||
item.showMethod &&
|
||
pOnlineShowDictionary({
|
||
unitCode: item.unitCode,
|
||
showMethod: item.showMethod,
|
||
inputParameters: [{ name: item.inputParameter, value }],
|
||
callBack: res => res.success && onChange && onChange(item.name, res.outParameters[item.outputParameter])
|
||
});
|
||
//Формирование представления
|
||
return (
|
||
item && (
|
||
<TextField
|
||
fullWidth={fullWidth}
|
||
type={"text"}
|
||
variant={"standard"}
|
||
value={value}
|
||
label={item.caption}
|
||
id={item.name}
|
||
onChange={handleChange}
|
||
{...(item.unitCode && {
|
||
InputLabelProps: { shrink: true },
|
||
InputProps: {
|
||
readOnly: true,
|
||
endAdornment: (
|
||
<InputAdornment position="end">
|
||
<IconButton onClick={handleClear}>
|
||
<Icon>clear</Icon>
|
||
</IconButton>
|
||
<IconButton onClick={handleDictionary}>
|
||
<Icon>list</Icon>
|
||
</IconButton>
|
||
</InputAdornment>
|
||
)
|
||
}
|
||
})}
|
||
/>
|
||
)
|
||
);
|
||
};
|
||
|
||
//Контроль свойств - элемент формы
|
||
FormItem.propTypes = {
|
||
item: ITEM_SHAPE,
|
||
fullWidth: PropTypes.bool,
|
||
value: PropTypes.any,
|
||
onChange: PropTypes.func
|
||
};
|
||
|
||
//-----------
|
||
//Тело модуля
|
||
//-----------
|
||
|
||
//Форма (представление)
|
||
const Form = ({ title = null, orientation = ORIENTATION.V, autoApply = false, items = ITEMS_INITIAL, values = {}, onValuesChange = null } = {}) => {
|
||
//Собственное состояние - значения элементов
|
||
const [selfValues, setSelfValues] = useState({});
|
||
|
||
//При изменении состава элементов или значений
|
||
useEffect(() => setSelfValues(items.reduce((sV, item) => ({ ...sV, [item.name]: values[item.name] }), {})), [items, values]);
|
||
|
||
//При изменении значения элемента формы
|
||
const handleItemChange = (name, value) => {
|
||
setSelfValues(pv => ({ ...pv, [name]: value }));
|
||
autoApply && onValuesChange && onValuesChange({ ...selfValues, [name]: value });
|
||
};
|
||
|
||
//При подтверждении изменений формы
|
||
const handleOkClick = () => onValuesChange && onValuesChange({ ...selfValues });
|
||
|
||
//Флаг настроенности формы
|
||
const haveConfing = items && Array.isArray(items) && items.length > 0;
|
||
|
||
//Формирование представления
|
||
return (
|
||
<Paper className={`component-view__container ${!haveConfing && "component-view__container__empty"}`} elevation={6}>
|
||
{haveConfing ? (
|
||
<Stack direction={"column"}>
|
||
<Stack direction={"row"} justifyContent={"space-between"} alignItems={"center"}>
|
||
{title && (
|
||
<Typography align={"left"} color={"text.primary"} variant={"subtitle2"} noWrap={true}>
|
||
{title}
|
||
</Typography>
|
||
)}
|
||
{!autoApply && (
|
||
<IconButton onClick={handleOkClick}>
|
||
<Icon>done</Icon>
|
||
</IconButton>
|
||
)}
|
||
</Stack>
|
||
<Stack direction={orientation == ORIENTATION.V ? "column" : "row"} spacing={1} pt={1} pb={1}>
|
||
{items.map((item, i) => (
|
||
<FormItem
|
||
key={i}
|
||
item={item}
|
||
value={selfValues?.[item.name] || ""}
|
||
onChange={handleItemChange}
|
||
fullWidth={orientation == ORIENTATION.V}
|
||
/>
|
||
))}
|
||
</Stack>
|
||
</Stack>
|
||
) : (
|
||
<ComponentInlineMessage icon={COMPONENT_ICON} name={COMPONENT_NAME} message={COMPONENT_MESSAGES.NO_SETTINGS} />
|
||
)}
|
||
</Paper>
|
||
);
|
||
};
|
||
|
||
//Контроль свойств компонента - Форма (представление)
|
||
Form.propTypes = {
|
||
id: PropTypes.string.isRequired,
|
||
title: PropTypes.string,
|
||
orientation: PropTypes.oneOf(Object.values(ORIENTATION)),
|
||
autoApply: PropTypes.bool,
|
||
items: PropTypes.arrayOf(ITEM_SHAPE),
|
||
values: PropTypes.object,
|
||
onValuesChange: PropTypes.func
|
||
};
|
||
|
||
//----------------
|
||
//Интерфейс модуля
|
||
//----------------
|
||
|
||
export default Form;
|