151 lines
6.1 KiB
JavaScript
Executable File
151 lines
6.1 KiB
JavaScript
Executable File
import React, { useEffect, useRef, useState } from "react";
|
||
import "../../Style/TreeTable.css";
|
||
import { statusManager1, statusManager2 } from "../TreeChart/dataUtils";
|
||
|
||
const TreeTable = ({ data }) => {
|
||
const tableRef = useRef(null);
|
||
const [fontSize, setFontSize] = useState(16);
|
||
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) => {
|
||
// Если это последний уровень, не отображаем заголовок
|
||
if (!item.items || item.items.length === 0) {
|
||
return null;
|
||
}
|
||
|
||
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: statusManager1.getStatusColor(item.status) }} />
|
||
<div className="status-indicator-bar" style={{ backgroundColor: statusManager2.getStatusColor(item.status), marginLeft: "5px" }} />
|
||
{item.title}
|
||
</div>
|
||
</th>
|
||
);
|
||
});
|
||
};
|
||
|
||
const renderRows = (items) => {
|
||
if (!items || items.length === 0) return null;
|
||
|
||
// Если это последний уровень, не отображаем строки
|
||
if (items.every((item) => !item.items || item.items.length === 0)) {
|
||
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: statusManager1.getStatusColor(child.status) }} />
|
||
<div className="status-indicator-bar" style={{ backgroundColor: statusManager2.getStatusColor(child.status), marginLeft: "5px" }} />
|
||
{child.title}
|
||
</div>
|
||
</td>
|
||
))}
|
||
</React.Fragment>
|
||
);
|
||
} else {
|
||
return null; // Не отображаем элементы последнего уровня
|
||
}
|
||
})}
|
||
</tr>
|
||
);
|
||
};
|
||
|
||
return (
|
||
<div className="tree-table-container">
|
||
<table ref={tableRef} className="tree-table" style={{ fontSize: `${fontSize}px` }}>
|
||
<thead>
|
||
<tr>
|
||
<th
|
||
colSpan={filteredData.reduce((acc, item) => acc + (item.items ? item.items.length : 1), 0)}
|
||
className="tree-table-header"
|
||
title={data.title}
|
||
>
|
||
<div className="header-content">
|
||
<div className="status-indicator-bar" style={{ backgroundColor: statusManager1.getStatusColor(data.status) }} />
|
||
<div className="status-indicator-bar" style={{ backgroundColor: statusManager2.getStatusColor(data.status), marginLeft: "5px" }} />
|
||
{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: statusManager1.getStatusColor(entry.status) }}>
|
||
[{entry.time}] {entry.status}: {entry.title}
|
||
</li>
|
||
))}
|
||
</ul>
|
||
</div>
|
||
)}
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default TreeTable; |