diff --git a/src/Components/Layout/SidebarMenu.jsx b/src/Components/Layout/SidebarMenu.jsx
index 98e7962..af22fb1 100644
--- a/src/Components/Layout/SidebarMenu.jsx
+++ b/src/Components/Layout/SidebarMenu.jsx
@@ -1,4 +1,4 @@
-import React, { useState, useEffect } from "react";
+import React, { useState, useEffect, useRef } from "react";
import {
Drawer,
List,
@@ -35,11 +35,10 @@ const SidebarResizer = styled('div')(({ theme }) => ({
const SidebarMenu = ({ data, onOpenTab, sidebarWidth, startResizing, collapsed, setCollapsed }) => {
const [hovered, setHovered] = useState(false);
const [menuData, setMenuData] = useState(data);
+ const contentCache = useRef({});
- // Обновляем статусы при изменении данных
useEffect(() => {
if (data) {
- // Создаем глубокую копию данных, чтобы не мутировать исходные
const dataCopy = JSON.parse(JSON.stringify(data));
statusManager1.updateStatuses(dataCopy);
setMenuData(dataCopy);
@@ -51,9 +50,16 @@ const SidebarMenu = ({ data, onOpenTab, sidebarWidth, startResizing, collapsed,
};
const handleSelectItem = (id, title, children) => {
- onOpenTab(id, title, children);
+ onOpenTab(id, title);
+
+ contentCache.current = tabContent({ items: children }, contentCache.current);
+ if (contentCache.current[id]) {
+ onOpenTab(id, title, contentCache.current[id].content);
+ }
};
+
+
const drawerWidth = collapsed ? 64 : sidebarWidth;
return (
diff --git a/src/Components/TreeChart/tabContent.jsx b/src/Components/TreeChart/tabContent.jsx
index a7845f8..15596a8 100755
--- a/src/Components/TreeChart/tabContent.jsx
+++ b/src/Components/TreeChart/tabContent.jsx
@@ -5,26 +5,23 @@ import Box from '@mui/material/Box';
const PrometheusChart = lazy(() => import('../../Charts/PrometheusChart'));
import LazyChartBatchRenderer from "../hooks/LazyChartBatchRender";
-// Функция для генерации названия метрики на основе id
const getMetricName = (id) => {
return `zvks_apiforsnmp_measure_${id}`;
};
-// Функция для рекурсивного сбора всех id потомков
const getAllChildIds = (node) => {
let ids = [];
if (node.id) {
- ids.push(node.id); // Добавляем id текущего узла
+ ids.push(node.id);
}
if (node.items && node.items.length > 0) {
node.items.forEach((child) => {
- ids = ids.concat(getAllChildIds(child)); // Рекурсивно собираем id потомков
+ ids = ids.concat(getAllChildIds(child));
});
}
return ids;
};
-// Компонент Skeleton для графика
const ChartSkeleton = () => (
{/* Заголовок */}
@@ -32,7 +29,6 @@ const ChartSkeleton = () => (
);
-// Компонент Skeleton для родительского контейнера
const ContainerSkeleton = () => (
{/* Заголовок */}
@@ -46,69 +42,52 @@ const ContainerSkeleton = () => (
);
-const tabContent = (data) => {
- const tabContent = {};
+const tabContent = (data, existingContent = {}) => {
+ const tabContent = { ...existingContent };
- // Функция для рекурсивного обхода и сбора данных
- // Функция для рекурсивного обхода и сбора данных
const generateContent = (nodes) => {
nodes.forEach((node) => {
- // Если у узла есть вложенные элементы, рекурсивно обрабатываем их
+ if (tabContent[node.id]) return;
+
if (node.items && node.items.length > 0) {
- // Создаем контент для родителя
- const childrenContent = generateContent(node.items);
+ generateContent(node.items);
const content = (
-
+
{node.title}
}>
-
tabContent[child.id].content)} />
+ tabContent[child.id]?.content) || }
+ />
- Контент для {node.title}.
- {/*childrenContent*/}
);
- // Сохраняем контент для текущего id
tabContent[node.id] = {
title: node.title,
content: content,
};
} else {
- // Если у узла нет вложенных элементов, это самый нижний уровень
const metricName = getMetricName(node.id);
const content = (
-
{node.title}
{/* Используем title узла */}
+
{node.title}
}>
);
- // Сохраняем контент для текущего id
tabContent[node.id] = {
title: node.title,
content: content,
};
}
});
-
- // Возвращаем контент для всех потомков
- return (
-
- {nodes.map((node) => (
-
{tabContent[node.id].content}
- ))}
-
- );
};
- // Начинаем обработку с корневого уровня
if (data.items && data.items.length > 0) {
generateContent(data.items);
- } else {
- console.warn("Данные отсутствуют или массив items пуст");
}
return tabContent;
diff --git a/src/Components/hooks/useTabs.jsx b/src/Components/hooks/useTabs.jsx
index 188cdf5..2df5f13 100644
--- a/src/Components/hooks/useTabs.jsx
+++ b/src/Components/hooks/useTabs.jsx
@@ -4,23 +4,63 @@ const useTabs = (initialTab) => {
const [tabs, setTabs] = useState([]);
const [activeTab, setActiveTab] = useState(initialTab);
- const handleOpenTab = useCallback((id, title) => {
- setTabs((prevTabs) =>
- prevTabs.some((tab) => tab.id === id)
- ? prevTabs
- : [...prevTabs, { id, title }]
- );
+ const handleOpenTab = useCallback((id, title, content) => {
+ setTabs((prevTabs) => {
+ const existingTabIndex = prevTabs.findIndex(tab => tab.id === id);
+
+ if (existingTabIndex >= 0) {
+ return prevTabs.map((tab, index) => ({
+ ...tab,
+ content: content || tab.content,
+ active: index === existingTabIndex
+ }));
+ }
+
+ // Добавляем новую вкладку
+ return [
+ ...prevTabs.map(tab => ({ ...tab, active: false })),
+ {
+ id,
+ title,
+ content: content ||
Loading...
,
+ active: true
+ }
+ ];
+ });
setActiveTab(id);
}, []);
const handleCloseTab = useCallback((id) => {
- setTabs((prevTabs) => prevTabs.filter((tab) => tab.id !== id));
- if (activeTab === id) {
- setActiveTab(tabs.length > 1 ? tabs[tabs.length - 2].id : initialTab);
- }
- }, [activeTab, tabs, initialTab]);
+ setTabs((prevTabs) => {
+ const newTabs = prevTabs.filter((tab) => tab.id !== id);
- return { tabs, activeTab, handleOpenTab, handleCloseTab, setActiveTab };
+ if (activeTab === id) {
+ setActiveTab(newTabs.length > 0
+ ? newTabs[newTabs.length - 1].id
+ : initialTab
+ );
+ }
+
+ return newTabs;
+ });
+ }, [activeTab, initialTab]);
+
+ const updateTabContent = useCallback((id, content) => {
+ setTabs(prevTabs =>
+ prevTabs.map(tab =>
+ tab.id === id ? { ...tab, content } : tab
+ )
+ );
+ }, []);
+
+ return {
+ tabs,
+ activeTab,
+ handleOpenTab,
+ handleCloseTab,
+ setActiveTab,
+ updateTabContent
+ };
};
export default useTabs;
\ No newline at end of file