Skip to content

Commit

Permalink
feat(filters): add new IN_COLLECTION operator to allow searching cell…
Browse files Browse the repository at this point in the history
… value as Array (#282)

* feat(filters): add new IN_COLLECTION operator to allow searching cell value as Array

Co-authored-by: Arnaud Van Herck <[email protected]>
  • Loading branch information
ArnaudVanHerck and AVHHogia authored Mar 18, 2021
1 parent 4fdab08 commit ecce93c
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 4 deletions.
2 changes: 1 addition & 1 deletion packages/common/src/enums/operatorString.type.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export type OperatorString = '' | '<>' | '!=' | '=' | '==' | '>' | '>=' | '<' | '<=' | '*' | 'a*' | '*z' | 'EQ' | 'GE' | 'GT' | 'NE' | 'LE' | 'LT' | 'IN' | 'NIN' | 'NOT_IN' | 'IN_CONTAINS' | 'NIN_CONTAINS' | 'NOT_IN_CONTAINS' | 'NOT_CONTAINS' | 'Not_Contains' | 'CONTAINS' | 'Contains' | 'EndsWith' | 'StartsWith' | 'RangeInclusive' | 'RangeExclusive';
export type OperatorString = '' | '<>' | '!=' | '=' | '==' | '>' | '>=' | '<' | '<=' | '*' | 'a*' | '*z' | 'EQ' | 'GE' | 'GT' | 'NE' | 'LE' | 'LT' | 'IN' | 'NIN' | 'NOT_IN' | 'IN_CONTAINS' | 'NIN_CONTAINS' | 'NOT_IN_CONTAINS' | 'NOT_CONTAINS' | 'Not_Contains' | 'CONTAINS' | 'Contains' | 'EndsWith' | 'StartsWith' | 'RangeInclusive' | 'RangeExclusive' | 'IN_COLLECTION' | 'NOT_IN_COLLECTION';
6 changes: 6 additions & 0 deletions packages/common/src/enums/operatorType.enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,10 @@ export enum OperatorType {

/** Inversed (Not In) of substring contained inside a collection */
notInContains = 'NOT_IN_CONTAINS',

/** Find a value from within a collection inside another collection */
inCollection = 'IN_COLLECTION',

/** Inversed (Not In) of looking for a value from a collection inside another collection */
notInCollection = 'NOT_IN_COLLECTION'
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,76 @@ describe('executeCollectionSearchFilterCondition method', () => {
expect(output1).toBe(false);
expect(output2).toBe(false);
});

it('should return True when input value is found when using "InCollection" searchTerms content (string)', () => {
const options = { dataKey: '', operator: 'IN_COLLECTION', cellValue: ['Task2', 'Task3'], fieldType: FieldType.string, searchTerms: ['Task2', 'Task3'] } as FilterConditionOption;
const output = executeCollectionSearchFilterCondition(options);
expect(output).toBe(true);
});

it('should return True when input value is found when using "InCollection" searchTerms content (number)', () => {
const options = { dataKey: '', operator: 'IN_COLLECTION', cellValue: [2, 3], fieldType: FieldType.number, searchTerms: ['2', '3'] } as FilterConditionOption;
const output = executeCollectionSearchFilterCondition(options);
expect(output).toBe(true);
});

it('should return True when input value is found when using "InCollection" searchTerms content (boolean)', () => {
const options = { dataKey: '', operator: 'IN_COLLECTION', cellValue: [true], fieldType: FieldType.boolean, searchTerms: ['true', 'false'] } as FilterConditionOption;
const output = executeCollectionSearchFilterCondition(options);
expect(output).toBe(true);
});

it('should return False when input value is not found when using "InCollection" searchTerms content (string)', () => {
const options = { dataKey: '', operator: 'IN_COLLECTION', cellValue: ['Task11', 'Task22', 'Task33'], fieldType: FieldType.string, searchTerms: ['Task1', 'Task2', 'Task3'] } as FilterConditionOption;
const output = executeCollectionSearchFilterCondition(options);
expect(output).toBe(false);
});

it('should return False when input value is not found when using "InCollection" searchTerms content (number)', () => {
const options = { dataKey: '', operator: 'IN_COLLECTION', cellValue: [2, 3], fieldType: FieldType.number, searchTerms: ['4', '5'] } as FilterConditionOption;
const output = executeCollectionSearchFilterCondition(options);
expect(output).toBe(false);
});

it('should return False when input value is not found when using "InCollection" searchTerms content (boolean)', () => {
const options = { dataKey: '', operator: 'IN_COLLECTION', cellValue: [true], fieldType: FieldType.boolean, searchTerms: ['false'] } as FilterConditionOption;
const output = executeCollectionSearchFilterCondition(options);
expect(output).toBe(false);
});

it('should return True when input value is not found when using "NotInCollection" searchTerms content (string)', () => {
const options = { dataKey: '', operator: 'NOT_IN_COLLECTION', cellValue: ['Task22', 'Task33'], fieldType: FieldType.string, searchTerms: ['Task2', 'Task3'] } as FilterConditionOption;
const output = executeCollectionSearchFilterCondition(options);
expect(output).toBe(true);
});

it('should return True when input value is not found when using "NotInCollection" searchTerms content (number)', () => {
const options = { dataKey: '', operator: 'NOT_IN_COLLECTION', cellValue: [22, 33], fieldType: FieldType.number, searchTerms: ['2', '3'] } as FilterConditionOption;
const output = executeCollectionSearchFilterCondition(options);
expect(output).toBe(true);
});

it('should return True when input value is not found when using "NotInCollection" searchTerms content (boolean)', () => {
const options = { dataKey: '', operator: 'NOT_IN_COLLECTION', cellValue: [true], fieldType: FieldType.boolean, searchTerms: ['false'] } as FilterConditionOption;
const output = executeCollectionSearchFilterCondition(options);
expect(output).toBe(true);
});

it('should return False when input value is found when using "NotInCollection" searchTerms content (string)', () => {
const options = { dataKey: '', operator: 'NOT_IN_COLLECTION', cellValue: ['Task2', 'Task3'], fieldType: FieldType.string, searchTerms: ['Task2', 'Task3'] } as FilterConditionOption;
const output = executeCollectionSearchFilterCondition(options);
expect(output).toBe(false);
});

it('should return False when input value is found when using "NotInCollection" searchTerms content (number)', () => {
const options = { dataKey: '', operator: 'NOT_IN_COLLECTION', cellValue: [2, 3], fieldType: FieldType.number, searchTerms: ['2', '3'] } as FilterConditionOption;
const output = executeCollectionSearchFilterCondition(options);
expect(output).toBe(false);
});

it('should return False when input value is found when using "NotInCollection" searchTerms content (boolean)', () => {
const options = { dataKey: '', operator: 'NOT_IN_COLLECTION', cellValue: [true, false], fieldType: FieldType.boolean, searchTerms: ['true', 'false'] } as FilterConditionOption;
const output = executeCollectionSearchFilterCondition(options);
expect(output).toBe(false);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,55 @@ describe('filterUtilities', () => {
expect(output1).toBeFalsy();
expect(output2).toBeFalsy();
});

it('should return False when value2 is not a collection', () => {
const output = testFilterCondition('NOT_IN_CONTAINS', 'Task2,Task3', 'Task2');
expect(output).toBeFalsy();
});

it('should return True when some of value1 is "IN_COLLECTION" of value2 collection', () => {
const output = testFilterCondition('IN_COLLECTION', ['Task2', 'Task3'], ['Task2']);
expect(output).toBeTruthy();
});

it('should return True when both of value1 is "IN_COLLECTION" of value2 collection', () => {
const output = testFilterCondition('IN_COLLECTION', ['Task2', 'Task3'], ['Task2', 'Task3']);
expect(output).toBeTruthy();
});

it('should return False when none of value1 is "IN_COLLECTION" of value2 collection', () => {
const output = testFilterCondition('IN_COLLECTION', ['Task11', 'Task4'], ['Task 1', 'Task2', 'Task3']);
expect(output).toBeFalsy();
});

it('should return False when is value1 not a collection', () => {
const output = testFilterCondition('IN_COLLECTION', 'Task1,Task4', ['Task2']);
expect(output).toBeFalsy();
});

it('should return False when value2 is not a collection', () => {
const output = testFilterCondition('IN_COLLECTION', ['Task2', 'Task3'], 'Task2');
expect(output).toBeFalsy();
});

it('should return True when none of value1 is "NOT_IN_COLLECTION" of value2 collection', () => {
const output1 = testFilterCondition('NOT_IN_COLLECTION', ['Task11', 'Task4'], ['Task1', 'Task2', 'Task3']);
expect(output1).toBeTruthy();
});

it('should return False when value1 is not "NOT_IN_COLLECTION" value2 collection', () => {
const output1 = testFilterCondition('NOT_IN_COLLECTION', ['Task2', 'Task3'], ['Task2', 'Task3']);
expect(output1).toBeFalsy();
});

it('should return False when value1 is not a collection', () => {
const output = testFilterCondition('NOT_IN_COLLECTION', 'Task2, Task3', ['Task2']);
expect(output).toBeFalsy();
});

it('should return False when value2 is not a collection', () => {
const output = testFilterCondition('NOT_IN_COLLECTION', ['Task2', 'Task3'], 'Task2');
expect(output).toBeFalsy();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ import { testFilterCondition } from './filterUtilities';
*/
export const executeCollectionSearchFilterCondition: FilterCondition = (options: FilterConditionOption) => {
// multiple-select will always return text, so we should make our cell values text as well
const cellValue = (options.cellValue === undefined || options.cellValue === null) ? '' : `${options.cellValue}`;
const filterOperator = options.operator;
let cellValue: string | string[];
if (Array.isArray(options.cellValue) && (filterOperator === 'IN_COLLECTION' || filterOperator === 'NOT_IN_COLLECTION')) {
cellValue = (!!options.cellValue.length ? options.cellValue.map(value => `${value}`) : []);
} else {
cellValue = (options.cellValue === undefined || options.cellValue === null) ? '' : `${options.cellValue}`;
}

return testFilterCondition(options.operator || 'IN', cellValue, options.searchTerms || []);
return testFilterCondition(filterOperator || 'IN', cellValue, options.searchTerms || []);
};
12 changes: 12 additions & 0 deletions packages/common/src/filter-conditions/filterUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ export function isCollectionOperator(operator: OperatorString): boolean {
case 'IN_CONTAINS':
case 'NIN_CONTAINS':
case 'NOT_IN_CONTAINS':
case 'IN_COLLECTION':
case 'NOT_IN_COLLECTION':
return true;
default:
return false;
Expand Down Expand Up @@ -82,6 +84,16 @@ export const testFilterCondition = (operator: OperatorString, value1: any, value
return !value2.some(item => value1.split(/[\s,]+/).includes(item));
}
return false;
case 'IN_COLLECTION':
if (value1 && value2 && Array.isArray(value1) && Array.isArray(value2)) {
return value2.some(item => value1.includes(item));
}
return false;
case 'NOT_IN_COLLECTION':
if (value1 && value2 && Array.isArray(value1) && Array.isArray(value2)) {
return !value2.some(item => value1.includes(item));
}
return false;
}
return true;
};

0 comments on commit ecce93c

Please sign in to comment.