Compare commits
No commits in common. "88b63959be53cc20e534fd25004b0df160975f5f" and "c9465b3c479069c8e3299da675c536f09b1975d4" have entirely different histories.
88b63959be
...
c9465b3c47
|
|
@ -1,30 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';
|
|
||||||
|
|
||||||
const NegativeStatusChart = ({ data }) => {
|
|
||||||
// Подсчет количества негативных статусов
|
|
||||||
const processedData = data.map(entry => ({
|
|
||||||
time: entry.time,
|
|
||||||
negativeCount: entry.statuses.filter(status => ['yellow', 'orange', 'red'].includes(status)).length
|
|
||||||
}));
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ResponsiveContainer width="100%" height={300}>
|
|
||||||
<LineChart
|
|
||||||
data={processedData}
|
|
||||||
margin={{
|
|
||||||
top: 5, right: 30, left: 20, bottom: 5,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<CartesianGrid strokeDasharray="3 3" />
|
|
||||||
<XAxis dataKey="time" />
|
|
||||||
<YAxis domain={[0, 'dataMax']} />
|
|
||||||
<Tooltip />
|
|
||||||
<Legend />
|
|
||||||
<Line type="monotone" dataKey="negativeCount" stroke="#FF5733" activeDot={{ r: 8 }} />
|
|
||||||
</LineChart>
|
|
||||||
</ResponsiveContainer>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default NegativeStatusChart;
|
|
||||||
|
|
@ -34,45 +34,6 @@ const PrometheusChart = ({ metricName }) => {
|
||||||
const [filteredData, setFilteredData] = useState(null); // Отфильтрованные данные
|
const [filteredData, setFilteredData] = useState(null); // Отфильтрованные данные
|
||||||
const intervalRef = useRef(null);
|
const intervalRef = useRef(null);
|
||||||
|
|
||||||
// Функция для интерполяции данных
|
|
||||||
const interpolateData = (data, minPoints = 15) => {
|
|
||||||
if (data.length >= minPoints) return data;
|
|
||||||
|
|
||||||
const interpolatedData = [];
|
|
||||||
for (let i = 0; i < data.length - 1; i++) {
|
|
||||||
interpolatedData.push(data[i]);
|
|
||||||
|
|
||||||
const currentPoint = data[i];
|
|
||||||
const nextPoint = data[i + 1];
|
|
||||||
|
|
||||||
// Вычисляем разницу во времени между точками
|
|
||||||
const currentTime = new Date(currentPoint.time).getTime();
|
|
||||||
const nextTime = new Date(nextPoint.time).getTime();
|
|
||||||
const timeDiff = nextTime - currentTime;
|
|
||||||
|
|
||||||
// Добавляем промежуточные точки
|
|
||||||
const steps = Math.ceil((minPoints - data.length) / (data.length - 1));
|
|
||||||
for (let j = 1; j <= steps; j++) {
|
|
||||||
const interpolatedTime = new Date(currentTime + (timeDiff * j) / (steps + 1)).toLocaleString();
|
|
||||||
const interpolatedPoint = { time: interpolatedTime };
|
|
||||||
|
|
||||||
// Интерполируем значения для каждой метрики
|
|
||||||
Object.keys(currentPoint).forEach(key => {
|
|
||||||
if (key !== 'time') {
|
|
||||||
const currentValue = currentPoint[key];
|
|
||||||
const nextValue = nextPoint[key];
|
|
||||||
interpolatedPoint[key] = currentValue + ((nextValue - currentValue) * j) / (steps + 1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
interpolatedData.push(interpolatedPoint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interpolatedData.push(data[data.length - 1]); // Добавляем последнюю точку
|
|
||||||
return interpolatedData.slice(0, minPoints); // Обрезаем до minPoints
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
try {
|
try {
|
||||||
let start, end;
|
let start, end;
|
||||||
|
|
@ -186,10 +147,7 @@ const PrometheusChart = ({ metricName }) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const filtered = data.slice(startIndex, endIndex + 1);
|
const filtered = data.slice(startIndex, endIndex + 1);
|
||||||
|
setFilteredData(filtered); // Сохраняем отфильтрованные данные
|
||||||
// Интерполируем данные, если точек меньше 15
|
|
||||||
const interpolated = interpolateData(filtered, 15);
|
|
||||||
setFilteredData(interpolated); // Сохраняем интерполированные данные
|
|
||||||
} else {
|
} else {
|
||||||
setFilteredData(null); // Сбрасываем фильтрацию, если диапазон не выбран
|
setFilteredData(null); // Сбрасываем фильтрацию, если диапазон не выбран
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';
|
|
||||||
|
|
||||||
const SystemStatusChart = ({ data }) => {
|
|
||||||
// Обрезаем массив, оставляя только последние 20 точек
|
|
||||||
const trimmedData = data.slice(-20);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ResponsiveContainer width="100%" height={300}>
|
|
||||||
<LineChart
|
|
||||||
data={trimmedData} // Используем обрезанный массив
|
|
||||||
margin={{
|
|
||||||
top: 5, right: 30, left: 20, bottom: 5,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<CartesianGrid strokeDasharray="3 3" />
|
|
||||||
<XAxis dataKey="time" />
|
|
||||||
<YAxis domain={[0, 100]} />
|
|
||||||
<Tooltip />
|
|
||||||
<Legend />
|
|
||||||
<Line type="monotone" dataKey="status" stroke="#8884d8" activeDot={{ r: 8 }} />
|
|
||||||
</LineChart>
|
|
||||||
</ResponsiveContainer>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SystemStatusChart;
|
|
||||||
|
|
@ -2,7 +2,7 @@ import React, { useState, useEffect, useRef } from "react";
|
||||||
import SidebarMenu from "./SidebarMenu";
|
import SidebarMenu from "./SidebarMenu";
|
||||||
import TreeChart from "../TreeChart/TreeChart";
|
import TreeChart from "../TreeChart/TreeChart";
|
||||||
import "../../Style/Dashboard.css";
|
import "../../Style/Dashboard.css";
|
||||||
import SystemStatusChart from "../../Charts/SystemStatusChart";
|
import ErrorIndicator from "../UI/ErrorIndicator";
|
||||||
import Tabs from "../UI/Tabs";
|
import Tabs from "../UI/Tabs";
|
||||||
import menuData from "../TreeChart/menuData.json"; // Импортируем JSON-данные
|
import menuData from "../TreeChart/menuData.json"; // Импортируем JSON-данные
|
||||||
import TreeTable from "../UI/TreeTable";
|
import TreeTable from "../UI/TreeTable";
|
||||||
|
|
@ -16,7 +16,6 @@ const Dashboard = () => {
|
||||||
const [treeData, setTreeData] = useState(menuData); // Загружаем меню в state
|
const [treeData, setTreeData] = useState(menuData); // Загружаем меню в state
|
||||||
const [sidebarWidth, setSidebarWidth] = useState(250); // Начальная ширина сайдбара
|
const [sidebarWidth, setSidebarWidth] = useState(250); // Начальная ширина сайдбара
|
||||||
const [isResizing, setIsResizing] = useState(false); // Состояние перетаскивания
|
const [isResizing, setIsResizing] = useState(false); // Состояние перетаскивания
|
||||||
const [statusHistory, setStatusHistory] = useState([]); // История статусов для графика
|
|
||||||
const sidebarRef = useRef(null); // Референс на сайдбар
|
const sidebarRef = useRef(null); // Референс на сайдбар
|
||||||
|
|
||||||
// Генерация контента для вкладок на основе menuData
|
// Генерация контента для вкладок на основе menuData
|
||||||
|
|
@ -30,17 +29,7 @@ const Dashboard = () => {
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
setTreeData((prevData) => {
|
setTreeData((prevData) => {
|
||||||
const updatedData = JSON.parse(JSON.stringify(prevData)); // Клонируем данные
|
const updatedData = JSON.parse(JSON.stringify(prevData)); // Клонируем данные
|
||||||
const averageStatusValue = updateStatuses(updatedData); // Обновляем статусы и получаем среднее значение
|
updateStatuses(updatedData); // Обновляем статусы
|
||||||
|
|
||||||
// Преобразуем среднее значение в проценты (0% - 100%)
|
|
||||||
const statusPercentage = (1 - (averageStatusValue / 3)) * 100;
|
|
||||||
|
|
||||||
// Добавляем новое состояние в историю
|
|
||||||
setStatusHistory((prevHistory) => [
|
|
||||||
...prevHistory,
|
|
||||||
{ time: new Date().toLocaleTimeString(), status: statusPercentage }
|
|
||||||
]);
|
|
||||||
|
|
||||||
return updatedData;
|
return updatedData;
|
||||||
});
|
});
|
||||||
}, 30000);
|
}, 30000);
|
||||||
|
|
@ -104,11 +93,8 @@ const Dashboard = () => {
|
||||||
if (activeTab === "Главная") {
|
if (activeTab === "Главная") {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h2>Общий мониторинг состояния системы</h2>
|
<h2>Общий мониторинг</h2>
|
||||||
<label>Процент доверия системы </label>
|
<TreeTable data={treeData.items} /> {/* Используем актуальные данные */}
|
||||||
<SystemStatusChart data={statusHistory} /> {/* График состояния системы */}
|
|
||||||
<label>Статус компонентов системы </label>
|
|
||||||
<TreeTable data={treeData} /> {/* Используем актуальные данные */}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else if (activeTab === "Визуализация") {
|
} else if (activeTab === "Визуализация") {
|
||||||
|
|
|
||||||
|
|
@ -1,56 +1,37 @@
|
||||||
// Функция для генерации случайных статусов
|
// Функция для генерации случайных статусов
|
||||||
const getRandomStatus = () => {
|
const getRandomStatus = () => {
|
||||||
const statuses = [
|
const statuses = [
|
||||||
...Array(90).fill("green"), // 90% chance
|
...Array(90).fill("green"), // 63/70 chance (примерно 90%)
|
||||||
...Array(6).fill("yellow"), // 6% chance
|
...Array(6).fill("yellow"), // 1/70 chance (примерно 1.43%)
|
||||||
...Array(3).fill("orange"), // 3% chance
|
...Array(3).fill("orange"), // 1/70 chance (примерно 1.43%)
|
||||||
...Array(1).fill("red"), // 1% chance
|
...Array(1).fill("red"), // 1/70 chance (примерно 1.43%)
|
||||||
];
|
];
|
||||||
return statuses[Math.floor(Math.random() * statuses.length)];
|
return statuses[Math.floor(Math.random() * statuses.length)];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Функция для получения числового значения статуса
|
|
||||||
const getStatusValue = (status) => {
|
|
||||||
switch (status) {
|
|
||||||
case "green":
|
|
||||||
return 0;
|
|
||||||
case "yellow":
|
|
||||||
return 1;
|
|
||||||
case "orange":
|
|
||||||
return 2;
|
|
||||||
case "red":
|
|
||||||
return 3;
|
|
||||||
default:
|
|
||||||
return 0; // По умолчанию green
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Функция для получения статуса по числовому значению
|
|
||||||
const getStatusFromValue = (value) => {
|
|
||||||
if (value >= 3) return "red";
|
|
||||||
if (value >= 2) return "orange";
|
|
||||||
if (value >= 1) return "yellow";
|
|
||||||
return "green";
|
|
||||||
};
|
|
||||||
|
|
||||||
// Функция для обновления статусов в дереве
|
// Функция для обновления статусов в дереве
|
||||||
const updateStatuses = (data) => {
|
const updateStatuses = (data) => {
|
||||||
if (!data.items || data.items.length === 0) {
|
if (!data.items || data.items.length === 0) {
|
||||||
// Если это элемент нижнего уровня, генерируем случайный статус
|
// Если это элемент нижнего уровня, генерируем случайный статус
|
||||||
data.status = getRandomStatus();
|
data.status = getRandomStatus();
|
||||||
return getStatusValue(data.status);
|
return data.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Рекурсивно обновляем статусы для всех дочерних элементов
|
// Рекурсивно обновляем статусы для всех дочерних элементов
|
||||||
let childStatusValues = data.items.map((child) => updateStatuses(child));
|
let childStatuses = data.items.map((child) => updateStatuses(child));
|
||||||
|
|
||||||
// Вычисляем среднее арифметическое значение статусов
|
// Определяем статус текущего элемента на основе статусов дочерних элементов
|
||||||
const averageStatusValue = childStatusValues.reduce((sum, value) => sum + value, 0) / childStatusValues.length;
|
if (childStatuses.includes("red")) {
|
||||||
|
data.status = "red";
|
||||||
|
} else if (childStatuses.includes("orange")) {
|
||||||
|
data.status = "orange";
|
||||||
|
} else if (childStatuses.includes("yellow")) {
|
||||||
|
data.status = "yellow";
|
||||||
|
} else {
|
||||||
|
data.status = "green";
|
||||||
|
}
|
||||||
|
|
||||||
// Определяем статус текущего элемента на основе среднего значения
|
return data.status;
|
||||||
data.status = getStatusFromValue(averageStatusValue);
|
|
||||||
|
|
||||||
return getStatusValue(data.status);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Функция для получения цвета по статусу
|
// Функция для получения цвета по статусу
|
||||||
|
|
@ -59,13 +40,13 @@ const getStatusColor = (status) => {
|
||||||
case "green":
|
case "green":
|
||||||
return "#4CAF50"; // Зеленый
|
return "#4CAF50"; // Зеленый
|
||||||
case "yellow":
|
case "yellow":
|
||||||
return "#cebd21"; // Желтый
|
return "#FFEB3B"; // Желтый
|
||||||
case "orange":
|
case "orange":
|
||||||
return "#FF9800"; // Оранжевый
|
return "#FF9800"; // Оранжевый
|
||||||
case "red":
|
case "red":
|
||||||
return "#F44336"; // Красный
|
return "#F44336"; // Красный
|
||||||
default:
|
default:
|
||||||
return "#4CAF50"; // По умолчанию зеленый
|
return "#4CAF50"; // Синий (или любой другой стандартный цвет)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
{
|
{
|
||||||
"title": "Сервис ЗВКС",
|
"title": "Сервер ЗВКС",
|
||||||
"id": "1",
|
"id": "1",
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"title": "Функциональные задачи",
|
"title": "Функциональные задачи",
|
||||||
"id": "functional_tasks",
|
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"id": "system_control",
|
"id": "system_control",
|
||||||
|
|
@ -452,11 +451,9 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Медиа сервер",
|
"title": "Медиа сервер",
|
||||||
"id": "media_server_1",
|
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"title": "Аппаратное обеспечение",
|
"title": "Аппаратное обеспечение",
|
||||||
"id": "system_software_1",
|
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"id": "media_system_software_1_2",
|
"id": "media_system_software_1_2",
|
||||||
|
|
@ -478,7 +475,6 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Программное обеспечение",
|
"title": "Программное обеспечение",
|
||||||
"id": "software_1",
|
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"id": "media_software_1_2",
|
"id": "media_software_1_2",
|
||||||
|
|
@ -502,11 +498,9 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Медиа сервер",
|
"title": "Медиа сервер",
|
||||||
"id": "media_server_2",
|
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"title": "Аппаратное обеспечение",
|
"title": "Аппаратное обеспечение",
|
||||||
"id": "system_software_2",
|
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"id": "media_system_software_1_3",
|
"id": "media_system_software_1_3",
|
||||||
|
|
@ -528,7 +522,6 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Программное обеспечение",
|
"title": "Программное обеспечение",
|
||||||
"id": "software_2",
|
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"id": "media_software_1_3",
|
"id": "media_software_1_3",
|
||||||
|
|
@ -552,11 +545,9 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Медиа сервер",
|
"title": "Медиа сервер",
|
||||||
"id": "media_server_3",
|
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"title": "Аппаратное обеспечение",
|
"title": "Аппаратное обеспечение",
|
||||||
"id": "system_software_3",
|
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"id": "media_system_software_1_4",
|
"id": "media_system_software_1_4",
|
||||||
|
|
@ -578,7 +569,6 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Программное обеспечение",
|
"title": "Программное обеспечение",
|
||||||
"id": "software_3",
|
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"id": "media_software_1_4",
|
"id": "media_software_1_4",
|
||||||
|
|
@ -602,11 +592,9 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Медиа сервер",
|
"title": "Медиа сервер",
|
||||||
"id": "media_server_4",
|
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"title": "Аппаратное обеспечение",
|
"title": "Аппаратное обеспечение",
|
||||||
"id": "system_software_4",
|
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"id": "media_system_software_1_5",
|
"id": "media_system_software_1_5",
|
||||||
|
|
@ -628,7 +616,6 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Программное обеспечение",
|
"title": "Программное обеспечение",
|
||||||
"id": "software_4",
|
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"id": "media_software_1_5",
|
"id": "media_software_1_5",
|
||||||
|
|
@ -652,11 +639,9 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Сервер систем",
|
"title": "Сервер систем",
|
||||||
"id": "system_server_1",
|
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"title": "Аппаратное обеспечение",
|
"title": "Аппаратное обеспечение",
|
||||||
"id": "system_software_5",
|
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"id": "copy_system_software_1",
|
"id": "copy_system_software_1",
|
||||||
|
|
@ -678,7 +663,6 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Программное обеспечение",
|
"title": "Программное обеспечение",
|
||||||
"id": "software_5",
|
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"id": "copy_software_1",
|
"id": "copy_software_1",
|
||||||
|
|
@ -702,11 +686,9 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Сервер систем",
|
"title": "Сервер систем",
|
||||||
"id": "system_server_2",
|
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"title": "Аппаратное обеспечение",
|
"title": "Аппаратное обеспечение",
|
||||||
"id": "system_software_6",
|
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"id": "control_system_software_1",
|
"id": "control_system_software_1",
|
||||||
|
|
@ -728,7 +710,6 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Программное обеспечение",
|
"title": "Программное обеспечение",
|
||||||
"id": "software_6",
|
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"id": "control_software_1",
|
"id": "control_software_1",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,382 @@
|
||||||
|
{
|
||||||
|
"title": "Сервис ВКС",
|
||||||
|
"id":"service_VKS",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"title": "Функциональные задачи",
|
||||||
|
"id":"functions",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "system_control",
|
||||||
|
"title": "Контроль системы"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "system_management",
|
||||||
|
"title": "Система управления"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "conference",
|
||||||
|
"title": "Проведение ВКС"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "backup",
|
||||||
|
"title": "Резервное копирование"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "relay_info",
|
||||||
|
"title": "Ретрансляция информации"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Медиа сервер",
|
||||||
|
"id":"media_server_1",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"title": "Аппаратное обеспечение",
|
||||||
|
"id":"system_software_1",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "media_system_software_1",
|
||||||
|
"title": "Центральный процессор"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_system_software_2",
|
||||||
|
"title": "Оперативная память"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_system_software_3",
|
||||||
|
"title": "Жесткий диск"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_system_software_4",
|
||||||
|
"title": "Сетевые адаптеры"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Программное обеспечение",
|
||||||
|
"id":"software_1",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "media_software_1",
|
||||||
|
"title": "ПО"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_software_2",
|
||||||
|
"title": "ПО"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_software_3",
|
||||||
|
"title": "ПО"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_software_4",
|
||||||
|
"title": "ПО"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Медиа сервер",
|
||||||
|
"id":"media_server_2",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"title": "Аппаратное обеспечение",
|
||||||
|
"id":"system_software_2",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "media_system_software_1_2",
|
||||||
|
"title": "Центральный процессор"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_system_software_2_2",
|
||||||
|
"title": "Оперативная память"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_system_software_3_2",
|
||||||
|
"title": "Жесткий диск"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_system_software_4_2",
|
||||||
|
"title": "Сетевые адаптеры"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Программное обеспечение",
|
||||||
|
"id":"software_2",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "media_software_1_2",
|
||||||
|
"title": "ПО"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_software_2_2",
|
||||||
|
"title": "ПО"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_software_3_2",
|
||||||
|
"title": "ПО"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_software_4_2",
|
||||||
|
"title": "ПО"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Медиа сервер",
|
||||||
|
"id":"media_server_3",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"title": "Аппаратное обеспечение",
|
||||||
|
"id":"system_software_3",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "media_system_software_1_3",
|
||||||
|
"title": "Центральный процессор"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_system_software_2_3",
|
||||||
|
"title": "Оперативная память"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_system_software_3_3",
|
||||||
|
"title": "Жесткий диск"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_system_software_4_3",
|
||||||
|
"title": "Сетевые адаптеры"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Программное обеспечение",
|
||||||
|
"id":"software_3",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "media_software_1_3",
|
||||||
|
"title": "ПО"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_software_2_3",
|
||||||
|
"title": "ПО"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_software_3_3",
|
||||||
|
"title": "ПО"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_software_4_3",
|
||||||
|
"title": "ПО"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Медиа сервер",
|
||||||
|
"id":"media_server_4",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"title": "Аппаратное обеспечение",
|
||||||
|
"id":"system_software_4",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "media_system_software_1_4",
|
||||||
|
"title": "Центральный процессор"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_system_software_2_4",
|
||||||
|
"title": "Оперативная память"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_system_software_3_4",
|
||||||
|
"title": "Жесткий диск"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_system_software_4_4",
|
||||||
|
"title": "Сетевые адаптеры"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Программное обеспечение",
|
||||||
|
"id":"software_4",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "media_software_1_4",
|
||||||
|
"title": "ПО"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_software_2_4",
|
||||||
|
"title": "ПО"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_software_3_4",
|
||||||
|
"title": "ПО"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_software_4_4",
|
||||||
|
"title": "ПО"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Медиа сервер",
|
||||||
|
"id":"media_server_5",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"title": "Аппаратное обеспечение",
|
||||||
|
"id":"system_software_5",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "media_system_software_1_5",
|
||||||
|
"title": "Центральный процессор"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_system_software_2_5",
|
||||||
|
"title": "Оперативная память"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_system_software_3_5",
|
||||||
|
"title": "Жесткий диск"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_system_software_4_5",
|
||||||
|
"title": "Сетевые адаптеры"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Программное обеспечение",
|
||||||
|
"id":"software_5",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "media_software_1_5",
|
||||||
|
"title": "ПО"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_software_2_5",
|
||||||
|
"title": "ПО"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_software_3_5",
|
||||||
|
"title": "ПО"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "media_software_4_5",
|
||||||
|
"title": "ПО"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Сервер систем",
|
||||||
|
"id":"system_server_1",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"title": "Аппаратное обеспечение",
|
||||||
|
"id":"system_software_6",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "copy_system_software_1",
|
||||||
|
"title": "Центральный процессор"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "copy_system_software_2",
|
||||||
|
"title": "Оперативная память"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "copy_system_software_3",
|
||||||
|
"title": "Жесткий диск"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "copy_system_software_4",
|
||||||
|
"title": "Сетевые адаптеры"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Программное обеспечение",
|
||||||
|
"id":"software_6",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "copy_software_1",
|
||||||
|
"title": "ПО"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "copy_software_2",
|
||||||
|
"title": "ПО"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "copy_software_3",
|
||||||
|
"title": "ПО"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "copy_software_4",
|
||||||
|
"title": "ПО"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Сервер систем",
|
||||||
|
"id":"system_server_2",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"title": "Аппаратное обеспечение",
|
||||||
|
"id":"system_software_7",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "control_system_software_1",
|
||||||
|
"title": "Центральный процессор"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "control_system_software_2",
|
||||||
|
"title": "Оперативная память"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "control_system_software_3",
|
||||||
|
"title": "Жесткий диск"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "control_system_software_4",
|
||||||
|
"title": "Сетевые адаптеры"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Программное обеспечение",
|
||||||
|
"id":"software_7",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "control_software_1",
|
||||||
|
"title": "ПО"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "control_software_2",
|
||||||
|
"title": "ПО"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "control_software_3",
|
||||||
|
"title": "ПО"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "control_software_4",
|
||||||
|
"title": "ПО"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
import React from "react";
|
||||||
|
import PrometheusChart from '../../Charts/PrometheusChart';
|
||||||
|
|
||||||
|
const tabContent = {
|
||||||
|
// Сервис ВКС
|
||||||
|
service1: { title: "Сервис ВКС", content: <div><h2>Сервис ВКС</h2></div> },
|
||||||
|
|
||||||
|
// Функциональные задачи
|
||||||
|
system_control: { title: "Контроль системы", content: <div><h2>Контроль системы</h2><p>Описание контроля.</p></div> },
|
||||||
|
system_management: { title: "Система управления", content: <div><h2>Система управления</h2><p>Описание системы управления.</p></div> },
|
||||||
|
conference: { title: "Проведение ВКС", content: <div><h2>Проведение ВКС</h2><p>Информация о проведении ВКС.</p></div> },
|
||||||
|
backup: { title: "Резервное копирование", content: <div><h2>Резервное копирование</h2><p>Процесс резервного копирования.</p></div> },
|
||||||
|
relay_info: { title: "Ретрансляция информации", content: <div><h2>Ретрансляция информации</h2><p>Детали ретрансляции.</p></div> },
|
||||||
|
|
||||||
|
// Медиа сервер 1
|
||||||
|
media_system_software_1: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора медиа сервера.</p></div> },
|
||||||
|
media_system_software_2: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти медиа сервера.</p></div> },
|
||||||
|
media_system_software_3: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска медиа сервера.</p></div> },
|
||||||
|
media_system_software_4: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров медиа сервера.</p></div> },
|
||||||
|
media_software_1: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><PrometheusChart /></div> },
|
||||||
|
media_software_2: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
|
||||||
|
media_software_3: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
|
||||||
|
media_software_4: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
|
||||||
|
|
||||||
|
// Медиа сервер 2
|
||||||
|
media_system_software_1_2: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора медиа сервера.</p></div> },
|
||||||
|
media_system_software_2_2: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти медиа сервера.</p></div> },
|
||||||
|
media_system_software_3_2: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска медиа сервера.</p></div> },
|
||||||
|
media_system_software_4_2: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров медиа сервера.</p></div> },
|
||||||
|
media_software_1_2: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><PrometheusChart /></div> },
|
||||||
|
media_software_2_2: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
|
||||||
|
media_software_3_2: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
|
||||||
|
media_software_4_2: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
|
||||||
|
|
||||||
|
// Медиа сервер 3
|
||||||
|
media_system_software_1_3: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора медиа сервера.</p></div> },
|
||||||
|
media_system_software_2_3: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти медиа сервера.</p></div> },
|
||||||
|
media_system_software_3_3: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска медиа сервера.</p></div> },
|
||||||
|
media_system_software_4_3: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров медиа сервера.</p></div> },
|
||||||
|
media_software_1_3: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><PrometheusChart /></div> },
|
||||||
|
media_software_2_3: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
|
||||||
|
media_software_3_3: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
|
||||||
|
media_software_4_3: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
|
||||||
|
|
||||||
|
// Медиа сервер 4
|
||||||
|
media_system_software_1_4: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора медиа сервера.</p></div> },
|
||||||
|
media_system_software_2_4: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти медиа сервера.</p></div> },
|
||||||
|
media_system_software_3_4: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска медиа сервера.</p></div> },
|
||||||
|
media_system_software_4_4: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров медиа сервера.</p></div> },
|
||||||
|
media_software_1_4: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><PrometheusChart /></div> },
|
||||||
|
media_software_2_4: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
|
||||||
|
media_software_3_4: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
|
||||||
|
media_software_4_4: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
|
||||||
|
|
||||||
|
// Медиа сервер 5
|
||||||
|
media_system_software_1_5: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора медиа сервера.</p></div> },
|
||||||
|
media_system_software_2_5: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти медиа сервера.</p></div> },
|
||||||
|
media_system_software_3_5: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска медиа сервера.</p></div> },
|
||||||
|
media_system_software_4_5: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров медиа сервера.</p></div> },
|
||||||
|
media_software_1_5: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><PrometheusChart /></div> },
|
||||||
|
media_software_2_5: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
|
||||||
|
media_software_3_5: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
|
||||||
|
media_software_4_5: { title: "ПО", content: <div><h2>Программное обеспечение медиа сервера</h2><p>Описание ПО медиа сервера.</p></div> },
|
||||||
|
|
||||||
|
// Сервер резервного копирования
|
||||||
|
copy_system_software_1: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора сервера резервного копирования.</p></div> },
|
||||||
|
copy_system_software_2: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти сервера резервного копирования.</p></div> },
|
||||||
|
copy_system_software_3: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска сервера резервного копирования.</p></div> },
|
||||||
|
copy_system_software_4: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров сервера резервного копирования.</p></div> },
|
||||||
|
copy_software_1: { title: "ПО", content: <div><h2>Программное обеспечение сервера резервного копирования</h2><p>Описание ПО сервера резервного копирования.</p></div> },
|
||||||
|
copy_software_2: { title: "ПО", content: <div><h2>Программное обеспечение сервера резервного копирования</h2><p>Описание ПО сервера резервного копирования.</p></div> },
|
||||||
|
copy_software_3: { title: "ПО", content: <div><h2>Программное обеспечение сервера резервного копирования</h2><p>Описание ПО сервера резервного копирования.</p></div> },
|
||||||
|
copy_software_4: { title: "ПО", content: <div><h2>Программное обеспечение сервера резервного копирования</h2><p>Описание ПО сервера резервного копирования.</p></div> },
|
||||||
|
|
||||||
|
// Сервер системы управления
|
||||||
|
control_system_software_1: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора сервера системы управления.</p></div> },
|
||||||
|
control_system_software_2: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти сервера системы управления.</p></div> },
|
||||||
|
control_system_software_3: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска сервера системы управления.</p></div> },
|
||||||
|
control_system_software_4: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров сервера системы управления.</p></div> },
|
||||||
|
control_software_1: { title: "ПО", content: <div><h2>Программное обеспечение сервера системы управления</h2><p>Описание ПО сервера системы управления.</p></div> },
|
||||||
|
control_software_2: { title: "ПО", content: <div><h2>Программное обеспечение сервера системы управления</h2><p>Описание ПО сервера системы управления.</p></div> },
|
||||||
|
control_software_3: { title: "ПО", content: <div><h2>Программное обеспечение сервера системы управления</h2><p>Описание ПО сервера системы управления.</p></div> },
|
||||||
|
control_software_4: { title: "ПО", content: <div><h2>Программное обеспечение сервера системы управления</h2><p>Описание ПО сервера системы управления.</p></div> },
|
||||||
|
|
||||||
|
// Сервер сбора и ретрансляции информации
|
||||||
|
system_software_1: { title: "Центральный процессор", content: <div><h2>Центральный процессор</h2><p>Описание центрального процессора сервера сбора и ретрансляции информации.</p></div> },
|
||||||
|
system_software_2: { title: "Оперативная память", content: <div><h2>Оперативная память</h2><p>Описание оперативной памяти сервера сбора и ретрансляции информации.</p></div> },
|
||||||
|
system_software_3: { title: "Жесткий диск", content: <div><h2>Жесткий диск</h2><p>Описание жесткого диска сервера сбора и ретрансляции информации.</p></div> },
|
||||||
|
system_software_4: { title: "Сетевые адаптеры", content: <div><h2>Сетевые адаптеры</h2><p>Описание сетевых адаптеров сервера сбора и ретрансляции информации.</p></div> },
|
||||||
|
software_1: { title: "ПО", content: <div><h2>Программное обеспечение сервера сбора и ретрансляции информации</h2><p>Описание ПО сервера сбора и ретрансляции информации.</p></div> },
|
||||||
|
software_2: { title: "ПО", content: <div><h2>Программное обеспечение сервера сбора и ретрансляции информации</h2><p>Описание ПО сервера сбора и ретрансляции информации.</p></div> },
|
||||||
|
software_3: { title: "ПО", content: <div><h2>Программное обеспечение сервера сбора и ретрансляции информации</h2><p>Описание ПО сервера сбора и ретрансляции информации.</p></div> },
|
||||||
|
software_4: { title: "ПО", content: <div><h2>Программное обеспечение сервера сбора и ретрансляции информации</h2><p>Описание ПО сервера сбора и ретрансляции информации.</p></div> },
|
||||||
|
};
|
||||||
|
|
||||||
|
export default tabContent;
|
||||||
|
|
@ -5,6 +5,7 @@ const Modal = ({ children, onClose }) => {
|
||||||
<div className="modal-overlay">
|
<div className="modal-overlay">
|
||||||
<div className="modal">
|
<div className="modal">
|
||||||
{children}
|
{children}
|
||||||
|
<button onClick={onClose}>Закрыть</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,146 +1,76 @@
|
||||||
import React, { useEffect, useRef, useState } from "react";
|
import React from "react";
|
||||||
import "../../Style/TreeTable.css";
|
import "../../Style/TreeTable.css";
|
||||||
import { getStatusColor } from "../TreeChart/dataUtils";
|
import { getStatusColor } from "../TreeChart/dataUtils"; // Импортируем функцию
|
||||||
|
|
||||||
const TreeTable = ({ data }) => {
|
const TreeTable = ({ data }) => {
|
||||||
const tableRef = useRef(null);
|
// Фильтруем данные, чтобы убрать "Функциональные задачи"
|
||||||
const [fontSize, setFontSize] = useState(16);
|
const filteredData = data.filter((item) => item.title !== "Функциональные задачи");
|
||||||
const [log, setLog] = useState([]);
|
|
||||||
const [isLogVisible, setIsLogVisible] = useState(true);
|
|
||||||
|
|
||||||
const adjustFontSize = () => {
|
|
||||||
if (tableRef.current) {
|
|
||||||
let newSize = 16;
|
|
||||||
const maxWidth = window.innerWidth;
|
|
||||||
|
|
||||||
while (tableRef.current.scrollWidth > maxWidth && newSize > 10) {
|
|
||||||
newSize -= 1;
|
|
||||||
tableRef.current.style.fontSize = `${newSize}px`;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (tableRef.current.scrollWidth < maxWidth && newSize < 16) {
|
|
||||||
newSize += 1;
|
|
||||||
tableRef.current.style.fontSize = `${newSize}px`;
|
|
||||||
}
|
|
||||||
|
|
||||||
setFontSize(newSize);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
adjustFontSize();
|
|
||||||
window.addEventListener("resize", adjustFontSize);
|
|
||||||
return () => window.removeEventListener("resize", adjustFontSize);
|
|
||||||
}, [data]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const newLog = [];
|
|
||||||
const traverse = (items) => {
|
|
||||||
items.forEach((item) => {
|
|
||||||
if (["yellow", "orange", "red"].includes(item.status)) {
|
|
||||||
newLog.push({
|
|
||||||
title: item.title,
|
|
||||||
status: item.status,
|
|
||||||
time: new Date().toLocaleTimeString() // Добавляем время
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (item.items) {
|
|
||||||
traverse(item.items);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
traverse(data.items);
|
|
||||||
setLog(newLog);
|
|
||||||
}, [data]);
|
|
||||||
|
|
||||||
const filteredData = data.items.filter((item) => item.title !== "Функциональные задачи");
|
|
||||||
|
|
||||||
const renderHeaders = (items) => {
|
|
||||||
return items.map((item) => {
|
|
||||||
const colSpan = item.items ? item.items.length : 1;
|
|
||||||
return (
|
|
||||||
<th key={item.id} colSpan={colSpan} className="tree-table-header" title={item.title}>
|
|
||||||
<div className="header-content">
|
|
||||||
<div className="status-indicator-bar" style={{ backgroundColor: getStatusColor(item.status) }} />
|
|
||||||
{item.title}
|
|
||||||
</div>
|
|
||||||
</th>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderRows = (items) => {
|
|
||||||
if (!items || items.length === 0) return null;
|
|
||||||
const hasChildren = items.some((item) => item.items && item.items.length > 0);
|
|
||||||
if (!hasChildren) return null;
|
|
||||||
return (
|
|
||||||
<tr className="tree-table-row">
|
|
||||||
{items.map((item) => {
|
|
||||||
if (item.items && item.items.length > 0) {
|
|
||||||
return (
|
|
||||||
<React.Fragment key={item.id}>
|
|
||||||
{item.items.map((child) => (
|
|
||||||
<td key={child.id} className="tree-table-cell" title={child.title}>
|
|
||||||
<div className="cell-content">
|
|
||||||
<div className="status-indicator-bar" style={{ backgroundColor: getStatusColor(child.status) }} />
|
|
||||||
{child.title}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
))}
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<td key={item.id} className="tree-table-cell" title={item.title}>
|
|
||||||
<div className="cell-content">
|
|
||||||
<div className="status-indicator-bar" style={{ backgroundColor: getStatusColor(item.status) }} />
|
|
||||||
{item.title}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})}
|
|
||||||
</tr>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="tree-table-container">
|
<div className="table-container">
|
||||||
<table ref={tableRef} className="tree-table" style={{ fontSize: `${fontSize}px` }}>
|
<table className="tree-table">
|
||||||
<thead>
|
<thead>
|
||||||
|
{/* Первый уровень: Заголовки "Медиа сервер" */}
|
||||||
<tr>
|
<tr>
|
||||||
<th
|
{filteredData.map((item, index) => (
|
||||||
colSpan={filteredData.reduce((acc, item) => acc + (item.items ? item.items.length : 1), 0)}
|
<th key={index} colSpan="2" className="tree-table-header" style={{ backgroundColor: getStatusColor(item.status) }}>
|
||||||
className="tree-table-header"
|
{item.title}
|
||||||
title={data.title}
|
</th>
|
||||||
>
|
|
||||||
<div className="header-content">
|
|
||||||
<div className="status-indicator-bar" style={{ backgroundColor: getStatusColor(data.status) }} />
|
|
||||||
{data.title}
|
|
||||||
</div>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
<tr>{renderHeaders(filteredData)}</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>{renderRows(filteredData)}</tbody>
|
|
||||||
</table>
|
|
||||||
<button onClick={() => setIsLogVisible(!isLogVisible)} className="toggle-log-button">
|
|
||||||
{isLogVisible ? "Скрыть лог" : "Показать лог"}
|
|
||||||
</button>
|
|
||||||
{isLogVisible && (
|
|
||||||
<div className="status-log">
|
|
||||||
<h3>Лог статусов</h3>
|
|
||||||
<ul>
|
|
||||||
{log.map((entry, index) => (
|
|
||||||
<li key={index} style={{ color: getStatusColor(entry.status) }}>
|
|
||||||
[{entry.time}] {entry.status}: {entry.title}
|
|
||||||
</li>
|
|
||||||
))}
|
))}
|
||||||
</ul>
|
</tr>
|
||||||
</div>
|
{/* Второй уровень: "АО" и "ПО" */}
|
||||||
)}
|
<tr>
|
||||||
|
{filteredData.map((item, index) => (
|
||||||
|
<React.Fragment key={index}>
|
||||||
|
<td className="tree-table-subheader" style={{ backgroundColor: getStatusColor(item.items[0]?.status) }}>
|
||||||
|
АО
|
||||||
|
</td>
|
||||||
|
<td className="tree-table-subheader" style={{ backgroundColor: getStatusColor(item.items[1]?.status) }}>
|
||||||
|
ПО
|
||||||
|
</td>
|
||||||
|
</React.Fragment>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{/* Третий уровень: Вложенные элементы "АО" и "ПО" */}
|
||||||
|
{renderRows(filteredData)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TreeTable;
|
// Функция для отображения строк с вложенными элементами
|
||||||
|
const renderRows = (data) => {
|
||||||
|
const rows = [];
|
||||||
|
|
||||||
|
// Находим максимальное количество элементов среди всех "АО" и "ПО"
|
||||||
|
const maxItems = Math.max(
|
||||||
|
...data.flatMap((item) => [
|
||||||
|
item.items[0]?.items?.length || 0, // АО
|
||||||
|
item.items[1]?.items?.length || 0 // ПО
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
// Генерируем строки
|
||||||
|
for (let i = 0; i < maxItems; i++) {
|
||||||
|
rows.push(
|
||||||
|
<tr key={i} className="tree-table-row">
|
||||||
|
{data.map((item, index) => (
|
||||||
|
<React.Fragment key={index}>
|
||||||
|
<td className="tree-table-cell" style={{ backgroundColor: getStatusColor(item.items[0]?.items[i]?.status) }}>
|
||||||
|
{item.items[0]?.items[i]?.title || ""}
|
||||||
|
</td>
|
||||||
|
<td className="tree-table-cell" style={{ backgroundColor: getStatusColor(item.items[1]?.items[i]?.status) }}>
|
||||||
|
{item.items[1]?.items[i]?.title || ""}
|
||||||
|
</td>
|
||||||
|
</React.Fragment>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rows;
|
||||||
|
};
|
||||||
|
export default TreeTable;
|
||||||
|
|
@ -2,11 +2,46 @@
|
||||||
.dashboard-container {
|
.dashboard-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
width: calc(100vw - 20px);
|
width: calc(100vw - 20px); /* Учитываем отступ */
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
background-color: var(--background-color);
|
}
|
||||||
color: var(--text-color);
|
|
||||||
|
/* Сайдбар */
|
||||||
|
.sidebar {
|
||||||
|
height: 100vh;
|
||||||
|
background-color: #3d74c7;
|
||||||
|
color: white;
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
z-index: 999;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: width 0.2s ease;
|
||||||
|
/* Плавное изменение ширины */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Элемент для перетаскивания */
|
||||||
|
.sidebar-resizer {
|
||||||
|
width: 5px;
|
||||||
|
/* Ширина элемента перетаскивания */
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(255, 255, 255, 0.1);
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
cursor: ew-resize;
|
||||||
|
/* Курсор "изменить размер" */
|
||||||
|
transition: background-color 0.2s ease;
|
||||||
|
z-index: 1000;
|
||||||
|
/* Убедимся, что элемент поверх других */
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-resizer:hover {
|
||||||
|
background-color: rgba(255, 255, 255, 0.3);
|
||||||
|
/* Эффект при наведении */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Основной контент */
|
/* Основной контент */
|
||||||
|
|
@ -15,27 +50,24 @@
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
margin-left: 50px;
|
margin-left: 50px;
|
||||||
transition: margin-left 0.2s ease;
|
transition: margin-left 0.2s ease;
|
||||||
overflow: auto;
|
overflow: auto; /* Позволяет прокручивать контент, если он не влезает */
|
||||||
background-color: var(--background-color);
|
|
||||||
color: var(--text-color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Контент */
|
/* Контент */
|
||||||
.content {
|
.content {
|
||||||
background-color: var(--modal-background);
|
background-color: #f9f9f9;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.521);
|
box-shadow: 0 2px 5px rgba(29, 1, 1, 0.521);
|
||||||
max-width: 100%;
|
max-width: 100%; /* Гарантируем, что контент не выйдет за границы */
|
||||||
overflow: auto;
|
overflow: auto; /* Включаем скролл, если нужно */
|
||||||
color: var(--text-color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Заголовки */
|
/* Заголовки */
|
||||||
h2 {
|
h2 {
|
||||||
color: var(--text-color);
|
color: #444;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
color: var(--text-color);
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,129 @@
|
||||||
|
/* DatePicker.css */
|
||||||
|
|
||||||
|
.react-datepicker-wrapper {
|
||||||
|
width: auto;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__input-container input {
|
||||||
|
width: 200px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
background-color: #fff;
|
||||||
|
transition: border-color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__input-container input:focus {
|
||||||
|
border-color: #0078d4;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker {
|
||||||
|
font-family: 'Segoe UI', sans-serif;
|
||||||
|
border: 1px solid #e0e0e0;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
background-color: #fff;
|
||||||
|
/* Непрозрачный фон */
|
||||||
|
z-index: 1000;
|
||||||
|
/* Календарь поверх других элементов */
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker-popper {
|
||||||
|
z-index: 1000;
|
||||||
|
/* Календарь поверх других элементов */
|
||||||
|
pointer-events: auto;
|
||||||
|
/* Разрешить взаимодействие только с календарем */
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__header {
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
/* Непрозрачный фон заголовка */
|
||||||
|
border-bottom: 1px solid #e0e0e0;
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__current-month {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__navigation {
|
||||||
|
top: 12px;
|
||||||
|
border: 0.45rem solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__navigation--previous {
|
||||||
|
left: 12px;
|
||||||
|
border-right-color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__navigation--next {
|
||||||
|
right: 12px;
|
||||||
|
border-left-color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day-names {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0 8px;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day-name {
|
||||||
|
width: 28px;
|
||||||
|
line-height: 28px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__month {
|
||||||
|
background-color: #fff;
|
||||||
|
/* Непрозрачный фон месяца */
|
||||||
|
margin: 0;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__week {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day {
|
||||||
|
width: 28px;
|
||||||
|
line-height: 28px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #333;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 50%;
|
||||||
|
transition: background-color 0.2s ease, color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day:hover {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day--selected {
|
||||||
|
background-color: #0078d4;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day--selected:hover {
|
||||||
|
background-color: #005bb5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day--outside-month {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day--disabled {
|
||||||
|
color: #ccc;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
@ -11,13 +11,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal {
|
.modal {
|
||||||
background: var(--modal-background);
|
background: rgb(255, 255, 255);
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
color: var(--modal-text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal h2 {
|
.modal h2 {
|
||||||
|
|
@ -27,7 +26,7 @@
|
||||||
.modal label {
|
.modal label {
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
color: var(--modal-text);
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal input {
|
.modal input {
|
||||||
|
|
@ -36,22 +35,20 @@
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
border: 1px solid #ccc;
|
border: 1px solid #ccc;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background-color: var(--modal-background);
|
|
||||||
color: var(--modal-text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal button {
|
.modal button {
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
background: var(--accent-color);
|
background: #08294b;
|
||||||
color: var(--text-color);
|
color: white;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal button:hover {
|
.modal button:hover {
|
||||||
background: var(--accent-hover-color);
|
background: #0056b3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
/* Сайдбар */
|
/* Боковое меню */
|
||||||
.sidebar {
|
.sidebar {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
background-color: var(--sidebar-color);
|
background-color: #3d74c7;
|
||||||
color: var(--sidebar-text-color);
|
color: white;
|
||||||
/* Используем переменную для цвета текста */
|
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
transition: width 0.2s ease;
|
transition: width 0.2s ease;
|
||||||
|
/* Плавное изменение ширины */
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
@ -18,8 +18,11 @@
|
||||||
.sidebar-content {
|
.sidebar-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
/* Вертикальная прокрутка */
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
/* Убираем горизонтальную прокрутку */
|
||||||
padding-bottom: 20px;
|
padding-bottom: 20px;
|
||||||
|
/* Отступ для "Помощи" и "Настроек" */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Заголовок меню */
|
/* Заголовок меню */
|
||||||
|
|
@ -27,39 +30,23 @@
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: var(--sidebar-text-color);
|
color: white;
|
||||||
/* Используем переменную для цвета текста */
|
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
/* Добавляем отступы */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Элементы меню */
|
/* Элементы меню */
|
||||||
.menu-item {
|
.menu-item {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
color: var(--sidebar-text-color);
|
color: white;
|
||||||
/* Используем переменную для цвета текста */
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
/* Ширина на всю ширину сайдбара */
|
||||||
|
|
||||||
/* Элемент для перетаскивания */
|
|
||||||
.sidebar-resizer {
|
|
||||||
width: 5px;
|
|
||||||
height: 100%;
|
|
||||||
background-color: rgba(255, 255, 255, 0.1);
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
cursor: ew-resize;
|
|
||||||
transition: background-color 0.2s ease;
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-resizer:hover {
|
|
||||||
background-color: rgba(255, 255, 255, 0.3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-item-header {
|
.menu-item-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
/* Выравниваем элементы по центру */
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
@ -68,6 +55,7 @@
|
||||||
|
|
||||||
.menu-item-header:hover {
|
.menu-item-header:hover {
|
||||||
background-color: rgba(255, 255, 255, 0.1);
|
background-color: rgba(255, 255, 255, 0.1);
|
||||||
|
/* Легкий эффект при наведении */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Круглый индикатор статуса */
|
/* Круглый индикатор статуса */
|
||||||
|
|
@ -75,8 +63,35 @@
|
||||||
width: 10px;
|
width: 10px;
|
||||||
height: 10px;
|
height: 10px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
/* Делаем круглым */
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
|
/* Отступ от текста */
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
/* Запрещаем сжатие */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Анимация мигания для красного индикатора */
|
||||||
|
@keyframes blink {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Полная видимость */
|
||||||
|
50% {
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Полупрозрачность */
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Полная видимость */
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-indicator.blinking {
|
||||||
|
animation: blink 1s infinite;
|
||||||
|
/* Бесконечная анимация с интервалом 1 секунда */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Подменю */
|
/* Подменю */
|
||||||
|
|
@ -88,18 +103,22 @@
|
||||||
/* Футер сайдбара */
|
/* Футер сайдбара */
|
||||||
.sidebar-footer {
|
.sidebar-footer {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
background-color: var(--sidebar-color);
|
background-color: #3d74c7;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
/* Разделительная линия */
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
/* Запрещаем сжатие */
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
/* Ширина на всю ширину сайдбара */
|
||||||
}
|
}
|
||||||
|
|
||||||
.help,
|
.help,
|
||||||
.settings {
|
.settings {
|
||||||
color: var(--sidebar-text-color);
|
color: white;
|
||||||
/* Используем переменную для цвета текста */
|
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
|
/* Отступы между элементами */
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
/* Убираем горизонтальную прокрутку */
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
@ -1,48 +1,58 @@
|
||||||
.tree-table-container {
|
/* Контейнер для таблицы с прокруткой */
|
||||||
|
.table-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
/* Занимает всю доступную ширину */
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
/* Горизонтальная прокрутка при необходимости */
|
||||||
|
margin: 0 auto;
|
||||||
|
/* Центрирование контейнера */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Стили для таблицы */
|
||||||
.tree-table {
|
.tree-table {
|
||||||
width: 100%;
|
width: auto;
|
||||||
|
/* Автоматическая ширина, чтобы таблица могла расширяться */
|
||||||
|
min-width: 95%;
|
||||||
|
/* Минимальная ширина таблицы */
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
text-align: center;
|
margin: 0 auto;
|
||||||
table-layout: fixed;
|
/* Центрирование таблицы */
|
||||||
background-color: var(--table-cell-background);
|
|
||||||
color: var(--table-text-color);
|
|
||||||
/* Используем переменную для цвета текста */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tree-table-header {
|
/* Заголовки таблицы (первый уровень) */
|
||||||
padding: 10px;
|
.tree-table th {
|
||||||
border: 1px solid var(--table-border);
|
border: 1px solid #ddd;
|
||||||
font-weight: bold;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
background-color: var(--table-header-background);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tree-table-cell {
|
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
border: 1px solid var(--table-border);
|
text-align: left;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
/* Запрет на перенос текста */
|
||||||
|
font-weight: bold;
|
||||||
|
/* Жирный шрифт для заголовков */
|
||||||
}
|
}
|
||||||
|
|
||||||
.cell-content,
|
/* Подзаголовки (второй уровень: "АО" и "ПО") */
|
||||||
.header-content {
|
.tree-table-subheader {
|
||||||
display: flex;
|
font-weight: 500;
|
||||||
align-items: center;
|
/* Жирный шрифт для подзаголовков */
|
||||||
gap: 2px;
|
|
||||||
width: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-indicator-bar {
|
/* Ячейки таблицы */
|
||||||
width: 6px;
|
.tree-table td {
|
||||||
height: 20px;
|
border: 1px solid #ddd;
|
||||||
border-radius: 3px;
|
padding: 8px;
|
||||||
flex-shrink: 0;
|
text-align: left;
|
||||||
|
white-space: nowrap;
|
||||||
|
/* Запрет на перенос текста */
|
||||||
|
font-weight: normal;
|
||||||
|
/* Обычный шрифт для ячеек */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Цвет фона для заголовков */
|
||||||
|
.tree-table-header {
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Чередование цвета строк */
|
||||||
|
.tree-table-row:nth-child(even) {
|
||||||
|
background-color: #f9f9f9;
|
||||||
}
|
}
|
||||||
|
|
@ -1,53 +1,72 @@
|
||||||
|
/* src/Style/common.css */
|
||||||
|
|
||||||
/* Контейнер для вкладок */
|
/* Контейнер для вкладок */
|
||||||
.tabs {
|
.tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 5px;
|
gap: 5px;
|
||||||
|
/* Расстояние между вкладками */
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
background-color: var(--sidebar-color);
|
background-color: #3d74c7;
|
||||||
border-bottom: 2px solid var(--accent-color);
|
/* Цвет фона */
|
||||||
|
border-bottom: 2px solid #195fc9;
|
||||||
|
/* Линия под вкладками */
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
/* Прокрутка, если вкладок много */
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
/* Скругление углов */
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
/* Запрет переноса текста */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Стили для отдельной вкладки */
|
/* Стили для отдельной вкладки */
|
||||||
.tab {
|
.tab {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: var(--sidebar-color);
|
background-color: #3d74c7;
|
||||||
color: var(--sidebar-text-color);
|
/* Цвет фона вкладки */
|
||||||
/* Используем переменную для цвета текста */
|
color: white;
|
||||||
|
/* Цвет текста */
|
||||||
padding: 5px 15px;
|
padding: 5px 15px;
|
||||||
|
/* Отступы внутри вкладки */
|
||||||
border-radius: 5px 5px 0 0;
|
border-radius: 5px 5px 0 0;
|
||||||
|
/* Скругление углов */
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
/* Курсор при наведении */
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
/* Запрет сжатия */
|
||||||
transition: background-color 0.3s ease;
|
transition: background-color 0.3s ease;
|
||||||
|
/* Плавное изменение цвета */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Активная вкладка */
|
/* Активная вкладка */
|
||||||
.tab.active {
|
.tab.active {
|
||||||
background-color: var(--accent-color);
|
background-color: #195fc9;
|
||||||
|
/* Цвет фона активной вкладки */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Кнопка закрытия вкладки */
|
/* Кнопка закрытия вкладки */
|
||||||
.close-tab {
|
.close-tab {
|
||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
color: var(--sidebar-text-color);
|
color: white;
|
||||||
/* Используем переменную для цвета текста */
|
/* Цвет крестика */
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
|
/* Отступ от текста */
|
||||||
padding: 0;
|
padding: 0;
|
||||||
transition: color 0.3s ease;
|
transition: color 0.3s ease;
|
||||||
|
/* Плавное изменение цвета */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Эффект при наведении на кнопку закрытия */
|
/* Эффект при наведении на кнопку закрытия */
|
||||||
.close-tab:hover {
|
.close-tab:hover {
|
||||||
color: #ff6b6b;
|
color: #ff6b6b;
|
||||||
|
/* Цвет крестика при наведении */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Эффект при наведении на вкладку */
|
/* Эффект при наведении на вкладку */
|
||||||
.tab:hover {
|
.tab:hover {
|
||||||
background-color: var(--accent-hover-color);
|
background-color: #195fc9;
|
||||||
|
/* Цвет фона при наведении */
|
||||||
}
|
}
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
/* Темная тема, если пользователь предпочитает ее */
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
:root {
|
|
||||||
--background-color: #1E1E1E;
|
|
||||||
--text-color: #E0E0E0;
|
|
||||||
/* Основной цвет текста (светлый) */
|
|
||||||
--sidebar-color: #2d2d2d;
|
|
||||||
/* Темный цвет сайдбара */
|
|
||||||
--sidebar-text-color: #E0E0E0;
|
|
||||||
/* Светлый текст в сайдбаре */
|
|
||||||
--modal-background: #333333;
|
|
||||||
--modal-text: #FFFFFF;
|
|
||||||
--table-border: #444444;
|
|
||||||
--table-header-background: #2d2d2d;
|
|
||||||
--table-cell-background: #333333;
|
|
||||||
--table-text-color: #E0E0E0;
|
|
||||||
/* Светлый текст в таблице */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
/* Светлая тема по умолчанию */
|
|
||||||
:root {
|
|
||||||
--background-color: #FFFFFF;
|
|
||||||
--text-color: #333333;
|
|
||||||
/* Основной цвет текста (черный) */
|
|
||||||
--sidebar-color: #3d74c7;
|
|
||||||
/* Синий цвет сайдбара */
|
|
||||||
--sidebar-text-color: #FFFFFF;
|
|
||||||
/* Белый текст в сайдбаре и вкладках */
|
|
||||||
--modal-background: #FFFFFF;
|
|
||||||
--modal-text: #333333;
|
|
||||||
--table-border: #ddd;
|
|
||||||
--table-header-background: #f9f9f9;
|
|
||||||
--table-cell-background: #FFFFFF;
|
|
||||||
--table-text-color: #000000;
|
|
||||||
/* Черный текст в таблице */
|
|
||||||
}
|
|
||||||
|
|
@ -2,8 +2,6 @@ import { StrictMode } from 'react'
|
||||||
import { createRoot } from 'react-dom/client'
|
import { createRoot } from 'react-dom/client'
|
||||||
import './index.css'
|
import './index.css'
|
||||||
import App from './App.jsx'
|
import App from './App.jsx'
|
||||||
import './Style/light-theme.css'; // Подключаем светлую тему по умолчанию
|
|
||||||
import './Style/dark-theme.css'; // Подключаем темную тему
|
|
||||||
|
|
||||||
createRoot(document.getElementById('root')).render(
|
createRoot(document.getElementById('root')).render(
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue