diff --git a/src/Components/Layout/SettingsComponents/FormulaEditor.jsx b/src/Components/Layout/SettingsComponents/FormulaEditor.jsx
new file mode 100644
index 0000000..206a843
--- /dev/null
+++ b/src/Components/Layout/SettingsComponents/FormulaEditor.jsx
@@ -0,0 +1,482 @@
+import React, { useState, useEffect, useCallback } from 'react';
+import {
+ TextField, Box, Typography, IconButton, Divider,
+ CircularProgress, Alert, Collapse, Tooltip, Button,
+ Card, CardContent, Chip, Dialog, DialogTitle,
+ DialogContent, DialogActions, Snackbar
+} from '@mui/material';
+import RefreshIcon from '@mui/icons-material/Refresh';
+import SearchIcon from '@mui/icons-material/Search';
+import EditIcon from '@mui/icons-material/Edit';
+import SaveIcon from '@mui/icons-material/Save';
+import axios from 'axios';
+
+const FormulaItem = React.memo(({ data, onEdit }) => {
+ const formatValue = (value) => {
+ if (typeof value === 'object' && value !== null) {
+ return JSON.stringify(value, null, 2);
+ }
+ return String(value);
+ };
+
+ const getValueColor = (value) => {
+ if (typeof value === 'boolean') return 'primary';
+ if (typeof value === 'number') return 'secondary';
+ if (value === null) return 'default';
+ return 'info';
+ };
+
+ return (
+
+
+
+
+ ID: {data.id || 'Без ID'}
+
+ }
+ onClick={() => onEdit(data)}
+ variant="outlined"
+ size="small"
+ >
+ Редактировать
+
+
+
+
+ {data.data.name}
+
+
+
+ {data.data.desription}
+
+
+
+
+ Параметры:
+
+
+
+
+
+ {JSON.stringify(data.data.values?.statusarr, null, 2)}
+
+
+
+
+
+
+ {JSON.stringify(data.data.values?.warr, null, 2)}
+
+
+
+
+
+
+ {data.data.formula}
+
+
+
+
+
+
+
+
+
+
+ );
+});
+
+const EditFormulaDialog = ({ open, formula, onClose, onSave }) => {
+ const [editedFormula, setEditedFormula] = useState('');
+
+ useEffect(() => {
+ if (formula) {
+ setEditedFormula(formula.data.formula || '');
+ }
+ }, [formula]);
+
+ const handleSave = () => {
+ if (formula && editedFormula.trim()) {
+ onSave(formula.id, editedFormula.trim());
+ }
+ };
+
+ return (
+
+ );
+};
+
+const FormulaEditor = () => {
+ const [formulas, setFormulas] = useState([]);
+ const [filter, setFilter] = useState('');
+ const [formulaId, setFormulaId] = useState('');
+ const [loading, setLoading] = useState(false);
+ const [error, setError] = useState(null);
+ const [refreshing, setRefreshing] = useState(false);
+ const [editingFormula, setEditingFormula] = useState(null);
+ const [saveLoading, setSaveLoading] = useState(false);
+ const [snackbar, setSnackbar] = useState({ open: false, message: '', severity: 'success' });
+
+ const showSnackbar = (message, severity = 'success') => {
+ setSnackbar({ open: true, message, severity });
+ };
+
+ const loadFormulas = useCallback(async (id = null) => {
+ try {
+ setLoading(true);
+ setError(null);
+
+ const targetId = id || formulaId;
+ const res = await axios.get(`http://192.168.2.39:3000/api/formula/7777/options`);
+
+ console.log('Полученные данные:', res.data);
+
+ let formattedData;
+
+ if (Array.isArray(res.data)) {
+ formattedData = res.data.map((item, index) => ({
+ id: item.id || `formula_${index + 1}`,
+ data: item
+ }));
+ } else if (typeof res.data === 'object' && res.data !== null) {
+ formattedData = [{
+ id: targetId,
+ data: res.data
+ }];
+ } else {
+ formattedData = [{
+ id: targetId,
+ data: { value: res.data }
+ }];
+ }
+
+ console.log('Форматированные данные:', formattedData);
+ setFormulas(formattedData);
+
+ } catch (err) {
+ console.error('Ошибка при загрузке формул:', err);
+ setError(`Ошибка загрузки: ${err.message}`);
+ } finally {
+ setLoading(false);
+ setRefreshing(false);
+ }
+ }, [formulaId]);
+
+ const handleEditFormula = (formula) => {
+ setEditingFormula(formula);
+ };
+
+ const handleSaveFormula = async (formulaId, newFormula) => {
+ try {
+ setSaveLoading(true);
+
+ // Обновляем формулу в локальном состоянии
+ const updatedFormulas = formulas.map(formula =>
+ formula.id === formulaId
+ ? { ...formula, data: { ...formula.data, formula: newFormula } }
+ : formula
+ );
+
+ setFormulas(updatedFormulas);
+ setEditingFormula(null);
+
+ showSnackbar('Формула успешно обновлена!');
+
+ } catch (err) {
+ console.error('Ошибка при сохранении формулы:', err);
+ showSnackbar('Ошибка при сохранении формулы', 'error');
+ } finally {
+ setSaveLoading(false);
+ }
+ };
+
+ const handleSendAllFormulas = async () => {
+ try {
+ setSaveLoading(true);
+
+ // Преобразуем данные обратно в исходный формат для отправки
+ const dataToSend = formulas.map(formula => ({
+ id: formula.data.id,
+ name: formula.data.name,
+ desription: formula.data.desription,
+ values: formula.data.values,
+ formula: formula.data.formula
+ }));
+
+ console.log('Отправляемые данные:', dataToSend);
+
+ const response = await axios.post(
+ 'http://192.168.2.39:9999/api/integration/3333',
+ dataToSend,
+ {
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ }
+ );
+
+ console.log('Ответ сервера:', response.data);
+ showSnackbar('Данные успешно отправлены на сервер!');
+
+ } catch (err) {
+ console.error('Ошибка при отправке данных:', err);
+ showSnackbar(`Ошибка отправки: ${err.message}`, 'error');
+ } finally {
+ setSaveLoading(false);
+ }
+ };
+
+ const refreshData = useCallback(() => {
+ setRefreshing(true);
+ loadFormulas();
+ }, [loadFormulas]);
+
+ const handleFormulaIdChange = (e) => {
+ setFormulaId(e.target.value);
+ };
+
+ const handleLoadClick = () => {
+ if (formulaId.trim()) {
+ loadFormulas(formulaId);
+ }
+ };
+
+ const filteredFormulas = formulas.filter(formula =>
+ formula.id.toLowerCase().includes(filter.toLowerCase()) ||
+ JSON.stringify(formula.data).toLowerCase().includes(filter.toLowerCase())
+ );
+
+ useEffect(() => {
+ loadFormulas();
+ }, []);
+
+ return (
+
+ {/* Загрузка */}
+ {(loading || refreshing) && (
+
+
+
+ )}
+
+ {/* Ошибки */}
+
+
+ Повторить
+
+ }
+ >
+ {error}
+
+
+
+ {/* Панель управления */}
+
+
+
+ Редактор формул
+
+
+ }
+ disabled={formulas.length === 0 || saveLoading}
+ >
+ {saveLoading ? : 'Отправить все формулы'}
+
+
+
+
+
+ }
+ disabled={!formulaId.trim() || loading}
+ >
+ Загрузить
+
+
+
+
+
+ setFilter(e.target.value)}
+ variant="standard"
+ placeholder="Введите текст для поиска..."
+ />
+
+
+
+
+
+
+ {/* Список формул */}
+
+ {filteredFormulas.map((formula, index) => (
+
+ ))}
+
+ {filteredFormulas.length === 0 && !loading && (
+
+ {filter ? 'Формулы не найдены' : 'Загрузите формулы по ID'}
+
+ )}
+
+
+ {/* Статус бар */}
+
+
+ Всего формул: {formulas.length} • Отфильтровано: {filteredFormulas.length}
+
+ }
+ disabled={refreshing}
+ size="small"
+ >
+ Обновить
+
+
+
+ {/* Диалог редактирования */}
+ setEditingFormula(null)}
+ onSave={handleSaveFormula}
+ />
+
+ {/* Уведомления */}
+ setSnackbar({ ...snackbar, open: false })}
+ >
+ setSnackbar({ ...snackbar, open: false })}
+ severity={snackbar.severity}
+ >
+ {snackbar.message}
+
+
+
+ );
+};
+
+export default React.memo(FormulaEditor);
\ No newline at end of file
diff --git a/src/Components/Layout/SettingsModal.jsx b/src/Components/Layout/SettingsModal.jsx
index f52cf56..c8ec7a6 100644
--- a/src/Components/Layout/SettingsModal.jsx
+++ b/src/Components/Layout/SettingsModal.jsx
@@ -21,7 +21,8 @@ import CloseIcon from '@mui/icons-material/Close';
import SaveIcon from '@mui/icons-material/Save';
import MetricRangeEditor from './SettingsComponents/MetricRangeEditor';
import UserManagement from './SettingsComponents/UserManagement';
-import MenuEditor from './SettingsComponents/MenuEditor'
+import MenuEditor from './SettingsComponents/MenuEditor';
+import FormulaEditor from './SettingsComponents/FormulaEditor';
const Transition = React.forwardRef(function Transition(props, ref) {
return ;
@@ -69,6 +70,10 @@ const SettingsModal = ({ open, onClose, onMenuUpdate }) => {
hasChanges: false,
save: () => Promise.resolve(true)
});
+ const [formulaEditorState, setFormulaEditorState] = useState({
+ hasChanges: false,
+ save: () => Promise.resolve(true)
+ });
const handleTabChange = (event, newValue) => {
if (hasChanges) {
@@ -96,6 +101,10 @@ const SettingsModal = ({ open, onClose, onMenuUpdate }) => {
success = success && await metricEditorState.save();
}
+ if (tabValue === 3 && formulaEditorState.hasChanges) {
+ success = success && await formulaEditorState.save();
+ }
+
if (success) {
setShowSuccess(true);
setHasChanges(false);
@@ -113,6 +122,11 @@ const SettingsModal = ({ open, onClose, onMenuUpdate }) => {
setHasChanges(hasChanges);
};
+ const handleFormulaEditorChange = ({ hasChanges, saveChanges }) => {
+ setFormulaEditorState({ hasChanges, save: saveChanges });
+ setHasChanges(hasChanges);
+ };
+
const handleClose = () => {
if (hasChanges) {
setShowConfirmClose(true);
@@ -163,6 +177,7 @@ const SettingsModal = ({ open, onClose, onMenuUpdate }) => {
+
{/* Добавить новые вкладки здесь */}
@@ -180,6 +195,10 @@ const SettingsModal = ({ open, onClose, onMenuUpdate }) => {
+
+
+
+
{/* Добавляйте новые TabPanel для новых вкладок */}