import { History, RefreshCw } from 'lucide-react' import { useTranslation } from '../../i18n' import { Tooltip } from '../shared/Tooltip' import { fs } from '../shared/DialogShell' import { SettingsCard, SettingsHint, SETTINGS_ICON_BUTTON } from './settingsKit' import { usePluginActivity } from './usePluginActivity' /** * Tailwind classes for a result-code pill. "ok" stays neutral; an access denial * reads as danger, anything else non-ok as a softer warning. Kept subtle — this * is meant to be a quiet log, not an alert wall. */ function codeTone(code: string): string { if (code === 'ok') return 'bg-surface-hover text-content-secondary' if (/FORBIDDEN|DENIED|UNAUTHORIZED/i.test(code)) return 'bg-danger-soft text-danger' return 'bg-warning-soft text-warning' } const TH = 'whitespace-nowrap px-3 py-2.5 text-start font-geist font-bold uppercase tracking-[.08em] text-content-faint' const TD = 'px-3 py-3 align-middle' /** * The signed-in user's own plugin activity log — every host-mediated action a * plugin took while bound to them, newest first. The user-facing half of the * capability audit; it's what keeps the deliberately broad read grants * accountable to the person whose data was read. Fail-safe: a failed load just * shows the empty state, never a crash. */ export default function PluginActivityPanel() { const { t } = useTranslation() const { rows, loading, load, fmtWhen } = usePluginActivity() const refreshLabel = t('settings.pluginActivity.refresh') return ( } > {rows.length === 0 ? ( {loading ? t('common.loading') : t('settings.pluginActivity.empty')} ) : (
{rows.map((r, i) => ( ))}
{t('settings.pluginActivity.columns.plugin')} {t('settings.pluginActivity.columns.action')} {t('settings.pluginActivity.columns.resource')} {t('settings.pluginActivity.columns.when')} {t('settings.pluginActivity.columns.status')}
{r.plugin_name || r.plugin_id} {r.method} {r.resource || '—'} {fmtWhen(r.ts)} {r.code}
)}
) }