From 46da90fbb6873911e5d081a0434d792b1d261955 Mon Sep 17 00:00:00 2001 From: DmitriyA Date: Tue, 8 Apr 2025 01:42:47 -0400 Subject: [PATCH] Fixed the date and time display --- src/Charts/Components/LineChartComponent.jsx | 58 +++++++++---- src/Charts/PrometheusChart.jsx | 91 +++++++++++--------- 2 files changed, 92 insertions(+), 57 deletions(-) diff --git a/src/Charts/Components/LineChartComponent.jsx b/src/Charts/Components/LineChartComponent.jsx index 53d859f..1973bac 100755 --- a/src/Charts/Components/LineChartComponent.jsx +++ b/src/Charts/Components/LineChartComponent.jsx @@ -13,24 +13,33 @@ const LineChartComponent = ({ const chartRef = useRef(null); const containerRef = useRef(null); - const allTimes = Object.values(chartData) + const allTimestamps = Object.values(chartData) .flat() - .map(point => point.time) - .filter((time, index, self) => self.indexOf(time) === index); + .map(point => point.timestamp) + .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 => { - const instanceData = chartData[key].find(p => p.time === time); + const instanceData = chartData[key].find(p => p.timestamp === timestamp); point[key] = instanceData ? instanceData.value : null; }); + 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; useEffect(() => { @@ -47,7 +56,7 @@ const LineChartComponent = ({ const handleMouseDown = (e) => { if (!e || !e.activeLabel) return; setIsSelecting(true); - setSelectionArea({ start: e.activeLabel, end: null }); + setSelectionArea({ start: e.activeLabel, end: null }); // activeLabel — это timestamp }; const handleMouseMove = (e) => { @@ -63,8 +72,8 @@ const LineChartComponent = ({ return; } - const startIndex = data.findIndex(point => point.time === selectionArea.start); - const endIndex = data.findIndex(point => point.time === selectionArea.end); + const startIndex = data.findIndex(point => point.timestamp === selectionArea.start); + const endIndex = data.findIndex(point => point.timestamp === selectionArea.end); if (startIndex >= 0 && endIndex >= 0) { onRangeSelect({ @@ -78,6 +87,9 @@ const LineChartComponent = ({ const CustomTooltip = ({ active, payload, label }) => { if (active && payload && payload.length) { + const currentPoint = data.find(point => point.timestamp === label); + const displayTime = currentPoint?.fullTime || new Date(label).toLocaleString(); + return (
-

{`${label}`}

+

{displayTime}

{payload.map((item, index) => (

{`Значение: ${item.value}`} @@ -98,6 +110,7 @@ const LineChartComponent = ({ return null; }; + if (!data.length) { return

Нет данных для отображения
; } @@ -128,9 +141,21 @@ const LineChartComponent = ({ > { + 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' + }); + }} /> + } /> {Object.keys(chartData).map((instance, index) => ( @@ -152,6 +177,7 @@ const LineChartComponent = ({ fill="#4a6baf" /> )} +
diff --git a/src/Charts/PrometheusChart.jsx b/src/Charts/PrometheusChart.jsx index ab30858..dce480d 100755 --- a/src/Charts/PrometheusChart.jsx +++ b/src/Charts/PrometheusChart.jsx @@ -22,20 +22,21 @@ const PrometheusChart = ({ metricName }) => { const formatTime = useCallback((timestamp, rangeSeconds) => { const date = new Date(timestamp); - if (rangeSeconds > 86400) { - return { - display: date.toLocaleString([], { - day: '2-digit', - month: '2-digit', - year: '2-digit', - hour: '2-digit', - minute: '2-digit' - }), - timestamp: timestamp - }; - } + const showDate = rangeSeconds > 86400; // Показывать дату если диапазон > 24 часов + return { - display: date.toLocaleTimeString([], { + display: date.toLocaleString([], { + + month: showDate ? '2-digit' : undefined, + day: showDate ? '2-digit' : undefined, + hour: '2-digit', + minute: '2-digit', + second: '2-digit' + }), + fullDisplay: date.toLocaleString([], { + + month: '2-digit', + day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' @@ -53,9 +54,9 @@ const PrometheusChart = ({ metricName }) => { }, []); const fetchData = useCallback(() => { - + if (isSelectingRange) return; - + const now = Math.floor(Date.now() / 1000); const start = now - selectedRange.value; const end = now; @@ -70,7 +71,7 @@ const PrometheusChart = ({ metricName }) => { _t: Date.now() }); } - }, [metricName, selectedRange.value, isSelectingRange]); + }, [metricName, selectedRange.value, isSelectingRange]); const groupBySecond = (points) => { const grouped = []; @@ -106,10 +107,21 @@ const PrometheusChart = ({ metricName }) => { const timestamp = item.timestamp > 1e12 ? item.timestamp : item.timestamp * 1000; 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({ - time: formatTime(timestamp, selectedRange.value).display, + time: formattedTime.display, + fullTime: formattedTime.fullDisplay, value: value, timestamp: timestamp }); @@ -117,7 +129,7 @@ const PrometheusChart = ({ metricName }) => { }); Object.keys(newData).forEach(instance => { - newData[instance] = groupBySecond(newData[instance]) + newData[instance] = newData[instance] .sort((a, b) => a.timestamp - b.timestamp) .slice(-1000); }); @@ -179,7 +191,7 @@ const PrometheusChart = ({ metricName }) => { const start = Math.floor(startDate.getTime() / 1000); const end = Math.floor(endDate.getTime() / 1000); const step = calculateStep(start, end); - + try { const response = await axios.get(`${import.meta.env.VITE_BACK_URL}/metrics`, { params: { @@ -189,7 +201,7 @@ const PrometheusChart = ({ metricName }) => { step } }); - + if (response.data) { // Изменили условие, так как бэкенд возвращает массив напрямую processMetricsData({ metric: metricName, @@ -209,17 +221,17 @@ const PrometheusChart = ({ metricName }) => { const handleRangeChange = useCallback((event) => { const selectedValue = event.target.value; const range = TIME_RANGES.find(r => r.value === parseInt(selectedValue, 10)); - + setSelectedRange(range); setUseCustomRange(false); setChartData(null); setSelectedGraphRange(null); setFilteredData(null); - + const now = new Date(); setEndDate(now); setStartDate(new Date(now.getTime() - range.value * 1000)); - + // Переподключение сокета при возврате к стандартным диапазонам if (!socketRef.current?.connected) { socketRef.current?.connect(); @@ -236,7 +248,7 @@ const PrometheusChart = ({ metricName }) => { const handleResetZoom = useCallback(() => { setSelectedGraphRange(null); setFilteredData(null); - setIsSelectingRange(false); + setIsSelectingRange(false); fetchData(); }, [fetchData]); @@ -245,7 +257,7 @@ const PrometheusChart = ({ metricName }) => { // Начало выделения - останавливаем обновления setIsSelectingRange(true); setSelectedGraphRange(range); - + // Отключаем сокет if (socketRef.current?.connected) { socketRef.current.disconnect(); @@ -258,7 +270,7 @@ const PrometheusChart = ({ metricName }) => { } else { // Окончание выделения - возобновляем соединение setIsSelectingRange(false); - + if (!useCustomRange && socketRef.current && !socketRef.current.connected) { socketRef.current.connect(); } @@ -274,16 +286,8 @@ const PrometheusChart = ({ metricName }) => { }, [setupWebSocket]); useEffect(() => { - if (useCustomRange) { - if (socketRef.current?.connected) { - socketRef.current.disconnect(); - } - fetchCustomRangeData(); - return; - } - - if (!socketRef.current?.connected || isSelectingRange) return; - + if (useCustomRange || isSelectingRange) return; + const fetchDataWrapper = () => { try { fetchData(); @@ -291,17 +295,22 @@ const PrometheusChart = ({ metricName }) => { console.error('Error in interval fetch:', error); } }; - + + // Очищаем предыдущий интервал + if (intervalRef.current) { + clearInterval(intervalRef.current); + } + + // Запускаем сразу и затем по интервалу fetchDataWrapper(); intervalRef.current = setInterval(fetchDataWrapper, selectedRange.interval); - + return () => { if (intervalRef.current) { clearInterval(intervalRef.current); - intervalRef.current = null; } }; - }, [fetchData, fetchCustomRangeData, selectedRange.interval, useCustomRange, isSelectingRange]); + }, [fetchData, selectedRange.interval, useCustomRange, isSelectingRange]); useEffect(() => { if (!chartData || !selectedGraphRange) {