]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: Refresh button on the iscsi targets page 42817/head
authorNizamudeen A <nia@redhat.com>
Mon, 9 Aug 2021 07:52:51 +0000 (13:22 +0530)
committerNizamudeen A <nia@redhat.com>
Tue, 17 Aug 2021 13:44:46 +0000 (19:14 +0530)
Added a refresh button on the iscsi targets page. I've noticed that the
auto reload causes some load on the backend. So I disabled the auto
reload and went for the same approach as we have on rgw. A yellow
warning color on refresh btn to let the user know to manually refresh
that whenever needed.

Fixes: https://tracker.ceph.com/issues/52102
Signed-off-by: Nizamudeen A <nia@redhat.com>
(cherry picked from commit 8f23a587a8ccc686b1e3acbfa587fcab76bee45d)

src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-list/iscsi-target-list.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-list/iscsi-target-list.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-list/iscsi-target-list.component.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-list/rgw-user-list.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-list/rgw-user-list.component.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/classes/list-with-details.class.ts

index 0103c11249a1bf2aa5daa7c622a35d42adfd3c51..f6ac54538e10479985987bb0cb8200adc83416a3 100644 (file)
@@ -23,6 +23,9 @@
           forceIdentifier="true"
           selectionType="single"
           [hasDetails]="true"
+          [autoReload]="false"
+          [status]="tableStatus"
+          (fetchData)="getTargets()"
           (setExpandedRow)="setExpandedRow($event)"
           (updateSelection)="updateSelection($event)">
   <div class="table-actions btn-toolbar">
index 4459f2519e61c241745bf015870a4474ca33a082..51998cf0b9e1cb5ab185b29be3db1fc6c0ae8fd0 100644 (file)
@@ -56,6 +56,7 @@ describe('IscsiTargetListComponent', () => {
 
     spyOn(iscsiService, 'status').and.returnValue(of({ available: true }));
     spyOn(iscsiService, 'version').and.returnValue(of({ ceph_iscsi_config_version: 11 }));
+    spyOn(component, 'setTableRefreshTimeout').and.stub();
   });
 
   it('should create', () => {
@@ -84,6 +85,12 @@ describe('IscsiTargetListComponent', () => {
       summaryService['summaryDataSource'].error(undefined);
       expect(component.table.reset).toHaveBeenCalled();
     });
+
+    it('should call settings on the getTargets methods', () => {
+      spyOn(iscsiService, 'settings').and.callThrough();
+      component.getTargets();
+      expect(iscsiService.settings).toHaveBeenCalled();
+    });
   });
 
   describe('handling of executing tasks', () => {
index 96b76d6b749e573a1f57ad5da43e3298b5e072b4..d0eed6a72c77ed11cf3f77badafdac443056bbb8 100644 (file)
@@ -1,4 +1,4 @@
-import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
+import { Component, NgZone, OnDestroy, OnInit, ViewChild } from '@angular/core';
 
 import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
 import _ from 'lodash';
@@ -64,9 +64,10 @@ export class IscsiTargetListComponent extends ListWithDetails implements OnInit,
     private notAvailablePipe: NotAvailablePipe,
     private modalService: ModalService,
     private taskWrapper: TaskWrapperService,
-    public actionLabels: ActionLabelsI18n
+    public actionLabels: ActionLabelsI18n,
+    protected ngZone: NgZone
   ) {
-    super();
+    super(ngZone);
     this.permission = this.authStorageService.getPermissions().iscsi;
 
     this.tableActions = [
@@ -124,29 +125,34 @@ export class IscsiTargetListComponent extends ListWithDetails implements OnInit,
     this.iscsiService.status().subscribe((result: any) => {
       this.available = result.available;
 
-      if (result.available) {
-        this.iscsiService.version().subscribe((res: any) => {
-          this.cephIscsiConfigVersion = res['ceph_iscsi_config_version'];
-          this.taskListService.init(
-            () => this.iscsiService.listTargets(),
-            (resp) => this.prepareResponse(resp),
-            (targets) => (this.targets = targets),
-            () => this.onFetchError(),
-            this.taskFilter,
-            this.itemFilter,
-            this.builders
-          );
-        });
-
-        this.iscsiService.settings().subscribe((settings: any) => {
-          this.settings = settings;
-        });
-      } else {
+      if (!result.available) {
         this.status = result.message;
       }
     });
   }
 
+  getTargets() {
+    if (this.available) {
+      this.setTableRefreshTimeout();
+      this.iscsiService.version().subscribe((res: any) => {
+        this.cephIscsiConfigVersion = res['ceph_iscsi_config_version'];
+      });
+      this.taskListService.init(
+        () => this.iscsiService.listTargets(),
+        (resp) => this.prepareResponse(resp),
+        (targets) => (this.targets = targets),
+        () => this.onFetchError(),
+        this.taskFilter,
+        this.itemFilter,
+        this.builders
+      );
+
+      this.iscsiService.settings().subscribe((settings: any) => {
+        this.settings = settings;
+      });
+    }
+  }
+
   ngOnDestroy() {
     if (this.summaryDataSubscription) {
       this.summaryDataSubscription.unsubscribe();
index 94dc9f070a15be6d45994899197913328a4ba423..ff070579317652ed649c2135c3c271d631ca70f6 100644 (file)
@@ -36,7 +36,7 @@ describe('RgwBucketListComponent', () => {
     rgwBucketServiceListSpy.and.returnValue(of([]));
     fixture = TestBed.createComponent(RgwBucketListComponent);
     component = fixture.componentInstance;
-    spyOn(component, 'timeConditionReached').and.stub();
+    spyOn(component, 'setTableRefreshTimeout').and.stub();
     fixture.detectChanges();
   });
 
index 0355e4808a3ca7c50586767ba115df3abe28bf23..515a0697dbc601faa59baf3c4f7365b059f0b191 100644 (file)
@@ -5,7 +5,6 @@ import { forkJoin as observableForkJoin, Observable, Subscriber } from 'rxjs';
 
 import { RgwBucketService } from '~/app/shared/api/rgw-bucket.service';
 import { ListWithDetails } from '~/app/shared/classes/list-with-details.class';
-import { TableStatus } from '~/app/shared/classes/table-status';
 import { CriticalConfirmationModalComponent } from '~/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
 import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
 import { TableComponent } from '~/app/shared/datatable/table/table.component';
@@ -42,7 +41,6 @@ export class RgwBucketListComponent extends ListWithDetails implements OnInit {
   columns: CdTableColumn[] = [];
   buckets: object[] = [];
   selection: CdTableSelection = new CdTableSelection();
-  tableStatus = new TableStatus();
   staleTimeout: number;
 
   constructor(
@@ -53,9 +51,9 @@ export class RgwBucketListComponent extends ListWithDetails implements OnInit {
     private modalService: ModalService,
     private urlBuilder: URLBuilderService,
     public actionLabels: ActionLabelsI18n,
-    private ngZone: NgZone
+    protected ngZone: NgZone
   ) {
-    super();
+    super(ngZone);
   }
 
   ngOnInit() {
@@ -120,7 +118,7 @@ export class RgwBucketListComponent extends ListWithDetails implements OnInit {
       canBePrimary: (selection: CdTableSelection) => selection.hasMultiSelection
     };
     this.tableActions = [addAction, editAction, deleteAction];
-    this.timeConditionReached();
+    this.setTableRefreshTimeout();
   }
 
   transformBucketData() {
@@ -140,23 +138,8 @@ export class RgwBucketListComponent extends ListWithDetails implements OnInit {
     });
   }
 
-  timeConditionReached() {
-    clearTimeout(this.staleTimeout);
-    this.ngZone.runOutsideAngular(() => {
-      this.staleTimeout = window.setTimeout(() => {
-        this.ngZone.run(() => {
-          this.tableStatus = new TableStatus(
-            'warning',
-            $localize`The bucket list data might be stale. If needed, you can manually reload it.`
-          );
-        });
-      }, 10000);
-    });
-  }
-
   getBucketList(context: CdTableFetchDataContext) {
-    this.tableStatus = new TableStatus();
-    this.timeConditionReached();
+    this.setTableRefreshTimeout();
     this.rgwBucketService.list().subscribe(
       (resp: object[]) => {
         this.buckets = resp;
index 379957d88ec73d521126932cdb7aecf4552fb6b5..2f886ccf5d4a42cfa5f740e9496de884d859451c 100644 (file)
@@ -30,7 +30,7 @@ describe('RgwUserListComponent', () => {
     rgwUserServiceListSpy.and.returnValue(of([]));
     fixture = TestBed.createComponent(RgwUserListComponent);
     component = fixture.componentInstance;
-    spyOn(component, 'timeConditionReached').and.stub();
+    spyOn(component, 'setTableRefreshTimeout').and.stub();
     fixture.detectChanges();
   });
 
index e7f47298ecffb14d58a6139d1fee904b7356b0c6..e48aaa7c406409de9f70440c9a81244ca1d2790e 100644 (file)
@@ -5,7 +5,6 @@ import { forkJoin as observableForkJoin, Observable, Subscriber } from 'rxjs';
 
 import { RgwUserService } from '~/app/shared/api/rgw-user.service';
 import { ListWithDetails } from '~/app/shared/classes/list-with-details.class';
-import { TableStatus } from '~/app/shared/classes/table-status';
 import { CriticalConfirmationModalComponent } from '~/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
 import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
 import { TableComponent } from '~/app/shared/datatable/table/table.component';
@@ -40,7 +39,6 @@ export class RgwUserListComponent extends ListWithDetails implements OnInit {
   columns: CdTableColumn[] = [];
   users: object[] = [];
   selection: CdTableSelection = new CdTableSelection();
-  tableStatus = new TableStatus();
   staleTimeout: number;
 
   constructor(
@@ -49,9 +47,9 @@ export class RgwUserListComponent extends ListWithDetails implements OnInit {
     private modalService: ModalService,
     private urlBuilder: URLBuilderService,
     public actionLabels: ActionLabelsI18n,
-    private ngZone: NgZone
+    protected ngZone: NgZone
   ) {
-    super();
+    super(ngZone);
   }
 
   ngOnInit() {
@@ -131,26 +129,11 @@ export class RgwUserListComponent extends ListWithDetails implements OnInit {
       canBePrimary: (selection: CdTableSelection) => selection.hasMultiSelection
     };
     this.tableActions = [addAction, editAction, deleteAction];
-    this.timeConditionReached();
-  }
-
-  timeConditionReached() {
-    clearTimeout(this.staleTimeout);
-    this.ngZone.runOutsideAngular(() => {
-      this.staleTimeout = window.setTimeout(() => {
-        this.ngZone.run(() => {
-          this.tableStatus = new TableStatus(
-            'warning',
-            $localize`The user list data might be stale. If needed, you can manually reload it.`
-          );
-        });
-      }, 10000);
-    });
+    this.setTableRefreshTimeout();
   }
 
   getUserList(context: CdTableFetchDataContext) {
-    this.tableStatus = new TableStatus();
-    this.timeConditionReached();
+    this.setTableRefreshTimeout();
     this.rgwUserService.list().subscribe(
       (resp: object[]) => {
         this.users = resp;
index 585742622417eb910d2ffcf2e977fb30636eb3d3..2eaeeb35eecf85f6f31b7e7805e671ffdd59dfe1 100644 (file)
@@ -1,7 +1,29 @@
+import { NgZone } from '@angular/core';
+
+import { TableStatus } from './table-status';
+
 export class ListWithDetails {
   expandedRow: any;
+  staleTimeout: number;
+  tableStatus: TableStatus;
+
+  constructor(protected ngZone?: NgZone) {}
 
   setExpandedRow(expandedRow: any) {
     this.expandedRow = expandedRow;
   }
+
+  setTableRefreshTimeout() {
+    clearTimeout(this.staleTimeout);
+    this.ngZone.runOutsideAngular(() => {
+      this.staleTimeout = window.setTimeout(() => {
+        this.ngZone.run(() => {
+          this.tableStatus = new TableStatus(
+            'warning',
+            $localize`The user list data might be stale. If needed, you can manually reload it.`
+          );
+        });
+      }, 10000);
+    });
+  }
 }