forked from CITKParus/P8-Panels
176 lines
6.3 KiB
JavaScript
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 };
|