diff --git a/src/Components/Layout/SettingsComponents/Licensing.jsx b/src/Components/Layout/SettingsComponents/Licensing.jsx
new file mode 100644
index 0000000..2e31d87
--- /dev/null
+++ b/src/Components/Layout/SettingsComponents/Licensing.jsx
@@ -0,0 +1,206 @@
+// components/SettingsComponents/Licensing.jsx
+import React, { useState, useEffect } from 'react';
+import {
+ Box,
+ Paper,
+ Typography,
+ List,
+ ListItem,
+ ListItemIcon,
+ ListItemText,
+ Divider,
+ Chip,
+ Button,
+ TextField,
+ InputAdornment,
+ IconButton,
+ Alert,
+ Stack,
+ Grid
+} from '@mui/material';
+import {
+ CheckCircle as CheckCircleIcon,
+ Cancel as CancelIcon,
+ VpnKey as VpnKeyIcon,
+ Refresh as RefreshIcon,
+ Api as ApiIcon,
+ Devices as DevicesIcon,
+ Storage as StorageIcon,
+ Security as SecurityIcon,
+ ContentCopy as ContentCopyIcon
+} from '@mui/icons-material';
+import { styled } from '@mui/material/styles';
+
+const StyledPaper = styled(Paper)(({ theme }) => ({
+ padding: theme.spacing(3),
+ marginBottom: theme.spacing(3),
+ backgroundColor: theme.palette.background.default,
+}));
+
+const LicenseKeyBox = styled(Box)(({ theme }) => ({
+ backgroundColor: theme.palette.background.paper,
+ padding: theme.spacing(2),
+ borderRadius: theme.shape.borderRadius,
+ border: `1px solid ${theme.palette.divider}`,
+ fontFamily: 'monospace',
+ fontSize: '1.1rem',
+ letterSpacing: '0.5px',
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ marginTop: theme.spacing(2),
+}));
+
+const Licensing = ({ onSave }) => {
+ const [hasChanges, setHasChanges] = useState(false);
+ const [licenseKey, setLicenseKey] = useState('ABCDE-FGHIJ-KLMNO-PQRST-UVWXY');
+ const [showCopySuccess, setShowCopySuccess] = useState(false);
+
+ // Текущий состав лицензии (заглушка)
+ const licenseFeatures = [
+ { name: 'Модуль API', active: true, icon: ApiIcon, description: 'Полный доступ к API' },
+ { name: 'Подключение устройств', active: true, icon: DevicesIcon, value: '', description: '' },
+ { name: 'Модуль контроля параметров устойчивого функционирования компонентов, доверенного ПАК', active: true, icon: StorageIcon, value: '', description: '' },
+ //{ name: 'Расширенная безопасность', active: false, icon: SecurityIcon, description: '' },
+ ];
+
+ // Уведомляем родительский компонент об изменениях
+ useEffect(() => {
+ if (onSave) {
+ onSave({
+ hasChanges,
+ saveChanges: handleSave
+ });
+ }
+ }, [hasChanges]);
+
+ const handleSave = async () => {
+ // Здесь будет логика сохранения
+ console.log('Сохранение лицензионных настроек');
+ setHasChanges(false);
+ return true;
+ };
+
+ const handleRefreshLicense = () => {
+ // Заглушка для обновления лицензии
+ const newKey = generateLicenseKey();
+ setLicenseKey(newKey);
+ setHasChanges(true);
+ };
+
+ const generateLicenseKey = () => {
+ // Заглушка для генерации ключа
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
+ const segments = [];
+ for (let i = 0; i < 5; i++) {
+ let segment = '';
+ for (let j = 0; j < 5; j++) {
+ segment += chars[Math.floor(Math.random() * chars.length)];
+ }
+ segments.push(segment);
+ }
+ return segments.join('-');
+ };
+
+ const handleCopyKey = () => {
+ navigator.clipboard.writeText(licenseKey);
+ setShowCopySuccess(true);
+ setTimeout(() => setShowCopySuccess(false), 2000);
+ };
+
+ return (
+
+ {/* Текущий состав лицензии */}
+
+
+
+ Текущий состав лицензии
+
+
+
+ {licenseFeatures.map((feature, index) => {
+ const IconComponent = feature.icon;
+ return (
+
+
+
+
+
+
+ {feature.name}
+ {feature.value && (
+
+ )}
+
+ }
+ secondary={feature.description}
+ />
+
+ {feature.active ? (
+
+ ) : (
+
+ )}
+
+
+ {index < licenseFeatures.length - 1 && }
+
+ );
+ })}
+
+
+
+ {/* Идентификатор лицензии */}
+
+
+
+
+ Идентификатор лицензии
+
+
+ Этот ключ используется для активации и обновления лицензии
+
+
+
+
+
+
+ {licenseKey}
+
+
+
+
+
+
+
+ {showCopySuccess && (
+ Ключ скопирован в буфер обмена
+ )}
+
+
+
+
+ }
+ >
+ Обновить лицензию
+
+
+
+
+
+
+ );
+};
+
+export default Licensing;
\ No newline at end of file
diff --git a/src/Components/Layout/SettingsModal.jsx b/src/Components/Layout/SettingsModal.jsx
index c8ec7a6..3a750f7 100644
--- a/src/Components/Layout/SettingsModal.jsx
+++ b/src/Components/Layout/SettingsModal.jsx
@@ -23,6 +23,7 @@ import MetricRangeEditor from './SettingsComponents/MetricRangeEditor';
import UserManagement from './SettingsComponents/UserManagement';
import MenuEditor from './SettingsComponents/MenuEditor';
import FormulaEditor from './SettingsComponents/FormulaEditor';
+import Licensing from './SettingsComponents/Licensing';
const Transition = React.forwardRef(function Transition(props, ref) {
return ;
@@ -74,6 +75,10 @@ const SettingsModal = ({ open, onClose, onMenuUpdate }) => {
hasChanges: false,
save: () => Promise.resolve(true)
});
+ const [licensingState, setLicensingState] = useState({
+ hasChanges: false,
+ save: () => Promise.resolve(true)
+ });
const handleTabChange = (event, newValue) => {
if (hasChanges) {
@@ -105,6 +110,10 @@ const SettingsModal = ({ open, onClose, onMenuUpdate }) => {
success = success && await formulaEditorState.save();
}
+ if (tabValue === 4 && licensingState.hasChanges) {
+ success = success && await licensingState.save();
+ }
+
if (success) {
setShowSuccess(true);
setHasChanges(false);
@@ -127,6 +136,11 @@ const SettingsModal = ({ open, onClose, onMenuUpdate }) => {
setHasChanges(hasChanges);
};
+ const handleLicensingChange = ({ hasChanges, saveChanges }) => {
+ setLicensingState({ hasChanges, save: saveChanges });
+ setHasChanges(hasChanges);
+ };
+
const handleClose = () => {
if (hasChanges) {
setShowConfirmClose(true);
@@ -178,6 +192,7 @@ const SettingsModal = ({ open, onClose, onMenuUpdate }) => {
+
{/* Добавить новые вкладки здесь */}
@@ -199,6 +214,10 @@ const SettingsModal = ({ open, onClose, onMenuUpdate }) => {
+
+
+
+
{/* Добавляйте новые TabPanel для новых вкладок */}