From c914ffa19a4caa1b6724d5b4bd1b87ac5d3a4000 Mon Sep 17 00:00:00 2001 From: Unai Zalba Date: Thu, 7 Mar 2024 09:20:15 +0100 Subject: [PATCH 1/5] refactor/AB#82357_create-shared-error-handler-logic-for-the-app feat: add error handler to display default snackbar message from one place for all error coming from our API that are not graphQL related feat: refactor all graphql errors to be treated in the error section of the subscription feat: adapt all grapql subscriptions in order to keep the errors correctly handled as the aforementioned reason --- .../pages/dashboard/dashboard.component.ts | 29 +- .../pages/workflow/workflow.component.ts | 25 +- apps/back-office/src/app/app.module.ts | 6 + .../pages/add-page/add-page.component.ts | 51 +- .../pages/archive/archive.component.ts | 20 +- .../pages/settings/settings.component.ts | 49 +- .../pages/workflow/workflow.component.ts | 75 +- .../duplicate-application-modal.component.ts | 49 +- .../api-configuration.component.ts | 49 +- .../api-configurations.component.ts | 87 +- .../applications/applications.component.ts | 133 ++- .../form-builder/form-builder.component.ts | 140 +-- .../form-records/form-records.component.ts | 96 +-- .../dashboard/pages/forms/forms.component.ts | 84 +- .../pages/pull-jobs/pull-jobs.component.ts | 179 ++-- .../reference-data.component.ts | 48 +- .../reference-datas.component.ts | 73 +- .../aggregations-tab.component.ts | 30 +- .../calculated-fields-tab.component.ts | 23 +- .../resource/forms-tab/forms-tab.component.ts | 41 +- .../records-tab/records-tab.component.ts | 39 +- .../pages/resource/resource.component.ts | 60 +- .../pages/resources/resources.component.ts | 50 +- .../dashboard/pages/users/users.component.ts | 129 ++- apps/front-office/src/app/app.module.ts | 6 + .../pages/workflow/workflow.component.ts | 25 +- .../pages/workflow/workflow.component.ts | 25 +- libs/shared/src/index.ts | 1 + .../form-modal/form-modal.component.ts | 107 +-- .../src/lib/components/form/form.component.ts | 31 +- .../record-history.component.ts | 25 +- .../record-modal/record-modal.component.ts | 26 +- .../role-features/role-features.component.ts | 1 + .../role-workflows.component.ts | 1 + .../role-resources.component.ts | 39 +- .../group-list/group-list.component.ts | 88 +- .../role-list/role-list.component.ts | 93 +- .../aggregation-builder.component.ts | 5 +- .../ui/core-grid/core-grid.component.ts | 28 +- .../user-app-roles.component.ts | 1 + .../user-back-roles.component.ts | 1 + .../user-groups/user-groups.component.ts | 1 + .../user-summary/user-summary.component.ts | 3 + .../invite-users-modal.component.ts | 8 +- .../template-aggregations.component.ts | 5 +- .../map-layers/map-layers.component.ts | 10 +- .../summary-card/summary-card.component.ts | 1 + .../error-handler-interceptor.service.ts | 90 ++ .../error-handler-interceptor.spec.ts | 18 + .../application-notifications.service.ts | 74 +- .../application/application.service.ts | 806 +++++++++--------- .../auth-interceptor.service.ts | 2 +- .../lib/services/context/context.service.ts | 5 +- .../services/dashboard/dashboard.service.ts | 5 +- .../form-builder/form-builder.service.ts | 37 +- .../form-helper/form-helper.service.ts | 72 +- .../lib/services/map/map-layers.service.ts | 26 +- .../lib/services/workflow/workflow.service.ts | 46 +- .../utils/graphql/error-message-formatter.ts | 8 + libs/shared/src/lib/utils/public-api.ts | 1 + .../application-users.component.ts | 16 +- .../lib/views/profile/profile.component.ts | 23 +- .../src/lib/snackbar/snackbar.component.html | 4 +- 63 files changed, 1657 insertions(+), 1672 deletions(-) create mode 100644 libs/shared/src/lib/interceptors/error-handler/error-handler-interceptor.service.ts create mode 100644 libs/shared/src/lib/interceptors/error-handler/error-handler-interceptor.spec.ts create mode 100644 libs/shared/src/lib/utils/graphql/error-message-formatter.ts diff --git a/apps/back-office/src/app/app-preview/pages/dashboard/dashboard.component.ts b/apps/back-office/src/app/app-preview/pages/dashboard/dashboard.component.ts index 2fadac1366..226ff819fb 100644 --- a/apps/back-office/src/app/app-preview/pages/dashboard/dashboard.component.ts +++ b/apps/back-office/src/app/app-preview/pages/dashboard/dashboard.component.ts @@ -84,25 +84,20 @@ export class DashboardComponent this.widgets = cloneDeep( data.dashboard.structure ? data.dashboard.structure : [] ); - this.loading = loading; - } else { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.accessNotProvided', - { - type: this.translate - .instant('common.dashboard.one') - .toLowerCase(), - error: '', - } - ), - { error: true } - ); - this.router.navigate(['/dashboards']); } + this.loading = loading; }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: () => { + this.loading = false; + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.accessNotProvided', { + type: this.translate + .instant('common.dashboard.one') + .toLowerCase(), + error: '', + }), + { error: true } + ); this.router.navigate(['/dashboards']); }, }); diff --git a/apps/back-office/src/app/app-preview/pages/workflow/workflow.component.ts b/apps/back-office/src/app/app-preview/pages/workflow/workflow.component.ts index 51ccec8057..c61d4dfe57 100644 --- a/apps/back-office/src/app/app-preview/pages/workflow/workflow.component.ts +++ b/apps/back-office/src/app/app-preview/pages/workflow/workflow.component.ts @@ -105,23 +105,18 @@ export class WorkflowComponent extends UnsubscribeComponent implements OnInit { if (this.steps.length > 0) { this.onOpenStep(0); } - } else { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.accessNotProvided', - { - type: this.translate - .instant('common.workflow.one') - .toLowerCase(), - error: '', - } - ), - { error: true } - ); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.accessNotProvided', { + type: this.translate + .instant('common.workflow.one') + .toLowerCase(), + error: '', + }), + { error: true } + ); }, }); }); diff --git a/apps/back-office/src/app/app.module.ts b/apps/back-office/src/app/app.module.ts index 533f0b2fe0..a5fae78dd4 100644 --- a/apps/back-office/src/app/app.module.ts +++ b/apps/back-office/src/app/app.module.ts @@ -29,6 +29,7 @@ import { AppAbility, FormService, DatePipe, + ErrorHandlerInterceptorService, } from '@oort-front/shared'; import { registerLocaleData } from '@angular/common'; import localeFr from '@angular/common/locales/fr'; @@ -146,6 +147,11 @@ export const httpTranslateLoader = (http: HttpClient) => useClass: AuthInterceptorService, multi: true, }, + { + provide: HTTP_INTERCEPTORS, + useClass: ErrorHandlerInterceptorService, + multi: true, + }, { provide: AppAbility, useValue: new AppAbility(), diff --git a/apps/back-office/src/app/application/pages/add-page/add-page.component.ts b/apps/back-office/src/app/application/pages/add-page/add-page.component.ts index c611f65973..a382c2d012 100644 --- a/apps/back-office/src/app/application/pages/add-page/add-page.component.ts +++ b/apps/back-office/src/app/application/pages/add-page/add-page.component.ts @@ -9,6 +9,7 @@ import { UnsubscribeComponent, FormsQueryResponse, AddFormMutationResponse, + errorMessageFormatter, } from '@oort-front/shared'; import { takeUntil } from 'rxjs'; import { ADD_FORM } from './graphql/mutations'; @@ -177,35 +178,31 @@ export class AddPageComponent extends UnsubscribeComponent implements OnInit { variables: variablesData, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotCreated', - { - type: this.translate - .instant('common.form.one') - .toLowerCase(), - error: errors ? errors[0].message : '', - } - ), - { error: true } - ); - } else { - const id = data?.addForm.id || ''; - this.pageForm.controls.content.setValue(id); - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectCreated', { - type: this.translate.instant('common.page.one'), - value: value.name, - }) - ); + next: ({ data }) => { + const id = data?.addForm.id || ''; + this.pageForm.controls.content.setValue(id); + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectCreated', { + type: this.translate.instant('common.page.one'), + value: value.name, + }) + ); - this.onSubmit(); - } + this.onSubmit(); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant( + 'common.notifications.objectNotCreated', + { + type: this.translate + .instant('common.form.one') + .toLowerCase(), + error: errorMessageFormatter(errors), + } + ), + { error: true } + ); }, }); } diff --git a/apps/back-office/src/app/application/pages/archive/archive.component.ts b/apps/back-office/src/app/application/pages/archive/archive.component.ts index 7644c31f79..ea6fd9bf19 100644 --- a/apps/back-office/src/app/application/pages/archive/archive.component.ts +++ b/apps/back-office/src/app/application/pages/archive/archive.component.ts @@ -89,21 +89,17 @@ export class ArchiveComponent extends UnsubscribeComponent implements OnInit { autoDeletedAt: page.autoDeletedAt, } as ArchivePage; }) ?? []; - } else { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.accessNotProvided', { - type: this.translate - .instant('common.workflow.one') - .toLowerCase(), - error: '', - }), - { error: true } - ); } this.loading = false; }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.accessNotProvided', { + type: this.translate.instant('common.workflow.one').toLowerCase(), + error: '', + }), + { error: true } + ); this.loading = false; }, }); diff --git a/apps/back-office/src/app/application/pages/settings/settings.component.ts b/apps/back-office/src/app/application/pages/settings/settings.component.ts index 2d26b57023..ccb601675e 100644 --- a/apps/back-office/src/app/application/pages/settings/settings.component.ts +++ b/apps/back-office/src/app/application/pages/settings/settings.component.ts @@ -8,6 +8,7 @@ import { UnsubscribeComponent, DeleteApplicationMutationResponse, status, + errorMessageFormatter, } from '@oort-front/shared'; import { Dialog } from '@angular/cdk/dialog'; import { DELETE_APPLICATION } from './graphql/mutations'; @@ -165,35 +166,27 @@ export class SettingsComponent extends UnsubscribeComponent implements OnInit { }, }) .subscribe({ - next: ({ errors }) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotDeleted', - { - value: this.translate.instant( - 'common.application.one' - ), - error: errors ? errors[0].message : '', - } - ), - { error: true } - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectDeleted', - { - value: this.translate.instant( - 'common.application.one' - ), - } - ) - ); - } + next: () => { + this.snackBar.openSnackBar( + this.translate.instant( + 'common.notifications.objectDeleted', + { + value: this.translate.instant('common.application.one'), + } + ) + ); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant( + 'common.notifications.objectNotDeleted', + { + value: this.translate.instant('common.application.one'), + error: errorMessageFormatter(errors), + } + ), + { error: true } + ); }, }); this.router.navigate(['/applications']); diff --git a/apps/back-office/src/app/application/pages/workflow/workflow.component.ts b/apps/back-office/src/app/application/pages/workflow/workflow.component.ts index fb5cace7f0..97500b4961 100644 --- a/apps/back-office/src/app/application/pages/workflow/workflow.component.ts +++ b/apps/back-office/src/app/application/pages/workflow/workflow.component.ts @@ -14,6 +14,7 @@ import { UnsubscribeComponent, DeleteStepMutationResponse, EditWorkflowMutationResponse, + errorMessageFormatter, } from '@oort-front/shared'; import { DELETE_STEP, EDIT_WORKFLOW } from './graphql/mutations'; import { TranslateService } from '@ngx-translate/core'; @@ -244,45 +245,41 @@ export class WorkflowComponent extends UnsubscribeComponent implements OnInit { }, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { + next: ({ data }) => { + if (data) { this.snackBar.openSnackBar( this.translate.instant( - 'common.notifications.objectNotDeleted', + 'common.notifications.objectDeleted', { value: this.translate.instant('common.step.one'), - error: errors ? errors[0].message : '', } - ), - { error: true } + ) ); - } else { - if (data) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectDeleted', - { - value: this.translate.instant('common.step.one'), - } - ) - ); - this.steps = this.steps.filter( - (x) => x.id !== data?.deleteStep.id - ); - if (index === this.activeStep) { - this.onOpenStep(-1); - } else { - if (currentStep) { - this.activeStep = this.steps.findIndex( - (x) => x.id === currentStep.id - ); - } + this.steps = this.steps.filter( + (x) => x.id !== data?.deleteStep.id + ); + if (index === this.activeStep) { + this.onOpenStep(-1); + } else { + if (currentStep) { + this.activeStep = this.steps.findIndex( + (x) => x.id === currentStep.id + ); } } } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant( + 'common.notifications.objectNotDeleted', + { + value: this.translate.instant('common.step.one'), + error: errorMessageFormatter(errors), + } + ), + { error: true } + ); }, }); } @@ -340,7 +337,7 @@ export class WorkflowComponent extends UnsubscribeComponent implements OnInit { }, }) .subscribe({ - next: ({ errors, data }) => { + next: ({ data }) => { if (data) { this.snackBar.openSnackBar( this.translate.instant('common.notifications.objectReordered', { @@ -352,18 +349,16 @@ export class WorkflowComponent extends UnsubscribeComponent implements OnInit { this.activeStep = index; } this.steps = steps; - } else { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectNotUpdated', { - type: this.translate.instant('common.workflow.one'), - error: errors ? errors[0].message : '', - }), - { error: true } - ); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectNotUpdated', { + type: this.translate.instant('common.workflow.one'), + error: errorMessageFormatter(errors), + }), + { error: true } + ); }, }); } diff --git a/apps/back-office/src/app/components/duplicate-application-modal/duplicate-application-modal.component.ts b/apps/back-office/src/app/components/duplicate-application-modal/duplicate-application-modal.component.ts index 5570af4e4c..6c12da6667 100644 --- a/apps/back-office/src/app/components/duplicate-application-modal/duplicate-application-modal.component.ts +++ b/apps/back-office/src/app/components/duplicate-application-modal/duplicate-application-modal.component.ts @@ -6,6 +6,7 @@ import { Application, DuplicateApplicationMutationResponse, SnackbarSpinnerComponent, + errorMessageFormatter, } from '@oort-front/shared'; import { TranslateService } from '@ngx-translate/core'; import { CommonModule } from '@angular/common'; @@ -94,35 +95,33 @@ export class DuplicateApplicationModalComponent { }, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { - snackBarSpinner.instance.message = this.translateService.instant( - 'common.notifications.objectNotDuplicated', - { - type: this.translateService - .instant('common.application.one') - .toLowerCase(), - error: errors ? errors[0].message : '', - } - ); - snackBarSpinner.instance.error = true; - } else { - snackBarSpinner.instance.message = this.translateService.instant( - 'common.notifications.objectDuplicated', - { - type: this.translateService - .instant('common.application.one') - .toLowerCase(), - value: this.currentApp.name, - } - ); - } + next: ({ data }) => { snackBarSpinner.instance.loading = false; + + snackBarSpinner.instance.message = this.translateService.instant( + 'common.notifications.objectDuplicated', + { + type: this.translateService + .instant('common.application.one') + .toLowerCase(), + value: this.currentApp.name, + } + ); + + this.loading = false; this.dialogRef.close(data?.duplicateApplication as any); }, - error: (err) => { - snackBarSpinner.instance.message = err.message; + error: (errors) => { snackBarSpinner.instance.loading = false; + snackBarSpinner.instance.message = this.translateService.instant( + 'common.notifications.objectNotDuplicated', + { + type: this.translateService + .instant('common.application.one') + .toLowerCase(), + error: errorMessageFormatter(errors), + } + ); snackBarSpinner.instance.error = true; }, }); diff --git a/apps/back-office/src/app/dashboard/pages/api-configuration/api-configuration.component.ts b/apps/back-office/src/app/dashboard/pages/api-configuration/api-configuration.component.ts index 31350220c2..b2b83acab2 100644 --- a/apps/back-office/src/app/dashboard/pages/api-configuration/api-configuration.component.ts +++ b/apps/back-office/src/app/dashboard/pages/api-configuration/api-configuration.component.ts @@ -11,6 +11,7 @@ import { UnsubscribeComponent, ApiConfigurationQueryResponse, EditApiConfigurationMutationResponse, + errorMessageFormatter, } from '@oort-front/shared'; import { Apollo } from 'apollo-angular'; import { takeUntil } from 'rxjs/operators'; @@ -109,24 +110,18 @@ export class ApiConfigurationComponent this.resetFormSettings(value); }); this.loading = loading; - } else { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.accessNotProvided', - { - type: this.translate - .instant('common.resource.one') - .toLowerCase(), - error: '', - } - ), - { error: true } - ); - this.router.navigate(['/settings/apiconfigurations']); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.accessNotProvided', { + type: this.translate + .instant('common.resource.one') + .toLowerCase(), + error: '', + }), + { error: true } + ); this.router.navigate(['/settings/apiconfigurations']); }, }); @@ -233,21 +228,23 @@ export class ApiConfigurationComponent permissions: e, }, }) - .subscribe(({ errors, data, loading }) => { - if (errors) { + .subscribe({ + next: ({ data, loading }) => { + if (data) { + this.apiConfiguration = data.editApiConfiguration; + } + this.loading = loading; + }, + error: (errors) => { + this.loading = false; this.snackBar.openSnackBar( this.translate.instant('common.notifications.objectNotUpdated', { type: this.translate.instant('common.apiConfiguration.one'), - error: errors ? errors[0].message : '', + error: errorMessageFormatter(errors), }), { error: true } ); - } else { - if (data) { - this.apiConfiguration = data.editApiConfiguration; - } - } - this.loading = loading; + }, }); } @@ -312,7 +309,7 @@ export class ApiConfigurationComponent this.snackBar.openSnackBar( this.translate.instant('common.notifications.objectNotUpdated', { type: this.translate.instant('common.apiConfiguration.one'), - error: errors ? errors[0].message : '', + error: errorMessageFormatter(errors), }), { error: true } ); diff --git a/apps/back-office/src/app/dashboard/pages/api-configurations/api-configurations.component.ts b/apps/back-office/src/app/dashboard/pages/api-configurations/api-configurations.component.ts index 65068f5e6d..8a43125fe0 100644 --- a/apps/back-office/src/app/dashboard/pages/api-configurations/api-configurations.component.ts +++ b/apps/back-office/src/app/dashboard/pages/api-configurations/api-configurations.component.ts @@ -10,6 +10,7 @@ import { DeleteApiConfigurationMutationResponse, getCachedValues, updateQueryUniqueValues, + errorMessageFormatter, } from '@oort-front/shared'; import { ADD_API_CONFIGURATION, @@ -180,39 +181,35 @@ export class ApiConfigurationsComponent }, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotCreated', - { - type: this.translate - .instant('common.apiConfiguration.one') - .toLowerCase(), - error: errors ? errors[0].message : '', - } - ), - { error: true } - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectCreated', { + next: ({ data }) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectCreated', { + type: this.translate + .instant('common.apiConfiguration.one') + .toLowerCase(), + value: data?.addApiConfiguration.name, + }) + ); + if (data) { + this.router.navigate([ + '/settings/apiconfigurations', + data.addApiConfiguration.id, + ]); + } + }, + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant( + 'common.notifications.objectNotCreated', + { type: this.translate .instant('common.apiConfiguration.one') .toLowerCase(), - value: data?.addApiConfiguration.name, - }) - ); - if (data) { - this.router.navigate([ - '/settings/apiconfigurations', - data.addApiConfiguration.id, - ]); - } - } - }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: errorMessageFormatter(errors), + } + ), + { error: true } + ); }, }); } @@ -249,7 +246,7 @@ export class ApiConfigurationsComponent }) .subscribe({ next: (res) => { - if (res && !res.errors) { + if (res) { this.snackBar.openSnackBar( this.translate.instant('common.notifications.objectDeleted', { value: this.translate.instant( @@ -260,23 +257,21 @@ export class ApiConfigurationsComponent this.dataSource = this.dataSource.filter( (x) => x.id !== element.id ); - } else { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotDeleted', - { - value: this.translate.instant( - 'common.apiConfiguration.one' - ), - error: res.errors ? res.errors[0].message : '', - } - ), - { error: true } - ); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant( + 'common.notifications.objectNotDeleted', + { + value: this.translate.instant( + 'common.apiConfiguration.one' + ), + error: errorMessageFormatter(errors), + } + ), + { error: true } + ); }, }); } diff --git a/apps/back-office/src/app/dashboard/pages/applications/applications.component.ts b/apps/back-office/src/app/dashboard/pages/applications/applications.component.ts index 1a563ed2d3..02e386a5e6 100644 --- a/apps/back-office/src/app/dashboard/pages/applications/applications.component.ts +++ b/apps/back-office/src/app/dashboard/pages/applications/applications.component.ts @@ -12,6 +12,7 @@ import { EditApplicationMutationResponse, getCachedValues, updateQueryUniqueValues, + errorMessageFormatter, } from '@oort-front/shared'; import { DELETE_APPLICATION, @@ -256,34 +257,30 @@ export class ApplicationsComponent }, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotDeleted', - { - value: this.translate.instant('common.application.one'), - error: errors ? errors[0].message : '', - } - ), - { error: true } - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectDeleted', { - value: this.translate.instant('common.application.one'), - }) - ); - this.applications = this.applications.filter( - (x) => x.id !== data?.deleteApplication.id - ); - this.newApplications = this.newApplications.filter( - (x) => x.id !== data?.deleteApplication.id - ); - } + next: ({ data }) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectDeleted', { + value: this.translate.instant('common.application.one'), + }) + ); + this.applications = this.applications.filter( + (x) => x.id !== data?.deleteApplication.id + ); + this.newApplications = this.newApplications.filter( + (x) => x.id !== data?.deleteApplication.id + ); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant( + 'common.notifications.objectNotDeleted', + { + value: this.translate.instant('common.application.one'), + error: errorMessageFormatter(errors), + } + ), + { error: true } + ); }, }); } @@ -300,32 +297,28 @@ export class ApplicationsComponent mutation: ADD_APPLICATION, }) .subscribe({ - next: ({ errors, data }) => { - if (errors?.length) { + next: ({ data }) => { + if (data) { this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectNotCreated', { - type: this.translate - .instant('common.application.one') - .toLowerCase(), - error: errors ? errors[0].message : '', - }), - { error: true } + this.translate.instant('common.notifications.objectCreated', { + type: this.translate.instant('common.application.one'), + value: data.addApplication.name, + }) ); - } else { - if (data) { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectCreated', { - type: this.translate.instant('common.application.one'), - value: data.addApplication.name, - }) - ); - const id = data.addApplication.id; - this.router.navigate(['/applications', id]); - } + const id = data.addApplication.id; + this.router.navigate(['/applications', id]); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectNotCreated', { + type: this.translate + .instant('common.application.one') + .toLowerCase(), + error: errorMessageFormatter(errors), + }), + { error: true } + ); }, }); } @@ -346,34 +339,30 @@ export class ApplicationsComponent }, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { + next: ({ data }) => { + if (data) { this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectNotUpdated', { + this.translate.instant('common.notifications.objectUpdated', { type: this.translate.instant('common.access'), - error: errors ? errors[0].message : '', - }), - { error: true } + value: element.name, + }) ); - } else { - if (data) { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectUpdated', { - type: this.translate.instant('common.access'), - value: element.name, - }) - ); - const index = this.applications.findIndex( - (x) => x.id === element.id - ); - this.applications[index] = data.editApplication; - // eslint-disable-next-line no-self-assign - this.applications = this.applications; - } + const index = this.applications.findIndex( + (x) => x.id === element.id + ); + this.applications[index] = data.editApplication; + // eslint-disable-next-line no-self-assign + this.applications = this.applications; } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectNotUpdated', { + type: this.translate.instant('common.access'), + error: errorMessageFormatter(errors), + }), + { error: true } + ); }, }); } diff --git a/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts b/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts index bf3f4a1e88..406934a99e 100644 --- a/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts +++ b/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts @@ -18,6 +18,7 @@ import { FormQueryResponse, EditFormMutationResponse, SnackbarSpinnerComponent, + errorMessageFormatter, } from '@oort-front/shared'; import { SpinnerComponent } from '@oort-front/ui'; import { Observable } from 'rxjs'; @@ -177,25 +178,16 @@ export class FormBuilderComponent implements OnInit { this.hasChanges = true; this.authService.canLogout.next(!this.hasChanges); } - } else { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.accessNotProvided', - { - type: this.translate - .instant('common.form.one') - .toLowerCase(), - error: '', - } - ), - { error: true } - ); - // redirect to default screen if error - this.router.navigate(['/forms']); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.accessNotProvided', { + type: this.translate.instant('common.form.one').toLowerCase(), + error: '', + }), + { error: true } + ); // redirect to default screen if error this.router.navigate(['/forms']); }, @@ -279,34 +271,35 @@ export class FormBuilderComponent implements OnInit { }, }) .subscribe({ - next: ({ errors, data }) => { + next: ({ data }) => { // Dismiss the loading snackbar loadingSnackbarRef.instance.dismiss(); - // Open new snackbar with the request error or success message - const message = errors - ? errors[0].message - : this.translate.instant('common.notifications.objectUpdated', { - type: this.translate.instant('common.form.one').toLowerCase(), - value: '', - }); - const snackbarConfig = { - ...REQUEST_SNACKBAR_CONF, - error: errors ? true : false, - }; - this.snackBar.openSnackBar(message, snackbarConfig); + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectUpdated', { + type: this.translate.instant('common.form.one').toLowerCase(), + value: '', + }), + { + ...REQUEST_SNACKBAR_CONF, + error: false, + } + ); - if (!errors) { - this.form = { ...data?.editForm, structure }; - this.structure = structure; - localStorage.removeItem(`form:${this.id}`); - this.hasChanges = false; - this.authService.canLogout.next(true); - } + this.form = { ...data?.editForm, structure }; + this.structure = structure; + localStorage.removeItem(`form:${this.id}`); + this.hasChanges = false; + this.authService.canLogout.next(true); }, - error: (err) => { + error: (errors) => { // Dismiss the loading snackbar loadingSnackbarRef.instance.dismiss(); - this.snackBar.openSnackBar(err.message, { error: true }); + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + ...REQUEST_SNACKBAR_CONF, + error: true, + }); + // Detach the current set overlay + overlayRef.detach(); }, complete: () => { // Detach the current set overlay @@ -334,15 +327,15 @@ export class FormBuilderComponent implements OnInit { }, }) .subscribe({ - next: ({ errors, data }) => { + next: ({ data }) => { // Dismiss the loading snackbar loadingSnackbarRef.instance.dismiss(); - this.handleFormMutationResponse(data, errors); + this.handleFormMutationResponse(data, []); }, - error: (err) => { + error: (errors) => { // Dismiss the loading snackbar loadingSnackbarRef.instance.dismiss(); - this.snackBar.openSnackBar(err.message, { error: true }); + this.handleFormMutationResponse(null, errors); }, complete: () => { // Detach the current set overlay @@ -363,13 +356,13 @@ export class FormBuilderComponent implements OnInit { errors: readonly GraphQLError[] | undefined, formName?: string ) { - if (errors) { + if (errors?.length) { this.snackBar.openSnackBar( this.translate.instant('common.notifications.objectNotUpdated', { type: this.translate.instant( formName ? 'common.form.one' : 'common.status' ), - error: errors ? errors[0].message : '', + error: errorMessageFormatter(errors), }), { error: true } ); @@ -454,14 +447,17 @@ export class FormBuilderComponent implements OnInit { }, }) .subscribe({ - next: ({ errors, data }) => { + next: ({ data }) => { // Dismiss the loading snackbar loadingSnackbarRef.instance.dismiss(); - this.handleFormMutationResponse(data, errors, formName); + this.handleFormMutationResponse(data, [], formName); }, - error: () => { + error: (errors) => { // Dismiss the loading snackbar loadingSnackbarRef.instance.dismiss(); + this.handleFormMutationResponse(null, errors, formName); + // Detach the current set overlay + overlayRef.detach(); }, complete: () => { // Detach the current set overlay @@ -489,31 +485,37 @@ export class FormBuilderComponent implements OnInit { }, }) .subscribe({ - next: ({ errors, data }) => { + next: ({ data }) => { // Dismiss the loading snackbar loadingSnackbarRef.instance.dismiss(); - // Open new snackbar with the request error or success message - const message = errors - ? this.translate.instant('common.notifications.objectNotUpdated', { - type: this.translate.instant('common.access'), - error: errors ? errors[0].message : '', - }) - : this.translate.instant('common.notifications.objectUpdated', { - type: this.translate.instant('common.access'), - value: '', - }); - const snackbarConfig = { - ...REQUEST_SNACKBAR_CONF, - error: errors ? true : false, - }; - this.snackBar.openSnackBar(message, snackbarConfig); - if (!errors) { - this.form = { ...data?.editForm, structure: this.structure }; - } + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectUpdated', { + type: this.translate.instant('common.access'), + value: '', + }), + { + ...REQUEST_SNACKBAR_CONF, + error: false, + } + ); + + this.form = { ...data?.editForm, structure: this.structure }; }, - error: (err) => { + error: (errors) => { + // Dismiss the loading snackbar loadingSnackbarRef.instance.dismiss(); - this.snackBar.openSnackBar(err.message, { error: true }); + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectNotUpdated', { + type: this.translate.instant('common.access'), + error: errorMessageFormatter(errors), + }), + { + ...REQUEST_SNACKBAR_CONF, + error: false, + } + ); + // Detach the current set overlay + overlayRef.detach(); }, complete: () => { // Detach the current set overlay diff --git a/apps/back-office/src/app/dashboard/pages/form-records/form-records.component.ts b/apps/back-office/src/app/dashboard/pages/form-records/form-records.component.ts index b424c448b2..e670bff23f 100644 --- a/apps/back-office/src/app/dashboard/pages/form-records/form-records.component.ts +++ b/apps/back-office/src/app/dashboard/pages/form-records/form-records.component.ts @@ -19,6 +19,7 @@ import { DownloadService, getCachedValues, updateQueryUniqueValues, + errorMessageFormatter, } from '@oort-front/shared'; import { Dialog } from '@angular/cdk/dialog'; import { TranslateService } from '@ngx-translate/core'; @@ -155,22 +156,21 @@ export class FormRecordsComponent }, }); - this.recordsQuery.valueChanges - .pipe(takeUntil(this.destroy$)) - .subscribe(({ errors, data, loading }) => { + this.recordsQuery.valueChanges.pipe(takeUntil(this.destroy$)).subscribe({ + next: ({ data, loading }) => { this.updateValues(data, loading, true); - - if (errors) { - // TO-DO: Check why it's not working as intended. - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.accessNotProvided', { - type: this.translate.instant('common.record.one').toLowerCase(), - error: errors ? errors[0].message : '', - }), - { error: true } - ); - } - }); + }, + error: (errors) => { + // TO-DO: Check why it's not working as intended. + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.accessNotProvided', { + type: this.translate.instant('common.record.one').toLowerCase(), + error: errorMessageFormatter(errors), + }), + { error: true } + ); + }, + }); } /** @@ -321,6 +321,10 @@ export class FormRecordsComponent * @param id Id of record to delete. */ private deleteRecord(id: string): void { + const recordMutationMessage = { + success: 'common.notifications.objectDeleted', + error: 'common.notifications.objectNotDeleted', + }; this.apollo .mutate({ mutation: DELETE_RECORD, @@ -330,18 +334,11 @@ export class FormRecordsComponent }, }) .subscribe({ - next: ({ errors }) => { - this.handleRecordMutationResponse( - errors, - { - success: 'common.notifications.objectDeleted', - error: 'common.notifications.objectNotDeleted', - }, - id - ); + next: () => { + this.handleRecordMutationResponse([], recordMutationMessage, id); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.handleRecordMutationResponse(errors, recordMutationMessage, id); }, }); } @@ -378,23 +375,17 @@ export class FormRecordsComponent }, }) .subscribe({ - next: ({ errors }) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.dataNotRecovered' - ), - { error: true } - ); - } else { - this.layoutService.setRightSidenav(null); - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.dataRecovered') - ); - } + next: () => { + this.layoutService.setRightSidenav(null); + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.dataRecovered') + ); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.dataNotRecovered'), + { error: true } + ); }, }); } @@ -497,6 +488,10 @@ export class FormRecordsComponent */ public onRestoreRecord(id: string, e: any): void { e.stopPropagation(); + const restoreRecordMessage = { + success: 'common.notifications.objectRestored', + error: 'common.notifications.objectNotRestored', + }; this.apollo .mutate({ mutation: RESTORE_RECORD, @@ -505,18 +500,11 @@ export class FormRecordsComponent }, }) .subscribe({ - next: ({ errors }) => { - this.handleRecordMutationResponse( - errors, - { - success: 'common.notifications.objectRestored', - error: 'common.notifications.objectNotRestored', - }, - id - ); + next: () => { + this.handleRecordMutationResponse([], restoreRecordMessage, id); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.handleRecordMutationResponse(errors, restoreRecordMessage, id); }, }); } @@ -539,7 +527,7 @@ export class FormRecordsComponent this.snackBar.openSnackBar( this.translate.instant(messageKeys.error, { value: this.translate.instant('common.record.one'), - error: errors ? errors[0].message : '', + error: errorMessageFormatter(errors), }), { error: true } ); diff --git a/apps/back-office/src/app/dashboard/pages/forms/forms.component.ts b/apps/back-office/src/app/dashboard/pages/forms/forms.component.ts index 34ab4b1412..3fc5fbd59c 100644 --- a/apps/back-office/src/app/dashboard/pages/forms/forms.component.ts +++ b/apps/back-office/src/app/dashboard/pages/forms/forms.component.ts @@ -12,6 +12,7 @@ import { AddFormMutationResponse, getCachedValues, updateQueryUniqueValues, + errorMessageFormatter, } from '@oort-front/shared'; import { GET_SHORT_FORMS } from './graphql/queries'; import { DELETE_FORM, ADD_FORM } from './graphql/mutations'; @@ -228,32 +229,27 @@ export class FormsComponent extends UnsubscribeComponent implements OnInit { }, }) .subscribe({ - next: ({ errors }) => { - if (!errors) { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectDeleted', { - value: this.translate.instant('common.form.one'), - }) - ); - this.forms = this.forms.filter( - (x) => - x.id !== form.id && form.id !== x.resource?.coreForm?.id - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotDeleted', - { - value: this.translate.instant('common.form.one'), - error: errors ? errors[0].message : '', - } - ), - { error: true } - ); - } + next: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectDeleted', { + value: this.translate.instant('common.form.one'), + }) + ); + this.forms = this.forms.filter( + (x) => x.id !== form.id && form.id !== x.resource?.coreForm?.id + ); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant( + 'common.notifications.objectNotDeleted', + { + value: this.translate.instant('common.form.one'), + error: errorMessageFormatter(errors), + } + ), + { error: true } + ); }, }); } @@ -283,29 +279,25 @@ export class FormsComponent extends UnsubscribeComponent implements OnInit { variables: variablesData, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotCreated', - { - type: this.translate - .instant('common.form.one') - .toLowerCase(), - error: errors ? errors[0].message : '', - } - ), - { error: true } - ); - } else { - if (data) { - const { id } = data.addForm; - this.router.navigate(['/forms/' + id + '/builder']); - } + next: ({ data }) => { + if (data) { + const { id } = data.addForm; + this.router.navigate(['/forms/' + id + '/builder']); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant( + 'common.notifications.objectNotCreated', + { + type: this.translate + .instant('common.form.one') + .toLowerCase(), + error: errorMessageFormatter(errors), + } + ), + { error: true } + ); }, }); } diff --git a/apps/back-office/src/app/dashboard/pages/pull-jobs/pull-jobs.component.ts b/apps/back-office/src/app/dashboard/pages/pull-jobs/pull-jobs.component.ts index a7c3834020..66642be1e7 100644 --- a/apps/back-office/src/app/dashboard/pages/pull-jobs/pull-jobs.component.ts +++ b/apps/back-office/src/app/dashboard/pages/pull-jobs/pull-jobs.component.ts @@ -11,6 +11,7 @@ import { PullJobsNodesQueryResponse, getCachedValues, updateQueryUniqueValues, + errorMessageFormatter, } from '@oort-front/shared'; import { Apollo, QueryRef } from 'apollo-angular'; import { GET_PULL_JOBS } from './graphql/queries'; @@ -177,46 +178,39 @@ export class PullJobsComponent extends UnsubscribeComponent implements OnInit { variables, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { + next: ({ data }) => { + if (data?.addPullJob) { this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotCreated', - { - type: this.translate - .instant('common.pullJob.one') - .toLowerCase(), - error: errors ? errors[0].message : '', - } - ), - { error: true } + this.translate.instant('common.notifications.objectCreated', { + type: this.translate.instant('common.pullJob.one'), + value: value.name, + }) ); - } else { - if (data?.addPullJob) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectCreated', - { - type: this.translate.instant('common.pullJob.one'), - value: value.name, - } - ) + if (this.cachedPullJobs.length === this.pageInfo.length) { + this.cachedPullJobs = this.cachedPullJobs.concat([ + data?.addPullJob, + ]); + this.pullJobs = this.cachedPullJobs.slice( + ITEMS_PER_PAGE * this.pageInfo.pageIndex, + ITEMS_PER_PAGE * (this.pageInfo.pageIndex + 1) ); - if (this.cachedPullJobs.length === this.pageInfo.length) { - this.cachedPullJobs = this.cachedPullJobs.concat([ - data?.addPullJob, - ]); - this.pullJobs = this.cachedPullJobs.slice( - ITEMS_PER_PAGE * this.pageInfo.pageIndex, - ITEMS_PER_PAGE * (this.pageInfo.pageIndex + 1) - ); - } - this.pageInfo.length += 1; } + this.pageInfo.length += 1; } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant( + 'common.notifications.objectNotCreated', + { + type: this.translate + .instant('common.pullJob.one') + .toLowerCase(), + error: errorMessageFormatter(errors), + } + ), + { error: true } + ); }, }); } @@ -253,41 +247,37 @@ export class PullJobsComponent extends UnsubscribeComponent implements OnInit { }, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { + next: ({ data }) => { + if (data?.deletePullJob) { this.snackBar.openSnackBar( this.translate.instant( - 'common.notifications.objectNotDeleted', + 'common.notifications.objectDeleted', { value: this.translate.instant('common.pullJob.one'), - error: errors ? errors[0].message : '', } - ), - { error: true } + ) + ); + this.cachedPullJobs = this.cachedPullJobs.filter( + (x) => x.id !== data?.deletePullJob.id + ); + this.pageInfo.length -= 1; + this.pullJobs = this.cachedPullJobs.slice( + ITEMS_PER_PAGE * this.pageInfo.pageIndex, + ITEMS_PER_PAGE * (this.pageInfo.pageIndex + 1) ); - } else { - if (data?.deletePullJob) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectDeleted', - { - value: this.translate.instant('common.pullJob.one'), - } - ) - ); - this.cachedPullJobs = this.cachedPullJobs.filter( - (x) => x.id !== data?.deletePullJob.id - ); - this.pageInfo.length -= 1; - this.pullJobs = this.cachedPullJobs.slice( - ITEMS_PER_PAGE * this.pageInfo.pageIndex, - ITEMS_PER_PAGE * (this.pageInfo.pageIndex + 1) - ); - } } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant( + 'common.notifications.objectNotDeleted', + { + value: this.translate.instant('common.pullJob.one'), + error: errorMessageFormatter(errors), + } + ), + { error: true } + ); }, }); } @@ -338,48 +328,41 @@ export class PullJobsComponent extends UnsubscribeComponent implements OnInit { variables, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { + next: ({ data }) => { + if (data?.editPullJob) { this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotUpdated', - { - value: this.translate.instant('common.pullJob.one'), - error: errors ? errors[0].message : '', - } - ), - { error: true } + this.translate.instant('common.notifications.objectUpdated', { + type: this.translate + .instant('common.pullJob.one') + .toLowerCase(), + value: value.name, + }) ); - } else { - if (data?.editPullJob) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectUpdated', - { - type: this.translate - .instant('common.pullJob.one') - .toLowerCase(), - value: value.name, - } - ) - ); - this.cachedPullJobs = this.cachedPullJobs.map( - (pullJob: PullJob) => { - if (pullJob.id === data?.editPullJob.id) { - pullJob = data?.editPullJob || pullJob; - } - return pullJob; + this.cachedPullJobs = this.cachedPullJobs.map( + (pullJob: PullJob) => { + if (pullJob.id === data?.editPullJob.id) { + pullJob = data?.editPullJob || pullJob; } - ); - this.pullJobs = this.cachedPullJobs.slice( - ITEMS_PER_PAGE * this.pageInfo.pageIndex, - ITEMS_PER_PAGE * (this.pageInfo.pageIndex + 1) - ); - } + return pullJob; + } + ); + this.pullJobs = this.cachedPullJobs.slice( + ITEMS_PER_PAGE * this.pageInfo.pageIndex, + ITEMS_PER_PAGE * (this.pageInfo.pageIndex + 1) + ); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant( + 'common.notifications.objectNotUpdated', + { + value: this.translate.instant('common.pullJob.one'), + error: errorMessageFormatter(errors), + } + ), + { error: true } + ); }, }); } diff --git a/apps/back-office/src/app/dashboard/pages/reference-data/reference-data.component.ts b/apps/back-office/src/app/dashboard/pages/reference-data/reference-data.component.ts index f5d1b00c8e..74a7e4feb8 100644 --- a/apps/back-office/src/app/dashboard/pages/reference-data/reference-data.component.ts +++ b/apps/back-office/src/app/dashboard/pages/reference-data/reference-data.component.ts @@ -27,6 +27,7 @@ import { ApiConfigurationQueryResponse, EditReferenceDataMutationResponse, paginationStrategy, + errorMessageFormatter, } from '@oort-front/shared'; import { Apollo, QueryRef } from 'apollo-angular'; import { EDIT_REFERENCE_DATA } from './graphql/mutations'; @@ -399,24 +400,21 @@ export class ReferenceDataComponent this.loadApiConfigurations(type); }); this.loading = loading; - } else { - this.snackBar.openSnackBar( - this.translateService.instant( - 'common.notifications.accessNotProvided', - { - type: this.translateService - .instant('notification.term.resource') - .toLowerCase(), - error: '', - } - ), - { error: true } - ); - this.router.navigate(['/referencedata']); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: () => { + this.snackBar.openSnackBar( + this.translateService.instant( + 'common.notifications.accessNotProvided', + { + type: this.translateService + .instant('notification.term.resource') + .toLowerCase(), + error: '', + } + ), + { error: true } + ); this.router.navigate(['/referencedata']); }, }); @@ -502,11 +500,11 @@ export class ReferenceDataComponent }, }) .subscribe({ - next: ({ errors, data, loading }) => { - this.handleEditReferenceDataResponse(data, errors, loading); + next: ({ data, loading }) => { + this.handleEditReferenceDataResponse(data, [], loading); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.handleEditReferenceDataResponse(null, errors, false); }, }); } @@ -529,7 +527,7 @@ export class ReferenceDataComponent this.snackBar.openSnackBar( this.translateService.instant('common.notifications.objectNotUpdated', { type: this.translateService.instant('common.referenceData.one'), - error: errors ? errors[0].message : '', + error: errorMessageFormatter(errors), }), { error: true } ); @@ -682,11 +680,11 @@ export class ReferenceDataComponent variables, }) .subscribe({ - next: ({ errors, data, loading }) => { - this.handleEditReferenceDataResponse(data, errors, loading, true); + next: ({ data, loading }) => { + this.handleEditReferenceDataResponse(data, [], loading, true); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.handleEditReferenceDataResponse(null, errors, false, true); }, }); } diff --git a/apps/back-office/src/app/dashboard/pages/reference-datas/reference-datas.component.ts b/apps/back-office/src/app/dashboard/pages/reference-datas/reference-datas.component.ts index 4ebf821c8b..15fe17cf7e 100644 --- a/apps/back-office/src/app/dashboard/pages/reference-datas/reference-datas.component.ts +++ b/apps/back-office/src/app/dashboard/pages/reference-datas/reference-datas.component.ts @@ -9,6 +9,7 @@ import { ReferenceDatasQueryResponse, getCachedValues, updateQueryUniqueValues, + errorMessageFormatter, } from '@oort-front/shared'; import { GET_REFERENCE_DATAS } from './graphql/queries'; import { ADD_REFERENCE_DATA, DELETE_REFERENCE_DATA } from './graphql/mutations'; @@ -169,31 +170,27 @@ export class ReferenceDatasComponent }, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotCreated', - { - type: this.translate - .instant('common.referenceData.one') - .toLowerCase(), - error: errors ? errors[0].message : '', - } - ), - { error: true } - ); - } else { - if (data) { - this.router.navigate([ - '/referencedata', - data.addReferenceData.id, - ]); - } + next: ({ data }) => { + if (data) { + this.router.navigate([ + '/referencedata', + data.addReferenceData.id, + ]); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant( + 'common.notifications.objectNotCreated', + { + type: this.translate + .instant('common.referenceData.one') + .toLowerCase(), + error: errorMessageFormatter(errors), + } + ), + { error: true } + ); }, }); } @@ -230,7 +227,7 @@ export class ReferenceDatasComponent }) .subscribe({ next: (res) => { - if (res && !res.errors) { + if (res) { this.snackBar.openSnackBar( this.translate.instant('common.notifications.objectDeleted', { value: this.translate.instant('common.referenceData.one'), @@ -239,25 +236,19 @@ export class ReferenceDatasComponent this.dataSource = this.dataSource.filter( (x) => x.id !== element.id ); - } else { - if (res.errors) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotDeleted', - { - value: this.translate.instant( - 'common.referenceData.one' - ), - error: res.errors ? res.errors[0] : '', - } - ), - { error: true } - ); - } } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant( + 'common.notifications.objectNotDeleted', + { + value: this.translate.instant('common.referenceData.one'), + error: errorMessageFormatter(errors), + } + ), + { error: true } + ); }, }); } diff --git a/apps/back-office/src/app/dashboard/pages/resource/aggregations-tab/aggregations-tab.component.ts b/apps/back-office/src/app/dashboard/pages/resource/aggregations-tab/aggregations-tab.component.ts index d769dc4d5e..d44cbcb70b 100644 --- a/apps/back-office/src/app/dashboard/pages/resource/aggregations-tab/aggregations-tab.component.ts +++ b/apps/back-office/src/app/dashboard/pages/resource/aggregations-tab/aggregations-tab.component.ts @@ -10,12 +10,17 @@ import { ResourceQueryResponse, getCachedValues, updateQueryUniqueValues, + errorMessageFormatter, } from '@oort-front/shared'; import { Apollo, QueryRef } from 'apollo-angular'; import get from 'lodash/get'; import { GET_RESOURCE_AGGREGATIONS } from './graphql/queries'; import { takeUntil } from 'rxjs'; -import { UIPageChangeEvent, handleTablePageEvent } from '@oort-front/ui'; +import { + SnackbarService, + UIPageChangeEvent, + handleTablePageEvent, +} from '@oort-front/ui'; /** * Aggregations tab of resource page @@ -84,7 +89,8 @@ export class AggregationsTabComponent private dialog: Dialog, private aggregationService: AggregationService, private confirmService: ConfirmService, - private translate: TranslateService + private translate: TranslateService, + private snackbarService: SnackbarService ) { super(); } @@ -189,11 +195,21 @@ export class AggregationsTabComponent if (value) { this.aggregationService .addAggregation(value, { resource: this.resource.id }) - .subscribe(({ data }: any) => { - if (data.addAggregation) { - this.aggregations = [...this.aggregations, data?.addAggregation]; - this.pageInfo.length += 1; - } + .subscribe({ + next: ({ data }: any) => { + if (data.addAggregation) { + this.aggregations = [ + ...this.aggregations, + data?.addAggregation, + ]; + this.pageInfo.length += 1; + } + }, + error: (errors) => { + this.snackbarService.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); + }, }); } }); diff --git a/apps/back-office/src/app/dashboard/pages/resource/calculated-fields-tab/calculated-fields-tab.component.ts b/apps/back-office/src/app/dashboard/pages/resource/calculated-fields-tab/calculated-fields-tab.component.ts index ab97be7a30..2fa552dd21 100644 --- a/apps/back-office/src/app/dashboard/pages/resource/calculated-fields-tab/calculated-fields-tab.component.ts +++ b/apps/back-office/src/app/dashboard/pages/resource/calculated-fields-tab/calculated-fields-tab.component.ts @@ -4,6 +4,7 @@ import { EditResourceMutationResponse, Resource, UnsubscribeComponent, + errorMessageFormatter, } from '@oort-front/shared'; import { Apollo } from 'apollo-angular'; import get from 'lodash/get'; @@ -160,14 +161,11 @@ export class CalculatedFieldsTabComponent ) ); } - if (res.errors) { - this.snackBar.openSnackBar(res.errors[0].message, { - error: true, - }); - } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); }, }); } @@ -217,14 +215,11 @@ export class CalculatedFieldsTabComponent (f: any) => f.name !== field.name ); } - if (res.errors) { - this.snackBar.openSnackBar(res.errors[0].message, { - error: true, - }); - } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); }, }); } diff --git a/apps/back-office/src/app/dashboard/pages/resource/forms-tab/forms-tab.component.ts b/apps/back-office/src/app/dashboard/pages/resource/forms-tab/forms-tab.component.ts index f9caa958cf..73e3be4a39 100644 --- a/apps/back-office/src/app/dashboard/pages/resource/forms-tab/forms-tab.component.ts +++ b/apps/back-office/src/app/dashboard/pages/resource/forms-tab/forms-tab.component.ts @@ -7,6 +7,7 @@ import { ConfirmService, UnsubscribeComponent, ResourceQueryResponse, + errorMessageFormatter, } from '@oort-front/shared'; import { TranslateService } from '@ngx-translate/core'; import { DELETE_FORM } from './graphql/mutations'; @@ -119,29 +120,25 @@ export class FormsTabComponent extends UnsubscribeComponent implements OnInit { }, }) .subscribe({ - next: ({ errors }) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotDeleted', - { - value: this.translate.instant('common.form.one'), - error: errors ? errors[0].message : '', - } - ), - { error: true } - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectDeleted', { - value: this.translate.instant('common.form.one'), - }) - ); - this.forms = this.forms.filter((x: any) => x.id !== form.id); - } + next: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectDeleted', { + value: this.translate.instant('common.form.one'), + }) + ); + this.forms = this.forms.filter((x: any) => x.id !== form.id); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant( + 'common.notifications.objectNotDeleted', + { + value: this.translate.instant('common.form.one'), + error: errorMessageFormatter(errors), + } + ), + { error: true } + ); }, }); } diff --git a/apps/back-office/src/app/dashboard/pages/resource/records-tab/records-tab.component.ts b/apps/back-office/src/app/dashboard/pages/resource/records-tab/records-tab.component.ts index 8fcf8f6c35..8f3863172c 100644 --- a/apps/back-office/src/app/dashboard/pages/resource/records-tab/records-tab.component.ts +++ b/apps/back-office/src/app/dashboard/pages/resource/records-tab/records-tab.component.ts @@ -12,6 +12,7 @@ import { RestoreRecordMutationResponse, getCachedValues, updateQueryUniqueValues, + errorMessageFormatter, } from '@oort-front/shared'; import { Apollo, QueryRef } from 'apollo-angular'; import get from 'lodash/get'; @@ -177,6 +178,10 @@ export class RecordsTabComponent * @param id Id of record to delete. */ private deleteRecord(id: string): void { + const deleteRecordMessage = { + success: 'common.notifications.objectDeleted', + error: 'common.notifications.objectNotDeleted', + }; this.apollo .mutate({ mutation: DELETE_RECORD, @@ -186,17 +191,11 @@ export class RecordsTabComponent }, }) .subscribe({ - next: ({ errors }) => { - this.handleRecordMutationResponse( - { - success: 'common.notifications.objectDeleted', - error: 'common.notifications.objectNotDeleted', - }, - errors - ); + next: () => { + this.handleRecordMutationResponse(deleteRecordMessage, []); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.handleRecordMutationResponse(deleteRecordMessage, errors); }, }); } @@ -220,7 +219,7 @@ export class RecordsTabComponent this.snackBar.openSnackBar( this.translate.instant(messageKeys.error, { value: this.translate.instant('common.record.one'), - error: errors ? errors[0].message : '', + error: errorMessageFormatter(errors), }), { error: true } ); @@ -242,6 +241,10 @@ export class RecordsTabComponent */ public onRestoreRecord(id: string, e: any): void { e.stopPropagation(); + const restoreRecordMessage = { + success: 'common.notifications.objectRestored', + error: 'common.notifications.objectNotRestored', + }; this.apollo .mutate({ mutation: RESTORE_RECORD, @@ -250,17 +253,11 @@ export class RecordsTabComponent }, }) .subscribe({ - next: ({ errors }) => { - this.handleRecordMutationResponse( - { - success: 'common.notifications.objectRestored', - error: 'common.notifications.objectNotRestored', - }, - errors - ); + next: () => { + this.handleRecordMutationResponse(restoreRecordMessage, []); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.handleRecordMutationResponse(restoreRecordMessage, errors); }, }); } diff --git a/apps/back-office/src/app/dashboard/pages/resource/resource.component.ts b/apps/back-office/src/app/dashboard/pages/resource/resource.component.ts index 011d1e688c..03bbc4093a 100644 --- a/apps/back-office/src/app/dashboard/pages/resource/resource.component.ts +++ b/apps/back-office/src/app/dashboard/pages/resource/resource.component.ts @@ -5,6 +5,7 @@ import { EditResourceMutationResponse, ResourceQueryResponse, BreadcrumbService, + errorMessageFormatter, } from '@oort-front/shared'; import { EDIT_RESOURCE } from './graphql/mutations'; import { GET_RESOURCE_BY_ID } from './graphql/queries'; @@ -104,21 +105,16 @@ export class ResourceComponent implements OnInit { ); history.pushState({ resource: this.resource }, ''); this.loading = loading; - } else { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.accessNotProvided', { - type: this.translate - .instant('common.resource.one') - .toLowerCase(), - error: '', - }), - { error: true } - ); - this.router.navigate(['/resources']); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.accessNotProvided', { + type: this.translate.instant('common.resource.one').toLowerCase(), + error: '', + }), + { error: true } + ); this.router.navigate(['/resources']); }, }); @@ -139,29 +135,25 @@ export class ResourceComponent implements OnInit { }, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectNotUpdated', { - type: this.translate.instant('common.resource.one'), - error: errors ? errors[0].message : '', - }), - { error: true } - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectUpdated', { - type: this.translate.instant('common.resource.one'), - value: '', - }) - ); - if (data) { - this.resource = data.editResource; - } + next: ({ data }) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectUpdated', { + type: this.translate.instant('common.resource.one'), + value: '', + }) + ); + if (data) { + this.resource = data.editResource; } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectNotUpdated', { + type: this.translate.instant('common.resource.one'), + error: errorMessageFormatter(errors), + }), + { error: true } + ); }, }); } diff --git a/apps/back-office/src/app/dashboard/pages/resources/resources.component.ts b/apps/back-office/src/app/dashboard/pages/resources/resources.component.ts index 108b5ed3cf..cc41d802f2 100644 --- a/apps/back-office/src/app/dashboard/pages/resources/resources.component.ts +++ b/apps/back-office/src/app/dashboard/pages/resources/resources.component.ts @@ -11,6 +11,7 @@ import { ResourcesQueryResponse, getCachedValues, updateQueryUniqueValues, + errorMessageFormatter, } from '@oort-front/shared'; import { Router } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; @@ -244,8 +245,8 @@ export class ResourcesComponent extends UnsubscribeComponent implements OnInit { id: resource.id, }, }) - .subscribe(({ errors }) => { - if (!errors) { + .subscribe({ + next: () => { this.resources = this.resources.filter( (x) => x.id !== resource.id ); @@ -254,18 +255,19 @@ export class ResourcesComponent extends UnsubscribeComponent implements OnInit { value: this.translate.instant('common.resource.one'), }) ); - } else { + }, + error: (errors) => { this.snackBar.openSnackBar( this.translate.instant( 'common.notifications.objectNotDeleted', { value: this.translate.instant('common.resource.one'), - error: errors[0].message, + error: errorMessageFormatter(errors), } ), { error: true } ); - } + }, }); } }); @@ -289,29 +291,25 @@ export class ResourcesComponent extends UnsubscribeComponent implements OnInit { variables: variablesData, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotCreated', - { - type: this.translate - .instant('common.form.one') - .toLowerCase(), - error: errors[0].message, - } - ), - { error: true } - ); - } else { - if (data) { - const { id } = data.addForm; - this.router.navigate(['/forms/builder', id]); - } + next: ({ data }) => { + if (data) { + const { id } = data.addForm; + this.router.navigate(['/forms/builder', id]); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant( + 'common.notifications.objectNotCreated', + { + type: this.translate + .instant('common.form.one') + .toLowerCase(), + error: errorMessageFormatter(errors), + } + ), + { error: true } + ); }, }); } diff --git a/apps/back-office/src/app/dashboard/pages/users/users.component.ts b/apps/back-office/src/app/dashboard/pages/users/users.component.ts index 8b172191db..4418bdbf6b 100644 --- a/apps/back-office/src/app/dashboard/pages/users/users.component.ts +++ b/apps/back-office/src/app/dashboard/pages/users/users.component.ts @@ -12,6 +12,7 @@ import { UnsubscribeComponent, User, UsersNodeQueryResponse, + errorMessageFormatter, getCachedValues, updateQueryUniqueValues, } from '@oort-front/shared'; @@ -166,36 +167,35 @@ export class UsersComponent extends UnsubscribeComponent implements OnInit { }, }) .subscribe({ - next: ({ errors, data }) => { - if (!errors) { - if (data?.addUsers.length) { - this.snackBar.openSnackBar( - this.translate.instant('components.users.onInvite.plural') - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant('components.users.onInvite.singular') - ); - } - this.fetchUsers(true); + next: ({ data }) => { + if (data?.addUsers.length) { + this.snackBar.openSnackBar( + this.translate.instant('components.users.onInvite.plural') + ); } else { - if (value.length > 1) { - this.snackBar.openSnackBar( - this.translate.instant( - 'components.users.onNotInvite.plural', - { error: errors[0].message } - ), - { error: true } - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant( - 'components.users.onNotInvite.singular', - { error: errors[0].message } - ), - { error: true } - ); - } + this.snackBar.openSnackBar( + this.translate.instant('components.users.onInvite.singular') + ); + } + this.fetchUsers(true); + }, + error: (errors) => { + if (value.length > 1) { + this.snackBar.openSnackBar( + this.translate.instant( + 'components.users.onNotInvite.plural', + { error: errorMessageFormatter(errors) } + ), + { error: true } + ); + } else { + this.snackBar.openSnackBar( + this.translate.instant( + 'components.users.onNotInvite.singular', + { error: errorMessageFormatter(errors) } + ), + { error: true } + ); } }, }); @@ -247,13 +247,25 @@ export class UsersComponent extends UnsubscribeComponent implements OnInit { variables: { ids }, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { + next: ({ data }) => { + this.loading = false; + if (data?.deleteUsers) { + if (data.deleteUsers > 1) { + this.snackBar.openSnackBar( + this.translate.instant('components.users.onDelete.plural') + ); + } else { + this.snackBar.openSnackBar( + this.translate.instant('components.users.onDelete.singular') + ); + } + this.fetchUsers(true); + } else { if (ids.length > 1) { this.snackBar.openSnackBar( this.translate.instant( 'components.users.onNotDelete.plural', - { error: errors ? errors[0].message : '' } + { error: '' } ), { error: true } ); @@ -261,45 +273,30 @@ export class UsersComponent extends UnsubscribeComponent implements OnInit { this.snackBar.openSnackBar( this.translate.instant( 'components.users.onNotDelete.singular', - { error: errors ? errors[0].message : '' } + { error: '' } ), { error: true } ); } + } + }, + error: (errors) => { + if (ids.length > 1) { + this.snackBar.openSnackBar( + this.translate.instant( + 'components.users.onNotDelete.plural', + { error: errorMessageFormatter(errors) } + ), + { error: true } + ); } else { - this.loading = false; - if (data?.deleteUsers) { - if (data.deleteUsers > 1) { - this.snackBar.openSnackBar( - this.translate.instant('components.users.onDelete.plural') - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant( - 'components.users.onDelete.singular' - ) - ); - } - this.fetchUsers(true); - } else { - if (ids.length > 1) { - this.snackBar.openSnackBar( - this.translate.instant( - 'components.users.onNotDelete.plural', - { error: '' } - ), - { error: true } - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant( - 'components.users.onNotDelete.singular', - { error: '' } - ), - { error: true } - ); - } - } + this.snackBar.openSnackBar( + this.translate.instant( + 'components.users.onNotDelete.singular', + { error: errorMessageFormatter(errors) } + ), + { error: true } + ); } }, }); diff --git a/apps/front-office/src/app/app.module.ts b/apps/front-office/src/app/app.module.ts index 258f69fbbd..e93ac7448a 100644 --- a/apps/front-office/src/app/app.module.ts +++ b/apps/front-office/src/app/app.module.ts @@ -29,6 +29,7 @@ import { AuthInterceptorService, FormService, DatePipe, + ErrorHandlerInterceptorService, } from '@oort-front/shared'; import { registerLocaleData } from '@angular/common'; import localeFr from '@angular/common/locales/fr'; @@ -142,6 +143,11 @@ export const httpTranslateLoader = (http: HttpClient) => useClass: AuthInterceptorService, multi: true, }, + { + provide: HTTP_INTERCEPTORS, + useClass: ErrorHandlerInterceptorService, + multi: true, + }, { provide: AppAbility, useValue: new AppAbility(), diff --git a/apps/front-office/src/app/application/pages/workflow/workflow.component.ts b/apps/front-office/src/app/application/pages/workflow/workflow.component.ts index 4502a707fc..2d4da4117f 100644 --- a/apps/front-office/src/app/application/pages/workflow/workflow.component.ts +++ b/apps/front-office/src/app/application/pages/workflow/workflow.component.ts @@ -115,23 +115,18 @@ export class WorkflowComponent extends UnsubscribeComponent implements OnInit { } this.onOpenStep(currentActiveStep); } - } else { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.accessNotProvided', - { - type: this.translate - .instant('common.workflow.one') - .toLowerCase(), - error: '', - } - ), - { error: true } - ); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.accessNotProvided', { + type: this.translate + .instant('common.workflow.one') + .toLowerCase(), + error: '', + }), + { error: true } + ); }, }); }); diff --git a/apps/web-widgets/src/app/widgets/app-widget/application/pages/workflow/workflow.component.ts b/apps/web-widgets/src/app/widgets/app-widget/application/pages/workflow/workflow.component.ts index b56353070e..e6f812b8b4 100644 --- a/apps/web-widgets/src/app/widgets/app-widget/application/pages/workflow/workflow.component.ts +++ b/apps/web-widgets/src/app/widgets/app-widget/application/pages/workflow/workflow.component.ts @@ -98,23 +98,18 @@ export class WorkflowComponent extends UnsubscribeComponent implements OnInit { } this.onOpenStep(currentActiveStep); } - } else { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.accessNotProvided', - { - type: this.translate - .instant('common.workflow.one') - .toLowerCase(), - error: '', - } - ), - { error: true } - ); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.accessNotProvided', { + type: this.translate + .instant('common.workflow.one') + .toLowerCase(), + error: '', + }), + { error: true } + ); }, }); }); diff --git a/libs/shared/src/index.ts b/libs/shared/src/index.ts index dc5819fa79..3c50b51cf2 100644 --- a/libs/shared/src/index.ts +++ b/libs/shared/src/index.ts @@ -25,6 +25,7 @@ export * from './lib/services/data-template/data-template.service'; export * from './lib/services/editor/editor.service'; export * from './lib/services/rest/rest.service'; export * from './lib/services/map/map-layers.service'; +export * from './lib/interceptors/error-handler/error-handler-interceptor.service'; // === DIRECTIVES === export * from './lib/directives/skeleton/public-api'; diff --git a/libs/shared/src/lib/components/form-modal/form-modal.component.ts b/libs/shared/src/lib/components/form-modal/form-modal.component.ts index 111070be3a..b50a744a26 100644 --- a/libs/shared/src/lib/components/form-modal/form-modal.component.ts +++ b/libs/shared/src/lib/components/form-modal/form-modal.component.ts @@ -41,6 +41,7 @@ import { UnsubscribeComponent } from '../utils/unsubscribe/unsubscribe.component import { FormHelpersService } from '../../services/form-helper/form-helper.service'; import { DialogModule } from '@oort-front/ui'; import { DraftRecordComponent } from '../draft-record/draft-record.component'; +import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; /** * Interface of Dialog data. @@ -353,34 +354,33 @@ export class FormModalComponent }, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { - this.snackBar.openSnackBar(`Error. ${errors[0].message}`, { - error: true, - }); - this.ngZone.run(() => { - this.dialogRef.close(); - }); - } else { - if (this.lastDraftRecord) { - const callback = () => { - this.lastDraftRecord = undefined; - }; - this.formHelpersService.deleteRecordDraft( - this.lastDraftRecord, - callback - ); - } - this.ngZone.run(() => { - this.dialogRef.close({ - template: this.data.template, - data: data?.addRecord, - } as any); - }); + next: ({ data }) => { + if (this.lastDraftRecord) { + const callback = () => { + this.lastDraftRecord = undefined; + }; + this.formHelpersService.deleteRecordDraft( + this.lastDraftRecord, + callback + ); } + this.ngZone.run(() => { + this.dialogRef.close({ + template: this.data.template, + data: data?.addRecord, + } as any); + }); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + `Error. ${errorMessageFormatter(errors)}`, + { + error: true, + } + ); + this.ngZone.run(() => { + this.dialogRef.close(); + }); }, }); } @@ -404,11 +404,14 @@ export class FormModalComponent }, }) .subscribe({ - next: ({ errors, data }) => { - this.handleRecordMutationResponse({ data, errors }, 'editRecord'); + next: ({ data }) => { + this.handleRecordMutationResponse({ data, errors: [] }, 'editRecord'); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.handleRecordMutationResponse( + { data: null, errors }, + 'editRecord' + ); }, }); } @@ -431,7 +434,7 @@ export class FormModalComponent }, }) .subscribe({ - next: ({ errors, data }) => { + next: ({ data }) => { if (this.lastDraftRecord) { const callback = () => { this.lastDraftRecord = undefined; @@ -441,10 +444,16 @@ export class FormModalComponent callback ); } - this.handleRecordMutationResponse({ data, errors }, 'editRecords'); + this.handleRecordMutationResponse( + { data, errors: [] }, + 'editRecords' + ); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.handleRecordMutationResponse( + { data: null, errors }, + 'editRecords' + ); }, }); } @@ -466,11 +475,11 @@ export class FormModalComponent responseType === 'editRecords' ? this.translate.instant('common.record.few') : this.translate.instant('common.record.one'); - if (errors) { + if (errors?.length) { this.snackBar.openSnackBar( this.translate.instant('common.notifications.objectNotUpdated', { type, - error: errors ? errors[0].message : '', + error: errorMessageFormatter(errors), }), { error: true } ); @@ -619,23 +628,19 @@ export class FormModalComponent }, }) .subscribe({ - next: (errors) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.dataNotRecovered' - ), - { error: true } - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.dataRecovered') - ); - } + next: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.dataRecovered') + ); + this.dialog.closeAll(); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.dataNotRecovered'), + { error: true } + ); + this.dialog.closeAll(); }, }); } diff --git a/libs/shared/src/lib/components/form/form.component.ts b/libs/shared/src/lib/components/form/form.component.ts index 3eb88d0527..84d104b1e2 100644 --- a/libs/shared/src/lib/components/form/form.component.ts +++ b/libs/shared/src/lib/components/form/form.component.ts @@ -28,6 +28,7 @@ import { UnsubscribeComponent } from '../utils/unsubscribe/unsubscribe.component import { FormHelpersService } from '../../services/form-helper/form-helper.service'; import { SnackbarService, UILayoutService } from '@oort-front/ui'; import { isNil } from 'lodash'; +import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; /** * This component is used to display forms @@ -300,7 +301,9 @@ export class FormComponent this.save.emit({ completed: false }); this.survey.clear(false, true); this.surveyActive = true; - this.snackBar.openSnackBar(errors[0].message, { error: true }); + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); } else { if (this.lastDraftRecord) { const callback = () => { @@ -405,23 +408,17 @@ export class FormComponent }, }) .subscribe({ - next: ({ errors }) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.dataNotRecovered' - ), - { error: true } - ); - } else { - this.layoutService.setRightSidenav(null); - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.dataRecovered') - ); - } + next: () => { + this.layoutService.setRightSidenav(null); + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.dataRecovered') + ); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.dataNotRecovered'), + { error: true } + ); }, }); } diff --git a/libs/shared/src/lib/components/record-history/record-history.component.ts b/libs/shared/src/lib/components/record-history/record-history.component.ts index 7111eab7e4..afcbe919ae 100644 --- a/libs/shared/src/lib/components/record-history/record-history.component.ts +++ b/libs/shared/src/lib/components/record-history/record-history.component.ts @@ -30,6 +30,7 @@ import { FormControl, FormGroup } from '@angular/forms'; import { startCase, isNil } from 'lodash'; import { ResizeEvent } from 'angular-resizable-element'; import { DOCUMENT } from '@angular/common'; +import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; /** * Return the type of the old value if existing, else the type of the new value. @@ -182,16 +183,8 @@ export class RecordHistoryComponent }, }) .pipe(takeUntil(this.destroy$)) - .subscribe(({ errors, data }) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.history.error', { - error: errors[0].message, - }), - { error: true } - ); - this.cancel.emit(true); - } else { + .subscribe({ + next: ({ data }) => { this.history = data.recordHistory.filter( (item) => item.changes.length ); @@ -203,7 +196,17 @@ export class RecordHistoryComponent }); }); this.loading = false; - } + }, + error: (errors) => { + this.loading = false; + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.history.error', { + error: errorMessageFormatter(errors), + }), + { error: true } + ); + this.cancel.emit(true); + }, }); }; if (this.refresh$) { diff --git a/libs/shared/src/lib/components/record-modal/record-modal.component.ts b/libs/shared/src/lib/components/record-modal/record-modal.component.ts index f41e3d156a..45593b4fd5 100644 --- a/libs/shared/src/lib/components/record-modal/record-modal.component.ts +++ b/libs/shared/src/lib/components/record-modal/record-modal.component.ts @@ -303,23 +303,19 @@ export class RecordModalComponent }, }) .subscribe({ - next: (errors) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.dataNotRecovered' - ), - { error: true } - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.dataRecovered') - ); - } + next: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.dataRecovered') + ); + this.dialogRef.close(); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.dataNotRecovered'), + { error: true } + ); + this.dialogRef.close(); }, }); } diff --git a/libs/shared/src/lib/components/role-summary/role-features/role-features.component.ts b/libs/shared/src/lib/components/role-summary/role-features/role-features.component.ts index b3861d3536..7c9786f873 100644 --- a/libs/shared/src/lib/components/role-summary/role-features/role-features.component.ts +++ b/libs/shared/src/lib/components/role-summary/role-features/role-features.component.ts @@ -137,6 +137,7 @@ export class RoleFeaturesComponent implements OnInit { }, error: (err) => { this.snackBar.openSnackBar(err.message, { error: true }); + this.loading = false; }, }); } diff --git a/libs/shared/src/lib/components/role-summary/role-features/role-workflows/role-workflows.component.ts b/libs/shared/src/lib/components/role-summary/role-features/role-workflows/role-workflows.component.ts index 4aa2eda736..41f903be6e 100644 --- a/libs/shared/src/lib/components/role-summary/role-features/role-workflows/role-workflows.component.ts +++ b/libs/shared/src/lib/components/role-summary/role-features/role-workflows/role-workflows.component.ts @@ -185,6 +185,7 @@ export class RoleWorkflowsComponent implements OnInit, OnChanges { }, error: (err) => { this.snackBar.openSnackBar(err.message, { error: true }); + this.loading = false; }, }); } diff --git a/libs/shared/src/lib/components/role-summary/role-resources/role-resources.component.ts b/libs/shared/src/lib/components/role-summary/role-resources/role-resources.component.ts index 75bbb7f230..b6df9e8516 100644 --- a/libs/shared/src/lib/components/role-summary/role-resources/role-resources.component.ts +++ b/libs/shared/src/lib/components/role-summary/role-resources/role-resources.component.ts @@ -29,6 +29,7 @@ import { UIPageChangeEvent, handleTablePageEvent, } from '@oort-front/ui'; +import { errorMessageFormatter } from '../../../utils/graphql/error-message-formatter'; /** Default page size */ const DEFAULT_PAGE_SIZE = 10; @@ -301,12 +302,20 @@ export class RoleResourcesComponent }) .pipe(takeUntil(this.destroy$)) .subscribe({ - next: ({ errors, data }) => { - this.handleResourceMutationResponse(resource, { data, errors }, true); + next: ({ data }) => { + this.handleResourceMutationResponse( + resource, + { data, errors: [] }, + true + ); this.updating = false; }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.handleResourceMutationResponse( + resource, + { data: null, errors }, + true + ); this.updating = false; }, }); @@ -331,12 +340,12 @@ export class RoleResourcesComponent }) .pipe(takeUntil(this.destroy$)) .subscribe({ - next: ({ errors, data }) => { - this.handleResourceMutationResponse(resource, { data, errors }); + next: ({ data }) => { + this.handleResourceMutationResponse(resource, { data, errors: [] }); this.updating = false; }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.handleResourceMutationResponse(resource, { data: null, errors }); this.updating = false; }, }); @@ -378,8 +387,10 @@ export class RoleResourcesComponent this.openedResource = tableElements[index].resource; } } - if (errors) { - this.snackBar.openSnackBar(errors[0].message, { error: true }); + if (errors?.length) { + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); } } @@ -428,12 +439,12 @@ export class RoleResourcesComponent }) .pipe(takeUntil(this.destroy$)) .subscribe({ - next: ({ errors, data }) => { - this.handleResourceMutationResponse(resource, { data, errors }); + next: ({ data }) => { + this.handleResourceMutationResponse(resource, { data, errors: [] }); this.updating = false; }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.handleResourceMutationResponse(resource, { data: null, errors }); this.updating = false; }, }); diff --git a/libs/shared/src/lib/components/roles/components/group-list/group-list.component.ts b/libs/shared/src/lib/components/roles/components/group-list/group-list.component.ts index fb780edafc..b8241992ab 100644 --- a/libs/shared/src/lib/components/roles/components/group-list/group-list.component.ts +++ b/libs/shared/src/lib/components/roles/components/group-list/group-list.component.ts @@ -18,6 +18,7 @@ import { } from '../../../../models/user.model'; import { SnackbarSpinnerComponent } from '../../../snackbar-spinner/snackbar-spinner.component'; import { FormBuilder } from '@angular/forms'; +import { errorMessageFormatter } from '../../../../utils/graphql/error-message-formatter'; /** * This component is used to display the groups tab in the platform @@ -160,32 +161,28 @@ export class GroupListComponent }) .pipe(takeUntil(this.destroy$)) .subscribe({ - next: ({ errors }) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotCreated', - { - type: this.translate - .instant('common.role.one') - .toLowerCase(), - error: errors ? errors[0].message : '', - } - ), - { error: true } - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectCreated', { - type: this.translate.instant('common.role.one'), - value: value.title, - }) - ); - this.getGroups(); - } + next: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectCreated', { + type: this.translate.instant('common.role.one'), + value: value.title, + }) + ); + this.getGroups(); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant( + 'common.notifications.objectNotCreated', + { + type: this.translate + .instant('common.role.one') + .toLowerCase(), + error: errorMessageFormatter(errors), + } + ), + { error: true } + ); }, }); } @@ -230,6 +227,7 @@ export class GroupListComponent ); }, error: () => { + this.loadingFetch = false; snackBarSpinner.instance.message = this.translate.instant( 'common.notifications.groups.error' ); @@ -276,29 +274,27 @@ export class GroupListComponent }) .pipe(takeUntil(this.destroy$)) .subscribe({ - next: ({ errors }) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotDeleted', - { - value: item.title, - error: errors ? errors[0].message : '', - } - ), - { error: true } - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectDeleted', { - value: item.title, - }) - ); - } + next: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectDeleted', { + value: item.title, + }) + ); + this.getGroups(); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant( + 'common.notifications.objectNotDeleted', + { + value: item.title, + error: errorMessageFormatter(errors), + } + ), + { error: true } + ); + this.getGroups(); }, }); } diff --git a/libs/shared/src/lib/components/roles/components/role-list/role-list.component.ts b/libs/shared/src/lib/components/roles/components/role-list/role-list.component.ts index 7b5ca6babd..417c57d636 100644 --- a/libs/shared/src/lib/components/roles/components/role-list/role-list.component.ts +++ b/libs/shared/src/lib/components/roles/components/role-list/role-list.component.ts @@ -18,6 +18,7 @@ import { UnsubscribeComponent } from '../../../utils/unsubscribe/unsubscribe.com import { takeUntil } from 'rxjs/operators'; import { SnackbarService } from '@oort-front/ui'; import { FormBuilder } from '@angular/forms'; +import { errorMessageFormatter } from '../../../../utils/graphql/error-message-formatter'; /** * This component is used to display the back-office roles tab @@ -156,35 +157,28 @@ export class RoleListComponent extends UnsubscribeComponent implements OnInit { }) .pipe(takeUntil(this.destroy$)) .subscribe({ - next: ({ errors }) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotCreated', - { - type: this.translate - .instant('common.role.one') - .toLowerCase(), - error: errors ? errors[0].message : '', - } - ), - { error: true } - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectCreated', - { - type: this.translate.instant('common.role.one'), - value: value.title, - } - ) - ); - this.getRoles(); - } + next: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectCreated', { + type: this.translate.instant('common.role.one'), + value: value.title, + }) + ); + this.getRoles(); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant( + 'common.notifications.objectNotCreated', + { + type: this.translate + .instant('common.role.one') + .toLowerCase(), + error: errorMessageFormatter(errors), + } + ), + { error: true } + ); }, }); } @@ -224,32 +218,25 @@ export class RoleListComponent extends UnsubscribeComponent implements OnInit { }) .pipe(takeUntil(this.destroy$)) .subscribe({ - next: ({ errors }) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotDeleted', - { - value: item.title, - error: errors ? errors[0].message : '', - } - ), - { error: true } - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectDeleted', - { - value: item.title, - } - ) - ); - this.getRoles(); - } + next: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectDeleted', { + value: item.title, + }) + ); + this.getRoles(); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant( + 'common.notifications.objectNotDeleted', + { + value: item.title, + error: errorMessageFormatter(errors), + } + ), + { error: true } + ); }, }); } diff --git a/libs/shared/src/lib/components/ui/aggregation-builder/aggregation-builder.component.ts b/libs/shared/src/lib/components/ui/aggregation-builder/aggregation-builder.component.ts index 53ce57940b..16af73f8f1 100644 --- a/libs/shared/src/lib/components/ui/aggregation-builder/aggregation-builder.component.ts +++ b/libs/shared/src/lib/components/ui/aggregation-builder/aggregation-builder.component.ts @@ -19,6 +19,7 @@ import { } from '../../../models/aggregation.model'; import { getReferenceMetadata } from '../../../utils/reference-data-metadata.util'; import { PipelineStage } from './pipeline/pipeline-stage.enum'; +import { errorMessageFormatter } from '../../../utils/graphql/error-message-formatter'; /** * Main component of Aggregation builder. @@ -313,7 +314,9 @@ export class AggregationBuilderComponent if (!aggregationData || errors) { this.loadingAggregationRecords = false; if (errors?.length) { - this.snackBar.openSnackBar(errors[0].message, { error: true }); + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); } return; } diff --git a/libs/shared/src/lib/components/ui/core-grid/core-grid.component.ts b/libs/shared/src/lib/components/ui/core-grid/core-grid.component.ts index 1b5fc834a0..775363d4f0 100644 --- a/libs/shared/src/lib/components/ui/core-grid/core-grid.component.ts +++ b/libs/shared/src/lib/components/ui/core-grid/core-grid.component.ts @@ -1343,24 +1343,18 @@ export class CoreGridComponent }) .pipe(takeUntil(this.destroy$)) .subscribe({ - next: ({ errors }) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.dataNotRecovered' - ), - { error: true } - ); - } else { - this.reloadData(); - this.layoutService.setRightSidenav(null); - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.dataRecovered') - ); - } + next: () => { + this.reloadData(); + this.layoutService.setRightSidenav(null); + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.dataRecovered') + ); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.dataNotRecovered'), + { error: true } + ); }, }); } diff --git a/libs/shared/src/lib/components/user-summary/user-roles/user-app-roles/user-app-roles.component.ts b/libs/shared/src/lib/components/user-summary/user-roles/user-app-roles/user-app-roles.component.ts index e96dac698b..6c0e9594f9 100644 --- a/libs/shared/src/lib/components/user-summary/user-roles/user-app-roles/user-app-roles.component.ts +++ b/libs/shared/src/lib/components/user-summary/user-roles/user-app-roles/user-app-roles.component.ts @@ -163,6 +163,7 @@ export class UserAppRolesComponent }, error: (err) => { this.snackBar.openSnackBar(err.message, { error: true }); + this.loading = false; }, }); } diff --git a/libs/shared/src/lib/components/user-summary/user-roles/user-back-roles/user-back-roles.component.ts b/libs/shared/src/lib/components/user-summary/user-roles/user-back-roles/user-back-roles.component.ts index 9d3914a1ac..1413b6078f 100644 --- a/libs/shared/src/lib/components/user-summary/user-roles/user-back-roles/user-back-roles.component.ts +++ b/libs/shared/src/lib/components/user-summary/user-roles/user-back-roles/user-back-roles.component.ts @@ -64,6 +64,7 @@ export class UserBackRolesComponent implements OnInit { }, error: (err) => { this.snackBar.openSnackBar(err.message, { error: true }); + this.loading = false; }, }); } diff --git a/libs/shared/src/lib/components/user-summary/user-roles/user-groups/user-groups.component.ts b/libs/shared/src/lib/components/user-summary/user-roles/user-groups/user-groups.component.ts index 768cfafd19..60e23ad548 100644 --- a/libs/shared/src/lib/components/user-summary/user-roles/user-groups/user-groups.component.ts +++ b/libs/shared/src/lib/components/user-summary/user-roles/user-groups/user-groups.component.ts @@ -71,6 +71,7 @@ export class UserGroupsComponent implements OnInit { }, error: (err) => { this.snackBar.openSnackBar(err.message, { error: true }); + this.loading = false; }, }); } diff --git a/libs/shared/src/lib/components/user-summary/user-summary.component.ts b/libs/shared/src/lib/components/user-summary/user-summary.component.ts index fb34f76665..9791bed679 100644 --- a/libs/shared/src/lib/components/user-summary/user-summary.component.ts +++ b/libs/shared/src/lib/components/user-summary/user-summary.component.ts @@ -77,6 +77,7 @@ export class UserSummaryComponent implements OnInit { }, error: (err) => { this.snackBar.openSnackBar(err.message, { error: true }); + this.loading = false; }, }); } @@ -105,6 +106,7 @@ export class UserSummaryComponent implements OnInit { }, error: (err) => { this.snackBar.openSnackBar(err.message, { error: true }); + this.loading = false; }, }); } @@ -142,6 +144,7 @@ export class UserSummaryComponent implements OnInit { }, error: (err) => { this.snackBar.openSnackBar(err.message, { error: true }); + this.loading = false; }, }); } diff --git a/libs/shared/src/lib/components/users/invite-users-modal/invite-users-modal.component.ts b/libs/shared/src/lib/components/users/invite-users-modal/invite-users-modal.component.ts index a367122234..1b48e72a78 100644 --- a/libs/shared/src/lib/components/users/invite-users-modal/invite-users-modal.component.ts +++ b/libs/shared/src/lib/components/users/invite-users-modal/invite-users-modal.component.ts @@ -20,6 +20,7 @@ import { TranslateModule } from '@ngx-translate/core'; import { UploadsModule } from '@progress/kendo-angular-upload'; import { ButtonModule as uiButtonModule, TextareaModule } from '@oort-front/ui'; import { DialogModule } from '@oort-front/ui'; +import { isNil } from 'lodash'; /** Model fot the input data */ interface DialogData { @@ -148,10 +149,7 @@ export class InviteUsersModalComponent extends UnsubscribeComponent { this.gridData.data = this.gridData.data.concat(res); }, error: (err) => { - if (err.status === 400) { - this.snackBar.openSnackBar(err.error, { error: true }); - this.resetFileInput(); - } else { + if (isNil(err.status)) { this.snackBar.openSnackBar( this.translate.instant( 'models.user.notifications.userImportFail' @@ -160,8 +158,8 @@ export class InviteUsersModalComponent extends UnsubscribeComponent { error: true, } ); - this.resetFileInput(); } + this.resetFileInput(); }, }); } else { diff --git a/libs/shared/src/lib/components/widgets/common/template-aggregations/template-aggregations.component.ts b/libs/shared/src/lib/components/widgets/common/template-aggregations/template-aggregations.component.ts index 05d20bdf8d..73789a6793 100644 --- a/libs/shared/src/lib/components/widgets/common/template-aggregations/template-aggregations.component.ts +++ b/libs/shared/src/lib/components/widgets/common/template-aggregations/template-aggregations.component.ts @@ -26,6 +26,7 @@ import { AggregationDataQueryResponse, ReferenceDataAggregationQueryResponse, } from '../../../../models/aggregation.model'; +import { errorMessageFormatter } from '../../../../utils/graphql/error-message-formatter'; /** * Template aggregations component. @@ -192,7 +193,9 @@ export class TemplateAggregationsComponent if (!aggregationData || errors) { this.loadingAggregationRecords = false; if (errors?.length) { - this.snackBar.openSnackBar(errors[0].message, { error: true }); + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); } return; } diff --git a/libs/shared/src/lib/components/widgets/map-settings/map-layers/map-layers.component.ts b/libs/shared/src/lib/components/widgets/map-settings/map-layers/map-layers.component.ts index 6f1b884665..facc46ada3 100644 --- a/libs/shared/src/lib/components/widgets/map-settings/map-layers/map-layers.component.ts +++ b/libs/shared/src/lib/components/widgets/map-settings/map-layers/map-layers.component.ts @@ -109,7 +109,10 @@ export class MapLayersComponent extends UnsubscribeComponent implements OnInit { this.mapLayers.push(res); } }, - error: (err) => console.error(err), + error: (err) => { + console.error(err); + this.loading = false; + }, complete: () => (this.loading = false), }); } else { @@ -184,7 +187,10 @@ export class MapLayersComponent extends UnsubscribeComponent implements OnInit { } } }, - error: (err) => console.log(err), + error: (err) => { + console.log(err); + this.loading = false; + }, complete: () => (this.loading = false), }); } else { diff --git a/libs/shared/src/lib/components/widgets/summary-card/summary-card.component.ts b/libs/shared/src/lib/components/widgets/summary-card/summary-card.component.ts index 49fd089f4a..92a768ff78 100644 --- a/libs/shared/src/lib/components/widgets/summary-card/summary-card.component.ts +++ b/libs/shared/src/lib/components/widgets/summary-card/summary-card.component.ts @@ -886,6 +886,7 @@ export class SummaryCardComponent } } } + this.loading = false; }, error: () => { this.loading = false; diff --git a/libs/shared/src/lib/interceptors/error-handler/error-handler-interceptor.service.ts b/libs/shared/src/lib/interceptors/error-handler/error-handler-interceptor.service.ts new file mode 100644 index 0000000000..f9c916b512 --- /dev/null +++ b/libs/shared/src/lib/interceptors/error-handler/error-handler-interceptor.service.ts @@ -0,0 +1,90 @@ +import { Inject, Injectable } from '@angular/core'; +import { + HttpRequest, + HttpHandler, + HttpEvent, + HttpInterceptor, + HttpResponseBase, +} from '@angular/common/http'; +import { Observable, catchError, of, switchMap, throwError } from 'rxjs'; +import { SnackbarService } from '@oort-front/ui'; +import { isNil } from 'lodash'; + +/** + * Error handler interceptor service + */ +@Injectable() +export class ErrorHandlerInterceptorService implements HttpInterceptor { + /** + * Error handler interceptor service constructor + * + * @param snackbarService Snackbar service + * @param environment Current environment data + */ + constructor( + private snackbarService: SnackbarService, + @Inject('environment') private environment: any + ) {} + + /** + * Handle http request error to show a snackbar in the UI + * + * @param request Http request + * @param next Http request handler + * @returns Current request result + */ + intercept( + request: HttpRequest, + next: HttpHandler + ): Observable> { + if (request.url.includes(this.environment.apiUrl)) { + return next.handle(request).pipe( + // GraphQl errors would be treated as so for the app even if status is 200 + switchMap((req) => { + const keysFromBody = Object.keys((req as any).body?.data); + if ( + req instanceof HttpResponseBase && + // Could be cases where we query two different objects and one can fail and the other no + // In those cases we prioritize the use of correctly retrieved data + // Therefor we treat as strict error if all queries fail + (((req as any).body?.errors?.length && + keysFromBody?.every((key) => + isNil((req as any).body?.data[key]) + )) || + keysFromBody?.every((key) => isNil((req as any).body?.data[key]))) + ) { + return throwError(() => { + return { error: { errors: (req as any).body?.errors } }; + }); + } else { + return of(req); + } + }), + catchError((res: any) => { + // Open default snackbar if error is not a GraphQL type + if (res.status) { + let errorMessage = `${res.statusText}: ${res.status}`; + if (Array.isArray(res.error.errors)) { + res.error.errors.forEach((error: { message: string }) => { + errorMessage = errorMessage + '\n' + error.message; + }); + } else { + errorMessage = errorMessage + '\n' + res.error; + } + this.snackbarService.openSnackBar(errorMessage, { + error: true, + duration: 0, + }); + } + return throwError(() => { + return !isNil(res.message) + ? { errors: [res.message] } + : res.error.errors; + }); + }) + ); + } else { + return next.handle(request); + } + } +} diff --git a/libs/shared/src/lib/interceptors/error-handler/error-handler-interceptor.spec.ts b/libs/shared/src/lib/interceptors/error-handler/error-handler-interceptor.spec.ts new file mode 100644 index 0000000000..d42bf7d362 --- /dev/null +++ b/libs/shared/src/lib/interceptors/error-handler/error-handler-interceptor.spec.ts @@ -0,0 +1,18 @@ +import { TestBed } from '@angular/core/testing'; + +import { ErrorHandlerInterceptorService } from './error-handler-interceptor.service'; + +describe('ErrorHandlerInterceptorService', () => { + beforeEach(() => + TestBed.configureTestingModule({ + providers: [ErrorHandlerInterceptorService], + }) + ); + + it('should be created', () => { + const interceptor: ErrorHandlerInterceptorService = TestBed.inject( + ErrorHandlerInterceptorService + ); + expect(interceptor).toBeTruthy(); + }); +}); diff --git a/libs/shared/src/lib/services/application-notifications/application-notifications.service.ts b/libs/shared/src/lib/services/application-notifications/application-notifications.service.ts index ac4a87c36c..a8cf3f5d34 100644 --- a/libs/shared/src/lib/services/application-notifications/application-notifications.service.ts +++ b/libs/shared/src/lib/services/application-notifications/application-notifications.service.ts @@ -13,6 +13,7 @@ import { } from './graphql/mutations'; import { TranslateService } from '@ngx-translate/core'; import { SnackbarService } from '@oort-front/ui'; +import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; /** * Shared service to manage application's notifications. */ @@ -60,18 +61,8 @@ export class ApplicationNotificationsService { notification, }, }) - .subscribe((res) => { - if (res.errors) { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectNotCreated', { - type: this.translate - .instant('common.customNotification.one') - .toLowerCase(), - error: res.errors ? res.errors[0].message : '', - }), - { error: true } - ); - } else { + .subscribe({ + next: (res) => { if (res.data) { this.snackBar.openSnackBar( this.translate.instant('common.notifications.objectCreated', { @@ -80,7 +71,18 @@ export class ApplicationNotificationsService { }) ); } - } + }, + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectNotCreated', { + type: this.translate + .instant('common.customNotification.one') + .toLowerCase(), + error: errorMessageFormatter(errors), + }), + { error: true } + ); + }, }); } @@ -98,16 +100,8 @@ export class ApplicationNotificationsService { id, }, }) - .subscribe((res) => { - if (res.errors) { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectNotDeleted', { - value: this.translate.instant('common.customNotification.one'), - error: res.errors ? res.errors[0].message : '', - }), - { error: true } - ); - } else { + .subscribe({ + next: (res) => { if (res.data) { this.snackBar.openSnackBar( this.translate.instant('common.notifications.objectDeleted', { @@ -115,7 +109,16 @@ export class ApplicationNotificationsService { }) ); } - } + }, + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectNotDeleted', { + value: this.translate.instant('common.customNotification.one'), + error: errorMessageFormatter(errors), + }), + { error: true } + ); + }, }); } @@ -134,16 +137,8 @@ export class ApplicationNotificationsService { notification, }, }) - .subscribe((res) => { - if (res.errors) { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectNotUpdated', { - value: this.translate.instant('common.customNotification.one'), - error: res.errors ? res.errors[0].message : '', - }), - { error: true } - ); - } else { + .subscribe({ + next: (res) => { if (res.data) { this.snackBar.openSnackBar( this.translate.instant('common.notifications.objectUpdated', { @@ -152,7 +147,16 @@ export class ApplicationNotificationsService { }) ); } - } + }, + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectNotUpdated', { + value: this.translate.instant('common.customNotification.one'), + error: errorMessageFormatter(errors), + }), + { error: true } + ); + }, }); } } diff --git a/libs/shared/src/lib/services/application/application.service.ts b/libs/shared/src/lib/services/application/application.service.ts index ecbd31a05b..a6d738fdfe 100644 --- a/libs/shared/src/lib/services/application/application.service.ts +++ b/libs/shared/src/lib/services/application/application.service.ts @@ -115,6 +115,7 @@ import { RestService } from '../rest/rest.service'; import { DownloadService } from '../download/download.service'; import { DOCUMENT } from '@angular/common'; import { GraphQLError } from 'graphql'; +import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; /** * Shared application service. Handles events of opened application. @@ -425,13 +426,13 @@ export class ApplicationService { }, }) .subscribe({ - next: ({ errors, data }) => { + next: ({ data }) => { this.handleEditionMutationResponse( - errors, + [], this.translate.instant('common.access'), application?.name ); - if (!errors && data?.editApplication) { + if (data?.editApplication) { const newApplication = { ...application, permissions: data.editApplication.permissions, @@ -439,8 +440,12 @@ export class ApplicationService { this.application.next(newApplication); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.handleEditionMutationResponse( + errors, + this.translate.instant('common.access'), + application?.name + ); }, }); } @@ -461,30 +466,26 @@ export class ApplicationService { }, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { + next: ({ data }) => { + if (data) { this.snackBar.openSnackBar( this.translate.instant( - 'models.application.notifications.notPublished' - ), - { error: true } + 'models.application.notifications.published', + { + value: data.editApplication.name, + } + ) ); - } else { - if (data) { - this.snackBar.openSnackBar( - this.translate.instant( - 'models.application.notifications.published', - { - value: data.editApplication.name, - } - ) - ); - this.router.navigate(['/applications']); - } + this.router.navigate(['/applications']); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: () => { + this.snackBar.openSnackBar( + this.translate.instant( + 'models.application.notifications.notPublished' + ), + { error: true } + ); }, }); } @@ -506,33 +507,36 @@ export class ApplicationService { id, }, }) - .subscribe(({ errors, data }) => { - if (data) { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectDeleted', { - value: this.translate.instant('common.page.one'), - }) - ); - const app = this.application.getValue(); - if (app) { - const newApplication = { - ...app, - pages: app.pages?.filter((x) => x.id !== data?.deletePage.id), - }; - this.application.next(newApplication); - if (!stayOnPage) { - this.router.navigate([`./applications/${app.id}`]); + .subscribe({ + next: ({ data }) => { + if (data) { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectDeleted', { + value: this.translate.instant('common.page.one'), + }) + ); + const app = this.application.getValue(); + if (app) { + const newApplication = { + ...app, + pages: app.pages?.filter((x) => x.id !== data?.deletePage.id), + }; + this.application.next(newApplication); + if (!stayOnPage) { + this.router.navigate([`./applications/${app.id}`]); + } } } - } else { + }, + error: (errors) => { this.snackBar.openSnackBar( this.translate.instant('common.notifications.objectNotDeleted', { value: this.translate.instant('common.page.one'), - error: errors ? errors[0].message : '', + error: errorMessageFormatter(errors), }), { error: true } ); - } + }, }); } } @@ -552,35 +556,38 @@ export class ApplicationService { id, }, }) - .subscribe(({ errors, data }) => { - if (data) { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectRestored', { - value: this.translate.instant('common.page.one'), - }) - ); - const application = this.application.getValue(); - if (application) { - const newApplication = { - ...application, - pages: application.pages?.concat([data.restorePage]), - }; - this.application.next(newApplication); - this.router.navigate([ - data.restorePage.type === ContentType.form - ? `/applications/${application.id}/${data.restorePage.type}/${data.restorePage.id}` - : `/applications/${application.id}/${data.restorePage.type}/${data.restorePage.content}`, - ]); + .subscribe({ + next: ({ data }) => { + if (data) { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectRestored', { + value: this.translate.instant('common.page.one'), + }) + ); + const application = this.application.getValue(); + if (application) { + const newApplication = { + ...application, + pages: application.pages?.concat([data.restorePage]), + }; + this.application.next(newApplication); + this.router.navigate([ + data.restorePage.type === ContentType.form + ? `/applications/${application.id}/${data.restorePage.type}/${data.restorePage.id}` + : `/applications/${application.id}/${data.restorePage.type}/${data.restorePage.content}`, + ]); + } } - } else { + }, + error: (errors) => { this.snackBar.openSnackBar( this.translate.instant('common.notifications.objectNotRestored', { value: this.translate.instant('common.page.one'), - error: errors ? errors[0].message : '', + error: errorMessageFormatter(errors), }), { error: true } ); - } + }, }); } } @@ -602,48 +609,44 @@ export class ApplicationService { }, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { - if (pages.length > 1) { - this.snackBar.openSnackBar( - this.translate.instant( - 'components.application.pages.notReordered.plural', - { error: errors ? errors[0].message : '' } - ), - { error: true } - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant( - 'components.application.pages.notReordered.singular', - { error: errors ? errors[0].message : '' } - ), - { error: true } - ); - } + next: ({ data }) => { + if (pages.length > 1) { + this.snackBar.openSnackBar( + this.translate.instant( + 'components.application.pages.reordered.plural' + ) + ); } else { - if (pages.length > 1) { - this.snackBar.openSnackBar( - this.translate.instant( - 'components.application.pages.reordered.plural' - ) - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant( - 'components.application.pages.reordered.singular' - ) - ); - } - - this.application.next({ - ...application, - ...{ pages: data?.editApplication.pages }, - }); + this.snackBar.openSnackBar( + this.translate.instant( + 'components.application.pages.reordered.singular' + ) + ); } + + this.application.next({ + ...application, + ...{ pages: data?.editApplication.pages }, + }); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + if (pages.length > 1) { + this.snackBar.openSnackBar( + this.translate.instant( + 'components.application.pages.notReordered.plural', + { error: errorMessageFormatter(errors) } + ), + { error: true } + ); + } else { + this.snackBar.openSnackBar( + this.translate.instant( + 'components.application.pages.notReordered.singular', + { error: errorMessageFormatter(errors) } + ), + { error: true } + ); + } }, }); } @@ -788,35 +791,38 @@ export class ApplicationService { structure, }, }) - .subscribe(({ errors, data }) => { - if (data?.addPage) { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectCreated', { - type: this.translate.instant('common.page.one').toLowerCase(), - value: data.addPage.name, - }) - ); + .subscribe({ + next: ({ data }) => { + if (data?.addPage) { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectCreated', { + type: this.translate.instant('common.page.one').toLowerCase(), + value: data.addPage.name, + }) + ); - const content = data.addPage.content; - const newApplication = { - ...application, - pages: application.pages?.concat([data.addPage]), - }; - this.application.next(newApplication); - this.router.navigate([ - page.type === ContentType.form - ? `/applications/${application.id}/${page.type}/${data.addPage.id}` - : `/applications/${application.id}/${page.type}/${content}`, - ]); - } else { + const content = data.addPage.content; + const newApplication = { + ...application, + pages: application.pages?.concat([data.addPage]), + }; + this.application.next(newApplication); + this.router.navigate([ + page.type === ContentType.form + ? `/applications/${application.id}/${page.type}/${data.addPage.id}` + : `/applications/${application.id}/${page.type}/${content}`, + ]); + } + }, + error: (errors) => { this.snackBar.openSnackBar( this.translate.instant('common.notifications.objectNotCreated', { type: this.translate.instant('common.page.one').toLowerCase(), - error: errors ? errors[0].message : '', + error: errorMessageFormatter(errors), }), { error: true } ); - } + }, }); } } @@ -844,16 +850,8 @@ export class ApplicationService { step: content.stepId, }, }) - .subscribe(({ errors, data }) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectNotCreated', { - type: this.translate.instant('common.page.one').toLowerCase(), - error: errors ? errors[0].message : '', - }), - { error: true } - ); - } else { + .subscribe({ + next: ({ data }) => { if (data?.duplicatePage) { const newPage = data.duplicatePage; this.translate.instant('common.notifications.objectCreated', { @@ -873,7 +871,16 @@ export class ApplicationService { ]); if (callback) callback(); } - } + }, + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectNotCreated', { + type: this.translate.instant('common.page.one').toLowerCase(), + error: errorMessageFormatter(errors), + }), + { error: true } + ); + }, }); } @@ -894,40 +901,29 @@ export class ApplicationService { }, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { + next: ({ data }) => { + if (data) { this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotCreated', - { - type: this.translate - .instant('common.role.one') - .toLowerCase(), - error: errors ? errors[0].message : '', - } - ), - { error: true } + this.translate.instant('common.notifications.objectCreated', { + type: this.translate.instant('common.role.one').toLowerCase(), + value: role.title, + }) ); - } else { - if (data) { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectCreated', { - type: this.translate - .instant('common.role.one') - .toLowerCase(), - value: role.title, - }) - ); - const newApplication = { - ...application, - roles: application.roles?.concat([data.addRole]), - }; - this.application.next(newApplication); - } + const newApplication = { + ...application, + roles: application.roles?.concat([data.addRole]), + }; + this.application.next(newApplication); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectNotCreated', { + type: this.translate.instant('common.role.one').toLowerCase(), + error: errorMessageFormatter(errors), + }), + { error: true } + ); }, }); } @@ -953,13 +949,13 @@ export class ApplicationService { }, }) .subscribe({ - next: ({ errors, data }) => { + next: ({ data }) => { this.handleEditionMutationResponse( - errors, + [], this.translate.instant('common.role.one'), role.title ); - if (!errors && data) { + if (data) { const newApplication: Application = { ...application, roles: application.roles?.map((x) => { @@ -994,8 +990,12 @@ export class ApplicationService { this.application.next(newApplication); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.handleEditionMutationResponse( + errors, + this.translate.instant('common.role.one'), + role.title + ); }, }); } @@ -1017,33 +1017,26 @@ export class ApplicationService { }, }) .subscribe({ - next: ({ errors }) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotDeleted', - { - value: role.title, - error: errors ? errors[0].message : '', - } - ), - { error: true } - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectDeleted', { - value: role.title, - }) - ); - const newApplication = { - ...application, - roles: application.roles?.filter((x) => x.id !== role.id), - }; - this.application.next(newApplication); - } + next: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectDeleted', { + value: role.title, + }) + ); + const newApplication = { + ...application, + roles: application.roles?.filter((x) => x.id !== role.id), + }; + this.application.next(newApplication); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectNotDeleted', { + value: role.title, + error: errorMessageFormatter(errors), + }), + { error: true } + ); }, }); } @@ -1067,13 +1060,26 @@ export class ApplicationService { }, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { + next: ({ data }) => { + if (data) { + const deletedUsers = data.deleteUsersFromApplication.map( + (x) => x.id + ); + if (deletedUsers.length > 1) { + this.snackBar.openSnackBar( + this.translate.instant('components.users.onDelete.plural') + ); + } else { + this.snackBar.openSnackBar( + this.translate.instant('components.users.onDelete.singular') + ); + } + } else { if (ids.length > 1) { this.snackBar.openSnackBar( this.translate.instant( 'components.users.onNotDelete.plural', - { error: errors ? errors[0].message : '' } + { error: '' } ), { error: true } ); @@ -1081,44 +1087,30 @@ export class ApplicationService { this.snackBar.openSnackBar( this.translate.instant( 'components.users.onNotDelete.singular', - { error: errors ? errors[0].message : '' } + { error: '' } ), { error: true } ); } + } + resolved(); + }, + error: (errors) => { + if (ids.length > 1) { + this.snackBar.openSnackBar( + this.translate.instant('components.users.onNotDelete.plural', { + error: errorMessageFormatter(errors), + }), + { error: true } + ); } else { - if (data) { - const deletedUsers = data.deleteUsersFromApplication.map( - (x) => x.id - ); - if (deletedUsers.length > 1) { - this.snackBar.openSnackBar( - this.translate.instant('components.users.onDelete.plural') - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant('components.users.onDelete.singular') - ); - } - } else { - if (ids.length > 1) { - this.snackBar.openSnackBar( - this.translate.instant( - 'components.users.onNotDelete.plural', - { error: '' } - ), - { error: true } - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant( - 'components.users.onNotDelete.singular', - { error: '' } - ), - { error: true } - ); - } - } + this.snackBar.openSnackBar( + this.translate.instant( + 'components.users.onNotDelete.singular', + { error: errorMessageFormatter(errors) } + ), + { error: true } + ); } resolved(); }, @@ -1156,43 +1148,36 @@ export class ApplicationService { }, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { + next: ({ data }) => { + if (data) { this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotCreated', - { - type: this.translate - .instant('common.positionCategory.one') - .toLowerCase(), - error: errors ? errors[0].message : '', - } - ), - { error: true } + this.translate.instant('common.notifications.objectCreated', { + type: this.translate + .instant('common.positionCategory.one') + .toLowerCase(), + value: category.title, + }) ); - } else { - if (data) { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectCreated', { - type: this.translate - .instant('common.positionCategory.one') - .toLowerCase(), - value: category.title, - }) - ); - const newApplication: Application = { - ...application, - positionAttributeCategories: - application.positionAttributeCategories?.concat([ - data.addPositionAttributeCategory, - ]), - }; - this.application.next(newApplication); - } + const newApplication: Application = { + ...application, + positionAttributeCategories: + application.positionAttributeCategories?.concat([ + data.addPositionAttributeCategory, + ]), + }; + this.application.next(newApplication); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectNotCreated', { + type: this.translate + .instant('common.positionCategory.one') + .toLowerCase(), + error: errorMessageFormatter(errors), + }), + { error: true } + ); }, }); } @@ -1215,38 +1200,31 @@ export class ApplicationService { }, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { + next: ({ data }) => { + if (data) { this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotDeleted', - { - value: category.title, - error: errors ? errors[0].message : '', - } - ), - { error: true } + this.translate.instant('common.notifications.objectDeleted', { + value: category.title, + }) ); - } else { - if (data) { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectDeleted', { - value: category.title, - }) - ); - const newApplication: Application = { - ...application, - positionAttributeCategories: - application.positionAttributeCategories?.filter( - (x) => x.id !== data?.deletePositionAttributeCategory.id - ), - }; - this.application.next(newApplication); - } + const newApplication: Application = { + ...application, + positionAttributeCategories: + application.positionAttributeCategories?.filter( + (x) => x.id !== data?.deletePositionAttributeCategory.id + ), + }; + this.application.next(newApplication); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectNotDeleted', { + value: category.title, + error: errorMessageFormatter(errors), + }), + { error: true } + ); }, }); } @@ -1328,40 +1306,33 @@ export class ApplicationService { }, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { + next: ({ data }) => { + if (data) { this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotCreated', - { - type: this.translate - .instant('common.channel.one') - .toLowerCase(), - error: errors ? errors[0].message : '', - } - ), - { error: true } + this.translate.instant('common.notifications.objectCreated', { + type: this.translate + .instant('common.channel.one') + .toLowerCase(), + value: channel.title, + }) ); - } else { - if (data) { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectCreated', { - type: this.translate - .instant('common.channel.one') - .toLowerCase(), - value: channel.title, - }) - ); - const newApplication: Application = { - ...application, - channels: application.channels?.concat([data.addChannel]), - }; - this.application.next(newApplication); - } + const newApplication: Application = { + ...application, + channels: application.channels?.concat([data.addChannel]), + }; + this.application.next(newApplication); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectNotCreated', { + type: this.translate + .instant('common.channel.one') + .toLowerCase(), + error: errorMessageFormatter(errors), + }), + { error: true } + ); }, }); } @@ -1384,13 +1355,13 @@ export class ApplicationService { }, }) .subscribe({ - next: ({ errors, data }) => { + next: ({ data }) => { this.handleEditionMutationResponse( - errors, + [], this.translate.instant('common.channel.one'), title ); - if (!errors && data) { + if (data) { const newApplication: Application = { ...application, channels: application?.channels?.map((x) => { @@ -1403,8 +1374,12 @@ export class ApplicationService { this.application.next(newApplication); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.handleEditionMutationResponse( + errors, + this.translate.instant('common.channel.one'), + title + ); }, }); } @@ -1425,37 +1400,30 @@ export class ApplicationService { }, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { + next: ({ data }) => { + if (data) { this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotDeleted', - { - value: channel.title, - error: errors ? errors[0].message : '', - } - ), - { error: true } + this.translate.instant('common.notifications.objectDeleted', { + value: channel.title, + }) ); - } else { - if (data) { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectDeleted', { - value: channel.title, - }) - ); - const newApplication: Application = { - ...application, - channels: application.channels?.filter( - (x) => x.id !== data?.deleteChannel.id - ), - }; - this.application.next(newApplication); - } + const newApplication: Application = { + ...application, + channels: application.channels?.filter( + (x) => x.id !== data?.deleteChannel.id + ), + }; + this.application.next(newApplication); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectNotDeleted', { + value: channel.title, + error: errorMessageFormatter(errors), + }), + { error: true } + ); }, }); } @@ -1490,42 +1458,35 @@ export class ApplicationService { }, }) .subscribe({ - next: ({ errors, data }) => { - if (errors) { + next: ({ data }) => { + if (data) { this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotCreated', - { - type: this.translate - .instant('common.subscription.one') - .toLowerCase(), - error: errors ? errors[0].message : '', - } - ), - { error: true } + this.translate.instant('common.notifications.objectCreated', { + type: this.translate + .instant('common.subscription.one') + .toLowerCase(), + value: subscription.title, + }) ); - } else { - if (data) { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectCreated', { - type: this.translate - .instant('common.subscription.one') - .toLowerCase(), - value: subscription.title, - }) - ); - const newApplication: Application = { - ...application, - subscriptions: application.subscriptions?.concat([ - data.addSubscription, - ]), - }; - this.application.next(newApplication); - } + const newApplication: Application = { + ...application, + subscriptions: application.subscriptions?.concat([ + data.addSubscription, + ]), + }; + this.application.next(newApplication); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectNotCreated', { + type: this.translate + .instant('common.subscription.one') + .toLowerCase(), + error: errorMessageFormatter(errors), + }), + { error: true } + ); }, }); } @@ -1548,35 +1509,28 @@ export class ApplicationService { }, }) .subscribe({ - next: ({ errors }) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotDeleted', - { - value: this.translate.instant('common.subscription.one'), - error: errors ? errors[0].message : '', - } - ), - { error: true } - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectDeleted', { - value: this.translate.instant('common.subscription.one'), - }) - ); - const newApplication = { - ...application, - subscriptions: application.subscriptions?.filter( - (sub) => sub.routingKey !== subscription - ), - }; - this.application.next(newApplication); - } + next: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectDeleted', { + value: this.translate.instant('common.subscription.one'), + }) + ); + const newApplication = { + ...application, + subscriptions: application.subscriptions?.filter( + (sub) => sub.routingKey !== subscription + ), + }; + this.application.next(newApplication); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectNotDeleted', { + value: this.translate.instant('common.subscription.one'), + error: errorMessageFormatter(errors), + }), + { error: true } + ); }, }); } @@ -1604,13 +1558,13 @@ export class ApplicationService { }, }) .subscribe({ - next: ({ errors, data }) => { + next: ({ data }) => { this.handleEditionMutationResponse( - errors, + [], this.translate.instant('common.subscription.one'), value.title ); - if (!errors && data) { + if (data) { const subscription = data.editSubscription; const newApplication = { ...application, @@ -1624,8 +1578,12 @@ export class ApplicationService { this.application.next(newApplication); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.handleEditionMutationResponse( + errors, + this.translate.instant('common.subscription.one'), + value.title + ); }, }); } @@ -2014,11 +1972,11 @@ export class ApplicationService { type: string, value?: string ) { - if (errors) { + if (errors?.length) { this.snackBar.openSnackBar( this.translate.instant('common.notifications.objectNotUpdated', { type, - error: errors ? errors[0].message : '', + error: errorMessageFormatter(errors), }), { error: true } ); diff --git a/libs/shared/src/lib/services/auth-interceptor/auth-interceptor.service.ts b/libs/shared/src/lib/services/auth-interceptor/auth-interceptor.service.ts index 2f215670e7..7f668fa3c1 100644 --- a/libs/shared/src/lib/services/auth-interceptor/auth-interceptor.service.ts +++ b/libs/shared/src/lib/services/auth-interceptor/auth-interceptor.service.ts @@ -65,7 +65,7 @@ export class AuthInterceptorService implements HttpInterceptor { // redirect user to the logout page } } - return throwError(() => new Error(err.error || err.message)); + return throwError(() => err); }) ); } diff --git a/libs/shared/src/lib/services/context/context.service.ts b/libs/shared/src/lib/services/context/context.service.ts index 31223a2bb9..86f3fc3263 100644 --- a/libs/shared/src/lib/services/context/context.service.ts +++ b/libs/shared/src/lib/services/context/context.service.ts @@ -38,6 +38,7 @@ import { ApplicationService } from '../application/application.service'; import { ActivatedRoute, Router } from '@angular/router'; import { RecordQueryResponse } from '../../models/record.model'; import { GET_RECORD_BY_ID } from './graphql/queries'; +import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; /** * Dashboard context service @@ -579,11 +580,11 @@ export class ContextService { dashboard?: Dashboard ) { const { data, errors } = response; - if (errors) { + if (errors?.length) { this.snackBar.openSnackBar( this.translate.instant('common.notifications.objectNotUpdated', { type: this.translate.instant('common.filter.one'), - error: errors ? errors[0].message : '', + error: errorMessageFormatter(errors), }), { error: true } ); diff --git a/libs/shared/src/lib/services/dashboard/dashboard.service.ts b/libs/shared/src/lib/services/dashboard/dashboard.service.ts index a5efe2070b..4b8d371057 100644 --- a/libs/shared/src/lib/services/dashboard/dashboard.service.ts +++ b/libs/shared/src/lib/services/dashboard/dashboard.service.ts @@ -15,6 +15,7 @@ import { Apollo } from 'apollo-angular'; import { EDIT_DASHBOARD, UPDATE_PAGE_CONTEXT } from './graphql/mutations'; import get from 'lodash/get'; import { GraphQLError } from 'graphql'; +import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; /** * Shared dashboard service. Handles dashboard events. @@ -57,11 +58,11 @@ export class DashboardService { type: string, value?: string ) { - if (errors) { + if (errors?.length) { this.snackBar.openSnackBar( this.translate.instant('common.notifications.objectNotUpdated', { type, - error: errors ? errors[0].message : '', + error: errorMessageFormatter(errors), }), { error: true } ); diff --git a/libs/shared/src/lib/services/form-builder/form-builder.service.ts b/libs/shared/src/lib/services/form-builder/form-builder.service.ts index ee626e2886..cc07030f19 100644 --- a/libs/shared/src/lib/services/form-builder/form-builder.service.ts +++ b/libs/shared/src/lib/services/form-builder/form-builder.service.ts @@ -16,6 +16,7 @@ import { BehaviorSubject } from 'rxjs'; import { SnackbarService } from '@oort-front/ui'; import { FormHelpersService } from '../form-helper/form-helper.service'; import { HttpClient } from '@angular/common/http'; +import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; /** * Shared form builder service. @@ -272,26 +273,22 @@ export class FormBuilderService { }, }) .subscribe({ - next: ({ errors }) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant( - 'common.notifications.objectNotUpdated', - { - type: this.translate.instant('common.record.one'), - error: errors ? errors[0].message : '', - } - ), - { error: true } - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectUpdated', { - type: this.translate.instant('common.record.one'), - value: '', - }) - ); - } + next: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectUpdated', { + type: this.translate.instant('common.record.one'), + value: '', + }) + ); + }, + error: (errors) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectNotUpdated', { + type: this.translate.instant('common.record.one'), + error: errorMessageFormatter(errors), + }), + { error: true } + ); }, }); } diff --git a/libs/shared/src/lib/services/form-helper/form-helper.service.ts b/libs/shared/src/lib/services/form-helper/form-helper.service.ts index ca9306efff..c2a0435a8d 100644 --- a/libs/shared/src/lib/services/form-helper/form-helper.service.ts +++ b/libs/shared/src/lib/services/form-helper/form-helper.service.ts @@ -22,6 +22,7 @@ import { DELETE_DRAFT_RECORD, EDIT_DRAFT_RECORD, } from './graphql/mutations'; +import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; /** * Shared survey helper service. */ @@ -191,29 +192,22 @@ export class FormHelpersService { }, }) .subscribe({ - next: ({ data, errors }) => { - if (errors) { - this.snackBar.openSnackBar( - `Error. ${errors[0].message}`, - { - error: true, - } - ); - reject(errors); - } else { - question.value[question.value.indexOf(recordId)] = - question.value.includes(recordId) - ? data?.addRecord.id - : recordId; // If there is no error, we replace in the question the temporary id by the final one - surveyData[question.name] = question.value; // We update the survey data to consider our changes - resolve(); - } + next: ({ data }) => { + question.value[question.value.indexOf(recordId)] = + question.value.includes(recordId) + ? data?.addRecord.id + : recordId; // If there is no error, we replace in the question the temporary id by the final one + surveyData[question.name] = question.value; // We update the survey data to consider our changes + resolve(); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { - error: true, - }); - reject(err); + error: (errors) => { + this.snackBar.openSnackBar( + `Error. ${errorMessageFormatter(errors)}`, + { + error: true, + } + ); + reject(errors); }, }); } else { @@ -474,21 +468,14 @@ export class FormHelpersService { }, }); mutation.subscribe({ - next: ({ errors, data }) => { - if (errors) { - survey.clear(false, true); - this.snackBar.openSnackBar(errors[0].message, { error: true }); - } else { - // localStorage.removeItem(this.storageId); - this.snackBar.openSnackBar( - this.translate.instant( - 'components.form.draftRecords.successSave' - ), - { - error: false, - } - ); - } + next: ({ data }) => { + // localStorage.removeItem(this.storageId); + this.snackBar.openSnackBar( + this.translate.instant('components.form.draftRecords.successSave'), + { + error: false, + } + ); // Callback to emit save but stay in record addition mode if (callback) { callback({ @@ -500,8 +487,11 @@ export class FormHelpersService { }); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + survey.clear(false, true); + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); }, }); } else { @@ -516,7 +506,9 @@ export class FormHelpersService { mutation.subscribe(({ errors }: any) => { if (errors) { survey.clear(false, true); - this.snackBar.openSnackBar(errors[0].message, { error: true }); + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); } else { // localStorage.removeItem(this.storageId); this.snackBar.openSnackBar( diff --git a/libs/shared/src/lib/services/map/map-layers.service.ts b/libs/shared/src/lib/services/map/map-layers.service.ts index 16f3ef41f2..c6f88ac15c 100644 --- a/libs/shared/src/lib/services/map/map-layers.service.ts +++ b/libs/shared/src/lib/services/map/map-layers.service.ts @@ -11,6 +11,7 @@ import { Observable, of, switchMap, + throwError, } from 'rxjs'; import { LayerFormData } from '../../components/ui/map/interfaces/layer-settings.type'; import { Layer, EMPTY_FEATURE_COLLECTION } from '../../components/ui/map/layer'; @@ -35,6 +36,7 @@ import { omitBy, isNil, get } from 'lodash'; import { ContextService } from '../context/context.service'; import { DOCUMENT } from '@angular/common'; import { MapPolygonsService } from './map-polygons.service'; +import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; /** * Shared map layer service @@ -86,11 +88,9 @@ export class MapLayersService { .pipe( filter((response) => !!response.data), map((response) => { - if (response.errors) { - throw new Error(response.errors[0].message); - } return response.data?.addLayer; - }) + }), + catchError((errors) => throwError(() => errorMessageFormatter(errors))) ); } @@ -117,11 +117,9 @@ export class MapLayersService { .pipe( filter((response) => !!response.data), map((response) => { - if (response.errors) { - throw new Error(response.errors[0].message); - } return response.data?.editLayer; - }) + }), + catchError((errors) => throwError(() => errorMessageFormatter(errors))) ); } @@ -157,11 +155,9 @@ export class MapLayersService { .pipe( filter((response) => !!response.data), map((response) => { - if (response.errors) { - throw new Error(response.errors[0].message); - } return response.data.layer; - }) + }), + catchError((errors) => throwError(() => errorMessageFormatter(errors))) ); } @@ -192,11 +188,9 @@ export class MapLayersService { .pipe( filter((response) => !!response.data), map((response) => { - if (response.errors) { - throw new Error(response.errors[0].message); - } return response.data.layers; - }) + }), + catchError((errors) => throwError(() => errorMessageFormatter(errors))) ); } diff --git a/libs/shared/src/lib/services/workflow/workflow.service.ts b/libs/shared/src/lib/services/workflow/workflow.service.ts index ec9641262e..7d90a7fbd0 100644 --- a/libs/shared/src/lib/services/workflow/workflow.service.ts +++ b/libs/shared/src/lib/services/workflow/workflow.service.ts @@ -14,6 +14,7 @@ import { import { ApplicationService } from '../application/application.service'; import { TranslateService } from '@ngx-translate/core'; import { SnackbarService } from '@oort-front/ui'; +import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; /** * Workflow service. Handles modification of workflow ( step addition / step name update ) and some workflow actions. @@ -84,35 +85,38 @@ export class WorkflowService { workflow: workflow.id, }, }) - .subscribe(({ errors, data }) => { - if (data) { - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectCreated', { - type: this.translate.instant('common.step.one').toLowerCase(), - value: data.addStep.name, - }) - ); - this.loadWorkflow(workflow.id); - if (step.type === ContentType.form) { - this.router.navigate( - ['../' + step.type + '/' + data.addStep.id], - { relativeTo: route.parent } - ); - } else { - this.router.navigate( - ['../' + step.type + '/' + data.addStep.content], - { relativeTo: route.parent } + .subscribe({ + next: ({ data }) => { + if (data) { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectCreated', { + type: this.translate.instant('common.step.one').toLowerCase(), + value: data.addStep.name, + }) ); + this.loadWorkflow(workflow.id); + if (step.type === ContentType.form) { + this.router.navigate( + ['../' + step.type + '/' + data.addStep.id], + { relativeTo: route.parent } + ); + } else { + this.router.navigate( + ['../' + step.type + '/' + data.addStep.content], + { relativeTo: route.parent } + ); + } } - } else { + }, + error: (errors) => { this.snackBar.openSnackBar( this.translate.instant('common.notifications.objectNotUpdated', { type: this.translate.instant('common.workflow.one'), - error: errors ? errors[0].message : '', + error: errorMessageFormatter(errors), }), { error: true } ); - } + }, }); } else { this.snackBar.openSnackBar( diff --git a/libs/shared/src/lib/utils/graphql/error-message-formatter.ts b/libs/shared/src/lib/utils/graphql/error-message-formatter.ts new file mode 100644 index 0000000000..9d4bb8231c --- /dev/null +++ b/libs/shared/src/lib/utils/graphql/error-message-formatter.ts @@ -0,0 +1,8 @@ +/** + * Gets the message in the graphql error + * + * @param errors GraphQL error + * @returns formatted message + */ +export const errorMessageFormatter = (errors: any): string => + (errors.networkError || errors)?.[0].message ?? ''; diff --git a/libs/shared/src/lib/utils/public-api.ts b/libs/shared/src/lib/utils/public-api.ts index c14a6f4fc3..9429c065f0 100644 --- a/libs/shared/src/lib/utils/public-api.ts +++ b/libs/shared/src/lib/utils/public-api.ts @@ -1,3 +1,4 @@ export * from './validators/cron.validator'; export * from './graphql/connection.type'; +export * from './graphql/error-message-formatter'; export * from './update-queries'; diff --git a/libs/shared/src/lib/views/application-users/application-users.component.ts b/libs/shared/src/lib/views/application-users/application-users.component.ts index 40ac14e197..4869a151c4 100644 --- a/libs/shared/src/lib/views/application-users/application-users.component.ts +++ b/libs/shared/src/lib/views/application-users/application-users.component.ts @@ -11,6 +11,7 @@ import { UserListComponent } from './components/user-list/user-list.component'; import { ADD_USERS } from './graphql/mutations'; import { SnackbarService } from '@oort-front/ui'; import { CompositeFilterDescriptor } from '@progress/kendo-data-query'; +import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; /** * Application users component. @@ -99,8 +100,8 @@ export class ApplicationUsersComponent application: this.roles[0].application?.id, }, }) - .subscribe(({ errors, data }) => { - if (!errors) { + .subscribe({ + next: ({ data }) => { if (data?.addUsers.length) { this.snackBar.openSnackBar( this.translate.instant('components.users.onInvite.plural') @@ -111,12 +112,13 @@ export class ApplicationUsersComponent ); } this.userList?.fetchUsers(true); - } else { - if (data?.addUsers?.length) { + }, + error: (errors) => { + if (value?.length > 1) { this.snackBar.openSnackBar( this.translate.instant( 'components.users.onNotInvite.plural', - { error: errors[0].message } + { error: errorMessageFormatter(errors) } ), { error: true } ); @@ -124,12 +126,12 @@ export class ApplicationUsersComponent this.snackBar.openSnackBar( this.translate.instant( 'components.users.onNotInvite.singular', - { error: errors[0].message } + { error: errorMessageFormatter(errors) } ), { error: true } ); } - } + }, }); } }); diff --git a/libs/shared/src/lib/views/profile/profile.component.ts b/libs/shared/src/lib/views/profile/profile.component.ts index effba854aa..262be0f130 100644 --- a/libs/shared/src/lib/views/profile/profile.component.ts +++ b/libs/shared/src/lib/views/profile/profile.component.ts @@ -8,6 +8,7 @@ import { UnsubscribeComponent } from '../../components/utils/unsubscribe/unsubsc import { takeUntil } from 'rxjs/operators'; import { SnackbarService } from '@oort-front/ui'; import { EditUserProfileMutationResponse, User } from '../../models/user.model'; +import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; /** * Shared profile page. @@ -79,11 +80,13 @@ export class ProfileComponent extends UnsubscribeComponent implements OnInit { }, }) .subscribe({ - next: ({ errors, data }) => { - this.handleUserProfileMutationResponse({ data, errors }, 'name'); + next: ({ data }) => { + this.handleUserProfileMutationResponse({ data, errors: [] }, 'name'); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); }, }); } @@ -105,14 +108,16 @@ export class ProfileComponent extends UnsubscribeComponent implements OnInit { }, }) .subscribe({ - next: ({ errors, data }) => { + next: ({ data }) => { this.handleUserProfileMutationResponse( - { data, errors }, + { data, errors: [] }, 'favoriteApp' ); }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); }, }); } @@ -145,7 +150,7 @@ export class ProfileComponent extends UnsubscribeComponent implements OnInit { profileProperty: 'name' | 'favoriteApp' ) { const { errors, data } = response; - if (errors) { + if (errors?.length) { this.snackBar.openSnackBar( this.translate.instant('pages.profile.notifications.notUpdated'), { error: true } diff --git a/libs/ui/src/lib/snackbar/snackbar.component.html b/libs/ui/src/lib/snackbar/snackbar.component.html index 90715f5d9f..6cf58b1912 100644 --- a/libs/ui/src/lib/snackbar/snackbar.component.html +++ b/libs/ui/src/lib/snackbar/snackbar.component.html @@ -23,7 +23,9 @@ >
-

+

{{ message }}

From 482133086ad7272a8d869192009d861f1437f6c1 Mon Sep 17 00:00:00 2001 From: Unai Zalba Date: Thu, 7 Mar 2024 09:22:07 +0100 Subject: [PATCH 2/5] refactor/AB#82357_create-shared-error-handler-logic-for-the-app fix: linting --- .../resource/aggregations-tab/aggregations-tab.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/back-office/src/app/dashboard/pages/resource/aggregations-tab/aggregations-tab.component.ts b/apps/back-office/src/app/dashboard/pages/resource/aggregations-tab/aggregations-tab.component.ts index d44cbcb70b..5d57ec0e45 100644 --- a/apps/back-office/src/app/dashboard/pages/resource/aggregations-tab/aggregations-tab.component.ts +++ b/apps/back-office/src/app/dashboard/pages/resource/aggregations-tab/aggregations-tab.component.ts @@ -83,6 +83,7 @@ export class AggregationsTabComponent * @param aggregationService Grid aggregation service * @param confirmService Shared confirm service * @param translate Angular translate service + * @param snackbarService Snackbar service */ constructor( private apollo: Apollo, From 28ea388ac89abc805b2c47cf27fd2f73e11b8951 Mon Sep 17 00:00:00 2001 From: Unai Zalba Date: Thu, 7 Mar 2024 09:50:32 +0100 Subject: [PATCH 3/5] refactor/AB#82357_create-shared-error-handler-logic-for-the-app feat: handle graphQL errors using apollo links --- apps/back-office/src/app/graphql.module.ts | 2 + apps/front-office/src/app/graphql.module.ts | 2 + .../form-modal/form-modal.component.ts | 2 +- .../src/lib/components/form/form.component.ts | 2 +- .../record-history.component.ts | 2 +- .../role-resources.component.ts | 2 +- .../group-list/group-list.component.ts | 2 +- .../role-list/role-list.component.ts | 2 +- .../aggregation-builder.component.ts | 2 +- .../template-aggregations.component.ts | 2 +- .../error-handler-interceptor.service.ts | 31 +------------- .../application-notifications.service.ts | 2 +- .../application/application.service.ts | 2 +- .../lib/services/context/context.service.ts | 2 +- .../services/dashboard/dashboard.service.ts | 2 +- .../form-builder/form-builder.service.ts | 2 +- .../form-helper/form-helper.service.ts | 2 +- .../lib/services/map/map-layers.service.ts | 2 +- .../lib/services/workflow/workflow.service.ts | 2 +- .../src/lib/utils/graphql/error-handler.ts | 40 +++++++++++++++++++ .../utils/graphql/error-message-formatter.ts | 8 ---- libs/shared/src/lib/utils/public-api.ts | 2 +- .../application-users.component.ts | 2 +- .../lib/views/profile/profile.component.ts | 2 +- 24 files changed, 65 insertions(+), 56 deletions(-) create mode 100644 libs/shared/src/lib/utils/graphql/error-handler.ts delete mode 100644 libs/shared/src/lib/utils/graphql/error-message-formatter.ts diff --git a/apps/back-office/src/app/graphql.module.ts b/apps/back-office/src/app/graphql.module.ts index 5fddd0e4aa..f4fdcf8985 100644 --- a/apps/back-office/src/app/graphql.module.ts +++ b/apps/back-office/src/app/graphql.module.ts @@ -14,6 +14,7 @@ import extractFiles from 'extract-files/extractFiles.mjs'; import isExtractableFile from 'extract-files/isExtractableFile.mjs'; import { GraphQLWsLink } from '@apollo/client/link/subscriptions'; import { createClient } from 'graphql-ws'; +import { createGraphQlErrorHandler } from '@oort-front/shared'; /** * Configuration of the Apollo client. @@ -52,6 +53,7 @@ export const createApollo = (httpLink: HttpLink): ApolloClientOptions => { const link = ApolloLink.from([ basic, + createGraphQlErrorHandler(console.error), split( ({ query }) => { const { kind, operation }: Definition = getMainDefinition(query); diff --git a/apps/front-office/src/app/graphql.module.ts b/apps/front-office/src/app/graphql.module.ts index eb2b400550..2d339fb92d 100644 --- a/apps/front-office/src/app/graphql.module.ts +++ b/apps/front-office/src/app/graphql.module.ts @@ -14,6 +14,7 @@ import extractFiles from 'extract-files/extractFiles.mjs'; import isExtractableFile from 'extract-files/isExtractableFile.mjs'; import { GraphQLWsLink } from '@apollo/client/link/subscriptions'; import { createClient } from 'graphql-ws'; +import { createGraphQlErrorHandler } from '@oort-front/shared'; /** * Configuration of the Apollo client. @@ -52,6 +53,7 @@ export const createApollo = (httpLink: HttpLink): ApolloClientOptions => { const link = ApolloLink.from([ basic, + createGraphQlErrorHandler(console.error), split( ({ query }) => { const { kind, operation }: Definition = getMainDefinition(query); diff --git a/libs/shared/src/lib/components/form-modal/form-modal.component.ts b/libs/shared/src/lib/components/form-modal/form-modal.component.ts index b50a744a26..325ed7c077 100644 --- a/libs/shared/src/lib/components/form-modal/form-modal.component.ts +++ b/libs/shared/src/lib/components/form-modal/form-modal.component.ts @@ -41,7 +41,7 @@ import { UnsubscribeComponent } from '../utils/unsubscribe/unsubscribe.component import { FormHelpersService } from '../../services/form-helper/form-helper.service'; import { DialogModule } from '@oort-front/ui'; import { DraftRecordComponent } from '../draft-record/draft-record.component'; -import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; +import { errorMessageFormatter } from '../../utils/graphql/error-handler'; /** * Interface of Dialog data. diff --git a/libs/shared/src/lib/components/form/form.component.ts b/libs/shared/src/lib/components/form/form.component.ts index 84d104b1e2..0ceb080893 100644 --- a/libs/shared/src/lib/components/form/form.component.ts +++ b/libs/shared/src/lib/components/form/form.component.ts @@ -28,7 +28,7 @@ import { UnsubscribeComponent } from '../utils/unsubscribe/unsubscribe.component import { FormHelpersService } from '../../services/form-helper/form-helper.service'; import { SnackbarService, UILayoutService } from '@oort-front/ui'; import { isNil } from 'lodash'; -import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; +import { errorMessageFormatter } from '../../utils/graphql/error-handler'; /** * This component is used to display forms diff --git a/libs/shared/src/lib/components/record-history/record-history.component.ts b/libs/shared/src/lib/components/record-history/record-history.component.ts index afcbe919ae..2b19b77fe3 100644 --- a/libs/shared/src/lib/components/record-history/record-history.component.ts +++ b/libs/shared/src/lib/components/record-history/record-history.component.ts @@ -30,7 +30,7 @@ import { FormControl, FormGroup } from '@angular/forms'; import { startCase, isNil } from 'lodash'; import { ResizeEvent } from 'angular-resizable-element'; import { DOCUMENT } from '@angular/common'; -import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; +import { errorMessageFormatter } from '../../utils/graphql/error-handler'; /** * Return the type of the old value if existing, else the type of the new value. diff --git a/libs/shared/src/lib/components/role-summary/role-resources/role-resources.component.ts b/libs/shared/src/lib/components/role-summary/role-resources/role-resources.component.ts index b6df9e8516..76b4ae76a3 100644 --- a/libs/shared/src/lib/components/role-summary/role-resources/role-resources.component.ts +++ b/libs/shared/src/lib/components/role-summary/role-resources/role-resources.component.ts @@ -29,7 +29,7 @@ import { UIPageChangeEvent, handleTablePageEvent, } from '@oort-front/ui'; -import { errorMessageFormatter } from '../../../utils/graphql/error-message-formatter'; +import { errorMessageFormatter } from '../../../utils/graphql/error-handler'; /** Default page size */ const DEFAULT_PAGE_SIZE = 10; diff --git a/libs/shared/src/lib/components/roles/components/group-list/group-list.component.ts b/libs/shared/src/lib/components/roles/components/group-list/group-list.component.ts index b8241992ab..2eef2e216d 100644 --- a/libs/shared/src/lib/components/roles/components/group-list/group-list.component.ts +++ b/libs/shared/src/lib/components/roles/components/group-list/group-list.component.ts @@ -18,7 +18,7 @@ import { } from '../../../../models/user.model'; import { SnackbarSpinnerComponent } from '../../../snackbar-spinner/snackbar-spinner.component'; import { FormBuilder } from '@angular/forms'; -import { errorMessageFormatter } from '../../../../utils/graphql/error-message-formatter'; +import { errorMessageFormatter } from '../../../../utils/graphql/error-handler'; /** * This component is used to display the groups tab in the platform diff --git a/libs/shared/src/lib/components/roles/components/role-list/role-list.component.ts b/libs/shared/src/lib/components/roles/components/role-list/role-list.component.ts index 417c57d636..2edd971a2d 100644 --- a/libs/shared/src/lib/components/roles/components/role-list/role-list.component.ts +++ b/libs/shared/src/lib/components/roles/components/role-list/role-list.component.ts @@ -18,7 +18,7 @@ import { UnsubscribeComponent } from '../../../utils/unsubscribe/unsubscribe.com import { takeUntil } from 'rxjs/operators'; import { SnackbarService } from '@oort-front/ui'; import { FormBuilder } from '@angular/forms'; -import { errorMessageFormatter } from '../../../../utils/graphql/error-message-formatter'; +import { errorMessageFormatter } from '../../../../utils/graphql/error-handler'; /** * This component is used to display the back-office roles tab diff --git a/libs/shared/src/lib/components/ui/aggregation-builder/aggregation-builder.component.ts b/libs/shared/src/lib/components/ui/aggregation-builder/aggregation-builder.component.ts index 16af73f8f1..463a5acb08 100644 --- a/libs/shared/src/lib/components/ui/aggregation-builder/aggregation-builder.component.ts +++ b/libs/shared/src/lib/components/ui/aggregation-builder/aggregation-builder.component.ts @@ -19,7 +19,7 @@ import { } from '../../../models/aggregation.model'; import { getReferenceMetadata } from '../../../utils/reference-data-metadata.util'; import { PipelineStage } from './pipeline/pipeline-stage.enum'; -import { errorMessageFormatter } from '../../../utils/graphql/error-message-formatter'; +import { errorMessageFormatter } from '../../../utils/graphql/error-handler'; /** * Main component of Aggregation builder. diff --git a/libs/shared/src/lib/components/widgets/common/template-aggregations/template-aggregations.component.ts b/libs/shared/src/lib/components/widgets/common/template-aggregations/template-aggregations.component.ts index 73789a6793..a95073a851 100644 --- a/libs/shared/src/lib/components/widgets/common/template-aggregations/template-aggregations.component.ts +++ b/libs/shared/src/lib/components/widgets/common/template-aggregations/template-aggregations.component.ts @@ -26,7 +26,7 @@ import { AggregationDataQueryResponse, ReferenceDataAggregationQueryResponse, } from '../../../../models/aggregation.model'; -import { errorMessageFormatter } from '../../../../utils/graphql/error-message-formatter'; +import { errorMessageFormatter } from '../../../../utils/graphql/error-handler'; /** * Template aggregations component. diff --git a/libs/shared/src/lib/interceptors/error-handler/error-handler-interceptor.service.ts b/libs/shared/src/lib/interceptors/error-handler/error-handler-interceptor.service.ts index f9c916b512..d23b76a854 100644 --- a/libs/shared/src/lib/interceptors/error-handler/error-handler-interceptor.service.ts +++ b/libs/shared/src/lib/interceptors/error-handler/error-handler-interceptor.service.ts @@ -4,11 +4,9 @@ import { HttpHandler, HttpEvent, HttpInterceptor, - HttpResponseBase, } from '@angular/common/http'; -import { Observable, catchError, of, switchMap, throwError } from 'rxjs'; +import { Observable, catchError, throwError } from 'rxjs'; import { SnackbarService } from '@oort-front/ui'; -import { isNil } from 'lodash'; /** * Error handler interceptor service @@ -39,27 +37,6 @@ export class ErrorHandlerInterceptorService implements HttpInterceptor { ): Observable> { if (request.url.includes(this.environment.apiUrl)) { return next.handle(request).pipe( - // GraphQl errors would be treated as so for the app even if status is 200 - switchMap((req) => { - const keysFromBody = Object.keys((req as any).body?.data); - if ( - req instanceof HttpResponseBase && - // Could be cases where we query two different objects and one can fail and the other no - // In those cases we prioritize the use of correctly retrieved data - // Therefor we treat as strict error if all queries fail - (((req as any).body?.errors?.length && - keysFromBody?.every((key) => - isNil((req as any).body?.data[key]) - )) || - keysFromBody?.every((key) => isNil((req as any).body?.data[key]))) - ) { - return throwError(() => { - return { error: { errors: (req as any).body?.errors } }; - }); - } else { - return of(req); - } - }), catchError((res: any) => { // Open default snackbar if error is not a GraphQL type if (res.status) { @@ -76,11 +53,7 @@ export class ErrorHandlerInterceptorService implements HttpInterceptor { duration: 0, }); } - return throwError(() => { - return !isNil(res.message) - ? { errors: [res.message] } - : res.error.errors; - }); + return throwError(() => res.error.errors); }) ); } else { diff --git a/libs/shared/src/lib/services/application-notifications/application-notifications.service.ts b/libs/shared/src/lib/services/application-notifications/application-notifications.service.ts index a8cf3f5d34..d94d2463a1 100644 --- a/libs/shared/src/lib/services/application-notifications/application-notifications.service.ts +++ b/libs/shared/src/lib/services/application-notifications/application-notifications.service.ts @@ -13,7 +13,7 @@ import { } from './graphql/mutations'; import { TranslateService } from '@ngx-translate/core'; import { SnackbarService } from '@oort-front/ui'; -import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; +import { errorMessageFormatter } from '../../utils/graphql/error-handler'; /** * Shared service to manage application's notifications. */ diff --git a/libs/shared/src/lib/services/application/application.service.ts b/libs/shared/src/lib/services/application/application.service.ts index a6d738fdfe..76c0036371 100644 --- a/libs/shared/src/lib/services/application/application.service.ts +++ b/libs/shared/src/lib/services/application/application.service.ts @@ -115,7 +115,7 @@ import { RestService } from '../rest/rest.service'; import { DownloadService } from '../download/download.service'; import { DOCUMENT } from '@angular/common'; import { GraphQLError } from 'graphql'; -import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; +import { errorMessageFormatter } from '../../utils/graphql/error-handler'; /** * Shared application service. Handles events of opened application. diff --git a/libs/shared/src/lib/services/context/context.service.ts b/libs/shared/src/lib/services/context/context.service.ts index 86f3fc3263..b90c452314 100644 --- a/libs/shared/src/lib/services/context/context.service.ts +++ b/libs/shared/src/lib/services/context/context.service.ts @@ -38,7 +38,7 @@ import { ApplicationService } from '../application/application.service'; import { ActivatedRoute, Router } from '@angular/router'; import { RecordQueryResponse } from '../../models/record.model'; import { GET_RECORD_BY_ID } from './graphql/queries'; -import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; +import { errorMessageFormatter } from '../../utils/graphql/error-handler'; /** * Dashboard context service diff --git a/libs/shared/src/lib/services/dashboard/dashboard.service.ts b/libs/shared/src/lib/services/dashboard/dashboard.service.ts index 4b8d371057..df729a90e3 100644 --- a/libs/shared/src/lib/services/dashboard/dashboard.service.ts +++ b/libs/shared/src/lib/services/dashboard/dashboard.service.ts @@ -15,7 +15,7 @@ import { Apollo } from 'apollo-angular'; import { EDIT_DASHBOARD, UPDATE_PAGE_CONTEXT } from './graphql/mutations'; import get from 'lodash/get'; import { GraphQLError } from 'graphql'; -import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; +import { errorMessageFormatter } from '../../utils/graphql/error-handler'; /** * Shared dashboard service. Handles dashboard events. diff --git a/libs/shared/src/lib/services/form-builder/form-builder.service.ts b/libs/shared/src/lib/services/form-builder/form-builder.service.ts index cc07030f19..de8dd9fd5e 100644 --- a/libs/shared/src/lib/services/form-builder/form-builder.service.ts +++ b/libs/shared/src/lib/services/form-builder/form-builder.service.ts @@ -16,7 +16,7 @@ import { BehaviorSubject } from 'rxjs'; import { SnackbarService } from '@oort-front/ui'; import { FormHelpersService } from '../form-helper/form-helper.service'; import { HttpClient } from '@angular/common/http'; -import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; +import { errorMessageFormatter } from '../../utils/graphql/error-handler'; /** * Shared form builder service. diff --git a/libs/shared/src/lib/services/form-helper/form-helper.service.ts b/libs/shared/src/lib/services/form-helper/form-helper.service.ts index c2a0435a8d..30b02b2cf2 100644 --- a/libs/shared/src/lib/services/form-helper/form-helper.service.ts +++ b/libs/shared/src/lib/services/form-helper/form-helper.service.ts @@ -22,7 +22,7 @@ import { DELETE_DRAFT_RECORD, EDIT_DRAFT_RECORD, } from './graphql/mutations'; -import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; +import { errorMessageFormatter } from '../../utils/graphql/error-handler'; /** * Shared survey helper service. */ diff --git a/libs/shared/src/lib/services/map/map-layers.service.ts b/libs/shared/src/lib/services/map/map-layers.service.ts index c6f88ac15c..e7ffa2ddcc 100644 --- a/libs/shared/src/lib/services/map/map-layers.service.ts +++ b/libs/shared/src/lib/services/map/map-layers.service.ts @@ -36,7 +36,7 @@ import { omitBy, isNil, get } from 'lodash'; import { ContextService } from '../context/context.service'; import { DOCUMENT } from '@angular/common'; import { MapPolygonsService } from './map-polygons.service'; -import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; +import { errorMessageFormatter } from '../../utils/graphql/error-handler'; /** * Shared map layer service diff --git a/libs/shared/src/lib/services/workflow/workflow.service.ts b/libs/shared/src/lib/services/workflow/workflow.service.ts index 7d90a7fbd0..ede0aa99b1 100644 --- a/libs/shared/src/lib/services/workflow/workflow.service.ts +++ b/libs/shared/src/lib/services/workflow/workflow.service.ts @@ -14,7 +14,7 @@ import { import { ApplicationService } from '../application/application.service'; import { TranslateService } from '@ngx-translate/core'; import { SnackbarService } from '@oort-front/ui'; -import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; +import { errorMessageFormatter } from '../../utils/graphql/error-handler'; /** * Workflow service. Handles modification of workflow ( step addition / step name update ) and some workflow actions. diff --git a/libs/shared/src/lib/utils/graphql/error-handler.ts b/libs/shared/src/lib/utils/graphql/error-handler.ts new file mode 100644 index 0000000000..d00765a0a7 --- /dev/null +++ b/libs/shared/src/lib/utils/graphql/error-handler.ts @@ -0,0 +1,40 @@ +import { ApolloLink, Observable } from '@apollo/client'; + +/** + * Gets the message in the graphql error + * + * @param errors GraphQL error + * @returns formatted message + */ +export const errorMessageFormatter = (errors: any): string => + (errors.networkError || errors)?.[0].message ?? ''; + +/** + * Create apollo link to handle any incoming graphQL error + * + * @param errorCallback error callback action when encountering an error + * @returns current graphql observable + */ +export const createGraphQlErrorHandler = (errorCallback: any) => + new ApolloLink((operation, forward) => { + return new Observable((observer) => { + const observable = forward(operation); + const subscription = observable.subscribe({ + next(value) { + if (value.errors) { + observer.error(value.errors); + } else { + observer.next(value); + } + }, + error(networkError) { + errorCallback({ networkError, operation }); + observer.error(networkError); + }, + complete() { + observer.complete(); + }, + }); + return () => subscription.unsubscribe(); + }); + }); diff --git a/libs/shared/src/lib/utils/graphql/error-message-formatter.ts b/libs/shared/src/lib/utils/graphql/error-message-formatter.ts deleted file mode 100644 index 9d4bb8231c..0000000000 --- a/libs/shared/src/lib/utils/graphql/error-message-formatter.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Gets the message in the graphql error - * - * @param errors GraphQL error - * @returns formatted message - */ -export const errorMessageFormatter = (errors: any): string => - (errors.networkError || errors)?.[0].message ?? ''; diff --git a/libs/shared/src/lib/utils/public-api.ts b/libs/shared/src/lib/utils/public-api.ts index 9429c065f0..9249a4c85e 100644 --- a/libs/shared/src/lib/utils/public-api.ts +++ b/libs/shared/src/lib/utils/public-api.ts @@ -1,4 +1,4 @@ export * from './validators/cron.validator'; export * from './graphql/connection.type'; -export * from './graphql/error-message-formatter'; +export * from './graphql/error-handler'; export * from './update-queries'; diff --git a/libs/shared/src/lib/views/application-users/application-users.component.ts b/libs/shared/src/lib/views/application-users/application-users.component.ts index 4869a151c4..864132161d 100644 --- a/libs/shared/src/lib/views/application-users/application-users.component.ts +++ b/libs/shared/src/lib/views/application-users/application-users.component.ts @@ -11,7 +11,7 @@ import { UserListComponent } from './components/user-list/user-list.component'; import { ADD_USERS } from './graphql/mutations'; import { SnackbarService } from '@oort-front/ui'; import { CompositeFilterDescriptor } from '@progress/kendo-data-query'; -import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; +import { errorMessageFormatter } from '../../utils/graphql/error-handler'; /** * Application users component. diff --git a/libs/shared/src/lib/views/profile/profile.component.ts b/libs/shared/src/lib/views/profile/profile.component.ts index 262be0f130..a903f698ae 100644 --- a/libs/shared/src/lib/views/profile/profile.component.ts +++ b/libs/shared/src/lib/views/profile/profile.component.ts @@ -8,7 +8,7 @@ import { UnsubscribeComponent } from '../../components/utils/unsubscribe/unsubsc import { takeUntil } from 'rxjs/operators'; import { SnackbarService } from '@oort-front/ui'; import { EditUserProfileMutationResponse, User } from '../../models/user.model'; -import { errorMessageFormatter } from '../../utils/graphql/error-message-formatter'; +import { errorMessageFormatter } from '../../utils/graphql/error-handler'; /** * Shared profile page. From abf26ec8be5800c548ae787b06824361b0bd0955 Mon Sep 17 00:00:00 2001 From: Unai Zalba Date: Tue, 12 Mar 2024 14:41:09 +0100 Subject: [PATCH 4/5] { errorsrefactor/AB#82357_create-shared-error-handler-logic-for-the-app feat: update error message handler function in order to format all message types coming from GraphQL requests feat: create error links for GraphQL error handling feat: update related requests with the new subscribe syntax with next and error callbacks to properly handle errors from requests --- .../app-preview/pages/form/form.component.ts | 76 ++- .../pages/workflow/workflow.component.ts | 1 + .../pages/archive/archive.component.ts | 2 +- .../application/pages/form/form.component.ts | 22 +- .../position-attributes.component.ts | 23 +- .../subscription-modal.component.ts | 9 +- .../add-form-modal.component.ts | 6 +- .../dashboard-filter-settings.component.ts | 33 +- .../duplicate-application-modal.component.ts | 3 +- .../api-configuration.component.ts | 17 +- .../applications/applications.component.ts | 18 +- .../chose-role/chose-role.component.ts | 9 +- .../context-datasource.component.ts | 16 +- .../pages/dashboard/dashboard.component.ts | 28 +- .../form-answer/form-answer.component.ts | 29 +- .../form-builder/form-builder.component.ts | 6 +- .../form-records/form-records.component.ts | 2 + .../dashboard/pages/forms/forms.component.ts | 12 +- .../edit-pull-job-modal.component.ts | 33 +- .../pages/pull-jobs/pull-jobs.component.ts | 11 +- .../reference-data.component.ts | 10 +- .../reference-datas.component.ts | 10 +- .../aggregations-tab.component.ts | 47 +- .../resource/forms-tab/forms-tab.component.ts | 15 +- .../layouts-tab/layouts-tab.component.ts | 55 +- .../records-tab/records-tab.component.ts | 11 +- .../pages/resources/resources.component.ts | 10 +- .../update-record/update-record.component.ts | 60 +- .../dashboard/pages/users/users.component.ts | 41 +- .../application/pages/form/form.component.ts | 18 +- .../pages/share/share.component.ts | 33 +- .../pages/workflow/workflow.component.ts | 1 + apps/web-widgets/src/app/graphql.module.ts | 2 + .../application/pages/form/form.component.ts | 18 +- .../pages/share/share.component.ts | 33 +- .../pages/workflow/workflow.component.ts | 1 + .../form-widget/components/form.component.ts | 15 +- .../edit-access/edit-access.component.ts | 6 +- .../add-aggregation-modal.component.ts | 13 +- .../aggregation-grid.component.ts | 7 +- .../aggregation-table.component.ts | 18 +- .../reference-data-select.component.ts | 11 +- .../resource-select.component.ts | 11 +- .../convert-modal/convert-modal.component.ts | 19 +- .../custom-widget-style.component.ts | 23 +- .../distribution-lists.component.ts | 25 +- .../draft-record-list-modal.component.ts | 13 +- .../src/lib/components/form/form.component.ts | 21 +- .../add-layout-modal.component.ts | 13 +- .../layout-table/layout-table.component.ts | 18 +- .../edit-notification-modal.component.ts | 18 +- .../notifications/notifications.component.ts | 57 +- .../query-builder/query-builder.component.ts | 40 +- .../record-dropdown.component.ts | 21 +- .../record-history.component.ts | 8 +- .../role-auto-assignment.component.ts | 62 ++- .../role-channels/role-channels.component.ts | 30 +- .../role-details/role-details.component.ts | 12 +- .../role-features/role-features.component.ts | 13 +- .../role-workflows.component.ts | 13 +- .../role-resources.component.ts | 29 +- .../role-summary/role-summary.component.ts | 38 +- .../role-users/role-users.component.ts | 12 +- .../group-list/group-list.component.ts | 25 +- .../role-list/role-list.component.ts | 13 +- .../aggregation-builder.component.ts | 26 +- .../ui/core-grid/core-grid.component.ts | 144 ++--- .../lib/components/ui/map/map.component.ts | 44 +- .../user-details/user-details.component.ts | 50 +- .../user-app-roles.component.ts | 13 +- .../user-back-roles.component.ts | 7 +- .../user-groups/user-groups.component.ts | 7 +- .../user-summary/user-summary.component.ts | 19 +- .../tab-filters/tab-filters.component.ts | 16 +- .../tab-main/tab-main.component.ts | 70 ++- .../widgets/chart/chart.component.ts | 15 +- .../template-aggregation-modal.component.ts | 44 +- .../template-aggregations.component.ts | 16 +- .../editor-settings.component.ts | 42 +- .../record-selection-tab.component.ts | 14 +- .../widgets/editor/editor.component.ts | 84 +-- .../grid-settings/grid-settings.component.ts | 41 +- .../components/widgets/grid/grid.component.ts | 161 +++--- .../edit-layer-modal.component.ts | 88 +-- .../layer-datasource.component.ts | 18 +- .../map-layers/map-layers.component.ts | 13 +- .../summary-card-general.component.ts | 32 +- .../summary-card-settings.component.ts | 56 +- .../summary-card/summary-card.component.ts | 27 +- .../error-handler-interceptor.service.ts | 1 + .../aggregation/aggregation.service.ts | 24 +- .../application/application.service.ts | 525 ++++++++++-------- .../lib/services/context/context.service.ts | 25 +- .../services/dashboard/dashboard.service.ts | 30 +- .../lib/services/download/download.service.ts | 40 +- .../form-helper/form-helper.service.ts | 96 ++-- .../grid-layout/grid-layout.service.ts | 24 +- .../lib/services/map/map-layers.service.ts | 9 +- .../lib/services/map/map-polygons.service.ts | 8 +- .../notification/notification.service.ts | 58 +- .../query-builder/query-builder.service.ts | 10 +- .../lib/services/workflow/workflow.service.ts | 134 +++-- .../application-dropdown.component.ts | 19 +- .../shared/src/lib/survey/components/owner.ts | 16 +- ...fig-display-grid-fields-modal.component.ts | 35 +- .../resource-dropdown.component.ts | 10 +- .../src/lib/survey/components/resource.ts | 50 +- .../src/lib/survey/components/resources.ts | 62 ++- .../test-service-dropdown.component.ts | 10 +- .../users-dropdown.component.ts | 10 +- .../src/lib/utils/graphql/error-handler.ts | 42 +- .../user-list/user-list.component.ts | 10 +- .../graphql-select.component.ts | 22 +- 113 files changed, 2133 insertions(+), 1509 deletions(-) diff --git a/apps/back-office/src/app/app-preview/pages/form/form.component.ts b/apps/back-office/src/app/app-preview/pages/form/form.component.ts index 4d55027e7d..c8192e5c2c 100644 --- a/apps/back-office/src/app/app-preview/pages/form/form.component.ts +++ b/apps/back-office/src/app/app-preview/pages/form/form.component.ts @@ -85,19 +85,29 @@ export class FormComponent extends UnsubscribeComponent implements OnInit { id: this.id, }, }) - .subscribe((res) => { - this.step = res.data.step; - this.apollo - .query({ - query: GET_SHORT_FORM_BY_ID, - variables: { - id: this.step.content, - }, - }) - .subscribe(({ data, loading }) => { - this.form = data.form; - this.loading = loading; - }); + .subscribe({ + next: (res) => { + this.step = res.data.step; + this.apollo + .query({ + query: GET_SHORT_FORM_BY_ID, + variables: { + id: this.step.content, + }, + }) + .subscribe({ + next: ({ data, loading }) => { + this.form = data.form; + this.loading = loading; + }, + error: () => { + this.loading = false; + }, + }); + }, + error: () => { + this.loading = false; + }, }); } else { this.apollo @@ -107,21 +117,31 @@ export class FormComponent extends UnsubscribeComponent implements OnInit { id: this.id, }, }) - .subscribe((res) => { - this.page = res.data.page; - this.apollo - .query({ - query: GET_SHORT_FORM_BY_ID, - variables: { - id: this.page.content, - }, - }) - .subscribe(({ data, loading }) => { - if (data) { - this.form = data.form; - } - this.loading = loading; - }); + .subscribe({ + next: (res) => { + this.page = res.data.page; + this.apollo + .query({ + query: GET_SHORT_FORM_BY_ID, + variables: { + id: this.page.content, + }, + }) + .subscribe({ + next: ({ data, loading }) => { + if (data) { + this.form = data.form; + } + this.loading = loading; + }, + error: () => { + this.loading = false; + }, + }); + }, + error: () => { + this.loading = false; + }, }); } }); diff --git a/apps/back-office/src/app/app-preview/pages/workflow/workflow.component.ts b/apps/back-office/src/app/app-preview/pages/workflow/workflow.component.ts index c61d4dfe57..b0f5dbc56e 100644 --- a/apps/back-office/src/app/app-preview/pages/workflow/workflow.component.ts +++ b/apps/back-office/src/app/app-preview/pages/workflow/workflow.component.ts @@ -108,6 +108,7 @@ export class WorkflowComponent extends UnsubscribeComponent implements OnInit { } }, error: () => { + this.loading = false; this.snackBar.openSnackBar( this.translate.instant('common.notifications.accessNotProvided', { type: this.translate diff --git a/apps/back-office/src/app/application/pages/archive/archive.component.ts b/apps/back-office/src/app/application/pages/archive/archive.component.ts index ea6fd9bf19..4eca0cabe8 100644 --- a/apps/back-office/src/app/application/pages/archive/archive.component.ts +++ b/apps/back-office/src/app/application/pages/archive/archive.component.ts @@ -93,6 +93,7 @@ export class ArchiveComponent extends UnsubscribeComponent implements OnInit { this.loading = false; }, error: () => { + this.loading = false; this.snackBar.openSnackBar( this.translate.instant('common.notifications.accessNotProvided', { type: this.translate.instant('common.workflow.one').toLowerCase(), @@ -100,7 +101,6 @@ export class ArchiveComponent extends UnsubscribeComponent implements OnInit { }), { error: true } ); - this.loading = false; }, }); } diff --git a/apps/back-office/src/app/application/pages/form/form.component.ts b/apps/back-office/src/app/application/pages/form/form.component.ts index 46d3657298..09510e1665 100644 --- a/apps/back-office/src/app/application/pages/form/form.component.ts +++ b/apps/back-office/src/app/application/pages/form/form.component.ts @@ -108,9 +108,14 @@ export class FormComponent extends UnsubscribeComponent implements OnInit { return this.getFormQuery(this.step.content ?? ''); }) ) - .subscribe(({ data, loading }) => { - this.handleFormQueryResponse(data, 'step'); - this.loading = loading; + .subscribe({ + next: ({ data, loading }) => { + this.handleFormQueryResponse(data, 'step'); + this.loading = loading; + }, + error: () => { + this.loading = false; + }, }); } else { this.querySubscription = this.apollo @@ -126,9 +131,14 @@ export class FormComponent extends UnsubscribeComponent implements OnInit { return this.getFormQuery(this.page.content ?? ''); }) ) - .subscribe(({ data, loading }) => { - this.handleFormQueryResponse(data, 'page'); - this.loading = loading; + .subscribe({ + next: ({ data, loading }) => { + this.handleFormQueryResponse(data, 'page'); + this.loading = loading; + }, + error: () => { + this.loading = false; + }, }); } }); diff --git a/apps/back-office/src/app/application/pages/position-attributes/position-attributes.component.ts b/apps/back-office/src/app/application/pages/position-attributes/position-attributes.component.ts index 1844b89574..9807feb2e8 100644 --- a/apps/back-office/src/app/application/pages/position-attributes/position-attributes.component.ts +++ b/apps/back-office/src/app/application/pages/position-attributes/position-attributes.component.ts @@ -56,13 +56,22 @@ export class PositionAttributesComponent implements OnInit { id: this.id, }, }) - .subscribe(({ data, loading }) => { - this.positionAttributes = data.positionAttributes; - if (this.positionAttributes.length > 0) { - this.categoryName = this.positionAttributes[0].category?.title || ''; - this.breadcrumbService.setBreadcrumb('@attribute', this.categoryName); - } - this.loading = loading; + .subscribe({ + next: ({ data, loading }) => { + this.positionAttributes = data.positionAttributes; + if (this.positionAttributes.length > 0) { + this.categoryName = + this.positionAttributes[0].category?.title || ''; + this.breadcrumbService.setBreadcrumb( + '@attribute', + this.categoryName + ); + } + this.loading = loading; + }, + error: () => { + this.loading = false; + }, }); } } diff --git a/apps/back-office/src/app/application/pages/subscriptions/components/subscription-modal/subscription-modal.component.ts b/apps/back-office/src/app/application/pages/subscriptions/components/subscription-modal/subscription-modal.component.ts index 1342220808..d6a638b8bc 100644 --- a/apps/back-office/src/app/application/pages/subscriptions/components/subscription-modal/subscription-modal.component.ts +++ b/apps/back-office/src/app/application/pages/subscriptions/components/subscription-modal/subscription-modal.component.ts @@ -165,8 +165,13 @@ export class SubscriptionModalComponent // this.applications$ = this.applications.asObservable(); this.applicationsQuery.valueChanges .pipe(takeUntil(this.destroy$)) - .subscribe((results) => { - this.updateValues(results.data, results.loading); + .subscribe({ + next: (results) => { + this.updateValues(results.data, results.loading); + }, + error: () => { + this.applicationsLoading = false; + }, }); this.formsQuery = this.apollo.watchQuery({ diff --git a/apps/back-office/src/app/components/add-form-modal/add-form-modal.component.ts b/apps/back-office/src/app/components/add-form-modal/add-form-modal.component.ts index 28169dab08..d51830da64 100644 --- a/apps/back-office/src/app/components/add-form-modal/add-form-modal.component.ts +++ b/apps/back-office/src/app/components/add-form-modal/add-form-modal.component.ts @@ -143,8 +143,10 @@ export class AddFormModalComponent implements OnInit { id, }, }) - .subscribe(({ data }) => { - this.templates = data.resource.forms || []; + .subscribe({ + next: ({ data }) => { + this.templates = data.resource.forms || []; + }, }); } } diff --git a/apps/back-office/src/app/components/dashboard-filter-settings/dashboard-filter-settings.component.ts b/apps/back-office/src/app/components/dashboard-filter-settings/dashboard-filter-settings.component.ts index 55a98fb986..90c4103334 100644 --- a/apps/back-office/src/app/components/dashboard-filter-settings/dashboard-filter-settings.component.ts +++ b/apps/back-office/src/app/components/dashboard-filter-settings/dashboard-filter-settings.component.ts @@ -139,21 +139,32 @@ export class DashboardFilterSettingsComponent }, }) .subscribe({ - next: ({ errors }) => { + next: () => { + this.dashboardService.handleEditionMutationResponse( + [], + this.translate.instant('common.dashboard.one') + ); + const filter = value; + this.dashboard = { + ...this.dashboard, + filter, + }; + // Updates parent component + const updates = { filter }; + this.parentComponent.onUpdate.emit(updates); + }, + error: (errors) => { this.dashboardService.handleEditionMutationResponse( errors, this.translate.instant('common.dashboard.one') ); - if (!errors) { - const filter = value; - this.dashboard = { - ...this.dashboard, - filter, - }; - // Updates parent component - const updates = { filter }; - this.parentComponent.onUpdate.emit(updates); - } + this.contextService.isFilterEnabled.next(value.show); + this.contextService.filterPosition.next({ + position: + (this.dashboard.filter?.position as FilterPosition) || + FilterPosition.BOTTOM, + dashboardId: this.dashboard.id ?? '', + }); }, complete: () => { this.contextService.isFilterEnabled.next(value.show); diff --git a/apps/back-office/src/app/components/duplicate-application-modal/duplicate-application-modal.component.ts b/apps/back-office/src/app/components/duplicate-application-modal/duplicate-application-modal.component.ts index 6c12da6667..2f6294a7a3 100644 --- a/apps/back-office/src/app/components/duplicate-application-modal/duplicate-application-modal.component.ts +++ b/apps/back-office/src/app/components/duplicate-application-modal/duplicate-application-modal.component.ts @@ -97,7 +97,6 @@ export class DuplicateApplicationModalComponent { .subscribe({ next: ({ data }) => { snackBarSpinner.instance.loading = false; - snackBarSpinner.instance.message = this.translateService.instant( 'common.notifications.objectDuplicated', { @@ -107,11 +106,11 @@ export class DuplicateApplicationModalComponent { value: this.currentApp.name, } ); - this.loading = false; this.dialogRef.close(data?.duplicateApplication as any); }, error: (errors) => { + this.loading = false; snackBarSpinner.instance.loading = false; snackBarSpinner.instance.message = this.translateService.instant( 'common.notifications.objectNotDuplicated', diff --git a/apps/back-office/src/app/dashboard/pages/api-configuration/api-configuration.component.ts b/apps/back-office/src/app/dashboard/pages/api-configuration/api-configuration.component.ts index b2b83acab2..8ea99267bd 100644 --- a/apps/back-office/src/app/dashboard/pages/api-configuration/api-configuration.component.ts +++ b/apps/back-office/src/app/dashboard/pages/api-configuration/api-configuration.component.ts @@ -304,8 +304,14 @@ export class ApiConfigurationComponent mutation: EDIT_API_CONFIGURATION, variables, }) - .subscribe(({ errors, data, loading }) => { - if (errors) { + .subscribe({ + next: ({ data, loading }) => { + this.apiConfiguration = data?.editApiConfiguration; + this.resetFormSettings(this.apiConfiguration?.authType as string); + this.loading = loading || false; + }, + error: (errors) => { + this.loading = false; this.snackBar.openSnackBar( this.translate.instant('common.notifications.objectNotUpdated', { type: this.translate.instant('common.apiConfiguration.one'), @@ -313,12 +319,7 @@ export class ApiConfigurationComponent }), { error: true } ); - } else { - this.apiConfiguration = data?.editApiConfiguration; - this.resetFormSettings(this.apiConfiguration?.authType as string); - this.loading = loading || false; - } - this.loading = loading; + }, }); } diff --git a/apps/back-office/src/app/dashboard/pages/applications/applications.component.ts b/apps/back-office/src/app/dashboard/pages/applications/applications.component.ts index 02e386a5e6..da06e650bd 100644 --- a/apps/back-office/src/app/dashboard/pages/applications/applications.component.ts +++ b/apps/back-office/src/app/dashboard/pages/applications/applications.component.ts @@ -130,18 +130,24 @@ export class ApplicationsComponent }, }) .pipe(takeUntil(this.destroy$)) - .subscribe(({ data }) => { - this.newApplications = data.applications.edges.map((x) => x.node); + .subscribe({ + next: ({ data }) => { + this.newApplications = data.applications.edges.map((x) => x.node); + }, }); this.applicationsQuery.valueChanges .pipe(takeUntil(this.destroy$)) - .subscribe( - ( + .subscribe({ + next: ( results: ApolloQueryResult ) => { this.updateValues(results.data, results.loading); - } - ); + }, + error: () => { + this.loading = false; + this.updating = false; + }, + }); } /** diff --git a/apps/back-office/src/app/dashboard/pages/applications/components/chose-role/chose-role.component.ts b/apps/back-office/src/app/dashboard/pages/applications/components/chose-role/chose-role.component.ts index 1b48fcc188..a77458590a 100644 --- a/apps/back-office/src/app/dashboard/pages/applications/components/chose-role/chose-role.component.ts +++ b/apps/back-office/src/app/dashboard/pages/applications/components/chose-role/chose-role.component.ts @@ -52,8 +52,13 @@ export class ChoseRoleComponent implements OnInit { }, }); - this.rolesQuery.valueChanges.subscribe(({ loading }) => { - this.loading = loading; + this.rolesQuery.valueChanges.subscribe({ + next: ({ loading }) => { + this.loading = loading; + }, + error: () => { + this.loading = false; + }, }); } } diff --git a/apps/back-office/src/app/dashboard/pages/dashboard/components/context-datasource/context-datasource.component.ts b/apps/back-office/src/app/dashboard/pages/dashboard/components/context-datasource/context-datasource.component.ts index 5c7c8cd506..34ea1e0d8f 100644 --- a/apps/back-office/src/app/dashboard/pages/dashboard/components/context-datasource/context-datasource.component.ts +++ b/apps/back-office/src/app/dashboard/pages/dashboard/components/context-datasource/context-datasource.component.ts @@ -174,9 +174,11 @@ export class ContextDatasourceComponent id, }, }) - .subscribe(({ data }) => { - this.refData = data.referenceData; - this.updateDisplayFieldOptions(); + .subscribe({ + next: ({ data }) => { + this.refData = data.referenceData; + this.updateDisplayFieldOptions(); + }, }); } @@ -193,9 +195,11 @@ export class ContextDatasourceComponent id, }, }) - .subscribe(({ data }) => { - this.resource = data.resource; - this.updateDisplayFieldOptions(); + .subscribe({ + next: ({ data }) => { + this.resource = data.resource; + this.updateDisplayFieldOptions(); + }, }); } diff --git a/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts b/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts index bccc611863..5db5a1e043 100644 --- a/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts +++ b/apps/back-office/src/app/dashboard/pages/dashboard/dashboard.component.ts @@ -485,7 +485,15 @@ export class DashboardComponent }, }) .subscribe({ - next: ({ errors }) => { + next: () => { + this.loading = false; + this.applicationService.handleEditionMutationResponse( + [], + this.translate.instant('common.dashboard.one') + ); + }, + error: (errors) => { + this.loading = false; this.applicationService.handleEditionMutationResponse( errors, this.translate.instant('common.dashboard.one') @@ -575,8 +583,10 @@ export class DashboardComponent this.dashboardService .saveDashboardButtons(this.dashboard?.id, [...currButtons, button]) ?.pipe(takeUntil(this.destroy$)) - .subscribe(() => { - this.buttonActions.push(button); + .subscribe({ + next: () => { + this.buttonActions.push(button); + }, }); }); } @@ -692,11 +702,13 @@ export class DashboardComponent this.dashboardService .saveDashboardButtons(this.dashboard?.id, this.buttonActions) - ?.subscribe(() => { - this.dashboard = { - ...this.dashboard, - buttons: this.buttonActions, - }; + ?.subscribe({ + next: () => { + this.dashboard = { + ...this.dashboard, + buttons: this.buttonActions, + }; + }, }); } diff --git a/apps/back-office/src/app/dashboard/pages/form-answer/form-answer.component.ts b/apps/back-office/src/app/dashboard/pages/form-answer/form-answer.component.ts index 1dbf1dbf57..1812359255 100644 --- a/apps/back-office/src/app/dashboard/pages/form-answer/form-answer.component.ts +++ b/apps/back-office/src/app/dashboard/pages/form-answer/form-answer.component.ts @@ -53,18 +53,23 @@ export class FormAnswerComponent implements OnInit { id: this.id, }, }) - .valueChanges.subscribe(({ data, loading }) => { - this.loading = loading; - this.form = data.form; - this.breadcrumbService.setBreadcrumb( - '@form', - this.form.name as string - ); - this.breadcrumbService.setBreadcrumb( - '@resource', - this.form.resource?.name as string - ); - // this.breadcrumbService.setResourceName(); + .valueChanges.subscribe({ + next: ({ data, loading }) => { + this.loading = loading; + this.form = data.form; + this.breadcrumbService.setBreadcrumb( + '@form', + this.form.name as string + ); + this.breadcrumbService.setBreadcrumb( + '@resource', + this.form.resource?.name as string + ); + // this.breadcrumbService.setResourceName(); + }, + error: () => { + this.loading = false; + }, }); } } diff --git a/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts b/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts index 406934a99e..614f52b494 100644 --- a/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts +++ b/apps/back-office/src/app/dashboard/pages/form-builder/form-builder.component.ts @@ -401,8 +401,10 @@ export class FormBuilderComponent implements OnInit { id, }, }) - .valueChanges.subscribe(({ data }) => { - this.structure = data.form.structure; + .valueChanges.subscribe({ + next: ({ data }) => { + this.structure = data.form.structure; + }, }); } diff --git a/apps/back-office/src/app/dashboard/pages/form-records/form-records.component.ts b/apps/back-office/src/app/dashboard/pages/form-records/form-records.component.ts index e670bff23f..ee0a54e8d4 100644 --- a/apps/back-office/src/app/dashboard/pages/form-records/form-records.component.ts +++ b/apps/back-office/src/app/dashboard/pages/form-records/form-records.component.ts @@ -161,6 +161,8 @@ export class FormRecordsComponent this.updateValues(data, loading, true); }, error: (errors) => { + this.loading = false; + this.updating = false; // TO-DO: Check why it's not working as intended. this.snackBar.openSnackBar( this.translate.instant('common.notifications.accessNotProvided', { diff --git a/apps/back-office/src/app/dashboard/pages/forms/forms.component.ts b/apps/back-office/src/app/dashboard/pages/forms/forms.component.ts index 3fc5fbd59c..97bdef393d 100644 --- a/apps/back-office/src/app/dashboard/pages/forms/forms.component.ts +++ b/apps/back-office/src/app/dashboard/pages/forms/forms.component.ts @@ -115,11 +115,15 @@ export class FormsComponent extends UnsubscribeComponent implements OnInit { }, }); - this.formsQuery.valueChanges - .pipe(takeUntil(this.destroy$)) - .subscribe((results) => { + this.formsQuery.valueChanges.pipe(takeUntil(this.destroy$)).subscribe({ + next: (results) => { this.updateValues(results.data, results.loading); - }); + }, + error: () => { + this.loading = false; + this.updating = false; + }, + }); } /** diff --git a/apps/back-office/src/app/dashboard/pages/pull-jobs/components/edit-pull-job-modal/edit-pull-job-modal.component.ts b/apps/back-office/src/app/dashboard/pages/pull-jobs/components/edit-pull-job-modal/edit-pull-job-modal.component.ts index 85ce3316c1..ae1706a4ec 100644 --- a/apps/back-office/src/app/dashboard/pages/pull-jobs/components/edit-pull-job-modal/edit-pull-job-modal.component.ts +++ b/apps/back-office/src/app/dashboard/pages/pull-jobs/components/edit-pull-job-modal/edit-pull-job-modal.component.ts @@ -228,12 +228,12 @@ export class EditPullJobModalComponent implements OnInit { first: ITEMS_PER_PAGE, }, }); - this.apiConfigurationsQuery.valueChanges.subscribe( - ({ data }) => + this.apiConfigurationsQuery.valueChanges.subscribe({ + next: ({ data }) => (this.apiConfigurations = data.apiConfigurations.edges.map( (x) => x.node - )) - ); + )), + }); // Fetch form fields if any for mapping if (this.data.pullJob?.convertTo?.id) { @@ -256,8 +256,13 @@ export class EditPullJobModalComponent implements OnInit { }); // this.applications$ = this.applications.asObservable(); - this.applicationsQuery.valueChanges.subscribe(({ data, loading }) => { - this.updateValues(data, loading); + this.applicationsQuery.valueChanges.subscribe({ + next: ({ data, loading }) => { + this.updateValues(data, loading); + }, + error: () => { + this.applicationsLoading = false; + }, }); // Set boolean to allow additional fields if it's not isHardcoded @@ -317,13 +322,15 @@ export class EditPullJobModalComponent implements OnInit { id, }, }) - .valueChanges.subscribe((resForm) => { - if (resForm.data.form) { - this.fields = resForm.data.form.fields || []; - this.fields = this.fields.concat( - DEFAULT_FIELDS.map((x) => ({ name: x })) - ); - } + .valueChanges.subscribe({ + next: (resForm) => { + if (resForm.data.form) { + this.fields = resForm.data.form.fields || []; + this.fields = this.fields.concat( + DEFAULT_FIELDS.map((x) => ({ name: x })) + ); + } + }, }); } diff --git a/apps/back-office/src/app/dashboard/pages/pull-jobs/pull-jobs.component.ts b/apps/back-office/src/app/dashboard/pages/pull-jobs/pull-jobs.component.ts index 66642be1e7..3181d657c0 100644 --- a/apps/back-office/src/app/dashboard/pages/pull-jobs/pull-jobs.component.ts +++ b/apps/back-office/src/app/dashboard/pages/pull-jobs/pull-jobs.component.ts @@ -92,11 +92,14 @@ export class PullJobsComponent extends UnsubscribeComponent implements OnInit { }, }); - this.pullJobsQuery.valueChanges - .pipe(takeUntil(this.destroy$)) - .subscribe((results) => { + this.pullJobsQuery.valueChanges.pipe(takeUntil(this.destroy$)).subscribe({ + next: (results) => { this.updateValues(results.data, results.loading); - }); + }, + error: () => { + this.loading = false; + }, + }); } /** diff --git a/apps/back-office/src/app/dashboard/pages/reference-data/reference-data.component.ts b/apps/back-office/src/app/dashboard/pages/reference-data/reference-data.component.ts index 74a7e4feb8..8b03e58ee6 100644 --- a/apps/back-office/src/app/dashboard/pages/reference-data/reference-data.component.ts +++ b/apps/back-office/src/app/dashboard/pages/reference-data/reference-data.component.ts @@ -460,10 +460,12 @@ export class ReferenceDataComponent id: this.referenceForm.value.apiConfiguration, }, }) - .subscribe(({ data }) => { - if (data.apiConfiguration) { - this.selectedApiConfiguration = data.apiConfiguration; - } + .subscribe({ + next: ({ data }) => { + if (data.apiConfiguration) { + this.selectedApiConfiguration = data.apiConfiguration; + } + }, }); } diff --git a/apps/back-office/src/app/dashboard/pages/reference-datas/reference-datas.component.ts b/apps/back-office/src/app/dashboard/pages/reference-datas/reference-datas.component.ts index 15fe17cf7e..37cb81758d 100644 --- a/apps/back-office/src/app/dashboard/pages/reference-datas/reference-datas.component.ts +++ b/apps/back-office/src/app/dashboard/pages/reference-datas/reference-datas.component.ts @@ -112,8 +112,14 @@ export class ReferenceDatasComponent this.referenceDatasQuery.valueChanges .pipe(takeUntil(this.destroy$)) - .subscribe(({ data, loading }) => { - this.updateValues(data, loading); + .subscribe({ + next: ({ data, loading }) => { + this.updateValues(data, loading); + }, + error: () => { + this.loading = false; + this.updating = false; + }, }); // Initializing sort to an empty one diff --git a/apps/back-office/src/app/dashboard/pages/resource/aggregations-tab/aggregations-tab.component.ts b/apps/back-office/src/app/dashboard/pages/resource/aggregations-tab/aggregations-tab.component.ts index 5d57ec0e45..c8dc25988b 100644 --- a/apps/back-office/src/app/dashboard/pages/resource/aggregations-tab/aggregations-tab.component.ts +++ b/apps/back-office/src/app/dashboard/pages/resource/aggregations-tab/aggregations-tab.component.ts @@ -109,8 +109,13 @@ export class AggregationsTabComponent }, }); - this.aggregationsQuery.valueChanges.subscribe(({ data, loading }) => { - this.updateValues(data, loading); + this.aggregationsQuery.valueChanges.subscribe({ + next: ({ data, loading }) => { + this.updateValues(data, loading); + }, + error: () => { + this.loading = false; + }, }); } @@ -236,16 +241,18 @@ export class AggregationsTabComponent if (value) { this.aggregationService .editAggregation(aggregation, value, { resource: this.resource.id }) - .subscribe(({ data }: any) => { - if (data.editAggregation) { - this.aggregations = this.aggregations.map((x: any) => { - if (x.id === aggregation.id) { - return data.editAggregation; - } else { - return x; - } - }); - } + .subscribe({ + next: ({ data }: any) => { + if (data.editAggregation) { + this.aggregations = this.aggregations.map((x: any) => { + if (x.id === aggregation.id) { + return data.editAggregation; + } else { + return x; + } + }); + } + }, }); } }); @@ -273,13 +280,15 @@ export class AggregationsTabComponent if (value) { this.aggregationService .deleteAggregation(aggregation, { resource: this.resource.id }) - .subscribe(({ data }: any) => { - if (data.deleteAggregation) { - this.aggregations = this.aggregations.filter( - (x: any) => x.id !== aggregation.id - ); - this.pageInfo.length -= 1; - } + .subscribe({ + next: ({ data }: any) => { + if (data.deleteAggregation) { + this.aggregations = this.aggregations.filter( + (x: any) => x.id !== aggregation.id + ); + this.pageInfo.length -= 1; + } + }, }); } }); diff --git a/apps/back-office/src/app/dashboard/pages/resource/forms-tab/forms-tab.component.ts b/apps/back-office/src/app/dashboard/pages/resource/forms-tab/forms-tab.component.ts index 73e3be4a39..67d87c8a48 100644 --- a/apps/back-office/src/app/dashboard/pages/resource/forms-tab/forms-tab.component.ts +++ b/apps/back-office/src/app/dashboard/pages/resource/forms-tab/forms-tab.component.ts @@ -81,11 +81,16 @@ export class FormsTabComponent extends UnsubscribeComponent implements OnInit { id: this.resource?.id, }, }) - .subscribe(({ data }) => { - if (data.resource) { - this.forms = data.resource.forms || []; - } - this.loading = false; + .subscribe({ + next: ({ data }) => { + if (data.resource) { + this.forms = data.resource.forms || []; + } + this.loading = false; + }, + error: () => { + this.loading = false; + }, }); } diff --git a/apps/back-office/src/app/dashboard/pages/resource/layouts-tab/layouts-tab.component.ts b/apps/back-office/src/app/dashboard/pages/resource/layouts-tab/layouts-tab.component.ts index 4b7a2b179b..9f5ac47f36 100644 --- a/apps/back-office/src/app/dashboard/pages/resource/layouts-tab/layouts-tab.component.ts +++ b/apps/back-office/src/app/dashboard/pages/resource/layouts-tab/layouts-tab.component.ts @@ -103,8 +103,13 @@ export class LayoutsTabComponent }, }); - this.layoutsQuery.valueChanges.subscribe(({ data, loading }) => { - this.updateValues(data, loading); + this.layoutsQuery.valueChanges.subscribe({ + next: ({ data, loading }) => { + this.updateValues(data, loading); + }, + error: () => { + this.loading = false; + }, }); } @@ -186,14 +191,14 @@ export class LayoutsTabComponent }); dialogRef.closed.pipe(takeUntil(this.destroy$)).subscribe((value: any) => { if (value) { - this.gridLayoutService - .addLayout(value, this.resource.id) - .subscribe(({ data }: any) => { + this.gridLayoutService.addLayout(value, this.resource.id).subscribe({ + next: ({ data }: any) => { if (data.addLayout) { this.layouts = [...this.layouts, data?.addLayout]; this.pageInfo.length += 1; } - }); + }, + }); } }); } @@ -216,16 +221,18 @@ export class LayoutsTabComponent if (value) { this.gridLayoutService .editLayout(layout, value, this.resource.id) - .subscribe(({ data }: any) => { - if (data.editLayout) { - this.layouts = this.layouts.map((x: any) => { - if (x.id === layout.id) { - return data.editLayout; - } else { - return x; - } - }); - } + .subscribe({ + next: ({ data }: any) => { + if (data.editLayout) { + this.layouts = this.layouts.map((x: any) => { + if (x.id === layout.id) { + return data.editLayout; + } else { + return x; + } + }); + } + }, }); } }); @@ -253,13 +260,15 @@ export class LayoutsTabComponent if (value) { this.gridLayoutService .deleteLayout(layout, this.resource.id) - .subscribe(({ data }: any) => { - if (data.deleteLayout) { - this.layouts = this.layouts.filter( - (x: any) => x.id !== layout.id - ); - this.pageInfo.length -= 1; - } + .subscribe({ + next: ({ data }: any) => { + if (data.deleteLayout) { + this.layouts = this.layouts.filter( + (x: any) => x.id !== layout.id + ); + this.pageInfo.length -= 1; + } + }, }); } }); diff --git a/apps/back-office/src/app/dashboard/pages/resource/records-tab/records-tab.component.ts b/apps/back-office/src/app/dashboard/pages/resource/records-tab/records-tab.component.ts index 8f3863172c..cfff27964b 100644 --- a/apps/back-office/src/app/dashboard/pages/resource/records-tab/records-tab.component.ts +++ b/apps/back-office/src/app/dashboard/pages/resource/records-tab/records-tab.component.ts @@ -132,11 +132,14 @@ export class RecordsTabComponent showDeletedRecords: this.showDeletedRecords, }, }); - this.recordsQuery.valueChanges - .pipe(takeUntil(this.destroy$)) - .subscribe(({ data, loading }) => { + this.recordsQuery.valueChanges.pipe(takeUntil(this.destroy$)).subscribe({ + next: ({ data, loading }) => { this.updateValues(data, loading); - }); + }, + error: () => { + this.loading = false; + }, + }); } /** diff --git a/apps/back-office/src/app/dashboard/pages/resources/resources.component.ts b/apps/back-office/src/app/dashboard/pages/resources/resources.component.ts index cc41d802f2..3c6e8a5f23 100644 --- a/apps/back-office/src/app/dashboard/pages/resources/resources.component.ts +++ b/apps/back-office/src/app/dashboard/pages/resources/resources.component.ts @@ -128,8 +128,14 @@ export class ResourcesComponent extends UnsubscribeComponent implements OnInit { }, }); - this.resourcesQuery.valueChanges.subscribe(({ data, loading }) => { - this.updateValues(data, loading); + this.resourcesQuery.valueChanges.subscribe({ + next: ({ data, loading }) => { + this.updateValues(data, loading); + }, + error: () => { + this.loading = false; + this.updating = false; + }, }); } diff --git a/apps/back-office/src/app/dashboard/pages/update-record/update-record.component.ts b/apps/back-office/src/app/dashboard/pages/update-record/update-record.component.ts index 271afa44da..1fcd5bec71 100644 --- a/apps/back-office/src/app/dashboard/pages/update-record/update-record.component.ts +++ b/apps/back-office/src/app/dashboard/pages/update-record/update-record.component.ts @@ -52,13 +52,18 @@ export class UpdateRecordComponent implements OnInit { id: template, }, }) - .valueChanges.subscribe(({ data, loading }) => { - this.form = data.form; - this.breadcrumbService.setBreadcrumb( - '@resource', - this.form.name as string - ); - this.loading = loading; + .valueChanges.subscribe({ + next: ({ data, loading }) => { + this.form = data.form; + this.breadcrumbService.setBreadcrumb( + '@resource', + this.form.name as string + ); + this.loading = loading; + }, + error: () => { + this.loading = false; + }, }); } if (this.id !== null) { @@ -69,24 +74,29 @@ export class UpdateRecordComponent implements OnInit { id: this.id, }, }) - .valueChanges.subscribe(({ data, loading }) => { - this.record = data.record; - this.breadcrumbService.setBreadcrumb( - '@record', - this.record.incrementalId as string - ); - this.breadcrumbService.setBreadcrumb( - '@form', - this.record.form?.name as string - ); - this.breadcrumbService.setBreadcrumb( - '@resource', - this.record.form?.name as string - ); - if (!template) { - this.form = this.record.form || {}; - this.loading = loading; - } + .valueChanges.subscribe({ + next: ({ data, loading }) => { + this.record = data.record; + this.breadcrumbService.setBreadcrumb( + '@record', + this.record.incrementalId as string + ); + this.breadcrumbService.setBreadcrumb( + '@form', + this.record.form?.name as string + ); + this.breadcrumbService.setBreadcrumb( + '@resource', + this.record.form?.name as string + ); + if (!template) { + this.form = this.record.form || {}; + this.loading = loading; + } + }, + error: () => { + this.loading = false; + }, }); } } diff --git a/apps/back-office/src/app/dashboard/pages/users/users.component.ts b/apps/back-office/src/app/dashboard/pages/users/users.component.ts index 4418bdbf6b..a1d1ac4eed 100644 --- a/apps/back-office/src/app/dashboard/pages/users/users.component.ts +++ b/apps/back-office/src/app/dashboard/pages/users/users.component.ts @@ -121,16 +121,24 @@ export class UsersComponent extends UnsubscribeComponent implements OnInit { .watchQuery({ query: GET_ROLES, }) - .valueChanges.subscribe(({ data, loading }) => { - this.roles = data.roles; - this.loading = loading; + .valueChanges.subscribe({ + next: ({ data, loading }) => { + this.roles = data.roles; + this.loading = loading; + }, + error: () => { + this.loading = false; + }, }); - this.usersQuery.valueChanges - .pipe(takeUntil(this.destroy$)) - .subscribe(({ data, loading }) => { + this.usersQuery.valueChanges.pipe(takeUntil(this.destroy$)).subscribe({ + next: ({ data, loading }) => { this.loading = true; this.updateValues(data, loading); - }); + }, + error: () => { + this.loading = false; + }, + }); } /** @@ -260,27 +268,10 @@ export class UsersComponent extends UnsubscribeComponent implements OnInit { ); } this.fetchUsers(true); - } else { - if (ids.length > 1) { - this.snackBar.openSnackBar( - this.translate.instant( - 'components.users.onNotDelete.plural', - { error: '' } - ), - { error: true } - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant( - 'components.users.onNotDelete.singular', - { error: '' } - ), - { error: true } - ); - } } }, error: (errors) => { + this.loading = false; if (ids.length > 1) { this.snackBar.openSnackBar( this.translate.instant( diff --git a/apps/front-office/src/app/application/pages/form/form.component.ts b/apps/front-office/src/app/application/pages/form/form.component.ts index 2de2312f26..ef003f75ee 100644 --- a/apps/front-office/src/app/application/pages/form/form.component.ts +++ b/apps/front-office/src/app/application/pages/form/form.component.ts @@ -99,8 +99,13 @@ export class FormComponent extends UnsubscribeComponent implements OnInit { return this.getFormQuery(this.step.content ?? ''); }) ) - .subscribe(({ data, loading }) => { - this.handleApplicationLoadResponse(data, loading); + .subscribe({ + next: ({ data, loading }) => { + this.handleApplicationLoadResponse(data, loading); + }, + error: () => { + this.loading = false; + }, }); } else { this.querySubscription = this.apollo @@ -116,8 +121,13 @@ export class FormComponent extends UnsubscribeComponent implements OnInit { return this.getFormQuery(this.page.content ?? ''); }) ) - .subscribe(({ data, loading }) => { - this.handleApplicationLoadResponse(data, loading); + .subscribe({ + next: ({ data, loading }) => { + this.handleApplicationLoadResponse(data, loading); + }, + error: () => { + this.loading = false; + }, }); } }); diff --git a/apps/front-office/src/app/application/pages/share/share.component.ts b/apps/front-office/src/app/application/pages/share/share.component.ts index e529d20b2d..3cbfef64be 100644 --- a/apps/front-office/src/app/application/pages/share/share.component.ts +++ b/apps/front-office/src/app/application/pages/share/share.component.ts @@ -53,20 +53,24 @@ export class ShareComponent extends UnsubscribeComponent implements OnInit { id: params.id, }, }) - .subscribe(({ data }) => { - let url = ''; - const dashboard: Dashboard = data.dashboard; - if (dashboard) { - if (dashboard.step) { - url += - '/' + data.dashboard.step?.workflow?.page?.application?.id; - url += '/workflow/' + data.dashboard.step?.workflow?.id; - url += '/dashboard/' + data.dashboard.id; - } else { - url += '/' + data.dashboard.page?.application?.id; - url += '/dashboard/' + data.dashboard.id; + .subscribe({ + next: ({ data }) => { + let url = ''; + const dashboard: Dashboard = data.dashboard; + if (dashboard) { + if (dashboard.step) { + url += + '/' + data.dashboard.step?.workflow?.page?.application?.id; + url += '/workflow/' + data.dashboard.step?.workflow?.id; + url += '/dashboard/' + data.dashboard.id; + } else { + url += '/' + data.dashboard.page?.application?.id; + url += '/dashboard/' + data.dashboard.id; + } } - } else { + this.router.navigate([url]); + }, + error: () => { // Error handling this.snackBar.openSnackBar( this.translateService.instant( @@ -80,8 +84,7 @@ export class ShareComponent extends UnsubscribeComponent implements OnInit { ), { error: true } ); - } - this.router.navigate([url]); + }, }); }); } diff --git a/apps/front-office/src/app/application/pages/workflow/workflow.component.ts b/apps/front-office/src/app/application/pages/workflow/workflow.component.ts index 2d4da4117f..8ee0276163 100644 --- a/apps/front-office/src/app/application/pages/workflow/workflow.component.ts +++ b/apps/front-office/src/app/application/pages/workflow/workflow.component.ts @@ -118,6 +118,7 @@ export class WorkflowComponent extends UnsubscribeComponent implements OnInit { } }, error: () => { + this.loading = false; this.snackBar.openSnackBar( this.translate.instant('common.notifications.accessNotProvided', { type: this.translate diff --git a/apps/web-widgets/src/app/graphql.module.ts b/apps/web-widgets/src/app/graphql.module.ts index 113d734641..7e576c1cb1 100644 --- a/apps/web-widgets/src/app/graphql.module.ts +++ b/apps/web-widgets/src/app/graphql.module.ts @@ -14,6 +14,7 @@ import extractFiles from 'extract-files/extractFiles.mjs'; import isExtractableFile from 'extract-files/isExtractableFile.mjs'; import { GraphQLWsLink } from '@apollo/client/link/subscriptions'; import { createClient } from 'graphql-ws'; +import { createGraphQlErrorHandler } from '@oort-front/shared'; /** * Configuration of the Apollo client. @@ -63,6 +64,7 @@ export const createApollo = (httpLink: HttpLink): ApolloClientOptions => { const link = ApolloLink.from([ basic, + createGraphQlErrorHandler(console.error), auth, split( ({ query }) => { diff --git a/apps/web-widgets/src/app/widgets/app-widget/application/pages/form/form.component.ts b/apps/web-widgets/src/app/widgets/app-widget/application/pages/form/form.component.ts index 23d52c3c6c..6987d4538d 100644 --- a/apps/web-widgets/src/app/widgets/app-widget/application/pages/form/form.component.ts +++ b/apps/web-widgets/src/app/widgets/app-widget/application/pages/form/form.component.ts @@ -99,8 +99,13 @@ export class FormComponent extends UnsubscribeComponent implements OnInit { return this.getFormQuery(this.step.content ?? ''); }) ) - .subscribe(({ data, loading }) => { - this.handleApplicationLoadResponse(data, loading); + .subscribe({ + next: ({ data, loading }) => { + this.handleApplicationLoadResponse(data, loading); + }, + error: () => { + this.loading = false; + }, }); } else { this.querySubscription = this.apollo @@ -116,8 +121,13 @@ export class FormComponent extends UnsubscribeComponent implements OnInit { return this.getFormQuery(this.page.content ?? ''); }) ) - .subscribe(({ data, loading }) => { - this.handleApplicationLoadResponse(data, loading); + .subscribe({ + next: ({ data, loading }) => { + this.handleApplicationLoadResponse(data, loading); + }, + error: () => { + this.loading = false; + }, }); } }); diff --git a/apps/web-widgets/src/app/widgets/app-widget/application/pages/share/share.component.ts b/apps/web-widgets/src/app/widgets/app-widget/application/pages/share/share.component.ts index 7b222ed633..0069d234ea 100644 --- a/apps/web-widgets/src/app/widgets/app-widget/application/pages/share/share.component.ts +++ b/apps/web-widgets/src/app/widgets/app-widget/application/pages/share/share.component.ts @@ -53,20 +53,24 @@ export class ShareComponent extends UnsubscribeComponent implements OnInit { id: params.id, }, }) - .subscribe(({ data }) => { - let url = ''; - const dashboard: Dashboard = data.dashboard; - if (dashboard) { - if (dashboard.step) { - url += - '/' + data.dashboard.step?.workflow?.page?.application?.id; - url += '/workflow/' + data.dashboard.step?.workflow?.id; - url += '/dashboard/' + data.dashboard.id; - } else { - url += '/' + data.dashboard.page?.application?.id; - url += '/dashboard/' + data.dashboard.id; + .subscribe({ + next: ({ data }) => { + let url = ''; + const dashboard: Dashboard = data.dashboard; + if (dashboard) { + if (dashboard.step) { + url += + '/' + data.dashboard.step?.workflow?.page?.application?.id; + url += '/workflow/' + data.dashboard.step?.workflow?.id; + url += '/dashboard/' + data.dashboard.id; + } else { + url += '/' + data.dashboard.page?.application?.id; + url += '/dashboard/' + data.dashboard.id; + } } - } else { + this.router.navigate([url]); + }, + error: () => { // Error handling this.snackBar.openSnackBar( this.translateService.instant( @@ -80,8 +84,7 @@ export class ShareComponent extends UnsubscribeComponent implements OnInit { ), { error: true } ); - } - this.router.navigate([url]); + }, }); }); } diff --git a/apps/web-widgets/src/app/widgets/app-widget/application/pages/workflow/workflow.component.ts b/apps/web-widgets/src/app/widgets/app-widget/application/pages/workflow/workflow.component.ts index e6f812b8b4..ff657542f9 100644 --- a/apps/web-widgets/src/app/widgets/app-widget/application/pages/workflow/workflow.component.ts +++ b/apps/web-widgets/src/app/widgets/app-widget/application/pages/workflow/workflow.component.ts @@ -101,6 +101,7 @@ export class WorkflowComponent extends UnsubscribeComponent implements OnInit { } }, error: () => { + this.loading = false; this.snackBar.openSnackBar( this.translate.instant('common.notifications.accessNotProvided', { type: this.translate diff --git a/apps/web-widgets/src/app/widgets/form-widget/components/form.component.ts b/apps/web-widgets/src/app/widgets/form-widget/components/form.component.ts index 66e3847449..fc24035dbf 100644 --- a/apps/web-widgets/src/app/widgets/form-widget/components/form.component.ts +++ b/apps/web-widgets/src/app/widgets/form-widget/components/form.component.ts @@ -58,11 +58,16 @@ export class FormComponent implements OnInit, OnChanges { * Trigger get form query action */ private getFormById() { - this.getFormQuery.subscribe(({ data, loading }) => { - if (data) { - this.form = data.form; - this.loading = loading; - } + this.getFormQuery.subscribe({ + next: ({ data, loading }) => { + if (data) { + this.form = data.form; + this.loading = loading; + } + }, + error: () => { + this.loading = false; + }, }); } diff --git a/libs/shared/src/lib/components/access/edit-access/edit-access.component.ts b/libs/shared/src/lib/components/access/edit-access/edit-access.component.ts index 16d39d14be..103fd11e3d 100644 --- a/libs/shared/src/lib/components/access/edit-access/edit-access.component.ts +++ b/libs/shared/src/lib/components/access/edit-access/edit-access.component.ts @@ -86,8 +86,10 @@ export class EditAccessComponent }, }) .pipe(takeUntil(this.destroy$)) - .subscribe(({ data }) => { - this.roles = data.roles; + .subscribe({ + next: ({ data }) => { + this.roles = data.roles; + }, }); if (!this.useModal) { diff --git a/libs/shared/src/lib/components/aggregation/add-aggregation-modal/add-aggregation-modal.component.ts b/libs/shared/src/lib/components/aggregation/add-aggregation-modal/add-aggregation-modal.component.ts index 5c457fed78..8a371434c3 100644 --- a/libs/shared/src/lib/components/aggregation/add-aggregation-modal/add-aggregation-modal.component.ts +++ b/libs/shared/src/lib/components/aggregation/add-aggregation-modal/add-aggregation-modal.component.ts @@ -150,12 +150,15 @@ export class AddAggregationModalComponent resource: this.resource?.id, referenceData: this.referenceData?.id, }) - .subscribe(({ data }) => { - if (data?.addAggregation) { - this.dialogRef.close(data.addAggregation as any); - } else { + .subscribe({ + next: ({ data }) => { + if (data?.addAggregation) { + this.dialogRef.close(data.addAggregation as any); + } + }, + error: () => { this.dialogRef.close(); - } + }, }); } }); diff --git a/libs/shared/src/lib/components/aggregation/aggregation-grid/aggregation-grid.component.ts b/libs/shared/src/lib/components/aggregation/aggregation-grid/aggregation-grid.component.ts index f282a295f2..8eb69f2142 100644 --- a/libs/shared/src/lib/components/aggregation/aggregation-grid/aggregation-grid.component.ts +++ b/libs/shared/src/lib/components/aggregation/aggregation-grid/aggregation-grid.component.ts @@ -287,7 +287,12 @@ export class AggregationGridComponent }) ) .pipe(takeUntil(merge(this.cancelRefresh$, this.destroy$))) - .subscribe((results) => this.updateValues(results.data, results.loading)); + .subscribe({ + next: (results) => this.updateValues(results.data, results.loading), + error: () => { + this.loading = false; + }, + }); } /** diff --git a/libs/shared/src/lib/components/aggregation/aggregation-table/aggregation-table.component.ts b/libs/shared/src/lib/components/aggregation/aggregation-table/aggregation-table.component.ts index 9812378d60..f207d8026d 100644 --- a/libs/shared/src/lib/components/aggregation/aggregation-table/aggregation-table.component.ts +++ b/libs/shared/src/lib/components/aggregation/aggregation-table/aggregation-table.component.ts @@ -137,14 +137,16 @@ export class AggregationTableComponent if (value) { this.aggregationService .editAggregation(aggregation, value, { resource: this.resource?.id }) - .subscribe(({ data }: any) => { - if (data.editAggregation) { - const layouts = [...this.allAggregations]; - const index = layouts.findIndex((x) => x.id === aggregation.id); - layouts[index] = data.editAggregation; - this.allAggregations = layouts; - this.setSelectedAggregations(this.selectedAggregations?.value); - } + .subscribe({ + next: ({ data }: any) => { + if (data.editAggregation) { + const layouts = [...this.allAggregations]; + const index = layouts.findIndex((x) => x.id === aggregation.id); + layouts[index] = data.editAggregation; + this.allAggregations = layouts; + this.setSelectedAggregations(this.selectedAggregations?.value); + } + }, }); } }); diff --git a/libs/shared/src/lib/components/controls/reference-data-select/reference-data-select.component.ts b/libs/shared/src/lib/components/controls/reference-data-select/reference-data-select.component.ts index d4055b4b0b..c336d7e429 100644 --- a/libs/shared/src/lib/components/controls/reference-data-select/reference-data-select.component.ts +++ b/libs/shared/src/lib/components/controls/reference-data-select/reference-data-select.component.ts @@ -102,9 +102,14 @@ export class ReferenceDataSelectComponent extends GraphQLSelectComponent { this.query.valueChanges .pipe(takeUntil(this.queryChange$), takeUntil(this.destroy$)) - .subscribe(({ data, loading }) => { - this.queryName = Object.keys(data)[0]; - this.updateValues(data, loading); + .subscribe({ + next: ({ data, loading }) => { + this.queryName = Object.keys(data)[0]; + this.updateValues(data, loading); + }, + error: () => { + this.loading = false; + }, }); } super.onOpenSelect(); diff --git a/libs/shared/src/lib/components/controls/resource-select/resource-select.component.ts b/libs/shared/src/lib/components/controls/resource-select/resource-select.component.ts index 4fb555a4d1..d8106d00f3 100644 --- a/libs/shared/src/lib/components/controls/resource-select/resource-select.component.ts +++ b/libs/shared/src/lib/components/controls/resource-select/resource-select.component.ts @@ -102,9 +102,14 @@ export class ResourceSelectComponent extends GraphQLSelectComponent { this.query.valueChanges .pipe(takeUntil(this.queryChange$), takeUntil(this.destroy$)) - .subscribe(({ data, loading }) => { - this.queryName = Object.keys(data)[0]; - this.updateValues(data, loading); + .subscribe({ + next: ({ data, loading }) => { + this.queryName = Object.keys(data)[0]; + this.updateValues(data, loading); + }, + error: () => { + this.loading = false; + }, }); } super.onOpenSelect(); diff --git a/libs/shared/src/lib/components/convert-modal/convert-modal.component.ts b/libs/shared/src/lib/components/convert-modal/convert-modal.component.ts index 613cf179e1..d44c991c2b 100644 --- a/libs/shared/src/lib/components/convert-modal/convert-modal.component.ts +++ b/libs/shared/src/lib/components/convert-modal/convert-modal.component.ts @@ -100,13 +100,18 @@ export class ConvertModalComponent }, }) .pipe(takeUntil(this.destroy$)) - .subscribe(({ data }) => { - const record = data.record; - this.form = record.form; - this.loading = false; - this.availableForms = - this.form?.resource?.forms?.filter((x) => x.id !== this.form?.id) || - []; + .subscribe({ + next: ({ data }) => { + const record = data.record; + this.form = record.form; + this.loading = false; + this.availableForms = + this.form?.resource?.forms?.filter((x) => x.id !== this.form?.id) || + []; + }, + error: () => { + this.loading = false; + }, }); this.convertForm .get('targetForm') diff --git a/libs/shared/src/lib/components/custom-widget-style/custom-widget-style.component.ts b/libs/shared/src/lib/components/custom-widget-style/custom-widget-style.component.ts index 2db81546c7..bdc6eff0d8 100644 --- a/libs/shared/src/lib/components/custom-widget-style/custom-widget-style.component.ts +++ b/libs/shared/src/lib/components/custom-widget-style/custom-widget-style.component.ts @@ -107,13 +107,22 @@ export class CustomWidgetStyleComponent this.restService .post('style/scss-to-css', { scss }, { responseType: 'text' }) .pipe(takeUntil(this.destroy$)) - .subscribe((css) => { - set(this.widgetComp, 'widget.settings.widgetDisplay.style', value); - this.styleApplied.innerText = css; - this.document - .getElementsByTagName('head')[0] - .appendChild(this.styleApplied); - this.loading = false; + .subscribe({ + next: (css) => { + set( + this.widgetComp, + 'widget.settings.widgetDisplay.style', + value + ); + this.styleApplied.innerText = css; + this.document + .getElementsByTagName('head')[0] + .appendChild(this.styleApplied); + this.loading = false; + }, + error: () => { + this.loading = false; + }, }); }); } diff --git a/libs/shared/src/lib/components/distribution-lists/distribution-lists.component.ts b/libs/shared/src/lib/components/distribution-lists/distribution-lists.component.ts index c59d09ba40..3178507b1a 100644 --- a/libs/shared/src/lib/components/distribution-lists/distribution-lists.component.ts +++ b/libs/shared/src/lib/components/distribution-lists/distribution-lists.component.ts @@ -4,7 +4,6 @@ import { ApplicationService } from '../../services/application/application.servi import { Dialog } from '@angular/cdk/dialog'; import { takeUntil } from 'rxjs'; import { UnsubscribeComponent } from '../utils/unsubscribe/unsubscribe.component'; -import { SnackbarService } from '@oort-front/ui'; import { DistributionList } from '../../models/distribution-list.model'; /** @@ -36,13 +35,8 @@ export class DistributionListsComponent * * @param dialog The Dialog service * @param translate The translation service - * @param snackBar Shared snackbar service */ - constructor( - public dialog: Dialog, - private translate: TranslateService, - private snackBar: SnackbarService - ) { + constructor(public dialog: Dialog, private translate: TranslateService) { super(); } @@ -78,12 +72,6 @@ export class DistributionListsComponent name: value.name, emails: value.emails, }); - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectUpdated', { - value: value.name, - type: this.translate.instant('common.distributionList.one'), - }) - ); } }); } @@ -105,12 +93,6 @@ export class DistributionListsComponent name: value.name, emails: value.emails, }); - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectCreated', { - value: value.name, - type: this.translate.instant('common.distributionList.one'), - }) - ); } }); } @@ -147,11 +129,6 @@ export class DistributionListsComponent this.applicationService.deleteDistributionList( distributionList.id || '' ); - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectDeleted', { - value: distributionList.name, - }) - ); } }); } diff --git a/libs/shared/src/lib/components/draft-record-list-modal/draft-record-list-modal.component.ts b/libs/shared/src/lib/components/draft-record-list-modal/draft-record-list-modal.component.ts index 2a010d99cb..8a59138436 100644 --- a/libs/shared/src/lib/components/draft-record-list-modal/draft-record-list-modal.component.ts +++ b/libs/shared/src/lib/components/draft-record-list-modal/draft-record-list-modal.component.ts @@ -101,10 +101,15 @@ export class DraftRecordListModalComponent implements OnInit { }, }) .pipe() - .subscribe(({ data }) => { - this.form = data.form; - this.draftRecords = data.draftRecords; - this.loading = false; + .subscribe({ + next: ({ data }) => { + this.form = data.form; + this.draftRecords = data.draftRecords; + this.loading = false; + }, + error: () => { + this.loading = false; + }, }); } diff --git a/libs/shared/src/lib/components/form/form.component.ts b/libs/shared/src/lib/components/form/form.component.ts index 0ceb080893..5eda6cffa9 100644 --- a/libs/shared/src/lib/components/form/form.component.ts +++ b/libs/shared/src/lib/components/form/form.component.ts @@ -296,15 +296,8 @@ export class FormComponent }, }); } - mutation.subscribe(({ errors, data }: any) => { - if (errors) { - this.save.emit({ completed: false }); - this.survey.clear(false, true); - this.surveyActive = true; - this.snackBar.openSnackBar(errorMessageFormatter(errors), { - error: true, - }); - } else { + mutation.subscribe({ + next: ({ data }: any) => { if (this.lastDraftRecord) { const callback = () => { this.lastDraftRecord = undefined; @@ -331,7 +324,15 @@ export class FormComponent completed: true, hideNewRecord: data.addRecord && data.addRecord.form.uniqueRecord, }); - } + }, + error: (errors: any) => { + this.save.emit({ completed: false }); + this.survey.clear(false, true); + this.surveyActive = true; + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); + }, }); }; diff --git a/libs/shared/src/lib/components/grid-layout/add-layout-modal/add-layout-modal.component.ts b/libs/shared/src/lib/components/grid-layout/add-layout-modal/add-layout-modal.component.ts index 7323cc7a14..0d9ff24266 100644 --- a/libs/shared/src/lib/components/grid-layout/add-layout-modal/add-layout-modal.component.ts +++ b/libs/shared/src/lib/components/grid-layout/add-layout-modal/add-layout-modal.component.ts @@ -153,12 +153,15 @@ export class AddLayoutModalComponent if (layout) { this.gridLayoutService .addLayout(layout, this.resource?.id, this.form?.id) - .subscribe(({ data }) => { - if (data?.addLayout) { - this.dialogRef.close(data.addLayout as any); - } else { + .subscribe({ + next: ({ data }) => { + if (data?.addLayout) { + this.dialogRef.close(data.addLayout as any); + } + }, + error: () => { this.dialogRef.close(); - } + }, }); } }); diff --git a/libs/shared/src/lib/components/grid-layout/layout-table/layout-table.component.ts b/libs/shared/src/lib/components/grid-layout/layout-table/layout-table.component.ts index 19e075d4f2..fd625ec3e0 100644 --- a/libs/shared/src/lib/components/grid-layout/layout-table/layout-table.component.ts +++ b/libs/shared/src/lib/components/grid-layout/layout-table/layout-table.component.ts @@ -155,14 +155,16 @@ export class LayoutTableComponent if (value) { this.gridLayoutService .editLayout(layout, value, this.resource?.id, this.form?.id) - .subscribe(({ data }: any) => { - if (data.editLayout) { - const layouts = [...this.allLayouts]; - const index = layouts.findIndex((x) => x.id === layout.id); - layouts[index] = data.editLayout; - this.allLayouts = layouts; - this.setSelectedLayouts(this.selectedLayouts?.value); - } + .subscribe({ + next: ({ data }: any) => { + if (data.editLayout) { + const layouts = [...this.allLayouts]; + const index = layouts.findIndex((x) => x.id === layout.id); + layouts[index] = data.editLayout; + this.allLayouts = layouts; + this.setSelectedLayouts(this.selectedLayouts?.value); + } + }, }); } }); diff --git a/libs/shared/src/lib/components/notifications/components/edit-notification-modal/edit-notification-modal.component.ts b/libs/shared/src/lib/components/notifications/components/edit-notification-modal/edit-notification-modal.component.ts index 47095225b9..64ca48e584 100644 --- a/libs/shared/src/lib/components/notifications/components/edit-notification-modal/edit-notification-modal.component.ts +++ b/libs/shared/src/lib/components/notifications/components/edit-notification-modal/edit-notification-modal.component.ts @@ -223,11 +223,13 @@ export class EditNotificationModalComponent layoutIds: layoutId ? [layoutId] : null, }, }) - .subscribe((res) => { - this.resource = res.data.resource; - if (layoutId && this.resource.layouts?.edges[0]) { - this.layout = this.resource.layouts.edges[0].node; - } + .subscribe({ + next: (res) => { + this.resource = res.data.resource; + if (layoutId && this.resource.layouts?.edges[0]) { + this.layout = this.resource.layouts.edges[0].node; + } + }, }); } @@ -272,8 +274,10 @@ export class EditNotificationModalComponent if (value && this.layout) { this.gridLayoutService .editLayout(this.layout, value, this.resource?.id) - .subscribe((res: any) => { - this.layout = res.data?.editLayout; + .subscribe({ + next: (res: any) => { + this.layout = res.data?.editLayout; + }, }); } }); diff --git a/libs/shared/src/lib/components/notifications/notifications.component.ts b/libs/shared/src/lib/components/notifications/notifications.component.ts index 0d4cee1e14..8ff27d335a 100644 --- a/libs/shared/src/lib/components/notifications/notifications.component.ts +++ b/libs/shared/src/lib/components/notifications/notifications.component.ts @@ -1,7 +1,7 @@ import { Dialog } from '@angular/cdk/dialog'; import { Component, OnDestroy, OnInit } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; -import { SnackbarService, UIPageChangeEvent } from '@oort-front/ui'; +import { UIPageChangeEvent } from '@oort-front/ui'; import { Apollo, QueryRef } from 'apollo-angular'; import { Subscription, takeUntil } from 'rxjs'; import { @@ -64,15 +64,13 @@ export class NotificationsComponent * @param confirmService Shared confirmation service * @param apollo Apollo service * @param applicationService Shared application service - * @param snackBar Shared snackbar service */ constructor( public dialog: Dialog, private translate: TranslateService, private confirmService: ConfirmService, private apollo: Apollo, - private applicationService: ApplicationService, - private snackBar: SnackbarService + private applicationService: ApplicationService ) { super(); } @@ -92,21 +90,27 @@ export class NotificationsComponent }, } ); - this.notificationsQuery.valueChanges.subscribe((res) => { - this.cachedNotifications = - res.data.application.customNotifications.edges.map( - (x) => x.node + this.notificationsQuery.valueChanges.subscribe({ + next: (res) => { + this.cachedNotifications = + res.data.application.customNotifications.edges.map( + (x) => x.node + ); + this.notifications = this.cachedNotifications.slice( + this.pageInfo.pageSize * this.pageInfo.pageIndex, + this.pageInfo.pageSize * (this.pageInfo.pageIndex + 1) ); - this.notifications = this.cachedNotifications.slice( - this.pageInfo.pageSize * this.pageInfo.pageIndex, - this.pageInfo.pageSize * (this.pageInfo.pageIndex + 1) - ); - this.pageInfo.length = - res.data.application.customNotifications.totalCount; - this.pageInfo.endCursor = - res.data.application.customNotifications.pageInfo.endCursor; - this.loading = res.loading; - this.updating = false; + this.pageInfo.length = + res.data.application.customNotifications.totalCount; + this.pageInfo.endCursor = + res.data.application.customNotifications.pageInfo.endCursor; + this.loading = res.loading; + this.updating = false; + }, + error: () => { + this.loading = false; + this.updating = false; + }, }); } } @@ -146,12 +150,6 @@ export class NotificationsComponent this.notificationsQuery.refetch(); } ); - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectUpdated', { - value: value.name, - type: this.translate.instant('common.customNotification.one'), - }) - ); } }); } @@ -182,11 +180,6 @@ export class NotificationsComponent this.notificationsQuery.refetch(); } ); - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectDeleted', { - value: notification.name, - }) - ); } }); } @@ -205,12 +198,6 @@ export class NotificationsComponent this.applicationService.addCustomNotification(value, () => { this.notificationsQuery.refetch(); }); - this.snackBar.openSnackBar( - this.translate.instant('common.notifications.objectCreated', { - value: value.name, - type: this.translate.instant('common.customNotification.one'), - }) - ); } }); } diff --git a/libs/shared/src/lib/components/query-builder/query-builder.component.ts b/libs/shared/src/lib/components/query-builder/query-builder.component.ts index fab36d5034..407277ccda 100644 --- a/libs/shared/src/lib/components/query-builder/query-builder.component.ts +++ b/libs/shared/src/lib/components/query-builder/query-builder.component.ts @@ -119,27 +119,29 @@ export class QueryBuilderComponent } } else { this.availableQueries = this.queryBuilder.availableQueries$; - this.availableQueries.subscribe((res) => { - if (res && res.length > 0) { - if (this.queryName) { - this.allQueries = res - .filter((x) => x.name === this.queryName) - .map((x) => x.name); - if (this.allQueries.length === 1) { - this.form?.get('name')?.setValue(this.allQueries[0]); + this.availableQueries.subscribe({ + next: (res) => { + if (res && res.length > 0) { + if (this.queryName) { + this.allQueries = res + .filter((x) => x.name === this.queryName) + .map((x) => x.name); + if (this.allQueries.length === 1) { + this.form?.get('name')?.setValue(this.allQueries[0]); + } + } else { + this.allQueries = res.filter((x) => x.name).map((x) => x.name); } - } else { - this.allQueries = res.filter((x) => x.name).map((x) => x.name); + this.filteredQueries = this.filterQueries(this.form?.value.name); + this.availableFields = this.queryBuilder.getFields( + this.form?.value.name + ); + this.form?.setControl( + 'filter', + createFilterGroup(this.form?.value.filter) + ); } - this.filteredQueries = this.filterQueries(this.form?.value.name); - this.availableFields = this.queryBuilder.getFields( - this.form?.value.name - ); - this.form?.setControl( - 'filter', - createFilterGroup(this.form?.value.filter) - ); - } + }, }); const setFormBuilderControls = ( fieldControlRequired: boolean = false diff --git a/libs/shared/src/lib/components/record-dropdown/record-dropdown.component.ts b/libs/shared/src/lib/components/record-dropdown/record-dropdown.component.ts index 8a9e411cd2..048c2e49c6 100644 --- a/libs/shared/src/lib/components/record-dropdown/record-dropdown.component.ts +++ b/libs/shared/src/lib/components/record-dropdown/record-dropdown.component.ts @@ -97,10 +97,12 @@ export class RecordDropdownComponent }, }) .pipe(takeUntil(this.destroy$)) - .subscribe(({ data }) => { - if (data.record) { - this.selectedRecord = data.record; - } + .subscribe({ + next: ({ data }) => { + if (data.record) { + this.selectedRecord = data.record; + } + }, }); } @@ -118,11 +120,14 @@ export class RecordDropdownComponent }); this.records$ = this.records.asObservable(); - this.recordsQuery.valueChanges - .pipe(takeUntil(this.destroy$)) - .subscribe(({ data, loading }) => { + this.recordsQuery.valueChanges.pipe(takeUntil(this.destroy$)).subscribe({ + next: ({ data, loading }) => { this.updateValues(data, loading); - }); + }, + error: () => { + this.loading = false; + }, + }); } } diff --git a/libs/shared/src/lib/components/record-history/record-history.component.ts b/libs/shared/src/lib/components/record-history/record-history.component.ts index 2b19b77fe3..faf0f0ce6d 100644 --- a/libs/shared/src/lib/components/record-history/record-history.component.ts +++ b/libs/shared/src/lib/components/record-history/record-history.component.ts @@ -169,9 +169,11 @@ export class RecordHistoryComponent }, }) .pipe(takeUntil(this.destroy$)) - .subscribe(({ data }) => { - this.record = data.record; - this.sortedFields = this.sortFields(this.getFields()); + .subscribe({ + next: ({ data }) => { + this.record = data.record; + this.sortedFields = this.sortFields(this.getFields()); + }, }); this.apollo diff --git a/libs/shared/src/lib/components/role-summary/role-auto-assignment/role-auto-assignment.component.ts b/libs/shared/src/lib/components/role-summary/role-auto-assignment/role-auto-assignment.component.ts index 801defe28c..92e6fbc8ba 100644 --- a/libs/shared/src/lib/components/role-summary/role-auto-assignment/role-auto-assignment.component.ts +++ b/libs/shared/src/lib/components/role-summary/role-auto-assignment/role-auto-assignment.component.ts @@ -85,39 +85,43 @@ export class RoleAutoAssignmentComponent .query({ query: GET_GROUPS, }) - .subscribe(({ data }) => { - if (data.groups) { - this.groups = data.groups; - this.fields.push({ - text: 'User Groups', - name: '{{groups}}', - editor: 'select', - multiSelect: true, - options: this.groups.map((group) => ({ - text: group.title, - value: group.id, - })), - filter: { - operators: ['eq', 'contains'], - }, - }); - } + .subscribe({ + next: ({ data }) => { + if (data.groups) { + this.groups = data.groups; + this.fields.push({ + text: 'User Groups', + name: '{{groups}}', + editor: 'select', + multiSelect: true, + options: this.groups.map((group) => ({ + text: group.title, + value: group.id, + })), + filter: { + operators: ['eq', 'contains'], + }, + }); + } + }, }); const url = '/permissions/attributes'; - this.restService.get(url).subscribe((res: any) => { - if (isArray(res)) { - res.forEach((attr: { value: string; text: string }) => { - this.fields.push({ - text: attr.text, - name: `{{attributes.${attr.value}}}`, - filter: { - operators: ['eq'], - }, - editor: 'text', + this.restService.get(url).subscribe({ + next: (res: any) => { + if (isArray(res)) { + res.forEach((attr: { value: string; text: string }) => { + this.fields.push({ + text: attr.text, + name: `{{attributes.${attr.value}}}`, + filter: { + operators: ['eq'], + }, + editor: 'text', + }); }); - }); - } + } + }, }); } diff --git a/libs/shared/src/lib/components/role-summary/role-channels/role-channels.component.ts b/libs/shared/src/lib/components/role-summary/role-channels/role-channels.component.ts index 69abee4ea8..b24686a609 100644 --- a/libs/shared/src/lib/components/role-summary/role-channels/role-channels.component.ts +++ b/libs/shared/src/lib/components/role-summary/role-channels/role-channels.component.ts @@ -65,20 +65,22 @@ export class RoleChannelsComponent }, }) .pipe(takeUntil(this.destroy$)) - .subscribe(({ data }) => { - this.channels = data.channels; - // Move channels in an array under corresponding applications. - this.applications = Array.from( - new Set(this.channels.map((x) => x.application?.name)) - ).map((name) => ({ - name: name ? name : 'Global', - channels: this.channels.reduce((o: Channel[], channel: Channel) => { - if (channel?.application?.name === name) { - o.push(channel); - } - return o; - }, []), - })); + .subscribe({ + next: ({ data }) => { + this.channels = data.channels; + // Move channels in an array under corresponding applications. + this.applications = Array.from( + new Set(this.channels.map((x) => x.application?.name)) + ).map((name) => ({ + name: name ? name : 'Global', + channels: this.channels.reduce((o: Channel[], channel: Channel) => { + if (channel?.application?.name === name) { + o.push(channel); + } + return o; + }, []), + })); + }, }); } diff --git a/libs/shared/src/lib/components/role-summary/role-details/role-details.component.ts b/libs/shared/src/lib/components/role-summary/role-details/role-details.component.ts index 3cdd97fde3..0f3228e27d 100644 --- a/libs/shared/src/lib/components/role-summary/role-details/role-details.component.ts +++ b/libs/shared/src/lib/components/role-summary/role-details/role-details.component.ts @@ -78,12 +78,16 @@ export class RoleDetailsComponent implements OnInit { application: this.role.application !== null, }, }) - .subscribe(({ data }) => { - this.permissions = data.permissions; + .subscribe({ + next: ({ data }) => { + this.permissions = data.permissions; + }, }); const url = `/roles/${this.role.id}/summary`; - this.restService.get(url).subscribe((res: any) => { - this.roleStats = res; + this.restService.get(url).subscribe({ + next: (res: any) => { + this.roleStats = res; + }, }); } diff --git a/libs/shared/src/lib/components/role-summary/role-features/role-features.component.ts b/libs/shared/src/lib/components/role-summary/role-features/role-features.component.ts index 7c9786f873..5283be7707 100644 --- a/libs/shared/src/lib/components/role-summary/role-features/role-features.component.ts +++ b/libs/shared/src/lib/components/role-summary/role-features/role-features.component.ts @@ -14,6 +14,7 @@ import { Role } from '../../../models/user.model'; import { EDIT_PAGE_ACCESS } from '../graphql/mutations'; import { GET_APPLICATION_FEATURES } from '../graphql/queries'; import { SnackbarService } from '@oort-front/ui'; +import { errorMessageFormatter } from '../../../utils/public-api'; /** * Features tab of Role Summary component. @@ -73,8 +74,10 @@ export class RoleFeaturesComponent implements OnInit { ); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); }, }); } @@ -135,9 +138,11 @@ export class RoleFeaturesComponent implements OnInit { } this.loading = loading; }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { this.loading = false; + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); }, }); } diff --git a/libs/shared/src/lib/components/role-summary/role-features/role-workflows/role-workflows.component.ts b/libs/shared/src/lib/components/role-summary/role-features/role-workflows/role-workflows.component.ts index 41f903be6e..9effd171df 100644 --- a/libs/shared/src/lib/components/role-summary/role-features/role-workflows/role-workflows.component.ts +++ b/libs/shared/src/lib/components/role-summary/role-features/role-workflows/role-workflows.component.ts @@ -22,6 +22,7 @@ import { EditStepMutationResponse, Step } from '../../../../models/step.model'; import { WorkflowQueryResponse } from '../../../../models/workflow.model'; import { EDIT_STEP_ACCESS } from '../../graphql/mutations'; import { SnackbarService } from '@oort-front/ui'; +import { errorMessageFormatter } from '../../../../utils/graphql/error-handler'; /** Component for the workflows section of the roles features */ @Component({ @@ -141,8 +142,10 @@ export class RoleWorkflowsComponent implements OnInit, OnChanges { ); } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); }, }); } @@ -183,9 +186,11 @@ export class RoleWorkflowsComponent implements OnInit, OnChanges { } this.loading = loading; }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { this.loading = false; + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); }, }); } diff --git a/libs/shared/src/lib/components/role-summary/role-resources/role-resources.component.ts b/libs/shared/src/lib/components/role-summary/role-resources/role-resources.component.ts index 76b4ae76a3..34e50edbdb 100644 --- a/libs/shared/src/lib/components/role-summary/role-resources/role-resources.component.ts +++ b/libs/shared/src/lib/components/role-summary/role-resources/role-resources.component.ts @@ -125,11 +125,15 @@ export class RoleResourcesComponent }, }); - this.resourcesQuery.valueChanges - .pipe(takeUntil(this.destroy$)) - .subscribe(({ data, loading }) => { + this.resourcesQuery.valueChanges.pipe(takeUntil(this.destroy$)).subscribe({ + next: ({ data, loading }) => { this.updateValues(data, loading); - }); + }, + error: () => { + this.loading = false; + this.updating = false; + }, + }); } /** @@ -232,11 +236,16 @@ export class RoleResourcesComponent }, }) .pipe(takeUntil(this.destroy$)) - .subscribe(({ data }) => { - if (data.resource) { - this.openedResource = data.resource; - } - this.updating = false; + .subscribe({ + next: ({ data }) => { + if (data.resource) { + this.openedResource = data.resource; + } + this.updating = false; + }, + error: () => { + this.updating = false; + }, }); } } @@ -311,12 +320,12 @@ export class RoleResourcesComponent this.updating = false; }, error: (errors) => { + this.updating = false; this.handleResourceMutationResponse( resource, { data: null, errors }, true ); - this.updating = false; }, }); } diff --git a/libs/shared/src/lib/components/role-summary/role-summary.component.ts b/libs/shared/src/lib/components/role-summary/role-summary.component.ts index d072a09aaf..f63d37e146 100644 --- a/libs/shared/src/lib/components/role-summary/role-summary.component.ts +++ b/libs/shared/src/lib/components/role-summary/role-summary.component.ts @@ -51,15 +51,20 @@ export class RoleSummaryComponent implements OnInit { id: this.id, }, }) - .subscribe(({ data, loading }) => { - if (data) { - this.role = data.role; - this.breadcrumbService.setBreadcrumb( - '@role', - this.role.title as string - ); - } - this.loading = loading; + .subscribe({ + next: ({ data, loading }) => { + if (data) { + this.role = data.role; + this.breadcrumbService.setBreadcrumb( + '@role', + this.role.title as string + ); + } + this.loading = loading; + }, + error: () => { + this.loading = false; + }, }); } @@ -76,11 +81,16 @@ export class RoleSummaryComponent implements OnInit { mutation: EDIT_ROLE, variables: { ...e, id: this.id }, }) - .subscribe(({ data, loading }) => { - if (data) { - this.role = data.editRole; - this.loading = loading; - } + .subscribe({ + next: ({ data, loading }) => { + if (data) { + this.role = data.editRole; + this.loading = loading; + } + }, + error: () => { + this.loading = false; + }, }); } } diff --git a/libs/shared/src/lib/components/role-summary/role-users/role-users.component.ts b/libs/shared/src/lib/components/role-summary/role-users/role-users.component.ts index 0ba2e846c5..254519ef00 100644 --- a/libs/shared/src/lib/components/role-summary/role-users/role-users.component.ts +++ b/libs/shared/src/lib/components/role-summary/role-users/role-users.component.ts @@ -73,11 +73,15 @@ export class RoleUsersComponent extends UnsubscribeComponent implements OnInit { automated: this.autoAssigned, }, }); - this.usersQuery.valueChanges - .pipe(takeUntil(this.destroy$)) - .subscribe(({ data, loading }) => { + this.usersQuery.valueChanges.pipe(takeUntil(this.destroy$)).subscribe({ + next: ({ data, loading }) => { this.updateValues(data, loading); - }); + }, + error: () => { + this.loading = false; + this.updating = false; + }, + }); } /** diff --git a/libs/shared/src/lib/components/roles/components/group-list/group-list.component.ts b/libs/shared/src/lib/components/roles/components/group-list/group-list.component.ts index 2eef2e216d..86ce55d749 100644 --- a/libs/shared/src/lib/components/roles/components/group-list/group-list.component.ts +++ b/libs/shared/src/lib/components/roles/components/group-list/group-list.component.ts @@ -107,11 +107,16 @@ export class GroupListComponent query: GET_GROUPS, }) .pipe(takeUntil(this.destroy$)) - .subscribe(({ data, loading }) => { - this.groups = data.groups; - this.filteredGroups = this.groups; - // this.manualCreation = data.groups.manualCreation; - this.loading = loading; + .subscribe({ + next: ({ data, loading }) => { + this.groups = data.groups; + this.filteredGroups = this.groups; + // this.manualCreation = data.groups.manualCreation; + this.loading = loading; + }, + error: () => { + this.loading = false; + }, }); } @@ -123,8 +128,10 @@ export class GroupListComponent this.restService .get(url) .pipe(takeUntil(this.destroy$)) - .subscribe((res) => { - this.manualCreation = get(res, 'groups.local', true); + .subscribe({ + next: (res) => { + this.manualCreation = get(res, 'groups.local', true); + }, }); } @@ -164,7 +171,7 @@ export class GroupListComponent next: () => { this.snackBar.openSnackBar( this.translate.instant('common.notifications.objectCreated', { - type: this.translate.instant('common.role.one'), + type: this.translate.instant('common.group.one'), value: value.title, }) ); @@ -176,7 +183,7 @@ export class GroupListComponent 'common.notifications.objectNotCreated', { type: this.translate - .instant('common.role.one') + .instant('common.group.one') .toLowerCase(), error: errorMessageFormatter(errors), } diff --git a/libs/shared/src/lib/components/roles/components/role-list/role-list.component.ts b/libs/shared/src/lib/components/roles/components/role-list/role-list.component.ts index 2edd971a2d..ffadcf3325 100644 --- a/libs/shared/src/lib/components/roles/components/role-list/role-list.component.ts +++ b/libs/shared/src/lib/components/roles/components/role-list/role-list.component.ts @@ -128,10 +128,15 @@ export class RoleListComponent extends UnsubscribeComponent implements OnInit { query: GET_ROLES, }) .pipe(takeUntil(this.destroy$)) - .subscribe(({ data, loading }) => { - this.roles = data.roles; - this.loading = loading; - this.filterPredicate(); + .subscribe({ + next: ({ data, loading }) => { + this.roles = data.roles; + this.loading = loading; + this.filterPredicate(); + }, + error: () => { + this.loading = false; + }, }); } diff --git a/libs/shared/src/lib/components/ui/aggregation-builder/aggregation-builder.component.ts b/libs/shared/src/lib/components/ui/aggregation-builder/aggregation-builder.component.ts index 463a5acb08..2d421f4904 100644 --- a/libs/shared/src/lib/components/ui/aggregation-builder/aggregation-builder.component.ts +++ b/libs/shared/src/lib/components/ui/aggregation-builder/aggregation-builder.component.ts @@ -106,10 +106,12 @@ export class AggregationBuilderComponent // Fixes issue where sometimes we try to load the fields before the queries are loaded this.queryBuilder.availableQueries$ .pipe(takeUntil(this.destroy$)) - .subscribe((queryList) => { - if (queryList.length > 0) { - this.initFields(); - } + .subscribe({ + next: (queryList) => { + if (queryList.length > 0) { + this.initFields(); + } + }, }); this.stageList = this.referenceData @@ -309,15 +311,15 @@ export class AggregationBuilderComponent pipeline: this.aggregationForm.value.pipeline, first: -1, }); - - const { data: aggregationData, errors } = await firstValueFrom(query$); - if (!aggregationData || errors) { + let aggregationData!: any; + try { + const { data } = await firstValueFrom(query$); + aggregationData = data; + } catch (errors) { this.loadingAggregationRecords = false; - if (errors?.length) { - this.snackBar.openSnackBar(errorMessageFormatter(errors), { - error: true, - }); - } + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); return; } this.loadingAggregationRecords = false; diff --git a/libs/shared/src/lib/components/ui/core-grid/core-grid.component.ts b/libs/shared/src/lib/components/ui/core-grid/core-grid.component.ts index 775363d4f0..96baaed88a 100644 --- a/libs/shared/src/lib/components/ui/core-grid/core-grid.component.ts +++ b/libs/shared/src/lib/components/ui/core-grid/core-grid.component.ts @@ -55,6 +55,7 @@ import { ConfirmService } from '../../../services/confirm/confirm.service'; import { ContextService } from '../../../services/context/context.service'; import { ResourceQueryResponse } from '../../../models/resource.model'; import { Router } from '@angular/router'; +import { errorMessageFormatter } from '../../../utils/public-api'; /** * Default file name when exporting grid data. @@ -508,17 +509,14 @@ export class CoreGridComponent } this.getRecords(); }, - error: (err: any) => { + error: (errors: any) => { this.loading = false; this.status = { error: true, message: this.translate.instant( 'components.widget.grid.errors.metaQueryFetchFailed', { - error: - err.networkError?.error?.errors - ?.map((x: any) => x.message) - .join(', ') || err, + error: errorMessageFormatter(errors), } ), }; @@ -592,61 +590,67 @@ export class CoreGridComponent }, }) .pipe(takeUntil(this.destroy$)) - .subscribe(({ data }) => { - if (data?.editRecord.data) { - const editedData = data.editRecord.data; - this.apollo - .query({ - query: GET_RESOURCE_QUERY_NAME, - variables: { - id: this.settings.resource, - }, - }) - .pipe(takeUntil(this.destroy$)) - .subscribe(({ data }) => { - const queryName = data.resource.singleQueryName; - if (queryName) { - const query = this.queryBuilder.buildQuery( - { - query: { - ...this.settings.query, - name: queryName, - }, - }, - true - ); - if (query) { - this.apollo - .query({ - query, - variables: { - id: item.id, - data: editedData, + .subscribe({ + next: ({ data }) => { + if (data?.editRecord.data) { + const editedData = data.editRecord.data; + this.apollo + .query({ + query: GET_RESOURCE_QUERY_NAME, + variables: { + id: this.settings.resource, + }, + }) + .pipe(takeUntil(this.destroy$)) + .subscribe({ + next: ({ data }) => { + const queryName = data.resource.singleQueryName; + if (queryName) { + const query = this.queryBuilder.buildQuery( + { + query: { + ...this.settings.query, + name: queryName, + }, }, - }) - .pipe(takeUntil(this.destroy$)) - .subscribe(({ data }) => { - const dataItem = this.gridData.data.find( - (x) => x.id === item.id - ); - // Update data item element - Object.assign(dataItem, get(data, queryName)); - // Update data item raw value ( used by inline edition ) - dataItem._meta.raw = editedData; - item.saved = false; - const index = this.updatedItems.findIndex( - (x) => x.id === item.id - ); - this.updatedItems.splice(index, 1, { - id: item.id, - ...editedData, - }); - this.loadItems(); - }); - } - } - }); - } + true + ); + if (query) { + this.apollo + .query({ + query, + variables: { + id: item.id, + data: editedData, + }, + }) + .pipe(takeUntil(this.destroy$)) + .subscribe({ + next: ({ data }) => { + const dataItem = this.gridData.data.find( + (x) => x.id === item.id + ); + // Update data item element + Object.assign(dataItem, get(data, queryName)); + // Update data item raw value ( used by inline edition ) + dataItem._meta.raw = editedData; + item.saved = false; + const index = this.updatedItems.findIndex( + (x) => x.id === item.id + ); + this.updatedItems.splice(index, 1, { + id: item.id, + ...editedData, + }); + this.loadItems(); + }, + }); + } + } + }, + }); + } + }, }); } @@ -826,16 +830,13 @@ export class CoreGridComponent this.getTemporaryRecords(); } }, - error: (err: any) => { + error: (errors: any) => { this.status = { error: true, message: this.translate.instant( 'components.widget.grid.errors.queryFetchFailed', { - error: - err.networkError?.error?.errors - ?.map((x: any) => x.message) - .join(', ') || err, + error: errorMessageFormatter(errors), } ), }; @@ -1218,9 +1219,11 @@ export class CoreGridComponent }, }) .pipe(takeUntil(this.destroy$)) - .subscribe(() => { - this.reloadData(); - this.layoutService.setRightSidenav(null); + .subscribe({ + next: () => { + this.reloadData(); + this.layoutService.setRightSidenav(null); + }, }); } }); @@ -1469,7 +1472,12 @@ export class CoreGridComponent }) ) .pipe(takeUntil(merge(this.cancelRefresh$, this.destroy$))) - .subscribe(() => (this.loading = false)); + .subscribe({ + next: () => (this.loading = false), + error: () => { + this.loading = false; + }, + }); } // === FILTERING === diff --git a/libs/shared/src/lib/components/ui/map/map.component.ts b/libs/shared/src/lib/components/ui/map/map.component.ts index be382387c2..329720d5a0 100644 --- a/libs/shared/src/lib/components/ui/map/map.component.ts +++ b/libs/shared/src/lib/components/ui/map/map.component.ts @@ -1100,32 +1100,34 @@ export class MapComponent this.resetLayers(this.layers.filter((x) => x.shouldRefresh)); from(this.getLayers(layersToGet ?? [], false)) .pipe(takeUntil(merge(this.cancelRefresh$, this.destroy$))) - .subscribe((res) => { - this.overlaysTree = [res.layers]; - - flatMapDeep(this.overlaysTree.flat(), flattenOverlaysTree).forEach( - (x) => { - if (x.layer) { - const id = (x.layer as any).id; - if (!isNil(shouldDisplayStatuses[id])) { - (x.layer as any).shouldDisplay = shouldDisplayStatuses[id]; - if (shouldDisplayStatuses[id]) { + .subscribe({ + next: (res) => { + this.overlaysTree = [res.layers]; + + flatMapDeep(this.overlaysTree.flat(), flattenOverlaysTree).forEach( + (x) => { + if (x.layer) { + const id = (x.layer as any).id; + if (!isNil(shouldDisplayStatuses[id])) { + (x.layer as any).shouldDisplay = shouldDisplayStatuses[id]; + if (shouldDisplayStatuses[id]) { + this.map.addLayer(x.layer); + } + } else { this.map.addLayer(x.layer); } - } else { - this.map.addLayer(x.layer); } } - } - ); - - if (controls.layer) { - // update layer controls, from newly created layers - this.setLayersControl( - flatten(this.basemapTree), - flatten(this.overlaysTree) ); - } + + if (controls.layer) { + // update layer controls, from newly created layers + this.setLayersControl( + flatten(this.basemapTree), + flatten(this.overlaysTree) + ); + } + }, }); } diff --git a/libs/shared/src/lib/components/user-summary/user-details/user-details.component.ts b/libs/shared/src/lib/components/user-summary/user-details/user-details.component.ts index f9961700be..eeb477f9d7 100644 --- a/libs/shared/src/lib/components/user-summary/user-details/user-details.component.ts +++ b/libs/shared/src/lib/components/user-summary/user-details/user-details.component.ts @@ -76,33 +76,35 @@ export class UserDetailsComponent implements OnInit { * Get attributes from back-end, and set controls if any */ private getAttributes(): void { - this.restService.get('/permissions/configuration').subscribe((config) => { - // can user edit attributes - const manualCreation = get(config, 'attributes.local', true); - this.restService - .get('/permissions/attributes') - .subscribe((attributes: any) => { - this.form.addControl( - 'attributes', - this.fb.group( - attributes.reduce( - (group: any, attribute: any) => ({ - ...group, - [attribute.value]: this.fb.control({ - value: get( - this.user, - `attributes.${attribute.value}`, - null - ), - disabled: !manualCreation, + this.restService.get('/permissions/configuration').subscribe({ + next: (config) => { + // can user edit attributes + const manualCreation = get(config, 'attributes.local', true); + this.restService.get('/permissions/attributes').subscribe({ + next: (attributes: any) => { + this.form.addControl( + 'attributes', + this.fb.group( + attributes.reduce( + (group: any, attribute: any) => ({ + ...group, + [attribute.value]: this.fb.control({ + value: get( + this.user, + `attributes.${attribute.value}`, + null + ), + disabled: !manualCreation, + }), }), - }), - {} + {} + ) ) - ) - ); - this.attributes = attributes; + ); + this.attributes = attributes; + }, }); + }, }); } } diff --git a/libs/shared/src/lib/components/user-summary/user-roles/user-app-roles/user-app-roles.component.ts b/libs/shared/src/lib/components/user-summary/user-roles/user-app-roles/user-app-roles.component.ts index 6c0e9594f9..1ffafe6dc6 100644 --- a/libs/shared/src/lib/components/user-summary/user-roles/user-app-roles/user-app-roles.component.ts +++ b/libs/shared/src/lib/components/user-summary/user-roles/user-app-roles/user-app-roles.component.ts @@ -11,6 +11,7 @@ import { GET_APPLICATIONS, GET_ROLES } from '../../graphql/queries'; import { UnsubscribeComponent } from '../../../utils/unsubscribe/unsubscribe.component'; import { takeUntil } from 'rxjs/operators'; import { SnackbarService } from '@oort-front/ui'; +import { errorMessageFormatter } from '../../../../utils/public-api'; /** Roles tab for the user summary */ @Component({ @@ -102,8 +103,10 @@ export class UserAppRolesComponent this.applicationsQuery.valueChanges .pipe(takeUntil(this.destroy$)) .subscribe({ - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); }, }); } @@ -161,8 +164,10 @@ export class UserAppRolesComponent ); this.loading = loading; }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); this.loading = false; }, }); diff --git a/libs/shared/src/lib/components/user-summary/user-roles/user-back-roles/user-back-roles.component.ts b/libs/shared/src/lib/components/user-summary/user-roles/user-back-roles/user-back-roles.component.ts index 1413b6078f..45cb2d9f7d 100644 --- a/libs/shared/src/lib/components/user-summary/user-roles/user-back-roles/user-back-roles.component.ts +++ b/libs/shared/src/lib/components/user-summary/user-roles/user-back-roles/user-back-roles.component.ts @@ -5,6 +5,7 @@ import { get } from 'lodash'; import { Role, RolesQueryResponse, User } from '../../../../models/user.model'; import { GET_ROLES } from '../../graphql/queries'; import { SnackbarService } from '@oort-front/ui'; +import { errorMessageFormatter } from '../../../../utils/public-api'; /** Back-office roles section the user summary */ @Component({ @@ -62,8 +63,10 @@ export class UserBackRolesComponent implements OnInit { } this.loading = loading; }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); this.loading = false; }, }); diff --git a/libs/shared/src/lib/components/user-summary/user-roles/user-groups/user-groups.component.ts b/libs/shared/src/lib/components/user-summary/user-roles/user-groups/user-groups.component.ts index 60e23ad548..6cc8386421 100644 --- a/libs/shared/src/lib/components/user-summary/user-roles/user-groups/user-groups.component.ts +++ b/libs/shared/src/lib/components/user-summary/user-roles/user-groups/user-groups.component.ts @@ -9,6 +9,7 @@ import { } from '../../../../models/user.model'; import { GET_GROUPS } from '../../graphql/queries'; import { SnackbarService } from '@oort-front/ui'; +import { errorMessageFormatter } from '../../../../utils/public-api'; /** Back-office groups section the user summary */ @Component({ @@ -69,8 +70,10 @@ export class UserGroupsComponent implements OnInit { } this.loading = loading; }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); this.loading = false; }, }); diff --git a/libs/shared/src/lib/components/user-summary/user-summary.component.ts b/libs/shared/src/lib/components/user-summary/user-summary.component.ts index 9791bed679..119afbb09d 100644 --- a/libs/shared/src/lib/components/user-summary/user-summary.component.ts +++ b/libs/shared/src/lib/components/user-summary/user-summary.component.ts @@ -11,6 +11,7 @@ import { EDIT_USER_PROFILE, EDIT_USER_ROLES } from './graphql/mutations'; import { GET_USER } from './graphql/queries'; import { BreadcrumbService } from '../../services/breadcrumb/breadcrumb.service'; import { SnackbarService } from '@oort-front/ui'; +import { errorMessageFormatter } from '../../utils/graphql/error-handler'; /** * User Summary shared component. @@ -75,8 +76,10 @@ export class UserSummaryComponent implements OnInit { } this.loading = loading; }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); this.loading = false; }, }); @@ -104,8 +107,10 @@ export class UserSummaryComponent implements OnInit { this.loading = loading; } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); this.loading = false; }, }); @@ -142,8 +147,10 @@ export class UserSummaryComponent implements OnInit { this.loading = loading; } }, - error: (err) => { - this.snackBar.openSnackBar(err.message, { error: true }); + error: (errors) => { + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); this.loading = false; }, }); diff --git a/libs/shared/src/lib/components/widgets/chart-settings/tab-filters/tab-filters.component.ts b/libs/shared/src/lib/components/widgets/chart-settings/tab-filters/tab-filters.component.ts index 1baa91d13d..2243581a71 100644 --- a/libs/shared/src/lib/components/widgets/chart-settings/tab-filters/tab-filters.component.ts +++ b/libs/shared/src/lib/components/widgets/chart-settings/tab-filters/tab-filters.component.ts @@ -108,9 +108,11 @@ export class TabFiltersComponent implements OnInit { id: resourceID, }, }) - .subscribe((res) => { - this.resource = res.data.resource; - this.filterFields = this.resource?.metadata ?? []; + .subscribe({ + next: (res) => { + this.resource = res.data.resource; + this.filterFields = this.resource?.metadata ?? []; + }, }); } else if (referenceDataID) { this.apollo @@ -120,9 +122,11 @@ export class TabFiltersComponent implements OnInit { id: referenceDataID, }, }) - .subscribe((res) => { - this.referenceData = res.data.referenceData; - this.filterFields = getReferenceMetadata(this.referenceData); + .subscribe({ + next: (res) => { + this.referenceData = res.data.referenceData; + this.filterFields = getReferenceMetadata(this.referenceData); + }, }); } } diff --git a/libs/shared/src/lib/components/widgets/chart-settings/tab-main/tab-main.component.ts b/libs/shared/src/lib/components/widgets/chart-settings/tab-main/tab-main.component.ts index dcc8693908..d4f6fdb2f9 100644 --- a/libs/shared/src/lib/components/widgets/chart-settings/tab-main/tab-main.component.ts +++ b/libs/shared/src/lib/components/widgets/chart-settings/tab-main/tab-main.component.ts @@ -120,17 +120,22 @@ export class TabMainComponent extends UnsubscribeComponent implements OnInit { }, }) .pipe(takeUntil(this.destroy$)) - .subscribe(({ data }) => { - this.resource = data.resource; - if (aggregationId && this.resource.aggregations?.edges[0]) { - this.aggregation = this.resource.aggregations.edges[0].node; - this.availableSeriesFields = - this.aggregationBuilder.getAvailableSeriesFields(this.aggregation, { - resource: this.resource, - }); - } else { - this.availableSeriesFields = []; - } + .subscribe({ + next: ({ data }) => { + this.resource = data.resource; + if (aggregationId && this.resource.aggregations?.edges[0]) { + this.aggregation = this.resource.aggregations.edges[0].node; + this.availableSeriesFields = + this.aggregationBuilder.getAvailableSeriesFields( + this.aggregation, + { + resource: this.resource, + } + ); + } else { + this.availableSeriesFields = []; + } + }, }); } @@ -150,17 +155,22 @@ export class TabMainComponent extends UnsubscribeComponent implements OnInit { }, }) .pipe(takeUntil(this.destroy$)) - .subscribe(({ data }) => { - this.referenceData = data.referenceData; - if (aggregationId && this.referenceData.aggregations?.edges[0]) { - this.aggregation = this.referenceData.aggregations.edges[0].node; - this.availableSeriesFields = - this.aggregationBuilder.getAvailableSeriesFields(this.aggregation, { - referenceData: this.referenceData, - }); - } else { - this.availableSeriesFields = []; - } + .subscribe({ + next: ({ data }) => { + this.referenceData = data.referenceData; + if (aggregationId && this.referenceData.aggregations?.edges[0]) { + this.aggregation = this.referenceData.aggregations.edges[0].node; + this.availableSeriesFields = + this.aggregationBuilder.getAvailableSeriesFields( + this.aggregation, + { + referenceData: this.referenceData, + } + ); + } else { + this.availableSeriesFields = []; + } + }, }); } @@ -223,14 +233,16 @@ export class TabMainComponent extends UnsubscribeComponent implements OnInit { referenceData: this.referenceData?.id, }) .pipe(takeUntil(this.destroy$)) - .subscribe(({ data }) => { - if (data?.editAggregation) { - if (this.resource) { - this.getResource(this.resource?.id as string); - } else { - this.getReferenceData(this.referenceData?.id as string); + .subscribe({ + next: ({ data }) => { + if (data?.editAggregation) { + if (this.resource) { + this.getResource(this.resource?.id as string); + } else { + this.getReferenceData(this.referenceData?.id as string); + } } - } + }, }); } }); diff --git a/libs/shared/src/lib/components/widgets/chart/chart.component.ts b/libs/shared/src/lib/components/widgets/chart/chart.component.ts index 07ed7a8f9b..4bcbe052b9 100644 --- a/libs/shared/src/lib/components/widgets/chart/chart.component.ts +++ b/libs/shared/src/lib/components/widgets/chart/chart.component.ts @@ -343,12 +343,8 @@ export class ChartComponent private getData(): void { this.dataQuery .pipe(takeUntil(merge(this.cancelRefresh$, this.destroy$))) - .subscribe(({ errors, data, loading }: any) => { - if (errors) { - this.loading = false; - this.hasError = true; - this.series.next([]); - } else { + .subscribe({ + next: ({ data, loading }: any) => { this.hasError = false; const today = new Date(); this.lastUpdate = @@ -415,7 +411,12 @@ export class ChartComponent ); } this.loading = loading; - } + }, + error: () => { + this.loading = false; + this.hasError = true; + this.series.next([]); + }, }); } diff --git a/libs/shared/src/lib/components/widgets/common/template-aggregation-modal/template-aggregation-modal.component.ts b/libs/shared/src/lib/components/widgets/common/template-aggregation-modal/template-aggregation-modal.component.ts index 334f38c519..d6238434ef 100644 --- a/libs/shared/src/lib/components/widgets/common/template-aggregation-modal/template-aggregation-modal.component.ts +++ b/libs/shared/src/lib/components/widgets/common/template-aggregation-modal/template-aggregation-modal.component.ts @@ -164,12 +164,14 @@ export class TemplateAggregationModalComponent }, }) .pipe(takeUntil(this.destroy$)) - .subscribe(({ data }) => { - this.resource = data.resource; - if (aggregationId && this.resource.aggregations?.edges[0]) { - this.aggregation = this.resource.aggregations.edges[0].node; - this.form.controls.name.setValue(this.aggregation.name as string); - } + .subscribe({ + next: ({ data }) => { + this.resource = data.resource; + if (aggregationId && this.resource.aggregations?.edges[0]) { + this.aggregation = this.resource.aggregations.edges[0].node; + this.form.controls.name.setValue(this.aggregation.name as string); + } + }, }); } @@ -189,12 +191,14 @@ export class TemplateAggregationModalComponent }, }) .pipe(takeUntil(this.destroy$)) - .subscribe(({ data }) => { - this.referenceData = data.referenceData; - if (aggregationId && this.referenceData.aggregations?.edges[0]) { - this.aggregation = this.referenceData.aggregations.edges[0].node; - this.form.controls.name.setValue(this.aggregation.name as string); - } + .subscribe({ + next: ({ data }) => { + this.referenceData = data.referenceData; + if (aggregationId && this.referenceData.aggregations?.edges[0]) { + this.aggregation = this.referenceData.aggregations.edges[0].node; + this.form.controls.name.setValue(this.aggregation.name as string); + } + }, }); } @@ -249,14 +253,16 @@ export class TemplateAggregationModalComponent referenceData: this.referenceData?.id, }) .pipe(takeUntil(this.destroy$)) - .subscribe(({ data }) => { - if (data?.editAggregation) { - if (this.resource) { - this.getResource(this.resource?.id as string); - } else { - this.getReferenceData(this.referenceData?.id as string); + .subscribe({ + next: ({ data }) => { + if (data?.editAggregation) { + if (this.resource) { + this.getResource(this.resource?.id as string); + } else { + this.getReferenceData(this.referenceData?.id as string); + } } - } + }, }); } }); diff --git a/libs/shared/src/lib/components/widgets/common/template-aggregations/template-aggregations.component.ts b/libs/shared/src/lib/components/widgets/common/template-aggregations/template-aggregations.component.ts index a95073a851..8202ad3bd3 100644 --- a/libs/shared/src/lib/components/widgets/common/template-aggregations/template-aggregations.component.ts +++ b/libs/shared/src/lib/components/widgets/common/template-aggregations/template-aggregations.component.ts @@ -188,15 +188,15 @@ export class TemplateAggregationsComponent : undefined, first: -1, }); - - const { data: aggregationData, errors } = await firstValueFrom(query$); - if (!aggregationData || errors) { + let aggregationData!: any; + try { + const { data } = await firstValueFrom(query$); + aggregationData = data; + } catch (errors) { this.loadingAggregationRecords = false; - if (errors?.length) { - this.snackBar.openSnackBar(errorMessageFormatter(errors), { - error: true, - }); - } + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, + }); return; } this.loadingAggregationRecords = false; diff --git a/libs/shared/src/lib/components/widgets/editor-settings/editor-settings.component.ts b/libs/shared/src/lib/components/widgets/editor-settings/editor-settings.component.ts index 8956975834..d17b09523c 100644 --- a/libs/shared/src/lib/components/widgets/editor-settings/editor-settings.component.ts +++ b/libs/shared/src/lib/components/widgets/editor-settings/editor-settings.component.ts @@ -209,17 +209,22 @@ export class EditorSettingsComponent layout: layout ? [layout] : undefined, }, }) - .subscribe(({ data }) => { - if (data) { - this.resource = data.resource; - if (layout) { - this.layout = data.resource.layouts?.edges[0]?.node || null; - } else { - this.layout = null; + .subscribe({ + next: ({ data }) => { + if (data) { + this.resource = data.resource; + if (layout) { + this.layout = data.resource.layouts?.edges[0]?.node || null; + } else { + this.layout = null; + } + this.updateFields(); } - this.updateFields(); - } - this.loading = false; + this.loading = false; + }, + error: () => { + this.loading = false; + }, }); } @@ -237,12 +242,17 @@ export class EditorSettingsComponent id: referenceData, }, }) - .subscribe(({ data }) => { - if (data) { - this.referenceData = data.referenceData; - this.updateFields(); - } - this.loading = false; + .subscribe({ + next: ({ data }) => { + if (data) { + this.referenceData = data.referenceData; + this.updateFields(); + } + this.loading = false; + }, + error: () => { + this.loading = false; + }, }); } diff --git a/libs/shared/src/lib/components/widgets/editor-settings/record-selection-tab/record-selection-tab.component.ts b/libs/shared/src/lib/components/widgets/editor-settings/record-selection-tab/record-selection-tab.component.ts index c7cb041075..b171f744be 100644 --- a/libs/shared/src/lib/components/widgets/editor-settings/record-selection-tab/record-selection-tab.component.ts +++ b/libs/shared/src/lib/components/widgets/editor-settings/record-selection-tab/record-selection-tab.component.ts @@ -119,12 +119,14 @@ export class RecordSelectionTabComponent if (value && this.layout) { this.gridLayoutService .editLayout(this.layout, value, this.resource?.id) - .subscribe(() => { - if (this.form.get('layout')) { - this.form - .get('layout') - ?.setValue(this.form.get('layout')?.value || null); - } + .subscribe({ + next: () => { + if (this.form.get('layout')) { + this.form + .get('layout') + ?.setValue(this.form.get('layout')?.value || null); + } + }, }); } }); diff --git a/libs/shared/src/lib/components/widgets/editor/editor.component.ts b/libs/shared/src/lib/components/widgets/editor/editor.component.ts index 53731cd50c..0de2f6bac6 100644 --- a/libs/shared/src/lib/components/widgets/editor/editor.component.ts +++ b/libs/shared/src/lib/components/widgets/editor/editor.component.ts @@ -310,23 +310,25 @@ export class EditorComponent extends UnsubscribeComponent implements OnInit { ]) ) .pipe(takeUntil(this.cancelRefresh$)) - .subscribe(() => { - this.formattedStyle = this.dataTemplateService.renderStyle( - this.settings.wholeCardStyles || false, - this.fieldsValue, - this.styles - ); - this.formattedHtml = this.dataTemplateService.renderHtml( - this.settings.text, - { - data: this.fieldsValue, - aggregation: this.aggregations, - fields: this.fields, - styles: this.styles, - } - ); - this.loading = false; - callback(); + .subscribe({ + next: () => { + this.formattedStyle = this.dataTemplateService.renderStyle( + this.settings.wholeCardStyles || false, + this.fieldsValue, + this.styles + ); + this.formattedHtml = this.dataTemplateService.renderHtml( + this.settings.text, + { + data: this.fieldsValue, + aggregation: this.aggregations, + fields: this.fields, + styles: this.styles, + } + ); + this.loading = false; + callback(); + }, }); } else if (this.settings.element && this.settings.referenceData) { from( @@ -362,32 +364,36 @@ export class EditorComponent extends UnsubscribeComponent implements OnInit { ]) ) .pipe(takeUntil(this.cancelRefresh$)) - .subscribe(() => { - this.formattedHtml = this.dataTemplateService.renderHtml( - this.settings.text, - { - data: this.fieldsValue, - aggregation: this.aggregations, - fields: this.fields, - } - ); - this.loading = false; - callback(); + .subscribe({ + next: () => { + this.formattedHtml = this.dataTemplateService.renderHtml( + this.settings.text, + { + data: this.fieldsValue, + aggregation: this.aggregations, + fields: this.fields, + } + ); + this.loading = false; + callback(); + }, }); } else { from(Promise.all([this.getAggregationsData()])) .pipe(takeUntil(this.cancelRefresh$)) - .subscribe(() => { - this.formattedHtml = this.dataTemplateService.renderHtml( - this.settings.text, - { - data: this.fieldsValue, - aggregation: this.aggregations, - fields: this.fields, - } - ); - this.loading = false; - callback(); + .subscribe({ + next: () => { + this.formattedHtml = this.dataTemplateService.renderHtml( + this.settings.text, + { + data: this.fieldsValue, + aggregation: this.aggregations, + fields: this.fields, + } + ); + this.loading = false; + callback(); + }, }); } } diff --git a/libs/shared/src/lib/components/widgets/grid-settings/grid-settings.component.ts b/libs/shared/src/lib/components/widgets/grid-settings/grid-settings.component.ts index 82b251564d..06b233d1e1 100644 --- a/libs/shared/src/lib/components/widgets/grid-settings/grid-settings.component.ts +++ b/libs/shared/src/lib/components/widgets/grid-settings/grid-settings.component.ts @@ -280,8 +280,10 @@ export class GridSettingsComponent }, }) .pipe(takeUntil(this.destroy$)) - .subscribe(({ data }) => { - this.channels = data.channels; + .subscribe({ + next: ({ data }) => { + this.channels = data.channels; + }, }); } else { this.apollo @@ -289,8 +291,10 @@ export class GridSettingsComponent query: GET_CHANNELS, }) .pipe(takeUntil(this.destroy$)) - .subscribe(({ data }) => { - this.channels = data.channels; + .subscribe({ + next: ({ data }) => { + this.channels = data.channels; + }, }); } }); @@ -317,8 +321,8 @@ export class GridSettingsComponent firstAggregations: aggregationIds?.length || 10, }, }) - .subscribe(({ data }) => { - if (data) { + .subscribe({ + next: ({ data }) => { this.resource = data.resource; this.relatedForms = data.resource.relatedForms || []; this.templates = data.resource.forms || []; @@ -331,12 +335,13 @@ export class GridSettingsComponent this.resource.queryName as string ); } - } else { + }, + error: () => { this.relatedForms = []; this.templates = []; this.resource = null; this.fields = []; - } + }, }); } else { this.relatedForms = []; @@ -368,15 +373,17 @@ export class GridSettingsComponent resource: this.resource.id, aggregation: aggregationId || '', }) - .subscribe(({ data }: any) => { - if (data.recordsAggregation) { - this.fields = data.recordsAggregation.items[0] - ? Object.keys(data.recordsAggregation.items[0]).map((f) => ({ - name: f, - editor: 'text', - })) - : []; - } + .subscribe({ + next: ({ data }: any) => { + if (data.recordsAggregation) { + this.fields = data.recordsAggregation.items[0] + ? Object.keys(data.recordsAggregation.items[0]).map((f) => ({ + name: f, + editor: 'text', + })) + : []; + } + }, }); } } diff --git a/libs/shared/src/lib/components/widgets/grid/grid.component.ts b/libs/shared/src/lib/components/widgets/grid/grid.component.ts index e6e589b636..ba9c848774 100644 --- a/libs/shared/src/lib/components/widgets/grid/grid.component.ts +++ b/libs/shared/src/lib/components/widgets/grid/grid.component.ts @@ -186,14 +186,16 @@ export class GridWidgetComponent resource: this.settings.resource, }, }) - .subscribe((res) => { - if (res.data) { - this.canCreateRecords = get( - res, - 'data.resource.canCreateRecords', - false - ); - } + .subscribe({ + next: (res) => { + if (res.data) { + this.canCreateRecords = get( + res, + 'data.resource.canCreateRecords', + false + ); + } + }, }); if (layouts.length > 0) { @@ -623,81 +625,84 @@ export class GridWidgetComponent id: value.record, }, }) - .subscribe((getRecord) => { - const resourceField = form.fields?.find( - (field) => - field.resource && - field.resource === this.settings.resource - ); - let data = getRecord.data.record.data; - const key = resourceField.name; - if (resourceField.type === 'resource') { - data = { ...data, [key]: selectedRecords[0] }; - } else { - if (data[key]) { - data = { - ...data, - [key]: data[key].concat(selectedRecords), - }; + .subscribe({ + next: (getRecord) => { + const resourceField = form.fields?.find( + (field) => + field.resource && + field.resource === this.settings.resource + ); + let data = getRecord.data.record.data; + const key = resourceField.name; + if (resourceField.type === 'resource') { + data = { ...data, [key]: selectedRecords[0] }; } else { - data = { ...data, [key]: selectedRecords }; - } - } - this.apollo - .mutate({ - mutation: EDIT_RECORD, - variables: { - id: value.record, - template: targetForm, - data, - }, - }) - .subscribe(async (editRecord) => { - if (editRecord.errors) { - this.snackBar.openSnackBar( - this.translate.instant( - 'models.record.notifications.rowsNotAdded' - ), - { error: true } - ); - resolve(false); + if (data[key]) { + data = { + ...data, + [key]: data[key].concat(selectedRecords), + }; } else { - if (editRecord.data) { - const record = editRecord.data.editRecord; - if (record) { - this.snackBar.openSnackBar( - this.translate.instant( - 'models.record.notifications.rowsAdded', + data = { ...data, [key]: selectedRecords }; + } + } + this.apollo + .mutate({ + mutation: EDIT_RECORD, + variables: { + id: value.record, + template: targetForm, + data, + }, + }) + .subscribe({ + next: async (editRecord) => { + if (editRecord.data) { + const record = editRecord.data.editRecord; + if (record) { + this.snackBar.openSnackBar( + this.translate.instant( + 'models.record.notifications.rowsAdded', + { + field: record.data[targetFormField], + length: selectedRecords.length, + value: key, + } + ) + ); + const { FormModalComponent } = await import( + '../../form-modal/form-modal.component' + ); + const dialogRef2 = this.dialog.open( + FormModalComponent, { - field: record.data[targetFormField], - length: selectedRecords.length, - value: key, + disableClose: true, + data: { + recordId: record.id, + template: targetForm, + }, + autoFocus: false, } - ) - ); - const { FormModalComponent } = await import( - '../../form-modal/form-modal.component' - ); - const dialogRef2 = this.dialog.open( - FormModalComponent, - { - disableClose: true, - data: { - recordId: record.id, - template: targetForm, - }, - autoFocus: false, - } - ); - dialogRef2.closed - .pipe(takeUntil(this.destroy$)) - .subscribe(() => resolve(true)); - } else { - resolve(false); + ); + dialogRef2.closed + .pipe(takeUntil(this.destroy$)) + .subscribe(() => resolve(true)); + } else { + resolve(false); + } } - } - } - }); + }, + error: () => { + this.snackBar.openSnackBar( + this.translate.instant( + 'models.record.notifications.rowsNotAdded' + ), + { error: true } + ); + resolve(false); + }, + }); + }, }); } else { resolve(false); diff --git a/libs/shared/src/lib/components/widgets/map-settings/edit-layer-modal/edit-layer-modal.component.ts b/libs/shared/src/lib/components/widgets/map-settings/edit-layer-modal/edit-layer-modal.component.ts index 693c9ca554..9d641dcf68 100644 --- a/libs/shared/src/lib/components/widgets/map-settings/edit-layer-modal/edit-layer-modal.component.ts +++ b/libs/shared/src/lib/components/widgets/map-settings/edit-layer-modal/edit-layer-modal.component.ts @@ -529,29 +529,33 @@ export class EditLayerModalComponent }, }) .pipe(takeUntil(this.destroy$)) - .subscribe(({ data }) => { - this.resource = data.resource; - // Update fields - if (layoutID) { - this.layout = get(data, 'resource.layouts.edges[0].node', null); - this.fields.next(this.mapLayersService.getQueryFields(this.layout)); - } else { - if (aggregationID) { - this.aggregation = get( - data, - 'resource.aggregations.edges[0].node', - null - ); + .subscribe({ + next: ({ data }) => { + this.resource = data.resource; + // Update fields + if (layoutID) { + this.layout = get(data, 'resource.layouts.edges[0].node', null); this.fields.next( - this.aggregation - ? this.mapLayersService.getAggregationFields( - data.resource.queryName ?? '', - this.aggregation - ) - : [] + this.mapLayersService.getQueryFields(this.layout) ); + } else { + if (aggregationID) { + this.aggregation = get( + data, + 'resource.aggregations.edges[0].node', + null + ); + this.fields.next( + this.aggregation + ? this.mapLayersService.getAggregationFields( + data.resource.queryName ?? '', + this.aggregation + ) + : [] + ); + } } - } + }, }); } } @@ -573,27 +577,29 @@ export class EditLayerModalComponent aggregation: aggregationID ? [aggregationID] : [], }, }) - .subscribe(({ data }) => { - this.referenceData = data.referenceData; - if (aggregationID) { - this.aggregation = get( - data, - 'referenceData.aggregations.edges[0].node', - null - ); - this.fields.next( - this.aggregation - ? this.mapLayersService.getAggregationFields( - data.referenceData.graphQLTypeName ?? '', - this.aggregation - ) - : [] - ); - } else { - this.fields.next( - this.getFieldsFromRefData(this.referenceData?.fields || []) - ); - } + .subscribe({ + next: ({ data }) => { + this.referenceData = data.referenceData; + if (aggregationID) { + this.aggregation = get( + data, + 'referenceData.aggregations.edges[0].node', + null + ); + this.fields.next( + this.aggregation + ? this.mapLayersService.getAggregationFields( + data.referenceData.graphQLTypeName ?? '', + this.aggregation + ) + : [] + ); + } else { + this.fields.next( + this.getFieldsFromRefData(this.referenceData?.fields || []) + ); + } + }, }); } } diff --git a/libs/shared/src/lib/components/widgets/map-settings/edit-layer-modal/layer-datasource/layer-datasource.component.ts b/libs/shared/src/lib/components/widgets/map-settings/edit-layer-modal/layer-datasource/layer-datasource.component.ts index a694317ae3..65d54d8d71 100644 --- a/libs/shared/src/lib/components/widgets/map-settings/edit-layer-modal/layer-datasource/layer-datasource.component.ts +++ b/libs/shared/src/lib/components/widgets/map-settings/edit-layer-modal/layer-datasource/layer-datasource.component.ts @@ -134,8 +134,12 @@ export class LayerDatasourceComponent extends UnsubscribeComponent { if (value && this.layout) { this.gridLayoutService .editLayout(this.layout, value, this.resource?.id) - .subscribe(() => { - this.formGroup.get('layout')?.setValue(this.formGroup.value.layout); + .subscribe({ + next: () => { + this.formGroup + .get('layout') + ?.setValue(this.formGroup.value.layout); + }, }); } }); @@ -160,10 +164,12 @@ export class LayerDatasourceComponent extends UnsubscribeComponent { resource: this.resource?.id, referenceData: this.referenceData?.id, }) - .subscribe(() => { - this.formGroup - .get('aggregation') - ?.setValue(this.formGroup.value.aggregation); + .subscribe({ + next: () => { + this.formGroup + .get('aggregation') + ?.setValue(this.formGroup.value.aggregation); + }, }); } }); diff --git a/libs/shared/src/lib/components/widgets/map-settings/map-layers/map-layers.component.ts b/libs/shared/src/lib/components/widgets/map-settings/map-layers/map-layers.component.ts index facc46ada3..ab9f0393c1 100644 --- a/libs/shared/src/lib/components/widgets/map-settings/map-layers/map-layers.component.ts +++ b/libs/shared/src/lib/components/widgets/map-settings/map-layers/map-layers.component.ts @@ -58,9 +58,14 @@ export class MapLayersComponent extends UnsubscribeComponent implements OnInit { */ private updateLayerList(): void { const layerIds = this.control.value; - this.mapLayersService.getLayers(layerIds).subscribe((layers) => { - this.mapLayers = layers; - this.loading = false; + this.mapLayersService.getLayers(layerIds).subscribe({ + next: (layers) => { + this.mapLayers = layers; + this.loading = false; + }, + error: () => { + this.loading = false; + }, }); } @@ -188,7 +193,7 @@ export class MapLayersComponent extends UnsubscribeComponent implements OnInit { } }, error: (err) => { - console.log(err); + console.error(err); this.loading = false; }, complete: () => (this.loading = false), diff --git a/libs/shared/src/lib/components/widgets/summary-card-settings/summary-card-general/summary-card-general.component.ts b/libs/shared/src/lib/components/widgets/summary-card-settings/summary-card-general/summary-card-general.component.ts index d4071e3d25..9aa12b44d3 100644 --- a/libs/shared/src/lib/components/widgets/summary-card-settings/summary-card-general/summary-card-general.component.ts +++ b/libs/shared/src/lib/components/widgets/summary-card-settings/summary-card-general/summary-card-general.component.ts @@ -130,12 +130,14 @@ export class SummaryCardGeneralComponent extends UnsubscribeComponent { if (value && this.layout) { this.layoutService .editLayout(this.layout, value, this.resource?.id) - .subscribe(() => { - if (this.formGroup.get('card.layout')) { - this.formGroup - .get('card.layout') - ?.setValue(this.formGroup.get('card.layout')?.value || null); - } + .subscribe({ + next: () => { + if (this.formGroup.get('card.layout')) { + this.formGroup + .get('card.layout') + ?.setValue(this.formGroup.get('card.layout')?.value || null); + } + }, }); } }); @@ -188,14 +190,16 @@ export class SummaryCardGeneralComponent extends UnsubscribeComponent { .editAggregation(this.aggregation, value, { resource: this.resource?.id, }) - .subscribe(() => { - if (this.formGroup.get('card.aggregation')) { - this.formGroup - .get('card.aggregation') - ?.setValue( - this.formGroup.get('card.aggregation')?.value || null - ); - } + .subscribe({ + next: () => { + if (this.formGroup.get('card.aggregation')) { + this.formGroup + .get('card.aggregation') + ?.setValue( + this.formGroup.get('card.aggregation')?.value || null + ); + } + }, }); } }); diff --git a/libs/shared/src/lib/components/widgets/summary-card-settings/summary-card-settings.component.ts b/libs/shared/src/lib/components/widgets/summary-card-settings/summary-card-settings.component.ts index 1bb1328689..3c57b77407 100644 --- a/libs/shared/src/lib/components/widgets/summary-card-settings/summary-card-settings.component.ts +++ b/libs/shared/src/lib/components/widgets/summary-card-settings/summary-card-settings.component.ts @@ -298,15 +298,8 @@ export class SummaryCardSettingsComponent aggregation: aggregationID ? [aggregationID] : undefined, }, }) - .subscribe(({ data, errors }) => { - if (errors) { - this.widgetFormGroup.get('card.resource')?.patchValue(null); - this.widgetFormGroup.get('card.layout')?.patchValue(null); - this.widgetFormGroup.get('card.aggregation')?.patchValue(null); - this.resource = null; - this.layout = null; - this.aggregation = null; - } else { + .subscribe({ + next: ({ data }) => { this.resource = data.resource; if (layoutID) { this.layout = data?.resource.layouts?.edges[0]?.node || null; @@ -327,7 +320,15 @@ export class SummaryCardSettingsComponent data?.resource.aggregations?.edges[0]?.node || null; this.getCustomAggregation(); } - } + }, + error: () => { + this.widgetFormGroup.get('card.resource')?.patchValue(null); + this.widgetFormGroup.get('card.layout')?.patchValue(null); + this.widgetFormGroup.get('card.aggregation')?.patchValue(null); + this.resource = null; + this.layout = null; + this.aggregation = null; + }, }); } @@ -344,11 +345,8 @@ export class SummaryCardSettingsComponent id, }, }) - .subscribe(({ data, errors }) => { - if (errors) { - this.widgetFormGroup.get('card.referenceData')?.patchValue(null); - this.referenceData = null; - } else { + .subscribe({ + next: ({ data }) => { this.referenceData = data.referenceData; this.fields = (this.referenceData.fields || []) .filter((field) => field && typeof field !== 'string') @@ -359,7 +357,11 @@ export class SummaryCardSettingsComponent type: field.type, }; }); - } + }, + error: () => { + this.widgetFormGroup.get('card.referenceData')?.patchValue(null); + this.referenceData = null; + }, }); } @@ -374,16 +376,18 @@ export class SummaryCardSettingsComponent resource: this.resource.id, aggregation: this.aggregation.id || '', }) - ?.subscribe(({ data }: any) => { - if (data.recordsAggregation) { - const customAggregation = data.recordsAggregation; - this.fields = customAggregation.items[0] - ? Object.keys(customAggregation.items[0]).map((f) => ({ - name: f, - editor: 'text', - })) - : []; - } + ?.subscribe({ + next: ({ data }: any) => { + if (data.recordsAggregation) { + const customAggregation = data.recordsAggregation; + this.fields = customAggregation.items[0] + ? Object.keys(customAggregation.items[0]).map((f) => ({ + name: f, + editor: 'text', + })) + : []; + } + }, }); } diff --git a/libs/shared/src/lib/components/widgets/summary-card/summary-card.component.ts b/libs/shared/src/lib/components/widgets/summary-card/summary-card.component.ts index 92a768ff78..c9fc4cbdd3 100644 --- a/libs/shared/src/lib/components/widgets/summary-card/summary-card.component.ts +++ b/libs/shared/src/lib/components/widgets/summary-card/summary-card.component.ts @@ -466,9 +466,10 @@ export class SummaryCardComponent }) ) .pipe(takeUntil(merge(this.cancelRefresh$, this.destroy$))) - .subscribe(({ items, pageInfo }) => - this.updateReferenceDataCards(items, pageInfo) - ); + .subscribe({ + next: ({ items, pageInfo }) => + this.updateReferenceDataCards(items, pageInfo), + }); } } @@ -1014,7 +1015,7 @@ export class SummaryCardComponent }) ) .pipe(takeUntil(merge(this.cancelRefresh$, this.destroy$))) - .subscribe(() => this.updateRecordCards.bind(this)); + .subscribe({ next: () => this.updateRecordCards.bind(this) }); } } } @@ -1063,9 +1064,14 @@ export class SummaryCardComponent }) ) .pipe(takeUntil(merge(this.cancelRefresh$, this.destroy$))) - .subscribe(({ items, pageInfo }) => { - this.updateReferenceDataCards(items, pageInfo); - this.loading = false; + .subscribe({ + next: ({ items, pageInfo }) => { + this.updateReferenceDataCards(items, pageInfo); + this.loading = false; + }, + error: () => { + this.loading = false; + }, }); } } @@ -1159,7 +1165,12 @@ export class SummaryCardComponent }) ) .pipe(takeUntil(merge(this.cancelRefresh$, this.destroy$))) - .subscribe(() => (this.loading = false)); + .subscribe({ + next: () => (this.loading = false), + error: () => { + this.loading = false; + }, + }); } else if (this.useReferenceData) { if (this.refData?.pageInfo?.strategy) { this.refresh(); diff --git a/libs/shared/src/lib/interceptors/error-handler/error-handler-interceptor.service.ts b/libs/shared/src/lib/interceptors/error-handler/error-handler-interceptor.service.ts index d23b76a854..02a5612515 100644 --- a/libs/shared/src/lib/interceptors/error-handler/error-handler-interceptor.service.ts +++ b/libs/shared/src/lib/interceptors/error-handler/error-handler-interceptor.service.ts @@ -48,6 +48,7 @@ export class ErrorHandlerInterceptorService implements HttpInterceptor { } else { errorMessage = errorMessage + '\n' + res.error; } + errorMessage = errorMessage + '\n' + res.message; this.snackbarService.openSnackBar(errorMessage, { error: true, duration: 0, diff --git a/libs/shared/src/lib/services/aggregation/aggregation.service.ts b/libs/shared/src/lib/services/aggregation/aggregation.service.ts index 5f01793c0a..8af09b014e 100644 --- a/libs/shared/src/lib/services/aggregation/aggregation.service.ts +++ b/libs/shared/src/lib/services/aggregation/aggregation.service.ts @@ -84,13 +84,13 @@ export class AggregationService { first: options.first, }, }) - ).then(async ({ errors, data }) => { - if (errors) { - return FALLBACK_AGGREGATIONS; - } else { + ) + .then(async ({ data }) => { return data.resource.aggregations || FALLBACK_AGGREGATIONS; - } - }); + }) + .catch(() => { + return FALLBACK_AGGREGATIONS; + }); } else { return await firstValueFrom( this.apollo.query({ @@ -101,13 +101,13 @@ export class AggregationService { first: options.first, }, }) - ).then(async ({ errors, data }) => { - if (errors) { - return FALLBACK_AGGREGATIONS; - } else { + ) + .then(async ({ data }) => { return data.referenceData.aggregations || FALLBACK_AGGREGATIONS; - } - }); + }) + .catch(() => { + return FALLBACK_AGGREGATIONS; + }); } } diff --git a/libs/shared/src/lib/services/application/application.service.ts b/libs/shared/src/lib/services/application/application.service.ts index 76c0036371..128a83d3c9 100644 --- a/libs/shared/src/lib/services/application/application.service.ts +++ b/libs/shared/src/lib/services/application/application.service.ts @@ -278,17 +278,19 @@ export class ApplicationService { id, }, }) - .subscribe(() => { - const snackBar = this.snackBar.openSnackBar( - this.translate.instant('models.application.notifications.updated'), - { - action: 'Reload', - duration: 0, - } - ); - snackBar.instance.actionComplete.subscribe(() => - window.location.reload() - ); + .subscribe({ + next: () => { + const snackBar = this.snackBar.openSnackBar( + this.translate.instant('models.application.notifications.updated'), + { + action: 'Reload', + duration: 0, + } + ); + snackBar.instance.actionComplete.subscribe(() => + window.location.reload() + ); + }, }); this.lockSubscription = this.apollo .subscribe({ @@ -297,16 +299,18 @@ export class ApplicationService { id, }, }) - .subscribe(({ data }) => { - if (data?.applicationUnlocked) { - const application = this.application.getValue(); - const newApplication = { - ...application, - locked: data?.applicationUnlocked?.locked, - lockedByUser: data?.applicationUnlocked?.lockedByUser, - }; - this.application.next(newApplication); - } + .subscribe({ + next: ({ data }) => { + if (data?.applicationUnlocked) { + const application = this.application.getValue(); + const newApplication = { + ...application, + locked: data?.applicationUnlocked?.locked, + lockedByUser: data?.applicationUnlocked?.lockedByUser, + }; + this.application.next(newApplication); + } + }, }); } @@ -352,17 +356,19 @@ export class ApplicationService { lock: !locked, }, }) - .subscribe(({ data }) => { - if (data?.toggleApplicationLock) { - if (!data.toggleApplicationLock.lockedByUser) { - const newApplication = { - ...application, - locked: data?.toggleApplicationLock?.locked, - lockedByUser: data?.toggleApplicationLock.lockedByUser, - }; - this.application.next(newApplication); + .subscribe({ + next: ({ data }) => { + if (data?.toggleApplicationLock) { + if (!data.toggleApplicationLock.lockedByUser) { + const newApplication = { + ...application, + locked: data?.toggleApplicationLock?.locked, + lockedByUser: data?.toggleApplicationLock.lockedByUser, + }; + this.application.next(newApplication); + } } - } + }, }); } @@ -386,13 +392,13 @@ export class ApplicationService { status: value.status, }, }) - .subscribe(({ errors, data }) => { - this.handleEditionMutationResponse( - errors, - this.translate.instant('common.application.one'), - value.name - ); - if (!errors && data && data.editApplication) { + .subscribe({ + next: ({ data }) => { + this.handleEditionMutationResponse( + [], + this.translate.instant('common.application.one'), + value.name + ); if (data?.editApplication) { const newApplication = { ...application, @@ -404,7 +410,14 @@ export class ApplicationService { }; this.application.next(newApplication); } - } + }, + error: (errors) => { + this.handleEditionMutationResponse( + errors, + this.translate.instant('common.application.one'), + value.name + ); + }, }); } } @@ -669,25 +682,34 @@ export class ApplicationService { name: page.name, }, }) - .subscribe(({ errors, data }) => { - this.handleEditionMutationResponse( - errors, - this.translate.instant('common.page.one'), - page.name - ); - if (!errors && data) { - const newApplication = { - ...application, - pages: application.pages?.map((x) => { - if (x.id === page.id) { - x = { ...x, name: page.name }; - } - return x; - }), - }; - this.application.next(newApplication); - if (callback) callback(); - } + .subscribe({ + next: ({ data }) => { + this.handleEditionMutationResponse( + [], + this.translate.instant('common.page.one'), + page.name + ); + if (data) { + const newApplication = { + ...application, + pages: application.pages?.map((x) => { + if (x.id === page.id) { + x = { ...x, name: page.name }; + } + return x; + }), + }; + this.application.next(newApplication); + if (callback) callback(); + } + }, + error: (errors) => { + this.handleEditionMutationResponse( + errors, + this.translate.instant('common.page.one'), + page.name + ); + }, }); } } @@ -710,24 +732,32 @@ export class ApplicationService { visible: page.visible, }, }) - .subscribe(({ errors, data }) => { - this.handleEditionMutationResponse( - errors, - this.translate.instant('common.page.one') - ); - if (!errors && data) { - const newApplication = { - ...application, - pages: application.pages?.map((x) => { - if (x.id === page.id) { - x = { ...x, visible: data.editPage.visible }; - } - return x; - }), - }; - this.application.next(newApplication); - if (callback) callback(); - } + .subscribe({ + next: ({ data }) => { + this.handleEditionMutationResponse( + [], + this.translate.instant('common.page.one') + ); + if (data) { + const newApplication = { + ...application, + pages: application.pages?.map((x) => { + if (x.id === page.id) { + x = { ...x, visible: data.editPage.visible }; + } + return x; + }), + }; + this.application.next(newApplication); + if (callback) callback(); + } + }, + error: (errors) => { + this.handleEditionMutationResponse( + errors, + this.translate.instant('common.page.one') + ); + }, }); } } @@ -750,24 +780,32 @@ export class ApplicationService { icon, }, }) - .subscribe(({ errors, data }) => { - this.handleEditionMutationResponse( - errors, - this.translate.instant('common.page.one') - ); - if (!errors && data) { - const newApplication = { - ...application, - pages: application.pages?.map((x) => { - if (x.id === page.id) { - x = { ...x, icon: data.editPage.icon }; - } - return x; - }), - }; - this.application.next(newApplication); - if (callback) callback(); - } + .subscribe({ + next: ({ data }) => { + this.handleEditionMutationResponse( + [], + this.translate.instant('common.page.one') + ); + if (data) { + const newApplication = { + ...application, + pages: application.pages?.map((x) => { + if (x.id === page.id) { + x = { ...x, icon: data.editPage.icon }; + } + return x; + }), + }; + this.application.next(newApplication); + if (callback) callback(); + } + }, + error: (errors) => { + this.handleEditionMutationResponse( + errors, + this.translate.instant('common.page.one') + ); + }, }); } } @@ -1074,24 +1112,6 @@ export class ApplicationService { this.translate.instant('components.users.onDelete.singular') ); } - } else { - if (ids.length > 1) { - this.snackBar.openSnackBar( - this.translate.instant( - 'components.users.onNotDelete.plural', - { error: '' } - ), - { error: true } - ); - } else { - this.snackBar.openSnackBar( - this.translate.instant( - 'components.users.onNotDelete.singular', - { error: '' } - ), - { error: true } - ); - } } resolved(); }, @@ -1251,18 +1271,8 @@ export class ApplicationService { title: value.title, }, }) - .subscribe(({ errors, data }) => { - if (errors) { - this.snackBar.openSnackBar( - this.translate.instant('common.errors.objectDuplicated', { - type: this.translate - .instant('common.positionCategory.one') - .toLowerCase(), - value: value.title, - }), - { error: true } - ); - } else { + .subscribe({ + next: ({ data }) => { this.snackBar.openSnackBar( this.translate.instant('common.notifications.objectUpdated', { type: this.translate.instant('common.positionCategory.one'), @@ -1283,7 +1293,18 @@ export class ApplicationService { }), }; this.application.next(newApplication); - } + }, + error: () => { + this.snackBar.openSnackBar( + this.translate.instant('common.errors.objectDuplicated', { + type: this.translate + .instant('common.positionCategory.one') + .toLowerCase(), + value: value.title, + }), + { error: true } + ); + }, }); } } @@ -1633,16 +1654,18 @@ export class ApplicationService { }, }, }) - .subscribe(({ data }) => { - if (data) { - const newApplication: Application = { - ...application, - templates: [...(application.templates || []), data.addTemplate], - }; + .subscribe({ + next: ({ data }) => { + if (data) { + const newApplication: Application = { + ...application, + templates: [...(application.templates || []), data.addTemplate], + }; - this.application.next(newApplication); - if (callback) callback(data.addTemplate); - } + this.application.next(newApplication); + if (callback) callback(data.addTemplate); + } + }, }); } } @@ -1663,14 +1686,16 @@ export class ApplicationService { id, }, }) - .subscribe(({ data }) => { - if (data) { - const newApplication: Application = { - ...application, - templates: this.templates.filter((t) => t.id !== id), - }; - this.application.next(newApplication); - } + .subscribe({ + next: ({ data }) => { + if (data) { + const newApplication: Application = { + ...application, + templates: this.templates.filter((t) => t.id !== id), + }; + this.application.next(newApplication); + } + }, }); } } @@ -1696,20 +1721,22 @@ export class ApplicationService { }, }, }) - .subscribe(({ data }) => { - if (data?.editTemplate) { - const updatedTemplate = data.editTemplate; - const newApplication: Application = { - ...application, - templates: application.templates?.map((t) => { - if (t.id === template.id) { - t = updatedTemplate; - } - return t; - }), - }; - this.application.next(newApplication); - } + .subscribe({ + next: ({ data }) => { + if (data?.editTemplate) { + const updatedTemplate = data.editTemplate; + const newApplication: Application = { + ...application, + templates: application.templates?.map((t) => { + if (t.id === template.id) { + t = updatedTemplate; + } + return t; + }), + }; + this.application.next(newApplication); + } + }, }); } } @@ -1734,20 +1761,30 @@ export class ApplicationService { }, }, }) - .subscribe(({ data }) => { - if (data?.editDistributionList) { - const updatedDistributionList = data.editDistributionList; - const newApplication: Application = { - ...application, - distributionLists: application.distributionLists?.map((dist) => { - if (dist.id === distributionList.id) { - dist = updatedDistributionList; - } - return dist; - }), - }; - this.application.next(newApplication); - } + .subscribe({ + next: ({ data }) => { + if (data?.editDistributionList) { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectUpdated', { + value: data.editDistributionList.name, + type: this.translate.instant('common.distributionList.one'), + }) + ); + const updatedDistributionList = data.editDistributionList; + const newApplication: Application = { + ...application, + distributionLists: application.distributionLists?.map( + (dist) => { + if (dist.id === distributionList.id) { + dist = updatedDistributionList; + } + return dist; + } + ), + }; + this.application.next(newApplication); + } + }, }); } } @@ -1775,18 +1812,26 @@ export class ApplicationService { }, }, }) - .subscribe(({ data }) => { - if (data?.addDistributionList) { - const newApplication: Application = { - ...application, - distributionLists: [ - ...(application.distributionLists || []), - data.addDistributionList, - ], - }; - this.application.next(newApplication); - if (callback) callback(data.addDistributionList); - } + .subscribe({ + next: ({ data }) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectCreated', { + value: distributionList.name, + type: this.translate.instant('common.distributionList.one'), + }) + ); + if (data?.addDistributionList) { + const newApplication: Application = { + ...application, + distributionLists: [ + ...(application.distributionLists || []), + data.addDistributionList, + ], + }; + this.application.next(newApplication); + if (callback) callback(data.addDistributionList); + } + }, }); } } @@ -1807,16 +1852,23 @@ export class ApplicationService { id, }, }) - .subscribe(({ data }) => { - if (data) { - const newApplication: Application = { - ...application, - distributionLists: application.distributionLists?.filter( - (dist) => dist.id !== id - ), - }; - this.application.next(newApplication); - } + .subscribe({ + next: ({ data }) => { + if (data) { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectDeleted', { + value: data.deleteDistributionList.name, + }) + ); + const newApplication: Application = { + ...application, + distributionLists: application.distributionLists?.filter( + (dist) => dist.id !== id + ), + }; + this.application.next(newApplication); + } + }, }); } } @@ -1841,8 +1893,16 @@ export class ApplicationService { notification, }, }) - .subscribe((res) => { - if (callback) callback(res); + .subscribe({ + next: (res) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectCreated', { + value: notification.name, + type: this.translate.instant('common.customNotification.one'), + }) + ); + if (callback) callback(res); + }, }); } } @@ -1864,8 +1924,15 @@ export class ApplicationService { application: application.id, }, }) - .subscribe((res) => { - if (callback) callback(res); + .subscribe({ + next: (res) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectDeleted', { + value: res.data?.deleteCustomNotification.name, + }) + ); + if (callback) callback(res); + }, }); } } @@ -1893,8 +1960,16 @@ export class ApplicationService { notification, }, }) - .subscribe((res) => { - if (callback) callback(res); + .subscribe({ + next: (res) => { + this.snackBar.openSnackBar( + this.translate.instant('common.notifications.objectUpdated', { + value: notification.name, + type: this.translate.instant('common.customNotification.one'), + }) + ); + if (callback) callback(res); + }, }); } } @@ -2008,29 +2083,37 @@ export class ApplicationService { permissions, }, }) - .subscribe(({ errors, data }) => { - this.handleEditionMutationResponse( - errors, - this.translate.instant('common.page.one') - ); - if (!errors && data) { - const newApplication = { - ...application, - pages: application.pages?.map((x) => { - if (x.id === page.id) { - x = { - ...x, - canSee: data.editPage.permissions.canSee, - canDelete: data.editPage.permissions.canDelete, - canUpdate: data.editPage.permissions.canUpdate, - }; - } - return x; - }), - }; - this.application.next(newApplication); - if (callback) callback(data.editPage.permissions); - } + .subscribe({ + next: ({ data }) => { + this.handleEditionMutationResponse( + [], + this.translate.instant('common.page.one') + ); + if (data) { + const newApplication = { + ...application, + pages: application.pages?.map((x) => { + if (x.id === page.id) { + x = { + ...x, + canSee: data.editPage.permissions.canSee, + canDelete: data.editPage.permissions.canDelete, + canUpdate: data.editPage.permissions.canUpdate, + }; + } + return x; + }), + }; + this.application.next(newApplication); + if (callback) callback(data.editPage.permissions); + } + }, + error: (errors) => { + this.handleEditionMutationResponse( + errors, + this.translate.instant('common.page.one') + ); + }, }); } } diff --git a/libs/shared/src/lib/services/context/context.service.ts b/libs/shared/src/lib/services/context/context.service.ts index b90c452314..874e7d3311 100644 --- a/libs/shared/src/lib/services/context/context.service.ts +++ b/libs/shared/src/lib/services/context/context.service.ts @@ -534,13 +534,15 @@ export class ContextService { id: dContext.record, }, }) - .subscribe((res) => { - if (res?.data) { - callback({ - record: dContext.record, - recordData: res.data.record, - }); - } + .subscribe({ + next: (res) => { + if (res?.data) { + callback({ + record: dContext.record, + recordData: res.data.record, + }); + } + }, }); } } @@ -562,8 +564,13 @@ export class ContextService { }, }, }) - .subscribe(({ errors, data }) => { - this.handleFilterMutationResponse({ data, errors }, dashboard); + .subscribe({ + next: ({ data }) => { + this.handleFilterMutationResponse({ data, errors: [] }, dashboard); + }, + error: (errors) => { + this.handleFilterMutationResponse({ data: null, errors }, dashboard); + }, }); } diff --git a/libs/shared/src/lib/services/dashboard/dashboard.service.ts b/libs/shared/src/lib/services/dashboard/dashboard.service.ts index df729a90e3..f46e7b7754 100644 --- a/libs/shared/src/lib/services/dashboard/dashboard.service.ts +++ b/libs/shared/src/lib/services/dashboard/dashboard.service.ts @@ -133,8 +133,10 @@ export class DashboardService { name, }, }) - .subscribe(() => { - if (callback) callback(); + .subscribe({ + next: () => { + if (callback) callback(); + }, }); } @@ -183,14 +185,22 @@ export class DashboardService { gridOptions, }, }) - .subscribe(({ errors, data }) => { - this.handleEditionMutationResponse( - errors, - this.translate.instant('common.page.one') - ); - if (!errors && data) { - if (callback) callback(); - } + .subscribe({ + next: ({ data }) => { + this.handleEditionMutationResponse( + [], + this.translate.instant('common.page.one') + ); + if (data) { + if (callback) callback(); + } + }, + error: (errors) => { + this.handleEditionMutationResponse( + errors, + this.translate.instant('common.page.one') + ); + }, }); } } diff --git a/libs/shared/src/lib/services/download/download.service.ts b/libs/shared/src/lib/services/download/download.service.ts index 16b038c81d..f5617425e9 100644 --- a/libs/shared/src/lib/services/download/download.service.ts +++ b/libs/shared/src/lib/services/download/download.service.ts @@ -293,27 +293,27 @@ export class DownloadService { const formData = new FormData(); formData.append('file', file, file.name); return new Promise((resolve, reject) => { - this.restService - .post(path, formData, { headers }) - .subscribe((res: { path: string }) => { + this.restService.post(path, formData, { headers }).subscribe({ + next: (res: { path: string }) => { const { path } = res ?? {}; - if (path) { - snackBarRef.instance.message = this.translate.instant( - 'common.notifications.file.upload.ready' - ); - snackBarRef.instance.loading = false; - snackBarRef.instance.triggerSnackBar(SNACKBAR_DURATION); - resolve(path); - } else { - snackBarRef.instance.message = this.translate.instant( - 'common.notifications.file.upload.error' - ); - snackBarRef.instance.loading = false; - snackBarRef.instance.error = true; - snackBarRef.instance.triggerSnackBar(SNACKBAR_DURATION); - reject(); - } - }); + + snackBarRef.instance.message = this.translate.instant( + 'common.notifications.file.upload.ready' + ); + snackBarRef.instance.loading = false; + snackBarRef.instance.triggerSnackBar(SNACKBAR_DURATION); + resolve(path); + }, + error: () => { + snackBarRef.instance.message = this.translate.instant( + 'common.notifications.file.upload.error' + ); + snackBarRef.instance.loading = false; + snackBarRef.instance.error = true; + snackBarRef.instance.triggerSnackBar(SNACKBAR_DURATION); + reject(); + }, + }); }); } } diff --git a/libs/shared/src/lib/services/form-helper/form-helper.service.ts b/libs/shared/src/lib/services/form-helper/form-helper.service.ts index 30b02b2cf2..42987419aa 100644 --- a/libs/shared/src/lib/services/form-helper/form-helper.service.ts +++ b/libs/shared/src/lib/services/form-helper/form-helper.service.ts @@ -281,30 +281,34 @@ export class FormHelpersService { data, }, }) - ).then((res) => { - // change the draftId to the new recordId - const newId = res.data?.addRecord?.id; - if (!newId) return; - updateIds[draftId](newId); - // update question.newCreatedRecords too - const isResource = element.question.getType() === 'resource'; - const draftIndex = ( - isResource - ? [element.question.newCreatedRecords] - : element.question.newCreatedRecords - ).indexOf(draftId); - if (draftIndex !== -1) { - if (isResource) { - element.question.newCreatedRecords = newId; - } else { - element.question.newCreatedRecords[draftIndex] = newId; + ) + .then((res) => { + // change the draftId to the new recordId + const newId = res.data?.addRecord?.id; + if (!newId) return; + updateIds[draftId](newId); + // update question.newCreatedRecords too + const isResource = element.question.getType() === 'resource'; + const draftIndex = ( + isResource + ? [element.question.newCreatedRecords] + : element.question.newCreatedRecords + ).indexOf(draftId); + if (draftIndex !== -1) { + if (isResource) { + element.question.newCreatedRecords = newId; + } else { + element.question.newCreatedRecords[draftIndex] = newId; + } } - } - // delete old temporary/draft record and data - this.deleteRecordDraft(draftId); - delete element.question.draftData[draftId]; - return; - }) + // delete old temporary/draft record and data + this.deleteRecordDraft(draftId); + delete element.question.draftData[draftId]; + return; + }) + .catch(() => { + return; + }) ); } } @@ -503,13 +507,8 @@ export class FormHelpersService { data: survey.data, }, }); - mutation.subscribe(({ errors }: any) => { - if (errors) { - survey.clear(false, true); - this.snackBar.openSnackBar(errorMessageFormatter(errors), { - error: true, - }); - } else { + mutation.subscribe({ + next: () => { // localStorage.removeItem(this.storageId); this.snackBar.openSnackBar( this.translate.instant('components.form.draftRecords.successEdit'), @@ -517,17 +516,24 @@ export class FormHelpersService { error: false, } ); - } - // Callback to emit save but stay in record addition mode - if (callback) { - callback({ - id: draftId, - save: { - completed: false, - hideNewRecord: true, - }, + + // Callback to emit save but stay in record addition mode + if (callback) { + callback({ + id: draftId, + save: { + completed: false, + hideNewRecord: true, + }, + }); + } + }, + error: (errors) => { + survey.clear(false, true); + this.snackBar.openSnackBar(errorMessageFormatter(errors), { + error: true, }); - } + }, }); } } @@ -546,10 +552,12 @@ export class FormHelpersService { id: draftId, }, }) - .subscribe(() => { - if (callback) { - callback(); - } + .subscribe({ + next: () => { + if (callback) { + callback(); + } + }, }); } diff --git a/libs/shared/src/lib/services/grid-layout/grid-layout.service.ts b/libs/shared/src/lib/services/grid-layout/grid-layout.service.ts index 36b161fd12..59e112b65d 100644 --- a/libs/shared/src/lib/services/grid-layout/grid-layout.service.ts +++ b/libs/shared/src/lib/services/grid-layout/grid-layout.service.ts @@ -60,8 +60,11 @@ export class GridLayoutService { first: options.first, }, }) - ).then(async ({ errors, data }) => { - if (errors) { + ) + .then(async ({ data }) => { + return data.resource.layouts || FALLBACK_LAYOUTS; + }) + .catch(async () => { return await firstValueFrom( this.apollo.query({ query: GET_GRID_FORM_META, @@ -71,17 +74,14 @@ export class GridLayoutService { first: options.first, }, }) - ).then((res2) => { - if (res2.errors) { - return FALLBACK_LAYOUTS; - } else { + ) + .then((res2) => { return res2.data.form.layouts || FALLBACK_LAYOUTS; - } - }); - } else { - return data.resource.layouts || FALLBACK_LAYOUTS; - } - }); + }) + .catch(() => { + return FALLBACK_LAYOUTS; + }); + }); } /** diff --git a/libs/shared/src/lib/services/map/map-layers.service.ts b/libs/shared/src/lib/services/map/map-layers.service.ts index e7ffa2ddcc..ee01887de5 100644 --- a/libs/shared/src/lib/services/map/map-layers.service.ts +++ b/libs/shared/src/lib/services/map/map-layers.service.ts @@ -36,7 +36,6 @@ import { omitBy, isNil, get } from 'lodash'; import { ContextService } from '../context/context.service'; import { DOCUMENT } from '@angular/common'; import { MapPolygonsService } from './map-polygons.service'; -import { errorMessageFormatter } from '../../utils/graphql/error-handler'; /** * Shared map layer service @@ -90,7 +89,7 @@ export class MapLayersService { map((response) => { return response.data?.addLayer; }), - catchError((errors) => throwError(() => errorMessageFormatter(errors))) + catchError((errors) => throwError(() => errors)) ); } @@ -119,7 +118,7 @@ export class MapLayersService { map((response) => { return response.data?.editLayer; }), - catchError((errors) => throwError(() => errorMessageFormatter(errors))) + catchError((errors) => throwError(() => errors)) ); } @@ -157,7 +156,7 @@ export class MapLayersService { map((response) => { return response.data.layer; }), - catchError((errors) => throwError(() => errorMessageFormatter(errors))) + catchError((errors) => throwError(() => errors)) ); } @@ -190,7 +189,7 @@ export class MapLayersService { map((response) => { return response.data.layers; }), - catchError((errors) => throwError(() => errorMessageFormatter(errors))) + catchError((errors) => throwError(() => errors)) ); } diff --git a/libs/shared/src/lib/services/map/map-polygons.service.ts b/libs/shared/src/lib/services/map/map-polygons.service.ts index 05ab52041a..ebebbaeb1f 100644 --- a/libs/shared/src/lib/services/map/map-polygons.service.ts +++ b/libs/shared/src/lib/services/map/map-polygons.service.ts @@ -44,14 +44,14 @@ export class MapPolygonsService { * Retrieve admin0 polygons */ public getAdmin0Polygons() { - this.restService - .get(`${this.restService.apiUrl}/gis/admin0`) - .subscribe((value) => { + this.restService.get(`${this.restService.apiUrl}/gis/admin0`).subscribe({ + next: (value) => { if (value) { this.admin0s = value; this.admin0sReady.next(true); } - }); + }, + }); } /** diff --git a/libs/shared/src/lib/services/notification/notification.service.ts b/libs/shared/src/lib/services/notification/notification.service.ts index 4fd48635dc..a85fee8bbb 100644 --- a/libs/shared/src/lib/services/notification/notification.service.ts +++ b/libs/shared/src/lib/services/notification/notification.service.ts @@ -74,27 +74,37 @@ export class NotificationService { }, }); - this.notificationsQuery.valueChanges.subscribe(({ data }) => { - this.updateValues(data); + this.notificationsQuery.valueChanges.subscribe({ + next: ({ data }) => { + this.updateValues(data); + }, + error: () => { + this.firstLoad = false; + }, }); this.apollo .subscribe({ query: NOTIFICATION_SUBSCRIPTION, }) - .subscribe(({ data }) => { - if (data && data.notification) { - // prevent new notification duplication - if (this.previousNotificationId !== data.notification.id) { - const notifications = this.notifications.getValue(); - if (notifications) { - this.notifications.next([data.notification, ...notifications]); - } else { - this.notifications.next([data.notification]); + .subscribe({ + next: ({ data }) => { + if (data && data.notification) { + // prevent new notification duplication + if (this.previousNotificationId !== data.notification.id) { + const notifications = this.notifications.getValue(); + if (notifications) { + this.notifications.next([ + data.notification, + ...notifications, + ]); + } else { + this.notifications.next([data.notification]); + } } + this.previousNotificationId = data.notification.id; } - this.previousNotificationId = data.notification.id; - } + }, }); } } @@ -113,13 +123,15 @@ export class NotificationService { id: notification.id, }, }) - .subscribe(({ data }) => { - if (data && data.seeNotification) { - const seeNotification = data.seeNotification; - this.notifications.next( - notifications.filter((x) => x.id !== seeNotification.id) - ); - } + .subscribe({ + next: ({ data }) => { + if (data && data.seeNotification) { + const seeNotification = data.seeNotification; + this.notifications.next( + notifications.filter((x) => x.id !== seeNotification.id) + ); + } + }, }); } @@ -135,8 +147,10 @@ export class NotificationService { ids: notificationsIds, }, }) - .subscribe(() => { - this.fetchMore(); + .subscribe({ + next: () => { + this.fetchMore(); + }, }); } diff --git a/libs/shared/src/lib/services/query-builder/query-builder.service.ts b/libs/shared/src/lib/services/query-builder/query-builder.service.ts index c6f1fcd4b0..91822136b1 100644 --- a/libs/shared/src/lib/services/query-builder/query-builder.service.ts +++ b/libs/shared/src/lib/services/query-builder/query-builder.service.ts @@ -118,10 +118,12 @@ export class QueryBuilderService { .query({ query: GET_QUERY_TYPES, }) - .subscribe(({ data }) => { - this.isDoneLoading.next(true); - this.availableQueries.next(data.types.availableQueries); - this.userFields = data.types.userFields; + .subscribe({ + next: ({ data }) => { + this.isDoneLoading.next(true); + this.availableQueries.next(data.types.availableQueries); + this.userFields = data.types.userFields; + }, }); } diff --git a/libs/shared/src/lib/services/workflow/workflow.service.ts b/libs/shared/src/lib/services/workflow/workflow.service.ts index ede0aa99b1..6462f9244a 100644 --- a/libs/shared/src/lib/services/workflow/workflow.service.ts +++ b/libs/shared/src/lib/services/workflow/workflow.service.ts @@ -62,8 +62,10 @@ export class WorkflowService { id, }, }) - .subscribe(({ data }) => { - this.workflow.next(data.workflow); + .subscribe({ + next: ({ data }) => { + this.workflow.next(data.workflow); + }, }); } @@ -146,25 +148,34 @@ export class WorkflowService { name: step.name, }, }) - .subscribe(({ errors, data }) => { - this.applicationService.handleEditionMutationResponse( - errors, - this.translate.instant('common.step.one'), - step.name - ); - if (!errors && data) { - const newWorkflow: Workflow = { - ...workflow, - steps: workflow.steps?.map((x) => { - if (x.id === step.id) { - x = { ...x, name: step.name }; - } - return x; - }), - }; - this.workflow.next(newWorkflow); - if (callback) callback(); - } + .subscribe({ + next: ({ data }) => { + this.applicationService.handleEditionMutationResponse( + [], + this.translate.instant('common.step.one'), + step.name + ); + if (data) { + const newWorkflow: Workflow = { + ...workflow, + steps: workflow.steps?.map((x) => { + if (x.id === step.id) { + x = { ...x, name: step.name }; + } + return x; + }), + }; + this.workflow.next(newWorkflow); + if (callback) callback(); + } + }, + error: (errors) => { + this.applicationService.handleEditionMutationResponse( + errors, + this.translate.instant('common.step.one'), + step.name + ); + }, }); } } @@ -187,25 +198,34 @@ export class WorkflowService { icon, }, }) - .subscribe(({ errors, data }) => { - this.applicationService.handleEditionMutationResponse( - errors, - this.translate.instant('common.step.one'), - step.name - ); - if (!errors && data) { - const newWorkflow: Workflow = { - ...workflow, - steps: workflow.steps?.map((x) => { - if (x.id === step.id) { - x = { ...x, icon: data.editStep.icon }; - } - return x; - }), - }; - this.workflow.next(newWorkflow); - if (callback) callback(); - } + .subscribe({ + next: ({ data }) => { + this.applicationService.handleEditionMutationResponse( + [], + this.translate.instant('common.step.one'), + step.name + ); + if (data) { + const newWorkflow: Workflow = { + ...workflow, + steps: workflow.steps?.map((x) => { + if (x.id === step.id) { + x = { ...x, icon: data.editStep.icon }; + } + return x; + }), + }; + this.workflow.next(newWorkflow); + if (callback) callback(); + } + }, + error: (errors) => { + this.applicationService.handleEditionMutationResponse( + errors, + this.translate.instant('common.step.one'), + step.name + ); + }, }); } } @@ -228,19 +248,27 @@ export class WorkflowService { permissions, }, }) - .subscribe(({ errors, data }) => { - this.applicationService.handleEditionMutationResponse( - errors, - this.translate.instant('common.step.one') - ); - if (!errors && data) { - const newWorkflow: Workflow = { - ...workflow, - permissions: data.editStep.permissions, - }; - this.workflow.next(newWorkflow); - if (callback) callback(data.editStep.permissions); - } + .subscribe({ + next: ({ data }) => { + this.applicationService.handleEditionMutationResponse( + [], + this.translate.instant('common.step.one') + ); + if (data) { + const newWorkflow: Workflow = { + ...workflow, + permissions: data.editStep.permissions, + }; + this.workflow.next(newWorkflow); + if (callback) callback(data.editStep.permissions); + } + }, + error: (errors) => { + this.applicationService.handleEditionMutationResponse( + errors, + this.translate.instant('common.step.one') + ); + }, }); } } diff --git a/libs/shared/src/lib/survey/components/application-dropdown/application-dropdown.component.ts b/libs/shared/src/lib/survey/components/application-dropdown/application-dropdown.component.ts index c75cc7af2f..e446f32268 100644 --- a/libs/shared/src/lib/survey/components/application-dropdown/application-dropdown.component.ts +++ b/libs/shared/src/lib/survey/components/application-dropdown/application-dropdown.component.ts @@ -119,10 +119,12 @@ export class ApplicationDropdownComponent }, }) .pipe(takeUntil(this.destroy$)) - .subscribe(({ data }) => { - this.selectedApplications = data.applications.edges.map( - (x) => x.node - ); + .subscribe({ + next: ({ data }) => { + this.selectedApplications = data.applications.edges.map( + (x) => x.node + ); + }, }); } @@ -139,8 +141,13 @@ export class ApplicationDropdownComponent this.applications$ = this.applications.asObservable(); this.applicationsQuery.valueChanges .pipe(takeUntil(this.destroy$)) - .subscribe(({ data, loading }) => { - this.updateValues(data, loading); + .subscribe({ + next: ({ data, loading }) => { + this.updateValues(data, loading); + }, + error: () => { + this.loading = false; + }, }); } diff --git a/libs/shared/src/lib/survey/components/owner.ts b/libs/shared/src/lib/survey/components/owner.ts index 64845fd1e8..3d4ad455a6 100644 --- a/libs/shared/src/lib/survey/components/owner.ts +++ b/libs/shared/src/lib/survey/components/owner.ts @@ -56,14 +56,16 @@ export const init = ( applications: question.applications, }, }) - .subscribe(({ data }) => { - if (data.rolesFromApplications) { - const roles = []; - for (const role of data.rolesFromApplications) { - roles.push({ value: role.id, text: role.title }); + .subscribe({ + next: ({ data }) => { + if (data.rolesFromApplications) { + const roles = []; + for (const role of data.rolesFromApplications) { + roles.push({ value: role.id, text: role.title }); + } + question.contentQuestion.choices = roles; } - question.contentQuestion.choices = roles; - } + }, }); }, // eslint-disable-next-line @typescript-eslint/no-empty-function diff --git a/libs/shared/src/lib/survey/components/resource-available-fields/config-display-grid-fields-modal/config-display-grid-fields-modal.component.ts b/libs/shared/src/lib/survey/components/resource-available-fields/config-display-grid-fields-modal/config-display-grid-fields-modal.component.ts index 74998c3c2d..52047a40f0 100644 --- a/libs/shared/src/lib/survey/components/resource-available-fields/config-display-grid-fields-modal/config-display-grid-fields-modal.component.ts +++ b/libs/shared/src/lib/survey/components/resource-available-fields/config-display-grid-fields-modal/config-display-grid-fields-modal.component.ts @@ -75,24 +75,29 @@ export class ConfigDisplayGridFieldsModalComponent ngOnInit(): void { this.queryBuilder.availableQueries$ .pipe(takeUntil(this.destroy$)) - .subscribe((res) => { - if (res.length > 0) { - const hasDataForm = this.data.form !== null; - const queryName = hasDataForm - ? this.data.form.value.name - : this.queryBuilder.getQueryNameFromResourceName( - this.data.resourceName - ); + .subscribe({ + next: (res) => { + if (res.length > 0) { + const hasDataForm = this.data.form !== null; + const queryName = hasDataForm + ? this.data.form.value.name + : this.queryBuilder.getQueryNameFromResourceName( + this.data.resourceName + ); - this.form = createQueryForm({ - name: queryName, - fields: hasDataForm ? this.data.form.value.fields : [], - sort: hasDataForm ? this.data.form.value.sort : {}, - filter: hasDataForm ? this.data.form.value.filter : {}, - }); + this.form = createQueryForm({ + name: queryName, + fields: hasDataForm ? this.data.form.value.fields : [], + sort: hasDataForm ? this.data.form.value.sort : {}, + filter: hasDataForm ? this.data.form.value.filter : {}, + }); + this.loading = false; + } + }, + error: () => { this.loading = false; - } + }, }); } } diff --git a/libs/shared/src/lib/survey/components/resource-dropdown/resource-dropdown.component.ts b/libs/shared/src/lib/survey/components/resource-dropdown/resource-dropdown.component.ts index 7f74858dd0..8daf0851af 100644 --- a/libs/shared/src/lib/survey/components/resource-dropdown/resource-dropdown.component.ts +++ b/libs/shared/src/lib/survey/components/resource-dropdown/resource-dropdown.component.ts @@ -69,10 +69,12 @@ export class ResourceDropdownComponent id: this.model.value, }, }) - .subscribe(({ data }) => { - if (data.resource) { - this.selectedResource = data.resource; - } + .subscribe({ + next: ({ data }) => { + if (data.resource) { + this.selectedResource = data.resource; + } + }, }); } } diff --git a/libs/shared/src/lib/survey/components/resource.ts b/libs/shared/src/lib/survey/components/resource.ts index c99cefc564..6e46617554 100644 --- a/libs/shared/src/lib/survey/components/resource.ts +++ b/libs/shared/src/lib/survey/components/resource.ts @@ -183,16 +183,18 @@ export const init = ( visibleIndex: 3, choices: (obj: QuestionResource, choicesCallback: any) => { if (obj.resource) { - getResourceById({ id: obj.resource }).subscribe(({ data }) => { - const choices = (data.resource.fields || []) - .filter((item: any) => item.type !== 'matrix') - .map((item: any) => { - return { - value: item.name, - }; - }); - choices.unshift({ value: null }); - choicesCallback(choices); + getResourceById({ id: obj.resource }).subscribe({ + next: ({ data }) => { + const choices = (data.resource.fields || []) + .filter((item: any) => item.type !== 'matrix') + .map((item: any) => { + return { + value: item.name, + }; + }); + choices.unshift({ value: null }); + choicesCallback(choices); + }, }); } }, @@ -272,12 +274,14 @@ export const init = ( visibleIndex: 3, choices: (obj: QuestionResource, choicesCallback: any) => { if (obj.resource && obj.addRecord) { - getResourceById({ id: obj.resource }).subscribe(({ data }) => { - const choices = (data.resource.forms || []).map((item: any) => { - return { value: item.id, text: item.name }; - }); - choices.unshift({ value: null, text: '' }); - choicesCallback(choices); + getResourceById({ id: obj.resource }).subscribe({ + next: ({ data }) => { + const choices = (data.resource.forms || []).map((item: any) => { + return { value: item.id, text: item.name }; + }); + choices.unshift({ value: null, text: '' }); + choicesCallback(choices); + }, }); } }, @@ -336,11 +340,15 @@ export const init = ( !!obj && !!obj.selectQuestion && !!obj.displayField, choices: (obj: QuestionResource, choicesCallback: any) => { if (obj.resource) { - getResourceById({ id: obj.resource }).subscribe(({ data }) => { - const choices = (data.resource.fields || []).map((item: any) => { - return { value: item.name }; - }); - choicesCallback(choices); + getResourceById({ id: obj.resource }).subscribe({ + next: ({ data }) => { + const choices = (data.resource.fields || []).map( + (item: any) => { + return { value: item.name }; + } + ); + choicesCallback(choices); + }, }); } }, diff --git a/libs/shared/src/lib/survey/components/resources.ts b/libs/shared/src/lib/survey/components/resources.ts index 9c71e4dc6a..7f2f6e26a8 100644 --- a/libs/shared/src/lib/survey/components/resources.ts +++ b/libs/shared/src/lib/survey/components/resources.ts @@ -164,14 +164,16 @@ export const init = ( visibleIndex: 3, choices: (obj: any, choicesCallback: any) => { if (obj.resource) { - getResourceById({ id: obj.resource }).subscribe(({ data }) => { - const choices = (data.resource.fields || []) - .filter((item: any) => item.type !== 'matrix') - .map((item: any) => { - return { value: item.name }; - }); - choices.unshift({ value: null }); - choicesCallback(choices); + getResourceById({ id: obj.resource }).subscribe({ + next: ({ data }) => { + const choices = (data.resource.fields || []) + .filter((item: any) => item.type !== 'matrix') + .map((item: any) => { + return { value: item.name }; + }); + choices.unshift({ value: null }); + choicesCallback(choices); + }, }); } }, @@ -306,12 +308,14 @@ export const init = ( visibleIndex: 3, choices: (obj: any, choicesCallback: any) => { if (obj.resource && obj.addRecord) { - getResourceById({ id: obj.resource }).subscribe(({ data }) => { - const choices = (data.resource.forms || []).map((item: any) => { - return { value: item.id, text: item.name }; - }); - choices.unshift({ value: null, text: '' }); - choicesCallback(choices); + getResourceById({ id: obj.resource }).subscribe({ + next: ({ data }) => { + const choices = (data.resource.forms || []).map((item: any) => { + return { value: item.id, text: item.name }; + }); + choices.unshift({ value: null, text: '' }); + choicesCallback(choices); + }, }); } }, @@ -379,11 +383,15 @@ export const init = ( visibleIf: (obj: any) => obj.selectQuestion && obj.displayField, choices: (obj: any, choicesCallback: any) => { if (obj.resource) { - getResourceById({ id: obj.resource }).subscribe(({ data }) => { - const choices = (data.resource.fields || []).map((item: any) => { - return { value: item.name }; - }); - choicesCallback(choices); + getResourceById({ id: obj.resource }).subscribe({ + next: ({ data }) => { + const choices = (data.resource.fields || []).map( + (item: any) => { + return { value: item.name }; + } + ); + choicesCallback(choices); + }, }); } }, @@ -504,13 +512,15 @@ export const init = ( this.populateChoices(question); } } - getResourceById({ id: question.resource }).subscribe(({ data }) => { - // const choices = mapQuestionChoices(data, question); - // question.contentQuestion.choices = choices; - if (!question.placeholder) { - question.contentQuestion.optionsCaption = - 'Select a record from ' + data.resource.name + '...'; - } + getResourceById({ id: question.resource }).subscribe({ + next: ({ data }) => { + // const choices = mapQuestionChoices(data, question); + // question.contentQuestion.choices = choices; + if (!question.placeholder) { + question.contentQuestion.optionsCaption = + 'Select a record from ' + data.resource.name + '...'; + } + }, }); if (question.selectQuestion) { if (question.selectQuestion === '#staticValue') { diff --git a/libs/shared/src/lib/survey/components/test-service-dropdown/test-service-dropdown.component.ts b/libs/shared/src/lib/survey/components/test-service-dropdown/test-service-dropdown.component.ts index 75e94e0ab1..1788222e97 100644 --- a/libs/shared/src/lib/survey/components/test-service-dropdown/test-service-dropdown.component.ts +++ b/libs/shared/src/lib/survey/components/test-service-dropdown/test-service-dropdown.component.ts @@ -113,10 +113,12 @@ export class TestServiceDropdownComponent id: this.model.value, }, }) - .subscribe(({ data }) => { - if (data) { - this.selectedRecord = data.record; - } + .subscribe({ + next: ({ data }) => { + if (data) { + this.selectedRecord = data.record; + } + }, }); } if (this.resource) { diff --git a/libs/shared/src/lib/survey/components/users-dropdown/users-dropdown.component.ts b/libs/shared/src/lib/survey/components/users-dropdown/users-dropdown.component.ts index fa624bfb64..7e2de85038 100644 --- a/libs/shared/src/lib/survey/components/users-dropdown/users-dropdown.component.ts +++ b/libs/shared/src/lib/survey/components/users-dropdown/users-dropdown.component.ts @@ -112,10 +112,12 @@ export class UsersDropdownComponent }, }) .pipe(takeUntil(this.destroy$)) - .subscribe(({ data }) => { - if (data.users) { - this.initialSelection = data.users.edges.map((x) => x.node); - } + .subscribe({ + next: ({ data }) => { + if (data.users) { + this.initialSelection = data.users.edges.map((x) => x.node); + } + }, }); } diff --git a/libs/shared/src/lib/utils/graphql/error-handler.ts b/libs/shared/src/lib/utils/graphql/error-handler.ts index d00765a0a7..4af01db4ed 100644 --- a/libs/shared/src/lib/utils/graphql/error-handler.ts +++ b/libs/shared/src/lib/utils/graphql/error-handler.ts @@ -1,4 +1,5 @@ import { ApolloLink, Observable } from '@apollo/client'; +import { isNil } from 'lodash'; /** * Gets the message in the graphql error @@ -6,8 +7,22 @@ import { ApolloLink, Observable } from '@apollo/client'; * @param errors GraphQL error * @returns formatted message */ -export const errorMessageFormatter = (errors: any): string => - (errors.networkError || errors)?.[0].message ?? ''; +export const errorMessageFormatter = (errors: any): string => { + let messages = []; + if (errors.networkError.length) { + messages = errors.networkError.map((x: any) => x.message); + } + if (errors.protocolErrors.length) { + messages = errors.protocolErrors.map((x: any) => x.message); + } + if (errors.clientErrors.length) { + messages = errors.clientErrors.map((x: any) => x.message); + } + if (errors.graphQLErrors.length) { + messages = errors.graphQLErrors.map((x: any) => x.message); + } + return messages.join(', '); +}; /** * Create apollo link to handle any incoming graphQL error @@ -20,17 +35,36 @@ export const createGraphQlErrorHandler = (errorCallback: any) => return new Observable((observer) => { const observable = forward(operation); const subscription = observable.subscribe({ + /** + * Handle successful request + * + * @param value Value sent from the GraphQL request + */ next(value) { - if (value.errors) { + if ( + value.errors && + // And all involved data in the request are nullish + Object.keys(value.data ?? {}).every((key) => + isNil(value.data?.[key]) + ) + ) { observer.error(value.errors); } else { observer.next(value); } }, + /** + * Handle error request + * + * @param networkError Error sent from GraphQL request + */ error(networkError) { - errorCallback({ networkError, operation }); + errorCallback(networkError); observer.error(networkError); }, + /** + * Complete given observable by default + */ complete() { observer.complete(); }, diff --git a/libs/shared/src/lib/views/application-users/components/user-list/user-list.component.ts b/libs/shared/src/lib/views/application-users/components/user-list/user-list.component.ts index 72b0964583..d3a05da64b 100644 --- a/libs/shared/src/lib/views/application-users/components/user-list/user-list.component.ts +++ b/libs/shared/src/lib/views/application-users/components/user-list/user-list.component.ts @@ -141,8 +141,14 @@ export class UserListComponent }); this.usersQuery.valueChanges .pipe(takeUntil(this.destroy$)) - .subscribe(({ data, loading }) => { - this.updateValues(data, loading); + .subscribe({ + next: ({ data, loading }) => { + this.updateValues(data, loading); + }, + error: () => { + this.loading.next(false); + this.updating = false; + }, }); } }); diff --git a/libs/ui/src/lib/graphql-select/graphql-select.component.ts b/libs/ui/src/lib/graphql-select/graphql-select.component.ts index 4cfad79c00..d65fb81b9c 100644 --- a/libs/ui/src/lib/graphql-select/graphql-select.component.ts +++ b/libs/ui/src/lib/graphql-select/graphql-select.component.ts @@ -306,9 +306,14 @@ export class GraphQLSelectComponent if (this.query) { this.query.valueChanges .pipe(takeUntil(this.queryChange$), takeUntil(this.destroy$)) - .subscribe(({ data, loading }) => { - this.queryName = Object.keys(data)[0]; - this.updateValues(data, loading); + .subscribe({ + next: ({ data, loading }) => { + this.queryName = Object.keys(data)[0]; + this.updateValues(data, loading); + }, + error: () => { + this.loading = false; + }, }); } this.ngControl?.valueChanges @@ -370,9 +375,14 @@ export class GraphQLSelectComponent // Subscribe to the new query this.query.valueChanges .pipe(takeUntil(this.queryChange$), takeUntil(this.destroy$)) - .subscribe(({ data, loading }) => { - this.queryName = Object.keys(data)[0]; - this.updateValues(data, loading); + .subscribe({ + next: ({ data, loading }) => { + this.queryName = Object.keys(data)[0]; + this.updateValues(data, loading); + }, + error: () => { + this.loading = false; + }, }); } else { const elements = this.elements.getValue(); From d9637ffcfd31bd59027a3d2f16fcfa78e7c72392 Mon Sep 17 00:00:00 2001 From: Unai Zalba Date: Tue, 12 Mar 2024 16:03:08 +0100 Subject: [PATCH 5/5] refactor/AB#82357_create-shared-error-handler-logic-for-the-app fix: linting --- .../resource/aggregations-tab/aggregations-tab.component.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/back-office/src/app/dashboard/pages/resource/aggregations-tab/aggregations-tab.component.ts b/apps/back-office/src/app/dashboard/pages/resource/aggregations-tab/aggregations-tab.component.ts index 021248e628..dd3a784913 100644 --- a/apps/back-office/src/app/dashboard/pages/resource/aggregations-tab/aggregations-tab.component.ts +++ b/apps/back-office/src/app/dashboard/pages/resource/aggregations-tab/aggregations-tab.component.ts @@ -8,7 +8,6 @@ import { Resource, ResourceQueryResponse, UnsubscribeComponent, - errorMessageFormatter, getCachedValues, updateQueryUniqueValues, } from '@oort-front/shared';