import React, { useEffect, useState, useRef, useCallback } from 'react'; import { useApiRequest } from '../../hooks/useApi'; import { useLanguage } from '../../providers/language/LanguageContext'; import styles from './RagRunningBadge.module.css'; interface _RagJob { jobId: string; connectionId: string; connectionLabel?: string; jobType: string; progress: number | null; progressMessage: string; } const _POLL_INTERVAL_ACTIVE_MS = 5_000; const _POLL_INTERVAL_IDLE_MS = 60_000; const _DONE_TOAST_MS = 4_000; export const RagRunningBadge: React.FC = () => { const { t } = useLanguage(); const { request } = useApiRequest(); const [jobs, setJobs] = useState<_RagJob[]>([]); const [justFinished, setJustFinished] = useState(false); const [expanded, setExpanded] = useState(false); const timerRef = useRef | null>(null); const previousJobCount = useRef(0); const toastTimerRef = useRef | null>(null); const _fetchJobs = useCallback(async () => { try { const result = await request({ url: '/api/rag/inventory/jobs', method: 'get' }); const list = Array.isArray(result) ? (result as _RagJob[]) : []; // Detect "all running jobs just completed" → flash a brief success toast // so the user gets visible confirmation that the work actually finished // instead of the spinner just silently disappearing. if (previousJobCount.current > 0 && list.length === 0) { setJustFinished(true); if (toastTimerRef.current) clearTimeout(toastTimerRef.current); toastTimerRef.current = setTimeout(() => setJustFinished(false), _DONE_TOAST_MS); } previousJobCount.current = list.length; setJobs(list); } catch { setJobs([]); } }, [request]); useEffect(() => { _fetchJobs(); }, [_fetchJobs]); useEffect(() => { if (timerRef.current) clearInterval(timerRef.current); const interval = jobs.length > 0 ? _POLL_INTERVAL_ACTIVE_MS : _POLL_INTERVAL_IDLE_MS; timerRef.current = setInterval(_fetchJobs, interval); return () => { if (timerRef.current) clearInterval(timerRef.current); }; }, [_fetchJobs, jobs.length]); useEffect(() => { return () => { if (toastTimerRef.current) clearTimeout(toastTimerRef.current); }; }, []); if (jobs.length === 0 && !justFinished) return null; if (jobs.length === 0 && justFinished) { return (
{t('Sync abgeschlossen')}
); } return (
{expanded && (
{t('Aktive RAG-Jobs')}
{jobs.map(job => (
{job.connectionLabel || job.jobType} {job.progressMessage || t('läuft...')}
))}
)}
); };