Complete implementation across all 13 phases: - vault-core: types, YAML frontmatter parsing, entity classification, filesystem ops, config, prompt composition, validation, search - vault-watch: filesystem watcher with daemon write filtering, event classification - vault-scheduler: cron engine, process executor, task runner with retry logic and concurrency limiting - vault-api: Axum REST API (15 route modules), WebSocket with broadcast, AI assistant proxy, validation, templates - Dashboard: React + TypeScript + Tailwind v4 with kanban, CodeMirror editor, dynamic view system, AI chat sidebar - Nix flake with dev shell and NixOS module - Graceful shutdown, inotify overflow recovery, tracing instrumentation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
39 lines
1.3 KiB
TypeScript
39 lines
1.3 KiB
TypeScript
import { useActivity } from '../hooks/useApi';
|
|
|
|
export function ActivityFeed() {
|
|
const { data: activity, isLoading } = useActivity();
|
|
|
|
if (isLoading) return <div className="p-4 text-sm text-text-muted">Loading...</div>;
|
|
if (!activity?.length) return <div className="p-4 text-sm text-text-muted">No recent activity</div>;
|
|
|
|
return (
|
|
<div className="space-y-1">
|
|
{activity.slice(0, 20).map((item, i) => (
|
|
<div key={i} className="flex items-center gap-2 px-4 py-1.5 text-xs">
|
|
<span className={`h-1.5 w-1.5 rounded-full ${kindColor(item.kind)}`} />
|
|
<span className="flex-1 truncate text-text-secondary">{item.name}</span>
|
|
<span className="text-text-muted">{timeAgo(item.modified)}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function kindColor(kind: string): string {
|
|
switch (kind) {
|
|
case 'human_task': return 'bg-accent';
|
|
case 'agent_task': return 'bg-warning';
|
|
case 'knowledge': return 'bg-success';
|
|
default: return 'bg-text-muted';
|
|
}
|
|
}
|
|
|
|
function timeAgo(iso: string): string {
|
|
const ms = Date.now() - new Date(iso).getTime();
|
|
const mins = Math.floor(ms / 60000);
|
|
if (mins < 1) return 'now';
|
|
if (mins < 60) return `${mins}m`;
|
|
const hrs = Math.floor(mins / 60);
|
|
if (hrs < 24) return `${hrs}h`;
|
|
return `${Math.floor(hrs / 24)}d`;
|
|
}
|