]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: Display table status in refresh button 35980/head
authorTiago Melo <tmelo@suse.com>
Wed, 1 Jul 2020 09:12:32 +0000 (09:12 +0000)
committerTiago Melo <tmelo@suse.com>
Mon, 20 Jul 2020 09:11:33 +0000 (09:11 +0000)
Fixes: https://tracker.ceph.com/issues/40330
Signed-off-by: Tiago Melo <tmelo@suse.com>
40 files changed:
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/daemon-list/daemon-list.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/daemon-list/daemon-list.component.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/image-list/image-list.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/image-list/image-list.component.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/overview/overview.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-list/pool-list.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/mirroring/pool-list/pool-list.component.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-clients/cephfs-clients.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-clients/cephfs-clients.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-clients/cephfs-clients.component.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-tabs/cephfs-tabs.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-tabs/cephfs-tabs.component.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-list/pool-list.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-list/pool-list.component.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.html
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.html
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/table-status-view-cache.spec.ts [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/shared/classes/table-status-view-cache.ts [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/shared/classes/table-status.spec.ts [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/shared/classes/table-status.ts [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.html [deleted file]
src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.scss [deleted file]
src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.spec.ts [deleted file]
src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.ts [deleted file]
src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/datatable.module.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.html
src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/models/mirroring-summary.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-list.service.ts

index b7e42d6baa5843328a820e7d1f222b5401a9a160..c7c3bab87b4c1b444c87560a41d734aa6f0d0df6 100644 (file)
@@ -2,7 +2,8 @@
           columnMode="flex"
           [columns]="columns"
           [autoReload]="-1"
-          (fetchData)="refresh()">
+          (fetchData)="refresh()"
+          [status]="tableStatus">
 </cd-table>
 
 <ng-template #healthTmpl
index 399e88750d2c294f50b05a36551972837d79153d..e49a895d87dc08d8d7f742ff794b387d2d24ac55 100644 (file)
@@ -3,6 +3,7 @@ import { Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/c
 import { Subscription } from 'rxjs';
 
 import { RbdMirroringService } from '../../../../shared/api/rbd-mirroring.service';
+import { TableStatusViewCache } from '../../../../shared/classes/table-status-view-cache';
 import { CephShortVersionPipe } from '../../../../shared/pipes/ceph-short-version.pipe';
 
 @Component({
@@ -19,6 +20,8 @@ export class DaemonListComponent implements OnInit, OnDestroy {
   data: [];
   columns: {};
 
+  tableStatus = new TableStatusViewCache();
+
   constructor(
     private rbdMirroringService: RbdMirroringService,
     private cephShortVersionPipe: CephShortVersionPipe
@@ -45,6 +48,7 @@ export class DaemonListComponent implements OnInit, OnDestroy {
 
     this.subs = this.rbdMirroringService.subscribeSummary((data) => {
       this.data = data.content_data.daemons;
+      this.tableStatus = new TableStatusViewCache(data.status);
     });
   }
 
index ee2f3d0421b3ea2294c8383fb511e10e6bdf3247..25f1442f887598e7e7a0dc44399071cdcd41af32 100644 (file)
@@ -10,7 +10,8 @@
                 columnMode="flex"
                 [columns]="image_error.columns"
                 [autoReload]="-1"
-                (fetchData)="refresh()">
+                (fetchData)="refresh()"
+                [status]="tableStatus">
       </cd-table>
     </ng-template>
   </li>
@@ -22,7 +23,8 @@
                 columnMode="flex"
                 [columns]="image_syncing.columns"
                 [autoReload]="-1"
-                (fetchData)="refresh()">
+                (fetchData)="refresh()"
+                [status]="tableStatus">
       </cd-table>
     </ng-template>
   </li>
@@ -34,7 +36,8 @@
                 columnMode="flex"
                 [columns]="image_ready.columns"
                 [autoReload]="-1"
-                (fetchData)="refresh()">
+                (fetchData)="refresh()"
+                [status]="tableStatus">
       </cd-table>
     </ng-template>
   </li>
index 6b1db0c066132686225e01cb54a7a3325c1e0749..75744e3937bcacb4b0c48c0beca6e7f9ea5d67f3 100644 (file)
@@ -3,6 +3,7 @@ import { Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/c
 import { Subscription } from 'rxjs';
 
 import { RbdMirroringService } from '../../../../shared/api/rbd-mirroring.service';
+import { TableStatusViewCache } from '../../../../shared/classes/table-status-view-cache';
 
 @Component({
   selector: 'cd-mirroring-images',
@@ -32,6 +33,8 @@ export class ImageListComponent implements OnInit, OnDestroy {
     columns: {}
   };
 
+  tableStatus = new TableStatusViewCache();
+
   constructor(private rbdMirroringService: RbdMirroringService) {}
 
   ngOnInit() {
@@ -80,6 +83,7 @@ export class ImageListComponent implements OnInit, OnDestroy {
       this.image_error.data = data.content_data.image_error;
       this.image_syncing.data = data.content_data.image_syncing;
       this.image_ready.data = data.content_data.image_ready;
+      this.tableStatus = new TableStatusViewCache(data.status);
     });
   }
 
index 38e7fa8d0a79f82dd7800975a0e90fa360d0835c..7bd0bf017b370f2b710452290a5dd5b156c73c87 100644 (file)
@@ -1,5 +1,3 @@
-<cd-view-cache [status]="status"></cd-view-cache>
-
 <div class="row">
   <div class="col-md-12">
     <span><strong i18n>Site Name:</strong> {{siteName}}</span>
index 755da08342b6d434ea138fbe79b06070ceaf0d15..b6081b8e03d634e371f564e887ca6162019f74ce 100644 (file)
@@ -6,7 +6,8 @@
           [autoReload]="-1"
           (fetchData)="refresh()"
           selectionType="single"
-          (updateSelection)="updateSelection($event)">
+          (updateSelection)="updateSelection($event)"
+          [status]="tableStatus">
   <cd-table-actions class="table-actions"
                     [permission]="permission"
                     [selection]="selection"
index 6c18acc08ce1082c6fdc0a86f531f898eb14f0ff..356927ea8f44b1718348db3e9a8ec833b2a369aa 100644 (file)
@@ -4,6 +4,7 @@ import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
 import { Observable, Subscriber, Subscription } from 'rxjs';
 
 import { RbdMirroringService } from '../../../../shared/api/rbd-mirroring.service';
+import { TableStatusViewCache } from '../../../../shared/classes/table-status-view-cache';
 import { CriticalConfirmationModalComponent } from '../../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
 import { Icons } from '../../../../shared/enum/icons.enum';
 import { CdTableAction } from '../../../../shared/models/cd-table-action';
@@ -36,6 +37,8 @@ export class PoolListComponent implements OnInit, OnDestroy {
   data: [];
   columns: {};
 
+  tableStatus = new TableStatusViewCache();
+
   constructor(
     private authStorageService: AuthStorageService,
     private rbdMirroringService: RbdMirroringService,
@@ -95,6 +98,7 @@ export class PoolListComponent implements OnInit, OnDestroy {
 
     this.subs = this.rbdMirroringService.subscribeSummary((data) => {
       this.data = data.content_data.pools;
+      this.tableStatus = new TableStatusViewCache(data.status);
     });
   }
 
index 4150269993f82c3733191cb4f1b4b749a4eb7ae0..a0b9148596a5569a15d3d5a4c9625890a919d589 100644 (file)
@@ -3,7 +3,7 @@ import { FormsModule } from '@angular/forms';
 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
 import { RouterTestingModule } from '@angular/router/testing';
 
-import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
+import { NgbDropdownModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';
 import { NgxDatatableModule } from '@swimlane/ngx-datatable';
 import { ChartsModule } from 'ng2-charts';
 
@@ -29,7 +29,8 @@ describe('RbdConfigurationListComponent', () => {
       ComponentsModule,
       NgbDropdownModule,
       ChartsModule,
-      PipesModule
+      PipesModule,
+      NgbTooltipModule
     ],
     declarations: [RbdConfigurationListComponent, TableComponent],
     providers: [FormatterService, RbdConfigurationService]
index dc198e90724f6d0b8d2329b463cb5ca3f7d931a4..c254597b350868e27c585a2ae3bd6c9aa7134d0b 100644 (file)
@@ -1,9 +1,5 @@
 <cd-rbd-tabs></cd-rbd-tabs>
 
-<cd-view-cache *ngFor="let viewCacheStatus of viewCacheStatusList"
-               [status]="viewCacheStatus.status"
-               [statusFor]="viewCacheStatus.statusFor"></cd-view-cache>
-
 <cd-table #table
           [data]="images"
           columnMode="flex"
@@ -13,6 +9,9 @@
           forceIdentifier="true"
           selectionType="single"
           [hasDetails]="true"
+          [status]="tableStatus"
+          [autoReload]="-1"
+          (fetchData)="taskListService.fetch()"
           (setExpandedRow)="setExpandedRow($event)"
           (updateSelection)="updateSelection($event)">
   <cd-table-actions class="table-actions"
index 193a338feb773c2e76f4f8b040123c2ccf0cc5a0..a029c83f9b1f4e8c5df81114a12faa78519b58c0 100644 (file)
@@ -13,6 +13,7 @@ import {
   PermissionHelper
 } from '../../../../testing/unit-test-helper';
 import { RbdService } from '../../../shared/api/rbd.service';
+import { TableStatusViewCache } from '../../../shared/classes/table-status-view-cache';
 import { TableActionsComponent } from '../../../shared/datatable/table-actions/table-actions.component';
 import { ViewCacheStatus } from '../../../shared/enum/view-cache-status.enum';
 import { ExecutingTask } from '../../../shared/models/executing-task';
@@ -91,7 +92,9 @@ describe('RbdListComponent', () => {
       spyOn(component.table, 'reset');
       summaryService['summaryDataSource'].error(undefined);
       expect(component.table.reset).toHaveBeenCalled();
-      expect(component.viewCacheStatusList).toEqual([{ status: ViewCacheStatus.ValueException }]);
+      expect(component.tableStatus).toEqual(
+        new TableStatusViewCache(ViewCacheStatus.ValueException)
+      );
     });
   });
 
index 18ac272143e6264031828e610232b69e2f3bb6c0..3b3af0c8d117b6f7111b9293f1a1cc536a283e86 100644 (file)
@@ -5,6 +5,7 @@ import * as _ from 'lodash';
 
 import { RbdService } from '../../../shared/api/rbd.service';
 import { ListWithDetails } from '../../../shared/classes/list-with-details.class';
+import { TableStatusViewCache } from '../../../shared/classes/table-status-view-cache';
 import { ConfirmationModalComponent } from '../../../shared/components/confirmation-modal/confirmation-modal.component';
 import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
 import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
@@ -60,7 +61,7 @@ export class RbdListComponent extends ListWithDetails implements OnInit {
   images: any;
   columns: CdTableColumn[];
   retries: number;
-  viewCacheStatusList: any[];
+  tableStatus = new TableStatusViewCache();
   selection = new CdTableSelection();
 
   modalRef: NgbModalRef;
@@ -106,7 +107,7 @@ export class RbdListComponent extends ListWithDetails implements OnInit {
     private dimlessPipe: DimlessPipe,
     private modalService: ModalService,
     private taskWrapper: TaskWrapperService,
-    private taskListService: TaskListService,
+    public taskListService: TaskListService,
     private urlBuilder: URLBuilderService,
     public actionLabels: ActionLabelsI18n
   ) {
@@ -299,12 +300,13 @@ export class RbdListComponent extends ListWithDetails implements OnInit {
 
   onFetchError() {
     this.table.reset(); // Disable loading indicator.
-    this.viewCacheStatusList = [{ status: ViewCacheStatus.ValueException }];
+    this.tableStatus = new TableStatusViewCache(ViewCacheStatus.ValueException);
   }
 
   prepareResponse(resp: any[]): any[] {
     let images: any[] = [];
     const viewCacheStatusMap = {};
+
     resp.forEach((pool) => {
       if (_.isUndefined(viewCacheStatusMap[pool.status])) {
         viewCacheStatusMap[pool.status] = [];
@@ -312,18 +314,26 @@ export class RbdListComponent extends ListWithDetails implements OnInit {
       viewCacheStatusMap[pool.status].push(pool.pool_name);
       images = images.concat(pool.value);
     });
-    const viewCacheStatusList: any[] = [];
-    _.forEach(viewCacheStatusMap, (value: any, key) => {
-      viewCacheStatusList.push({
-        status: parseInt(key, 10),
-        statusFor:
-          (value.length > 1 ? 'pools ' : 'pool ') +
-          '<strong>' +
-          value.join('</strong>, <strong>') +
-          '</strong>'
-      });
-    });
-    this.viewCacheStatusList = viewCacheStatusList;
+
+    let status: number;
+    if (viewCacheStatusMap[ViewCacheStatus.ValueException]) {
+      status = ViewCacheStatus.ValueException;
+    } else if (viewCacheStatusMap[ViewCacheStatus.ValueStale]) {
+      status = ViewCacheStatus.ValueStale;
+    } else if (viewCacheStatusMap[ViewCacheStatus.ValueNone]) {
+      status = ViewCacheStatus.ValueNone;
+    }
+
+    if (status) {
+      const statusFor =
+        (viewCacheStatusMap[status].length > 1 ? 'pools ' : 'pool ') +
+        viewCacheStatusMap[status].join();
+
+      this.tableStatus = new TableStatusViewCache(status, statusFor);
+    } else {
+      this.tableStatus = new TableStatusViewCache();
+    }
+
     return images;
   }
 
index ac9bc04c8f70d8609814dec47a816495104dfeb2..340d0d0d4993a2dee54ff733ffbb20e706461896 100644 (file)
@@ -1,15 +1,14 @@
 <cd-rbd-tabs></cd-rbd-tabs>
 
-<cd-view-cache *ngFor="let viewCacheStatus of viewCacheStatusList"
-               [status]="viewCacheStatus.status"
-               [statusFor]="viewCacheStatus.statusFor"></cd-view-cache>
-
 <cd-table [data]="images"
           columnMode="flex"
           [columns]="columns"
           identifier="id"
           forceIdentifier="true"
           selectionType="single"
+          [status]="tableStatus"
+          [autoReload]="-1"
+          (fetchData)="taskListService.fetch()"
           (updateSelection)="updateSelection($event)">
   <div class="table-actions btn-toolbar">
     <cd-table-actions class="btn-group"
index 63b4d085bb384ac61b59f311ad610b09b0979a5c..f6743c6607e72ba2dde2b7f904bb7fa1bd4ff7c3 100644 (file)
@@ -5,6 +5,7 @@ import * as _ from 'lodash';
 import * as moment from 'moment';
 
 import { RbdService } from '../../../shared/api/rbd.service';
+import { TableStatusViewCache } from '../../../shared/classes/table-status-view-cache';
 import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
 import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
 import { TableComponent } from '../../../shared/datatable/table/table.component';
@@ -51,7 +52,7 @@ export class RbdTrashListComponent implements OnInit {
   retries: number;
   selection = new CdTableSelection();
   tableActions: CdTableAction[];
-  viewCacheStatusList: any[];
+  tableStatus = new TableStatusViewCache();
   disablePurgeBtn = true;
 
   constructor(
@@ -59,7 +60,7 @@ export class RbdTrashListComponent implements OnInit {
     private rbdService: RbdService,
     private modalService: ModalService,
     private cdDatePipe: CdDatePipe,
-    private taskListService: TaskListService,
+    public taskListService: TaskListService,
     private taskWrapper: TaskWrapperService,
     public actionLabels: ActionLabelsI18n
   ) {
@@ -139,6 +140,7 @@ export class RbdTrashListComponent implements OnInit {
   prepareResponse(resp: any[]): any[] {
     let images: any[] = [];
     const viewCacheStatusMap = {};
+
     resp.forEach((pool: Record<string, any>) => {
       if (_.isUndefined(viewCacheStatusMap[pool.status])) {
         viewCacheStatusMap[pool.status] = [];
@@ -148,27 +150,35 @@ export class RbdTrashListComponent implements OnInit {
       this.disablePurgeBtn = !images.length;
     });
 
-    const viewCacheStatusList: any[] = [];
-    _.forEach(viewCacheStatusMap, (value: any, key) => {
-      viewCacheStatusList.push({
-        status: parseInt(key, 10),
-        statusFor:
-          (value.length > 1 ? 'pools ' : 'pool ') +
-          '<strong>' +
-          value.join('</strong>, <strong>') +
-          '</strong>'
-      });
-    });
-    this.viewCacheStatusList = viewCacheStatusList;
+    let status: number;
+    if (viewCacheStatusMap[3]) {
+      status = 3;
+    } else if (viewCacheStatusMap[1]) {
+      status = 1;
+    } else if (viewCacheStatusMap[2]) {
+      status = 2;
+    }
+
+    if (status) {
+      const statusFor =
+        (viewCacheStatusMap[status].length > 1 ? 'pools ' : 'pool ') +
+        viewCacheStatusMap[status].join();
+
+      this.tableStatus = new TableStatusViewCache(status, statusFor);
+    } else {
+      this.tableStatus = new TableStatusViewCache();
+    }
+
     images.forEach((image) => {
       image.cdIsExpired = moment().isAfter(image.deferment_end_time);
     });
+
     return images;
   }
 
   onFetchError() {
     this.table.reset(); // Disable loading indicator.
-    this.viewCacheStatusList = [{ status: ViewCacheStatus.ValueException }];
+    this.tableStatus = new TableStatusViewCache(ViewCacheStatus.ValueException);
   }
 
   updateSelection(selection: CdTableSelection) {
index 91ad412900c3c35eb0e9f4882cb4df4acf842d63..cb1ee364c26af294dcd8eab4cc4aba4641b10baa 100644 (file)
@@ -1,7 +1,8 @@
-<cd-view-cache [status]="clients.status"></cd-view-cache>
-
 <cd-table [data]="clients.data"
           [columns]="columns"
+          [status]="clients.status"
+          [autoReload]="-1"
+          (fetchData)="triggerApiUpdate.emit()"
           selectionType="single"
           (updateSelection)="updateSelection($event)">
   <cd-table-actions class="table-actions"
index ea6ca381e9d464eb3bcdeb0b06ddac6deddde6ea..c3982a9cc1e6a68374e976ec7d290b370a5425c3 100644 (file)
@@ -5,6 +5,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
 import { ToastrModule } from 'ngx-toastr';
 
 import { configureTestBed, PermissionHelper } from '../../../../testing/unit-test-helper';
+import { TableStatusViewCache } from '../../../shared/classes/table-status-view-cache';
 import { TableActionsComponent } from '../../../shared/datatable/table-actions/table-actions.component';
 import { ViewCacheStatus } from '../../../shared/enum/view-cache-status.enum';
 import { SharedModule } from '../../../shared/shared.module';
@@ -28,7 +29,7 @@ describe('CephfsClientsComponent', () => {
     fixture = TestBed.createComponent(CephfsClientsComponent);
     component = fixture.componentInstance;
     component.clients = {
-      status: ViewCacheStatus.ValueOk,
+      status: new TableStatusViewCache(ViewCacheStatus.ValueOk),
       data: [{}, {}, {}, {}]
     };
   });
index 5d128fb7dd0103b9a158edc8c72aa358027b2c38..f88714d6fd1efb9eb18bee875094aec9459624e8 100644 (file)
@@ -3,11 +3,11 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
 import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
 
 import { CephfsService } from '../../../shared/api/cephfs.service';
+import { TableStatusViewCache } from '../../../shared/classes/table-status-view-cache';
 import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
 import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
 import { Icons } from '../../../shared/enum/icons.enum';
 import { NotificationType } from '../../../shared/enum/notification-type.enum';
-import { ViewCacheStatus } from '../../../shared/enum/view-cache-status.enum';
 import { CdTableAction } from '../../../shared/models/cd-table-action';
 import { CdTableColumn } from '../../../shared/models/cd-table-column';
 import { CdTableSelection } from '../../../shared/models/cd-table-selection';
@@ -28,7 +28,7 @@ export class CephfsClientsComponent implements OnInit {
   @Input()
   clients: {
     data: any[];
-    status: ViewCacheStatus;
+    status: TableStatusViewCache;
   };
 
   @Output()
index 714f4e467bfe5e0ec33e4b68cc80e5fbd807409d..92480eb2dbca67f17576328cef947c29f0c2cd8c 100644 (file)
@@ -10,6 +10,7 @@ import { of } from 'rxjs';
 
 import { configureTestBed } from '../../../../testing/unit-test-helper';
 import { CephfsService } from '../../../shared/api/cephfs.service';
+import { TableStatusViewCache } from '../../../shared/classes/table-status-view-cache';
 import { ViewCacheStatus } from '../../../shared/enum/view-cache-status.enum';
 import { SharedModule } from '../../../shared/shared.module';
 import { CephfsClientsComponent } from '../cephfs-clients/cephfs-clients.component';
@@ -146,7 +147,7 @@ describe('CephfsTabsComponent', () => {
     };
     const defaultClients: Record<string, any> = {
       data: [],
-      status: ViewCacheStatus.ValueNone
+      status: new TableStatusViewCache(ViewCacheStatus.ValueNone)
     };
     component['subscribeInterval'] = () => undefined;
     updateData();
index 3a24dec2ec9084892f1b5f07f4e6fb375661e210..64449b3919fae430eeb364bd75142f057a73503f 100644 (file)
@@ -4,6 +4,7 @@ import * as _ from 'lodash';
 import { Subscription, timer } from 'rxjs';
 
 import { CephfsService } from '../../../shared/api/cephfs.service';
+import { TableStatusViewCache } from '../../../shared/classes/table-status-view-cache';
 import { ViewCacheStatus } from '../../../shared/enum/view-cache-status.enum';
 import { Permission } from '../../../shared/models/permissions';
 import { AuthStorageService } from '../../../shared/services/auth-storage.service';
@@ -25,7 +26,7 @@ export class CephfsTabsComponent implements OnChanges, OnDestroy {
   id: number;
   clients: Record<string, any> = {
     data: [],
-    status: ViewCacheStatus.ValueNone
+    status: new TableStatusViewCache(ViewCacheStatus.ValueNone)
   };
 
   // Details tab
@@ -71,7 +72,7 @@ export class CephfsTabsComponent implements OnChanges, OnDestroy {
     };
     this.clients = {
       data: [],
-      status: ViewCacheStatus.ValueNone
+      status: new TableStatusViewCache(ViewCacheStatus.ValueNone)
     };
     this.updateInterval();
   }
@@ -103,7 +104,7 @@ export class CephfsTabsComponent implements OnChanges, OnDestroy {
         this.softRefresh();
       },
       () => {
-        this.clients.status = ViewCacheStatus.ValueException;
+        this.clients.status = new TableStatusViewCache(ViewCacheStatus.ValueException);
       }
     );
   }
@@ -112,6 +113,7 @@ export class CephfsTabsComponent implements OnChanges, OnDestroy {
     const data = _.cloneDeep(this.data); // Forces update of tab tables on tab switch
     // Clients tab
     this.clients = data.clients;
+    this.clients.status = new TableStatusViewCache(this.clients.status);
     // Details tab
     this.details = {
       standbys: data.standbys,
index bd313df7de1b0b14d7aa68706fc2351a83a2201b..2d3ee6976b47415d72adac61d5b87423b077a41d 100644 (file)
@@ -5,16 +5,15 @@
     <a ngbNavLink
        i18n>Pools List</a>
     <ng-template ngbNavContent>
-      <cd-view-cache *ngFor="let viewCacheStatus of viewCacheStatusList"
-                     [status]="viewCacheStatus.status"
-                     [statusFor]="viewCacheStatus.statusFor"></cd-view-cache>
-
       <cd-table #table
                 id="pool-list"
                 [data]="pools"
                 [columns]="columns"
                 selectionType="single"
                 [hasDetails]="true"
+                [status]="tableStatus"
+                [autoReload]="-1"
+                (fetchData)="taskListService.fetch()"
                 (setExpandedRow)="setExpandedRow($event)"
                 (updateSelection)="updateSelection($event)">
         <cd-table-actions id="pool-list-actions"
index eae76ef70c7f2fc2b36d8cbdcaa18017e065fecf..12fd577afb82e1f2de17063b8cb26f77a3de5f86 100644 (file)
@@ -6,6 +6,7 @@ import * as _ from 'lodash';
 import { ConfigurationService } from '../../../shared/api/configuration.service';
 import { PoolService } from '../../../shared/api/pool.service';
 import { ListWithDetails } from '../../../shared/classes/list-with-details.class';
+import { TableStatusViewCache } from '../../../shared/classes/table-status-view-cache';
 import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
 import { ActionLabelsI18n, URLVerbs } from '../../../shared/constants/app.constants';
 import { TableComponent } from '../../../shared/datatable/table/table.component';
@@ -55,7 +56,7 @@ export class PoolListComponent extends ListWithDetails implements OnInit {
   executingTasks: ExecutingTask[] = [];
   permissions: Permissions;
   tableActions: CdTableAction[];
-  viewCacheStatusList: any[];
+  tableStatus = new TableStatusViewCache();
   cacheTiers: any[] = [];
   monAllowPoolDelete = false;
 
@@ -63,7 +64,7 @@ export class PoolListComponent extends ListWithDetails implements OnInit {
     private poolService: PoolService,
     private taskWrapper: TaskWrapperService,
     private authStorageService: AuthStorageService,
-    private taskListService: TaskListService,
+    public taskListService: TaskListService,
     private modalService: ModalService,
     private pgCategoryService: PgCategoryService,
     private dimlessPipe: DimlessPipe,
@@ -202,10 +203,13 @@ export class PoolListComponent extends ListWithDetails implements OnInit {
     this.taskListService.init(
       () => this.poolService.getList(),
       undefined,
-      (pools) => (this.pools = this.transformPoolsData(pools)),
+      (pools) => {
+        this.pools = this.transformPoolsData(pools);
+        this.tableStatus = new TableStatusViewCache();
+      },
       () => {
         this.table.reset(); // Disable loading indicator.
-        this.viewCacheStatusList = [{ status: ViewCacheStatus.ValueException }];
+        this.tableStatus = new TableStatusViewCache(ViewCacheStatus.ValueException);
       },
       (task) => task.name.startsWith(`${BASE_URL}/`),
       (pool, task) => task.metadata['pool_name'] === pool.pool_name,
index a8844d6575e948fa978698ae70eb0d5c4f18ee9c..45bedb46f304d4cb2b09b8248740a0071b74d307 100644 (file)
@@ -1,7 +1,3 @@
-<cd-alert-panel *ngIf="isStale"
-                type="warning"
-                size="slim"
-                i18n>The bucket list data might be stale. If needed, you can manually reload it.</cd-alert-panel>
 <cd-table #table
           [autoReload]="false"
           [data]="buckets"
@@ -12,7 +8,8 @@
           (setExpandedRow)="setExpandedRow($event)"
           (updateSelection)="updateSelection($event)"
           identifier="bid"
-          (fetchData)="getBucketList($event)">
+          (fetchData)="getBucketList($event)"
+          [status]="tableStatus">
   <cd-table-actions class="table-actions"
                     [permission]="permission"
                     [selection]="selection"
index f35b19f8280ab12e8daae2953b8d443e4a23af1f..2cc2601488c5076044f6d23a2cbc29352c6da052 100644 (file)
@@ -12,6 +12,7 @@ import { forkJoin as observableForkJoin, Observable, Subscriber } from 'rxjs';
 
 import { RgwBucketService } from '../../../shared/api/rgw-bucket.service';
 import { ListWithDetails } from '../../../shared/classes/list-with-details.class';
+import { TableStatus } from '../../../shared/classes/table-status';
 import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
 import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
 import { TableComponent } from '../../../shared/datatable/table/table.component';
@@ -48,7 +49,7 @@ export class RgwBucketListComponent extends ListWithDetails implements OnInit {
   columns: CdTableColumn[] = [];
   buckets: object[] = [];
   selection: CdTableSelection = new CdTableSelection();
-  isStale = false;
+  tableStatus = new TableStatus();
   staleTimeout: number;
 
   constructor(
@@ -154,14 +155,17 @@ export class RgwBucketListComponent extends ListWithDetails implements OnInit {
     this.ngZone.runOutsideAngular(() => {
       this.staleTimeout = window.setTimeout(() => {
         this.ngZone.run(() => {
-          this.isStale = true;
+          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.isStale = false;
+    this.tableStatus = new TableStatus();
     this.timeConditionReached();
     this.rgwBucketService.list().subscribe(
       (resp: object[]) => {
index e274e8214d6f2752ca1f22904dba6b23d04be5b5..d751069689e675ea266003461e2b645aa1d1ca4e 100644 (file)
@@ -1,7 +1,3 @@
-<cd-alert-panel *ngIf="isStale"
-                type="warning"
-                size="slim"
-                i18n>The user list data might be stale. If needed, you can manually reload it.</cd-alert-panel>
 <cd-table #table
           [autoReload]="false"
           [data]="users"
@@ -12,7 +8,8 @@
           (setExpandedRow)="setExpandedRow($event)"
           (updateSelection)="updateSelection($event)"
           identifier="uid"
-          (fetchData)="getUserList($event)">
+          (fetchData)="getUserList($event)"
+          [status]="tableStatus">
   <cd-table-actions class="table-actions"
                     [permission]="permission"
                     [selection]="selection"
index d5ed7c17e8474059437aaab74fcc67c2956bbcc2..7dd344c7ca605dcd2ce18ace4f4b2e6ea7f6252b 100644 (file)
@@ -4,6 +4,7 @@ import { forkJoin as observableForkJoin, Observable, Subscriber } from 'rxjs';
 
 import { RgwUserService } from '../../../shared/api/rgw-user.service';
 import { ListWithDetails } from '../../../shared/classes/list-with-details.class';
+import { TableStatus } from '../../../shared/classes/table-status';
 import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
 import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
 import { TableComponent } from '../../../shared/datatable/table/table.component';
@@ -34,7 +35,7 @@ export class RgwUserListComponent extends ListWithDetails {
   columns: CdTableColumn[] = [];
   users: object[] = [];
   selection: CdTableSelection = new CdTableSelection();
-  isStale = false;
+  tableStatus = new TableStatus();
   staleTimeout: number;
 
   constructor(
@@ -113,14 +114,17 @@ export class RgwUserListComponent extends ListWithDetails {
     this.ngZone.runOutsideAngular(() => {
       this.staleTimeout = window.setTimeout(() => {
         this.ngZone.run(() => {
-          this.isStale = true;
+          this.tableStatus = new TableStatus(
+            'warning',
+            $localize`The user list data might be stale. If needed, you can manually reload it.`
+          );
         });
       }, 10000);
     });
   }
 
   getUserList(context: CdTableFetchDataContext) {
-    this.isStale = false;
+    this.tableStatus = new TableStatus();
     this.timeConditionReached();
     this.rgwUserService.list().subscribe(
       (resp: object[]) => {
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/classes/table-status-view-cache.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/classes/table-status-view-cache.spec.ts
new file mode 100644 (file)
index 0000000..cff2ec3
--- /dev/null
@@ -0,0 +1,40 @@
+import { ViewCacheStatus } from '../enum/view-cache-status.enum';
+import { TableStatusViewCache } from './table-status-view-cache';
+
+describe('TableStatusViewCache', () => {
+  it('should create an instance', () => {
+    const ts = new TableStatusViewCache();
+    expect(ts).toBeTruthy();
+    expect(ts).toEqual({ msg: '', type: 'light' });
+  });
+
+  it('should create a ValueStale instance', () => {
+    let ts = new TableStatusViewCache(ViewCacheStatus.ValueStale);
+    expect(ts).toEqual({ type: 'warning', msg: 'Displaying previously cached data.' });
+
+    ts = new TableStatusViewCache(ViewCacheStatus.ValueStale, 'foo bar');
+    expect(ts).toEqual({ type: 'warning', msg: 'Displaying previously cached data for foo bar.' });
+  });
+
+  it('should create a ValueNone instance', () => {
+    let ts = new TableStatusViewCache(ViewCacheStatus.ValueNone);
+    expect(ts).toEqual({ type: 'info', msg: 'Retrieving data. Please wait...' });
+
+    ts = new TableStatusViewCache(ViewCacheStatus.ValueNone, 'foo bar');
+    expect(ts).toEqual({ type: 'info', msg: 'Retrieving data for foo bar. Please wait...' });
+  });
+
+  it('should create a ValueException instance', () => {
+    let ts = new TableStatusViewCache(ViewCacheStatus.ValueException);
+    expect(ts).toEqual({
+      type: 'danger',
+      msg: 'Could not load data. Please check the cluster health.'
+    });
+
+    ts = new TableStatusViewCache(ViewCacheStatus.ValueException, 'foo bar');
+    expect(ts).toEqual({
+      type: 'danger',
+      msg: 'Could not load data for foo bar. Please check the cluster health.'
+    });
+  });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/classes/table-status-view-cache.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/classes/table-status-view-cache.ts
new file mode 100644 (file)
index 0000000..91c53a0
--- /dev/null
@@ -0,0 +1,37 @@
+import { ViewCacheStatus } from '../enum/view-cache-status.enum';
+import { TableStatus } from './table-status';
+
+export class TableStatusViewCache extends TableStatus {
+  constructor(status: ViewCacheStatus = ViewCacheStatus.ValueOk, statusFor: string = '') {
+    super();
+
+    switch (status) {
+      case ViewCacheStatus.ValueOk:
+        this.type = 'light';
+        this.msg = '';
+        break;
+      case ViewCacheStatus.ValueNone:
+        this.type = 'info';
+        this.msg =
+          (statusFor ? $localize`Retrieving data for ${statusFor}.` : $localize`Retrieving data.`) +
+          ' ' +
+          $localize`Please wait...`;
+        break;
+      case ViewCacheStatus.ValueStale:
+        this.type = 'warning';
+        this.msg = statusFor
+          ? $localize`Displaying previously cached data for ${statusFor}.`
+          : $localize`Displaying previously cached data.`;
+        break;
+      case ViewCacheStatus.ValueException:
+        this.type = 'danger';
+        this.msg =
+          (statusFor
+            ? $localize`Could not load data for ${statusFor}.`
+            : $localize`Could not load data.`) +
+          ' ' +
+          $localize`Please check the cluster health.`;
+        break;
+    }
+  }
+}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/classes/table-status.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/classes/table-status.spec.ts
new file mode 100644 (file)
index 0000000..7fa7ba1
--- /dev/null
@@ -0,0 +1,15 @@
+import { TableStatus } from './table-status';
+
+describe('TableStatus', () => {
+  it('should create an instance', () => {
+    const ts = new TableStatus();
+    expect(ts).toBeTruthy();
+    expect(ts).toEqual({ msg: '', type: 'light' });
+  });
+
+  it('should create with parameters', () => {
+    const ts = new TableStatus('danger', 'foo');
+    expect(ts).toBeTruthy();
+    expect(ts).toEqual({ msg: 'foo', type: 'danger' });
+  });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/classes/table-status.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/classes/table-status.ts
new file mode 100644 (file)
index 0000000..fa9be80
--- /dev/null
@@ -0,0 +1,3 @@
+export class TableStatus {
+  constructor(public type: 'info' | 'warning' | 'danger' | 'light' = 'light', public msg = '') {}
+}
index 1daffe40deefa98e220ea6b7e4b96005cabbb094..917310640806dc16def2737c593ef5a11956bc93 100644 (file)
@@ -42,7 +42,6 @@ import { SparklineComponent } from './sparkline/sparkline.component';
 import { SubmitButtonComponent } from './submit-button/submit-button.component';
 import { TelemetryNotificationComponent } from './telemetry-notification/telemetry-notification.component';
 import { UsageBarComponent } from './usage-bar/usage-bar.component';
-import { ViewCacheComponent } from './view-cache/view-cache.component';
 
 @NgModule({
   imports: [
@@ -66,7 +65,6 @@ import { ViewCacheComponent } from './view-cache/view-cache.component';
     NgbTimepickerModule
   ],
   declarations: [
-    ViewCacheComponent,
     SparklineComponent,
     HelperComponent,
     SelectBadgesComponent,
@@ -93,7 +91,6 @@ import { ViewCacheComponent } from './view-cache/view-cache.component';
   ],
   providers: [],
   exports: [
-    ViewCacheComponent,
     SparklineComponent,
     HelperComponent,
     SelectBadgesComponent,
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.html
deleted file mode 100644 (file)
index 05afc42..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-<cd-alert-panel type="info"
-                *ngIf="status === vcs.ValueNone">
-  <ng-container i18n>Retrieving data<span *ngIf="statusFor"> for
-  <span [innerHtml]="statusFor"></span></span>. Please wait...</ng-container>
-</cd-alert-panel>
-
-<cd-alert-panel *ngIf="status === vcs.ValueStale"
-                type="warning">
-  <ng-container i18n>Displaying previously cached data<span *ngIf="statusFor">
-  for <span [innerHtml]="statusFor"></span></span>.</ng-container>
-</cd-alert-panel>
-
-<cd-alert-panel type="error"
-                *ngIf="status === vcs.ValueException">
-  <ng-container i18n>Could not load data<span *ngIf="statusFor"> for
-  <span [innerHtml]="statusFor"></span></span>.
-  Please check the cluster health.</ng-container>
-</cd-alert-panel>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.scss
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.spec.ts
deleted file mode 100644 (file)
index 1e76f40..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-
-import { NgbAlertModule } from '@ng-bootstrap/ng-bootstrap';
-
-import { configureTestBed } from '../../../../testing/unit-test-helper';
-import { AlertPanelComponent } from '../alert-panel/alert-panel.component';
-import { ViewCacheComponent } from './view-cache.component';
-
-describe('ViewCacheComponent', () => {
-  let component: ViewCacheComponent;
-  let fixture: ComponentFixture<ViewCacheComponent>;
-
-  configureTestBed({
-    declarations: [ViewCacheComponent, AlertPanelComponent],
-    imports: [NgbAlertModule]
-  });
-
-  beforeEach(() => {
-    fixture = TestBed.createComponent(ViewCacheComponent);
-    component = fixture.componentInstance;
-    fixture.detectChanges();
-  });
-
-  it('should create', () => {
-    expect(component).toBeTruthy();
-  });
-});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/view-cache/view-cache.component.ts
deleted file mode 100644 (file)
index ff669a0..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-import { Component, Input } from '@angular/core';
-
-import { ViewCacheStatus } from '../../enum/view-cache-status.enum';
-
-@Component({
-  selector: 'cd-view-cache',
-  templateUrl: './view-cache.component.html',
-  styleUrls: ['./view-cache.component.scss']
-})
-export class ViewCacheComponent {
-  @Input()
-  status: ViewCacheStatus;
-  @Input()
-  statusFor: string;
-  vcs = ViewCacheStatus;
-}
index 26aee6fce37c3dfca2f42be56dd948d25a8457fb..b32ee065589b62d47a5d66a7909931fbd9d89949 100644 (file)
@@ -3,7 +3,7 @@ import { NgModule } from '@angular/core';
 import { FormsModule } from '@angular/forms';
 import { RouterModule } from '@angular/router';
 
-import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
+import { NgbDropdownModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';
 import { NgxDatatableModule } from '@swimlane/ngx-datatable';
 
 import { ComponentsModule } from '../components/components.module';
@@ -18,6 +18,7 @@ import { TableComponent } from './table/table.component';
     NgxDatatableModule,
     FormsModule,
     NgbDropdownModule,
+    NgbTooltipModule,
     PipesModule,
     ComponentsModule,
     RouterModule
index d69d6298ecdc747638966bf8d1de7b996d6f610d..0ed31b78836164c15c16265b26349b7ac660841e 100644 (file)
@@ -2,7 +2,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { FormsModule } from '@angular/forms';
 import { RouterTestingModule } from '@angular/router/testing';
 
-import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
+import { NgbDropdownModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';
 import { NgxDatatableModule } from '@swimlane/ngx-datatable';
 
 import { configureTestBed } from '../../../../testing/unit-test-helper';
@@ -26,7 +26,8 @@ describe('TableKeyValueComponent', () => {
       ComponentsModule,
       RouterTestingModule,
       NgbDropdownModule,
-      PipesModule
+      PipesModule,
+      NgbTooltipModule
     ]
   });
 
index 95bb3ecf74176d1a8f7b12dff59fd9580b29c07e..9a4c974b82efba6ff69b024858a07ed14ee608b3 100644 (file)
@@ -1,7 +1,3 @@
-<cd-alert-panel type="error"
-                *ngIf="loadingError"
-                i18n>Failed to load data.</cd-alert-panel>
-
 <div class="dataTables_wrapper">
 
   <div *ngIf="onlyActionHeader"
          *ngIf="fetchData.observers.length > 0">
 
       <button type="button"
-              class="btn btn-light"
+              [class]="'btn btn-' + status.type"
+              [ngbTooltip]="status.msg"
               (click)="refreshBtn()">
         <i [ngClass]="[icons.large, icons.refresh]"
            [class.fa-spin]="updating || loadingIndicator"></i>
index e27be89ed31ddb9e862db69c429a45c54098371d..baf3505cc1572730c26e34ba8c37bb2fecb5bca4 100644 (file)
@@ -3,7 +3,7 @@ import { FormsModule } from '@angular/forms';
 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
 import { RouterTestingModule } from '@angular/router/testing';
 
-import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
+import { NgbDropdownModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';
 import { NgxDatatableModule } from '@swimlane/ngx-datatable';
 import * as _ from 'lodash';
 
@@ -44,7 +44,8 @@ describe('TableComponent', () => {
       ComponentsModule,
       RouterTestingModule,
       NgbDropdownModule,
-      PipesModule
+      PipesModule,
+      NgbTooltipModule
     ]
   });
 
@@ -531,7 +532,7 @@ describe('TableComponent', () => {
       component.data = createFakeData(5);
       component.fetchData.subscribe((context: any) => {
         context.error();
-        expect(component.loadingError).toBeTruthy();
+        expect(component.status.type).toBe('danger');
         expect(component.data.length).toBe(0);
         expect(component.loadingIndicator).toBeFalsy();
         expect(component['updating']).toBeFalsy();
@@ -545,7 +546,7 @@ describe('TableComponent', () => {
         context.errorConfig.resetData = false;
         context.errorConfig.displayError = false;
         context.error();
-        expect(component.loadingError).toBeFalsy();
+        expect(component.status.type).toBe('danger');
         expect(component.data.length).toBe(10);
         expect(component.loadingIndicator).toBeFalsy();
         expect(component['updating']).toBeFalsy();
index c177cc994fcad61e8e312a5ac2e4aae82a4f0162..51259b27b16f24d6f86244e37e3f0bb6ee61123f 100644 (file)
@@ -25,6 +25,7 @@ import {
 import * as _ from 'lodash';
 import { Observable, Subject, Subscription, timer as observableTimer } from 'rxjs';
 
+import { TableStatus } from '../../../shared/classes/table-status';
 import { Icons } from '../../../shared/enum/icons.enum';
 import { CellTemplate } from '../../enum/cell-template.enum';
 import { CdTableColumn } from '../../models/cd-table-column';
@@ -144,6 +145,9 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges, O
   @Input()
   extraFilterableColumns: CdTableColumn[] = [];
 
+  @Input()
+  status = new TableStatus();
+
   /**
    * Should be a function to update the input data if undefined nothing will be triggered
    *
@@ -204,7 +208,6 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges, O
   search = '';
   rows: any[] = [];
   loadingIndicator = true;
-  loadingError = false;
   paginationClasses = {
     pagerLeftArrow: Icons.leftArrowDouble,
     pagerRightArrow: Icons.rightArrowDouble,
@@ -594,10 +597,12 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges, O
 
   reloadData() {
     if (!this.updating) {
-      this.loadingError = false;
+      this.status = new TableStatus();
       const context = new CdTableFetchDataContext(() => {
         // Do we have to display the error panel?
-        this.loadingError = context.errorConfig.displayError;
+        if (!!context.errorConfig.displayError) {
+          this.status = new TableStatus('danger', $localize`Failed to load data.`);
+        }
         // Force data table to show no data?
         if (context.errorConfig.resetData) {
           this.data = [];
index 95327ed779aff024b89b76430c5d96964d2d3316..5487fab0a5c53f5d377f778dbfe3d405ee4877a5 100644 (file)
@@ -1,4 +1,5 @@
 export interface MirroringSummary {
   content_data?: any;
   site_name?: any;
+  status?: any;
 }
index 9e5a7aa7327aff615ed374ec725021fdd81270da..bfc4573c00ad49c7fcf6d0a89440a4b226b7befb 100644 (file)
@@ -3,6 +3,7 @@ import { Injectable, OnDestroy } from '@angular/core';
 import { Observable, Subscription } from 'rxjs';
 
 import { ExecutingTask } from '../models/executing-task';
+import { Summary } from '../models/summary.model';
 import { SummaryService } from './summary.service';
 import { TaskMessageService } from './task-message.service';
 
@@ -17,6 +18,7 @@ export class TaskListService implements OnDestroy {
   taskFilter: (task: ExecutingTask) => boolean;
   itemFilter: (item: any, task: ExecutingTask) => boolean;
   builders: object;
+  summary: Summary;
 
   constructor(
     private taskMessageService: TaskMessageService,
@@ -57,9 +59,14 @@ export class TaskListService implements OnDestroy {
     this.builders = builders || {};
 
     this.summaryDataSubscription = this.summaryService.subscribe((summary) => {
-      this.getUpdate().subscribe((resp: any) => {
-        this.updateData(resp, summary['executing_tasks'].filter(this.taskFilter));
-      }, this.onFetchError);
+      this.summary = summary;
+      this.fetch();
+    }, this.onFetchError);
+  }
+
+  fetch() {
+    this.getUpdate().subscribe((resp: any) => {
+      this.updateData(resp, this.summary['executing_tasks'].filter(this.taskFilter));
     }, this.onFetchError);
   }