Remove idle connection timeout handling

Remove error handling for closed connections

Add progress watchdog to detect stalled accounts

Improve error modal styling and pagination
This commit is contained in:
2026-07-05 14:50:25 +07:00
parent 95ddbf5619
commit e84366eb0c
7 changed files with 191 additions and 145 deletions
+59 -33
View File
@@ -3,6 +3,7 @@ import { Modal } from './Modal'
import { listAccountErrors, type AccountError } from '../api'
const fmt = (iso: string) => (iso ? new Date(iso).toLocaleString() : '—')
const PAGE_SIZE = 50
export function AccountErrorsModal({
taskId,
@@ -15,51 +16,76 @@ export function AccountErrorsModal({
}) {
const [errors, setErrors] = useState<AccountError[] | null>(null)
const [failed, setFailed] = useState(false)
const [page, setPage] = useState(0)
const open = account !== null
useEffect(() => {
if (!account) return
setErrors(null)
setFailed(false)
setPage(0)
listAccountErrors(taskId, account.id)
.then((e) => setErrors(e ?? []))
.catch(() => setFailed(true))
}, [taskId, account])
const total = errors?.length ?? 0
const pageCount = Math.max(1, Math.ceil(total / PAGE_SIZE))
const current = Math.min(page, pageCount - 1)
const slice = errors?.slice(current * PAGE_SIZE, current * PAGE_SIZE + PAGE_SIZE) ?? []
const title = account
? `Errors — ${account.src_login}${total ? ` (${total})` : ''}`
: 'Errors'
return (
<Modal open={open} title={account ? `Errors — ${account.src_login}` : 'Errors'} onClose={onClose} size="lg">
<div className="tbl-wrap">
<table className="tbl">
<thead>
<tr>
<th>Time</th>
<th>Kind</th>
<th>Folder</th>
<th>Message</th>
<th>Error</th>
</tr>
</thead>
<tbody>
{failed ? (
<tr className="empty-row"><td colSpan={5}>failed to load errors</td></tr>
) : errors === null ? (
<tr className="empty-row"><td colSpan={5}>loading</td></tr>
) : errors.length === 0 ? (
<tr className="empty-row"><td colSpan={5}>no errors recorded</td></tr>
) : (
errors.map((e) => (
<tr key={e.id}>
<td>{fmt(e.created_at)}</td>
<td>{e.kind}</td>
<td>{e.folder || '—'}</td>
<td>{e.message_ref || '—'}</td>
<td className="err-cell">{e.error}</td>
</tr>
))
)}
</tbody>
</table>
</div>
<Modal open={open} title={title} onClose={onClose} size="lg">
{failed ? (
<div className="err-empty">failed to load errors</div>
) : errors === null ? (
<div className="err-empty">loading</div>
) : total === 0 ? (
<div className="err-empty">no errors recorded</div>
) : (
<>
<ul className="err-list">
{slice.map((e) => (
<li key={e.id} className="err-item">
<div className="err-item-head">
<span className="err-kind">{e.kind}</span>
{e.folder && <span className="err-folder">{e.folder}</span>}
{e.message_ref && <span className="err-ref">{e.message_ref}</span>}
<span className="err-time">{fmt(e.created_at)}</span>
</div>
<div className="err-text">{e.error}</div>
</li>
))}
</ul>
{pageCount > 1 && (
<div className="err-pager">
<button
type="button"
className="btn"
disabled={current === 0}
onClick={() => setPage(current - 1)}
>
prev
</button>
<span className="err-pageinfo">
page {current + 1} / {pageCount}
</span>
<button
type="button"
className="btn"
disabled={current >= pageCount - 1}
onClick={() => setPage(current + 1)}
>
next
</button>
</div>
)}
</>
)}
</Modal>
)
}