automatic generation of tabs for the sidebar menu

pull/40/head
DmitriyA 2025-05-27 21:40:59 -04:00
parent 069cea21b0
commit efd8532ac3
5 changed files with 36 additions and 58 deletions

View File

@ -9,7 +9,7 @@ import TabContent from "../hooks/TabContent";
import menuData from "../TreeChart/menuData.json";
import SidebarMenuWrapper from "./SidebarMenuWrapper";
// Создаем стилизованные компоненты
// Стилизованные компоненты
const DashboardContainer = styled(Box)(({ theme }) => ({
display: 'flex',
height: '100vh',
@ -82,49 +82,36 @@ const Dashboard = ({ isDarkMode, setIsDarkMode }) => {
const handleMenuSelect = (item) => {
const tabId = `tab_${item.id}`;
const tabTitle = item.title || 'Новая вкладка';
const tabContent = <div style={{ padding: 20 }}>Контент для <strong>{item.title}</strong></div>;
const generateTabContentForItem = (item) => {
return (
<Box p={2}>
<Typography variant="h6">{item.title}</Typography>
{item.description && (
<Typography color="textSecondary">{item.description}</Typography>
)}
{item.metric && (
<Box mt={2}>
<Typography variant="subtitle1">Метрика: {item.metric}</Typography>
{/* Здесь можно добавить визуализацию метрики */}
</Box>
)}
</Box>
);
};
// Проверяем, существует ли уже такая вкладка
const existingTab = tabs.find(tab => tab.id === tabId);
if (!existingTab) {
const newTab = {
id: tabId,
title: tabTitle,
content: generateTabContentForItem(item),
type: 'menuItem',
itemData: item // Сохраняем данные элемента для возможного обновления
};
handleOpenTab(newTab);
handleOpenTab(tabId, tabTitle, tabContent); // Передаем аргументы отдельно
} else {
setActiveTab(tabId);
}
};
// Вспомогательная функция для получения всех дочерних элементов
const getAllChildren = (node) => {
let children = [];
if (node.items && node.items.length > 0) {
node.items.forEach((child) => {
children.push(child);
children = children.concat(getAllChildren(child));
});
}
return children;
};
return (
<DashboardContainer>
{/* Сайдбар - теперь используется SidebarMenuWrapper */}
{/* Сайдбар */}
<SidebarMenuWrapper
isDarkMode={isDarkMode}
setIsDarkMode={setIsDarkMode}
onSelectItem={handleMenuSelect}
onMenuSelect={handleMenuSelect}
/>
{/* Основной контент */}
@ -160,6 +147,7 @@ const Dashboard = ({ isDarkMode, setIsDarkMode }) => {
treeData1={treeData1}
tabContent={tabContent}
handleOpenTab={handleOpenTab}
tabs={tabs}
/>
</Content>
</MainContent>

View File

@ -122,7 +122,7 @@ const SidebarMenu = ({
collapsed={collapsed}
level={0}
onEdit={onEditItem}
onSelect={onSelectItem}
onSelectItem={onSelectItem}
/>
)}
</List>

View File

@ -12,8 +12,7 @@ import {
MenuItem as MuiMenuItem
} from "@mui/material";
import { ExpandLess, ExpandMore, Folder, FolderOpen, Edit } from "@mui/icons-material";
import { getStatusColor } from "../../TreeChart/dataUtils";
import StatusIndicator from "./StatusIndicator"
import StatusIndicator from "./StatusIndicator";
const StyledListItem = styled(ListItem)(({ theme, level }) => ({
cursor: "pointer",
@ -55,25 +54,17 @@ const MenuItem = ({ item, onSelectItem, level = 0, collapsed, onEdit }) => {
setIsOpen(!isOpen);
};
const handleItemClick = (e) => {
e.stopPropagation();
// Если есть обработчик выбора и элемент можно выбрать
if (onSelectItem && (!item.items || item.items.length === 0)) {
const handleClick = () => {
if (onSelectItem) {
onSelectItem(item);
}
// Если есть подэлементы - переключаем раскрытие
if (item.items && item.items.length > 0) {
setIsOpen(!isOpen);
}
};
return (
<>
<StyledListItem
component="div"
onClick={handleItemClick}
onClick={hasChildren ? handleToggle : handleClick}
onContextMenu={handleContextMenu}
level={level}
sx={{
@ -113,7 +104,6 @@ const MenuItem = ({ item, onSelectItem, level = 0, collapsed, onEdit }) => {
)}
</StyledListItem>
{/* Контекстное меню */}
<Menu
open={contextMenu !== null}
onClose={handleCloseContextMenu}
@ -134,7 +124,7 @@ const MenuItem = ({ item, onSelectItem, level = 0, collapsed, onEdit }) => {
<List component="div" disablePadding>
{item.items.map((child, index) => (
<MenuItem
key={index}
key={child.id ?? index}
item={child}
onSelectItem={onSelectItem}
onEdit={onEdit}
@ -149,4 +139,4 @@ const MenuItem = ({ item, onSelectItem, level = 0, collapsed, onEdit }) => {
);
};
export default MenuItem;
export default MenuItem;

View File

@ -4,11 +4,11 @@ import FlowChart from "../TreeChart/FlowChart";
import { getStatusColor } from "../TreeChart/dataUtils";
const TabContent = ({ activeTab, statusHistories, treeData1, tabContent, handleOpenTab }) => {
const TabContent = ({ activeTab, tabs, statusHistories, treeData1, tabContent, handleOpenTab }) => {
// Функция для подсчета количества элементов каждого статуса
const countStatuses = (data) => {
const counts = { green: 0, yellow: 0, orange: 0, red: 0 };
const countRecursive = (node) => {
if (node.status) {
counts[node.status]++;
@ -17,7 +17,7 @@ const TabContent = ({ activeTab, statusHistories, treeData1, tabContent, handleO
node.items.forEach(child => countRecursive(child));
}
};
countRecursive(data);
return counts;
};
@ -38,11 +38,11 @@ const TabContent = ({ activeTab, statusHistories, treeData1, tabContent, handleO
<SystemStatusChart data={statusHistories.history2} />
</div>
</div>
{/* Контейнер для индикаторов статусов */}
<div style={{
display: 'flex',
justifyContent: 'flex-end',
<div style={{
display: 'flex',
justifyContent: 'flex-end',
marginTop: '20px',
gap: '10px'
}}>
@ -63,7 +63,7 @@ const TabContent = ({ activeTab, statusHistories, treeData1, tabContent, handleO
</div>
))}
</div>
<label>Статус компонентов системы</label>
<TreeTable data={treeData1} />
</div>
@ -71,7 +71,7 @@ const TabContent = ({ activeTab, statusHistories, treeData1, tabContent, handleO
} else if (activeTab === "Визуализация") {
return <FlowChart data={treeData1} onNodeClick={(id, title) => handleOpenTab(id, title)} />;
} else {
const tabData = tabContent[activeTab];
const tabData = tabs.find(t => t.id === activeTab);
return tabData ? tabData.content : <p>Нет данных</p>;
}
};

View File

@ -11,11 +11,11 @@ const useTabs = (initialTab) => {
if (existingTabIndex >= 0) {
return prevTabs.map((tab, index) => ({
...tab,
content: content || tab.content,
title: title || tab.title,
content: content || tab.content,
active: index === existingTabIndex
}));
}
// Добавляем новую вкладку
return [
...prevTabs.map(tab => ({ ...tab, active: false })),