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 для новых вкладок */}