P8-Panels/app/components/p8p_input.js

159 lines
7.5 KiB
JavaScript

/*
Парус 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"; //Интерфейсные компоненты
import { P8P_AUTOCOMPLETE_VARIANT } from "../theme/variants/p8p_autocomplete_variants"; //Варианты полей выбора (Autocomplete)
import { P8P_INPUT_LABEL_VARIANT } from "../theme/variants/p8p_input_label_variants"; //Варианты меток выбора
import { P8P_TEXT_FIELD_VARIANT } from "../theme/variants/p8p_text_field_variants"; //Варианты полей ввода
import { P8P_SELECT_VARIANT } from "../theme/variants/p8p_select_variants"; //Варианты полей выбора (Select)
import { P8P_MENU_ITEM_VARIANT } from "../theme/variants/p8p_menu_item_variants"; //Варианты элементов меню
import { P8P_INPUT_VARIANT } from "../theme/variants/p8p_input_variants"; //Варианты полей ввода (Input)
//---------
//Константы
//---------
//Формат свойств поля ввода
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 [current, setCurrent] = useState({ type: undefined, value: "" });
//При получении нового значения или типа из вне
useEffect(() => setCurrent({ value, type }), [type, value]);
//Выбор значения из словаря
const handleDictionaryClick = () => dictionary && dictionary(formValues, res => (res ? res.map(i => handleChangeByName(i.name, i.value)) : null));
//Изменение значения элемента (по событию)
const handleChange = e => {
setCurrent(pv => ({ ...pv, value: e.target.value }));
if (onChange) onChange(e.target.name, e.target.value);
};
//Изменение значения элемента (по имени и значению)
const handleChangeByName = (targetName, value) => {
if (targetName === name) setCurrent(pv => ({ ...pv, value }));
if (onChange) onChange(targetName, value);
};
//Генерация содержимого
return (
<Box p={1} minWidth="300px">
<FormControl variant={"standard"} fullWidth {...other}>
{list ? (
freeSolo ? (
<Autocomplete
id={name}
name={name}
freeSolo
disabled={disabled}
inputValue={current.value ? current.value : ""}
onChange={(event, newValue) => handleChangeByName(name, newValue)}
onInputChange={(event, newInputValue) => handleChangeByName(name, newInputValue)}
options={list}
variant={P8P_AUTOCOMPLETE_VARIANT.PRIMARY}
renderInput={params => (
<TextField {...params} label={label} name={name} variant={"standard"} data-variant={P8P_TEXT_FIELD_VARIANT.PRIMARY} />
)}
/>
) : (
<>
<FormControl variant="standard" fullWidth>
<InputLabel id={`${name}Lable`} shrink data-variant={P8P_INPUT_LABEL_VARIANT.PRIMARY}>
{label}
</InputLabel>
<Select
labelId={`${name}Lable`}
id={name}
name={name}
label={label}
value={[undefined, null].includes(current.value) ? "" : current.value}
onChange={handleChange}
disabled={disabled}
displayEmpty
data-variant={P8P_SELECT_VARIANT.PRIMARY}
>
{list.map((item, i) => (
<MenuItem
key={i}
value={[undefined, null].includes(item.value) ? "" : item.value}
variant={P8P_MENU_ITEM_VARIANT.PRIMARY}
>
{item.name}
</MenuItem>
))}
</Select>
</FormControl>
</>
)
) : (
<>
<FormControl variant="standard" fullWidth>
<InputLabel
{...(current.type == "date" ? { shrink: true } : {})}
htmlFor={name}
data-variant={P8P_INPUT_LABEL_VARIANT.PRIMARY}
>
{label}
</InputLabel>
<Input
id={name}
name={name}
value={current.value ? current.value : ""}
endAdornment={
dictionary ? (
<InputAdornment position="end">
<IconButton aria-label={`${name} select`} onClick={handleDictionaryClick} edge="end">
<Icon>list</Icon>
</IconButton>
</InputAdornment>
) : null
}
{...(current.type ? { type: current.type } : {})}
onChange={handleChange}
disabled={disabled}
variant={P8P_INPUT_VARIANT.PRIMARY}
/>
</FormControl>
</>
)}
</FormControl>
</Box>
);
};
//Контроль свойств - Поле ввода
P8PInput.propTypes = P8P_INPUT;
//----------------
//Интерфейс модуля
//----------------
export { P8P_INPUT, P8PInput };