harbor/src/portal/src/app/base/project/robot-account/robot-account.component.ts

440 lines
17 KiB
TypeScript

import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { ClrDatagridStateInterface, ClrLoadingState } from '@clr/angular';
import {
catchError,
debounceTime,
distinctUntilChanged,
finalize,
map,
switchMap,
} from 'rxjs/operators';
import { forkJoin, Observable, of, Subscription } from 'rxjs';
import {
UserPermissionService,
USERSTATICPERMISSION,
} from '../../../shared/services';
import { PermissionsKinds } from '../../left-side-nav/system-robot-accounts/system-robot-util';
import {
clone,
getPageSizeFromLocalStorage,
getSortingString,
PageSizeMapKeys,
setPageSizeToLocalStorage,
} from '../../../shared/units/utils';
import { ViewTokenComponent } from '../../../shared/components/view-token/view-token.component';
import { FilterComponent } from '../../../shared/components/filter/filter.component';
import { MessageHandlerService } from '../../../shared/services/message-handler.service';
import { OperationService } from '../../../shared/components/operation/operation.service';
import { RobotService } from '../../../../../ng-swagger-gen/services/robot.service';
import { Robot } from '../../../../../ng-swagger-gen/models/robot';
import { ActivatedRoute } from '@angular/router';
import { Project } from '../../../../../ng-swagger-gen/models/project';
import { HttpErrorResponse } from '@angular/common/http';
import {
operateChanges,
OperateInfo,
OperationState,
} from '../../../shared/components/operation/operate';
import { AddRobotComponent } from './add-robot/add-robot.component';
import { TranslateService } from '@ngx-translate/core';
import { DomSanitizer } from '@angular/platform-browser';
import { ConfirmationDialogService } from '../../global-confirmation-dialog/confirmation-dialog.service';
import {
ConfirmationButtons,
ConfirmationState,
ConfirmationTargets,
} from '../../../shared/entities/shared.const';
import { errorHandler } from '../../../shared/units/shared.utils';
import { ConfirmationMessage } from '../../global-confirmation-dialog/confirmation-message';
import { SysteminfoService } from '../../../../../ng-swagger-gen/services/systeminfo.service';
import { PermissionSelectPanelModes } from '../../../shared/components/robot-permissions-panel/robot-permissions-panel.component';
import { PermissionsService } from '../../../../../ng-swagger-gen/services/permissions.service';
import { Permissions } from '../../../../../ng-swagger-gen/models/permissions';
@Component({
selector: 'app-robot-account',
templateUrl: './robot-account.component.html',
styleUrls: ['./robot-account.component.scss'],
})
export class RobotAccountComponent implements OnInit, OnDestroy {
pageSize: number = getPageSizeFromLocalStorage(
PageSizeMapKeys.PROJECT_ROBOT_COMPONENT
);
currentPage: number = 1;
total: number = 0;
robots: Robot[] = [];
selectedRows: Robot[] = [];
loading: boolean = true;
addBtnState: ClrLoadingState = ClrLoadingState.DEFAULT;
@ViewChild(AddRobotComponent)
newRobotComponent: AddRobotComponent;
@ViewChild(ViewTokenComponent)
viewTokenComponent: ViewTokenComponent;
@ViewChild(FilterComponent, { static: true })
filterComponent: FilterComponent;
searchSub: Subscription;
searchKey: string;
subscription: Subscription;
hasRobotCreatePermission: boolean;
hasRobotUpdatePermission: boolean;
hasRobotDeletePermission: boolean;
hasRobotReadPermission: boolean;
projectId: number;
projectName: string;
deltaTime: number; // the different between server time and local time
loadingMetadata: boolean = false;
robotMetadata: Permissions;
constructor(
private robotService: RobotService,
private msgHandler: MessageHandlerService,
private operateDialogService: ConfirmationDialogService,
private operationService: OperationService,
private userPermissionService: UserPermissionService,
private route: ActivatedRoute,
private translate: TranslateService,
private sanitizer: DomSanitizer,
private systemInfoService: SysteminfoService,
private permissionService: PermissionsService
) {}
ngOnInit() {
this.getCurrenTime();
this.projectId = +this.route.snapshot.parent.parent.params['id'];
let resolverData = this.route.snapshot.parent.parent.data;
if (resolverData) {
let project = <Project>resolverData['projectResolver'];
this.projectName = project.name;
}
this.getPermissionsList();
if (!this.searchSub) {
this.searchSub = this.filterComponent.filterTerms
.pipe(
debounceTime(500),
distinctUntilChanged(),
switchMap(robotSearchName => {
this.currentPage = 1;
this.selectedRows = [];
const queryParam: RobotService.ListRobotParams = {
page: this.currentPage,
pageSize: this.pageSize,
};
this.searchKey = robotSearchName;
if (this.searchKey) {
queryParam.q = encodeURIComponent(
`Level=${PermissionsKinds.PROJECT},ProjectID=${this.projectId},name=~${this.searchKey}`
);
} else {
queryParam.q = encodeURIComponent(
`Level=${PermissionsKinds.PROJECT},ProjectID=${this.projectId}`
);
}
this.loading = true;
return this.robotService
.ListRobotResponse(queryParam)
.pipe(
finalize(() => {
this.loading = false;
})
);
})
)
.subscribe(
response => {
this.total = Number.parseInt(
response.headers.get('x-total-count'),
10
);
this.robots = response.body as Robot[];
},
error => {
this.msgHandler.handleError(error);
}
);
}
if (!this.subscription) {
this.subscription =
this.operateDialogService.confirmationConfirm$.subscribe(
message => {
if (
message &&
message.state === ConfirmationState.CONFIRMED &&
message.source ===
ConfirmationTargets.PROJECT_ROBOT_ACCOUNT
) {
this.deleteRobots(message.data);
}
if (
message.state === ConfirmationState.CONFIRMED &&
message.source ===
ConfirmationTargets.PROJECT_ROBOT_ACCOUNT_ENABLE_OR_DISABLE
) {
this.operateRobot();
}
}
);
}
}
getRobotPermissions() {
this.loadingMetadata = true;
this.permissionService
.getPermissions()
.pipe(finalize(() => (this.loadingMetadata = false)))
.subscribe(res => {
this.robotMetadata = res;
});
}
getCurrenTime() {
this.systemInfoService.getSystemInfo().subscribe(res => {
if (res?.current_time) {
this.deltaTime =
new Date().getTime() -
new Date(res?.current_time).getTime();
}
});
}
getPermissionsList(): void {
let permissionsList = [];
permissionsList.push(
this.userPermissionService.getPermission(
this.projectId,
USERSTATICPERMISSION.ROBOT.KEY,
USERSTATICPERMISSION.ROBOT.VALUE.CREATE
)
);
permissionsList.push(
this.userPermissionService.getPermission(
this.projectId,
USERSTATICPERMISSION.ROBOT.KEY,
USERSTATICPERMISSION.ROBOT.VALUE.UPDATE
)
);
permissionsList.push(
this.userPermissionService.getPermission(
this.projectId,
USERSTATICPERMISSION.ROBOT.KEY,
USERSTATICPERMISSION.ROBOT.VALUE.DELETE
)
);
permissionsList.push(
this.userPermissionService.getPermission(
this.projectId,
USERSTATICPERMISSION.ROBOT.KEY,
USERSTATICPERMISSION.ROBOT.VALUE.READ
)
);
forkJoin(...permissionsList).subscribe(
Rules => {
this.hasRobotCreatePermission = Rules[0] as boolean;
if (this.hasRobotCreatePermission) {
this.getRobotPermissions();
}
this.hasRobotUpdatePermission = Rules[1] as boolean;
this.hasRobotDeletePermission = Rules[2] as boolean;
this.hasRobotReadPermission = Rules[3] as boolean;
},
error => this.msgHandler.error(error)
);
}
ngOnDestroy() {
if (this.searchSub) {
this.searchSub.unsubscribe();
this.searchSub = null;
}
if (this.subscription) {
this.subscription.unsubscribe();
this.subscription = null;
}
}
clrLoad(state?: ClrDatagridStateInterface) {
if (state && state.page && state.page.size) {
this.pageSize = state.page.size;
setPageSizeToLocalStorage(
PageSizeMapKeys.PROJECT_ROBOT_COMPONENT,
this.pageSize
);
}
this.selectedRows = [];
const queryParam: RobotService.ListRobotParams = {
page: this.currentPage,
pageSize: this.pageSize,
sort: getSortingString(state),
q: encodeURIComponent(
`Level=${PermissionsKinds.PROJECT},ProjectID=${this.projectId}`
),
};
if (this.searchKey) {
queryParam.q += encodeURIComponent(`,name=~${this.searchKey}`);
}
this.loading = true;
this.robotService
.ListRobotResponse(queryParam)
.pipe(finalize(() => (this.loading = false)))
.subscribe(
response => {
this.total = Number.parseInt(
response.headers.get('x-total-count'),
10
);
this.robots = response.body as Robot[];
},
err => {
this.msgHandler.error(err);
}
);
}
openNewRobotModal(isEditMode: boolean) {
if (isEditMode) {
this.newRobotComponent.resetForEdit(clone(this.selectedRows[0]));
} else {
this.newRobotComponent.reset();
}
}
openTokenModal() {
this.viewTokenComponent.open();
this.viewTokenComponent.robot = clone(this.selectedRows[0]);
}
refresh() {
this.currentPage = 1;
this.selectedRows = [];
this.clrLoad();
}
deleteRobots(robots: Robot[]) {
let observableLists: Observable<any>[] = [];
if (robots && robots.length) {
robots.forEach(item => {
observableLists.push(this.deleteRobot(item));
});
forkJoin(...observableLists).subscribe(resArr => {
let error;
if (resArr && resArr.length) {
resArr.forEach(item => {
if (item instanceof HttpErrorResponse) {
error = errorHandler(item);
}
});
}
if (error) {
this.msgHandler.handleError(error);
} else {
this.msgHandler.showSuccess(
'SYSTEM_ROBOT.DELETE_ROBOT_SUCCESS'
);
}
this.refresh();
});
}
}
deleteRobot(robot: Robot): Observable<any> {
let operMessage = new OperateInfo();
operMessage.name = 'SYSTEM_ROBOT.DELETE_ROBOT';
operMessage.data.id = robot.id;
operMessage.state = OperationState.progressing;
operMessage.data.name = robot.name;
this.operationService.publishInfo(operMessage);
return this.robotService.DeleteRobot({ robotId: robot.id }).pipe(
map(() => {
operateChanges(operMessage, OperationState.success);
}),
catchError(error => {
const message = errorHandler(error);
operateChanges(operMessage, OperationState.failure, message);
return of(error);
})
);
}
openDeleteRobotsDialog() {
const robotNames = this.selectedRows.map(robot => robot.name).join(',');
const deletionMessage = new ConfirmationMessage(
'ROBOT_ACCOUNT.DELETION_TITLE',
'ROBOT_ACCOUNT.DELETION_SUMMARY',
robotNames,
this.selectedRows,
ConfirmationTargets.PROJECT_ROBOT_ACCOUNT,
ConfirmationButtons.DELETE_CANCEL
);
this.operateDialogService.openComfirmDialog(deletionMessage);
}
disableOrEnable() {
const title: string = this.selectedRows[0].disable
? 'SYSTEM_ROBOT.ENABLE_TITLE'
: 'SYSTEM_ROBOT.DISABLE_TITLE';
const summary: string = this.selectedRows[0].disable
? 'SYSTEM_ROBOT.ENABLE_SUMMARY'
: 'SYSTEM_ROBOT.DISABLE_SUMMARY';
const deletionMessage = new ConfirmationMessage(
title,
summary,
this.selectedRows[0].name,
this.selectedRows[0],
ConfirmationTargets.PROJECT_ROBOT_ACCOUNT_ENABLE_OR_DISABLE,
this.selectedRows[0].disable
? ConfirmationButtons.ENABLE_CANCEL
: ConfirmationButtons.DISABLE_CANCEL
);
this.operateDialogService.openComfirmDialog(deletionMessage);
}
operateRobot() {
const robot: Robot = clone(this.selectedRows[0]);
const successMessage: string = robot.disable
? 'SYSTEM_ROBOT.ENABLE_ROBOT_SUCCESSFULLY'
: 'SYSTEM_ROBOT.DISABLE_ROBOT_SUCCESSFULLY';
robot.disable = !robot.disable;
delete robot.secret;
const opeMessage = new OperateInfo();
opeMessage.name = robot.disable
? 'SYSTEM_ROBOT.DISABLE_TITLE'
: 'SYSTEM_ROBOT.ENABLE_TITLE';
opeMessage.data.id = robot.id;
opeMessage.state = OperationState.progressing;
opeMessage.data.name = robot.name;
this.operationService.publishInfo(opeMessage);
this.robotService
.UpdateRobot({
robot: robot,
robotId: robot.id,
})
.subscribe(
res => {
operateChanges(opeMessage, OperationState.success);
this.msgHandler.showSuccess(successMessage);
this.refresh();
},
error => {
operateChanges(
opeMessage,
OperationState.failure,
errorHandler(error)
);
this.msgHandler.showSuccess(error);
}
);
}
addSuccess(robot: Robot) {
if (robot) {
this.viewTokenComponent.open();
this.viewTokenComponent.tokenModalOpened = false;
this.viewTokenComponent.robot = clone(robot);
this.viewTokenComponent.copyToken = true;
this.translate
.get('ROBOT_ACCOUNT.CREATED_SUCCESS', { param: robot.name })
.subscribe((res: string) => {
this.viewTokenComponent.createSuccess = res;
});
// export to token file
const downLoadUrl = `data:text/json;charset=utf-8, ${encodeURIComponent(
JSON.stringify(robot)
)}`;
this.viewTokenComponent.downLoadHref =
this.sanitizer.bypassSecurityTrustUrl(downLoadUrl);
this.viewTokenComponent.downLoadFileName = `${robot.name}.json`;
}
this.refresh();
}
protected readonly PermissionSelectPanelModes = PermissionSelectPanelModes;
}