Fixed the date and time display

pull/29/head
DmitriyA 2025-04-08 01:42:47 -04:00
parent 64401cadbc
commit 46da90fbb6
2 changed files with 92 additions and 57 deletions

View File

@ -13,24 +13,33 @@ const LineChartComponent = ({
const chartRef = useRef(null); const chartRef = useRef(null);
const containerRef = useRef(null); const containerRef = useRef(null);
const allTimes = Object.values(chartData) const allTimestamps = Object.values(chartData)
.flat() .flat()
.map(point => point.time) .map(point => point.timestamp)
.filter((time, index, self) => self.indexOf(time) === index); .filter((timestamp, index, self) => self.indexOf(timestamp) === index)
.sort((a, b) => a - b);
const data = allTimestamps.map(timestamp => {
const point = { timestamp };
const firstPoint = Object.values(chartData)
.flat()
.find(p => p.timestamp === timestamp);
if (firstPoint) {
point.time = firstPoint.time;
point.fullTime = firstPoint.fullTime;
}
const data = allTimes.map(time => {
const point = { time };
Object.keys(chartData).forEach(key => { Object.keys(chartData).forEach(key => {
const instanceData = chartData[key].find(p => p.time === time); const instanceData = chartData[key].find(p => p.timestamp === timestamp);
point[key] = instanceData ? instanceData.value : null; point[key] = instanceData ? instanceData.value : null;
}); });
return point; return point;
}).sort((a, b) => {
const timeA = chartData[Object.keys(chartData)[0]].find(d => d.time === a.time)?.timestamp;
const timeB = chartData[Object.keys(chartData)[0]].find(d => d.time === b.time)?.timestamp;
return timeA - timeB;
}); });
const displayData = filteredData || data; const displayData = filteredData || data;
useEffect(() => { useEffect(() => {
@ -47,7 +56,7 @@ const LineChartComponent = ({
const handleMouseDown = (e) => { const handleMouseDown = (e) => {
if (!e || !e.activeLabel) return; if (!e || !e.activeLabel) return;
setIsSelecting(true); setIsSelecting(true);
setSelectionArea({ start: e.activeLabel, end: null }); setSelectionArea({ start: e.activeLabel, end: null }); // activeLabel это timestamp
}; };
const handleMouseMove = (e) => { const handleMouseMove = (e) => {
@ -63,8 +72,8 @@ const LineChartComponent = ({
return; return;
} }
const startIndex = data.findIndex(point => point.time === selectionArea.start); const startIndex = data.findIndex(point => point.timestamp === selectionArea.start);
const endIndex = data.findIndex(point => point.time === selectionArea.end); const endIndex = data.findIndex(point => point.timestamp === selectionArea.end);
if (startIndex >= 0 && endIndex >= 0) { if (startIndex >= 0 && endIndex >= 0) {
onRangeSelect({ onRangeSelect({
@ -78,6 +87,9 @@ const LineChartComponent = ({
const CustomTooltip = ({ active, payload, label }) => { const CustomTooltip = ({ active, payload, label }) => {
if (active && payload && payload.length) { if (active && payload && payload.length) {
const currentPoint = data.find(point => point.timestamp === label);
const displayTime = currentPoint?.fullTime || new Date(label).toLocaleString();
return ( return (
<div style={{ <div style={{
backgroundColor: '#fff', backgroundColor: '#fff',
@ -86,7 +98,7 @@ const LineChartComponent = ({
borderRadius: '4px', borderRadius: '4px',
boxShadow: '0 2px 5px rgba(0,0,0,0.1)' boxShadow: '0 2px 5px rgba(0,0,0,0.1)'
}}> }}>
<p style={{ fontWeight: 'bold', marginBottom: '5px' }}>{`${label}`}</p> <p style={{ fontWeight: 'bold', marginBottom: '5px' }}>{displayTime}</p>
{payload.map((item, index) => ( {payload.map((item, index) => (
<p key={index} style={{ color: item.color }}> <p key={index} style={{ color: item.color }}>
{`Значение: ${item.value}`} {`Значение: ${item.value}`}
@ -98,6 +110,7 @@ const LineChartComponent = ({
return null; return null;
}; };
if (!data.length) { if (!data.length) {
return <div style={{ padding: '20px', textAlign: 'center' }}>Нет данных для отображения</div>; return <div style={{ padding: '20px', textAlign: 'center' }}>Нет данных для отображения</div>;
} }
@ -128,9 +141,21 @@ const LineChartComponent = ({
> >
<CartesianGrid strokeDasharray="3 3" stroke="#f0f0f0" /> <CartesianGrid strokeDasharray="3 3" stroke="#f0f0f0" />
<XAxis <XAxis
dataKey="time" dataKey="timestamp"
tick={{ fontSize: 12 }} height={75}
tick={{ fontSize: 12, angle: -45, textAnchor: 'end' }}
interval={Math.max(1, Math.floor(data.length / 10))}
tickFormatter={(timestamp) => {
const point = data.find(p => p.timestamp === timestamp);
return point?.fullTime || new Date(timestamp).toLocaleString('ru-RU', {
day: '2-digit',
month: '2-digit',
hour: '2-digit',
minute: '2-digit'
});
}}
/> />
<YAxis tick={{ fontSize: 12 }} /> <YAxis tick={{ fontSize: 12 }} />
<Tooltip content={<CustomTooltip />} /> <Tooltip content={<CustomTooltip />} />
{Object.keys(chartData).map((instance, index) => ( {Object.keys(chartData).map((instance, index) => (
@ -152,6 +177,7 @@ const LineChartComponent = ({
fill="#4a6baf" fill="#4a6baf"
/> />
)} )}
</LineChart> </LineChart>
</ResponsiveContainer> </ResponsiveContainer>
</div> </div>

View File

@ -22,20 +22,21 @@ const PrometheusChart = ({ metricName }) => {
const formatTime = useCallback((timestamp, rangeSeconds) => { const formatTime = useCallback((timestamp, rangeSeconds) => {
const date = new Date(timestamp); const date = new Date(timestamp);
if (rangeSeconds > 86400) { const showDate = rangeSeconds > 86400; // Показывать дату если диапазон > 24 часов
return { return {
display: date.toLocaleString([], { display: date.toLocaleString([], {
day: '2-digit',
month: '2-digit', month: showDate ? '2-digit' : undefined,
year: '2-digit', day: showDate ? '2-digit' : undefined,
hour: '2-digit', hour: '2-digit',
minute: '2-digit' minute: '2-digit',
second: '2-digit'
}), }),
timestamp: timestamp fullDisplay: date.toLocaleString([], {
};
} month: '2-digit',
return { day: '2-digit',
display: date.toLocaleTimeString([], {
hour: '2-digit', hour: '2-digit',
minute: '2-digit', minute: '2-digit',
second: '2-digit' second: '2-digit'
@ -106,10 +107,21 @@ const PrometheusChart = ({ metricName }) => {
const timestamp = item.timestamp > 1e12 ? item.timestamp : item.timestamp * 1000; const timestamp = item.timestamp > 1e12 ? item.timestamp : item.timestamp * 1000;
const value = parseFloat(item.value); const value = parseFloat(item.value);
const formattedTime = formatTime(timestamp, selectedRange.value);
if (!newData[instance].some(p => p.timestamp === timestamp)) { const existingPointIndex = newData[instance].findIndex(p => p.timestamp === timestamp);
if (existingPointIndex >= 0) {
newData[instance][existingPointIndex] = {
time: formattedTime.display,
fullTime: formattedTime.fullDisplay,
value: value,
timestamp: timestamp
};
} else {
newData[instance].push({ newData[instance].push({
time: formatTime(timestamp, selectedRange.value).display, time: formattedTime.display,
fullTime: formattedTime.fullDisplay,
value: value, value: value,
timestamp: timestamp timestamp: timestamp
}); });
@ -117,7 +129,7 @@ const PrometheusChart = ({ metricName }) => {
}); });
Object.keys(newData).forEach(instance => { Object.keys(newData).forEach(instance => {
newData[instance] = groupBySecond(newData[instance]) newData[instance] = newData[instance]
.sort((a, b) => a.timestamp - b.timestamp) .sort((a, b) => a.timestamp - b.timestamp)
.slice(-1000); .slice(-1000);
}); });
@ -274,15 +286,7 @@ const PrometheusChart = ({ metricName }) => {
}, [setupWebSocket]); }, [setupWebSocket]);
useEffect(() => { useEffect(() => {
if (useCustomRange) { if (useCustomRange || isSelectingRange) return;
if (socketRef.current?.connected) {
socketRef.current.disconnect();
}
fetchCustomRangeData();
return;
}
if (!socketRef.current?.connected || isSelectingRange) return;
const fetchDataWrapper = () => { const fetchDataWrapper = () => {
try { try {
@ -292,16 +296,21 @@ const PrometheusChart = ({ metricName }) => {
} }
}; };
// Очищаем предыдущий интервал
if (intervalRef.current) {
clearInterval(intervalRef.current);
}
// Запускаем сразу и затем по интервалу
fetchDataWrapper(); fetchDataWrapper();
intervalRef.current = setInterval(fetchDataWrapper, selectedRange.interval); intervalRef.current = setInterval(fetchDataWrapper, selectedRange.interval);
return () => { return () => {
if (intervalRef.current) { if (intervalRef.current) {
clearInterval(intervalRef.current); clearInterval(intervalRef.current);
intervalRef.current = null;
} }
}; };
}, [fetchData, fetchCustomRangeData, selectedRange.interval, useCustomRange, isSelectingRange]); }, [fetchData, selectedRange.interval, useCustomRange, isSelectingRange]);
useEffect(() => { useEffect(() => {
if (!chartData || !selectedGraphRange) { if (!chartData || !selectedGraphRange) {