P8-Panels/app/components/p8p_panels_menu.js

251 lines
11 KiB
JavaScript

/*
Парус 8 - Панели мониторинга
Компонент: Меню панелей
*/
//---------------------
//Подключение библиотек
//---------------------
import React from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import {
Button,
Typography,
Icon,
Box,
Card,
CardActions,
CardContent,
CardMedia,
Stack,
Grid,
Divider,
List,
ListItem,
ListItemButton,
ListItemIcon,
ListItemText
} from "@mui/material"; //Интерфейсные компоненты
import { P8P_BOX_PANELS_MENU_CONTAINER } from "../theme/styles/box"; //Стили контейнеров
import { P8P_GRID_VARIANT } from "../theme/variants/p8p_grid_variants"; //Варианты сеток
import { P8P_CARD_VARIANT } from "../theme/variants/p8p_card_variants"; //Варианты карточек
import { P8P_COMPONENT_HEIGHT } from "../theme/styles/common"; //Стили - общие
import { P8P_ICON_VARIANT } from "../theme/variants/p8p_icon_variants"; //Варианты иконок
import { P8P_CARD_ACTIONS_VARIANT } from "../theme/variants/p8p_card_actions_variants"; //Варианты действий карточки
import { P8P_TYPOGRAPHY_VARIANT } from "../theme/p8p_typography"; //Варианты шрифтов
import { P8P_BUTTON_VARIANT } from "../theme/variants/p8p_button_variants"; //Варианты кнопок
import { P8P_LIST_ITEM_TEXT_VARIANT } from "../theme/variants/p8p_list_item_text_variants"; //Варианты значений списков
import { P8P_TYPOGRAPHY_PANEL_DESK } from "../theme/styles/typography"; //Стили текста
//---------
//Константы
//---------
//Типы меню
const P8P_PANELS_MENU_VARIANT = {
DRAWER: "DRAWER",
GRID: "GRID",
DESKTOP: "DESKTOP"
};
//Структура элемента описания панели
const P8P_PANELS_MENU_PANEL_SHAPE = PropTypes.shape({
name: PropTypes.string.isRequired,
caption: PropTypes.string.isRequired,
desc: PropTypes.string.isRequired,
group: PropTypes.string,
icon: PropTypes.string.isRequired,
path: PropTypes.string.isRequired,
preview: PropTypes.string.isRequired,
showInPanelsList: PropTypes.bool.isRequired,
url: PropTypes.string.isRequired
});
//--------------------------------
//Вспомогательные классы и функции
//--------------------------------
//Формирование групп
const getGroups = (panels, group) => {
let res = [];
let addDefaultGroup = false;
for (const panel of panels)
if (panel.showInPanelsList == true) {
if (panel.group && !res.includes(panel.group)) res.push(panel.group);
if (!panel.group) addDefaultGroup = true;
}
if (addDefaultGroup || res.length == 0) res.push(null);
if (group) res = res.filter(g => g == group);
return res;
};
//Формирование ссылок на панели
const getPanelsLinks = ({ variant, panels, selectedPanel, group, defaultGroupTytle, navigateCaption, onItemNavigate }) => {
//Получим группы
let grps = getGroups(panels, group);
//Построим ссылки
const panelsLinks = [];
for (const grp of grps) {
if (!(grps.length == 1 && grps[0] == null))
panelsLinks.push(
variant === P8P_PANELS_MENU_VARIANT.GRID ? (
<Grid item xs={12} sm={12} md={12} lg={12} xl={12} key={grp}>
<Typography variant={P8P_TYPOGRAPHY_VARIANT.H5} color="P8PPurple">
{grp ? grp : defaultGroupTytle}
</Typography>
</Grid>
) : variant === P8P_PANELS_MENU_VARIANT.DRAWER ? (
<Divider key={grp} />
) : (
<Box pb={1} key={grp}>
<Typography variant={P8P_TYPOGRAPHY_VARIANT.DESKTOP_GROUP}>{grp ? grp : defaultGroupTytle}</Typography>
</Box>
)
);
for (const panel of panels) {
if (panel.showInPanelsList == true && ((grp && panel.group === grp) || (!grp && !panel.group)))
panelsLinks.push(
variant === P8P_PANELS_MENU_VARIANT.GRID ? (
<Grid item xs={12} sm={6} md={4} lg={4} xl={4} key={panel.name}>
<Card variant={P8P_CARD_VARIANT.PANEL_INFO}>
{panel.preview ? (
<CardMedia component="img" alt={panel.name} image={panel.preview} sx={P8P_COMPONENT_HEIGHT({ height: 140 })} />
) : (
<CardMedia
component="img"
alt={panel.name}
image={"./img/default_preview.png"}
sx={P8P_COMPONENT_HEIGHT({ height: 140 })}
/>
)}
<CardContent>
<Stack gap={1} direction="row" alignItems="flex-start">
{panel.icon ? <Icon variant={P8P_ICON_VARIANT.PANEL_MENU_TITLE}>{panel.icon}</Icon> : null}
<Typography variant={P8P_TYPOGRAPHY_VARIANT.H6_LIGHT}>{panel.caption}</Typography>
</Stack>
<Typography variant={P8P_TYPOGRAPHY_VARIANT.BODY3_LIGHT}>{panel.desc}</Typography>
</CardContent>
<CardActions variant={P8P_CARD_ACTIONS_VARIANT.PANEL_CARD}>
<Button
size="large"
onClick={() => (onItemNavigate ? onItemNavigate(panel) : null)}
variant={P8P_BUTTON_VARIANT.TEXT}
>
{navigateCaption}
</Button>
</CardActions>
</Card>
</Grid>
) : variant === P8P_PANELS_MENU_VARIANT.DRAWER ? (
<ListItem key={panel.name} disablePadding>
<ListItemButton
selected={selectedPanel?.name === panel.name}
onClick={() => (onItemNavigate ? onItemNavigate(panel) : null)}
>
<ListItemIcon>
<Icon>{panel.icon}</Icon>
</ListItemIcon>
<ListItemText variant={P8P_LIST_ITEM_TEXT_VARIANT.PRIMARY} primary={panel.caption} />
</ListItemButton>
</ListItem>
) : (
<Button
p={3}
key={panel.name}
onClick={() => (onItemNavigate ? onItemNavigate(panel) : null)}
variant={P8P_BUTTON_VARIANT.DESKTOP_PANEL}
title={panel.caption}
>
<Icon variant={P8P_ICON_VARIANT.DESKTOP_PANEL}>{panel.icon}</Icon>
<Typography sx={P8P_TYPOGRAPHY_PANEL_DESK} variant={P8P_TYPOGRAPHY_VARIANT.DESKTOP_CAPTION}>
{panel.caption}
</Typography>
</Button>
)
);
}
}
//Вернём ссылки
return panelsLinks;
};
//-----------
//Тело модуля
//-----------
//Меню панелей - сдвигающееся боковое меню
const P8PPanelsMenuDrawer = ({ onItemNavigate, panels = [], selectedPanel } = {}) => {
//Формируем ссылки на панели
const panelsLinks = getPanelsLinks({ variant: P8P_PANELS_MENU_VARIANT.DRAWER, panels, selectedPanel, onItemNavigate });
//Генерация содержимого
return <List sx={{ paddingTop: 0 }}>{panelsLinks}</List>;
};
//Контроль свойств - Меню панелей - сдвигающееся боковое меню
P8PPanelsMenuDrawer.propTypes = {
onItemNavigate: PropTypes.func,
panels: PropTypes.arrayOf(P8P_PANELS_MENU_PANEL_SHAPE).isRequired,
selectedPanel: P8P_PANELS_MENU_PANEL_SHAPE
};
//Меню панелей - грид
const P8PPanelsMenuGrid = ({ onItemNavigate, navigateCaption, panels = [], defaultGroupTytle } = {}) => {
//Формируем ссылки на панели
const panelsLinks = getPanelsLinks({
variant: P8P_PANELS_MENU_VARIANT.GRID,
panels,
defaultGroupTytle,
navigateCaption,
onItemNavigate
});
//Генерация содержимого
return (
<Box sx={P8P_BOX_PANELS_MENU_CONTAINER}>
<Grid container spacing={2} p={2} variant={P8P_GRID_VARIANT.PANELS_MENU}>
{panelsLinks}
</Grid>
</Box>
);
};
//Контроль свойств - Меню панелей - грид
P8PPanelsMenuGrid.propTypes = {
onItemNavigate: PropTypes.func,
navigateCaption: PropTypes.string.isRequired,
panels: PropTypes.arrayOf(P8P_PANELS_MENU_PANEL_SHAPE).isRequired,
defaultGroupTytle: PropTypes.string.isRequired
};
//Меню панелей - рабочий стол
const P8PPanelsMenuDesktop = ({ group, onItemNavigate, panels = [], defaultGroupTytle } = {}) => {
//Формируем ссылки на панели
const panelsLinks = getPanelsLinks({ variant: P8P_PANELS_MENU_VARIANT.DESKTOP, panels, group, defaultGroupTytle, onItemNavigate });
//Генерация содержимого
return (
<Box p={2}>
{panelsLinks[0]}
<Stack direction="row">{panelsLinks.map((l, i) => (i > 0 ? l : null))}</Stack>
</Box>
);
};
//Контроль свойств - Меню панелей - рабочий стол
P8PPanelsMenuDesktop.propTypes = {
group: PropTypes.string,
onItemNavigate: PropTypes.func,
panels: PropTypes.arrayOf(P8P_PANELS_MENU_PANEL_SHAPE).isRequired,
defaultGroupTytle: PropTypes.string.isRequired
};
//----------------
//Интерфейс модуля
//----------------
export { P8P_PANELS_MENU_PANEL_SHAPE, P8PPanelsMenuDrawer, P8PPanelsMenuGrid, P8PPanelsMenuDesktop };