From: Stephan Müller Date: Fri, 16 Feb 2018 16:26:44 +0000 (+0100) Subject: mgr/dashboard_v2: Data transform in k/v table X-Git-Tag: v13.0.2~84^2~42 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=189c31b4e377769f550410d5d1c6ffeac278fd79;p=ceph.git mgr/dashboard_v2: Data transform in k/v table The key value table can transform the input data into key value objects now, you don't have to care about that anymore. Also the first column of the data used in cd-table will be sorted if not set manual through the "sorts" array. Signed-off-by: Stephan Müller --- 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 418f46c707c7..e6be4f277a63 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 @@ -11,7 +11,7 @@ import { RgwDaemonService } from '../services/rgw-daemon.service'; }) export class RgwDaemonDetailsComponent implements OnInit { - metadata: Array = []; + metadata: any; serviceId = ''; @Input() selected?: Array = []; @@ -29,19 +29,9 @@ export class RgwDaemonDetailsComponent implements OnInit { if (_.isEmpty(this.serviceId)) { return; } - this.rgwDaemonService.get(this.serviceId) .then((resp) => { - const metadata = []; - const keys = _.keys(resp['rgw_metadata']); - keys.sort(); - _.map(keys, (key) => { - metadata.push({ - 'key': key, - 'value': resp['rgw_metadata'][key] - }); - }); - this.metadata = metadata; + this.metadata = resp['rgw_metadata']; }); } } diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.html b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.html index b09e5e9e1ba3..d0ab74c07863 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.html +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.html @@ -1,4 +1,4 @@ - { beforeEach(() => { fixture = TestBed.createComponent(TableKeyValueComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); + + it('should make key value object pairs out of arrays with length two', () => { + component.data = [ + ['someKey', 0], + [3, 'something'], + ]; + component.ngOnInit(); + expect(component.tableData.length).toBe(2); + expect(component.tableData[0].key).toBe('someKey'); + expect(component.tableData[1].value).toBe('something'); + }); + + it('should transform arrays', () => { + component.data = [ + ['someKey', [1, 2, 3]], + [3, 'something'] + ]; + component.ngOnInit(); + expect(component.tableData.length).toBe(2); + expect(component.tableData[0].key).toBe('someKey'); + expect(component.tableData[0].value).toBe('1, 2, 3'); + expect(component.tableData[1].value).toBe('something'); + }); + + it('should remove pure object values', () => { + component.data = [ + [3, 'something'], + ['will be removed', { a: 3, b: 4, c: 5}] + ]; + component.ngOnInit(); + expect(component.tableData.length).toBe(1); + expect(component.tableData[0].value).toBe('something'); + }); + + it('should make key value object pairs out of an object', () => { + component.data = { + 3: 'something', + someKey: 0 + }; + component.ngOnInit(); + expect(component.tableData.length).toBe(2); + expect(component.tableData[0].value).toBe('something'); + expect(component.tableData[1].key).toBe('someKey'); + }); + + it('should make do nothing if data is correct', () => { + component.data = [ + { + key: 3, + value: 'something' + }, + { + key: 'someKey', + value: 0 + } + ]; + component.ngOnInit(); + expect(component.tableData.length).toBe(2); + expect(component.tableData[0].value).toBe('something'); + expect(component.tableData[1].key).toBe('someKey'); + }); + + it('should throw error if miss match', () => { + component.data = 38; + expect(() => component.ngOnInit()).toThrowError('Wrong data format'); + component.data = [['someKey', 0, 3]]; + expect(() => component.ngOnInit()).toThrowError('Wrong array format'); + }); }); diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.ts index 46e4f71f90ec..101580f35ef1 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.ts +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.ts @@ -1,4 +1,6 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core'; + +import * as _ from 'lodash'; import { CellTemplate } from '../../enum/cell-template.enum'; import { CdTableColumn } from '../../models/cd-table-column'; @@ -16,28 +18,16 @@ import { CdTableColumn } from '../../models/cd-table-column'; templateUrl: './table-key-value.component.html', styleUrls: ['./table-key-value.component.scss'] }) -export class TableKeyValueComponent implements OnInit { +export class TableKeyValueComponent implements OnInit, OnChanges { columns: Array = []; - /** - * An array of objects to be displayed in the data table. - */ - @Input() data: Array = []; + @Input() data: any; - /** - * The name of the attribute to be displayed as key. - * Defaults to 'key'. - * @type {string} - */ - @Input() key = 'key'; - - /** - * The name of the attribute to be displayed as value. - * Defaults to 'value'. - * @type {string} - */ - @Input() value = 'value'; + tableData: { + key: string, + value: any + }[]; /** * The function that will be called to update the input data. @@ -49,15 +39,58 @@ export class TableKeyValueComponent implements OnInit { ngOnInit() { this.columns = [ { - prop: this.key, + prop: 'key', flexGrow: 1, cellTransformation: CellTemplate.bold }, { - prop: this.value, + prop: 'value', flexGrow: 3 } ]; + this.useData(); + } + + ngOnChanges(changes) { + this.useData(); + } + + useData() { + let temp = []; + if (!this.data) { + return; // Wait for data + } else if (_.isArray(this.data)) { + const first = this.data[0]; + if (_.isPlainObject(first) && _.has(first, 'key') && _.has(first, 'value')) { + temp = [...this.data]; + } else { + if (_.isArray(first)) { + if (first.length === 2) { + temp = this.data.map(a => ({ + key: a[0], + value: a[1] + })); + } else { + throw new Error('Wrong array format'); + } + } + } + } else if (_.isPlainObject(this.data)) { + temp = Object.keys(this.data).map(k => ({ + key: k, + value: this.data[k] + })); + } else { + throw new Error('Wrong data format'); + } + this.tableData = temp.map(o => { + if (_.isArray(o.value)) { + o.value = o.value.join(', '); + } else if (_.isObject(o.value)) { + return; + } + return o; + }).filter(o => o); // Filters out undefined } reloadData() { 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 a3c66b861ace..9445a5f26c12 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 @@ -53,6 +53,7 @@ [selectionType]="selectionType" [selected]="selected" (select)="toggleExpandRow()" + [sorts]="sorts" [columns]="columns" [columnMode]="columnMode" [rows]="rows" diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table/table.component.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table/table.component.ts index 9f0c2ad8a450..5ecba71dfcc2 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table/table.component.ts +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/datatable/table/table.component.ts @@ -12,7 +12,7 @@ import { ViewChild } from '@angular/core'; -import { DatatableComponent } from '@swimlane/ngx-datatable'; +import { DatatableComponent, SortDirection, SortPropDir } from '@swimlane/ngx-datatable'; import * as _ from 'lodash'; import { CdTableColumn } from '../../models/cd-table-column'; @@ -34,6 +34,8 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges { @Input() data: any[] = []; // Each item -> { prop: 'attribute name', name: 'display name' } @Input() columns: CdTableColumn[]; + // Each item -> { prop: 'attribute name', dir: 'asc'||'desc'} + @Input() sorts?: SortPropDir[]; // Method used for setting column widths. @Input() columnMode ?= 'force'; // Name of the component e.g. 'TableDetailsComponent' @@ -87,6 +89,14 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges { if (this.detailsComponent) { this.selectionType = 'multi'; } + if (!this.sorts) { + this.sorts = [ + { + prop: this.columns[0].prop, + dir: SortDirection.asc + } + ]; + } } ngAfterContentChecked() { @@ -97,8 +107,7 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges { // https://github.com/swimlane/ngx-datatable/issues/193#issuecomment-329144543 if (this.table && this.table.element.clientWidth !== this.currentWidth) { this.currentWidth = this.table.element.clientWidth; - // Force the redrawing of the table. - window.dispatchEvent(new Event('resize')); + this.table.recalculate(); } } @@ -128,6 +137,9 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges { } useData() { + if (!this.data) { + return; // Wait for data + } this.rows = [...this.data]; this.loadingIndicator = false; }