Remove mcp-gateway/dashboard/dashboard.html
This commit is contained in:
parent
7689aeb7d8
commit
9427f3e4da
1 changed files with 0 additions and 238 deletions
|
|
@ -1,238 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>MCP Gateway Dashboard</title>
|
||||
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
|
||||
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script src="https://unpkg.com/@tabler/icons@latest"></script>
|
||||
<style>
|
||||
body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif; }
|
||||
.animate-spin { animation: spin 1s linear infinite; }
|
||||
@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script>
|
||||
// Lucide React Icons (simplified versions)
|
||||
const CheckCircle = ({ className = '' }) => (
|
||||
<svg className={className} fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
const AlertCircle = ({ className = '' }) => (
|
||||
<svg className={className} fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
const RotateCcw = ({ className = '' }) => (
|
||||
<svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
const Clock = ({ className = '' }) => (
|
||||
<svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4l3 2m6-2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
const Zap = ({ className = '' }) => (
|
||||
<svg className={className} fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
// Dashboard Component
|
||||
const Dashboard = () => {
|
||||
const [services, setServices] = React.useState([]);
|
||||
const [loading, setLoading] = React.useState(true);
|
||||
const [error, setError] = React.useState(null);
|
||||
const [lastUpdated, setLastUpdated] = React.useState(null);
|
||||
|
||||
const fetchServiceStatus = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const response = await fetch('/mcp/status');
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch service status');
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
setServices(data.services || []);
|
||||
setLastUpdated(new Date());
|
||||
} catch (err) {
|
||||
console.error('Error fetching status:', err);
|
||||
setError(err.message);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
fetchServiceStatus();
|
||||
const interval = setInterval(fetchServiceStatus, 30000);
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
const getStatusIcon = (status) => {
|
||||
if (status === 'healthy') {
|
||||
return React.createElement(CheckCircle, { className: 'w-5 h-5 text-green-500' });
|
||||
} else if (status === 'warning') {
|
||||
return React.createElement(AlertCircle, { className: 'w-5 h-5 text-yellow-500' });
|
||||
} else {
|
||||
return React.createElement(AlertCircle, { className: 'w-5 h-5 text-red-500' });
|
||||
}
|
||||
};
|
||||
|
||||
const getStatusBgColor = (status) => {
|
||||
if (status === 'healthy') return 'bg-green-50 border-green-200';
|
||||
if (status === 'warning') return 'bg-yellow-50 border-yellow-200';
|
||||
return 'bg-red-50 border-red-200';
|
||||
};
|
||||
|
||||
const getStatusTextColor = (status) => {
|
||||
if (status === 'healthy') return 'text-green-700';
|
||||
if (status === 'warning') return 'text-yellow-700';
|
||||
return 'text-red-700';
|
||||
};
|
||||
|
||||
const totalTools = services.reduce((sum, service) => sum + (service.toolCount || 0), 0);
|
||||
const healthyCount = services.filter(s => s.status === 'healthy').length;
|
||||
|
||||
return React.createElement('div', { className: 'min-h-screen bg-gradient-to-br from-slate-50 to-slate-100 p-8' },
|
||||
React.createElement('div', { className: 'max-w-7xl mx-auto' },
|
||||
// Header
|
||||
React.createElement('div', { className: 'flex items-center justify-between mb-8' },
|
||||
React.createElement('div', null,
|
||||
React.createElement('h1', { className: 'text-4xl font-bold text-slate-900 mb-2' }, 'MCP Gateway Dashboard'),
|
||||
React.createElement('p', { className: 'text-slate-600' }, 'Real-time status and monitoring of all MCP services')
|
||||
),
|
||||
React.createElement('button', {
|
||||
onClick: fetchServiceStatus,
|
||||
disabled: loading,
|
||||
className: 'flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:bg-blue-400 transition-colors'
|
||||
},
|
||||
React.createElement(RotateCcw, { className: `w-4 h-4 ${loading ? 'animate-spin' : ''}` }),
|
||||
'Refresh'
|
||||
)
|
||||
),
|
||||
|
||||
// Summary Stats
|
||||
React.createElement('div', { className: 'grid grid-cols-1 md:grid-cols-3 gap-4 mb-8' },
|
||||
React.createElement('div', { className: 'bg-white rounded-lg shadow p-6' },
|
||||
React.createElement('div', { className: 'flex items-center justify-between' },
|
||||
React.createElement('div', null,
|
||||
React.createElement('p', { className: 'text-slate-600 text-sm font-medium' }, 'Total Services'),
|
||||
React.createElement('p', { className: 'text-3xl font-bold text-slate-900 mt-1' }, services.length)
|
||||
),
|
||||
React.createElement(Zap, { className: 'w-8 h-8 text-blue-500' })
|
||||
)
|
||||
),
|
||||
React.createElement('div', { className: 'bg-white rounded-lg shadow p-6' },
|
||||
React.createElement('div', { className: 'flex items-center justify-between' },
|
||||
React.createElement('div', null,
|
||||
React.createElement('p', { className: 'text-slate-600 text-sm font-medium' }, 'Total Tools'),
|
||||
React.createElement('p', { className: 'text-3xl font-bold text-slate-900 mt-1' }, totalTools)
|
||||
),
|
||||
React.createElement(Zap, { className: 'w-8 h-8 text-green-500' })
|
||||
)
|
||||
),
|
||||
React.createElement('div', { className: 'bg-white rounded-lg shadow p-6' },
|
||||
React.createElement('div', { className: 'flex items-center justify-between' },
|
||||
React.createElement('div', null,
|
||||
React.createElement('p', { className: 'text-slate-600 text-sm font-medium' }, 'Healthy Services'),
|
||||
React.createElement('p', { className: 'text-3xl font-bold text-slate-900 mt-1' }, healthyCount)
|
||||
),
|
||||
React.createElement(CheckCircle, { className: 'w-8 h-8 text-green-500' })
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
// Last Updated
|
||||
lastUpdated && React.createElement('div', { className: 'text-sm text-slate-600 mb-6 flex items-center gap-2' },
|
||||
React.createElement(Clock, { className: 'w-4 h-4' }),
|
||||
`Last updated: ${lastUpdated.toLocaleTimeString()}`
|
||||
),
|
||||
|
||||
// Error State
|
||||
error && React.createElement('div', { className: 'bg-red-50 border border-red-200 rounded-lg p-4 mb-8 text-red-700' },
|
||||
React.createElement('p', { className: 'font-medium' }, 'Error loading service status'),
|
||||
React.createElement('p', { className: 'text-sm' }, error)
|
||||
),
|
||||
|
||||
// Services Grid
|
||||
React.createElement('div', { className: 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6' },
|
||||
services.map((service) =>
|
||||
React.createElement('div', {
|
||||
key: service.name,
|
||||
className: `rounded-lg border-2 p-6 transition-all hover:shadow-lg ${getStatusBgColor(service.status)}`
|
||||
},
|
||||
// Service Header
|
||||
React.createElement('div', { className: 'flex items-start justify-between mb-4' },
|
||||
React.createElement('div', null,
|
||||
React.createElement('h3', { className: 'text-lg font-bold text-slate-900 capitalize' }, service.name),
|
||||
React.createElement('p', { className: `text-sm font-medium ${getStatusTextColor(service.status)}` },
|
||||
service.status.charAt(0).toUpperCase() + service.status.slice(1)
|
||||
)
|
||||
),
|
||||
getStatusIcon(service.status)
|
||||
),
|
||||
|
||||
// Service Details
|
||||
React.createElement('div', { className: 'space-y-3' },
|
||||
// Tool Count
|
||||
React.createElement('div', { className: 'flex items-center justify-between p-3 bg-white rounded border border-slate-200' },
|
||||
React.createElement('span', { className: 'text-sm text-slate-600' }, 'Tools Available'),
|
||||
React.createElement('span', { className: 'text-xl font-bold text-slate-900' }, service.toolCount || 0)
|
||||
),
|
||||
|
||||
// Response Time
|
||||
service.responseTime !== undefined && React.createElement('div', { className: 'flex items-center justify-between p-3 bg-white rounded border border-slate-200' },
|
||||
React.createElement('span', { className: 'text-sm text-slate-600' }, 'Response Time'),
|
||||
React.createElement('span', { className: 'text-sm font-mono font-bold text-slate-900' }, `${service.responseTime}ms`)
|
||||
),
|
||||
|
||||
// URL
|
||||
React.createElement('div', { className: 'p-3 bg-white rounded border border-slate-200 text-xs' },
|
||||
React.createElement('p', { className: 'text-slate-600 mb-1' }, 'Service URL'),
|
||||
React.createElement('p', { className: 'text-slate-900 font-mono break-all' }, service.url)
|
||||
),
|
||||
|
||||
// Last Check
|
||||
service.lastCheck && React.createElement('div', { className: 'text-xs text-slate-600 px-3' },
|
||||
`Last health check: ${new Date(service.lastCheck).toLocaleTimeString()}`
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
// Empty State
|
||||
!loading && services.length === 0 && !error && React.createElement('div', { className: 'text-center py-12' },
|
||||
React.createElement('p', { className: 'text-slate-600' }, 'No services available yet. Check your configuration.')
|
||||
),
|
||||
|
||||
// Loading State
|
||||
loading && services.length === 0 && React.createElement('div', { className: 'text-center py-12' },
|
||||
React.createElement('div', { className: 'inline-block' },
|
||||
React.createElement('div', { className: 'w-8 h-8 border-4 border-slate-300 border-t-blue-600 rounded-full animate-spin' })
|
||||
),
|
||||
React.createElement('p', { className: 'text-slate-600 mt-4' }, 'Loading service status...')
|
||||
)
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||
root.render(React.createElement(Dashboard));
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in a new issue