From: Tiago Melo Date: Thu, 8 Mar 2018 15:37:47 +0000 (+0000) Subject: mgr/dashboard_v2: fix and improve table details X-Git-Tag: v13.1.0~579^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=ab780bafc2a13be461e37407f5db8c602b7741d1;p=ceph.git mgr/dashboard_v2: fix and improve table details 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 --- diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/cluster.module.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/cluster.module.ts index 9b683f0a8d40d..d661f51baed41 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/cluster.module.ts +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/cluster.module.ts @@ -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 diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.html b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.html index 831e5620dc30b..c511d54e78c13 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.html +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.html @@ -1,4 +1,4 @@ - + diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.spec.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.spec.ts index 67eaaa9c41b02..c24618286de12 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.spec.ts +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.spec.ts @@ -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(); }); diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.ts index 572e0d65b549d..7f2af3724976e 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.ts +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.ts @@ -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(); }; diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.html b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.html index d67eefb55bf8b..2683102f01884 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.html +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.html @@ -7,15 +7,18 @@ + selectionType="single" + (updateSelection)="updateSelection($event)"> + + + + [class.text-warning]="'down' === state || 'out' === state"> {{ state }}, diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.spec.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.spec.ts index 06faf69da28c3..506b536a63645 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.spec.ts +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.spec.ts @@ -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: [ diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.ts index 5573550e98258..29f0f22ede287 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.ts +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.ts @@ -14,9 +14,10 @@ import { OsdService } from '../osd.service'; export class OsdListComponent implements OnInit { @ViewChild('statusColor') statusColor: TemplateRef; + 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; diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.html b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.html index 73ffbb7ebb8fb..81c5919db6971 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.html +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.html @@ -1,4 +1,4 @@ - + { let component: RgwDaemonDetailsComponent; let fixture: ComponentFixture; + 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(); }); diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.ts index e6be4f277a637..8ac62fac84c84 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.ts +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.ts @@ -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 = []; + @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']; + }); } } diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.html b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.html index d22ed89b1020c..64b703fd98e41 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.html +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.html @@ -5,10 +5,14 @@ aria-current="page">Object Gateway + + selectionType="single" + (updateSelection)="updateSelection($event)" + (fetchData)="getDaemonList()"> + + diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.spec.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.spec.ts index d3c5a11a68444..c0d331e3599f6 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.spec.ts +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.spec.ts @@ -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 ] }) diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.ts index a9b41942bcdf8..ce1c2456fdf03 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.ts +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.ts @@ -14,8 +14,7 @@ export class RgwDaemonListComponent { columns: Array = []; daemons: Array = []; - - 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; } } diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/core/navigation/navigation.module.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/core/navigation/navigation.module.ts index 6ec240de965e5..823d4feea1849 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/core/navigation/navigation.module.ts +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/core/navigation/navigation.module.ts @@ -13,7 +13,7 @@ import { NavigationComponent } from './navigation/navigation.component'; imports: [ CommonModule, AuthModule, - BsDropdownModule, + BsDropdownModule.forRoot(), AppRoutingModule, SharedModule, RouterModule diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/datatable.module.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/datatable.module.ts index 19d1a45605a68..b09a31ebaa7c4 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/datatable.module.ts +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/datatable.module.ts @@ -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 index b3e26843cbac3..0000000000000 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table-details.directive.spec.ts +++ /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 index 5c529dc72b74d..0000000000000 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table-details.directive.ts +++ /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) { } - -} diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table/table.component.html b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table/table.component.html index 2c68b32e9790b..ba6adf5ae7e77 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table/table.component.html +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table/table.component.html @@ -90,12 +90,11 @@ [loadingIndicator]="loadingIndicator" [rowIdentity]="rowIdentity()" [rowHeight]="'auto'"> - - - - + + + ; @ViewChild('sparklineTpl') sparklineTpl: TemplateRef; @ViewChild('routerLinkTpl') routerLinkTpl: TemplateRef; @@ -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 } = {}; - 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 = >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) }; }; } diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/models/cd-table-selection.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/models/cd-table-selection.ts index f6ec8b4deb52b..9732abc5a032b 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/models/cd-table-selection.ts +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/models/cd-table-selection.ts @@ -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; }