]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: Render all objects in KV-table 25894/head
authorStephan Müller <smueller@suse.com>
Thu, 10 Jan 2019 13:58:39 +0000 (14:58 +0100)
committerStephan Müller <smueller@suse.com>
Fri, 11 Jan 2019 08:07:47 +0000 (09:07 +0100)
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>
src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.ts

index cb69b3badfa16df23289b7b1a0bf2bcde237e238..f697b2c1b5368c3c5b4fc1810b0baf84d6d2d4fe 100644 (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: 'anotherSetting2', value: 'somethingElse' },
         { key: 'keyWithEmptyObject', value: '' },
+        { key: 'someKey', value: 0 },
         { key: 'someSetting1', value: 38 },
-        { key: 'anotherSetting2', value: 'somethingElse' },
         { 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 }
       ]);
     });
   });
index 500ee033d3922cf587c6bbb30258dad29550d22c..3bc9d2a1281af4cc54ba56457601d052f33a3cdf 100644 (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);
+      })
+    );
+  }
 
-    _.remove(temp, (item, itemIndex) => {
-      return _.includes(itemsToRemoveIndexes, itemIndex);
-    });
-    itemsToAdd.forEach((item) => {
-      temp.push(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;
     });
-
-    return temp;
   }
 
   _convertValue(v: Item): Item {