Range editor update

pull/51/head
DmitriyA 2025-07-08 04:46:12 -04:00
parent 26276e0360
commit 61c623b93d
3 changed files with 67 additions and 46 deletions

View File

@ -1,4 +1,5 @@
import React from 'react';
import { statusConfig } from '../../Components/Layout/SettingsComponents/statusConfig';
import {
Table,
TableBody,
@ -11,15 +12,6 @@ import {
Typography
} from '@mui/material';
// Используем те же цвета, что и в LineChartComponent
const statusColors = {
'0': '#757575', // серый (нет связи)
'1': '#4CAF50', // зеленый (норма)
'2': '#FFC107', // желтый (отклонение)
'3': '#FF9800', // оранжевый (критично)
'4': '#F44336' // красный (авария)
};
const StatusLogTable = ({ logs }) => {
return (
<TableContainer component={Paper} sx={{ mt: 2, maxHeight: 400 }}>
@ -44,10 +36,10 @@ const StatusLogTable = ({ logs }) => {
<TableCell>{log.source_id?.split('$')[1]}</TableCell>
<TableCell>
<Chip
label={getStatusText(log.status)}
style={{
backgroundColor: statusColors[log.status],
color: '#ffffff', // белый текст для лучшей читаемости
label={statusConfig.getStatusText(log.status)}
style={{
backgroundColor: statusConfig.getStatusColor(log.status),
color: '#ffffff',
fontWeight: 'bold',
border: 'none'
}}
@ -57,7 +49,7 @@ const StatusLogTable = ({ logs }) => {
<TableCell>{parseFloat(log.value).toFixed(2)}</TableCell>
<TableCell>
<Typography variant="body2">
{log.description || getStatusDescription(log.status)}
{log.description || statusConfig.getStatusDescription(log.status)}
</Typography>
</TableCell>
</TableRow>
@ -68,27 +60,4 @@ const StatusLogTable = ({ logs }) => {
);
};
// Вспомогательные функции (оставляем без изменений)
const getStatusText = (status) => {
const statusMap = {
'0': 'Нет соединения',
'1': 'Норма',
'2': 'Отклонение',
'3': 'Критично',
'4': 'Авария'
};
return statusMap[status] || 'Неизвестно';
};
const getStatusDescription = (status) => {
const descriptions = {
'0': 'Устройство не отвечает',
'1': 'Параметры в норме',
'2': 'Обнаружены отклонения от нормы',
'3': 'Критическое состояние системы',
'4': 'Аварийное состояние системы'
};
return descriptions[status] || 'Статус неизвестен';
};
export default StatusLogTable;

View File

@ -1,12 +1,13 @@
import React, { useState, useEffect, useCallback, useMemo } from 'react';
import {
TextField, Box, Typography, IconButton, Divider,
CircularProgress, Alert, Collapse, Tooltip, Button
CircularProgress, Alert, Collapse, Tooltip, Button, Select, MenuItem
} from '@mui/material';
import DeleteIcon from '@mui/icons-material/Delete';
import AddIcon from '@mui/icons-material/Add';
import SearchIcon from '@mui/icons-material/Search';
import axios from 'axios';
import { statusConfig } from './statusConfig';
import { VariableSizeList as List } from 'react-window';
import AutoSizer from 'react-virtualized-auto-sizer';
@ -30,7 +31,7 @@ const MetricItem = React.memo(({ metric, index, updateRange, addRange, deleteRan
sx={{
display: 'flex',
gap: 2,
alignItems: 'center',
alignItems: 'flex-end', // Изменено с 'center' на 'flex-end'
mt: 1,
'& > *': { flex: 1 }
}}
@ -51,19 +52,38 @@ const MetricItem = React.memo(({ metric, index, updateRange, addRange, deleteRan
size="small"
variant="standard"
/>
<TextField
<Select
label="Статус"
type="number"
value={r.status}
onChange={(e) => updateRange(index, j, 'status', e.target.value)}
size="small"
variant="standard"
/>
sx={{
// Добавляем вертикальное выравнивание для label
'& .MuiInputLabel-root': {
transform: 'translate(0, -20px) scale(0.75)'
},
// Корректируем положение выбранного значения
'& .MuiSelect-select': {
paddingBottom: '8px'
}
}}
>
{statusConfig.getAvailableStatuses().map(({ value, text }) => (
<MenuItem key={value} value={value}>
{text}
</MenuItem>
))}
</Select>
<Tooltip title="Удалить диапазон">
<IconButton
onClick={() => deleteRange(index, j)}
size="small"
sx={{ flex: 'none' }}
sx={{
flex: 'none',
// Корректируем положение иконки
marginBottom: '8px'
}}
>
<DeleteIcon fontSize="small" />
</IconButton>
@ -238,7 +258,6 @@ const MetricRangeEditor = ({ onSave }) => {
{!loading && (
<>
<Box sx={{ display: 'flex', alignItems: 'flex-end', gap: 1, mb: 2 }}>
<SearchIcon sx={{ color: 'action.active', mr: 1 }} />
<TextField
label="Поиск по метрике"
fullWidth
@ -246,9 +265,15 @@ const MetricRangeEditor = ({ onSave }) => {
onChange={(e) => setFilter(e.target.value)}
variant="standard"
/>
<SearchIcon sx={{ color: 'action.active', mr: 1 }} />
</Box>
<Box sx={{ display: 'flex', gap: 2, alignItems: 'center', mb: 3 }}>
<Box sx={{
display: 'flex',
gap: 2,
alignItems: 'flex-end', // меняем с 'center' на 'flex-end'
mb: 3
}}>
<TextField
label="Новая метрика"
value={newMetricName}
@ -262,7 +287,7 @@ const MetricRangeEditor = ({ onSave }) => {
color="primary"
disabled={!newMetricName.trim()}
>
<AddIcon />
<AddIcon sx={{ color: 'action.active' }} />
</IconButton>
</Tooltip>
</Box>

View File

@ -0,0 +1,27 @@
export const statusConfig = {
statusMap: {
'0': { text: 'Нет соединения', color: '#757575', description: 'Устройство не отвечает' },
'1': { text: 'Норма', color: '#4CAF50', description: 'Параметры в норме' },
'2': { text: 'Отклонение', color: '#FFC107', description: 'Обнаружены отклонения от нормы' },
'3': { text: 'Критично', color: '#FF9800', description: 'Критическое состояние системы' },
'4': { text: 'Авария', color: '#F44336', description: 'Аварийное состояние системы' }
},
getStatusText(status) {
return this.statusMap[status]?.text || 'Неизвестно';
},
getStatusColor(status) {
return this.statusMap[status]?.color || '#757575';
},
getStatusDescription(status) {
return this.statusMap[status]?.description || 'Статус неизвестен';
},
getAvailableStatuses() {
return Object.entries(this.statusMap)
.filter(([key]) => key !== '0') // исключаем статус "Нет соединения"
.map(([value, config]) => ({ value, text: config.text }));
}
};