improving charts
test-org/trust-module-frontend/pipeline/pr-rc This commit looks good
Details
test-org/trust-module-frontend/pipeline/pr-rc This commit looks good
Details
parent
b5b758ffa0
commit
f87274d41a
|
|
@ -37,7 +37,8 @@ const getStatusText = (status) => {
|
|||
0: 'Нет соединения',
|
||||
1: 'Норма',
|
||||
2: 'Отклонение',
|
||||
3: 'Критично'
|
||||
3: 'Критично',
|
||||
4: 'Авария'
|
||||
}[status] || 'Неизвестно';
|
||||
};
|
||||
|
||||
|
|
@ -46,7 +47,8 @@ const getStatusDescription = (status) => {
|
|||
0: 'Устройство не отвечает',
|
||||
1: 'Параметры в норме',
|
||||
2: 'Обнаружены отклонения от нормы',
|
||||
3: 'Критическое состояние системы'
|
||||
3: 'Критическое состояние системы',
|
||||
4: 'Авария'
|
||||
}[status] || 'Статус неизвестен';
|
||||
};
|
||||
|
||||
|
|
@ -143,62 +145,69 @@ const LineChartComponent = ({
|
|||
x1={area.start}
|
||||
x2={area.end}
|
||||
fill={getStatusColor(area.status)}
|
||||
fillOpacity={0.1}
|
||||
/>
|
||||
));
|
||||
};
|
||||
|
||||
const renderRangeAreas = () => {
|
||||
if (!ranges || ranges.length === 0) return null;
|
||||
|
||||
return ranges.map((range, index) => {
|
||||
const hasData = data && data.length > 0;
|
||||
const minX = hasData ? data[0].timestamp : 0;
|
||||
const maxX = hasData ? data[data.length - 1].timestamp : 0;
|
||||
|
||||
return (
|
||||
<ReferenceArea
|
||||
key={`range-${index}`}
|
||||
y1={range.min}
|
||||
y2={range.max}
|
||||
x1={minX}
|
||||
x2={maxX}
|
||||
fill={rangeColors[range.status] || '#e8e8e8'}
|
||||
fillOpacity={0.15}
|
||||
stroke={rangeColors[range.status] || '#e8e8e8'}
|
||||
fillOpacity={0.12}
|
||||
stroke={getStatusColor(area.status)}
|
||||
strokeWidth={1}
|
||||
strokeDasharray="3 3"
|
||||
ifOverflow="extendDomain"
|
||||
strokeOpacity={0.5}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
));
|
||||
};
|
||||
|
||||
const renderRangeLines = () => {
|
||||
if (!ranges || ranges.length === 0) return null;
|
||||
|
||||
const uniqueValues = new Set();
|
||||
ranges.forEach(range => {
|
||||
uniqueValues.add(range.min);
|
||||
uniqueValues.add(range.max);
|
||||
// Собираем только уникальные граничные значения, исключая дубликаты на стыках диапазонов
|
||||
const boundaryValues = [];
|
||||
ranges.forEach((range, index) => {
|
||||
// Для первого диапазона добавляем и min и max
|
||||
if (index === 0) {
|
||||
boundaryValues.push(range.min);
|
||||
boundaryValues.push(range.max);
|
||||
}
|
||||
// Для остальных добавляем только max (min будет совпадать с max предыдущего)
|
||||
else {
|
||||
boundaryValues.push(range.max);
|
||||
}
|
||||
});
|
||||
|
||||
return Array.from(uniqueValues).map((value, index) => (
|
||||
return boundaryValues.map((value, index) => {
|
||||
// Находим диапазон, к которому принадлежит эта граница
|
||||
const range = ranges.find(r => r.min === value || r.max === value);
|
||||
const status = range ? range.status : 1;
|
||||
|
||||
const lineStyle = {
|
||||
1: { strokeWidth: 1, strokeDasharray: "none", opacity: 0.7 },
|
||||
2: { strokeWidth: 2, strokeDasharray: "none", opacity: 0.9 },
|
||||
3: { strokeWidth: 2, strokeDasharray: "none", opacity: 1 },
|
||||
4: { strokeWidth: 2, strokeDasharray: "none", opacity: 1 }
|
||||
}[status] || { strokeWidth: 1, strokeDasharray: "3 3", opacity: 0.7 };
|
||||
|
||||
return (
|
||||
<ReferenceLine
|
||||
key={`line-${index}`}
|
||||
key={`line-${value}`} // Используем значение как ключ для стабильности
|
||||
y={value}
|
||||
stroke="#888"
|
||||
strokeDasharray="3 3"
|
||||
strokeOpacity={0.7}
|
||||
stroke={rangeColors[status] || '#888'}
|
||||
strokeWidth={lineStyle.strokeWidth}
|
||||
strokeDasharray={lineStyle.strokeDasharray}
|
||||
strokeOpacity={lineStyle.opacity}
|
||||
ifOverflow="extendDomain"
|
||||
label={{
|
||||
value: value.toFixed(1),
|
||||
position: 'insideRight',
|
||||
fill: '#888',
|
||||
fontSize: 12
|
||||
position: 'right',
|
||||
fill: rangeColors[status] || '#888',
|
||||
fontSize: 12,
|
||||
fontWeight: 'bold',
|
||||
background: 'rgba(255, 255, 255, 0.9)',
|
||||
padding: [4, 6],
|
||||
borderRadius: 4,
|
||||
stroke: 'none',
|
||||
boxShadow: '0 0 2px rgba(0,0,0,0.1)',
|
||||
textAnchor: 'start'
|
||||
}}
|
||||
/>
|
||||
));
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const renderStatusBoundaries = () => {
|
||||
|
|
@ -290,8 +299,7 @@ const LineChartComponent = ({
|
|||
/>
|
||||
<YAxis />
|
||||
{renderRangeLines()}
|
||||
{renderRangeAreas()}
|
||||
{renderStatusBoundaries()} {/* Добавляем отображение границ */}
|
||||
{renderStatusBoundaries()}
|
||||
{getStatusAreas()}
|
||||
<Tooltip content={<CustomTooltip />} />
|
||||
<Legend />
|
||||
|
|
@ -306,6 +314,8 @@ const LineChartComponent = ({
|
|||
name={title}
|
||||
/>
|
||||
</LineChart>
|
||||
|
||||
|
||||
</ResponsiveContainer>
|
||||
|
||||
{/* Легенда статусов */}
|
||||
|
|
@ -320,6 +330,7 @@ const LineChartComponent = ({
|
|||
{ status: 1, label: '1 - Норма' },
|
||||
{ status: 2, label: '2 - Отклонение' },
|
||||
{ status: 3, label: '3 - Критично' },
|
||||
{ status: 4, label: '4 - Авария' },
|
||||
{ status: 0, label: '0 - Нет связи' }
|
||||
].map(item => (
|
||||
<div key={item.status} style={{ display: 'flex', alignItems: 'center' }}>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
// src/Components/StatusLogTable.jsx
|
||||
import React from 'react';
|
||||
import {
|
||||
Table,
|
||||
|
|
@ -12,11 +11,13 @@ import {
|
|||
Typography
|
||||
} from '@mui/material';
|
||||
|
||||
// Используем те же цвета, что и в LineChartComponent
|
||||
const statusColors = {
|
||||
'0': 'default',
|
||||
'1': 'success',
|
||||
'2': 'warning',
|
||||
'3': 'error'
|
||||
'0': '#757575', // серый (нет связи)
|
||||
'1': '#4CAF50', // зеленый (норма)
|
||||
'2': '#FFC107', // желтый (отклонение)
|
||||
'3': '#FF9800', // оранжевый (критично)
|
||||
'4': '#F44336' // красный (авария)
|
||||
};
|
||||
|
||||
const StatusLogTable = ({ logs }) => {
|
||||
|
|
@ -44,7 +45,12 @@ const StatusLogTable = ({ logs }) => {
|
|||
<TableCell>
|
||||
<Chip
|
||||
label={getStatusText(log.status)}
|
||||
color={statusColors[log.status] || 'default'}
|
||||
style={{
|
||||
backgroundColor: statusColors[log.status],
|
||||
color: '#ffffff', // белый текст для лучшей читаемости
|
||||
fontWeight: 'bold',
|
||||
border: 'none'
|
||||
}}
|
||||
size="small"
|
||||
/>
|
||||
</TableCell>
|
||||
|
|
@ -62,13 +68,14 @@ const StatusLogTable = ({ logs }) => {
|
|||
);
|
||||
};
|
||||
|
||||
// Вспомогательные функции
|
||||
// Вспомогательные функции (оставляем без изменений)
|
||||
const getStatusText = (status) => {
|
||||
const statusMap = {
|
||||
'0': 'Нет соединения',
|
||||
'1': 'Норма',
|
||||
'2': 'Отклонение',
|
||||
'3': 'Критично'
|
||||
'3': 'Критично',
|
||||
'4': 'Авария'
|
||||
};
|
||||
return statusMap[status] || 'Неизвестно';
|
||||
};
|
||||
|
|
@ -78,7 +85,8 @@ const getStatusDescription = (status) => {
|
|||
'0': 'Устройство не отвечает',
|
||||
'1': 'Параметры в норме',
|
||||
'2': 'Обнаружены отклонения от нормы',
|
||||
'3': 'Критическое состояние системы'
|
||||
'3': 'Критическое состояние системы',
|
||||
'4': 'Аварийное состояние системы'
|
||||
};
|
||||
return descriptions[status] || 'Статус неизвестен';
|
||||
};
|
||||
|
|
|
|||
|
|
@ -53,6 +53,19 @@ const PrometheusChart = ({ metricInfo, chartHeight = 580 }) => {
|
|||
.sort((a, b) => a.timestamp - b.timestamp);
|
||||
};
|
||||
|
||||
const downsampleData = (data, maxPoints = 500) => {
|
||||
if (data.length <= maxPoints) return data;
|
||||
|
||||
const ratio = Math.ceil(data.length / maxPoints);
|
||||
return data.filter((_, index) => index % ratio === 0);
|
||||
};
|
||||
|
||||
const calculateStep = (startTime, endTime, maxPoints = 10000) => {
|
||||
const seconds = (endTime.getTime() - startTime.getTime()) / 1000;
|
||||
return Math.max(Math.ceil(seconds / maxPoints), 1); // в секундах
|
||||
};
|
||||
|
||||
|
||||
// Обновляем логи при изменении данных
|
||||
useEffect(() => {
|
||||
if (chartData.length > 0) {
|
||||
|
|
@ -78,15 +91,17 @@ const PrometheusChart = ({ metricInfo, chartHeight = 580 }) => {
|
|||
...(source_id && { source_id: source_id.toString() })
|
||||
};
|
||||
|
||||
const step = calculateStep(start, end);
|
||||
const data = await metricsService.fetchMetricsRange(
|
||||
metricName,
|
||||
Math.floor(start.getTime() / 1000),
|
||||
Math.floor(end.getTime() / 1000),
|
||||
15,
|
||||
step,
|
||||
extendedFilters
|
||||
);
|
||||
|
||||
const formattedData = formatMetricData(data);
|
||||
|
||||
const formattedData = downsampleData(formatMetricData(data), 100); //КОЛИЧЕСТВО ТОЧЕК НА ГРАФИКЕ
|
||||
if (formattedData.length > 0) {
|
||||
setMetricMeta({
|
||||
type: data[0]?.type,
|
||||
|
|
|
|||
Loading…
Reference in New Issue