199 lines
5.9 KiB
JavaScript
Executable File
199 lines
5.9 KiB
JavaScript
Executable File
import React, { useState, useEffect } from "react";
|
|
import { Box, styled } from "@mui/material";
|
|
import { statusManager1, statusManager2 } from "../TreeChart/dataUtils";
|
|
import generateTabContent from "../TreeChart/tabContent";
|
|
import CustomTabs from "../UI/MUItabs";
|
|
import useTabs from "../hooks/useTabs";
|
|
import useSidebarResize from "../hooks/useSidebarResize";
|
|
import TabContent from "../hooks/TabContent";
|
|
import menuData from "../TreeChart/menuData.json";
|
|
import SidebarMenuWrapper from "./SidebarMenuWrapper";
|
|
import MetricTabContent from "./MetricTabContent";
|
|
import ProfileMenu from "../UI/ProfileMenu";
|
|
|
|
const DashboardContainer = styled(Box)(({ theme }) => ({
|
|
display: 'flex',
|
|
height: '100vh',
|
|
width: '100vw',
|
|
overflow: 'hidden',
|
|
backgroundColor: theme.palette.background.default,
|
|
color: theme.palette.text.primary,
|
|
}));
|
|
|
|
const MainContent = styled(Box)(({ theme }) => ({
|
|
flexGrow: 1,
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
padding: theme.spacing(2.5),
|
|
overflow: 'auto',
|
|
backgroundColor: theme.palette.background.default,
|
|
}));
|
|
|
|
const Content = styled(Box)(({ theme }) => ({
|
|
backgroundColor: theme.palette.custom.modalBackground,
|
|
borderRadius: '10px',
|
|
maxWidth: '100%',
|
|
overflow: 'auto',
|
|
color: theme.palette.custom.modalText,
|
|
}));
|
|
|
|
const Dashboard = ({ isDarkMode, setIsDarkMode, user, onLogout }) => {
|
|
const { tabs, activeTab, handleOpenTab, handleCloseTab, setActiveTab } = useTabs("Главная");
|
|
const [tabContent, setTabContent] = useState({});
|
|
const [treeData1, setTreeData1] = useState(menuData);
|
|
const [treeData2, setTreeData2] = useState(menuData);
|
|
const [statusHistories, setStatusHistories] = useState({
|
|
history1: [],
|
|
history2: [],
|
|
});
|
|
|
|
useEffect(() => {
|
|
const generatedTabContent = generateTabContent(menuData);
|
|
setTabContent(generatedTabContent);
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
const interval = setInterval(() => {
|
|
const updatedData1 = JSON.parse(JSON.stringify(treeData1));
|
|
const averageStatusValue1 = statusManager1.updateStatuses(updatedData1);
|
|
const statusPercentage1 = Math.max(0, Math.min(100, averageStatusValue1 * 100));
|
|
|
|
const updatedData2 = JSON.parse(JSON.stringify(treeData2));
|
|
const averageStatusValue2 = statusManager2.updateStatuses(updatedData2);
|
|
const statusPercentage2 = Math.max(0, Math.min(100, averageStatusValue2 * 100));
|
|
|
|
setStatusHistories((prevHistories) => ({
|
|
history1: [
|
|
...prevHistories.history1.slice(-29),
|
|
{ time: new Date().toLocaleTimeString(), status: statusPercentage1 },
|
|
],
|
|
history2: [
|
|
...prevHistories.history2.slice(-29),
|
|
{ time: new Date().toLocaleTimeString(), status: statusPercentage2 },
|
|
],
|
|
}));
|
|
|
|
setTreeData1(updatedData1);
|
|
setTreeData2(updatedData2);
|
|
}, 30000);
|
|
|
|
return () => clearInterval(interval);
|
|
}, [treeData1, treeData2]);
|
|
|
|
const handleMenuSelect = (item) => {
|
|
const tabId = `tab_${item.id}`;
|
|
const tabTitle = item.title || 'Новая вкладка';
|
|
|
|
const tabContent = item.metric
|
|
? <MetricTabContent
|
|
metricInfo={{
|
|
name: item.metric,
|
|
filters: item.filters,
|
|
title: item.title,
|
|
description: item.description,
|
|
ranges: item.ranges,
|
|
context: {
|
|
device: item.filters?.device,
|
|
source_id: item.filters?.source_id,
|
|
parent: item
|
|
}
|
|
}}
|
|
/>
|
|
: <div style={{ padding: 20 }}>Контент для <strong>{item.title}</strong></div>;
|
|
|
|
const existingTab = tabs.find(tab => tab.id === tabId);
|
|
|
|
if (!existingTab) {
|
|
const newTab = {
|
|
id: tabId,
|
|
title: tabTitle,
|
|
content: tabContent,
|
|
type: item.metric ? 'metric' : 'menuItem',
|
|
metric: item.metric,
|
|
filters: item.filters,
|
|
ranges: item.ranges
|
|
};
|
|
handleOpenTab(newTab);
|
|
} 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>
|
|
|
|
<Box
|
|
sx={{
|
|
position: 'fixed',
|
|
top: 12,
|
|
right: 20,
|
|
zIndex: (theme) => theme.zIndex.tooltip + 10,
|
|
pointerEvents: 'auto'
|
|
}}
|
|
>
|
|
<ProfileMenu user={user} onLogout={onLogout} />
|
|
</Box>
|
|
|
|
{/* Сайдбар */}
|
|
<SidebarMenuWrapper
|
|
isDarkMode={isDarkMode}
|
|
setIsDarkMode={setIsDarkMode}
|
|
onMenuSelect={handleMenuSelect}
|
|
user={user}
|
|
/>
|
|
|
|
{/* Основной контент */}
|
|
<Box sx={{
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
flexGrow: 1,
|
|
overflow: 'hidden'
|
|
}}>
|
|
{/* Вкладки */}
|
|
<Box sx={{
|
|
borderBottom: 1,
|
|
borderColor: 'divider',
|
|
backgroundColor: 'background.default',
|
|
zIndex: 1,
|
|
transform: 'translateY(31px)'
|
|
}}>
|
|
<CustomTabs
|
|
tabs={tabs}
|
|
activeTab={activeTab}
|
|
onTabClick={setActiveTab}
|
|
onCloseTab={handleCloseTab}
|
|
/>
|
|
</Box>
|
|
|
|
{/* Остальной контент */}
|
|
<MainContent>
|
|
{/* Контент вкладки */}
|
|
<Content>
|
|
<TabContent
|
|
activeTab={activeTab}
|
|
statusHistories={statusHistories}
|
|
treeData1={treeData1}
|
|
tabContent={tabContent}
|
|
handleOpenTab={handleOpenTab}
|
|
tabs={tabs}
|
|
/>
|
|
</Content>
|
|
</MainContent>
|
|
</Box>
|
|
</DashboardContainer>
|
|
);
|
|
};
|
|
|
|
export default Dashboard; |