Fix jwt-token
This commit is contained in:
218
management/src/components/DataRetentionMetrics.jsx
Normal file
218
management/src/components/DataRetentionMetrics.jsx
Normal file
@@ -0,0 +1,218 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import api from '../services/api'
|
||||
import {
|
||||
TrashIcon,
|
||||
ServerIcon,
|
||||
ChartBarIcon,
|
||||
ClockIcon,
|
||||
ExclamationTriangleIcon,
|
||||
CheckCircleIcon
|
||||
} from '@heroicons/react/24/outline'
|
||||
|
||||
const DataRetentionMetrics = () => {
|
||||
const [metrics, setMetrics] = useState(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState(null)
|
||||
const [lastUpdate, setLastUpdate] = useState(null)
|
||||
|
||||
useEffect(() => {
|
||||
loadDataRetentionMetrics()
|
||||
// Auto-refresh every 30 seconds
|
||||
const interval = setInterval(loadDataRetentionMetrics, 30000)
|
||||
return () => clearInterval(interval)
|
||||
}, [])
|
||||
|
||||
const loadDataRetentionMetrics = async () => {
|
||||
try {
|
||||
setError(null)
|
||||
const response = await api.get('/data-retention/status')
|
||||
setMetrics(response.data)
|
||||
setLastUpdate(new Date())
|
||||
} catch (error) {
|
||||
console.error('Error loading data retention metrics:', error)
|
||||
setError(error.response?.data?.message || 'Failed to load data retention metrics')
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
const formatUptime = (seconds) => {
|
||||
if (!seconds) return 'Unknown'
|
||||
const days = Math.floor(seconds / 86400)
|
||||
const hours = Math.floor((seconds % 86400) / 3600)
|
||||
const minutes = Math.floor((seconds % 3600) / 60)
|
||||
|
||||
if (days > 0) return `${days}d ${hours}h ${minutes}m`
|
||||
if (hours > 0) return `${hours}h ${minutes}m`
|
||||
return `${minutes}m`
|
||||
}
|
||||
|
||||
const formatMemory = (mb) => {
|
||||
if (!mb) return 'Unknown'
|
||||
if (mb > 1024) return `${(mb / 1024).toFixed(1)} GB`
|
||||
return `${mb} MB`
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="bg-white rounded-lg shadow p-6">
|
||||
<div className="flex items-center mb-4">
|
||||
<TrashIcon className="h-6 w-6 text-purple-600 mr-2" />
|
||||
<h3 className="text-lg font-semibold text-gray-900">Data Retention Service</h3>
|
||||
</div>
|
||||
<div className="animate-pulse">
|
||||
<div className="h-4 bg-gray-200 rounded w-3/4 mb-2"></div>
|
||||
<div className="h-4 bg-gray-200 rounded w-1/2"></div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className="bg-white rounded-lg shadow p-6">
|
||||
<div className="flex items-center mb-4">
|
||||
<TrashIcon className="h-6 w-6 text-purple-600 mr-2" />
|
||||
<h3 className="text-lg font-semibold text-gray-900">Data Retention Service</h3>
|
||||
<ExclamationTriangleIcon className="h-5 w-5 text-red-500 ml-2" />
|
||||
</div>
|
||||
<div className="bg-red-50 border border-red-200 rounded-md p-4">
|
||||
<div className="flex">
|
||||
<ExclamationTriangleIcon className="h-5 w-5 text-red-400 mr-2 flex-shrink-0 mt-0.5" />
|
||||
<div>
|
||||
<p className="text-sm text-red-700 font-medium">Service Unavailable</p>
|
||||
<p className="text-sm text-red-600 mt-1">{error}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={loadDataRetentionMetrics}
|
||||
className="mt-4 px-4 py-2 bg-red-100 text-red-700 rounded-md hover:bg-red-200 transition-colors text-sm"
|
||||
>
|
||||
Retry Connection
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const isConnected = metrics?.service?.connected
|
||||
const serviceHealth = metrics?.health
|
||||
const serviceMetrics = metrics?.metrics
|
||||
|
||||
return (
|
||||
<div className="bg-white rounded-lg shadow p-6">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<div className="flex items-center">
|
||||
<TrashIcon className="h-6 w-6 text-purple-600 mr-2" />
|
||||
<h3 className="text-lg font-semibold text-gray-900">Data Retention Service</h3>
|
||||
{isConnected ? (
|
||||
<CheckCircleIcon className="h-5 w-5 text-green-500 ml-2" />
|
||||
) : (
|
||||
<ExclamationTriangleIcon className="h-5 w-5 text-red-500 ml-2" />
|
||||
)}
|
||||
</div>
|
||||
<div className="text-sm text-gray-500">
|
||||
{lastUpdate && `Updated ${lastUpdate.toLocaleTimeString()}`}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{isConnected ? (
|
||||
<div className="space-y-4">
|
||||
{/* Service Status */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<div className="bg-green-50 rounded-lg p-4">
|
||||
<div className="flex items-center">
|
||||
<CheckCircleIcon className="h-5 w-5 text-green-600 mr-2" />
|
||||
<div>
|
||||
<p className="text-sm font-medium text-green-800">Status</p>
|
||||
<p className="text-lg font-bold text-green-900">{serviceMetrics?.service?.status || 'Running'}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-blue-50 rounded-lg p-4">
|
||||
<div className="flex items-center">
|
||||
<ClockIcon className="h-5 w-5 text-blue-600 mr-2" />
|
||||
<div>
|
||||
<p className="text-sm font-medium text-blue-800">Uptime</p>
|
||||
<p className="text-lg font-bold text-blue-900">
|
||||
{formatUptime(serviceMetrics?.service?.uptime || serviceHealth?.uptime)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-purple-50 rounded-lg p-4">
|
||||
<div className="flex items-center">
|
||||
<ServerIcon className="h-5 w-5 text-purple-600 mr-2" />
|
||||
<div>
|
||||
<p className="text-sm font-medium text-purple-800">Memory</p>
|
||||
<p className="text-lg font-bold text-purple-900">
|
||||
{formatMemory(serviceMetrics?.performance?.memoryUsage?.heapUsed)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Cleanup Information */}
|
||||
{serviceMetrics?.cleanup && (
|
||||
<div className="border-t pt-4">
|
||||
<h4 className="font-medium text-gray-900 mb-3">Cleanup Operations</h4>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">Last Cleanup</p>
|
||||
<p className="font-medium">
|
||||
{serviceMetrics.cleanup.lastRunFormatted || 'Never'}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">Next Scheduled</p>
|
||||
<p className="font-medium">{serviceMetrics.cleanup.nextScheduledRun || '2:00 AM UTC daily'}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{serviceMetrics.cleanup.stats && (
|
||||
<div className="mt-3">
|
||||
<p className="text-sm text-gray-600 mb-2">Last Cleanup Stats</p>
|
||||
<div className="flex flex-wrap gap-4 text-sm">
|
||||
<span className="bg-gray-100 px-2 py-1 rounded">
|
||||
Detections: {serviceMetrics.cleanup.stats.totalDetections || 0}
|
||||
</span>
|
||||
<span className="bg-gray-100 px-2 py-1 rounded">
|
||||
Heartbeats: {serviceMetrics.cleanup.stats.totalHeartbeats || 0}
|
||||
</span>
|
||||
<span className="bg-gray-100 px-2 py-1 rounded">
|
||||
Logs: {serviceMetrics.cleanup.stats.totalLogs || 0}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Schedule Information */}
|
||||
{serviceMetrics?.schedule && (
|
||||
<div className="border-t pt-4">
|
||||
<h4 className="font-medium text-gray-900 mb-2">Schedule</h4>
|
||||
<p className="text-sm text-gray-600">{serviceMetrics.schedule.description}</p>
|
||||
<p className="text-xs text-gray-500 mt-1">
|
||||
Cron: {serviceMetrics.schedule.cronExpression} ({serviceMetrics.schedule.timezone})
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-center py-8">
|
||||
<ExclamationTriangleIcon className="h-12 w-12 text-red-400 mx-auto mb-4" />
|
||||
<p className="text-gray-600">Data retention service is not connected</p>
|
||||
<p className="text-sm text-gray-500 mt-1">
|
||||
{metrics?.service?.error || 'Service health check failed'}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default DataRetentionMetrics
|
||||
@@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react'
|
||||
import api from '../services/api'
|
||||
import { t } from '../utils/tempTranslations' // Temporary translation system
|
||||
import { BuildingOfficeIcon, UsersIcon, ServerIcon, ChartBarIcon } from '@heroicons/react/24/outline'
|
||||
import DataRetentionMetrics from '../components/DataRetentionMetrics'
|
||||
|
||||
const Dashboard = () => {
|
||||
const [stats, setStats] = useState({
|
||||
@@ -96,8 +97,8 @@ const Dashboard = () => {
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Quick Actions */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||
{/* Quick Actions and Data Retention */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
|
||||
<div className="bg-white rounded-lg shadow p-6">
|
||||
<h3 className="text-lg font-semibold text-gray-900 mb-4">Quick Actions</h3>
|
||||
<div className="space-y-3">
|
||||
@@ -142,6 +143,9 @@ const Dashboard = () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Data Retention Service Metrics */}
|
||||
<DataRetentionMetrics />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user