automatic generation of tabs for the sidebar menu
parent
069cea21b0
commit
efd8532ac3
|
|
@ -9,7 +9,7 @@ import TabContent from "../hooks/TabContent";
|
||||||
import menuData from "../TreeChart/menuData.json";
|
import menuData from "../TreeChart/menuData.json";
|
||||||
import SidebarMenuWrapper from "./SidebarMenuWrapper";
|
import SidebarMenuWrapper from "./SidebarMenuWrapper";
|
||||||
|
|
||||||
// Создаем стилизованные компоненты
|
// Стилизованные компоненты
|
||||||
const DashboardContainer = styled(Box)(({ theme }) => ({
|
const DashboardContainer = styled(Box)(({ theme }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
height: '100vh',
|
height: '100vh',
|
||||||
|
|
@ -82,49 +82,36 @@ const Dashboard = ({ isDarkMode, setIsDarkMode }) => {
|
||||||
const handleMenuSelect = (item) => {
|
const handleMenuSelect = (item) => {
|
||||||
const tabId = `tab_${item.id}`;
|
const tabId = `tab_${item.id}`;
|
||||||
const tabTitle = item.title || 'Новая вкладка';
|
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);
|
const existingTab = tabs.find(tab => tab.id === tabId);
|
||||||
|
|
||||||
if (!existingTab) {
|
if (!existingTab) {
|
||||||
const newTab = {
|
handleOpenTab(tabId, tabTitle, tabContent); // Передаем аргументы отдельно
|
||||||
id: tabId,
|
|
||||||
title: tabTitle,
|
|
||||||
content: generateTabContentForItem(item),
|
|
||||||
type: 'menuItem',
|
|
||||||
itemData: item // Сохраняем данные элемента для возможного обновления
|
|
||||||
};
|
|
||||||
|
|
||||||
handleOpenTab(newTab);
|
|
||||||
} else {
|
} else {
|
||||||
setActiveTab(tabId);
|
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 (
|
return (
|
||||||
<DashboardContainer>
|
<DashboardContainer>
|
||||||
{/* Сайдбар - теперь используется SidebarMenuWrapper */}
|
{/* Сайдбар */}
|
||||||
<SidebarMenuWrapper
|
<SidebarMenuWrapper
|
||||||
isDarkMode={isDarkMode}
|
isDarkMode={isDarkMode}
|
||||||
setIsDarkMode={setIsDarkMode}
|
setIsDarkMode={setIsDarkMode}
|
||||||
onSelectItem={handleMenuSelect}
|
onMenuSelect={handleMenuSelect}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Основной контент */}
|
{/* Основной контент */}
|
||||||
|
|
@ -160,6 +147,7 @@ const Dashboard = ({ isDarkMode, setIsDarkMode }) => {
|
||||||
treeData1={treeData1}
|
treeData1={treeData1}
|
||||||
tabContent={tabContent}
|
tabContent={tabContent}
|
||||||
handleOpenTab={handleOpenTab}
|
handleOpenTab={handleOpenTab}
|
||||||
|
tabs={tabs}
|
||||||
/>
|
/>
|
||||||
</Content>
|
</Content>
|
||||||
</MainContent>
|
</MainContent>
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,7 @@ const SidebarMenu = ({
|
||||||
collapsed={collapsed}
|
collapsed={collapsed}
|
||||||
level={0}
|
level={0}
|
||||||
onEdit={onEditItem}
|
onEdit={onEditItem}
|
||||||
onSelect={onSelectItem}
|
onSelectItem={onSelectItem}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</List>
|
</List>
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,7 @@ import {
|
||||||
MenuItem as MuiMenuItem
|
MenuItem as MuiMenuItem
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { ExpandLess, ExpandMore, Folder, FolderOpen, Edit } from "@mui/icons-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 }) => ({
|
const StyledListItem = styled(ListItem)(({ theme, level }) => ({
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
|
|
@ -55,25 +54,17 @@ const MenuItem = ({ item, onSelectItem, level = 0, collapsed, onEdit }) => {
|
||||||
setIsOpen(!isOpen);
|
setIsOpen(!isOpen);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleItemClick = (e) => {
|
const handleClick = () => {
|
||||||
e.stopPropagation();
|
if (onSelectItem) {
|
||||||
|
|
||||||
// Если есть обработчик выбора и элемент можно выбрать
|
|
||||||
if (onSelectItem && (!item.items || item.items.length === 0)) {
|
|
||||||
onSelectItem(item);
|
onSelectItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Если есть подэлементы - переключаем раскрытие
|
|
||||||
if (item.items && item.items.length > 0) {
|
|
||||||
setIsOpen(!isOpen);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<StyledListItem
|
<StyledListItem
|
||||||
component="div"
|
component="div"
|
||||||
onClick={handleItemClick}
|
onClick={hasChildren ? handleToggle : handleClick}
|
||||||
onContextMenu={handleContextMenu}
|
onContextMenu={handleContextMenu}
|
||||||
level={level}
|
level={level}
|
||||||
sx={{
|
sx={{
|
||||||
|
|
@ -113,7 +104,6 @@ const MenuItem = ({ item, onSelectItem, level = 0, collapsed, onEdit }) => {
|
||||||
)}
|
)}
|
||||||
</StyledListItem>
|
</StyledListItem>
|
||||||
|
|
||||||
{/* Контекстное меню */}
|
|
||||||
<Menu
|
<Menu
|
||||||
open={contextMenu !== null}
|
open={contextMenu !== null}
|
||||||
onClose={handleCloseContextMenu}
|
onClose={handleCloseContextMenu}
|
||||||
|
|
@ -134,7 +124,7 @@ const MenuItem = ({ item, onSelectItem, level = 0, collapsed, onEdit }) => {
|
||||||
<List component="div" disablePadding>
|
<List component="div" disablePadding>
|
||||||
{item.items.map((child, index) => (
|
{item.items.map((child, index) => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={index}
|
key={child.id ?? index}
|
||||||
item={child}
|
item={child}
|
||||||
onSelectItem={onSelectItem}
|
onSelectItem={onSelectItem}
|
||||||
onEdit={onEdit}
|
onEdit={onEdit}
|
||||||
|
|
@ -149,4 +139,4 @@ const MenuItem = ({ item, onSelectItem, level = 0, collapsed, onEdit }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MenuItem;
|
export default MenuItem;
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ import FlowChart from "../TreeChart/FlowChart";
|
||||||
import { getStatusColor } from "../TreeChart/dataUtils";
|
import { getStatusColor } from "../TreeChart/dataUtils";
|
||||||
|
|
||||||
|
|
||||||
const TabContent = ({ activeTab, statusHistories, treeData1, tabContent, handleOpenTab }) => {
|
const TabContent = ({ activeTab, tabs, statusHistories, treeData1, tabContent, handleOpenTab }) => {
|
||||||
// Функция для подсчета количества элементов каждого статуса
|
// Функция для подсчета количества элементов каждого статуса
|
||||||
const countStatuses = (data) => {
|
const countStatuses = (data) => {
|
||||||
const counts = { green: 0, yellow: 0, orange: 0, red: 0 };
|
const counts = { green: 0, yellow: 0, orange: 0, red: 0 };
|
||||||
|
|
||||||
const countRecursive = (node) => {
|
const countRecursive = (node) => {
|
||||||
if (node.status) {
|
if (node.status) {
|
||||||
counts[node.status]++;
|
counts[node.status]++;
|
||||||
|
|
@ -17,7 +17,7 @@ const TabContent = ({ activeTab, statusHistories, treeData1, tabContent, handleO
|
||||||
node.items.forEach(child => countRecursive(child));
|
node.items.forEach(child => countRecursive(child));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
countRecursive(data);
|
countRecursive(data);
|
||||||
return counts;
|
return counts;
|
||||||
};
|
};
|
||||||
|
|
@ -38,11 +38,11 @@ const TabContent = ({ activeTab, statusHistories, treeData1, tabContent, handleO
|
||||||
<SystemStatusChart data={statusHistories.history2} />
|
<SystemStatusChart data={statusHistories.history2} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Контейнер для индикаторов статусов */}
|
{/* Контейнер для индикаторов статусов */}
|
||||||
<div style={{
|
<div style={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
justifyContent: 'flex-end',
|
justifyContent: 'flex-end',
|
||||||
marginTop: '20px',
|
marginTop: '20px',
|
||||||
gap: '10px'
|
gap: '10px'
|
||||||
}}>
|
}}>
|
||||||
|
|
@ -63,7 +63,7 @@ const TabContent = ({ activeTab, statusHistories, treeData1, tabContent, handleO
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label>Статус компонентов системы</label>
|
<label>Статус компонентов системы</label>
|
||||||
<TreeTable data={treeData1} />
|
<TreeTable data={treeData1} />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -71,7 +71,7 @@ const TabContent = ({ activeTab, statusHistories, treeData1, tabContent, handleO
|
||||||
} else if (activeTab === "Визуализация") {
|
} else if (activeTab === "Визуализация") {
|
||||||
return <FlowChart data={treeData1} onNodeClick={(id, title) => handleOpenTab(id, title)} />;
|
return <FlowChart data={treeData1} onNodeClick={(id, title) => handleOpenTab(id, title)} />;
|
||||||
} else {
|
} else {
|
||||||
const tabData = tabContent[activeTab];
|
const tabData = tabs.find(t => t.id === activeTab);
|
||||||
return tabData ? tabData.content : <p>Нет данных</p>;
|
return tabData ? tabData.content : <p>Нет данных</p>;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,11 @@ const useTabs = (initialTab) => {
|
||||||
if (existingTabIndex >= 0) {
|
if (existingTabIndex >= 0) {
|
||||||
return prevTabs.map((tab, index) => ({
|
return prevTabs.map((tab, index) => ({
|
||||||
...tab,
|
...tab,
|
||||||
content: content || tab.content,
|
title: title || tab.title,
|
||||||
|
content: content || tab.content,
|
||||||
active: index === existingTabIndex
|
active: index === existingTabIndex
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Добавляем новую вкладку
|
// Добавляем новую вкладку
|
||||||
return [
|
return [
|
||||||
...prevTabs.map(tab => ({ ...tab, active: false })),
|
...prevTabs.map(tab => ({ ...tab, active: false })),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue