P8-Panels/app/components/p8p_indicator.js

176 lines
6.3 KiB
JavaScript

/*
Парус 8 - Панели мониторинга
Компонент: Индикатор
*/
//---------------------
//Подключение библиотек
//---------------------
import React, { useState } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { IconButton, Icon, Typography, Paper, Stack } from "@mui/material"; //Интерфейсные компоненты MUI
import { P8PHintDialog } from "./p8p_app_message"; //Диалог подсказки
import { TEXTS, STATE } from "../../app.text"; //Типовые текстовые ресурсы и константы
import { useP8PIndicator } from "./p8p_indicator_hooks"; //Хук для индикатора
import { P8P_TYPOGRAPHY_VARIANT } from "../theme/p8p_typography"; //Варианты шрифтов
import { P8P_TYPOGRAPHY_CLICKABLE } from "../theme/styles/typography"; //Стили текстовых полей
import { P8P_PAPER_INDICATOR } from "../theme/styles/paper"; //Стили выделяемого контейнера
import { P8P_STACK_INLINE_HIDDEN } from "../theme/styles/stack"; //Стили для групповой информации
import { P8P_ICON_INDICATOR } from "../theme/styles/icon"; //Стили иконок
//---------
//Константы
//---------
//Варианты исполнения
const P8P_INDICATOR_VARIANT = {
ELEVATION: "elevation",
OUTLINED: "outlined"
};
//Состояния
const P8P_INDICATOR_STATE = {
UNDEFINED: STATE.UNDEFINED,
OK: STATE.OK,
WARN: STATE.WARN,
ERR: STATE.ERR
};
//Ширина для элементов индикатора
const WIDTH_ICON_VALUE = "1rem"; //Иконка значения индикатора
const WIDTH_ICON = "50px"; //Иконка индикатора
const WIDTH_CAPTION = "99cqw"; //Заголовок индикатора
//-----------
//Тело модуля
//-----------
//Индикатор
const P8PIndicator = ({
caption,
value,
icon = null,
state = STATE.UNDEFINED,
square = false,
elevation = 3,
variant = P8P_INDICATOR_VARIANT.ELEVATION,
hint = null,
onClick = null,
onValueClick = null,
onCaptionClick = null,
backgroundColor = null,
color = null
} = {}) => {
//Собственное состояние - отображение окна подсказки
const [showHint, setShowHint] = useState(false);
//При нажатии на индикатор
const handleClick = () => (onClick && !showHint ? onClick() : null);
//При нажатии на кнопку получения подсказки
const handleHintClick = e => {
setShowHint(true);
e.stopPropagation();
};
//При нажатии на кнопку закрытия подсказки
const handleHintClose = e => {
setShowHint(false);
e.stopPropagation();
};
//При нажатии на заголовок
const handleCaptionClick = event => {
//Если есть функция нажатия на заголовок
onCaptionClick && onCaptionClick(event);
};
//При нажатии на значение
const handleValueClick = event => {
//Если есть функция нажатия на заголовок
onValueClick && onValueClick(event);
};
//Представление текста значения индикатора
const valueTextView = (
<Typography variant={P8P_TYPOGRAPHY_VARIANT.H4} sx={onValueClick ? { ...P8P_TYPOGRAPHY_CLICKABLE } : {}} onClick={handleValueClick}>
{[undefined, null, ""].includes(value) ? TEXTS.NO_DATA_FOUND_SHORT : value}
</Typography>
);
//Представление текста подписи индикатора
const captionView = (
<Typography
variant={P8P_TYPOGRAPHY_VARIANT.BODY3}
align={"left"}
noWrap={true}
sx={{ width: WIDTH_CAPTION, ...(onCaptionClick ? { ...P8P_TYPOGRAPHY_CLICKABLE } : {}) }}
title={caption}
onClick={handleCaptionClick}
>
{caption}
</Typography>
);
//Представление подписи индикатора
const valueView = hint ? (
<>
{showHint && <P8PHintDialog title={caption} hint={hint} onOk={handleHintClose} />}
<Stack direction={"row"} alignItems={"start"}>
{valueTextView}
<IconButton onClick={handleHintClick}>
<Icon sx={P8P_ICON_INDICATOR({ state, fontSize: WIDTH_ICON_VALUE, color })}>help_outline</Icon>
</IconButton>
</Stack>
</>
) : (
valueTextView
);
//Флаг активности индикатора
const clickable = onClick ? true : false;
//Представление
return (
<Paper
elevation={variant === P8P_INDICATOR_VARIANT.ELEVATION ? elevation : 0}
sx={P8P_PAPER_INDICATOR({ state, color, backgroundColor, clickable })}
square={square}
variant={variant}
onClick={handleClick}
>
<Stack direction={"row"} alignItems={"center"} justifyContent={"space-between"}>
<Stack direction={"column"} alignItems={"start"} pr={2} sx={P8P_STACK_INLINE_HIDDEN}>
{valueView}
{captionView}
</Stack>
{icon ? <Icon sx={P8P_ICON_INDICATOR({ state, fontSize: WIDTH_ICON, color })}>{icon}</Icon> : null}
</Stack>
</Paper>
);
};
//Контроль свойств - Индикатор
P8PIndicator.propTypes = {
caption: PropTypes.string.isRequired,
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
icon: PropTypes.string,
state: PropTypes.oneOf(Object.values(P8P_INDICATOR_STATE)),
square: PropTypes.bool,
elevation: PropTypes.number,
variant: PropTypes.oneOf(Object.values(P8P_INDICATOR_VARIANT)),
hint: PropTypes.string,
onClick: PropTypes.func,
onValueClick: PropTypes.func,
onCaptionClick: PropTypes.func,
backgroundColor: PropTypes.string,
color: PropTypes.string
};
//----------------
//Интерфейс модуля
//----------------
export { P8P_INDICATOR_VARIANT, P8P_INDICATOR_STATE, P8PIndicator, useP8PIndicator };