2026-08-20 17:25:18 +03:00

194 lines
5.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Box, CircularProgress, Modal, Tab, Tabs, Typography } from '@mui/material';
import { useEffect, useState } from 'react';
import { EVENT_CONFIGS, EVENT_CONFIGS_MULT_DEPENDENTS } from '../constants/configEvent';
import { VALUE_TRANSFORMERS } from '../utils/transformers';
const JsonViewModal = ({ open, onClose, jsonData, eventType }) => {
const [extractedInfo, setExtractedInfo] = useState();
const [activeTab, setActiveTab] = useState(1);
const handleTabChange = (event, newValue) => {
setActiveTab(newValue);
};
useEffect(() => {
if (!open) {
setExtractedInfo(undefined);
setActiveTab(1);
}
}, [open]);
useEffect(() => {
if (!open) return;
extractInfo(jsonData, eventType).then((data) => {
setExtractedInfo(data);
});
}, [jsonData, eventType, open]);
// Основная универсальная функция
async function extractInfo(data, type) {
data = JSON.parse(data);
const config = EVENT_CONFIGS[type] || {};
const configForMultDependents = EVENT_CONFIGS_MULT_DEPENDENTS[type] || {};
const result = {};
// Функция для рекурсивного обхода всех узлов
async function traverseAndExtract(obj, path = '') {
if (!obj || typeof obj !== 'object') return;
for (const key in obj) {
const currentPath = path ? `${path}.${key}` : key;
if (config[currentPath] || config[key]) {
let value = obj[key];
const configKey = config[currentPath] || config[key];
// Применяем преобразование, если есть функция для этого ключа
if (VALUE_TRANSFORMERS[configKey] && value !== null && value !== undefined) {
try {
// Собираем зависимости для трансформера
// По умолчанию передаём только текущее значение
const dependents = [value];
// Если для этого ключа есть дополнительные зависимости (другие поля)
if (configForMultDependents[configKey] || configForMultDependents[configKey]) {
configForMultDependents[configKey].forEach((d) => {
// Добавляем значения из зависимых полей (в корне data)
dependents.push(data[d]);
});
}
const transformer = VALUE_TRANSFORMERS[configKey];
if (transformer.constructor.name === 'AsyncFunction') {
value = await transformer(...dependents);
} else {
value = transformer(...dependents);
}
} catch (error) {
console.error(`Ошибка в трансформере для ключа "${configKey}":`, error);
value = '—';
}
}
result[configKey] = value ?? '—';
}
// Если значение - объект или массив, рекурсивно обходим его
if (obj[key] && typeof obj[key] === 'object') {
await traverseAndExtract(obj[key], currentPath);
}
}
}
try {
await traverseAndExtract(data);
} catch (error) {
return JSON.stringify({ error: 'Ошибка при извлечении данных' }, null, 2);
}
return JSON.stringify(result, null, 2);
}
if (!open) return null;
return (
<Modal
open={open}
onClose={onClose}
aria-labelledby='json-view-modal'
aria-describedby='json-details-modal'
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}>
<Box
sx={{
border: '1px solid #e5e7eb',
borderRadius: '0.63rem',
padding: '1.06rem 1.06rem 0.06rem',
width: 'max-content',
bgcolor: 'background.paper',
outline: 'none',
position: 'relative',
}}>
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
mb: '.75rem',
}}>
<Typography variant='subtitle1' sx={{ fontWeight: 'medium' }}>
Детали события:
</Typography>
</Box>
{/* Вкладки */}
<Tabs
value={activeTab}
onChange={handleTabChange}
sx={{
borderBottom: '1px solid #e5e7eb',
mb: '1rem',
'& .MuiTab-root': {
textTransform: 'none',
fontSize: '0.875rem',
},
}}>
<Tab label='Данные события' />
<Tab label='Форматированные данные события' />
</Tabs>
<Box
sx={{
maxHeight: '300px',
overflow: 'auto',
mb: '1rem',
backgroundColor: '#F9FAFB',
border: '1px solid #e5e7eb',
padding: '0.8rem',
borderRadius: '0.25rem',
}}>
{activeTab === 0 ? (
<Typography
variant='body2'
component='pre'
sx={{
fontFamily: 'monospace',
fontSize: '0.75rem',
whiteSpace: 'pre-wrap',
m: 0,
lineHeight: 1.4,
}}>
{jsonData}
</Typography>
) : (
<Box
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}>
<Typography
variant='body2'
component='pre'
sx={{
fontFamily: 'monospace',
fontSize: '0.75rem',
whiteSpace: 'pre-wrap',
m: 0,
lineHeight: 1.4,
}}>
{extractedInfo || <CircularProgress />}
</Typography>
</Box>
)}
</Box>
</Box>
</Modal>
);
};
export default JsonViewModal;