mgr/dashboard: Render all objects in KV-table

The problem was that the key value table didn't render all objects in
the given object, even if 'renderObjects' was set to true.

For example you give it an object with 2 attributes each of them holds a
non empty object, this will result in a table data that is not fully
converted to key value objects, which will result as text '[Object
object]' in the table view.

Now every object will be rendered and the key value array will be sorted
by key.

Fixes: https://tracker.ceph.com/issues/37859
Signed-off-by: Stephan Müller <smueller@suse.com>
This commit is contained in:
Stephan Müller 2019-01-10 14:58:39 +01:00
parent e99a8ee39b
commit 1033314a24
2 changed files with 47 additions and 61 deletions

View File

@ -130,9 +130,10 @@ describe('TableKeyValueComponent', () => {
it('tests _makePairs', () => {
expect(component._makePairs([['dash', 'board']])).toEqual([{ key: 'dash', value: 'board' }]);
const pair = [{ key: 'dash', value: 'board' }, { key: 'ceph', value: 'mimic' }];
expect(component._makePairs(pair)).toEqual(pair);
const pairInverse = [{ key: 'ceph', value: 'mimic' }, { key: 'dash', value: 'board' }];
expect(component._makePairs(pair)).toEqual(pairInverse);
expect(component._makePairs({ dash: 'board' })).toEqual([{ key: 'dash', value: 'board' }]);
expect(component._makePairs({ dash: 'board', ceph: 'mimic' })).toEqual(pair);
expect(component._makePairs({ dash: 'board', ceph: 'mimic' })).toEqual(pairInverse);
});
it('tests _makePairsFromArray', () => {
@ -179,32 +180,6 @@ describe('TableKeyValueComponent', () => {
});
});
it('tests _insertFlattenObjects', () => {
component.renderObjects = true;
const v = [
{
key: 'no',
value: 'change'
},
{
key: 'first',
value: {
second: {
l3_1: 33,
l3_2: 44
},
layer: 'something'
}
}
];
expect(component._insertFlattenObjects(v)).toEqual([
{ key: 'no', value: 'change' },
{ key: 'first layer', value: 'something' },
{ key: 'first second l3_1', value: 33 },
{ key: 'first second l3_2', value: 44 }
]);
});
describe('render objects', () => {
beforeEach(() => {
component.data = {
@ -218,6 +193,14 @@ describe('TableKeyValueComponent', () => {
}
},
someKey: 0,
o2: {
sub1: {
x: 42
},
sub2: {
y: 555
}
},
additionalKeyContainingObject: { type: 'none' },
keyWithEmptyObject: {}
};
@ -227,14 +210,16 @@ describe('TableKeyValueComponent', () => {
it('with parent key', () => {
component.ngOnInit();
expect(component.tableData).toEqual([
{ key: 'someKey', value: 0 },
{ key: 'additionalKeyContainingObject type', value: 'none' },
{ key: 'keyWithEmptyObject', value: '' },
{ key: 'options someSetting1', value: 38 },
{ key: 'o2 sub1 x', value: 42 },
{ key: 'o2 sub2 y', value: 555 },
{ key: 'options anotherSetting2', value: 'somethingElse' },
{ key: 'options someSetting1', value: 38 },
{ key: 'options suboptions sub1', value: 12 },
{ key: 'options suboptions sub2', value: 34 },
{ key: 'options suboptions sub3', value: 56 },
{ key: 'additionalKeyContainingObject type', value: 'none' }
{ key: 'someKey', value: 0 }
]);
});
@ -242,14 +227,16 @@ describe('TableKeyValueComponent', () => {
component.appendParentKey = false;
component.ngOnInit();
expect(component.tableData).toEqual([
{ key: 'someKey', value: 0 },
{ key: 'keyWithEmptyObject', value: '' },
{ key: 'someSetting1', value: 38 },
{ key: 'anotherSetting2', value: 'somethingElse' },
{ key: 'keyWithEmptyObject', value: '' },
{ key: 'someKey', value: 0 },
{ key: 'someSetting1', value: 38 },
{ key: 'sub1', value: 12 },
{ key: 'sub2', value: 34 },
{ key: 'sub3', value: 56 },
{ key: 'type', value: 'none' }
{ key: 'type', value: 'none' },
{ key: 'x', value: 42 },
{ key: 'y', value: 555 }
]);
});
});

View File

@ -107,7 +107,7 @@ export class TableKeyValueComponent implements OnInit, OnChanges {
throw new Error('Wrong data format');
}
temp = temp.map((v) => this._convertValue(v)).filter((o) => o); // Filters out undefined
return this.renderObjects ? this._insertFlattenObjects(temp) : temp;
return _.sortBy(this.renderObjects ? this.insertFlattenObjects(temp) : temp, 'key');
}
_makePairsFromArray(data: any[]): Item[] {
@ -142,34 +142,33 @@ export class TableKeyValueComponent implements OnInit, OnChanges {
}));
}
_insertFlattenObjects(temp: any[]) {
const itemsToRemoveIndexes = [];
const itemsToAdd = [];
temp.forEach((v, i) => {
if (_.isObject(v.value)) {
if (_.isEmpty(v.value)) {
temp[i]['value'] = '';
} else {
itemsToRemoveIndexes.push(i);
this._makePairs(v.value).forEach((item) => {
if (this.appendParentKey) {
item.key = v.key + ' ' + item.key;
}
itemsToAdd.push(item);
i++;
});
private insertFlattenObjects(temp: Item[]): any[] {
return _.flattenDeep(
temp.map((item) => {
const value = item.value;
const isObject = _.isObject(value);
if (!isObject || _.isEmpty(value)) {
if (isObject) {
item.value = '';
}
return item;
}
return this.splitItemIntoItems(item);
})
);
}
/**
* Split item into items will call _makePairs inside _makePairs (recursion), in oder to split
* the object item up into items as planned.
*/
private splitItemIntoItems(v: { key: string; value: object }): Item[] {
return this._makePairs(v.value).map((item) => {
if (this.appendParentKey) {
item.key = v.key + ' ' + item.key;
}
return item;
});
_.remove(temp, (item, itemIndex) => {
return _.includes(itemsToRemoveIndexes, itemIndex);
});
itemsToAdd.forEach((item) => {
temp.push(item);
});
return temp;
}
_convertValue(v: Item): Item {