]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: Search with spaces 20807/head
authorStephan Müller <smueller@suse.com>
Fri, 16 Mar 2018 10:55:44 +0000 (11:55 +0100)
committerStephan Müller <smueller@suse.com>
Fri, 6 Apr 2018 14:50:24 +0000 (16:50 +0200)
Removed the usage of using comma to indicated a new search term and
introduced the possibility to use quoted strings in order to search for
spaces too.

Also improved the column search handling in order to not get no search
results found while typing a column name.

Signed-off-by: Stephan Müller <smueller@suse.com>
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 8340dc6adf1fec65059dd254e982fd60039183b4..92f6ec905c376c6710d2675426ddbf0b61dd5a50 100644 (file)
@@ -83,6 +83,23 @@ describe('TableComponent', () => {
     expect(component.rows[8].a).toBe(87);
   });
 
+  it('should test search manipulation', () => {
+    let searchTerms = [];
+    spyOn(component, 'subSearch').and.callFake((d, search, c) => {
+      expect(search).toEqual(searchTerms);
+    });
+    const searchTest = (s: string, st: string[]) => {
+      component.search = s;
+      searchTerms = st;
+      component.updateFilter(true);
+    };
+    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']});
   });
@@ -96,6 +113,18 @@ describe('TableComponent', () => {
     doSearch('array:score21', 6, {a: 15, b: 225, c: [-5, 'score21']});
   });
 
+  it('should search with spaces', () => {
+    doSearch('\'poker array\':score21', 6, {a: 15, b: 225, c: [-5, 'score21']});
+    doSearch('"poker array":score21', 6, {a: 15, b: 225, c: [-5, 'score21']});
+    doSearch('poker+array:score21', 6, {a: 15, b: 225, c: [-5, 'score21']});
+  });
+
+  it('should not search if column name is incomplete', () => {
+    doSearch('\'poker array\'', 100, {a: 0, b: 0, c: [-0, 'score6']});
+    doSearch('pok', 100, {a: 0, b: 0, c: [-0, 'score6']});
+    doSearch('pok:', 100, {a: 0, b: 0, c: [-0, 'score6']});
+  });
+
   it('should restore full table after search', () => {
     expect(component.rows.length).toBe(100);
     component.search = '13';
index efda07a9180718ffefa128318e8802003f838e10..a528946737ab8609f22239426894b7f7b835b145 100644 (file)
@@ -255,44 +255,61 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges, O
     if (!event) {
       this.search = '';
     }
+    let search = this.search.toLowerCase().replace(/,/g, '');
     const columns = this.columns.filter(c => c.cellTransformation !== CellTemplate.sparkline);
+    if (search.match(/['"][^'"]+['"]/)) {
+      search = search.replace(/['"][^'"]+['"]/g, (match: string) => {
+        return match.replace(/(['"])([^'"]+)(['"])/g, '$2').replace(/ /g, '+');
+      });
+    }
     // update the rows
-    this.rows = this.subSearch(this.data, this.search.toLowerCase().split(/[, ]/), columns);
+    this.rows = this.subSearch(this.data, search.split(' ').filter(s => s.length > 0), columns);
     // Whenever the filter changes, always go back to the first page
     this.table.offset = 0;
   }
 
   subSearch (data: any[], currentSearch: string[], columns: CdTableColumn[]) {
-    let tempColumns: CdTableColumn[];
     if (currentSearch.length === 0 || data.length === 0) {
       return data;
     }
-    const searchWords: string[] = currentSearch.pop().split(':');
-    if (searchWords.length === 2) {
-      tempColumns = [...columns];
-      columns = columns.filter((c) => c.name.toLowerCase().indexOf(searchWords[0]) !== -1);
+    const searchTerms: string[] = currentSearch.pop().replace('+', ' ').split(':');
+    const columnsClone = [...columns];
+    const dataClone = [...data];
+    const filterColumns = (columnName: string) =>
+      columnsClone.filter((c) => c.name.toLowerCase().indexOf(columnName) !== -1);
+    if (searchTerms.length === 2) {
+      columns = filterColumns(searchTerms[0]);
     }
-    const searchWord: string = _.last(searchWords);
-    if (searchWord.length > 0) {
-      data = data.filter(d => {
-        return columns.filter(c => {
-          let cellValue: any = _.get(d, c.prop);
-          if (_.isUndefined(cellValue)) {
-            return;
-          }
-          if (_.isArray(cellValue)) {
-            cellValue = cellValue.join('');
-          } else if (_.isNumber(cellValue)) {
-            cellValue = cellValue.toString();
-          }
-          return cellValue.toLowerCase().indexOf(searchWord) !== -1;
-        }).length > 0;
-      });
+    const searchTerm: string = _.last(searchTerms);
+    data = this.basicDataSearch(searchTerm, data, columns);
+    // Checks if user searches for column but he is still typing
+    if (data.length === 0 && searchTerms.length === 1 && filterColumns(searchTerm).length > 0) {
+      data = dataClone;
     }
-    if (_.isArray(tempColumns)) {
-      columns = tempColumns;
+    return this.subSearch(data, currentSearch, columnsClone);
+  }
+
+  basicDataSearch(searchTerm: string, data: any[], columns: CdTableColumn[]) {
+    if (searchTerm.length === 0) {
+      return data;
     }
-    return this.subSearch(data, currentSearch, columns);
+    return data.filter(d => {
+      return columns.filter(c => {
+        let cellValue: any = _.get(d, c.prop);
+        if (!_.isUndefined(c.pipe)) {
+          cellValue = c.pipe.transform(cellValue);
+        }
+        if (_.isUndefined(cellValue)) {
+          return;
+        }
+        if (_.isArray(cellValue)) {
+          cellValue = cellValue.join(' ');
+        } else if (_.isNumber(cellValue)) {
+          cellValue = cellValue.toString();
+        }
+        return cellValue.toLowerCase().indexOf(searchTerm) !== -1;
+      }).length > 0;
+    });
   }
 
   getRowClass() {