]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: Searchable objects for table 32891/head
authorStephan Müller <smueller@suse.com>
Thu, 19 Sep 2019 14:04:34 +0000 (16:04 +0200)
committerShyukri Shyukriev <shshyukriev@suse.com>
Tue, 4 Feb 2020 10:53:24 +0000 (12:53 +0200)
The table can now search through objects, by default it won't search
through them, but it won't fail like before.

The RBD list page is now capable of searching through objects, which
only exist on an RBD that was cloned from a snapshot.

Fixes: https://tracker.ceph.com/issues/42480
Signed-off-by: Stephan Müller <smueller@suse.com>
(cherry picked from commit 31ea95946497afa6a46a6322ef48dea9729134d4)

 Conflicts:
src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.spec.ts

src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.html
src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.ts

index af73500de78872cb45cfa800d656743fb2f3c2e9..ccd95925353571c5afdbcada2ef6ad2bd956c43a 100644 (file)
@@ -7,6 +7,7 @@
           columnMode="flex"
           [columns]="columns"
           identifier="id"
+          [searchableObjects]="true"
           forceIdentifier="true"
           selectionType="single"
           (updateSelection)="updateSelection($event)">
index 780192b0b9e9c0cca6a8638f95b484300f3b2e48..44299f00acee037fe2635f683248c469945ac876 100644 (file)
@@ -77,14 +77,6 @@ describe('TableComponent', () => {
     it('should have an int in setLimit parsing a string', () => {
       expect(component.limit).toBe(10);
       expect(component.limit).toEqual(jasmine.any(Number));
-
-      const e = { target: { value: '1' } };
-      component.setLimit(e);
-      expect(component.userConfig.limit).toBe(1);
-      expect(component.userConfig.limit).toEqual(jasmine.any(Number));
-      e.target.value = '-20';
-      component.setLimit(e);
-      expect(component.userConfig.limit).toBe(1);
     });
 
     it('should prevent propagation of mouseenter event', (done) => {
@@ -111,85 +103,122 @@ describe('TableComponent', () => {
       expect(component.sorts[0].prop).toBe('a');
       expect(component.sorts).toEqual(component.createSortingDefinition('a'));
     });
+  });
 
-    describe('test search', () => {
-      const doSearch = (search: string, expectedLength: number, firstObject?: object) => {
-        component.search = search;
-        component.updateFilter();
-        expect(component.rows.length).toBe(expectedLength);
-        if (firstObject) {
-          expect(component.rows[0]).toEqual(firstObject);
+  describe('test search', () => {
+    const doSearch = (search: string, expectedLength: number, firstObject?: object) => {
+      component.search = search;
+      component.updateFilter();
+      expect(component.rows.length).toBe(expectedLength);
+      if (firstObject) {
+        expect(component.rows[0]).toEqual(firstObject);
+      }
+    };
+
+    describe('searchableObjects', () => {
+      const testObject = {
+        obj: {
+          min: 8,
+          max: 123
         }
       };
 
-      it('should search for 13', () => {
-        doSearch('13', 9, { a: 7, b: 49, c: [-7, 'score13'], d: false });
-        expect(component.rows[1].a).toBe(13);
-        expect(component.rows[8].a).toBe(87);
+      beforeEach(() => {
+        component.data = [testObject];
+        component.columns = [{ prop: 'obj', name: 'Object' }];
       });
 
-      it('should search for true', () => {
-        doSearch('true', 50, { a: 0, b: 0, c: [-0, 'score6'], d: true });
-        expect(component.rows[0].d).toBe(true);
-        expect(component.rows[1].d).toBe(true);
+      it('should not search through objects as default case', () => {
+        expect(component.searchableObjects).toBe(false);
+        doSearch('8', 0);
       });
 
-      it('should search for false', () => {
-        doSearch('false', 50, { a: 1, b: 1, c: [-1, 'score7'], d: false });
-        expect(component.rows[0].d).toBe(false);
-        expect(component.rows[1].d).toBe(false);
+      it('should search through objects if searchableObjects is set to true', () => {
+        component.searchableObjects = true;
+        doSearch('28', 0);
+        doSearch('8', 1, testObject);
+        doSearch('123', 1, testObject);
+        doSearch('max', 1, testObject);
       });
+    });
 
-      it('should test search manipulation', () => {
-        let searchTerms = [];
-        spyOn(component, 'subSearch').and.callFake((_d, search) => {
-          expect(search).toEqual(searchTerms);
-        });
-        const searchTest = (s: string, st: string[]) => {
-          component.search = s;
-          searchTerms = st;
-          component.updateFilter();
-        };
-        searchTest('a b c', ['a', 'b', 'c']);
-        searchTest('a+b c', ['a+b', 'c']);
-        searchTest('a,,,, b,,,     c', ['a', 'b', 'c']);
-        searchTest('a,,,+++b,,,     c', ['a+++b', 'c']);
-        searchTest('"a b c"   "d e  f", "g, h i"', ['a+b+c', 'd+e++f', 'g+h+i']);
-      });
+    it('should find a particular number', () => {
+      doSearch('5', 37, { a: 5, b: 25, c: [-5, 'score11'], d: false });
+      // { a: 3, b: 9, c: [ -3, 'score9' ], d: false },
+      // { a: 7, b: 49, c: [ -7, 'score13' ], d: false },
+      // { a: 9, b: 81, c: [ -9, 'score15' ], d: false },
 
-      it('should search for multiple values', () => {
-        doSearch('7 5 3', 5, { a: 57, b: 3249, c: [-7, 'score15'], d: false });
-      });
+      doSearch('9', 50, { a: 3, b: 9, c: [-3, 'score9'], d: false });
+    });
 
-      it('should search with column filter', () => {
-        doSearch('power:1369', 1, { a: 37, b: 1369, c: [-7, 'score11'], d: false });
-        doSearch('ndex:7 ofa:5 poker:3', 3, { a: 71, b: 5041, c: [-1, 'score13'], d: false });
-      });
+    it('should search for 13', () => {
+      doSearch('13', 9, { a: 7, b: 49, c: [-7, 'score13'], d: false });
+      expect(component.rows[1].a).toBe(13);
+      expect(component.rows[8].a).toBe(87);
+    });
 
-      it('should search with through array', () => {
-        doSearch('array:score21', 6, { a: 15, b: 225, c: [-5, 'score21'], d: false });
-      });
+    it('should search for true', () => {
+      doSearch('true', 50, { a: 0, b: 0, c: [-0, 'score6'], d: true });
+      expect(component.rows[0].d).toBe(true);
+      expect(component.rows[1].d).toBe(true);
+    });
 
-      it('should search with spaces', () => {
-        doSearch(`'poker array':score21`, 6, { a: 15, b: 225, c: [-5, 'score21'], d: false });
-        doSearch('"poker array":score21', 6, { a: 15, b: 225, c: [-5, 'score21'], d: false });
-        doSearch('poker+array:score21', 6, { a: 15, b: 225, c: [-5, 'score21'], d: false });
-      });
+    it('should search for false', () => {
+      doSearch('false', 50, { a: 1, b: 1, c: [-1, 'score7'], d: false });
+      expect(component.rows[0].d).toBe(false);
+      expect(component.rows[1].d).toBe(false);
+    });
 
-      it('should search if column name is incomplete', () => {
-        doSearch(`'poker array'`, 0);
-        doSearch('pok', 0);
-        doSearch('pok:', 100);
+    it('should test search manipulation', () => {
+      let searchTerms = [];
+      spyOn(component, 'subSearch').and.callFake((_d, search) => {
+        expect(search).toEqual(searchTerms);
       });
-
-      it('should restore full table after search', () => {
-        expect(component.rows.length).toBe(100);
-        component.search = '13';
+      const searchTest = (s: string, st: string[]) => {
+        component.search = s;
+        searchTerms = st;
         component.updateFilter();
-        expect(component.rows.length).toBe(9);
-        component.updateFilter(true);
-        expect(component.rows.length).toBe(100);
-      });
+      };
+      searchTest('a b c', ['a', 'b', 'c']);
+      searchTest('a+b c', ['a+b', 'c']);
+      searchTest('a,,,, b,,,     c', ['a', 'b', 'c']);
+      searchTest('a,,,+++b,,,     c', ['a+++b', 'c']);
+      searchTest('"a b c"   "d e  f", "g, h i"', ['a+b+c', 'd+e++f', 'g+h+i']);
+    });
+
+    it('should search for multiple values', () => {
+      doSearch('7 5 3', 5, { a: 57, b: 3249, c: [-7, 'score15'], d: false });
+    });
+
+    it('should search with column filter', () => {
+      doSearch('power:1369', 1, { a: 37, b: 1369, c: [-7, 'score11'], d: false });
+      doSearch('ndex:7 ofa:5 poker:3', 3, { a: 71, b: 5041, c: [-1, 'score13'], d: false });
+    });
+
+    it('should search with through array', () => {
+      doSearch('array:score21', 6, { a: 15, b: 225, c: [-5, 'score21'], d: false });
+    });
+
+    it('should search with spaces', () => {
+      doSearch(`'poker array':score21`, 6, { a: 15, b: 225, c: [-5, 'score21'], d: false });
+      doSearch('"poker array":score21', 6, { a: 15, b: 225, c: [-5, 'score21'], d: false });
+      doSearch('poker+array:score21', 6, { a: 15, b: 225, c: [-5, 'score21'], d: false });
+    });
+
+    it('should search if column name is incomplete', () => {
+      doSearch(`'poker array'`, 0);
+      doSearch('pok', 0);
+      doSearch('pok:', 100);
+    });
+
+    it('should restore full table after search', () => {
+      component.updateFilter();
+      expect(component.rows.length).toBe(100);
+      component.search = '13';
+      component.updateFilter();
+      expect(component.rows.length).toBe(9);
+      component.updateFilter(true);
+      expect(component.rows.length).toBe(100);
     });
   });
 
index 0fc351b610a3f80c38cc63824a7c32f76f6ab9dc..fa29c91094a36831b741d87c901a4c7813e61d9c 100644 (file)
@@ -105,6 +105,10 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges, O
   @Input()
   autoSave = true;
 
+  // Enable this in order to search through the JSON of any used object.
+  @Input()
+  searchableObjects = false;
+
   // Only needed to set if the classAddingTpl is used
   @Input()
   customCss?: { [css: string]: number | string | ((any) => boolean) };
@@ -537,6 +541,15 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges, O
           } else if (_.isNumber(cellValue) || _.isBoolean(cellValue)) {
             cellValue = cellValue.toString();
           }
+
+          if (_.isObjectLike(cellValue)) {
+            if (this.searchableObjects) {
+              cellValue = JSON.stringify(cellValue);
+            } else {
+              return false;
+            }
+          }
+
           return cellValue.toLowerCase().indexOf(searchTerm) !== -1;
         }).length > 0
       );