TarunikaHF's picture
feat(infrastructure): implement RBAC auth, CI/CD pipeline, and test suite
382dea6
Raw
History Blame Contribute Delete
4.08 kB
import React, { useState, useEffect, useRef } from 'react';
import { adminApi } from '../api/client';
import { Activity, Trash2, RefreshCw } from 'lucide-react';
import CacheStats from './CacheStats';
import LatencyChart from './LatencyChart';
import ClusterViz from './ClusterViz';
const AdminPanel = ({ stats, analytics, fetchData }) => {
const [isEvaluating, setIsEvaluating] = useState(false);
const [evalResults, setEvalResults] = useState(null);
const [adminMessage, setAdminMessage] = useState('');
const evalRef = useRef(null);
const handleClearCache = async () => {
try {
await adminApi.clearCache();
setAdminMessage('Cache cleared successfully!');
setTimeout(() => setAdminMessage(''), 3000);
fetchData();
} catch (err) {
console.error("Failed to clear cache", err);
}
};
const handleRunEvaluation = async () => {
setIsEvaluating(true);
try {
const res = await adminApi.runEvaluation();
setEvalResults(res.data);
setTimeout(() => {
if (evalRef.current) {
evalRef.current.scrollIntoView({ behavior: 'smooth' });
}
}, 100);
} catch (err) {
console.error("Eval failed", err);
}
setIsEvaluating(false);
};
return (
<div className="admin-panel glass-panel" style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
<div className="admin-header">
<h3><Activity size={18}/> System Dashboard</h3>
<button className="icon-button" onClick={fetchData}><RefreshCw size={14}/></button>
</div>
<div className="charts-grid" style={{ flex: 1, overflowY: 'auto', paddingRight: '0.5rem' }}>
<CacheStats stats={stats} analytics={analytics} />
<LatencyChart analytics={analytics} />
<div style={{ gridColumn: '1 / -1' }}>
<ClusterViz />
</div>
{evalResults && !evalResults.error && (
<div style={{ gridColumn: '1 / -1' }} ref={evalRef}>
<div className="eval-results glass-panel fade-in" style={{ marginTop: '1rem', overflowX: 'auto' }}>
<h4>Retrieval Evaluation (NDCG/MRR)</h4>
<table className="eval-table">
<thead>
<tr>
<th>Mode</th>
<th>NDCG@10</th>
<th>MRR</th>
<th>P@3</th>
<th>R@10</th>
<th>MAP</th>
</tr>
</thead>
<tbody>
{Object.entries(evalResults).map(([mode, metrics]) => (
<tr key={mode}>
<td>{mode}</td>
<td>{metrics['ndcg@10'].toFixed(4)}</td>
<td>{metrics['mrr'].toFixed(4)}</td>
<td>{metrics['p@3'].toFixed(4)}</td>
<td>{metrics['r@10'].toFixed(4)}</td>
<td>{metrics['map'].toFixed(4)}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
)}
{evalResults?.error && (
<div style={{ gridColumn: '1 / -1' }}>
<div className="eval-error">{evalResults.error}</div>
</div>
)}
</div>
<div className="admin-controls" style={{ marginTop: '1rem', borderTop: '1px solid rgba(255,255,255,0.1)', paddingTop: '1rem' }}>
<div className="button-group" style={{marginTop: '1rem', display: 'flex', alignItems: 'center', gap: '1rem'}}>
<button onClick={handleClearCache} className="btn-danger">
<Trash2 size={14}/> Clear Cache
</button>
<button onClick={handleRunEvaluation} className="btn-primary" disabled={isEvaluating}>
{isEvaluating ? 'Evaluating...' : 'Load IR Metrics'}
</button>
{adminMessage && <span style={{ color: 'var(--accent-primary)', fontSize: '0.8rem' }}>{adminMessage}</span>}
</div>
</div>
</div>
);
};
export default AdminPanel;