e045354892
Adds initial project structure, dependencies, and basic configuration for the License Tracker Pro v1.2 application. This includes setting up Vite for the build process, defining core types, and incorporating essential UI components like icons and a timeline. The project is now ready for development.
91 lines
5.1 KiB
TypeScript
91 lines
5.1 KiB
TypeScript
import React, { useEffect, useState } from 'react';
|
|
import { AuditLog } from '../types';
|
|
import { fetchLogs } from '../graphService';
|
|
|
|
const AuditLogs: React.FC = () => {
|
|
const [logs, setLogs] = useState<AuditLog[]>([]);
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
const [error, setError] = useState('');
|
|
|
|
const loadLogs = async () => {
|
|
setIsLoading(true);
|
|
try {
|
|
const data = await fetchLogs();
|
|
setLogs(Array.isArray(data) ? data : []);
|
|
setError('');
|
|
} catch (err: any) {
|
|
setError(err.message);
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
loadLogs();
|
|
}, []);
|
|
|
|
if (isLoading) return <div className="text-center text-cyan-400 py-16 font-mono text-sm animate-pulse tracking-widest">QUERYING SYSTEM JOURNALS...</div>;
|
|
if (error) return (
|
|
<div className="bg-red-900/20 border border-red-500/50 p-8 rounded-xl text-center">
|
|
<p className="text-red-400 font-mono text-xs mb-4">LOG_FETCH_FAILURE: {error}</p>
|
|
<button onClick={loadLogs} className="bg-red-600 text-white px-4 py-2 rounded-lg font-bold text-xs">Retry Connection</button>
|
|
</div>
|
|
);
|
|
|
|
return (
|
|
<div className="bg-slate-800 rounded-2xl shadow-xl overflow-hidden border border-slate-700 animate-in fade-in duration-500">
|
|
<div className="p-6 border-b border-slate-700 flex justify-between items-center bg-slate-900/50">
|
|
<div>
|
|
<h2 className="text-xl font-bold text-gray-200">System Audit Journal</h2>
|
|
<p className="text-[10px] text-slate-500 mt-1 uppercase font-black tracking-widest">Chronological Modification Tracking</p>
|
|
</div>
|
|
<button onClick={loadLogs} className="p-2 text-cyan-400 hover:bg-cyan-900/20 rounded-xl transition-all">
|
|
<svg className="w-4 h-4" 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>
|
|
</button>
|
|
</div>
|
|
<div className="overflow-x-auto">
|
|
<table className="w-full text-left text-sm text-gray-400">
|
|
<thead className="bg-slate-900 text-slate-500 uppercase text-[9px] font-black tracking-[0.2em]">
|
|
<tr>
|
|
<th className="px-6 py-4">Timestamp</th>
|
|
<th className="px-6 py-4">Identity</th>
|
|
<th className="px-6 py-4">Operation</th>
|
|
<th className="px-6 py-4">Object</th>
|
|
<th className="px-6 py-4">Details</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody className="divide-y divide-slate-700/50">
|
|
{logs.map((log) => (
|
|
<tr key={log.id} className="hover:bg-slate-700/30 transition-colors text-[11px]">
|
|
<td className="px-6 py-4 whitespace-nowrap text-slate-500 font-mono">{new Date(log.created_at).toLocaleString()}</td>
|
|
<td className="px-6 py-4 font-bold text-white tracking-tight">{log.username}</td>
|
|
<td className="px-6 py-4">
|
|
<span className={`px-2 py-0.5 rounded-full text-[9px] font-black uppercase tracking-tighter ${
|
|
log.action_type === 'CREATE' ? 'bg-green-900/40 text-green-400 border border-green-800/50' :
|
|
log.action_type === 'DELETE' ? 'bg-red-900/40 text-red-400 border border-red-800/50' :
|
|
log.action_type === 'LOGIN' ? 'bg-cyan-900/40 text-cyan-400 border border-cyan-800/50' :
|
|
'bg-blue-900/40 text-blue-400 border border-blue-800/50'
|
|
}`}>
|
|
{log.action_type}
|
|
</span>
|
|
</td>
|
|
<td className="px-6 py-4">
|
|
<span className="text-slate-500 uppercase text-[9px] font-black mr-2 opacity-50">{log.entity_type}</span>
|
|
<span className="text-gray-200">{log.entity_name}</span>
|
|
</td>
|
|
<td className="px-6 py-4 text-slate-400 italic max-w-xs truncate">{log.details}</td>
|
|
</tr>
|
|
))}
|
|
{logs.length === 0 && (
|
|
<tr>
|
|
<td colSpan={5} className="px-6 py-12 text-center text-slate-600 font-medium">No system events logged in current period.</td>
|
|
</tr>
|
|
)}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default AuditLogs; |