Skip to content

Commit

Permalink
fix(presets): compound filters operator not working correctly w/prese…
Browse files Browse the repository at this point in the history
…ts (#507)

* fix(presets): compound filters operator not working correctly w/presets
- grid presets should work with short/long operator names, basically StartsWith/EndsWith were not working correctly while a*/*z were working correctly, both options should work
  • Loading branch information
ghiscoding authored Jun 25, 2020
1 parent fbe0d5f commit f7b5270
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,8 @@ export class CompoundDateFilter implements Filter {
this.$filterInputElm.data('columnId', fieldId);

if (this.operator) {
this.$selectOperatorElm.val(this.operator);
const operatorShorthand = mapOperatorToShorthandDesignation(this.operator);
this.$selectOperatorElm.val(operatorShorthand);
}

// if there's a search term, we will add the "filled" class for styling purposes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,8 @@ export class CompoundInputFilter implements Filter {
this.$filterInputElm.data('columnId', fieldId);

if (this.operator) {
this.$selectOperatorElm.val(this.operator);
const operatorShorthand = mapOperatorToShorthandDesignation(this.operator);
this.$selectOperatorElm.val(operatorShorthand);
}

// if there's a search term, we will add the "filled" class for styling purposes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,8 @@ export class CompoundSliderFilter implements Filter {
this.$filterInputElm.data('columnId', fieldId);

if (this.operator) {
this.$selectOperatorElm.val(this.operator);
const operatorShorthand = mapOperatorToShorthandDesignation(this.operator);
this.$selectOperatorElm.val(operatorShorthand);
}

// if there's a search term, we will add the "filled" class for styling purposes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,20 @@ describe('GraphqlService', () => {
expect(removeSpaces(query)).toBe(removeSpaces(expectation));
});

it('should return a query with search having the operator EndsWith when the Column Filter was provided as EndsWith', () => {
const expectation = `query{users(first:10, offset:0, filterBy:[{field:gender, operator:EndsWith, value:"le"}]) { totalCount,nodes{ id,company,gender,name } }}`;
const mockColumn = { id: 'gender', field: 'gender', filter: { operator: 'EndsWith' } } as Column;
const mockColumnFilters = {
gender: { columnId: 'gender', columnDef: mockColumn, searchTerms: ['le'] },
} as ColumnFilters;

service.init(serviceOptions, paginationOptions, gridStub);
service.updateFilters(mockColumnFilters, false);
const query = service.buildQuery();

expect(removeSpaces(query)).toBe(removeSpaces(expectation));
});

it('should return a query with search having the operator StartsWith when the operator was provided as a*', () => {
const expectation = `query{users(first:10, offset:0, filterBy:[{field:gender, operator:StartsWith, value:"le"}]) { totalCount,nodes{ id,company,gender,name } }}`;
const mockColumn = { id: 'gender', field: 'gender' } as Column;
Expand All @@ -799,6 +813,20 @@ describe('GraphqlService', () => {
expect(removeSpaces(query)).toBe(removeSpaces(expectation));
});

it('should return a query with search having the operator StartsWith when the operator was provided as StartsWith', () => {
const expectation = `query{users(first:10, offset:0, filterBy:[{field:gender, operator:StartsWith, value:"le"}]) { totalCount,nodes{ id,company,gender,name } }}`;
const mockColumn = { id: 'gender', field: 'gender' } as Column;
const mockColumnFilters = {
gender: { columnId: 'gender', columnDef: mockColumn, searchTerms: ['le'], operator: 'StartsWith' },
} as ColumnFilters;

service.init(serviceOptions, paginationOptions, gridStub);
service.updateFilters(mockColumnFilters, false);
const query = service.buildQuery();

expect(removeSpaces(query)).toBe(removeSpaces(expectation));
});

it('should return a query with search having a range of exclusive numbers when the search value contains 2 (..) to represent a range of numbers', () => {
const expectation = `query{users(first:10, offset:0, filterBy:[{field:duration, operator:GT, value:"2"}, {field:duration, operator:LT, value:"33"}]) { totalCount,nodes{ id,company,gender,name } }}`;
const mockColumn = { id: 'duration', field: 'duration' } as Column;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,13 +297,13 @@ describe('GridOdataService', () => {
});

it('should return a query with a new filter when previous filters exists', () => {
const expectation = `$top=10&$filter=(Gender eq 'female' and FirstName eq 'John')`;
const expectation = `$top=10&$filter=(Gender eq 'female' and endswith(FirstName, 'John'))`;
const querySpy = jest.spyOn(service.odataService, 'buildQuery');
const resetSpy = jest.spyOn(service, 'resetPaginationOptions');
const mockColumn = { id: 'gender', field: 'gender' } as Column;
const mockColumnName = { id: 'firstName', field: 'firstName' } as Column;
const mockColumnFilter = { columnDef: mockColumn, columnId: 'gender', operator: 'EQ', searchTerms: ['female'] } as ColumnFilter;
const mockColumnFilterName = { columnDef: mockColumnName, columnId: 'firstName', operator: 'StartsWith', searchTerms: ['John'] } as ColumnFilter;
const mockColumnFilterName = { columnDef: mockColumnName, columnId: 'firstName', operator: 'EndsWith', searchTerms: ['John'] } as ColumnFilter;
const mockFilterChangedArgs = {
columnDef: mockColumn,
columnId: 'gender',
Expand All @@ -323,7 +323,7 @@ describe('GridOdataService', () => {
expect(resetSpy).toHaveBeenCalled();
expect(currentFilters).toEqual([
{ columnId: 'gender', operator: 'EQ', searchTerms: ['female'] },
{ columnId: 'firstName', operator: 'StartsWith', searchTerms: ['John'] }
{ columnId: 'firstName', operator: 'EndsWith', searchTerms: ['John'] }
]);
});

Expand Down Expand Up @@ -359,7 +359,7 @@ describe('GridOdataService', () => {
});

it('should return a query with a new filter when previous filters exists when "enablePagination" is set to False', () => {
const expectation = `$filter=(Gender eq 'female' and FirstName eq 'John')`;
const expectation = `$filter=(Gender eq 'female' and startswith(FirstName, 'John'))`;
const querySpy = jest.spyOn(service.odataService, 'buildQuery');
const resetSpy = jest.spyOn(service, 'resetPaginationOptions');
const mockColumn = { id: 'gender', field: 'gender' } as Column;
Expand Down
14 changes: 7 additions & 7 deletions src/app/modules/angular-slickgrid/services/grid-odata.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ export class GridOdataService implements BackendService {
const matches = fieldSearchValue.match(/^([<>!=\*]{0,2})(.*[^<>!=\*])([\*]?)$/); // group 1: Operator, 2: searchValue, 3: last char is '*' (meaning starts with, ex.: abc*)
let operator = columnFilter.operator || ((matches) ? matches[1] : '');
let searchValue = (!!matches) ? matches[2] : '';
const lastValueChar = (!!matches) ? matches[3] : (operator === '*z' ? '*' : '');
const lastValueChar = (!!matches) ? matches[3] : (operator === '*z' || operator === OperatorType.endsWith) ? '*' : '';
const bypassOdataQuery = columnFilter.bypassBackendQuery || false;

// no need to query if search value is empty
Expand Down Expand Up @@ -350,9 +350,9 @@ export class GridOdataService implements BackendService {
searchBy = `(${searchBy})`;
}
}
} else if (operator === '*' || operator === 'a*' || operator === '*z' || lastValueChar === '*') {
} else if (operator === '*' || operator === 'a*' || operator === '*z' || lastValueChar === '*' || operator === OperatorType.startsWith || operator === OperatorType.endsWith) {
// first/last character is a '*' will be a startsWith or endsWith
searchBy = (operator === '*' || operator === '*z') ? `endswith(${fieldName}, '${searchValue}')` : `startswith(${fieldName}, '${searchValue}')`;
searchBy = (operator === '*' || operator === '*z' || operator === OperatorType.endsWith) ? `endswith(${fieldName}, '${searchValue}')` : `startswith(${fieldName}, '${searchValue}')`;
} else if (fieldType === FieldType.string) {
// string field needs to be in single quotes
if (operator === '' || operator === OperatorType.contains || operator === OperatorType.notContains) {
Expand Down Expand Up @@ -535,7 +535,7 @@ export class GridOdataService implements BackendService {
});
}

private odataQueryVersionWrapper(queryType: 'dateTime' | 'substring', version: number, fieldName: string, searchValue: string): string {
private odataQueryVersionWrapper(queryType: 'dateTime' | 'substring', version: number, fieldName: string, searchValue = ''): string {
let query = '';
switch (queryType) {
case 'dateTime':
Expand All @@ -556,16 +556,16 @@ export class GridOdataService implements BackendService {
*/
private filterBySearchDate(fieldName: string, operator: OperatorType | OperatorString, searchTerms: SearchTerm[], version: number): string {
let query = '';
let searchValues: SearchTerm[];
let searchValues: SearchTerm[] = [];
if (Array.isArray(searchTerms) && searchTerms.length > 1) {
searchValues = searchTerms;
if (operator !== OperatorType.rangeExclusive && operator !== OperatorType.rangeInclusive) {
if (operator !== OperatorType.rangeExclusive && operator !== OperatorType.rangeInclusive && this._gridOptions.defaultFilterRangeOperator) {
operator = this._gridOptions.defaultFilterRangeOperator;
}
}

// single search value
if (!Array.isArray(searchValues) && Array.isArray(searchTerms) && searchTerms.length === 1 && searchTerms[0]) {
if (searchValues.length === 0 && Array.isArray(searchTerms) && searchTerms.length === 1 && searchTerms[0]) {
const searchValue1 = this.odataQueryVersionWrapper('dateTime', version, fieldName, parseUtcDate(searchTerms[0] as string, true));
if (searchValue1) {
return `${fieldName} ${this.mapOdataOperator(operator)} ${searchValue1}`;
Expand Down

0 comments on commit f7b5270

Please sign in to comment.