From 189c31b4e377769f550410d5d1c6ffeac278fd79 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Stephan=20M=C3=BCller?= Date: Fri, 16 Feb 2018 17:26:44 +0100 Subject: [PATCH] mgr/dashboard_v2: Data transform in k/v table MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 --- .../rgw-daemon-details.component.ts | 14 +--- .../table-key-value.component.html | 2 +- .../table-key-value.component.spec.ts | 69 ++++++++++++++++- .../table-key-value.component.ts | 75 +++++++++++++------ .../datatable/table/table.component.html | 1 + .../shared/datatable/table/table.component.ts | 18 ++++- 6 files changed, 141 insertions(+), 38 deletions(-) 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 418f46c707c7b..e6be4f277a637 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 b09e5e9e1ba3d..d0ab74c078636 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 46e4f71f90ec6..101580f35ef11 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 a3c66b861acec..9445a5f26c121 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 9f0c2ad8a4508..5ecba71dfcc26 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; } -- 2.39.5