// Home — recent activity feed pulled from the audit log. import { api } from '../api.js'; import { el, mount } from '../dom.js'; const ROUTE_BY_TYPE = { space: id => '#/space/' + id, project: id => '#/project/' + id, task: () => '#/', // tasks list inside their project — no detail view yet page: id => '#/page/' + id, ref: id => '#/ref/' + id, resource: id => '#/resource/' + id, source_doc: () => '#/', conversation: () => '#/' }; const ACTION_VERB = { create: 'created', update: 'updated', delete: 'deleted', suggest: 'suggested', approve: 'approved', reject: 'rejected' }; function actorLabel(row) { if (row.actor_kind === 'user') return 'You'; if (row.actor_kind === 'agent') return 'Agent ' + (row.actor_id || '').slice(0, 8); return row.actor_kind; } function fmtWhen(ts) { const d = new Date(ts); const diff = (Date.now() - d.getTime()) / 1000; if (diff < 60) return Math.round(diff) + 's ago'; if (diff < 3600) return Math.round(diff / 60) + 'm ago'; if (diff < 86400) return Math.round(diff / 3600) + 'h ago'; return d.toISOString().slice(0, 10); } function activityRow(row) { const route = ROUTE_BY_TYPE[row.entity_type]; const link = route && row.entity_id ? route(row.entity_id) : null; return el('li', {}, el('span', { class: 'muted' }, fmtWhen(row.occurred_at) + ' — '), actorLabel(row), ' ', ACTION_VERB[row.action] || row.action, ' ', link ? el('a', { href: link }, row.entity_type) : el('span', {}, row.entity_type) ); } export async function render(main) { mount(main, el('h1', { class: 'view-h1' }, 'The Void'), el('p', { class: 'view-sub' }, 'Recent activity across all spaces.'), el('div', { class: 'card' }, el('h3', {}, 'Recent activity'), el('div', { id: 'home-activity' }, el('span', { class: 'muted' }, 'Loading …')) ) ); try { const rows = await api.get('/api/audit/actor?limit=20'); const wrap = document.getElementById('home-activity'); if (!wrap) return; if (!rows.length) { mount(wrap, el('span', { class: 'muted' }, 'Nothing yet — create a space to begin.')); return; } mount(wrap, el('ul', { class: 'plain' }, rows.map(activityRow))); } catch (e) { const wrap = document.getElementById('home-activity'); if (wrap) mount(wrap, el('span', { class: 'muted' }, 'Could not load activity: ' + e.message)); } }