@agenticmail/enterprise 0.5.279 โ 0.5.281
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -175,9 +175,12 @@ export function DatabaseAccessPage() {
|
|
|
175
175
|
|
|
176
176
|
// Tabs
|
|
177
177
|
h('div', { style: s.tabs },
|
|
178
|
-
h('div', { style: tab === 'connections' ? s.tabActive : s.tab, onClick: function() { setTab('connections'); } },
|
|
179
|
-
|
|
180
|
-
h('div', { style: tab === '
|
|
178
|
+
h('div', { style: tab === 'connections' ? s.tabActive : s.tab, onClick: function() { setTab('connections'); } },
|
|
179
|
+
h('span', { style: css('display: inline-flex; align-items: center; gap: 6px;') }, h('span', { style: css('display: flex; transform: scale(0.7);') }, I.database()), 'Connections')),
|
|
180
|
+
h('div', { style: tab === 'agents' ? s.tabActive : s.tab, onClick: function() { setTab('agents'); } },
|
|
181
|
+
h('span', { style: css('display: inline-flex; align-items: center; gap: 6px;') }, h('span', { style: css('display: flex; transform: scale(0.7);') }, I.shield()), 'Agent Access')),
|
|
182
|
+
h('div', { style: tab === 'audit' ? s.tabActive : s.tab, onClick: function() { setTab('audit'); } },
|
|
183
|
+
h('span', { style: css('display: inline-flex; align-items: center; gap: 6px;') }, h('span', { style: css('display: flex; transform: scale(0.7);') }, I.audit()), 'Audit Log')),
|
|
181
184
|
),
|
|
182
185
|
|
|
183
186
|
// Content
|
|
@@ -260,7 +263,7 @@ function AgentAccessTab(props) {
|
|
|
260
263
|
|
|
261
264
|
if (agentsWithAccess.length === 0) {
|
|
262
265
|
return h('div', { style: s.emptyState },
|
|
263
|
-
h('div', { style: s.emptyIcon },
|
|
266
|
+
h('div', { style: s.emptyIcon }, I.lock()),
|
|
264
267
|
h('div', { style: css('font-size: 16px; font-weight: 600; margin-bottom: 8px;') }, 'No Agents Have Database Access'),
|
|
265
268
|
h('div', null, 'Grant access from the Connections tab to allow agents to query databases.'),
|
|
266
269
|
);
|
|
@@ -305,46 +308,161 @@ function AgentAccessTab(props) {
|
|
|
305
308
|
|
|
306
309
|
// โโโ Audit Tab โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
307
310
|
|
|
311
|
+
var AUDIT_PAGE_SIZE = 15;
|
|
312
|
+
|
|
308
313
|
function AuditTab(props) {
|
|
314
|
+
var [search, setSearch] = useState('');
|
|
315
|
+
var [opFilter, setOpFilter] = useState('all');
|
|
316
|
+
var [statusFilter, setStatusFilter] = useState('all');
|
|
317
|
+
var [agentFilter, setAgentFilter] = useState('all');
|
|
318
|
+
var [page, setPage] = useState(0);
|
|
319
|
+
var [expanded, setExpanded] = useState(null);
|
|
320
|
+
|
|
321
|
+
// Get unique agents from audit log
|
|
322
|
+
var agents = [];
|
|
323
|
+
var agentSet = {};
|
|
324
|
+
props.auditLog.forEach(function(e) {
|
|
325
|
+
var name = e.agent_name || e.agent_id;
|
|
326
|
+
if (name && !agentSet[name]) { agentSet[name] = true; agents.push(name); }
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
// Filter entries
|
|
330
|
+
var filtered = props.auditLog.filter(function(e) {
|
|
331
|
+
if (opFilter !== 'all' && e.operation !== opFilter) return false;
|
|
332
|
+
if (statusFilter === 'ok' && !e.success) return false;
|
|
333
|
+
if (statusFilter === 'fail' && e.success) return false;
|
|
334
|
+
if (agentFilter !== 'all' && (e.agent_name || e.agent_id) !== agentFilter) return false;
|
|
335
|
+
if (search) {
|
|
336
|
+
var q = search.toLowerCase();
|
|
337
|
+
var haystack = ((e.query || '') + ' ' + (e.agent_name || '') + ' ' + (e.connection_name || '') + ' ' + (e.error || '')).toLowerCase();
|
|
338
|
+
if (haystack.indexOf(q) < 0) return false;
|
|
339
|
+
}
|
|
340
|
+
return true;
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
var totalPages = Math.max(1, Math.ceil(filtered.length / AUDIT_PAGE_SIZE));
|
|
344
|
+
if (page >= totalPages) page = totalPages - 1;
|
|
345
|
+
var paged = filtered.slice(page * AUDIT_PAGE_SIZE, (page + 1) * AUDIT_PAGE_SIZE);
|
|
346
|
+
|
|
347
|
+
// Reset page when filters change
|
|
348
|
+
var resetPage = function() { setPage(0); };
|
|
349
|
+
|
|
309
350
|
if (props.auditLog.length === 0) {
|
|
310
351
|
return h('div', { style: s.emptyState },
|
|
311
|
-
h('div', { style: s.emptyIcon },
|
|
352
|
+
h('div', { style: s.emptyIcon }, I.audit()),
|
|
312
353
|
h('div', { style: css('font-size: 16px; font-weight: 600; margin-bottom: 8px;') }, 'No Query Activity Yet'),
|
|
313
354
|
h('div', null, 'Queries executed by agents will appear here with full audit details.'),
|
|
314
355
|
);
|
|
315
356
|
}
|
|
316
357
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
h('
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
358
|
+
var opColor = function(op) {
|
|
359
|
+
return op === 'read' ? 'var(--success)' : op === 'write' ? 'var(--warning)' : op === 'delete' ? 'var(--danger)' : op === 'schema' ? 'var(--accent)' : 'var(--text-muted)';
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
var filterBar = css('display: flex; gap: 8px; margin-bottom: 16px; flex-wrap: wrap; align-items: center;');
|
|
363
|
+
var filterSelect = css('padding: 6px 10px; border-radius: 6px; border: 1px solid var(--border); background: var(--bg-secondary); color: var(--text-primary); font-size: 12px;');
|
|
364
|
+
var searchInput = css('padding: 6px 10px; border-radius: 6px; border: 1px solid var(--border); background: var(--bg-primary); color: var(--text-primary); font-size: 12px; flex: 1; min-width: 180px;');
|
|
365
|
+
var countBadge = css('font-size: 11px; color: var(--text-muted); margin-left: auto; white-space: nowrap;');
|
|
366
|
+
|
|
367
|
+
return h('div', null,
|
|
368
|
+
// Filter bar
|
|
369
|
+
h('div', { style: filterBar },
|
|
370
|
+
h('div', { style: css('display: flex; align-items: center; gap: 4px; color: var(--text-muted);') },
|
|
371
|
+
h('span', { style: css('display: flex; transform: scale(0.65);') }, I.search()),
|
|
372
|
+
),
|
|
373
|
+
h('input', { style: searchInput, placeholder: 'Search queries, agents, databases, errors...', value: search, onInput: function(e) { setSearch(e.target.value); resetPage(); } }),
|
|
374
|
+
h('select', { style: filterSelect, value: opFilter, onChange: function(e) { setOpFilter(e.target.value); resetPage(); } },
|
|
375
|
+
h('option', { value: 'all' }, 'All Operations'),
|
|
376
|
+
h('option', { value: 'read' }, 'Read'),
|
|
377
|
+
h('option', { value: 'write' }, 'Write'),
|
|
378
|
+
h('option', { value: 'delete' }, 'Delete'),
|
|
379
|
+
h('option', { value: 'schema' }, 'Schema'),
|
|
380
|
+
h('option', { value: 'execute' }, 'Execute'),
|
|
381
|
+
),
|
|
382
|
+
h('select', { style: filterSelect, value: statusFilter, onChange: function(e) { setStatusFilter(e.target.value); resetPage(); } },
|
|
383
|
+
h('option', { value: 'all' }, 'All Status'),
|
|
384
|
+
h('option', { value: 'ok' }, 'Success'),
|
|
385
|
+
h('option', { value: 'fail' }, 'Failed'),
|
|
386
|
+
),
|
|
387
|
+
agents.length > 1 && h('select', { style: filterSelect, value: agentFilter, onChange: function(e) { setAgentFilter(e.target.value); resetPage(); } },
|
|
388
|
+
h('option', { value: 'all' }, 'All Agents'),
|
|
389
|
+
agents.map(function(a) { return h('option', { key: a, value: a }, a); })
|
|
390
|
+
),
|
|
391
|
+
h('span', { style: countBadge }, filtered.length + ' of ' + props.auditLog.length + ' entries'),
|
|
392
|
+
h('button', { style: Object.assign({}, s.btn, { padding: '4px 10px', fontSize: '11px' }), onClick: props.onRefresh }, 'Refresh'),
|
|
393
|
+
),
|
|
394
|
+
|
|
395
|
+
// Table
|
|
396
|
+
h('div', { style: css('overflow-x: auto; border: 1px solid var(--border); border-radius: 8px;') },
|
|
397
|
+
h('table', { style: s.auditTable },
|
|
398
|
+
h('thead', null, h('tr', null,
|
|
399
|
+
h('th', { style: s.auditTh }, 'Time'),
|
|
400
|
+
h('th', { style: s.auditTh }, 'Agent'),
|
|
401
|
+
h('th', { style: s.auditTh }, 'Database'),
|
|
402
|
+
h('th', { style: s.auditTh }, 'Operation'),
|
|
403
|
+
h('th', { style: s.auditTh }, 'Query'),
|
|
404
|
+
h('th', { style: s.auditTh }, 'Rows'),
|
|
405
|
+
h('th', { style: s.auditTh }, 'Latency'),
|
|
406
|
+
h('th', { style: s.auditTh }, 'Status'),
|
|
407
|
+
)),
|
|
408
|
+
h('tbody', null,
|
|
409
|
+
paged.length === 0 && h('tr', null,
|
|
410
|
+
h('td', { colSpan: 8, style: Object.assign({}, s.auditTd, { textAlign: 'center', color: 'var(--text-muted)', padding: '24px' }) }, 'No entries match your filters')
|
|
411
|
+
),
|
|
412
|
+
paged.map(function(entry) {
|
|
413
|
+
var isExpanded = expanded === entry.id;
|
|
414
|
+
return h(Fragment, { key: entry.id },
|
|
415
|
+
h('tr', { style: css('cursor: pointer; transition: background 0.1s;'), onClick: function() { setExpanded(isExpanded ? null : entry.id); } },
|
|
416
|
+
h('td', { style: s.auditTd }, new Date(entry.timestamp).toLocaleString()),
|
|
417
|
+
h('td', { style: Object.assign({}, s.auditTd, { fontWeight: 500 }) }, entry.agent_name || (entry.agent_id ? entry.agent_id.slice(0, 8) + '...' : 'โ')),
|
|
418
|
+
h('td', { style: s.auditTd }, entry.connection_name || (entry.connection_id ? entry.connection_id.slice(0, 8) + '...' : 'โ')),
|
|
419
|
+
h('td', { style: Object.assign({}, s.auditTd, { fontWeight: 600, color: opColor(entry.operation) }) }, entry.operation),
|
|
420
|
+
h('td', { style: Object.assign({}, s.auditTd, { fontFamily: 'monospace', fontSize: '11px', maxWidth: '300px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }) }, entry.query),
|
|
421
|
+
h('td', { style: Object.assign({}, s.auditTd, { textAlign: 'right' }) }, entry.rows_affected != null ? entry.rows_affected : 'โ'),
|
|
422
|
+
h('td', { style: Object.assign({}, s.auditTd, { textAlign: 'right', whiteSpace: 'nowrap' }) }, entry.execution_time_ms != null ? entry.execution_time_ms + 'ms' : 'โ'),
|
|
423
|
+
h('td', { style: s.auditTd }, entry.success
|
|
424
|
+
? h('span', { style: Object.assign({}, s.badge, s.badgeActive) }, 'OK')
|
|
425
|
+
: h('span', { style: Object.assign({}, s.badge, s.badgeError) }, 'FAIL')
|
|
426
|
+
),
|
|
427
|
+
),
|
|
428
|
+
// Expanded row detail
|
|
429
|
+
isExpanded && h('tr', null,
|
|
430
|
+
h('td', { colSpan: 8, style: css('padding: 12px 16px; background: var(--bg-secondary); border-bottom: 1px solid var(--border);') },
|
|
431
|
+
h('div', { style: css('display: grid; grid-template-columns: 1fr 1fr; gap: 12px; font-size: 12px;') },
|
|
432
|
+
h('div', null,
|
|
433
|
+
h('div', { style: css('font-weight: 600; margin-bottom: 4px; color: var(--text-muted);') }, 'Full Query'),
|
|
434
|
+
h('pre', { style: css('margin: 0; padding: 8px; background: var(--bg-primary); border-radius: 6px; overflow-x: auto; font-size: 11px; white-space: pre-wrap; word-break: break-all; max-height: 200px;') }, entry.query || 'โ'),
|
|
435
|
+
),
|
|
436
|
+
h('div', null,
|
|
437
|
+
h('div', { style: css('font-weight: 600; margin-bottom: 4px; color: var(--text-muted);') }, 'Details'),
|
|
438
|
+
h('div', { style: css('display: flex; flex-direction: column; gap: 4px;') },
|
|
439
|
+
h('div', null, h('strong', null, 'Agent ID: '), entry.agent_id || 'โ'),
|
|
440
|
+
h('div', null, h('strong', null, 'Connection ID: '), entry.connection_id || 'โ'),
|
|
441
|
+
h('div', null, h('strong', null, 'Rows Affected: '), entry.rows_affected != null ? String(entry.rows_affected) : 'โ'),
|
|
442
|
+
h('div', null, h('strong', null, 'Execution Time: '), entry.execution_time_ms != null ? entry.execution_time_ms + 'ms' : 'โ'),
|
|
443
|
+
h('div', null, h('strong', null, 'IP: '), entry.ip_address || 'โ'),
|
|
444
|
+
!entry.success && entry.error && h('div', { style: css('margin-top: 4px; padding: 6px 8px; background: rgba(239,68,68,0.1); border-radius: 4px; color: var(--danger);') },
|
|
445
|
+
h('strong', null, 'Error: '), entry.error
|
|
446
|
+
),
|
|
447
|
+
),
|
|
448
|
+
),
|
|
449
|
+
),
|
|
450
|
+
),
|
|
451
|
+
),
|
|
452
|
+
);
|
|
453
|
+
})
|
|
454
|
+
),
|
|
346
455
|
),
|
|
347
456
|
),
|
|
457
|
+
|
|
458
|
+
// Pagination
|
|
459
|
+
totalPages > 1 && h('div', { style: css('display: flex; align-items: center; justify-content: center; gap: 8px; margin-top: 16px;') },
|
|
460
|
+
h('button', { style: Object.assign({}, s.btn, { padding: '4px 10px', fontSize: '12px' }), disabled: page === 0, onClick: function() { setPage(0); } }, 'ยซ'),
|
|
461
|
+
h('button', { style: Object.assign({}, s.btn, { padding: '4px 10px', fontSize: '12px' }), disabled: page === 0, onClick: function() { setPage(page - 1); } }, 'โน'),
|
|
462
|
+
h('span', { style: css('font-size: 12px; color: var(--text-secondary);') }, 'Page ' + (page + 1) + ' of ' + totalPages),
|
|
463
|
+
h('button', { style: Object.assign({}, s.btn, { padding: '4px 10px', fontSize: '12px' }), disabled: page >= totalPages - 1, onClick: function() { setPage(page + 1); } }, 'โบ'),
|
|
464
|
+
h('button', { style: Object.assign({}, s.btn, { padding: '4px 10px', fontSize: '12px' }), disabled: page >= totalPages - 1, onClick: function() { setPage(totalPages - 1); } }, 'ยป'),
|
|
465
|
+
),
|
|
348
466
|
);
|
|
349
467
|
}
|
|
350
468
|
|
package/package.json
CHANGED
|
@@ -175,9 +175,12 @@ export function DatabaseAccessPage() {
|
|
|
175
175
|
|
|
176
176
|
// Tabs
|
|
177
177
|
h('div', { style: s.tabs },
|
|
178
|
-
h('div', { style: tab === 'connections' ? s.tabActive : s.tab, onClick: function() { setTab('connections'); } },
|
|
179
|
-
|
|
180
|
-
h('div', { style: tab === '
|
|
178
|
+
h('div', { style: tab === 'connections' ? s.tabActive : s.tab, onClick: function() { setTab('connections'); } },
|
|
179
|
+
h('span', { style: css('display: inline-flex; align-items: center; gap: 6px;') }, h('span', { style: css('display: flex; transform: scale(0.7);') }, I.database()), 'Connections')),
|
|
180
|
+
h('div', { style: tab === 'agents' ? s.tabActive : s.tab, onClick: function() { setTab('agents'); } },
|
|
181
|
+
h('span', { style: css('display: inline-flex; align-items: center; gap: 6px;') }, h('span', { style: css('display: flex; transform: scale(0.7);') }, I.shield()), 'Agent Access')),
|
|
182
|
+
h('div', { style: tab === 'audit' ? s.tabActive : s.tab, onClick: function() { setTab('audit'); } },
|
|
183
|
+
h('span', { style: css('display: inline-flex; align-items: center; gap: 6px;') }, h('span', { style: css('display: flex; transform: scale(0.7);') }, I.audit()), 'Audit Log')),
|
|
181
184
|
),
|
|
182
185
|
|
|
183
186
|
// Content
|
|
@@ -260,7 +263,7 @@ function AgentAccessTab(props) {
|
|
|
260
263
|
|
|
261
264
|
if (agentsWithAccess.length === 0) {
|
|
262
265
|
return h('div', { style: s.emptyState },
|
|
263
|
-
h('div', { style: s.emptyIcon },
|
|
266
|
+
h('div', { style: s.emptyIcon }, I.lock()),
|
|
264
267
|
h('div', { style: css('font-size: 16px; font-weight: 600; margin-bottom: 8px;') }, 'No Agents Have Database Access'),
|
|
265
268
|
h('div', null, 'Grant access from the Connections tab to allow agents to query databases.'),
|
|
266
269
|
);
|
|
@@ -305,46 +308,161 @@ function AgentAccessTab(props) {
|
|
|
305
308
|
|
|
306
309
|
// โโโ Audit Tab โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
307
310
|
|
|
311
|
+
var AUDIT_PAGE_SIZE = 15;
|
|
312
|
+
|
|
308
313
|
function AuditTab(props) {
|
|
314
|
+
var [search, setSearch] = useState('');
|
|
315
|
+
var [opFilter, setOpFilter] = useState('all');
|
|
316
|
+
var [statusFilter, setStatusFilter] = useState('all');
|
|
317
|
+
var [agentFilter, setAgentFilter] = useState('all');
|
|
318
|
+
var [page, setPage] = useState(0);
|
|
319
|
+
var [expanded, setExpanded] = useState(null);
|
|
320
|
+
|
|
321
|
+
// Get unique agents from audit log
|
|
322
|
+
var agents = [];
|
|
323
|
+
var agentSet = {};
|
|
324
|
+
props.auditLog.forEach(function(e) {
|
|
325
|
+
var name = e.agent_name || e.agent_id;
|
|
326
|
+
if (name && !agentSet[name]) { agentSet[name] = true; agents.push(name); }
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
// Filter entries
|
|
330
|
+
var filtered = props.auditLog.filter(function(e) {
|
|
331
|
+
if (opFilter !== 'all' && e.operation !== opFilter) return false;
|
|
332
|
+
if (statusFilter === 'ok' && !e.success) return false;
|
|
333
|
+
if (statusFilter === 'fail' && e.success) return false;
|
|
334
|
+
if (agentFilter !== 'all' && (e.agent_name || e.agent_id) !== agentFilter) return false;
|
|
335
|
+
if (search) {
|
|
336
|
+
var q = search.toLowerCase();
|
|
337
|
+
var haystack = ((e.query || '') + ' ' + (e.agent_name || '') + ' ' + (e.connection_name || '') + ' ' + (e.error || '')).toLowerCase();
|
|
338
|
+
if (haystack.indexOf(q) < 0) return false;
|
|
339
|
+
}
|
|
340
|
+
return true;
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
var totalPages = Math.max(1, Math.ceil(filtered.length / AUDIT_PAGE_SIZE));
|
|
344
|
+
if (page >= totalPages) page = totalPages - 1;
|
|
345
|
+
var paged = filtered.slice(page * AUDIT_PAGE_SIZE, (page + 1) * AUDIT_PAGE_SIZE);
|
|
346
|
+
|
|
347
|
+
// Reset page when filters change
|
|
348
|
+
var resetPage = function() { setPage(0); };
|
|
349
|
+
|
|
309
350
|
if (props.auditLog.length === 0) {
|
|
310
351
|
return h('div', { style: s.emptyState },
|
|
311
|
-
h('div', { style: s.emptyIcon },
|
|
352
|
+
h('div', { style: s.emptyIcon }, I.audit()),
|
|
312
353
|
h('div', { style: css('font-size: 16px; font-weight: 600; margin-bottom: 8px;') }, 'No Query Activity Yet'),
|
|
313
354
|
h('div', null, 'Queries executed by agents will appear here with full audit details.'),
|
|
314
355
|
);
|
|
315
356
|
}
|
|
316
357
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
h('
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
358
|
+
var opColor = function(op) {
|
|
359
|
+
return op === 'read' ? 'var(--success)' : op === 'write' ? 'var(--warning)' : op === 'delete' ? 'var(--danger)' : op === 'schema' ? 'var(--accent)' : 'var(--text-muted)';
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
var filterBar = css('display: flex; gap: 8px; margin-bottom: 16px; flex-wrap: wrap; align-items: center;');
|
|
363
|
+
var filterSelect = css('padding: 6px 10px; border-radius: 6px; border: 1px solid var(--border); background: var(--bg-secondary); color: var(--text-primary); font-size: 12px;');
|
|
364
|
+
var searchInput = css('padding: 6px 10px; border-radius: 6px; border: 1px solid var(--border); background: var(--bg-primary); color: var(--text-primary); font-size: 12px; flex: 1; min-width: 180px;');
|
|
365
|
+
var countBadge = css('font-size: 11px; color: var(--text-muted); margin-left: auto; white-space: nowrap;');
|
|
366
|
+
|
|
367
|
+
return h('div', null,
|
|
368
|
+
// Filter bar
|
|
369
|
+
h('div', { style: filterBar },
|
|
370
|
+
h('div', { style: css('display: flex; align-items: center; gap: 4px; color: var(--text-muted);') },
|
|
371
|
+
h('span', { style: css('display: flex; transform: scale(0.65);') }, I.search()),
|
|
372
|
+
),
|
|
373
|
+
h('input', { style: searchInput, placeholder: 'Search queries, agents, databases, errors...', value: search, onInput: function(e) { setSearch(e.target.value); resetPage(); } }),
|
|
374
|
+
h('select', { style: filterSelect, value: opFilter, onChange: function(e) { setOpFilter(e.target.value); resetPage(); } },
|
|
375
|
+
h('option', { value: 'all' }, 'All Operations'),
|
|
376
|
+
h('option', { value: 'read' }, 'Read'),
|
|
377
|
+
h('option', { value: 'write' }, 'Write'),
|
|
378
|
+
h('option', { value: 'delete' }, 'Delete'),
|
|
379
|
+
h('option', { value: 'schema' }, 'Schema'),
|
|
380
|
+
h('option', { value: 'execute' }, 'Execute'),
|
|
381
|
+
),
|
|
382
|
+
h('select', { style: filterSelect, value: statusFilter, onChange: function(e) { setStatusFilter(e.target.value); resetPage(); } },
|
|
383
|
+
h('option', { value: 'all' }, 'All Status'),
|
|
384
|
+
h('option', { value: 'ok' }, 'Success'),
|
|
385
|
+
h('option', { value: 'fail' }, 'Failed'),
|
|
386
|
+
),
|
|
387
|
+
agents.length > 1 && h('select', { style: filterSelect, value: agentFilter, onChange: function(e) { setAgentFilter(e.target.value); resetPage(); } },
|
|
388
|
+
h('option', { value: 'all' }, 'All Agents'),
|
|
389
|
+
agents.map(function(a) { return h('option', { key: a, value: a }, a); })
|
|
390
|
+
),
|
|
391
|
+
h('span', { style: countBadge }, filtered.length + ' of ' + props.auditLog.length + ' entries'),
|
|
392
|
+
h('button', { style: Object.assign({}, s.btn, { padding: '4px 10px', fontSize: '11px' }), onClick: props.onRefresh }, 'Refresh'),
|
|
393
|
+
),
|
|
394
|
+
|
|
395
|
+
// Table
|
|
396
|
+
h('div', { style: css('overflow-x: auto; border: 1px solid var(--border); border-radius: 8px;') },
|
|
397
|
+
h('table', { style: s.auditTable },
|
|
398
|
+
h('thead', null, h('tr', null,
|
|
399
|
+
h('th', { style: s.auditTh }, 'Time'),
|
|
400
|
+
h('th', { style: s.auditTh }, 'Agent'),
|
|
401
|
+
h('th', { style: s.auditTh }, 'Database'),
|
|
402
|
+
h('th', { style: s.auditTh }, 'Operation'),
|
|
403
|
+
h('th', { style: s.auditTh }, 'Query'),
|
|
404
|
+
h('th', { style: s.auditTh }, 'Rows'),
|
|
405
|
+
h('th', { style: s.auditTh }, 'Latency'),
|
|
406
|
+
h('th', { style: s.auditTh }, 'Status'),
|
|
407
|
+
)),
|
|
408
|
+
h('tbody', null,
|
|
409
|
+
paged.length === 0 && h('tr', null,
|
|
410
|
+
h('td', { colSpan: 8, style: Object.assign({}, s.auditTd, { textAlign: 'center', color: 'var(--text-muted)', padding: '24px' }) }, 'No entries match your filters')
|
|
411
|
+
),
|
|
412
|
+
paged.map(function(entry) {
|
|
413
|
+
var isExpanded = expanded === entry.id;
|
|
414
|
+
return h(Fragment, { key: entry.id },
|
|
415
|
+
h('tr', { style: css('cursor: pointer; transition: background 0.1s;'), onClick: function() { setExpanded(isExpanded ? null : entry.id); } },
|
|
416
|
+
h('td', { style: s.auditTd }, new Date(entry.timestamp).toLocaleString()),
|
|
417
|
+
h('td', { style: Object.assign({}, s.auditTd, { fontWeight: 500 }) }, entry.agent_name || (entry.agent_id ? entry.agent_id.slice(0, 8) + '...' : 'โ')),
|
|
418
|
+
h('td', { style: s.auditTd }, entry.connection_name || (entry.connection_id ? entry.connection_id.slice(0, 8) + '...' : 'โ')),
|
|
419
|
+
h('td', { style: Object.assign({}, s.auditTd, { fontWeight: 600, color: opColor(entry.operation) }) }, entry.operation),
|
|
420
|
+
h('td', { style: Object.assign({}, s.auditTd, { fontFamily: 'monospace', fontSize: '11px', maxWidth: '300px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }) }, entry.query),
|
|
421
|
+
h('td', { style: Object.assign({}, s.auditTd, { textAlign: 'right' }) }, entry.rows_affected != null ? entry.rows_affected : 'โ'),
|
|
422
|
+
h('td', { style: Object.assign({}, s.auditTd, { textAlign: 'right', whiteSpace: 'nowrap' }) }, entry.execution_time_ms != null ? entry.execution_time_ms + 'ms' : 'โ'),
|
|
423
|
+
h('td', { style: s.auditTd }, entry.success
|
|
424
|
+
? h('span', { style: Object.assign({}, s.badge, s.badgeActive) }, 'OK')
|
|
425
|
+
: h('span', { style: Object.assign({}, s.badge, s.badgeError) }, 'FAIL')
|
|
426
|
+
),
|
|
427
|
+
),
|
|
428
|
+
// Expanded row detail
|
|
429
|
+
isExpanded && h('tr', null,
|
|
430
|
+
h('td', { colSpan: 8, style: css('padding: 12px 16px; background: var(--bg-secondary); border-bottom: 1px solid var(--border);') },
|
|
431
|
+
h('div', { style: css('display: grid; grid-template-columns: 1fr 1fr; gap: 12px; font-size: 12px;') },
|
|
432
|
+
h('div', null,
|
|
433
|
+
h('div', { style: css('font-weight: 600; margin-bottom: 4px; color: var(--text-muted);') }, 'Full Query'),
|
|
434
|
+
h('pre', { style: css('margin: 0; padding: 8px; background: var(--bg-primary); border-radius: 6px; overflow-x: auto; font-size: 11px; white-space: pre-wrap; word-break: break-all; max-height: 200px;') }, entry.query || 'โ'),
|
|
435
|
+
),
|
|
436
|
+
h('div', null,
|
|
437
|
+
h('div', { style: css('font-weight: 600; margin-bottom: 4px; color: var(--text-muted);') }, 'Details'),
|
|
438
|
+
h('div', { style: css('display: flex; flex-direction: column; gap: 4px;') },
|
|
439
|
+
h('div', null, h('strong', null, 'Agent ID: '), entry.agent_id || 'โ'),
|
|
440
|
+
h('div', null, h('strong', null, 'Connection ID: '), entry.connection_id || 'โ'),
|
|
441
|
+
h('div', null, h('strong', null, 'Rows Affected: '), entry.rows_affected != null ? String(entry.rows_affected) : 'โ'),
|
|
442
|
+
h('div', null, h('strong', null, 'Execution Time: '), entry.execution_time_ms != null ? entry.execution_time_ms + 'ms' : 'โ'),
|
|
443
|
+
h('div', null, h('strong', null, 'IP: '), entry.ip_address || 'โ'),
|
|
444
|
+
!entry.success && entry.error && h('div', { style: css('margin-top: 4px; padding: 6px 8px; background: rgba(239,68,68,0.1); border-radius: 4px; color: var(--danger);') },
|
|
445
|
+
h('strong', null, 'Error: '), entry.error
|
|
446
|
+
),
|
|
447
|
+
),
|
|
448
|
+
),
|
|
449
|
+
),
|
|
450
|
+
),
|
|
451
|
+
),
|
|
452
|
+
);
|
|
453
|
+
})
|
|
454
|
+
),
|
|
346
455
|
),
|
|
347
456
|
),
|
|
457
|
+
|
|
458
|
+
// Pagination
|
|
459
|
+
totalPages > 1 && h('div', { style: css('display: flex; align-items: center; justify-content: center; gap: 8px; margin-top: 16px;') },
|
|
460
|
+
h('button', { style: Object.assign({}, s.btn, { padding: '4px 10px', fontSize: '12px' }), disabled: page === 0, onClick: function() { setPage(0); } }, 'ยซ'),
|
|
461
|
+
h('button', { style: Object.assign({}, s.btn, { padding: '4px 10px', fontSize: '12px' }), disabled: page === 0, onClick: function() { setPage(page - 1); } }, 'โน'),
|
|
462
|
+
h('span', { style: css('font-size: 12px; color: var(--text-secondary);') }, 'Page ' + (page + 1) + ' of ' + totalPages),
|
|
463
|
+
h('button', { style: Object.assign({}, s.btn, { padding: '4px 10px', fontSize: '12px' }), disabled: page >= totalPages - 1, onClick: function() { setPage(page + 1); } }, 'โบ'),
|
|
464
|
+
h('button', { style: Object.assign({}, s.btn, { padding: '4px 10px', fontSize: '12px' }), disabled: page >= totalPages - 1, onClick: function() { setPage(totalPages - 1); } }, 'ยป'),
|
|
465
|
+
),
|
|
348
466
|
);
|
|
349
467
|
}
|
|
350
468
|
|