EverydayTech Platform - Developer Reference
Complete Source Code Documentation - All Applications
Loading...
Searching...
No Matches
TabLogs.jsx
Go to the documentation of this file.
1import React from "react";
2import { apiFetch } from "../../lib/api";
3
4export default function TabLogs({ agentId }) {
5 const [activityLogs, setActivityLogs] = React.useState([]);
6 const [agentLogs, setAgentLogs] = React.useState([]);
7 const [loading, setLoading] = React.useState(true);
8 const [activeTab, setActiveTab] = React.useState('activity'); // 'activity' or 'agent'
9
10 React.useEffect(() => {
11 if (!agentId) return;
12 setLoading(true);
13
14 Promise.all([
15 apiFetch(`/agent/${agentId}/activity-logs`).catch(() => []),
16 apiFetch(`/agent/${agentId}/agent-logs`).catch(() => [])
17 ]).then(([activity, agent]) => {
18 setActivityLogs(activity);
19 setAgentLogs(agent);
20 }).finally(() => setLoading(false));
21 }, [agentId]);
22
23 if (loading) {
24 return (
25 <div className="tab-container">
26 <h2>Logs</h2>
27 <div className="card">Loading logs...</div>
28 </div>
29 );
30 }
31
32 const safeActivityLogs = Array.isArray(activityLogs) ? activityLogs : [];
33 const safeAgentLogs = Array.isArray(agentLogs) ? agentLogs : [];
34
35 return (
36 <div className="tab-container">
37 <h2>Logs</h2>
38
39 {/* Tab Switcher */}
40 <div className="card" style={{ marginBottom: '16px', padding: '8px', display: 'flex', gap: '8px' }}>
41 <button
42 className={`btn ${activeTab === 'activity' ? 'btn-primary' : 'btn-secondary'}`}
43 onClick={() => setActiveTab('activity')}
44 style={{ flex: 1 }}
45 >
46 Activity Logs
47 </button>
48 <button
49 className={`btn ${activeTab === 'agent' ? 'btn-primary' : 'btn-secondary'}`}
50 onClick={() => setActiveTab('agent')}
51 style={{ flex: 1 }}
52 >
53 Agent Logs
54 </button>
55 </div>
56
57 {/* Activity Logs Tab */}
58 {activeTab === 'activity' && (
59 <div className="card">
60 <h3 style={{ marginTop: 0 }}>Activity Logs</h3>
61 <p style={{ color: '#888', fontSize: '14px', marginBottom: '16px' }}>
62 User actions: Remote sessions, script executions, file transfers, and system changes
63 </p>
64 <div className="log-box" style={{ maxHeight: '600px', overflow: 'auto' }}>
65 {safeActivityLogs.length === 0 ? (
66 <div style={{ padding: '20px', textAlign: 'center', color: '#888' }}>
67 No activity logs available yet
68 </div>
69 ) : (
70 safeActivityLogs.map((log, i) => (
71 <div key={i} className="log-entry" style={{
72 padding: '12px',
73 borderBottom: '1px solid #eee',
74 fontSize: '14px'
75 }}>
76 <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '4px' }}>
77 <strong style={{ color: '#333' }}>{log.action || 'Unknown Action'}</strong>
78 <span style={{ color: '#888', fontSize: '12px' }}>
79 {log.timestamp ? new Date(log.timestamp).toLocaleString() : ''}
80 </span>
81 </div>
82 <div style={{ color: '#666', fontSize: '13px' }}>
83 {log.details || log.message || 'No details'}
84 </div>
85 {log.user && (
86 <div style={{ color: '#888', fontSize: '12px', marginTop: '4px' }}>
87 User: {log.user}
88 </div>
89 )}
90 </div>
91 ))
92 )}
93 </div>
94 </div>
95 )}
96
97 {/* Agent Logs Tab */}
98 {activeTab === 'agent' && (
99 <div className="card">
100 <h3 style={{ marginTop: 0 }}>Agent Logs</h3>
101 <p style={{ color: '#888', fontSize: '14px', marginBottom: '16px' }}>
102 Agent internal logs: Heartbeats, errors, updates, and system events
103 </p>
104 <div className="log-box" style={{ maxHeight: '600px', overflow: 'auto', fontFamily: 'monospace' }}>
105 {safeAgentLogs.length === 0 ? (
106 <div style={{ padding: '20px', textAlign: 'center', color: '#888' }}>
107 No agent logs available yet
108 </div>
109 ) : (
110 safeAgentLogs.map((log, i) => (
111 <div key={i} className="log-entry" style={{
112 padding: '8px 12px',
113 borderBottom: '1px solid #eee',
114 fontSize: '13px',
115 whiteSpace: 'pre-wrap'
116 }}>
117 <span style={{ color: '#888' }}>
118 {log.timestamp ? new Date(log.timestamp).toLocaleString() : ''}
119 </span>
120 {' '}
121 <span style={{
122 color: log.level === 'error' ? '#dc3545' :
123 log.level === 'warn' ? '#ffc107' : '#666'
124 }}>
125 [{log.level?.toUpperCase() || 'INFO'}]
126 </span>
127 {' '}
128 {log.message || log.details || 'No message'}
129 </div>
130 ))
131 )}
132 </div>
133 </div>
134 )}
135 </div>
136 );
137}