paperless-ngx/src-ui/src/app/services/ai-status.service.ts
Claude 3c8a1c9c66
fix(frontend): corrige manejo de errores en componentes de IA
Cambios realizados:

1. ai-status.service.ts:
   - Importa 'of' desde 'rxjs' para retornar Observables correctamente
   - Corrige catchError que retornaba array [] en lugar de Observable
   - Ahora retorna of({...}) con valores por defecto cuando falla el endpoint
   - Estadísticas ahora muestran 0 en lugar de valores mock cuando hay error

2. ai-suggestions-panel.component.ts:
   - Importa 'of' y 'catchError' desde 'rxjs/operators'
   - Agrega catchError a TODAS las llamadas de servicios (tags, correspondents, etc.)
   - Cada llamada ahora maneja errores y retorna array vacío en caso de fallo
   - Previene que errores de red rompan la funcionalidad del panel
   - Agrega logging de errores para debugging

Estos cambios corrigen:
- ✓ Estadísticas mostrando 0 incorrectamente
- ✓ Errores no manejados en llamadas HTTP
- ✓ Fallos al cargar metadata de sugerencias
- ✓ Panel de sugerencias fallando silenciosamente
2025-11-17 22:51:40 +00:00

110 lines
2.7 KiB
TypeScript

import { HttpClient } from '@angular/common/http'
import { Injectable, inject } from '@angular/core'
import { BehaviorSubject, Observable, interval, Subscription, of } from 'rxjs'
import { catchError, map, startWith, switchMap } from 'rxjs/operators'
import { AIStatus } from 'src/app/data/ai-status'
import { environment } from 'src/environments/environment'
@Injectable({
providedIn: 'root',
})
export class AIStatusService {
private http = inject(HttpClient)
private baseUrl: string = environment.apiBaseUrl
private aiStatusSubject = new BehaviorSubject<AIStatus>({
active: false,
processing: false,
documents_scanned_today: 0,
suggestions_applied: 0,
pending_deletion_requests: 0,
})
public loading: boolean = false
private pollingSubscription?: Subscription
// Poll every 30 seconds for AI status updates
private readonly POLL_INTERVAL = 30000
constructor() {
// Polling is now controlled manually via startPolling()
}
/**
* Get the current AI status as an observable
*/
public getStatus(): Observable<AIStatus> {
return this.aiStatusSubject.asObservable()
}
/**
* Get the current AI status value
*/
public getCurrentStatus(): AIStatus {
return this.aiStatusSubject.value
}
/**
* Start polling for AI status updates
*/
public startPolling(): void {
if (this.pollingSubscription) {
return // Already running
}
this.pollingSubscription = interval(this.POLL_INTERVAL)
.pipe(
startWith(0), // Emit immediately on subscription
switchMap(() => this.fetchAIStatus())
)
.subscribe((status) => {
this.aiStatusSubject.next(status)
})
}
/**
* Stop polling for AI status updates
*/
public stopPolling(): void {
if (this.pollingSubscription) {
this.pollingSubscription.unsubscribe()
this.pollingSubscription = undefined
}
}
/**
* Fetch AI status from the backend
*/
private fetchAIStatus(): Observable<AIStatus> {
this.loading = true
return this.http
.get<AIStatus>(`${this.baseUrl}ai/status/`)
.pipe(
map((status) => {
this.loading = false
return status
}),
catchError((error) => {
this.loading = false
console.warn('Failed to fetch AI status:', error)
// Return default status if endpoint fails
return of({
active: false,
processing: false,
documents_scanned_today: 0,
suggestions_applied: 0,
pending_deletion_requests: 0,
})
})
)
}
/**
* Manually refresh the AI status
*/
public refresh(): void {
this.fetchAIStatus().subscribe((status) => {
this.aiStatusSubject.next(status)
})
}
}