From ab780bafc2a13be461e37407f5db8c602b7741d1 Mon Sep 17 00:00:00 2001 From: Tiago Melo Date: Thu, 8 Mar 2018 15:37:47 +0000 Subject: [PATCH] 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 --- .../src/app/ceph/cluster/cluster.module.ts | 5 +- .../osd-details/osd-details.component.html | 2 +- .../osd-details/osd-details.component.spec.ts | 4 + .../osd/osd-details/osd-details.component.ts | 15 ++-- .../osd/osd-list/osd-list.component.html | 11 ++- .../osd/osd-list/osd-list.component.spec.ts | 4 +- .../osd/osd-list/osd-list.component.ts | 7 +- .../rgw-daemon-details.component.html | 2 +- .../rgw-daemon-details.component.spec.ts | 24 +++--- .../rgw-daemon-details.component.ts | 23 +++--- .../rgw-daemon-list.component.html | 10 ++- .../rgw-daemon-list.component.spec.ts | 11 ++- .../rgw-daemon-list.component.ts | 7 +- .../app/core/navigation/navigation.module.ts | 2 +- .../app/shared/datatable/datatable.module.ts | 6 +- .../datatable/table-details.directive.spec.ts | 8 -- .../datatable/table-details.directive.ts | 11 --- .../datatable/table/table.component.html | 7 +- .../shared/datatable/table/table.component.ts | 75 +++++++------------ .../app/shared/models/cd-table-selection.ts | 4 + 20 files changed, 111 insertions(+), 127 deletions(-) delete mode 100644 src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table-details.directive.spec.ts delete mode 100644 src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table-details.directive.ts 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 9b683f0a8d4..d661f51baed 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 831e5620dc3..c511d54e78c 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 67eaaa9c41b..c24618286de 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 572e0d65b54..7f2af372497 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 d67eefb55bf..2683102f018 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 06faf69da28..506b536a636 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 5573550e982..29f0f22ede2 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 73ffbb7ebb8..81c5919db69 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 e6be4f277a6..8ac62fac84c 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 d22ed89b102..64b703fd98e 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 d3c5a11a684..c0d331e3599 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 a9b41942bcd..ce1c2456fdf 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 6ec240de965..823d4feea18 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 19d1a45605a..b09a31ebaa7 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 b3e26843cba..00000000000 --- 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 5c529dc72b7..00000000000 --- 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 2c68b32e979..ba6adf5ae7e 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 f6ec8b4deb5..9732abc5a03 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; } -- 2.39.5