]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard_v2: fix and improve table details 20811/head
authorTiago Melo <tmelo@suse.com>
Thu, 8 Mar 2018 15:37:47 +0000 (15:37 +0000)
committerTiago Melo <tmelo@suse.com>
Mon, 12 Mar 2018 16:00:53 +0000 (16:00 +0000)
There was a problem with the current implementation of the table details, when
compiled in production mode, where the method that created the details element
would throw an exception.

Besides fixing that, this commit also improves the way we define the details.
Now instead of sending the component name, through the 'detailsComponent' attr,
we need to get the current selection via 'updateSelection' attr and declare the
detail component inside the cdTable and add the cdTableDetail attr to that
element.

Signed-off-by: Tiago Melo <tmelo@suse.com>
20 files changed:
src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/cluster.module.ts
src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.html
src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.spec.ts
src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.ts
src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.html
src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.spec.ts
src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.ts
src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.html
src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.spec.ts
src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.ts
src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.html
src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.spec.ts
src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.ts
src/pybind/mgr/dashboard_v2/frontend/src/app/core/navigation/navigation.module.ts
src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/datatable.module.ts
src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table-details.directive.spec.ts [deleted file]
src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table-details.directive.ts [deleted file]
src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table/table.component.html
src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table/table.component.ts
src/pybind/mgr/dashboard_v2/frontend/src/app/shared/models/cd-table-selection.ts

index 9b683f0a8d40d418b9e57b6fdb3261af41c1564a..d661f51baed4168b9d4036ef7925d214d825ddab 100644 (file)
@@ -3,7 +3,8 @@ import { NgModule } from '@angular/core';
 import { FormsModule } from '@angular/forms';
 import { RouterModule } from '@angular/router';
 
-import { TabsModule } from 'ngx-bootstrap';
+import { TabsModule } from 'ngx-bootstrap/tabs';
+
 import { ComponentsModule } from '../../shared/components/components.module';
 import { SharedModule } from '../../shared/shared.module';
 import { PerformanceCounterModule } from '../performance-counter/performance-counter.module';
@@ -26,7 +27,7 @@ import { OsdService } from './osd/osd.service';
     CommonModule,
     PerformanceCounterModule,
     ComponentsModule,
-    TabsModule,
+    TabsModule.forRoot(),
     SharedModule,
     RouterModule,
     FormsModule
index 831e5620dc30bcddcfc0263dfbe940fbb4dff912..c511d54e78c13f36b9dc821014a55227c92aea07 100644 (file)
@@ -1,4 +1,4 @@
-<tabset>
+<tabset *ngIf="selection.hasSingleSelection">
   <tab heading="Attributes (OSD map)">
     <cd-table-key-value *ngIf="osd.loaded"
                         [data]="osd.details.osd_map">
index 67eaaa9c41b028f39b20e233c9293929c29ac600..c24618286de123d452a2d07f35b43df74481064b 100644 (file)
@@ -4,6 +4,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
 import { TabsModule } from 'ngx-bootstrap';
 
 import { DataTableModule } from '../../../../shared/datatable/datatable.module';
+import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
 import { PerformanceCounterModule } from '../../../performance-counter/performance-counter.module';
 import {
   OsdPerformanceHistogramComponent
@@ -35,6 +36,9 @@ describe('OsdDetailsComponent', () => {
   beforeEach(() => {
     fixture = TestBed.createComponent(OsdDetailsComponent);
     component = fixture.componentInstance;
+
+    component.selection = new CdTableSelection();
+
     fixture.detectChanges();
   });
 
index 572e0d65b549de17b46204eb20f0d1a91619bfbb..7f2af3724976efda0c01839b780909108225b6cb 100644 (file)
@@ -1,7 +1,8 @@
-import { Component, Input, OnInit } from '@angular/core';
+import { Component, Input, OnChanges } from '@angular/core';
 
 import * as _ from 'lodash';
 
+import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
 import { OsdService } from '../osd.service';
 
 @Component({
@@ -9,19 +10,19 @@ import { OsdService } from '../osd.service';
   templateUrl: './osd-details.component.html',
   styleUrls: ['./osd-details.component.scss']
 })
-export class OsdDetailsComponent implements OnInit {
-  osd: any;
+export class OsdDetailsComponent implements OnChanges {
+  @Input() selection: CdTableSelection;
 
-  @Input() selected?: any[] = [];
+  osd: any;
 
   constructor(private osdService: OsdService) {}
 
-  ngOnInit() {
+  ngOnChanges() {
     this.osd = {
       loaded: false
     };
-    if (this.selected.length > 0) {
-      this.osd = this.selected[0];
+    if (this.selection.hasSelection) {
+      this.osd = this.selection.first();
       this.osd.autoRefresh = () => {
         this.refresh();
       };
index d67eefb55bf8bcacb669fb0045ec871bcf12698b..2683102f01884f71e216cebbdfebfcf668c235e6 100644 (file)
@@ -7,15 +7,18 @@
 <cd-table [data]="osds"
           (fetchData)="getOsdList()"
           [columns]="columns"
-          [detailsComponent]="detailsComponent"
-          [beforeShowDetails]="beforeShowDetails">
+          selectionType="single"
+          (updateSelection)="updateSelection($event)">
+  <cd-osd-details cdTableDetail
+                  [selection]="selection">
+  </cd-osd-details>
 </cd-table>
+
 <ng-template #statusColor
              let-value="value">
   <span *ngFor="let state of value; last as last">
     <span [class.text-success]="'up' === state || 'in' === state"
-          [class.text-warning]="'down' === state || 'out' === state"
-          >
+          [class.text-warning]="'down' === state || 'out' === state">
       {{ state }}</span><span *ngIf="!last">, </span>
     <!-- Has to be on the same line to prevent a space between state and comma. -->
   </span>
index 06faf69da28c3035160e9475868a2ad8d4e1ee68..506b536a63645bb445b80b99da5d67cb7324e591 100644 (file)
@@ -1,7 +1,7 @@
 import { HttpClientModule } from '@angular/common/http';
 import { async, ComponentFixture, TestBed } from '@angular/core/testing';
 
-import { TabsModule } from 'ngx-bootstrap';
+import { TabsModule } from 'ngx-bootstrap/tabs';
 
 import { DataTableModule } from '../../../../shared/datatable/datatable.module';
 import { DimlessPipe } from '../../../../shared/pipes/dimless.pipe';
@@ -23,7 +23,7 @@ describe('OsdListComponent', () => {
       imports: [
         HttpClientModule,
         PerformanceCounterModule,
-        TabsModule,
+        TabsModule.forRoot(),
         DataTableModule
       ],
       declarations: [
index 5573550e982580376d0eefd6d2c39aca66f9ad9d..29f0f22ede287169603d734147a148732574a8a9 100644 (file)
@@ -14,9 +14,10 @@ import { OsdService } from '../osd.service';
 
 export class OsdListComponent implements OnInit {
   @ViewChild('statusColor') statusColor: TemplateRef<any>;
+
   osds = [];
-  detailsComponent = 'OsdDetailsComponent';
   columns: CdTableColumn[];
+  selection = new CdTableSelection();
 
   constructor(
     private osdService: OsdService,
@@ -45,6 +46,10 @@ export class OsdListComponent implements OnInit {
     ];
   }
 
+  updateSelection(selection: CdTableSelection) {
+    this.selection = selection;
+  }
+
   getOsdList() {
     this.osdService.getList().subscribe((data: any[]) => {
       this.osds = data;
index 73ffbb7ebb8fb0c834aff9cba7720d2d5ad63371..81c5919db69719ed98c24c7decfbdf167993f074 100644 (file)
@@ -1,4 +1,4 @@
-<tabset>
+<tabset *ngIf="selection.hasSingleSelection">
   <tab i18n-heading
        heading="Details">
     <cd-table-key-value [data]="metadata"
index ca2d7e6089f56ae98bdc7431ce438b63b41f761d..afce56a2bacf8c224e4da13d8ce107850def2919 100644 (file)
@@ -1,9 +1,8 @@
-import { HttpClientModule } from '@angular/common/http';
-import { HttpClientTestingModule } from '@angular/common/http/testing';
 import { async, ComponentFixture, TestBed } from '@angular/core/testing';
 
-import { BsDropdownModule, TabsModule } from 'ngx-bootstrap';
+import { TabsModule } from 'ngx-bootstrap/tabs';
 
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
 import { SharedModule } from '../../../shared/shared.module';
 import { PerformanceCounterModule } from '../../performance-counter/performance-counter.module';
 import { RgwDaemonService } from '../services/rgw-daemon.service';
@@ -13,25 +12,32 @@ describe('RgwDaemonDetailsComponent', () => {
   let component: RgwDaemonDetailsComponent;
   let fixture: ComponentFixture<RgwDaemonDetailsComponent>;
 
+  const fakeService = {
+    get: (id: string) => {
+      return new Promise(function(resolve, reject) {
+        return [];
+      });
+    }
+  };
+
   beforeEach(async(() => {
     TestBed.configureTestingModule({
       declarations: [ RgwDaemonDetailsComponent ],
       imports: [
         SharedModule,
         PerformanceCounterModule,
-        HttpClientTestingModule,
-        HttpClientModule,
-        BsDropdownModule.forRoot(),
         TabsModule.forRoot()
       ],
-      providers: [ RgwDaemonService ]
-    })
-    .compileComponents();
+      providers: [{ provide: RgwDaemonService, useValue: fakeService }]
+    });
   }));
 
   beforeEach(() => {
     fixture = TestBed.createComponent(RgwDaemonDetailsComponent);
     component = fixture.componentInstance;
+
+    component.selection = new CdTableSelection();
+
     fixture.detectChanges();
   });
 
index e6be4f277a6379271bbb157e5b49c4c2aa5d5f07..8ac62fac84c8478f8501153c265c7013e0a68394 100644 (file)
@@ -1,7 +1,8 @@
-import { Component, Input, OnInit } from '@angular/core';
+import { Component, Input, OnChanges } from '@angular/core';
 
 import * as _ from 'lodash';
 
+import { CdTableSelection } from '../../../shared/models/cd-table-selection';
 import { RgwDaemonService } from '../services/rgw-daemon.service';
 
 @Component({
@@ -9,19 +10,18 @@ import { RgwDaemonService } from '../services/rgw-daemon.service';
   templateUrl: './rgw-daemon-details.component.html',
   styleUrls: ['./rgw-daemon-details.component.scss']
 })
-export class RgwDaemonDetailsComponent implements OnInit {
-
+export class RgwDaemonDetailsComponent implements OnChanges {
   metadata: any;
   serviceId = '';
 
-  @Input() selected?: Array<any> = [];
+  @Input() selection: CdTableSelection;
 
-  constructor(private rgwDaemonService: RgwDaemonService) { }
+  constructor(private rgwDaemonService: RgwDaemonService) {}
 
-  ngOnInit() {
+  ngOnChanges() {
     // Get the service id of the first selected row.
-    if (this.selected.length > 0) {
-      this.serviceId = this.selected[0].id;
+    if (this.selection.hasSelection) {
+      this.serviceId = this.selection.first().id;
     }
   }
 
@@ -29,9 +29,8 @@ export class RgwDaemonDetailsComponent implements OnInit {
     if (_.isEmpty(this.serviceId)) {
       return;
     }
-    this.rgwDaemonService.get(this.serviceId)
-      .then((resp) => {
-        this.metadata = resp['rgw_metadata'];
-      });
+    this.rgwDaemonService.get(this.serviceId).then(resp => {
+      this.metadata = resp['rgw_metadata'];
+    });
   }
 }
index d22ed89b1020c34fb3e3fc207212ecccbdddb454..64b703fd98e4162231a668f59692959b7dbbf930 100644 (file)
@@ -5,10 +5,14 @@
         aria-current="page">Object Gateway</li>
   </ol>
 </nav>
+
 <cd-table [data]="daemons"
           [columns]="columns"
           columnMode="flex"
-          [detailsComponent]="detailsComponent"
-          (fetchData)="getDaemonList()"
-          [beforeShowDetails]="beforeShowDetails">
+          selectionType="single"
+          (updateSelection)="updateSelection($event)"
+          (fetchData)="getDaemonList()">
+  <cd-rgw-daemon-details cdTableDetail
+                         [selection]="selection">
+  </cd-rgw-daemon-details>
 </cd-table>
index d3c5a11a684444e5c6223a0bacdf32f478c1ba9c..c0d331e3599f65888696e6caefa083e1a022226e 100644 (file)
@@ -2,9 +2,11 @@ import { HttpClientModule } from '@angular/common/http';
 import { HttpClientTestingModule } from '@angular/common/http/testing';
 import { async, ComponentFixture, TestBed } from '@angular/core/testing';
 
-import { BsDropdownModule } from 'ngx-bootstrap';
+import { TabsModule } from 'ngx-bootstrap/tabs';
 
 import { DataTableModule } from '../../../shared/datatable/datatable.module';
+import { PerformanceCounterModule } from '../../performance-counter/performance-counter.module';
+import { RgwDaemonDetailsComponent } from '../rgw-daemon-details/rgw-daemon-details.component';
 import { RgwDaemonService } from '../services/rgw-daemon.service';
 import { RgwDaemonListComponent } from './rgw-daemon-list.component';
 
@@ -14,12 +16,13 @@ describe('RgwDaemonListComponent', () => {
 
   beforeEach(async(() => {
     TestBed.configureTestingModule({
-      declarations: [ RgwDaemonListComponent ],
+      declarations: [ RgwDaemonListComponent, RgwDaemonDetailsComponent ],
       imports: [
         DataTableModule,
         HttpClientTestingModule,
-        BsDropdownModule.forRoot(),
-        HttpClientModule
+        HttpClientModule,
+        TabsModule.forRoot(),
+        PerformanceCounterModule
       ],
       providers: [ RgwDaemonService ]
     })
index a9b41942bcdf884bcc3f10bea241eed775670126..ce1c2456fdf0341bff828df166d915a2923d083c 100644 (file)
@@ -14,8 +14,7 @@ export class RgwDaemonListComponent {
 
   columns: Array<CdTableColumn> = [];
   daemons: Array<object> = [];
-
-  detailsComponent = 'RgwDaemonDetailsComponent';
+  selection = new CdTableSelection();
 
   constructor(private rgwDaemonService: RgwDaemonService,
               cephShortVersionPipe: CephShortVersionPipe) {
@@ -46,7 +45,7 @@ export class RgwDaemonListComponent {
       });
   }
 
-  beforeShowDetails(selection: CdTableSelection) {
-    return selection.hasSingleSelection;
+  updateSelection(selection: CdTableSelection) {
+    this.selection = selection;
   }
 }
index 6ec240de965e5adbaa131b45d95a691797f7b328..823d4feea18492767193911210e91d708490288b 100644 (file)
@@ -13,7 +13,7 @@ import { NavigationComponent } from './navigation/navigation.component';
   imports: [
     CommonModule,
     AuthModule,
-    BsDropdownModule,
+    BsDropdownModule.forRoot(),
     AppRoutingModule,
     SharedModule,
     RouterModule
index 19d1a45605a6861d4d2f78f2b5bf58de91c50200..b09a31ebaa7c43dffed3da18997a9f076f163d5f 100644 (file)
@@ -4,11 +4,10 @@ import { FormsModule } from '@angular/forms';
 import { RouterModule } from '@angular/router';
 
 import { NgxDatatableModule } from '@swimlane/ngx-datatable';
+import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
 
-import { BsDropdownModule } from 'ngx-bootstrap';
 import { ComponentsModule } from '../components/components.module';
 import { PipesModule } from '../pipes/pipes.module';
-import { TableDetailsDirective } from './table-details.directive';
 import { TableKeyValueComponent } from './table-key-value/table-key-value.component';
 import { TableComponent } from './table/table.component';
 
@@ -17,14 +16,13 @@ import { TableComponent } from './table/table.component';
     CommonModule,
     NgxDatatableModule,
     FormsModule,
-    BsDropdownModule,
+    BsDropdownModule.forRoot(),
     PipesModule,
     ComponentsModule,
     RouterModule
   ],
   declarations: [
     TableComponent,
-    TableDetailsDirective,
     TableKeyValueComponent
   ],
   exports: [
diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table-details.directive.spec.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table-details.directive.spec.ts
deleted file mode 100644 (file)
index b3e2684..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-import { TableDetailsDirective } from './table-details.directive';
-
-describe('TableDetailsDirective', () => {
-  it('should create an instance', () => {
-    const directive = new TableDetailsDirective(null);
-    expect(directive).toBeTruthy();
-  });
-});
diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table-details.directive.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table-details.directive.ts
deleted file mode 100644 (file)
index 5c529dc..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-import { Directive, Input, ViewContainerRef } from '@angular/core';
-
-@Directive({
-  selector: '[cdTableDetails]'
-})
-export class TableDetailsDirective {
-  @Input() selected?: any[];
-
-  constructor(public viewContainerRef: ViewContainerRef) { }
-
-}
index 2c68b32e9790bdbe0f662242d6d5f71477514699..ba6adf5ae7e77107945a40bcd927e79726461afb 100644 (file)
                  [loadingIndicator]="loadingIndicator"
                  [rowIdentity]="rowIdentity()"
                  [rowHeight]="'auto'">
-    <!-- Row Detail Template -->
-    <ngx-datatable-row-detail (toggle)="updateDetailView()">
-    </ngx-datatable-row-detail>
   </ngx-datatable>
 </div>
-<ng-template cdTableDetails></ng-template>
+
+<!-- Table Details -->
+<ng-content select="[cdTableDetail]"></ng-content>
 
 <!-- cell templates that can be accessed from outside -->
 <ng-template #tableCellBoldTpl
index 775aa42e96e585669b37bd75505c83e0cf624860..9f04e91c71ca748e96fda8003ed54f9243b3aa87 100644 (file)
@@ -1,7 +1,6 @@
 import {
   AfterContentChecked,
   Component,
-  ComponentFactoryResolver,
   EventEmitter,
   Input,
   OnChanges,
@@ -25,7 +24,6 @@ import { Observable } from 'rxjs/Observable';
 
 import { CdTableColumn } from '../../models/cd-table-column';
 import { CdTableSelection } from '../../models/cd-table-selection';
-import { TableDetailsDirective } from '../table-details.directive';
 
 @Component({
   selector: 'cd-table',
@@ -34,7 +32,6 @@ import { TableDetailsDirective } from '../table-details.directive';
 })
 export class TableComponent implements AfterContentChecked, OnInit, OnChanges, OnDestroy {
   @ViewChild(DatatableComponent) table: DatatableComponent;
-  @ViewChild(TableDetailsDirective) detailTemplate: TableDetailsDirective;
   @ViewChild('tableCellBoldTpl') tableCellBoldTpl: TemplateRef<any>;
   @ViewChild('sparklineTpl') sparklineTpl: TemplateRef<any>;
   @ViewChild('routerLinkTpl') routerLinkTpl: TemplateRef<any>;
@@ -48,8 +45,6 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges, O
   @Input() sorts?: SortPropDir[];
   // Method used for setting column widths.
   @Input() columnMode ?= 'flex';
-  // Name of the component e.g. 'TableDetailsComponent'
-  @Input() detailsComponent?: string;
   // Display the tool header, including reload button, pagination and search fields?
   @Input() toolHeader ?= true;
   // Display the table header?
@@ -58,10 +53,6 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges, O
   @Input() footer ?= true;
   // Page size to show. Set to 0 to show unlimited number of rows.
   @Input() limit ?= 10;
-  // An optional function that is called before the details page is show.
-  // The current selection is passed as function argument. To do not display
-  // the details page, return false.
-  @Input() beforeShowDetails: Function;
 
   /**
    * Auto reload time in ms - per default every 5s
@@ -72,6 +63,9 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges, O
 
   // Which row property is unique for a row
   @Input() identifier = 'id';
+  // Allows other components to specify which type of selection they want,
+  // e.g. 'single' or 'multi'.
+  @Input() selectionType: string = undefined;
 
   /**
    * Should be a function to update the input data if undefined nothing will be triggered
@@ -84,6 +78,16 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges, O
    */
   @Output() fetchData = new EventEmitter();
 
+  /**
+   * This should be defined if you need access to the selection object.
+   *
+   * Each time the table selection changes, this will be triggered and
+   * the new selection object will be sent.
+   *
+   * @memberof TableComponent
+   */
+  @Output() updateSelection = new EventEmitter();
+
   /**
    * Use this variable to access the selected row(s).
    */
@@ -93,7 +97,6 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges, O
   cellTemplates: {
     [key: string]: TemplateRef<any>
   } = {};
-  selectionType: string = undefined;
   search = '';
   rows = [];
   loadingIndicator = true;
@@ -110,7 +113,7 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges, O
   // table columns after the browser window has been resized.
   private currentWidth: number;
 
-  constructor(private componentFactoryResolver: ComponentFactoryResolver) { }
+  constructor() {}
 
   ngOnInit() {
     this._addTemplates();
@@ -132,9 +135,6 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges, O
       }
       return c;
     });
-    if (this.detailsComponent) {
-      this.selectionType = 'multi';
-    }
     this.tableColumns = this.columns.filter(c => !c.isHidden);
     if (this.autoReload) { // Also if nothing is bound to fetchData nothing will be triggered
       // Force showing the loading indicator because it has been set to False in
@@ -164,7 +164,7 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges, O
     }
   }
 
-  _addTemplates () {
+  _addTemplates() {
     this.cellTemplates.bold = this.tableCellBoldTpl;
     this.cellTemplates.sparkline = this.sparklineTpl;
     this.cellTemplates.routerLink = this.routerLinkTpl;
@@ -218,15 +218,7 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges, O
 
   onSelect() {
     this.selection.update();
-    this.toggleExpandRow();
-  }
-
-  toggleExpandRow() {
-    if (this.selection.hasSelection) {
-      this.table.rowDetail.toggleExpandRow(this.selection.first());
-    } else {
-      this.detailTemplate.viewContainerRef.clear();
-    }
+    this.updateSelection.emit(_.clone(this.selection));
   }
 
   toggleColumn($event: any) {
@@ -258,25 +250,6 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges, O
     ];
   }
 
-  updateDetailView() {
-    if (!this.detailsComponent) {
-      return;
-    }
-    if (_.isFunction(this.beforeShowDetails)) {
-      if (!this.beforeShowDetails(this.selection)) {
-        this.detailTemplate.viewContainerRef.clear();
-        return;
-      }
-    }
-    const factories = Array.from(this.componentFactoryResolver['_factories'].keys());
-    const factoryClass = <Type<any>>factories.find((x: any) => x.name === this.detailsComponent);
-    this.detailTemplate.viewContainerRef.clear();
-    const cmpRef = this.detailTemplate.viewContainerRef.createComponent(
-      this.componentFactoryResolver.resolveComponentFactory(factoryClass)
-    );
-    cmpRef.instance.selected = this.selection.selected;
-  }
-
   updateFilter(event?) {
     if (!event) {
       this.search = '';
@@ -284,11 +257,15 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges, O
     const val = this.search.toLowerCase();
     const columns = this.columns;
     // update the rows
-    this.rows = this.data.filter(function (d) {
-      return columns.filter((c) => {
-        return (typeof d[c.prop] === 'string' || typeof d[c.prop] === 'number')
-          && (d[c.prop] + '').toLowerCase().indexOf(val) !== -1;
-      }).length > 0;
+    this.rows = this.data.filter((d) => {
+      return (
+        columns.filter(c => {
+          return (
+            (_.isString(d[c.prop]) || _.isNumber(d[c.prop])) &&
+            (d[c.prop] + '').toLowerCase().indexOf(val) !== -1
+          );
+        }).length > 0
+      );
     });
     // Whenever the filter changes, always go back to the first page
     this.table.offset = 0;
@@ -298,7 +275,7 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges, O
     // Return the function used to populate a row's CSS classes.
     return () => {
       return {
-        'clickable': !_.isUndefined(this.detailsComponent)
+        clickable: !_.isUndefined(this.selectionType)
       };
     };
   }
index f6ec8b4deb52b1e9594b21acb8d488f141496696..9732abc5a032b2694d8f2d04083545100f39f7da 100644 (file)
@@ -18,6 +18,10 @@ export class CdTableSelection {
     this.hasMultiSelection = this.selected.length > 1;
   }
 
+  /**
+   * Get the first selected row.
+   * @return {any | null}
+   */
   first() {
     return this.hasSelection ? this.selected[0] : null;
   }