From: Naman Munet Date: Tue, 18 Feb 2025 12:58:01 +0000 (+0530) Subject: mgr/dashboard: Update bucket details section after making bucket lifecycle changesn X-Git-Tag: v20.0.0~68^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F61875%2Fhead;p=ceph.git mgr/dashboard: Update bucket details section after making bucket lifecycle changesn Fixes: https://tracker.ceph.com/issues/69988 Signed-off-by: Naman Munet --- diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.html index 1e02f6b357d6..2c22cf80c609 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.html @@ -176,15 +176,19 @@ Lifecycle Progress + class="bold w-25"> + Lifecycle progress + - - {{ lifecycleProgress }} + [type]="lifecycleProgressMap.get(lifecycleProgress.status)?.color"> + {{ lifecycleProgress.status }} +
{{lifecycleProgress?.started}}
@@ -230,7 +234,8 @@ Tiering - + diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.scss index 4d05a9f5df70..4412732255e2 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.scss +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.scss @@ -1,3 +1,5 @@ +@use '@carbon/layout'; + table { table-layout: fixed; } @@ -11,3 +13,7 @@ table td { max-height: 50vh; overflow: auto; } + +.spacing-left { + margin-left: layout.$spacing-03; +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.spec.ts index efef91826d11..558defba0a28 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.spec.ts @@ -55,7 +55,7 @@ describe('RgwBucketDetailsComponent', () => { rgwBucketServiceGetSpy.and.returnValue(of(bucket)); component.selection = { bid: 'bucket' }; component.lifecycleFormat = 'json'; - component.ngOnChanges(); + component.extraxtDetailsfromResponse(); expect(component.selection.lifecycle).toEqual({}); }); @@ -85,7 +85,7 @@ describe('RgwBucketDetailsComponent', () => { const rateLimit = { bucket_ratelimit: { max_size: 1000 } }; spyOn(rgwBucketService, 'getBucketRateLimit').and.returnValue(of(rateLimit)); component.selection = { bid: 'bucket' }; - component.ngOnChanges(); + component.extraxtDetailsfromResponse(); expect(component.bucketRateLimit).toEqual(rateLimit.bucket_ratelimit); }); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.ts index c970a4eee12e..b95faa3140eb 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.ts @@ -13,7 +13,7 @@ import { RgwRateLimitConfig } from '../models/rgw-rate-limit'; export class RgwBucketDetailsComponent implements OnChanges { @Input() selection: any; - lifecycleProgress: string; + lifecycleProgress: { bucket: string; status: string; started: string }; lifecycleProgressMap = new Map([ ['UNINITIAL', { description: $localize`The process has not run yet`, color: 'cool-gray' }], ['PROCESSING', { description: $localize`The process is currently running`, color: 'cyan' }], @@ -27,33 +27,7 @@ export class RgwBucketDetailsComponent implements OnChanges { constructor(private rgwBucketService: RgwBucketService) {} ngOnChanges() { - if (this.selection) { - this.rgwBucketService.get(this.selection.bid).subscribe((bucket: object) => { - bucket['lock_retention_period_days'] = this.rgwBucketService.getLockDays(bucket); - this.selection = bucket; - if (this.lifecycleFormat === 'json' && !this.selection.lifecycle) { - this.selection.lifecycle = {}; - } - this.aclPermissions = this.parseXmlAcl(this.selection.acl, this.selection.owner); - if (this.selection.replication?.['Rule']?.['Status']) { - this.replicationStatus = this.selection.replication?.['Rule']?.['Status']; - } - if (this.selection.lifecycle_progress?.length > 0) { - this.selection.lifecycle_progress.forEach( - (progress: { bucket: string; status: string; started: string }) => { - if (progress.bucket.includes(this.selection.bucket)) { - this.lifecycleProgress = progress.status; - } - } - ); - } - }); - this.rgwBucketService.getBucketRateLimit(this.selection.bid).subscribe((resp: any) => { - if (resp && resp.bucket_ratelimit !== undefined) { - this.bucketRateLimit = resp.bucket_ratelimit; - } - }); - } + this.updateBucketDetails(this.extraxtDetailsfromResponse.bind(this)); } parseXmlAcl(xml: any, bucketOwner: string): Record { @@ -90,4 +64,42 @@ export class RgwBucketDetailsComponent implements OnChanges { }); return data; } + + updateBucketDetails(cbFn: Function) { + if (this.selection) { + this.rgwBucketService.get(this.selection.bid).subscribe((bucket: object) => { + bucket['lock_retention_period_days'] = this.rgwBucketService.getLockDays(bucket); + this.selection = bucket; + cbFn(); + }); + } + } + + extraxtDetailsfromResponse() { + this.aclPermissions = this.parseXmlAcl(this.selection.acl, this.selection.owner); + if (this.selection.replication?.['Rule']?.['Status']) { + this.replicationStatus = this.selection.replication?.['Rule']?.['Status']; + } + this.rgwBucketService.getBucketRateLimit(this.selection.bid).subscribe((resp: any) => { + if (resp && resp.bucket_ratelimit !== undefined) { + this.bucketRateLimit = resp.bucket_ratelimit; + } + }); + this.extractLifecycleDetails(); + } + + extractLifecycleDetails() { + if (this.lifecycleFormat === 'json' && !this.selection.lifecycle) { + this.selection.lifecycle = {}; + } + if (this.selection.lifecycle_progress?.length > 0) { + this.selection.lifecycle_progress.forEach( + (progress: { bucket: string; status: string; started: string }) => { + if (progress.bucket.includes(this.selection.bucket)) { + this.lifecycleProgress = progress; + } + } + ); + } + } } diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-lifecycle-list/rgw-bucket-lifecycle-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-lifecycle-list/rgw-bucket-lifecycle-list.component.ts index 759f42571286..a48feebe2372 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-lifecycle-list/rgw-bucket-lifecycle-list.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-lifecycle-list/rgw-bucket-lifecycle-list.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit, ViewChild } from '@angular/core'; +import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'; import { Bucket } from '../models/rgw-bucket'; import { RgwBucketService } from '~/app/shared/api/rgw-bucket.service'; import { AuthStorageService } from '~/app/shared/services/auth-storage.service'; @@ -25,6 +25,7 @@ import { NotificationType } from '~/app/shared/enum/notification-type.enum'; }) export class RgwBucketLifecycleListComponent implements OnInit { @Input() bucket: Bucket; + @Output() updateBucketDetails = new EventEmitter(); @ViewChild(TableComponent, { static: true }) table: TableComponent; permission: Permission; @@ -115,11 +116,12 @@ export class RgwBucketLifecycleListComponent implements OnInit { } openTieringModal(type: string) { - this.modalService.show(RgwBucketTieringFormComponent, { + const modalRef = this.modalService.show(RgwBucketTieringFormComponent, { bucket: this.bucket, selectedLifecycle: this.selection.first(), editing: type === this.actionLabels.EDIT ? true : false }); + modalRef?.close?.subscribe(() => this.updateBucketDetails.emit()); } updateSelection(selection: CdTableSelection) { @@ -149,6 +151,7 @@ export class RgwBucketLifecycleListComponent implements OnInit { NotificationType.success, $localize`Lifecycle rule deleted successfully` ); + this.updateBucketDetails.emit(); }, error: () => { this.modalRef.componentInstance.stopLoadingSpinner(); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.spec.ts index a1dff9182a35..121d39da0b93 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.spec.ts @@ -55,7 +55,7 @@ describe('RgwBucketListComponent', () => { expect(tableActions).toEqual({ 'create,update,delete': { - actions: ['Create', 'Edit', 'Delete', 'Tiering'], + actions: ['Create', 'Edit', 'Tiering', 'Delete'], primary: { multiple: 'Create', executing: 'Create', @@ -91,7 +91,7 @@ describe('RgwBucketListComponent', () => { } }, 'update,delete': { - actions: ['Edit', 'Delete', 'Tiering'], + actions: ['Edit', 'Tiering', 'Delete'], primary: { multiple: '', executing: '', diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.ts index 4761ff69d072..a9fdde02f143 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.ts @@ -137,7 +137,7 @@ export class RgwBucketListComponent extends ListWithDetails implements OnInit, O disable: () => !this.selection.hasSelection, name: this.actionLabels.TIERING }; - this.tableActions = [addAction, editAction, deleteAction, tieringAction]; + this.tableActions = [addAction, editAction, tieringAction, deleteAction]; this.setTableRefreshTimeout(); }