feat: delete task/account, edit endpoint, richer event log
- store: DeleteAccount, DeleteTask, UpdateEndpoint (+ cascade/update tests)
- httpapi: DELETE /tasks/{id}, DELETE /tasks/{id}/accounts/{accountId},
PUT /endpoints/{id}; delete guarded with 409 while task running
- orchestrator: enrich WS events with login/host/port/error (test + run + errors)
- web: delete buttons (task, account) with confirm, endpoint edit form,
human-readable event log (source/dest, host:port, error text)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MMHQTtnQtQqL8muAXHr9kd
This commit is contained in:
+25
-3
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useState, type FormEvent } from 'react'
|
||||
import { createTask, listEndpoints, listTasks, type Endpoint, type Task } from '../api'
|
||||
import { createTask, deleteTask, listEndpoints, listTasks, type Endpoint, type Task } from '../api'
|
||||
import { StatusBadge } from '../components/StatusBadge'
|
||||
|
||||
export function Tasks() {
|
||||
@@ -22,6 +22,17 @@ export function Tasks() {
|
||||
listEndpoints().then((e) => setEndpoints(e ?? [])).catch(() => {})
|
||||
}, [])
|
||||
|
||||
async function onDeleteTask(id: number, taskName: string) {
|
||||
if (!confirm(`Delete task "${taskName}" and all its accounts?`)) return
|
||||
setError(null)
|
||||
try {
|
||||
await deleteTask(id)
|
||||
reload()
|
||||
} catch (e: unknown) {
|
||||
setError(e instanceof Error ? e.message : 'Failed to delete task')
|
||||
}
|
||||
}
|
||||
|
||||
async function submit(e: FormEvent) {
|
||||
e.preventDefault()
|
||||
setBusy(true)
|
||||
@@ -118,16 +129,17 @@ export function Tasks() {
|
||||
<th>Name</th>
|
||||
<th>Route</th>
|
||||
<th>Status</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{tasks === null ? (
|
||||
<tr className="empty-row">
|
||||
<td colSpan={4}>loading…</td>
|
||||
<td colSpan={5}>loading…</td>
|
||||
</tr>
|
||||
) : tasks.length === 0 ? (
|
||||
<tr className="empty-row">
|
||||
<td colSpan={4}>no tasks yet — create one above</td>
|
||||
<td colSpan={5}>no tasks yet — create one above</td>
|
||||
</tr>
|
||||
) : (
|
||||
tasks.map((t) => (
|
||||
@@ -144,6 +156,16 @@ export function Tasks() {
|
||||
<td>
|
||||
<StatusBadge status={t.status} />
|
||||
</td>
|
||||
<td className="num-cell">
|
||||
<button
|
||||
type="button"
|
||||
className="link-btn danger"
|
||||
onClick={() => onDeleteTask(t.id, t.name)}
|
||||
disabled={t.status === 'running'}
|
||||
>
|
||||
delete
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user