flare / flare-ui /src /app /services /error-handler.service.ts
ciyidogan's picture
Rename flare-ui/src/app/services/error-handler-service.ts to flare-ui/src/app/services/error-handler.service.ts
f294f56 verified
raw
history blame
5.6 kB
// error-handler.service.ts (YENİ DOSYA)
// Path: /flare-ui/src/app/services/error-handler.service.ts
import { ErrorHandler, Injectable, Injector } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Router } from '@angular/router';
import { HttpErrorResponse } from '@angular/common/http';
interface FlareError {
error: string;
message: string;
details?: any;
request_id?: string;
timestamp?: string;
user_action?: string;
}
@Injectable({
providedIn: 'root'
})
export class GlobalErrorHandler implements ErrorHandler {
constructor(private injector: Injector) {}
handleError(error: Error | HttpErrorResponse): void {
// Get services lazily to avoid circular dependency
const snackBar = this.injector.get(MatSnackBar);
const router = this.injector.get(Router);
console.error('Global error caught:', error);
// Handle HTTP errors
if (error instanceof HttpErrorResponse) {
this.handleHttpError(error, snackBar, router);
} else {
// Handle client-side errors
this.handleClientError(error, snackBar);
}
}
private handleHttpError(error: HttpErrorResponse, snackBar: MatSnackBar, router: Router): void {
const flareError = error.error as FlareError;
// Race condition error (409)
if (error.status === 409 && flareError.error === 'RaceConditionError') {
const snackBarRef = snackBar.open(
flareError.message || 'The data was modified by another user. Please refresh and try again.',
'Refresh',
{
duration: 0,
panelClass: ['error-snackbar', 'race-condition-snackbar']
}
);
snackBarRef.onAction().subscribe(() => {
window.location.reload();
});
// Show additional info if available
if (flareError.details?.last_update_user) {
console.info(`Last updated by: ${flareError.details.last_update_user} at ${flareError.details.last_update_date}`);
}
return;
}
// Authentication error (401)
if (error.status === 401) {
snackBar.open(
'Your session has expired. Please login again.',
'Login',
{
duration: 5000,
panelClass: ['error-snackbar']
}
).onAction().subscribe(() => {
router.navigate(['/login']);
});
return;
}
// Validation error (422)
if (error.status === 422 && flareError.details) {
const fieldErrors = flareError.details
.map((d: any) => `${d.field}: ${d.message}`)
.join('\n');
snackBar.open(
flareError.message || 'Validation failed. Please check your input.',
'Close',
{
duration: 8000,
panelClass: ['error-snackbar', 'validation-snackbar']
}
);
console.error('Validation errors:', flareError.details);
return;
}
// Not found error (404)
if (error.status === 404) {
snackBar.open(
flareError.message || 'The requested resource was not found.',
'Close',
{
duration: 5000,
panelClass: ['error-snackbar']
}
);
return;
}
// Server errors (5xx)
if (error.status >= 500) {
const message = flareError.message || 'A server error occurred. Please try again later.';
const requestId = flareError.request_id;
snackBar.open(
requestId ? `${message} (Request ID: ${requestId})` : message,
'Close',
{
duration: 8000,
panelClass: ['error-snackbar', 'server-error-snackbar']
}
);
return;
}
// Generic HTTP error
snackBar.open(
flareError.message || `HTTP Error ${error.status}: ${error.statusText}`,
'Close',
{
duration: 6000,
panelClass: ['error-snackbar']
}
);
}
private handleClientError(error: Error, snackBar: MatSnackBar): void {
// Check if it's a network error
if (error.message.includes('NetworkError') || error.message.includes('Failed to fetch')) {
snackBar.open(
'Network connection error. Please check your internet connection.',
'Retry',
{
duration: 0,
panelClass: ['error-snackbar', 'network-error-snackbar']
}
).onAction().subscribe(() => {
window.location.reload();
});
return;
}
// Generic client error
snackBar.open(
'An unexpected error occurred. Please refresh the page.',
'Refresh',
{
duration: 6000,
panelClass: ['error-snackbar']
}
).onAction().subscribe(() => {
window.location.reload();
});
}
}
// Error interceptor for consistent error format
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).pipe(
catchError((error: HttpErrorResponse) => {
// Log request details for debugging
console.error('HTTP Error:', {
url: req.url,
method: req.method,
status: error.status,
error: error.error,
requestId: error.headers.get('X-Request-ID')
});
// Re-throw to be handled by global error handler
return throwError(() => error);
})
);
}
}