Compare commits
No commits in common. "3a142185a293432942a0973f45092b484e3ea831" and "7400e77fa060fc5be7e8a483612a6fc989fc51df" have entirely different histories.
3a142185a2
...
7400e77fa0
|
|
@ -1,206 +0,0 @@
|
||||||
// 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 (
|
|
||||||
<Box>
|
|
||||||
{/* Текущий состав лицензии */}
|
|
||||||
<StyledPaper elevation={0}>
|
|
||||||
<Typography variant="h6" gutterBottom sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
|
||||||
<VpnKeyIcon color="primary" />
|
|
||||||
Текущий состав лицензии
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
<List>
|
|
||||||
{licenseFeatures.map((feature, index) => {
|
|
||||||
const IconComponent = feature.icon;
|
|
||||||
return (
|
|
||||||
<React.Fragment key={feature.name}>
|
|
||||||
<ListItem>
|
|
||||||
<ListItemIcon>
|
|
||||||
<IconComponent color={feature.active ? "primary" : "disabled"} />
|
|
||||||
</ListItemIcon>
|
|
||||||
<ListItemText
|
|
||||||
primary={
|
|
||||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
|
||||||
<Typography variant="body1">{feature.name}</Typography>
|
|
||||||
{feature.value && (
|
|
||||||
<Chip
|
|
||||||
label={feature.value}
|
|
||||||
size="small"
|
|
||||||
color={feature.active ? "success" : "default"}
|
|
||||||
variant="outlined"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
secondary={feature.description}
|
|
||||||
/>
|
|
||||||
<ListItemIcon>
|
|
||||||
{feature.active ? (
|
|
||||||
<CheckCircleIcon color="success" />
|
|
||||||
) : (
|
|
||||||
<CancelIcon color="error" />
|
|
||||||
)}
|
|
||||||
</ListItemIcon>
|
|
||||||
</ListItem>
|
|
||||||
{index < licenseFeatures.length - 1 && <Divider variant="inset" component="li" />}
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</List>
|
|
||||||
</StyledPaper>
|
|
||||||
|
|
||||||
{/* Идентификатор лицензии */}
|
|
||||||
<StyledPaper elevation={0}>
|
|
||||||
<Grid container spacing={2} alignItems="center">
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Typography variant="h6" gutterBottom>
|
|
||||||
Идентификатор лицензии
|
|
||||||
</Typography>
|
|
||||||
<Typography variant="body2" color="textSecondary" paragraph>
|
|
||||||
Этот ключ используется для активации и обновления лицензии
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<LicenseKeyBox>
|
|
||||||
<Typography variant="body1" sx={{ fontFamily: 'monospace' }}>
|
|
||||||
{licenseKey}
|
|
||||||
</Typography>
|
|
||||||
<Box>
|
|
||||||
<IconButton onClick={handleCopyKey} size="small" title="Копировать">
|
|
||||||
<ContentCopyIcon />
|
|
||||||
</IconButton>
|
|
||||||
</Box>
|
|
||||||
</LicenseKeyBox>
|
|
||||||
{showCopySuccess && (
|
|
||||||
<Alert severity="success" sx={{ mt: 1 }}>Ключ скопирован в буфер обмена</Alert>
|
|
||||||
)}
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Box sx={{ display: 'flex', justifyContent: 'flex-end', mt: 2 }}>
|
|
||||||
<Button
|
|
||||||
variant="contained"
|
|
||||||
color="primary"
|
|
||||||
//onClick={handleRefreshLicense}
|
|
||||||
//startIcon={<RefreshIcon />}
|
|
||||||
>
|
|
||||||
Обновить лицензию
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</StyledPaper>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Licensing;
|
|
||||||
|
|
@ -23,7 +23,6 @@ import MetricRangeEditor from './SettingsComponents/MetricRangeEditor';
|
||||||
import UserManagement from './SettingsComponents/UserManagement';
|
import UserManagement from './SettingsComponents/UserManagement';
|
||||||
import MenuEditor from './SettingsComponents/MenuEditor';
|
import MenuEditor from './SettingsComponents/MenuEditor';
|
||||||
import FormulaEditor from './SettingsComponents/FormulaEditor';
|
import FormulaEditor from './SettingsComponents/FormulaEditor';
|
||||||
import Licensing from './SettingsComponents/Licensing';
|
|
||||||
|
|
||||||
const Transition = React.forwardRef(function Transition(props, ref) {
|
const Transition = React.forwardRef(function Transition(props, ref) {
|
||||||
return <Slide direction="up" ref={ref} {...props} />;
|
return <Slide direction="up" ref={ref} {...props} />;
|
||||||
|
|
@ -75,10 +74,6 @@ const SettingsModal = ({ open, onClose, onMenuUpdate }) => {
|
||||||
hasChanges: false,
|
hasChanges: false,
|
||||||
save: () => Promise.resolve(true)
|
save: () => Promise.resolve(true)
|
||||||
});
|
});
|
||||||
const [licensingState, setLicensingState] = useState({
|
|
||||||
hasChanges: false,
|
|
||||||
save: () => Promise.resolve(true)
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleTabChange = (event, newValue) => {
|
const handleTabChange = (event, newValue) => {
|
||||||
if (hasChanges) {
|
if (hasChanges) {
|
||||||
|
|
@ -110,10 +105,6 @@ const SettingsModal = ({ open, onClose, onMenuUpdate }) => {
|
||||||
success = success && await formulaEditorState.save();
|
success = success && await formulaEditorState.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tabValue === 4 && licensingState.hasChanges) {
|
|
||||||
success = success && await licensingState.save();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
setShowSuccess(true);
|
setShowSuccess(true);
|
||||||
setHasChanges(false);
|
setHasChanges(false);
|
||||||
|
|
@ -136,11 +127,6 @@ const SettingsModal = ({ open, onClose, onMenuUpdate }) => {
|
||||||
setHasChanges(hasChanges);
|
setHasChanges(hasChanges);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleLicensingChange = ({ hasChanges, saveChanges }) => {
|
|
||||||
setLicensingState({ hasChanges, save: saveChanges });
|
|
||||||
setHasChanges(hasChanges);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
if (hasChanges) {
|
if (hasChanges) {
|
||||||
setShowConfirmClose(true);
|
setShowConfirmClose(true);
|
||||||
|
|
@ -192,7 +178,6 @@ const SettingsModal = ({ open, onClose, onMenuUpdate }) => {
|
||||||
<Tab label="Границы метрик" id="settings-tab-1" aria-controls="settings-tabpanel-1" />
|
<Tab label="Границы метрик" id="settings-tab-1" aria-controls="settings-tabpanel-1" />
|
||||||
<Tab label="Управление пользователями" id="settings-tab-2" aria-controls="settings-tabpanel-2" />
|
<Tab label="Управление пользователями" id="settings-tab-2" aria-controls="settings-tabpanel-2" />
|
||||||
<Tab label="Настройка формул" id="settings-tab-3" aria-controls="settings-tabpanel-3" />
|
<Tab label="Настройка формул" id="settings-tab-3" aria-controls="settings-tabpanel-3" />
|
||||||
<Tab label="Лицензирование" id="settings-tab-4" aria-controls="settings-tabpanel-4" />
|
|
||||||
{/* Добавить новые вкладки здесь */}
|
{/* Добавить новые вкладки здесь */}
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
@ -214,10 +199,6 @@ const SettingsModal = ({ open, onClose, onMenuUpdate }) => {
|
||||||
<FormulaEditor onSave={handleFormulaEditorChange} />
|
<FormulaEditor onSave={handleFormulaEditorChange} />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
|
|
||||||
<TabPanel value={tabValue} index={4}>
|
|
||||||
<Licensing onSave={handleLicensingChange} />
|
|
||||||
</TabPanel>
|
|
||||||
|
|
||||||
{/* Добавляйте новые TabPanel для новых вкладок */}
|
{/* Добавляйте новые TabPanel для новых вкладок */}
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue