Skip to content

Commit

Permalink
Merge pull request #827 from gisaia/fix/appErrorHandling
Browse files Browse the repository at this point in the history
feat: add popup on 400 and 404 errors
  • Loading branch information
QuCMGisaia authored Jan 6, 2025
2 parents bca3e42 + 98ad45c commit 788ebcb
Show file tree
Hide file tree
Showing 16 changed files with 156 additions and 257 deletions.
7 changes: 7 additions & 0 deletions projects/arlas-toolkit/assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@
"Loading bookmark": "Loading bookmark {{bookmark}}",
"count": "count",
"HEADER_EXPORT": "{{metric}} of {{field}}",
"An error occured.": "An error occured.",
"An error occured when requesting data.": "An error occured when requesting data.",
"The requested data does not exist.": "The requested data does not exist.",
"tour.nextBtn": "Next",
"tour.prevBtn": "Previous",
"tour.doneBtn": "Done",
Expand All @@ -241,8 +244,12 @@
"access not authorized": "Log in to access this page.",
"Unknown error": "Unknown error",
"access not authorized anymore": "Access not authorized anymore",
"ARLAS backend services": "ARLAS backend services",
"ARLAS encountered an error": "ARLAS encountered an error",
"go to arlas hub": "Go to ARLAS-Hub.",
"The connection is lost": "The connection to {{service}} is lost.",
"The service is unavailable": "{{service}} is unavailable.",
"An error occured in the service": "An error occured in {{service}}.",
"Could not access the dashboard": "Access to dashboard denied",
"dashboard access forbidden": "You are not authorised to access this dashboard.",
"dashboard access not authorized": "Log in to access this dashboard.",
Expand Down
15 changes: 11 additions & 4 deletions projects/arlas-toolkit/assets/i18n/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,10 @@
"Send password reset email": "Recibir un correo electrónico de restablecimiento",
"Already have an account?": "¿Ya tiene una cuenta?",
"Log In": "Iniciar sesión",
"x-axis": "",
"x-axis": "Abscisa",
"to": "a",
"y-axis": "",
"interval": "",
"y-axis": "Ordenada",
"interval": "Intervalo",
"Export": "Exportar en formato CSV",
"Sign in": "Iniciar sesión",
"Please enter your password": "Introducir su contraseña",
Expand Down Expand Up @@ -170,7 +170,7 @@
"Replay": "Reproducir",
"Datepicker.rangeFromLabel": "Desde",
"Datepicker.rangeToLabel": "al",
"Time zone": "Zona horaria :",
"Time zone": "Zona horaria:",
"Remove time filter": "Quitar el filtro de tiempo",
"Show timeline": "Mostrar la línea de tiempo",
"Hide timeline": "Ocultar la línea de tiempo",
Expand Down Expand Up @@ -231,6 +231,9 @@
"Loading bookmark": "Cargango marcador {{bookmark}}",
"count": "Recuenta",
"HEADER_EXPORT": "{{field}} {{metric}}",
"An error occured.": "Se ha producido un error.",
"An error occured when requesting data.": "Se ha producido un error al solicitar datos.",
"The requested data does not exist.": "Los datos solicitados no existen.",
"tour.nextBtn": "Siguiente",
"tour.prevBtn": "Precedente",
"tour.doneBtn": "Hecho",
Expand All @@ -241,8 +244,12 @@
"access not authorized": "Inicie sesión para acceder a esta página.",
"Unknown error": "Error desconocido",
"access not authorized anymore": "No está autorizado a acceder a este panel más.",
"ARLAS backend services": "Servicios backend ARLAS",
"ARLAS encountered an error": "ARLAS ha encontrado un error.",
"go to arlas hub": "Ir a ARLAS-Hub.",
"The connection is lost": "Se pierde la conexión con {{service}}.",
"The service is unavailable": "{{service}} no está disponible.",
"An error occured in the service": "Se ha producido un error en {{service}}.",
"Could not access the dashboard": "Acceso al panel denegado.",
"dashboard access forbidden": "No está autorizado a acceder a este panel.",
"dashboard access not authorized": "Inicie sesión para acceder al panel.",
Expand Down
13 changes: 10 additions & 3 deletions projects/arlas-toolkit/assets/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
"x-axis": "Abscisse",
"to": "à",
"y-axis": "Ordonnée",
"interval": "",
"interval": "Intervalle",
"Export": "Exporter au format CSV",
"Sign in": "Connexion",
"Please enter your password": "Saisissez votre mot de passe",
Expand Down Expand Up @@ -185,7 +185,7 @@
"User informations": "Informations utilisateur",
"Organisations": "Organisations",
"Verify your email": "Vérifiez votre adresse e-mail",
"To validate your email, please set your password:": "Pour valider votre email, veuillez définir votre mot de passe:",
"To validate your email, please set your password:": "Pour valider votre email, veuillez définir votre mot de passe :",
"Your account is now active.": "Votre compte est maintenant actif.",
"Unknown user": "Utilisateur inconnu",
"User already verified": "Utilisateur déjà vérifié",
Expand Down Expand Up @@ -231,6 +231,9 @@
"Loading bookmark": "Chargement du bookmark {{bookmark}}",
"count": "Nombre",
"HEADER_EXPORT": "{{metric}} de {{field}}",
"An error occured.": "Une erreur est survenue.",
"An error occured when requesting data.": "Une erreur est survenue lors de la requête.",
"The requested data does not exist.": "La donnée demandée n'existe pas.",
"tour.nextBtn": "Suivant",
"tour.prevBtn": "Précédent",
"tour.doneBtn": "Terminé",
Expand All @@ -241,13 +244,17 @@
"access not authorized": "Veuillez vous connecter pour accéder à cette page.",
"Unknown error": "Erreur inconnue",
"access not authorized anymore": "Vous n'êtes plus autorisé(e) à accéder à cette page.",
"ARLAS backend services": "Services backend d'ARLAS",
"ARLAS encountered an error": "ARLAS a rencontré une erreur",
"go to arlas hub": "Aller sur ARLAS-Hub.",
"The connection is lost": "La connexion avec {{service}} a été perdue.",
"The service is unavailable": "{{service}} est indisponible.",
"An error occured in the service": "Une erreur s'est produite dans {{service}}.",
"Could not access the dashboard": "Accès au dashboard refusé",
"dashboard access forbidden": "Vous n'êtes pas autorisé à accéder à ce dashboard.",
"dashboard access not authorized": "Veuillez vous connecter pour accéder à ce dashboard.",
"dashboard does not exist": "Ce dashboard n'a pas été trouvé.",
"The connection to dashbords is lost": "",
"The connection to dashbords is lost": "La connexion aux dashboards a été perdue.",
"ARLAS Front-end Settings error": "Erreur de paramétrage de l'interface ARLAS",
"Please check if the settings.yaml file is provided and has a valid syntax": "Vérifier que le fichier settings.yaml est fourni et que sa syntaxe est valide.",
"ITEMS_PER_PAGE_LABEL": "Items par page",
Expand Down
7 changes: 7 additions & 0 deletions projects/arlas-toolkit/assets/i18n/template.json
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@
"Loading bookmark": "Loading bookmark",
"count": "count",
"HEADER_EXPORT": "HEADER_EXPORT",
"An error occured.": "An error occured.",
"An error occured when requesting data.": "An error occured when requesting data.",
"The requested data does not exist.": "The requested data does not exist.",
"tour.nextBtn": "tour.nextBtn",
"tour.prevBtn": "tour.prevBtn",
"tour.doneBtn": "tour.doneBtn",
Expand All @@ -241,8 +244,12 @@
"access not authorized": "access not authorized",
"Unknown error": "Unknown error",
"access not authorized anymore": "access not authorized anymore",
"ARLAS backend services": "ARLAS backend services",
"ARLAS encountered an error": "ARLAS encountered an error",
"go to arlas hub": "go to arlas hub",
"The connection is lost": "The connection is lost",
"The service is unavailable": "The service is unavailable",
"An error occured in the service": "An error occured in the service",
"Could not access the dashboard": "Could not access the dashboard",
"dashboard access forbidden": "dashboard access forbidden",
"dashboard access not authorized": "dashboard access not authorized",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@

import { Component, Inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { PersistenceService } from '../../../services/persistence/persistence.service';
import { Config, ConfigAction, ConfigActionEnum } from '../../../tools/utils';
import { marker } from '@colsen1991/ngx-translate-extract-marker';
import { ArlasConfigService } from '../../../services/startup/startup.service';
import { DataWithLinks, Exists } from 'arlas-persistence-api';
import { Observable, catchError, combineLatest, concatAll, finalize, forkJoin, from, map, mergeAll, mergeMap, of, take, tap } from 'rxjs';
import { DataWithLinks } from 'arlas-persistence-api';
import { Observable, catchError, forkJoin, map, mergeMap, of, take, tap } from 'rxjs';
import { ErrorService } from '../../../services/error/error.service';
import { PersistenceService } from '../../../services/persistence/persistence.service';
import { ArlasConfigService } from '../../../services/startup/startup.service';
import { AuthorisationOnActionError } from '../../../tools/errors/authorisation-on-action-error';
import { Config, ConfigAction, ConfigActionEnum } from '../../../tools/utils';

@Component({
selector: 'arlas-action-modal',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
<mat-dialog-content class="content">
<div class="errored">
<div><mat-icon class="icon">error</mat-icon></div>
<div class="state">{{arlasError?.message | translate}}</div>
<div class="state">{{arlasError?.message | translate:{service: $any(arlasError)?.service | translate} }}</div>
<ng-container *ngIf="arlasError?.actionType === 'link'; else buttonType">
<div *ngIf="arlasError?.showAction" class="action" (click)="arlasError.executeAction()">{{arlasError?.actionMessage | translate}}</div>
<div *ngIf="arlasError?.showAction" class="action" (click)="arlasError.executeAction()">{{arlasError?.actionMessage | translate }}</div>
</ng-container>
<ng-template #buttonType>
<button mat-stroked-button *ngIf="arlasError?.showAction" (click)="arlasError.executeAction()">{{arlasError?.actionMessage | translate}}</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ $error-color: #ce3d38;
.title {
font-size: $default-font-size;
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
}

.content {
Expand Down
28 changes: 24 additions & 4 deletions projects/arlas-toolkit/src/lib/services/error/error.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,27 @@

import { Injectable } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { marker } from '@colsen1991/ngx-translate-extract-marker';
import { Subscription } from 'rxjs';
import { DeniedAccessDialogComponent } from '../../components/denied-access-dialog/denied-access-dialog.component';
import { ArlasSettingsService } from '../../services/settings/arlas.settings.service';
import { AuthorisationError } from '../../tools/errors/authorisation-error';
import { BackendError } from '../../tools/errors/backend-error';
import { SettingsError } from '../../tools/errors/settings-error';
import { ArlasCollaborativesearchService } from '../collaborative-search/arlas.collaborative-search.service';

@Injectable({
providedIn: 'root'
})
export class ErrorService {

public constructor(
private dialog: MatDialog,
private settingsService: ArlasSettingsService) {
private arlasErrorsSubscription: Subscription;

}
public constructor(
private readonly dialog: MatDialog,
private readonly settingsService: ArlasSettingsService,
private readonly arlasCollaborationService: ArlasCollaborativesearchService
) { }

public emitAuthorisationError(error: AuthorisationError, forceAction = true) {
if (!this.dialog.openDialogs || this.dialog.openDialogs.length === 0) {
Expand Down Expand Up @@ -84,4 +89,19 @@ export class ErrorService {
this.dialog.closeAll();
return this.dialog;
}

public listenToArlasCollaborativeErrors() {
this.arlasErrorsSubscription = this.arlasCollaborationService.collaborationErrorBus.subscribe((e: any) => {
if (e.status >= 400) {
this.emitBackendError(e.status, e.message, marker('ARLAS-server'));
} else if (!e.status) {
// In case ARLAS-server got down during the use of the app
this.emitUnavailableService(marker('ARLAS-server'));
}
});
}

public unlistenToArlasCollaborativeErrors() {
this.arlasErrorsSubscription.unsubscribe();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,27 @@
*/

import { Injectable } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { Router } from '@angular/router';
import { marker } from '@colsen1991/ngx-translate-extract-marker';
import fetchIntercept from 'fetch-intercept';
import { ReconnectDialogComponent } from '../../components/reconnect-dialog/reconnect-dialog.component';
import { ArlasSettingsService } from '../settings/arlas.settings.service';
import { DeniedAccessDialogComponent } from '../../components/denied-access-dialog/denied-access-dialog.component';
import { DeniedAccessData } from '../../tools/utils';
import { AuthorisationError } from '../../tools/errors/authorisation-error';
import { ReconnectDialogComponent } from '../../components/reconnect-dialog/reconnect-dialog.component';
import { ErrorService } from '../../services/error/error.service';
import { Router } from '@angular/router';
import { MatDialog } from '@angular/material/dialog';
import { AuthorisationError } from '../../tools/errors/authorisation-error';
import { DeniedAccessData } from '../../tools/utils';
import { ArlasSettingsService } from '../settings/arlas.settings.service';

@Injectable({
providedIn: 'root'
})
export class FetchInterceptorService {

public constructor(
private arlasSettings: ArlasSettingsService,
private dialog: MatDialog,
private errorService: ErrorService,
private router: Router) { }
private readonly arlasSettings: ArlasSettingsService,
private readonly dialog: MatDialog,
private readonly errorService: ErrorService,
private readonly router: Router) { }

public interceptLogout() {
const settings = this.arlasSettings.settings;
Expand All @@ -63,27 +64,34 @@ export class FetchInterceptorService {
let code = response.status;
if (code === 401 || code === 403) {
// Check if the response comes from a call to a non arlas public uri
if (!!response.headers.get('WWW-Authenticate')) {
if (response.headers.has('WWW-Authenticate')) {
code = 403;
}
if (settings.authentication.auth_mode === 'iam') {
// If not currently logging in, display error
if (this.router.url !== '/login') {
this.errorService.emitAuthorisationError(new AuthorisationError(code));
}
} else {
} else if (this.dialog.openDialogs?.length === undefined || this.dialog.openDialogs?.length === 0) {
// Propose to reconnect or stay disconnected
if (!this.dialog.openDialogs || !this.dialog.openDialogs.length) {
this.dialog.open(
ReconnectDialogComponent,
{
disableClose: true,
data: { code },
backdropClass: 'reconnect-dialog',
panelClass: 'reconnect-dialog-panel'
});
}
this.dialog.open(
ReconnectDialogComponent,
{
disableClose: true,
data: { code },
backdropClass: 'reconnect-dialog',
panelClass: 'reconnect-dialog-panel'
});
}
} else if (code >= 400) {
let message: string = marker('An error occured.');

if (code === 400) {
message = marker('An error occured when requesting data.');
} else if (code === 404) {
message = marker('The requested data does not exist.');
}
this.errorService.emitBackendError(code, message, marker('ARLAS-server'));
}
return response;
},
Expand Down
30 changes: 17 additions & 13 deletions projects/arlas-toolkit/src/lib/toolkit.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,39 +18,41 @@
*/

import { Location } from '@angular/common';
import { AfterViewInit, Component, OnInit } from '@angular/core';
import { AfterViewInit, Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { interval } from 'rxjs';
import { take } from 'rxjs/operators';
import { ArlasCollaborativesearchService } from './services/collaborative-search/arlas.collaborative-search.service';
import { ArlasConfigService, ArlasStartupService } from './services/startup/startup.service';
import { ArlasWalkthroughService } from './services/walkthrough/walkthrough.service';
import { CONFIG_ID_QUERY_PARAM } from './tools/utils';
import { ErrorService } from './services/error/error.service';

@Component({
selector: 'arlas-tool-root',
templateUrl: './toolkit.component.html',
providers: [Location],
styleUrls: ['./toolkit.component.css']
})
export class ToolkitComponent implements AfterViewInit, OnInit {
export class ToolkitComponent implements AfterViewInit, OnInit, OnDestroy {

public analytics: Array<any>;
public languages: string[];
public analyticsOpen = false;
public target: string;

public constructor(
private configService: ArlasConfigService,
private arlasStartupService: ArlasStartupService,
private collaborativeService: ArlasCollaborativesearchService,
private activatedRoute: ActivatedRoute,
private router: Router,
private location: Location,
private walkthroughService: ArlasWalkthroughService
private readonly configService: ArlasConfigService,
private readonly arlasStartupService: ArlasStartupService,
private readonly collaborativeService: ArlasCollaborativesearchService,
private readonly activatedRoute: ActivatedRoute,
private readonly router: Router,
private readonly location: Location,
private readonly walkthroughService: ArlasWalkthroughService,
private readonly errorService: ErrorService
) {
// update url when filter are set
const queryParams: Params = Object.assign({}, this.activatedRoute.snapshot.queryParams);
const queryParams: Params = {...this.activatedRoute.snapshot.queryParams};
if (!this.arlasStartupService.emptyMode) {
this.collaborativeService.collaborationBus.subscribe(collaborationEvent => {
queryParams['filter'] = this.collaborativeService.urlBuilder().split('filter=')[1];
Expand Down Expand Up @@ -96,6 +98,7 @@ export class ToolkitComponent implements AfterViewInit, OnInit {
});
}

this.errorService.listenToArlasCollaborativeErrors();
}

public ngOnInit(): void {
Expand All @@ -111,9 +114,6 @@ export class ToolkitComponent implements AfterViewInit, OnInit {
this.collaborativeService.setCollaborations(dataModel);
}
});
// this.collaborativeService.setCollaborations({});
// this.analytics = this.arlasStartupService.analytics;
// this.languages = ['en', 'fr', 'it', 'es', 'de', 'us', 'cn'];
}

public ngAfterViewInit(): void {
Expand All @@ -133,6 +133,10 @@ export class ToolkitComponent implements AfterViewInit, OnInit {
this.walkthroughService.load();
}

public ngOnDestroy(): void {
this.errorService.unlistenToArlasCollaborativeErrors();
}

public openAnalytics(event) {
this.target = 'analytics-panel-' + event;
this.analyticsOpen = true;
Expand Down
Loading

0 comments on commit 788ebcb

Please sign in to comment.