// Recent activity view for tester/admin auditing import { api } from './api.js'; import { escHtml, formatDateTime } from './utils.js'; const ACTION_LABELS = { adobe_connected: 'Adobe connected', adobe_disconnected: 'Adobe disconnected', docusign_authorization_requested: 'DocuSign auth requested', docusign_authorization_started: 'DocuSign auth started', docusign_connected: 'DocuSign connected', docusign_account_selected: 'DocuSign account selected', docusign_disconnected: 'DocuSign disconnected', migration_run: 'Migration run', migration_batch_started: 'Batch migration started', migration_batch_completed: 'Batch migration completed', verification_sent: 'Verification sent', verification_voided: 'Verification voided', }; export async function renderActivity() { const outlet = document.getElementById('router-outlet'); outlet.innerHTML = `
`; try { const data = await api.audit.recent(150); const events = data.events || []; outlet.innerHTML = ` ${events.length === 0 ? `
๐Ÿงพ
No activity yet
Recent tester actions will appear here after people connect and use the app.
` : `
${events.map(renderEventRow).join('')}
Time Action DocuSign Adobe Session IP Details
`} `; } catch (e) { outlet.innerHTML = `
โŒFailed to load activity: ${escHtml(e.message)}
`; } } function renderEventRow(event) { const docusignLabel = event.docusign_account_name || event.docusign_user_name || event.docusign_user_email || 'โ€”'; const adobeLabel = event.adobe_account_name || event.adobe_user_name || event.adobe_user_email || 'โ€”'; const sessionId = event.session_id ? `${event.session_id.slice(0, 10)}โ€ฆ` : 'โ€”'; const detailText = formatDetails(event.details); return ` ${escHtml(formatDateTime(event.timestamp))} ${escHtml(ACTION_LABELS[event.action] || event.action || 'Activity')}
${escHtml(docusignLabel)}
${escHtml(event.docusign_account_id || event.docusign_user_email || '')}
${escHtml(adobeLabel)}
${escHtml(event.adobe_account_id || event.adobe_user_email || '')}
${escHtml(sessionId)} ${escHtml(event.ip || 'โ€”')} ${escHtml(detailText)} `; } function formatDetails(details) { if (!details || typeof details !== 'object') { return 'โ€”'; } const parts = Object.entries(details) .filter(([, value]) => value !== null && value !== undefined && value !== '') .map(([key, value]) => `${humanizeKey(key)}: ${formatValue(value)}`); return parts.length ? parts.join(' | ') : 'โ€”'; } function humanizeKey(key) { return key.replace(/_/g, ' '); } function formatValue(value) { if (typeof value === 'boolean') { return value ? 'yes' : 'no'; } return String(value); }