diff --git a/src/portal/lib/src/config/gc/gc.component.ts b/src/portal/lib/src/config/gc/gc.component.ts index c0e7a27e4..dc6d7bb19 100644 --- a/src/portal/lib/src/config/gc/gc.component.ts +++ b/src/portal/lib/src/config/gc/gc.component.ts @@ -53,6 +53,9 @@ export class GcComponent implements OnInit { this.gcRepoService.getSchedule().subscribe(schedule => { this.initSchedule(schedule); this.loadingGcStatus.emit(false); + }, error => { + this.errorHandler.error(error); + this.loadingGcStatus.emit(false); }); } diff --git a/src/portal/lib/src/config/vulnerability/vulnerability-config.component.ts b/src/portal/lib/src/config/vulnerability/vulnerability-config.component.ts index c9f8c9bbb..15932c607 100644 --- a/src/portal/lib/src/config/vulnerability/vulnerability-config.component.ts +++ b/src/portal/lib/src/config/vulnerability/vulnerability-config.component.ts @@ -90,6 +90,9 @@ export class VulnerabilityConfigComponent implements OnInit { this.initSchedule(schedule); this.onGoing = false; this.loadingStatus.emit(this.onGoing); + }, error => { + this.errorHandler.error(error); + this.loadingStatus.emit(this.onGoing); }); } diff --git a/src/portal/lib/src/endpoint/endpoint.component.ts b/src/portal/lib/src/endpoint/endpoint.component.ts index 15ab9a8db..a8feb0a9e 100644 --- a/src/portal/lib/src/endpoint/endpoint.component.ts +++ b/src/portal/lib/src/endpoint/endpoint.component.ts @@ -40,6 +40,7 @@ import { import { CreateEditEndpointComponent } from "../create-edit-endpoint/create-edit-endpoint.component"; import { CustomComparator } from "../utils"; +import { errorHandler as errorHandFn } from "../shared/shared.utils"; import { operateChanges, OperateInfo, OperationState } from "../operation/operate"; import { OperationService } from "../operation/operation.service"; @@ -80,7 +81,7 @@ export class EndpointComponent implements OnInit, OnDestroy { access_key: "", access_secret: "", type: "" - }, + }, description: "", insecure: false, name: "", @@ -210,17 +211,13 @@ export class EndpointComponent implements OnInit, OnDestroy { }); }) , catchError(error => { - if (error && error._body) { - const message = JSON.parse(error._body).message; - operateChanges(operMessage, OperationState.failure, message); - return observableThrowError(message); - } else { - return this.translateService.get('BATCH.DELETED_FAILURE').pipe(map(res => { - operateChanges(operMessage, OperationState.failure, res); - })); - } + const message = errorHandFn(error); + this.translateService.get(message).subscribe(res => + operateChanges(operMessage, OperationState.failure, res) + ); + return observableThrowError(message); } - )); + )); } // Forcely refresh the view diff --git a/src/portal/lib/src/label/label.component.ts b/src/portal/lib/src/label/label.component.ts index 9aaec0101..406028561 100644 --- a/src/portal/lib/src/label/label.component.ts +++ b/src/portal/lib/src/label/label.component.ts @@ -35,6 +35,7 @@ import { ConfirmationDialogComponent } from "../confirmation-dialog/confirmation import { operateChanges, OperateInfo, OperationState } from "../operation/operate"; import { OperationService } from "../operation/operation.service"; import { map, catchError } from "rxjs/operators"; +import { errorHandler as errorHandFn } from "../shared/shared.utils"; import { Observable, throwError as observableThrowError, forkJoin } from "rxjs"; @Component({ selector: "hbr-label", @@ -162,11 +163,13 @@ export class LabelComponent implements OnInit { .subscribe(res => { operateChanges(operMessage, OperationState.success); }); - }), catchError( error => { - return this.translateService.get('BATCH.DELETED_FAILURE').pipe(map(res => { - operateChanges(operMessage, OperationState.failure, res); - })); - })); + }), catchError(error => { + const message = errorHandFn(error); + this.translateService.get(message).subscribe(res => + operateChanges(operMessage, OperationState.failure, res) + ); + return observableThrowError(message); + })); } // Forcely refresh the view diff --git a/src/portal/lib/src/list-replication-rule/list-replication-rule.component.ts b/src/portal/lib/src/list-replication-rule/list-replication-rule.component.ts index 18d2ec493..e033081a2 100644 --- a/src/portal/lib/src/list-replication-rule/list-replication-rule.component.ts +++ b/src/portal/lib/src/list-replication-rule/list-replication-rule.component.ts @@ -46,6 +46,8 @@ import { ErrorHandler } from "../error-handler/error-handler"; import { CustomComparator } from "../utils"; import { operateChanges, OperateInfo, OperationState } from "../operation/operate"; import { OperationService } from "../operation/operation.service"; +import { errorHandler as errorHandFn } from "../shared/shared.utils"; + const jobstatus = "InProgress"; @Component({ @@ -131,7 +133,7 @@ export class ListReplicationRuleComponent implements OnInit, OnChanges { retrieveRules(ruleName = ""): void { this.loading = true; /*this.selectedRow = null;*/ - this.replicationService.getReplicationRules(this.projectId, ruleName) + this.replicationService.getReplicationRules(this.projectId, ruleName) .subscribe(rules => { this.rules = rules || []; // job list hidden @@ -220,18 +222,12 @@ export class ListReplicationRuleComponent implements OnInit, OnChanges { this.translateService.get('BATCH.DELETED_SUCCESS') .subscribe(res => operateChanges(operMessage, OperationState.success)); }) - , catchError(error => { - if (error && error._body) { - const message = JSON.parse(error._body).message; - operateChanges(operMessage, OperationState.failure, message); - return observableThrowError(message); - } else { - return this.translateService.get("BATCH.DELETED_FAILURE").pipe( - map(res => { - operateChanges(operMessage, OperationState.failure, res); - }) + , catchError(error => { + const message = errorHandFn(error); + this.translateService.get(message).subscribe(res => + operateChanges(operMessage, OperationState.failure, res) ); - } - })); + return observableThrowError(message); + })); } } diff --git a/src/portal/lib/src/replication/replication.component.ts b/src/portal/lib/src/replication/replication.component.ts index e75c58b87..de5ba5b71 100644 --- a/src/portal/lib/src/replication/replication.component.ts +++ b/src/portal/lib/src/replication/replication.component.ts @@ -60,6 +60,7 @@ import { } from "../operation/operate"; import { OperationService } from "../operation/operation.service"; import { Router } from "@angular/router"; +import { errorHandler as errorHandFn } from "../shared/shared.utils"; const ONE_HOUR_SECONDS: number = 3600; const ONE_MINUTE_SECONDS: number = 60; const ONE_DAY_SECONDS: number = 24 * ONE_HOUR_SECONDS; @@ -151,7 +152,7 @@ export class ReplicationComponent implements OnInit, OnDestroy { private replicationService: ReplicationService, private operationService: OperationService, private translateService: TranslateService - ) {} + ) { } public get showPaginationIndex(): boolean { return this.totalCount > 0; @@ -327,23 +328,11 @@ export class ReplicationComponent implements OnInit, OnDestroy { ); }), catchError(error => { - if (error && error.status === 504) { - return this.translateService.get("BATCH.TIME_OUT").pipe( - map(res => { - operateChanges(operMessage, OperationState.failure, res); - }) - ); - } else if (error && error._body) { - const message = JSON.parse(error._body).message; - operateChanges(operMessage, OperationState.failure, message); - return observableThrowError(message); - } else { - return this.translateService.get("BATCH.REPLICATE_FAILURE").pipe( - map(res => { - operateChanges(operMessage, OperationState.failure, res); - }) - ); - } + const message = errorHandFn(error); + this.translateService.get(message).subscribe(res => + operateChanges(operMessage, OperationState.failure, res) + ); + return observableThrowError(message); }) ); } @@ -417,7 +406,7 @@ export class ReplicationComponent implements OnInit, OnDestroy { this.selectedRow = []; }) ) - .subscribe(() => {}); + .subscribe(() => { }); } } @@ -440,17 +429,11 @@ export class ReplicationComponent implements OnInit, OnDestroy { ); }), catchError(error => { - if (error && error._body) { - const message = JSON.parse(error._body).message; - operateChanges(operMessage, OperationState.failure, message); - return observableThrowError(message); - } else { - return this.translateService.get("BATCH.STOP_FAILURE").pipe( - map(res => { - operateChanges(operMessage, OperationState.failure, res); - }) - ); - } + const message = errorHandFn(error); + this.translateService.get(message).subscribe(res => + operateChanges(operMessage, OperationState.failure, res) + ); + return observableThrowError(message); }) ); } diff --git a/src/portal/lib/src/repository-gridview/repository-gridview.component.ts b/src/portal/lib/src/repository-gridview/repository-gridview.component.ts index 60a0b2103..074bea76e 100644 --- a/src/portal/lib/src/repository-gridview/repository-gridview.component.ts +++ b/src/portal/lib/src/repository-gridview/repository-gridview.component.ts @@ -41,6 +41,7 @@ import { OperateInfo, OperationState, operateChanges } from "../operation/operat import { SERVICE_CONFIG, IServiceConfig } from '../service.config'; import { map, catchError } from "rxjs/operators"; import { Observable, throwError as observableThrowError } from "rxjs"; +import { errorHandler as errorHandFn } from "../shared/shared.utils"; @Component({ selector: "hbr-repository-gridview", templateUrl: "./repository-gridview.component.html", @@ -212,21 +213,11 @@ export class RepositoryGridviewComponent implements OnChanges, OnInit { operateChanges(operMessage, OperationState.success); }); }), catchError(error => { - if (error.status === "412") { - return forkJoin(this.translateService.get('BATCH.DELETED_FAILURE'), - this.translateService.get('REPOSITORY.TAGS_SIGNED')).pipe(map(res => { - operateChanges(operMessage, OperationState.failure, res[1]); - })); - } - if (error.status === 503) { - return forkJoin(this.translateService.get('BATCH.DELETED_FAILURE'), - this.translateService.get('REPOSITORY.TAGS_NO_DELETE')).pipe(map(res => { - operateChanges(operMessage, OperationState.failure, res[1]); - })); - } - return this.translateService.get('BATCH.DELETED_FAILURE').pipe(map(res => { - operateChanges(operMessage, OperationState.failure, res); - })); + const message = errorHandFn(error); + this.translateService.get(message).subscribe(res => + operateChanges(operMessage, OperationState.failure, res) + ); + return observableThrowError(message); })); } } diff --git a/src/portal/lib/src/shared/shared.utils.ts b/src/portal/lib/src/shared/shared.utils.ts index 3c9efed7b..eb988a702 100644 --- a/src/portal/lib/src/shared/shared.utils.ts +++ b/src/portal/lib/src/shared/shared.utils.ts @@ -23,9 +23,11 @@ export const errorHandler = function (error: any): string { if (!error) { return "UNKNOWN_ERROR"; } - - if (error && error._body) { - return error._body; + try { + return JSON.parse(error._body).message; + } catch (err) { } + if (error._body && error._body.message) { + return error._body.message; } if (!(error.statusCode || error.status)) { @@ -52,7 +54,6 @@ export const errorHandler = function (error: any): string { } } }; - export const extractJson = (res: Response) => { if (res.text() === '') { return []; diff --git a/src/portal/lib/src/tag/tag.component.ts b/src/portal/lib/src/tag/tag.component.ts index dc4cbc615..85cd912c2 100644 --- a/src/portal/lib/src/tag/tag.component.ts +++ b/src/portal/lib/src/tag/tag.component.ts @@ -59,6 +59,7 @@ import { operateChanges, OperateInfo, OperationState } from "../operation/operat import { OperationService } from "../operation/operation.service"; import { ImageNameInputComponent } from "../image-name-input/image-name-input.component"; import { map, catchError } from "rxjs/operators"; +import { errorHandler as errorHandFn } from "../shared/shared.utils"; import { Observable, throwError as observableThrowError } from "rxjs"; export interface LabelState { iconsShow: boolean; @@ -213,7 +214,7 @@ export class TagComponent implements OnInit, AfterViewInit { } }); - this.getImagePermissionRule(this.projectId); + this.getImagePermissionRule(this.projectId); } ngAfterViewInit() { @@ -668,15 +669,11 @@ export class TagComponent implements OnInit, AfterViewInit { operateChanges(operMessage, OperationState.success); }); }), catchError(error => { - if (error.status === 503) { - return forkJoin(this.translateService.get('BATCH.DELETED_FAILURE'), - this.translateService.get('REPOSITORY.TAGS_NO_DELETE')).pipe(map(res => { - operateChanges(operMessage, OperationState.failure, res[1]); - })); - } - return this.translateService.get("BATCH.DELETED_FAILURE").pipe(map(res => { - operateChanges(operMessage, OperationState.failure, res); - })); + const message = errorHandFn(error); + this.translateService.get(message).subscribe(res => + operateChanges(operMessage, OperationState.failure, res) + ); + return observableThrowError(message); })); } } @@ -751,12 +748,12 @@ export class TagComponent implements OnInit, AfterViewInit { let hasScanImagePermission = this.userPermissionService.getPermission(projectId, USERSTATICPERMISSION.REPOSITORY_TAG_SCAN_JOB.KEY, USERSTATICPERMISSION.REPOSITORY_TAG_SCAN_JOB.VALUE.CREATE); forkJoin(hasAddLabelImagePermission, hasRetagImagePermission, hasDeleteImagePermission, hasScanImagePermission) - .subscribe(permissions => { - this.hasAddLabelImagePermission = permissions[0] as boolean; - this.hasRetagImagePermission = permissions[1] as boolean; - this.hasDeleteImagePermission = permissions[2] as boolean; - this.hasScanImagePermission = permissions[3] as boolean; - }, error => this.errorHandler.error(error) ); + .subscribe(permissions => { + this.hasAddLabelImagePermission = permissions[0] as boolean; + this.hasRetagImagePermission = permissions[1] as boolean; + this.hasDeleteImagePermission = permissions[2] as boolean; + this.hasScanImagePermission = permissions[3] as boolean; + }, error => this.errorHandler.error(error)); } // Trigger scan scanNow(t: Tag[]): void { diff --git a/src/portal/src/app/group/group.component.ts b/src/portal/src/app/group/group.component.ts index f833de146..b447ed5dc 100644 --- a/src/portal/src/app/group/group.component.ts +++ b/src/portal/src/app/group/group.component.ts @@ -1,10 +1,10 @@ -import {of, Subscription, forkJoin } from "rxjs"; +import { of, Subscription, forkJoin } from "rxjs"; import { flatMap, catchError } from "rxjs/operators"; import { SessionService } from "./../shared/session.service"; import { TranslateService } from "@ngx-translate/core"; import { Component, OnInit, ViewChild, OnDestroy } from "@angular/core"; -import {operateChanges, OperateInfo, OperationService, OperationState} from "@harbor/ui"; +import { operateChanges, OperateInfo, OperationService, OperationState } from "@harbor/ui"; import { ConfirmationTargets, @@ -17,7 +17,8 @@ import { AddGroupModalComponent } from "./add-group-modal/add-group-modal.compon import { UserGroup } from "./group"; import { GroupService } from "./group.service"; import { MessageHandlerService } from "../shared/message-handler/message-handler.service"; - +import { errorHandler as errorHandFn } from "../shared/shared.utils"; +import { Observable, throwError as observableThrowError } from "rxjs"; @Component({ selector: "app-group", templateUrl: "./group.component.html", @@ -43,8 +44,9 @@ export class GroupComponent implements OnInit, OnDestroy { private operateDialogService: ConfirmationDialogService, private groupService: GroupService, private msgHandler: MessageHandlerService, - private session: SessionService - ) {} + private session: SessionService, + private translateService: TranslateService, + ) { } ngOnInit() { this.loadData(); @@ -74,9 +76,9 @@ export class GroupComponent implements OnInit, OnDestroy { this.loading = true; this.groupService.getUserGroups().subscribe(groups => { this.groups = groups.filter(group => { - if (!group.group_name) {group.group_name = ''; } + if (!group.group_name) { group.group_name = ''; } return group.group_name.includes(this.searchTerm); - } + } ); this.loading = false; }); @@ -128,11 +130,12 @@ export class GroupComponent implements OnInit, OnDestroy { return of(res); })); })) - .pipe(catchError(err => { - return this.translate.get("BATCH.DELETED_FAILURE").pipe(flatMap(res => { - operateChanges(operMessage, OperationState.failure, res); - return of(res); - })); + .pipe(catchError(error => { + const message = errorHandFn(error); + this.translateService.get(message).subscribe(res => + operateChanges(operMessage, OperationState.failure, res) + ); + return observableThrowError(message); })); }); @@ -147,7 +150,7 @@ export class GroupComponent implements OnInit, OnDestroy { } groupToSring(type: number) { - if (type === 1) {return 'GROUP.LDAP_TYPE'; } else {return 'UNKNOWN'; } + if (type === 1) { return 'GROUP.LDAP_TYPE'; } else { return 'UNKNOWN'; } } doFilter(groupName: string): void { diff --git a/src/portal/src/app/project/helm-chart/list-chart-versions/helm-chart-versions-detail/helm-chart-version.component.ts b/src/portal/src/app/project/helm-chart/list-chart-versions/helm-chart-versions-detail/helm-chart-version.component.ts index da6491097..887fe74ea 100644 --- a/src/portal/src/app/project/helm-chart/list-chart-versions/helm-chart-versions-detail/helm-chart-version.component.ts +++ b/src/portal/src/app/project/helm-chart/list-chart-versions/helm-chart-versions-detail/helm-chart-version.component.ts @@ -8,8 +8,8 @@ import { Output, EventEmitter } from "@angular/core"; -import { Observable, forkJoin } from "rxjs"; -import { finalize, map } from "rxjs/operators"; +import { Observable, forkJoin, throwError as observableThrowError } from "rxjs"; +import { finalize, map, catchError } from "rxjs/operators"; import { TranslateService } from "@ngx-translate/core"; import { State, @@ -41,6 +41,7 @@ import { ResourceType, Roles } from "../../../../shared/shared.const"; +import { errorHandler as errorHandFn } from "../../../../shared/shared.utils"; @Component({ selector: "hbr-helm-chart-version", @@ -95,6 +96,7 @@ export class ChartVersionComponent implements OnInit { public userPermissionService: UserPermissionService, private cdr: ChangeDetectorRef, private operationService: OperationService, + private translateService: TranslateService, ) { } public get registryUrl(): string { @@ -175,8 +177,14 @@ export class ChartVersionComponent implements OnInit { .deleteChartVersion(this.projectName, this.chartName, version.version) .pipe(map( () => operateChanges(operateMsg, OperationState.success), - err => operateChanges(operateMsg, OperationState.failure, err) - )); + catchError( error => { + const message = errorHandFn(error); + this.translateService.get(message).subscribe(res => + operateChanges(operateMsg, OperationState.failure, res) + ); + return observableThrowError(message); + } + ))); } deleteVersions(versions: HelmChartVersion[]) { diff --git a/src/portal/src/app/project/helm-chart/list-charts-detail/helm-chart.component.ts b/src/portal/src/app/project/helm-chart/list-charts-detail/helm-chart.component.ts index 412b445be..e121a2c77 100644 --- a/src/portal/src/app/project/helm-chart/list-charts-detail/helm-chart.component.ts +++ b/src/portal/src/app/project/helm-chart/list-charts-detail/helm-chart.component.ts @@ -14,7 +14,7 @@ import { State, ErrorHandler, SystemInfo, SystemInfoService, DEFAULT_PAGE_SIZE, downloadFile , OperationService, UserPermissionService, USERSTATICPERMISSION, OperateInfo, OperationState, operateChanges } from "@harbor/ui"; -import { forkJoin, throwError, Observable } from "rxjs"; +import { forkJoin, throwError as observableThrowError, Observable } from "rxjs"; import { finalize, map, catchError } from "rxjs/operators"; import { HelmChartItem } from "../helm-chart.interface.service"; import { HelmChartService } from "../helm-chart.service"; @@ -28,6 +28,7 @@ import { ConfirmationTargets, ConfirmationState, } from "../../../shared/shared.const"; +import { errorHandler as errorHandFn } from "../../../shared/shared.utils"; @Component({ selector: "hbr-helm-chart", @@ -202,8 +203,14 @@ export class HelmChartComponent implements OnInit { return this.helmChartService.deleteHelmChart(this.projectName, chartName) .pipe(map( () => operateChanges(operateMsg, OperationState.success), - err => operateChanges(operateMsg, OperationState.failure, err) - )); + catchError( error => { + const message = errorHandFn(error); + this.translateService.get(message).subscribe(res => + operateChanges(operateMsg, OperationState.failure, res) + ); + return observableThrowError(message); + } + ))); } deleteCharts(charts: HelmChartItem[]) { @@ -211,7 +218,7 @@ export class HelmChartComponent implements OnInit { let chartsDelete$ = charts.map(chart => this.deleteChart(chart.name)); forkJoin(chartsDelete$) .pipe( - catchError(err => throwError(err)), + catchError(err => observableThrowError(err)), finalize(() => { this.refresh(); this.selectedRows = []; diff --git a/src/portal/src/app/project/list-project/list-project.component.ts b/src/portal/src/app/project/list-project/list-project.component.ts index 96517479b..b7c63aa1c 100644 --- a/src/portal/src/app/project/list-project/list-project.component.ts +++ b/src/portal/src/app/project/list-project/list-project.component.ts @@ -41,6 +41,8 @@ import { Project } from "../project"; import { ProjectService } from "../project.service"; import { map, catchError } from "rxjs/operators"; import { throwError as observableThrowError } from "rxjs"; +import { errorHandler as errorHandFn } from "../../shared/shared.utils"; + @Component({ selector: "list-project", templateUrl: "list-project.component.html", @@ -78,6 +80,7 @@ export class ListProjectComponent implements OnDestroy { private translate: TranslateService, private deletionDialogService: ConfirmationDialogService, private operationService: OperationService, + private translateService: TranslateService, private ref: ChangeDetectorRef) { this.subscription = deletionDialogService.confirmationConfirm$.subscribe(message => { if (message && @@ -274,16 +277,11 @@ export class ListProjectComponent implements OnDestroy { }); }), catchError( error => { - if (error && error.status === 412) { - return observableForkJoin(this.translate.get("BATCH.DELETED_FAILURE"), - this.translate.get("PROJECT.FAILED_TO_DELETE_PROJECT")).pipe(map(res => { - operateChanges(operMessage, OperationState.failure, res[1]); - })); - } else { - return this.translate.get("BATCH.DELETED_FAILURE").pipe(map(res => { - operateChanges(operMessage, OperationState.failure, res); - })); - } + const message = errorHandFn(error); + this.translateService.get(message).subscribe(res => + operateChanges(operMessage, OperationState.failure, res) + ); + return observableThrowError(message); })); } diff --git a/src/portal/src/app/project/member/add-group/add-group.component.ts b/src/portal/src/app/project/member/add-group/add-group.component.ts index 406171cdf..dc57515f4 100644 --- a/src/portal/src/app/project/member/add-group/add-group.component.ts +++ b/src/portal/src/app/project/member/add-group/add-group.component.ts @@ -15,7 +15,8 @@ import { GroupService } from "../../../group/group.service"; import { ProjectRoles } from "../../../shared/shared.const"; import { MessageHandlerService } from '../../../shared/message-handler/message-handler.service'; import { Member } from "../member"; - +import { throwError as observableThrowError } from "rxjs"; +import { errorHandler as errorHandFn } from "../../../shared/shared.utils"; @Component({ selector: "add-group", templateUrl: "./add-group.component.html", @@ -135,12 +136,14 @@ export class AddGroupComponent implements OnInit { operateChanges(operMessage, OperationState.success); return observableOf(res); })); }), - catchError(error => { - return this.translateService.get("BATCH.DELETED_FAILURE").pipe( - mergeMap(res => { - operateChanges(operMessage, OperationState.failure, res); - return observableOf(res); - })); }), + catchError( + error => { + const message = errorHandFn(error); + this.translateService.get(message).subscribe(res => + operateChanges(operMessage, OperationState.failure, res) + ); + return observableThrowError(message); + }), catchError(error => observableOf(error.status)), ); }); forkJoin(GroupAdders$) diff --git a/src/portal/src/app/project/member/member.component.ts b/src/portal/src/app/project/member/member.component.ts index 79f25f367..a4bac5513 100644 --- a/src/portal/src/app/project/member/member.component.ts +++ b/src/portal/src/app/project/member/member.component.ts @@ -34,6 +34,7 @@ import { AddMemberComponent } from "./add-member/add-member.component"; import { AppConfigService } from "../../app-config.service"; import { UserPermissionService, USERSTATICPERMISSION, ErrorHandler } from "@harbor/ui"; import { map, catchError } from "rxjs/operators"; +import { errorHandler as errorHandFn } from "../../shared/shared.utils"; import { throwError as observableThrowError } from "rxjs"; @Component({ templateUrl: "member.component.html", @@ -260,9 +261,11 @@ export class MemberComponent implements OnInit, OnDestroy { operateChanges(operMessage, OperationState.success); }); }), catchError(error => { - return this.translate.get("BATCH.DELETED_FAILURE").pipe(map(res => { - operateChanges(operMessage, OperationState.failure, res); - })); + const message = errorHandFn(error); + this.translate.get(message).subscribe(res => + operateChanges(operMessage, OperationState.failure, res) + ); + return observableThrowError(message); })); }; diff --git a/src/portal/src/app/project/robot-account/robot-account.component.ts b/src/portal/src/app/project/robot-account/robot-account.component.ts index d0f2d0cac..b51713a3d 100644 --- a/src/portal/src/app/project/robot-account/robot-account.component.ts +++ b/src/portal/src/app/project/robot-account/robot-account.component.ts @@ -11,7 +11,7 @@ import { Robot } from "./robot"; import { Project } from "./../project"; import { finalize, catchError, map } from "rxjs/operators"; import { TranslateService } from "@ngx-translate/core"; -import { Subscription, forkJoin, Observable, throwError } from "rxjs"; +import { Subscription, forkJoin, Observable, throwError as observableThrowError } from "rxjs"; import { MessageHandlerService } from "../../shared/message-handler/message-handler.service"; import { RobotService } from "./robot-account.service"; import { ConfirmationMessage } from "../../shared/confirmation-dialog/confirmation-message"; @@ -30,7 +30,7 @@ import { USERSTATICPERMISSION, ErrorHandler } from "@harbor/ui"; - +import { errorHandler as errorHandFn } from "../../shared/shared.utils"; @Component({ selector: "app-robot-account", templateUrl: "./robot-account.component.html", @@ -140,7 +140,7 @@ export class RobotAccountComponent implements OnInit, OnDestroy { let robotsDelete$ = robots.map(robot => this.delOperate(robot)); forkJoin(robotsDelete$) .pipe( - catchError(err => throwError(err)), + catchError(err => observableThrowError(err)), finalize(() => { this.retrieve(); this.selectedRow = []; @@ -163,9 +163,15 @@ export class RobotAccountComponent implements OnInit, OnDestroy { .pipe( map( () => operateChanges(operMessage, OperationState.success), - err => operateChanges(operMessage, OperationState.failure, err) + catchError(error => { + const errorMsg = errorHandFn(error); + this.translate.get(errorMsg).subscribe(res => + operateChanges(operMessage, OperationState.failure, res) + ); + return observableThrowError(errorMsg); + } ) - ); + )); } createAccount(created: boolean): void { diff --git a/src/portal/src/app/shared/shared.utils.ts b/src/portal/src/app/shared/shared.utils.ts index 320b7d86b..a71770671 100644 --- a/src/portal/src/app/shared/shared.utils.ts +++ b/src/portal/src/app/shared/shared.utils.ts @@ -12,9 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. import { NgForm } from '@angular/forms'; -import {RequestOptions, Headers, Response} from "@angular/http"; +import { RequestOptions, Headers, Response } from "@angular/http"; import { Comparator, State } from '../../../lib/src/service/interface'; -import {RequestQueryParams} from "@harbor/ui"; +import { RequestQueryParams } from "@harbor/ui"; import { MessageService } from '../global-message/message.service'; import { httpStatusCode, AlertType } from './shared.const'; @@ -26,16 +26,21 @@ import { httpStatusCode, AlertType } from './shared.const'; * returns {string} */ export const errorHandler = function (error: any): string { - if (typeof error === "string") { - return error; + if (!error) { + return "UNKNOWN_ERROR"; } - if (error && error._body) { + + try { + return JSON.parse(error._body).message; + } catch (err) { } + + if (error._body && error._body.message) { + return error._body.message; + } + + if (!(error.statusCode || error.status)) { // treat as string message - if (typeof error._body === "string") { - return error._body; - } else if (error._body.error) { - return error._body.error; - } + return '' + error; } else { switch (error.statusCode || error.status) { case 400: diff --git a/src/portal/src/app/user/user.component.ts b/src/portal/src/app/user/user.component.ts index 33724a905..3e413146a 100644 --- a/src/portal/src/app/user/user.component.ts +++ b/src/portal/src/app/user/user.component.ts @@ -30,6 +30,7 @@ import { ChangePasswordComponent } from "./change-password/change-password.compo import { operateChanges, OperateInfo, OperationService, OperationState } from "@harbor/ui"; import { map, catchError } from 'rxjs/operators'; import { throwError as observableThrowError } from "rxjs"; +import { errorHandler as errorHandFn } from "../shared/shared.utils"; /** * NOTES: @@ -230,9 +231,9 @@ export class UserComponent implements OnInit, OnDestroy { this.selectedRow = []; this.refresh(); }, error => { - this.selectedRow = []; - this.msgHandler.handleError(error); - }); + this.selectedRow = []; + this.msgHandler.handleError(error); + }); } } @@ -296,9 +297,11 @@ export class UserComponent implements OnInit, OnDestroy { operateChanges(operMessage, OperationState.success); }); }, catchError(error => { - return this.translate.get('BATCH.DELETED_FAILURE').pipe(map(res => { - operateChanges(operMessage, OperationState.failure, res); - })); + const message = errorHandFn(error); + this.translate.get(message).subscribe(res => + operateChanges(operMessage, OperationState.failure, res) + ); + return observableThrowError(message); }))); } @@ -320,10 +323,10 @@ export class UserComponent implements OnInit, OnDestroy { return users; }, error => { - this.onGoing = false; - this.msgHandler.handleError(error); - this.forceRefreshView(5000); - }); + this.onGoing = false; + this.msgHandler.handleError(error); + this.forceRefreshView(5000); + }); } // Add new user