150 lines
6.5 KiB
JavaScript
150 lines
6.5 KiB
JavaScript
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) => {
|
|
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;
|
|
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: 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 (
|
|
<td key={item.id} className="tree-table-cell" title={item.title}>
|
|
<div className="cell-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>
|
|
</td>
|
|
);
|
|
}
|
|
})}
|
|
</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; |