diff --git a/modules/web/src/app/backup/details/automatic-backup/component.ts b/modules/web/src/app/backup/details/automatic-backup/component.ts index 860a6778f0..0426a51684 100644 --- a/modules/web/src/app/backup/details/automatic-backup/component.ts +++ b/modules/web/src/app/backup/details/automatic-backup/component.ts @@ -16,6 +16,7 @@ import {Component, OnDestroy, OnInit} from '@angular/core'; import {MatDialog, MatDialogConfig} from '@angular/material/dialog'; import {ActivatedRoute, Router} from '@angular/router'; import {getBackupHealthStatus, HealthStatus} from '@app/shared/utils/health-status'; +import {ClusterService} from '@core/services/cluster'; import {BackupService} from '@core/services/backup'; import {ProjectService} from '@core/services/project'; import {UserService} from '@core/services/user'; @@ -27,8 +28,9 @@ import {Project} from '@shared/entity/project'; import {GroupConfig} from '@shared/model/Config'; import {MemberUtils, Permission} from '@shared/utils/member'; import _ from 'lodash'; -import {Subject} from 'rxjs'; -import {filter, map, switchMap, take, takeUntil} from 'rxjs/operators'; +import {forkJoin, of, Subject} from 'rxjs'; +import {filter, switchMap, take, takeUntil} from 'rxjs/operators'; +import {Cluster} from '@app/shared/entity/cluster'; @Component({ selector: 'km-automatic-backup-details', @@ -43,7 +45,7 @@ export class AutomaticBackupDetailsComponent implements OnInit, OnDestroy { selectedProject = {} as Project; isInitialized = false; backup: EtcdBackupConfig = {} as EtcdBackupConfig; - + cluster: Cluster; get canDelete(): boolean { return MemberUtils.hasPermission(this._user, this._currentGroupConfig, View.Backups, Permission.Delete); } @@ -57,6 +59,7 @@ export class AutomaticBackupDetailsComponent implements OnInit, OnDestroy { } constructor( + private readonly _clusterService: ClusterService, private readonly _backupService: BackupService, private readonly _projectService: ProjectService, private readonly _userService: UserService, @@ -74,20 +77,23 @@ export class AutomaticBackupDetailsComponent implements OnInit, OnDestroy { this._projectService.selectedProject .pipe( - switchMap(project => { - this.selectedProject = project; - return this._userService.getCurrentUserGroup(project.id); - }) + switchMap(project => + forkJoin({ + userGroup: this._userService.getCurrentUserGroup(project.id).pipe(take(1)), + backups: this._backupService.list(project.id, false).pipe(take(1)), + clusters: this._clusterService.clusters(project.id, false).pipe(take(1)), + project: of(project), + }) + ) ) .pipe(takeUntil(this._unsubscribe)) - .subscribe(userGroup => (this._currentGroupConfig = this._userService.getCurrentUserGroupConfig(userGroup))); + .subscribe(({userGroup, backups, clusters, project}) => { + this.selectedProject = project; + this._currentGroupConfig = this._userService.getCurrentUserGroupConfig(userGroup); + + this.backup = backups.find(backup => backup.id === this._route.snapshot.params.backupID); + this.cluster = clusters.find(cluster => cluster.id === this.backup.spec?.clusterId); - this._projectService.selectedProject - .pipe(switchMap(project => this._backupService.list(project.id))) - .pipe(map(backups => backups.find(backup => backup.id === this._route.snapshot.params.backupID))) - .pipe(takeUntil(this._unsubscribe)) - .subscribe(backup => { - this.backup = backup; this.isInitialized = true; }); } diff --git a/modules/web/src/app/backup/details/automatic-backup/template.html b/modules/web/src/app/backup/details/automatic-backup/template.html index 68346f65c4..340d4a030a 100644 --- a/modules/web/src/app/backup/details/automatic-backup/template.html +++ b/modules/web/src/app/backup/details/automatic-backup/template.html @@ -54,6 +54,10 @@ + +
Cluster Name
+
{{cluster?.name || '-'}}
+
Cluster ID
{{backup.spec?.clusterId}}
diff --git a/modules/web/src/app/backup/details/snapshot/component.ts b/modules/web/src/app/backup/details/snapshot/component.ts index 5071e8a239..25ac0a57e5 100644 --- a/modules/web/src/app/backup/details/snapshot/component.ts +++ b/modules/web/src/app/backup/details/snapshot/component.ts @@ -19,6 +19,7 @@ import { DeleteSnapshotDialogComponent, DeleteSnapshotDialogConfig, } from '@app/backup/list/snapshot/delete-dialog/component'; +import {ClusterService} from '@core/services/cluster'; import {BackupService} from '@core/services/backup'; import {ProjectService} from '@core/services/project'; import {UserService} from '@core/services/user'; @@ -28,9 +29,10 @@ import {Member} from '@shared/entity/member'; import {Project} from '@shared/entity/project'; import {GroupConfig} from '@shared/model/Config'; import {MemberUtils, Permission} from '@shared/utils/member'; -import {Subject} from 'rxjs'; -import {filter, map, switchMap, take, takeUntil} from 'rxjs/operators'; +import {forkJoin, of, Subject} from 'rxjs'; +import {filter, switchMap, take, takeUntil} from 'rxjs/operators'; import {getBackupHealthStatus, HealthStatus} from '@shared/utils/health-status'; +import {Cluster} from '@app/shared/entity/cluster'; @Component({ selector: 'km-snapshot-details', @@ -45,7 +47,7 @@ export class SnapshotDetailsComponent implements OnInit, OnDestroy { selectedProject = {} as Project; isInitialized = false; backup: EtcdBackupConfig = {} as EtcdBackupConfig; - + cluster: Cluster; get canDelete(): boolean { return MemberUtils.hasPermission(this._user, this._currentGroupConfig, View.Backups, Permission.Delete); } @@ -59,6 +61,7 @@ export class SnapshotDetailsComponent implements OnInit, OnDestroy { } constructor( + private readonly _clusterService: ClusterService, private readonly _backupService: BackupService, private readonly _projectService: ProjectService, private readonly _userService: UserService, @@ -76,20 +79,23 @@ export class SnapshotDetailsComponent implements OnInit, OnDestroy { this._projectService.selectedProject .pipe( - switchMap(project => { - this.selectedProject = project; - return this._userService.getCurrentUserGroup(project.id); - }) + switchMap(project => + forkJoin({ + userGroup: this._userService.getCurrentUserGroup(project.id).pipe(take(1)), + backups: this._backupService.list(project.id, true).pipe(take(1)), + clusters: this._clusterService.clusters(project.id, false).pipe(take(1)), + project: of(project), + }) + ) ) .pipe(takeUntil(this._unsubscribe)) - .subscribe(userGroup => (this._currentGroupConfig = this._userService.getCurrentUserGroupConfig(userGroup))); + .subscribe(({userGroup, backups, clusters, project}) => { + this.selectedProject = project; + this._currentGroupConfig = this._userService.getCurrentUserGroupConfig(userGroup); + + this.backup = backups.find(backup => backup.id === this._route.snapshot.params.backupID); + this.cluster = clusters.find(cluster => cluster.id === this.backup.spec?.clusterId); - this._projectService.selectedProject - .pipe(switchMap(project => this._backupService.list(project.id, true))) - .pipe(map(backups => backups.find(backup => backup.id === this._route.snapshot.params.backupID))) - .pipe(takeUntil(this._unsubscribe)) - .subscribe(backup => { - this.backup = backup; this.isInitialized = true; }); } diff --git a/modules/web/src/app/backup/details/snapshot/template.html b/modules/web/src/app/backup/details/snapshot/template.html index e61d3b14f1..4b5f35dc86 100644 --- a/modules/web/src/app/backup/details/snapshot/template.html +++ b/modules/web/src/app/backup/details/snapshot/template.html @@ -47,6 +47,10 @@ + +
Cluster Name
+
{{cluster?.name || '-'}}
+
Cluster ID
{{backup.spec?.clusterId}}
diff --git a/modules/web/src/app/backup/list/automatic-backup/component.ts b/modules/web/src/app/backup/list/automatic-backup/component.ts index de1e591f83..7e3544aa99 100644 --- a/modules/web/src/app/backup/list/automatic-backup/component.ts +++ b/modules/web/src/app/backup/list/automatic-backup/component.ts @@ -21,7 +21,9 @@ import { AddAutomaticBackupDialogComponent, AddAutomaticBackupDialogConfig, } from '@app/backup/list/automatic-backup/add-dialog/component'; +import {Cluster} from '@app/shared/entity/cluster'; import {BackupService} from '@core/services/backup'; +import {ClusterService} from '@core/services/cluster'; import {NotificationService} from '@core/services/notification'; import {ProjectService} from '@core/services/project'; import {UserService} from '@core/services/user'; @@ -34,7 +36,7 @@ import {GroupConfig} from '@shared/model/Config'; import {HealthStatus, getBackupHealthStatus} from '@shared/utils/health-status'; import {MemberUtils, Permission} from '@shared/utils/member'; import _ from 'lodash'; -import {Subject} from 'rxjs'; +import {forkJoin, of, Subject} from 'rxjs'; import {filter, switchMap, take, takeUntil} from 'rxjs/operators'; @Component({ @@ -49,6 +51,7 @@ export class AutomaticBackupListComponent implements OnInit, OnDestroy { private _currentGroupConfig: GroupConfig; private _selectedProject = {} as Project; private _backups = []; + private _clusters = new Map(); dataSource = new MatTableDataSource(); isInitialized = true; @@ -57,7 +60,7 @@ export class AutomaticBackupListComponent implements OnInit, OnDestroy { } get columns(): string[] { - return ['status', 'name', 'cluster', 'destination', 'schedule', 'keep', 'created', 'actions']; + return ['status', 'name', 'clusterName', 'cluster', 'destination', 'schedule', 'keep', 'created', 'actions']; } get isEmpty(): boolean { @@ -82,6 +85,7 @@ export class AutomaticBackupListComponent implements OnInit, OnDestroy { constructor( private readonly _backupService: BackupService, + private readonly _clusterService: ClusterService, private readonly _projectService: ProjectService, private readonly _userService: UserService, private readonly _matDialog: MatDialog, @@ -101,20 +105,24 @@ export class AutomaticBackupListComponent implements OnInit, OnDestroy { this._projectService.selectedProject .pipe( - switchMap(project => { - this._selectedProject = project; - return this._userService.getCurrentUserGroup(project.id); - }) + switchMap(project => + forkJoin({ + userGroup: this._userService.getCurrentUserGroup(project.id).pipe(take(1)), + backups: this._backupService.list(project.id).pipe(take(1)), + clusters: this._clusterService.clusters(project.id, false).pipe(take(1)), + project: of(project), + }) + ) ) .pipe(takeUntil(this._unsubscribe)) - .subscribe(userGroup => (this._currentGroupConfig = this._userService.getCurrentUserGroupConfig(userGroup))); + .subscribe(({userGroup, backups, clusters, project}) => { + this._selectedProject = project; + this._currentGroupConfig = this._userService.getCurrentUserGroupConfig(userGroup); - this._projectService.selectedProject - .pipe(switchMap(project => this._backupService.list(project.id))) - .pipe(takeUntil(this._unsubscribe)) - .subscribe(backups => { this._backups = backups; this.dataSource.data = this._backups; + + clusters.forEach(cluster => this._clusters.set(cluster.id, cluster)); }); } @@ -136,6 +144,10 @@ export class AutomaticBackupListComponent implements OnInit, OnDestroy { return getBackupHealthStatus(backup, condition); } + getClusterName(backup: EtcdBackupConfig): string { + return this._clusters.get(backup.spec.clusterId)?.name ?? '-'; + } + delete(backup: EtcdBackupConfig): void { const config: MatDialogConfig = { data: { diff --git a/modules/web/src/app/backup/list/automatic-backup/template.html b/modules/web/src/app/backup/list/automatic-backup/template.html index 46600ecad6..88c0edc791 100644 --- a/modules/web/src/app/backup/list/automatic-backup/template.html +++ b/modules/web/src/app/backup/list/automatic-backup/template.html @@ -61,6 +61,17 @@ + + Cluster Name + + + {{getClusterName(element)}} + + + (); dataSource = new MatTableDataSource(); isInitialized = true; @@ -52,7 +55,7 @@ export class RestoreListComponent implements OnInit, OnDestroy { } get columns(): string[] { - return ['name', 'phase', 'clusterID', 'backupName', 'destination', 'actions']; + return ['name', 'phase', 'clusterName', 'clusterID', 'backupName', 'destination', 'actions']; } get isEmpty(): boolean { @@ -69,6 +72,7 @@ export class RestoreListComponent implements OnInit, OnDestroy { constructor( private readonly _backupService: BackupService, + private readonly _clusterService: ClusterService, private readonly _projectService: ProjectService, private readonly _userService: UserService, private readonly _matDialog: MatDialog, @@ -91,16 +95,21 @@ export class RestoreListComponent implements OnInit, OnDestroy { .subscribe(_ => this._onChange.next()); this._onChange - .pipe(switchMap(_ => this._userService.getCurrentUserGroup(this._selectedProject.id).pipe(take(1)))) - .pipe(takeUntil(this._unsubscribe)) - .subscribe(userGroup => (this._currentGroupConfig = this._userService.getCurrentUserGroupConfig(userGroup))); - - this._onChange - .pipe(switchMap(_ => this._backupService.restoreList(this._selectedProject.id))) + .pipe( + switchMap(_ => + forkJoin({ + userGroup: this._userService.getCurrentUserGroup(this._selectedProject.id).pipe(take(1)), + restores: this._backupService.restoreList(this._selectedProject.id).pipe(take(1)), + clusters: this._clusterService.clusters(this._selectedProject.id, false).pipe(take(1)), + }) + ) + ) .pipe(takeUntil(this._unsubscribe)) - .subscribe(restores => { + .subscribe(({userGroup, restores, clusters}) => { + this._currentGroupConfig = this._userService.getCurrentUserGroupConfig(userGroup); this._restores = restores; this.dataSource.data = this._restores; + clusters.forEach(cluster => this._clusters.set(cluster.id, cluster)); }); } @@ -109,6 +118,10 @@ export class RestoreListComponent implements OnInit, OnDestroy { this._unsubscribe.complete(); } + getClusterName(restore: EtcdRestore): string { + return this._clusters.get(restore.spec.clusterId)?.name ?? '-'; + } + delete(restore: EtcdRestore): void { const config: MatDialogConfig = { data: { diff --git a/modules/web/src/app/backup/list/restore/template.html b/modules/web/src/app/backup/list/restore/template.html index a32591620a..15099cbc62 100644 --- a/modules/web/src/app/backup/list/restore/template.html +++ b/modules/web/src/app/backup/list/restore/template.html @@ -51,6 +51,17 @@ + + Cluster Name + + + {{getClusterName(element)}} + + + (); dataSource = new MatTableDataSource(); isInitialized = true; @@ -55,7 +58,7 @@ export class SnapshotListComponent implements OnInit, OnDestroy { } get columns(): string[] { - return ['status', 'name', 'cluster', 'destination', 'created', 'actions']; + return ['status', 'name', 'cluster-name', 'cluster', 'destination', 'created', 'actions']; } get isEmpty(): boolean { @@ -79,6 +82,7 @@ export class SnapshotListComponent implements OnInit, OnDestroy { } constructor( + private readonly _clusterService: ClusterService, private readonly _backupService: BackupService, private readonly _projectService: ProjectService, private readonly _userService: UserService, @@ -98,20 +102,24 @@ export class SnapshotListComponent implements OnInit, OnDestroy { this._projectService.selectedProject .pipe( - switchMap(project => { - this._selectedProject = project; - return this._userService.getCurrentUserGroup(project.id); - }) + switchMap(project => + forkJoin({ + userGroup: this._userService.getCurrentUserGroup(project.id).pipe(take(1)), + backups: this._backupService.list(project.id, true).pipe(take(1)), + clusters: this._clusterService.clusters(project.id, false).pipe(take(1)), + project: of(project), + }) + ) ) .pipe(takeUntil(this._unsubscribe)) - .subscribe(userGroup => (this._currentGroupConfig = this._userService.getCurrentUserGroupConfig(userGroup))); + .subscribe(({userGroup, backups, clusters, project}) => { + this._selectedProject = project; + this._currentGroupConfig = this._userService.getCurrentUserGroupConfig(userGroup); - this._projectService.selectedProject - .pipe(switchMap(project => this._backupService.list(project.id, true))) - .pipe(takeUntil(this._unsubscribe)) - .subscribe(backups => { this._backups = backups; this.dataSource.data = this._backups; + + clusters.forEach(cluster => this._clusters.set(cluster.id, cluster)); }); } @@ -129,6 +137,10 @@ export class SnapshotListComponent implements OnInit, OnDestroy { return getBackupHealthStatus(backup, condition); } + getClusterName(backup: EtcdBackupConfig): string { + return this._clusters.get(backup.spec.clusterId)?.name ?? '-'; + } + delete(backup: EtcdBackupConfig): void { const config: MatDialogConfig = { data: { diff --git a/modules/web/src/app/backup/list/snapshot/template.html b/modules/web/src/app/backup/list/snapshot/template.html index ba74c735ba..4e226b8959 100644 --- a/modules/web/src/app/backup/list/snapshot/template.html +++ b/modules/web/src/app/backup/list/snapshot/template.html @@ -61,6 +61,17 @@ + + Cluster Name + + + {{getClusterName(element)}} + + +