187 lines
6.3 KiB
JavaScript
187 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 { APP_COLORS } from "../../app.styles"; //Типовые стили
|
|
|
|
//---------
|
|
//Константы
|
|
//---------
|
|
|
|
//Варианты исполнения
|
|
|
|
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 BG_COLOR = {
|
|
[STATE.OK]: APP_COLORS[STATE.OK].color,
|
|
[STATE.ERR]: APP_COLORS[STATE.ERR].color,
|
|
[STATE.WARN]: APP_COLORS[STATE.WARN].color
|
|
};
|
|
|
|
//Цвета текста и иконок
|
|
const COLOR = {
|
|
[STATE.OK]: APP_COLORS[STATE.OK].contrColor,
|
|
[STATE.ERR]: APP_COLORS[STATE.ERR].contrColor,
|
|
[STATE.WARN]: APP_COLORS[STATE.WARN].contrColor
|
|
};
|
|
|
|
//Стили
|
|
const STYLES = {
|
|
CONTAINER: (state, clickable, userColor, userBackgroundColor) => ({
|
|
padding: "10px",
|
|
width: "100%",
|
|
height: "100%",
|
|
overflow: "hidden",
|
|
...getBackgroundColor(state, userBackgroundColor),
|
|
...getColor(state, userColor),
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
justifyContent: "center",
|
|
...(clickable
|
|
? {
|
|
cursor: "pointer",
|
|
"&:hover": { backgroundColor: APP_COLORS.HOVER.color },
|
|
"&:active": { backgroundColor: APP_COLORS.ACTIVE.color }
|
|
}
|
|
: {})
|
|
}),
|
|
ICON: (state, userColor) => ({ fontSize: "50px", ...getColor(state, userColor) }),
|
|
HINT_ICON: (state, userColor) => ({ fontSize: "1rem", ...getColor(state, userColor) }),
|
|
VALUE_CAPTION_STACK: { containerType: "inline-size", width: "100%", overflow: "hidden" },
|
|
CAPTION_TYPOGRAPHY: { width: "99cqw" }
|
|
};
|
|
|
|
//-----------------------
|
|
//Вспомогательные функции
|
|
//-----------------------
|
|
|
|
//Подбор цвета заливки
|
|
const getBackgroundColor = (state, userColor) =>
|
|
userColor ? { backgroundColor: userColor } : BG_COLOR[state] ? { backgroundColor: BG_COLOR[state] } : {};
|
|
|
|
//Подбор цвета текста
|
|
const getColor = (state, userColor) => (userColor ? { color: userColor } : COLOR[state] ? { color: COLOR[state] } : {});
|
|
|
|
//-----------
|
|
//Тело модуля
|
|
//-----------
|
|
|
|
//Индикатор
|
|
const P8PIndicator = ({
|
|
caption,
|
|
value,
|
|
icon = null,
|
|
state = STATE.UNDEFINED,
|
|
square = false,
|
|
elevation = 3,
|
|
variant = P8P_INDICATOR_VARIANT.ELEVATION,
|
|
hint = null,
|
|
onClick = 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 = () => setShowHint(false);
|
|
|
|
//Представление текста значения индикатора
|
|
const valueTextView = <Typography variant={"h4"}>{[undefined, null, ""].includes(value) ? TEXTS.NO_DATA_FOUND_SHORT : value}</Typography>;
|
|
|
|
//Представление текста подписи индикатора
|
|
const captionView = (
|
|
<Typography align={"left"} noWrap={true} sx={STYLES.CAPTION_TYPOGRAPHY} title={caption}>
|
|
{caption}
|
|
</Typography>
|
|
);
|
|
|
|
//Представление подписи индикатора
|
|
const valueView = hint ? (
|
|
<>
|
|
{showHint && <P8PHintDialog title={caption} hint={hint} onOk={handleHintClose} />}
|
|
<Stack direction={"row"} alignItems={"start"}>
|
|
{valueTextView}
|
|
<IconButton onClick={handleHintClick}>
|
|
<Icon sx={STYLES.HINT_ICON(state, color)}>help_outline</Icon>
|
|
</IconButton>
|
|
</Stack>
|
|
</>
|
|
) : (
|
|
valueTextView
|
|
);
|
|
|
|
//Флаг активности индикатора
|
|
const clickable = onClick ? true : false;
|
|
|
|
//Представление
|
|
return (
|
|
<Paper
|
|
elevation={variant === P8P_INDICATOR_VARIANT.ELEVATION ? elevation : 0}
|
|
sx={STYLES.CONTAINER(state, clickable, color, backgroundColor)}
|
|
square={square}
|
|
variant={variant}
|
|
onClick={handleClick}
|
|
>
|
|
<Stack direction={"row"} alignItems={"center"} justifyContent={"space-between"}>
|
|
<Stack direction={"column"} alignItems={"start"} pr={2} sx={STYLES.VALUE_CAPTION_STACK}>
|
|
{valueView}
|
|
{captionView}
|
|
</Stack>
|
|
{icon ? <Icon sx={STYLES.ICON(state, 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,
|
|
backgroundColor: PropTypes.string,
|
|
color: PropTypes.string
|
|
};
|
|
|
|
//----------------
|
|
//Интерфейс модуля
|
|
//----------------
|
|
|
|
export { P8P_INDICATOR_VARIANT, P8P_INDICATOR_STATE, P8PIndicator };
|