WEBAPP: Новые компоненты P8PDialog и P8PInput
This commit is contained in:
parent
7c515f7ebb
commit
3f539065ba
76
app/components/p8p_dialog.js
Normal file
76
app/components/p8p_dialog.js
Normal file
@ -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 (
|
||||
<Dialog onClose={handleClose} open>
|
||||
<DialogTitle>{title}</DialogTitle>
|
||||
<DialogContent>
|
||||
{inputs.map((input, i) => (
|
||||
<P8PInput key={i} {...input} value={state[input.name]} formValues={state} 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,
|
||||
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 };
|
137
app/components/p8p_input.js
Normal file
137
app/components/p8p_input.js
Normal file
@ -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 (
|
||||
<Box p={1}>
|
||||
<FormControl variant={"standard"} fullWidth {...other}>
|
||||
{list ? (
|
||||
freeSolo ? (
|
||||
<Autocomplete
|
||||
id={name}
|
||||
name={name}
|
||||
freeSolo
|
||||
disabled={disabled}
|
||||
inputValue={currentValue ? currentValue : ""}
|
||||
onChange={(event, newValue) => handleChangeByName(name, newValue)}
|
||||
onInputChange={(event, newInputValue) => handleChangeByName(name, newInputValue)}
|
||||
options={list}
|
||||
renderInput={params => <TextField {...params} label={label} name={name} variant={"standard"} />}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<InputLabel id={`${name}Lable`} shrink>
|
||||
{label}
|
||||
</InputLabel>
|
||||
<Select
|
||||
labelId={`${name}Lable`}
|
||||
id={name}
|
||||
name={name}
|
||||
label={label}
|
||||
value={[undefined, null].includes(currentValue) ? "" : currentValue}
|
||||
onChange={handleChange}
|
||||
disabled={disabled}
|
||||
displayEmpty
|
||||
>
|
||||
{list.map((item, i) => (
|
||||
<MenuItem key={i} value={[undefined, null].includes(item.value) ? "" : item.value}>
|
||||
{item.name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</>
|
||||
)
|
||||
) : (
|
||||
<>
|
||||
<InputLabel {...(type == "date" ? { shrink: true } : {})} htmlFor={name}>
|
||||
{label}
|
||||
</InputLabel>
|
||||
<Input
|
||||
id={name}
|
||||
name={name}
|
||||
value={currentValue ? currentValue : ""}
|
||||
endAdornment={
|
||||
dictionary ? (
|
||||
<InputAdornment position="end">
|
||||
<IconButton aria-label={`${name} select`} onClick={handleDictionaryClick} edge="end">
|
||||
<Icon>list</Icon>
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
) : null
|
||||
}
|
||||
{...(type ? { type } : {})}
|
||||
onChange={handleChange}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</FormControl>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
//Контроль свойств - Поле ввода
|
||||
P8PInput.propTypes = P8P_INPUT;
|
||||
|
||||
//----------------
|
||||
//Интерфейс модуля
|
||||
//----------------
|
||||
|
||||
export { P8P_INPUT, P8PInput };
|
Loading…
x
Reference in New Issue
Block a user