mirror of
https://github.com/thegeneralist01/archivr
synced 2026-07-21 18:55:36 +02:00
feat: non-blocking batch capture dialog, toasts on failure, fix /runs errors
CaptureDialog:
- Replace single textarea with multi-row inputs; + button adds rows
- Submit fires all pending rows in parallel, dialog stays open/usable
- Polling intervals live on a persistent ref (not cleared on close) so
toasts fire even after the dialog is dismissed
- archiveId stored per item at submit time; page-refresh reconnect uses
it.archiveId instead of the possibly-null prop
- Completed rows flash green then self-remove; failed rows show inline
error + retry button
- Cancel becomes Close while jobs are in flight
ToastStack (new component):
- Fixed bottom-right overlay with spring-in animation
- Error toast: truncated locator, View error / Hide toggle expanding
full error_text in a monospace pre block
- Auto-dismisses after 7 s; timer pauses while detail is expanded
RunsView:
- Failed rows are clickable and expand a full-width detail row showing
error_summary in a scrollable monospace block
capture.rs (archivr-core):
- Staging dir is now "{millis}-{uuid}" — parallel captures in the same
millisecond can no longer collide on temp paths
- create_archive_run moved before URL Content-Type probe so every
attempt appears in /runs regardless of outcome
- Probe failures now call create_archive_run_item with source_metadata
fallback then fail_run, recording error_text on the item and
error_summary on the run with correct failed_count
styles.css:
- Capture dialog: header row, multi-row layout, status dots, spinner,
add-row dashed button, per-row error text
- Toast stack: fixed overlay, error card with coloured left border,
monospace detail expansion
- Run error rows: clickable hover tint, expand hint chevron, detail pre
This commit is contained in:
parent
d83faab8e6
commit
fb1115a409
11 changed files with 698 additions and 223 deletions
63
frontend/src/components/ToastStack.jsx
Normal file
63
frontend/src/components/ToastStack.jsx
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import { useState, useEffect } from 'react'
|
||||
|
||||
const TOAST_TTL = 7000 // ms before auto-dismiss; paused when error is expanded
|
||||
|
||||
export default function ToastStack({ toasts, onDismiss }) {
|
||||
if (!toasts.length) return null
|
||||
return (
|
||||
<div className="toast-stack" role="log" aria-live="polite" aria-label="Notifications">
|
||||
{toasts.map(t => (
|
||||
<Toast key={t.id} toast={t} onDismiss={onDismiss} />
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function Toast({ toast, onDismiss }) {
|
||||
const [expanded, setExpanded] = useState(false)
|
||||
|
||||
// Auto-dismiss after TTL; paused while error detail is expanded
|
||||
useEffect(() => {
|
||||
if (expanded) return
|
||||
const timer = setTimeout(() => onDismiss(toast.id), TOAST_TTL)
|
||||
return () => clearTimeout(timer)
|
||||
}, [expanded, toast.id, onDismiss])
|
||||
|
||||
const short = toast.locator
|
||||
? (toast.locator.length > 48 ? toast.locator.slice(0, 45) + '\u2026' : toast.locator)
|
||||
: null
|
||||
|
||||
return (
|
||||
<div className="toast toast--error" role="alert" aria-atomic="true">
|
||||
<div className="toast-top">
|
||||
<span className="toast-icon" aria-hidden="true">✕</span>
|
||||
<div className="toast-body">
|
||||
<span className="toast-headline">Capture failed</span>
|
||||
{short && <span className="toast-locator">{short}</span>}
|
||||
</div>
|
||||
<div className="toast-btns">
|
||||
{toast.errorText && (
|
||||
<button
|
||||
type="button"
|
||||
className="toast-view-btn"
|
||||
onClick={() => setExpanded(v => !v)}
|
||||
>
|
||||
{expanded ? 'Hide' : 'View error'}
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
className="toast-dismiss"
|
||||
onClick={() => onDismiss(toast.id)}
|
||||
aria-label="Dismiss"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{expanded && toast.errorText && (
|
||||
<pre className="toast-error-detail">{toast.errorText}</pre>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue