feat: detailed embed progress — current section, global bar, queue display
- Backend: tracks current_table, current_inserted, current_total, queue per embed task - Frontend: dual progress bars (section + global), queue of upcoming sections - Section bar shows table name + individual progress - Global bar shows inserted/skipped/total with green/red segments - Queue shows remaining sections with doc counts
This commit is contained in:
@@ -585,7 +585,11 @@ export default function ReportsPage() {
|
||||
const setEmbedTaskId = store.setRptEmbedTaskId;
|
||||
const [embedLoading, setEmbedLoading] = useState('');
|
||||
const [embedMsg, setEmbedMsg] = useState<{ type: 's' | 'e'; text: string } | null>(null);
|
||||
const [embedProgress, setEmbedProgress] = useState<{ inserted: number; skipped: number; processed: number; total: number } | null>(null);
|
||||
const [embedProgress, setEmbedProgress] = useState<{
|
||||
inserted: number; skipped: number; processed: number; total: number;
|
||||
currentTable?: string; currentInserted?: number; currentTotal?: number; currentSkipped?: number;
|
||||
queue?: { table: string; docs: number }[];
|
||||
} | null>(null);
|
||||
|
||||
/* ── HTML iframe (from store) ── */
|
||||
const showIframe = store.rptShowIframe;
|
||||
@@ -797,7 +801,14 @@ export default function ReportsPage() {
|
||||
const processed = (data.processed as number) || inserted;
|
||||
|
||||
if (total > 0) {
|
||||
setEmbedProgress({ inserted, skipped, processed, total });
|
||||
setEmbedProgress({
|
||||
inserted, skipped, processed, total,
|
||||
currentTable: (data.current_table as string) || undefined,
|
||||
currentInserted: (data.current_inserted as number) || 0,
|
||||
currentTotal: (data.current_total as number) || 0,
|
||||
currentSkipped: (data.current_skipped as number) || 0,
|
||||
queue: (data.queue as { table: string; docs: number }[]) || [],
|
||||
});
|
||||
}
|
||||
|
||||
if (s.status === 'done') {
|
||||
@@ -1491,29 +1502,51 @@ export default function ReportsPage() {
|
||||
|
||||
{/* Embed progress + message */}
|
||||
{embedProgress && embedProgress.total > 0 && (() => {
|
||||
const pct = Math.round((embedProgress.processed / embedProgress.total) * 100);
|
||||
const globalPct = Math.round((embedProgress.processed / embedProgress.total) * 100);
|
||||
const okPct = Math.round((embedProgress.inserted / embedProgress.total) * 100);
|
||||
const failPct = Math.round((embedProgress.skipped / embedProgress.total) * 100);
|
||||
const ct = embedProgress.currentTable;
|
||||
const ci = embedProgress.currentInserted || 0;
|
||||
const cTotal = embedProgress.currentTotal || 0;
|
||||
const cPct = cTotal > 0 ? Math.round((ci / cTotal) * 100) : 0;
|
||||
const queue = embedProgress.queue || [];
|
||||
return (
|
||||
<div className="mx-5 mt-3">
|
||||
<div className="flex items-center justify-between mb-1">
|
||||
<span className="text-[.65rem] font-medium" style={{ color: 'var(--t2)' }}>
|
||||
{embedProgress.inserted} OK
|
||||
{embedProgress.skipped > 0 && <span style={{ color: 'var(--rd)' }}> / {embedProgress.skipped} falhas</span>}
|
||||
{' '}({embedProgress.processed}/{embedProgress.total})
|
||||
</span>
|
||||
<span className="text-[.65rem] font-bold" style={{ color: embedProgress.skipped > 0 ? 'var(--yl)' : 'var(--gn)' }}>
|
||||
{pct}%
|
||||
</span>
|
||||
</div>
|
||||
<div className="w-full h-2 rounded-full overflow-hidden flex" style={{ background: 'var(--bg2)' }}>
|
||||
{okPct > 0 && (
|
||||
<div className="h-full transition-all duration-500" style={{ width: `${okPct}%`, background: 'var(--gn)' }} />
|
||||
)}
|
||||
{failPct > 0 && (
|
||||
<div className="h-full transition-all duration-500" style={{ width: `${failPct}%`, background: 'var(--rd)' }} />
|
||||
)}
|
||||
<div className="mx-5 mt-3 flex flex-col gap-2">
|
||||
{/* Current section */}
|
||||
{ct && (
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-1">
|
||||
<span className="text-[.65rem] font-semibold" style={{ color: 'var(--t1)' }}>
|
||||
{ct} <span style={{ color: 'var(--t4)', fontWeight: 400 }}>({ci}/{cTotal})</span>
|
||||
</span>
|
||||
<span className="text-[.65rem] font-bold" style={{ color: 'var(--ac)' }}>{cPct}%</span>
|
||||
</div>
|
||||
<div className="w-full h-1.5 rounded-full overflow-hidden" style={{ background: 'var(--bg2)' }}>
|
||||
<div className="h-full rounded-full transition-all duration-500" style={{ width: `${cPct}%`, background: 'var(--ac)' }} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{/* Global progress */}
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-1">
|
||||
<span className="text-[.6rem] font-medium" style={{ color: 'var(--t3)' }}>
|
||||
Global: {embedProgress.inserted} OK
|
||||
{embedProgress.skipped > 0 && <span style={{ color: 'var(--rd)' }}> / {embedProgress.skipped} falhas</span>}
|
||||
{' '}({embedProgress.processed}/{embedProgress.total})
|
||||
</span>
|
||||
<span className="text-[.6rem] font-bold" style={{ color: embedProgress.skipped > 0 ? 'var(--yl)' : 'var(--gn)' }}>{globalPct}%</span>
|
||||
</div>
|
||||
<div className="w-full h-1.5 rounded-full overflow-hidden flex" style={{ background: 'var(--bg2)' }}>
|
||||
{okPct > 0 && <div className="h-full transition-all duration-500" style={{ width: `${okPct}%`, background: 'var(--gn)' }} />}
|
||||
{failPct > 0 && <div className="h-full transition-all duration-500" style={{ width: `${failPct}%`, background: 'var(--rd)' }} />}
|
||||
</div>
|
||||
</div>
|
||||
{/* Queue */}
|
||||
{queue.length > 0 && (
|
||||
<div className="text-[.58rem]" style={{ color: 'var(--t4)' }}>
|
||||
Fila: {queue.map((q) => `${q.table} (${q.docs})`).join(' → ')}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})()}
|
||||
|
||||
Reference in New Issue
Block a user