import React, { useState, useEffect } from 'react'
import api from '../services/api'
import toast from 'react-hot-toast'
import {
CogIcon,
ServerIcon,
CircleStackIcon,
ShieldCheckIcon,
ClockIcon,
CpuChipIcon,
ChartBarIcon,
ExclamationTriangleIcon,
CheckCircleIcon,
XCircleIcon
} from '@heroicons/react/24/outline'
const System = () => {
const [systemInfo, setSystemInfo] = useState(null)
const [loading, setLoading] = useState(true)
const [lastUpdate, setLastUpdate] = useState(null)
useEffect(() => {
loadSystemInfo()
const interval = setInterval(loadSystemInfo, 30000) // Update every 30 seconds
return () => clearInterval(interval)
}, [])
const loadSystemInfo = async () => {
try {
if (!loading) setLoading(false) // Don't show loading for refreshes
const response = await api.get('/management/system-info')
setSystemInfo(response.data.data)
setLastUpdate(new Date())
} catch (error) {
console.error('Failed to load system info:', error)
toast.error('Failed to load system information')
} finally {
setLoading(false)
}
}
const StatusCard = ({ title, icon: Icon, children, status = 'normal' }) => {
const statusColors = {
normal: 'border-gray-200',
warning: 'border-yellow-300 bg-yellow-50',
critical: 'border-red-300 bg-red-50',
success: 'border-green-300 bg-green-50'
}
return (
)
}
const StatusIndicator = ({ status, label }) => {
const configs = {
valid: { color: 'bg-green-100 text-green-800', icon: CheckCircleIcon },
warning: { color: 'bg-yellow-100 text-yellow-800', icon: ExclamationTriangleIcon },
critical: { color: 'bg-red-100 text-red-800', icon: XCircleIcon },
error: { color: 'bg-red-100 text-red-800', icon: XCircleIcon },
connected: { color: 'bg-green-100 text-green-800', icon: CheckCircleIcon }
}
const config = configs[status] || configs.error
const Icon = config.icon
return (
{label || status.charAt(0).toUpperCase() + status.slice(1)}
)
}
const ProgressBar = ({ percentage, color = 'blue' }) => {
const colorClasses = {
blue: 'bg-blue-600',
green: 'bg-green-600',
yellow: 'bg-yellow-600',
red: 'bg-red-600'
}
const barColor = percentage > 80 ? 'red' : percentage > 60 ? 'yellow' : 'green'
return (
)
}
const ContainerCard = ({ name, metrics }) => {
const getTypeIcon = (type) => {
switch (type) {
case 'database': return '🗄️';
case 'cache': return '⚡';
case 'proxy': return '🌐';
case 'application': return '📱';
case 'app': return '📱';
case 'logging': return '📋';
case 'monitoring': return '📊';
default: return '📦';
}
};
const getTypeColor = (type) => {
switch (type) {
case 'database': return 'border-l-blue-500';
case 'cache': return 'border-l-yellow-500';
case 'proxy': return 'border-l-green-500';
case 'application': case 'app': return 'border-l-purple-500';
case 'logging': return 'border-l-orange-500';
case 'monitoring': return 'border-l-red-500';
default: return 'border-l-gray-500';
}
};
const getStatusColor = (status) => {
switch (status) {
case 'healthy': case 'responding': return 'text-green-600';
case 'timeout': case 'warning': return 'text-yellow-600';
case 'unreachable': case 'error': case 'health_check_failed': return 'text-red-600';
case 'running': case 'Up': return 'text-green-600';
default: return 'text-gray-600';
}
};
const getStatusIcon = (status) => {
switch (status) {
case 'healthy': case 'responding': return '✅';
case 'timeout': return '⏱️';
case 'unreachable': case 'error': return '❌';
case 'running': case 'Up': return '🟢';
default: return '⚪';
}
};
return (
{getTypeIcon(metrics.type)}
{name.replace('drone-detection-', '').replace('uamils-', '')}
{metrics.type && (
{metrics.type}
)}
Status
{getStatusIcon(metrics.status)}
{metrics.status === 'health_check_failed' ? 'Failed' :
metrics.status.charAt(0).toUpperCase() + metrics.status.slice(1)}
{metrics.error && (
Error Details:
{metrics.error}
)}
{metrics.raw && metrics.status === 'healthy' && (
Response: {metrics.raw.trim()}
)}
{/* Show resource metrics if available */}
{metrics.cpu && (
<>
CPU
{metrics.cpu}
Memory
{metrics.memory?.percentage || metrics.memory}
Network I/O
{metrics.network}
Disk I/O
{metrics.disk}
>
)}
{metrics.health && metrics.health !== 'unknown' && (
Health
{metrics.health}
)}
{metrics.ports && (
Ports
{metrics.ports}
)}
{metrics.source && (
Source: {metrics.source.replace('_', ' ').toUpperCase()}
)}
);
};
const SSLCard = ({ domain, ssl }) => (
{domain}
Status
{ssl.expiresAt && (
<>
Expires
{new Date(ssl.expiresAt).toLocaleDateString()}
{ssl.daysUntilExpiry !== undefined && (
Days Left
{ssl.daysUntilExpiry}
)}
{ssl.issuer && (
Issuer: {ssl.issuer}
)}
{ssl.fingerprint && (
Fingerprint: {ssl.fingerprint.substring(0, 20)}...
)}
>
)}
{ssl.error && (
Error:
{ssl.error}
{ssl.errorCode && (
Code: {ssl.errorCode}
)}
)}
)
if (loading) {
return (
)
}
if (!systemInfo) {
return (
No system information available
Unable to load system metrics.
)
}
return (
System Monitor
Real-time system health and configuration monitoring
{lastUpdate && (
Last updated: {lastUpdate.toLocaleTimeString()}
)}
{/* Platform Overview */}
Version
{systemInfo.platform.version}
Environment
{systemInfo.platform.environment}
Uptime
{systemInfo.platform.uptime}
{/* Container Health Summary */}
Service Health
{Object.entries(systemInfo.containers).map(([name, metrics]) => {
const isHealthy = metrics.status === 'healthy' || metrics.status === 'responding';
return (
);
})}
{systemInfo.system.error ? (
System metrics unavailable
{systemInfo.system.message}
) : (
CPU Usage
{systemInfo.system.cpu.usage}
Memory
{systemInfo.system.memory.used} / {systemInfo.system.memory.total}
Disk
{systemInfo.system.disk}
)}
Tenants
{systemInfo.statistics.tenants}
Total Users
{systemInfo.statistics.total_users}
Access Level
{systemInfo.security.management_access_level}
{systemInfo.security.last_backup !== 'Not configured'
? new Date(systemInfo.security.last_backup).toLocaleDateString()
: 'Not configured'
}
{/* Container Metrics */}
{systemInfo.containers.error ? (
Container monitoring unavailable
{systemInfo.containers.lastError}
{systemInfo.containers.troubleshooting && (
💡 Troubleshooting Tips:
- • {systemInfo.containers.troubleshooting.docker_access}
- • {systemInfo.containers.troubleshooting.permissions}
- • {systemInfo.containers.troubleshooting.environment}
)}
{systemInfo.containers.suggestions && (
🔧 Quick Fixes:
{systemInfo.containers.suggestions.map((suggestion, index) => (
- • {suggestion}
))}
)}
) : systemInfo.containers.info ? (
{systemInfo.containers.info}
{systemInfo.containers.message}
) : (
{/* Group containers by type */}
{['application', 'database', 'cache', 'proxy', 'logging', 'monitoring', 'unknown'].map(type => {
const containersOfType = Object.entries(systemInfo.containers).filter(([name, metrics]) =>
metrics.type === type || (type === 'unknown' && !metrics.type)
);
if (containersOfType.length === 0) return null;
const typeLabels = {
application: '📱 Application Services',
database: '🗄️ Database Services',
cache: '⚡ Cache Services',
proxy: '🌐 Proxy & Load Balancers',
logging: '📋 Logging Services',
monitoring: '📊 Monitoring Services',
unknown: '📦 Other Services'
};
return (
{typeLabels[type]} ({containersOfType.length})
{containersOfType.map(([name, metrics]) => (
))}
);
})}
)}
{/* SSL Certificates */}
ssl.status === 'critical') ? 'critical' :
Object.values(systemInfo.ssl).some(ssl => ssl.status === 'warning') ? 'warning' : 'success'}
>
{Object.entries(systemInfo.ssl).map(([domain, ssl]) => (
))}
)
}
export default System