import React, { useEffect, useState } from 'react' import { useParams, Link } from 'react-router-dom' interface Daemon { id: string ownerId: string connectionId: string hostname: string | null machineId: string | null maxConcurrentTasks: number currentTaskCount: number status: string lastHeartbeatAt: string connectedAt: string disconnectedAt: string | null } interface DaemonDirectory { path: string label: string directoryType: string hostname: string | null exists?: boolean } type Tab = 'overview' | 'directories' function statusIndicator(status: string): { color: string; label: string } { switch (status.toLowerCase()) { case 'connected': return { color: 'green', label: 'Connected' } case 'disconnected': return { color: 'red', label: 'Disconnected' } case 'unhealthy': return { color: 'yellow', label: 'Unhealthy' } default: return { color: 'gray', label: status } } } export function DaemonDetail() { const { id } = useParams<{ id: string }>() const [daemon, setDaemon] = useState(null) const [directories, setDirectories] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [activeTab, setActiveTab] = useState('overview') useEffect(() => { async function fetchDaemon() { if (!id) return try { setLoading(true) const [daemonRes, dirRes] = await Promise.all([ fetch(`/api/v1/mesh/daemons/${id}`), fetch('/api/v1/mesh/daemons/directories'), ]) if (!daemonRes.ok) { throw new Error(`Failed to fetch daemon: ${daemonRes.statusText}`) } const daemonData = await daemonRes.json() setDaemon(daemonData) if (dirRes.ok) { const dirData = await dirRes.json() setDirectories(dirData.directories || []) } } catch (err) { setError(err instanceof Error ? err.message : 'Unknown error') } finally { setLoading(false) } } fetchDaemon() const interval = setInterval(async () => { if (!id) return try { const response = await fetch(`/api/v1/mesh/daemons/${id}`) if (response.ok) { const daemonData = await response.json() setDaemon(daemonData) } } catch { // Silently ignore refresh errors } }, 10000) return () => clearInterval(interval) }, [id]) if (loading) { return (
Loading daemon...
) } if (error) { return (
Error: {error}
Back to Daemons
) } if (!daemon) { return (
Daemon not found
Back to Daemons
) } const status = statusIndicator(daemon.status) const filteredDirectories = directories.filter( (dir) => dir.hostname === daemon.hostname ) return (
Back to Daemons

{daemon.hostname || 'Unknown Host'}

{status.label} Tasks: {daemon.currentTaskCount} / {daemon.maxConcurrentTasks}
{activeTab === 'overview' && (

Daemon Overview

ID
{daemon.id}
Hostname
{daemon.hostname || 'N/A'}
Machine ID
{daemon.machineId || 'N/A'}
Status
{status.label}
Connection ID
{daemon.connectionId}
Max Concurrent Tasks
{daemon.maxConcurrentTasks}
Current Task Count
{daemon.currentTaskCount}
Connected At
{new Date(daemon.connectedAt).toLocaleString()}
Last Heartbeat At
{new Date(daemon.lastHeartbeatAt).toLocaleString()}
Disconnected At
{daemon.disconnectedAt ? new Date(daemon.disconnectedAt).toLocaleString() : 'N/A'}
)} {activeTab === 'directories' && (

Directories

{filteredDirectories.length === 0 ? (

No directories found for this daemon

) : (
    {filteredDirectories.map((dir, index) => (
  • {dir.label}

    Path: {dir.path} Type: {dir.directoryType}
  • ))}
)}
)}
) }