1import React from "react";
2import { apiFetch } from "../../lib/api";
4export default function TabTasks({ agentId }) {
5 const [processes, setProcesses] = React.useState([]);
6 const [loading, setLoading] = React.useState(true);
7 const [error, setError] = React.useState(null);
8 const [autoRefresh, setAutoRefresh] = React.useState(true);
10 function loadProcesses() {
13 apiFetch(`/agent/${agentId}/processes`)
14 .then((d) => setProcesses(d))
15 .catch((err) => setError(err.message))
16 .finally(() => setLoading(false));
19 React.useEffect(() => {
22 if (autoRefresh && agentId) {
23 interval = setInterval(() => loadProcesses(), 5000);
25 return () => interval && clearInterval(interval);
26 }, [agentId, autoRefresh]);
30 apiFetch(`/agent/${agentId}/process/${pid}/kill`, { method: "POST" })
34 if (loading) return <div className="card">Loading processes...</div>;
35 if (error) return <div className="card error">{error}</div>;
37 // Defensive: ensure processes is an array
38 if (!Array.isArray(processes)) {
40 <div className="tab-container">
41 <h2>Process Manager</h2>
42 <div className="card error">Process data is not available or invalid.</div>
47 // Show empty state if no processes
48 if (processes.length === 0) {
50 <div className="tab-container">
51 <h2>Process Manager</h2>
52 <div className="card controls">
57 onChange={(e) => setAutoRefresh(e.target.checked)}
61 <button className="btn-sm" onClick={loadProcesses}>Refresh Now</button>
63 <div className="card">
64 <p>No process data available yet. Process list updates every 5 seconds when the agent is connected.</p>
71 <div className="tab-container">
72 <h2>Process Manager</h2>
73 <div className="card controls">
78 onChange={(e) => setAutoRefresh(e.target.checked)}
82 <button className="btn-sm" onClick={loadProcesses}>Refresh Now</button>
84 <div className="card process-table">
85 <div className="table-header">
92 {processes.map((p) => (
93 <div key={p.pid} className="table-row">
99 <button className="btn-danger-sm" onClick={() => kill(p.pid)}>