Skip to content

Commit

Permalink
feat(filters): option to add custom compound operator list
Browse files Browse the repository at this point in the history
  • Loading branch information
ghiscoding committed Apr 21, 2021
1 parent 515a072 commit 3e8d2cb
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 52 deletions.
19 changes: 19 additions & 0 deletions packages/common/src/filters/__tests__/compoundDateFilter.spec.ts
Expand Up @@ -344,6 +344,25 @@ describe('CompoundDateFilter', () => {
expect(removeExtraSpaces(filterOperatorElm[0][6].textContent!)).toBe('<> Not equal to');
});

it('should have custom compound operator list showing up in the operator select dropdown options list', () => {
mockColumn.outputType = null as any;
filterArguments.searchTerms = ['2000-01-01T05:00:00.000Z'];
mockColumn.filter.compoundOperatorList = [
{ operator: '', description: '' },
{ operator: '=', description: 'Equal to' },
{ operator: '<', description: 'Less than' },
{ operator: '>', description: 'Greater than' },
];

filter.init(filterArguments);
const filterOperatorElm = divContainer.querySelectorAll<HTMLSelectElement>('.input-group-prepend.operator select');

expect(filterOperatorElm[0][0].title).toBe('');
expect(removeExtraSpaces(filterOperatorElm[0][1].textContent!)).toBe('= Equal to');
expect(removeExtraSpaces(filterOperatorElm[0][2].textContent!)).toBe('< Less than');
expect(removeExtraSpaces(filterOperatorElm[0][3].textContent!)).toBe('> Greater than');
});

describe('with French I18N translations', () => {
beforeEach(() => {
gridOptionMock.enableTranslate = true;
Expand Down
19 changes: 19 additions & 0 deletions packages/common/src/filters/__tests__/compoundInputFilter.spec.ts
Expand Up @@ -320,6 +320,25 @@ describe('CompoundInputFilter', () => {
expect(spyCallback).toHaveBeenCalledWith(undefined, { columnDef: mockColumn, clearFilterTriggered: true, shouldTriggerQuery: false });
});

it('should have custom compound operator list showing up in the operator select dropdown options list', () => {
mockColumn.outputType = null as any;
filterArguments.searchTerms = ['xyz'];
mockColumn.filter.compoundOperatorList = [
{ operator: '', description: '' },
{ operator: '=', description: 'Equal to' },
{ operator: '<', description: 'Less than' },
{ operator: '>', description: 'Greater than' },
];

filter.init(filterArguments);
const filterOperatorElm = divContainer.querySelectorAll<HTMLSelectElement>('.search-filter.filter-duration select');

expect(filterOperatorElm[0][0].title).toBe('');
expect(removeExtraSpaces(filterOperatorElm[0][1].textContent!)).toBe('= Equal to');
expect(removeExtraSpaces(filterOperatorElm[0][2].textContent!)).toBe('< Less than');
expect(removeExtraSpaces(filterOperatorElm[0][3].textContent!)).toBe('> Greater than');
});

describe('with French I18N translations', () => {
beforeEach(() => {
gridOptionMock.enableTranslate = true;
Expand Down
19 changes: 19 additions & 0 deletions packages/common/src/filters/__tests__/compoundSliderFilter.spec.ts
Expand Up @@ -239,6 +239,25 @@ describe('CompoundSliderFilter', () => {
expect(removeExtraSpaces(filterOperatorElm[0][6].textContent!)).toBe('<> Not equal to');
});

it('should have custom compound operator list showing up in the operator select dropdown options list', () => {
mockColumn.outputType = null as any;
filterArguments.searchTerms = ['9'];
mockColumn.filter.compoundOperatorList = [
{ operator: '', description: '' },
{ operator: '=', description: 'Equal to' },
{ operator: '<', description: 'Less than' },
{ operator: '>', description: 'Greater than' },
];

filter.init(filterArguments);
const filterOperatorElm = divContainer.querySelectorAll<HTMLSelectElement>('.search-filter.filter-duration select');

expect(filterOperatorElm[0][0].title).toBe('');
expect(removeExtraSpaces(filterOperatorElm[0][1].textContent!)).toBe('= Equal to');
expect(removeExtraSpaces(filterOperatorElm[0][2].textContent!)).toBe('< Less than');
expect(removeExtraSpaces(filterOperatorElm[0][3].textContent!)).toBe('> Greater than');
});

describe('with French I18N translations', () => {
beforeEach(() => {
gridOptionMock.enableTranslate = true;
Expand Down
28 changes: 17 additions & 11 deletions packages/common/src/filters/compoundDateFilter.ts
Expand Up @@ -12,6 +12,7 @@ import {
FlatpickrOption,
GridOption,
Locale,
OperatorDetail,
SlickGrid,
} from '../interfaces/index';
import { FieldType, OperatorString, OperatorType, SearchTerm } from '../enums/index';
Expand Down Expand Up @@ -229,16 +230,21 @@ export class CompoundDateFilter implements Filter {
return $filterInputElm;
}

protected getOptionValues(): { operator: OperatorString, description: string }[] {
return [
{ operator: '', description: '' },
{ operator: '=', description: this.getOutputText('EQUAL_TO', 'TEXT_EQUAL_TO', 'Equal to') },
{ operator: '<', description: this.getOutputText('LESS_THAN', 'TEXT_LESS_THAN', 'Less than') },
{ operator: '<=', description: this.getOutputText('LESS_THAN_OR_EQUAL_TO', 'TEXT_LESS_THAN_OR_EQUAL_TO', 'Less than or equal to') },
{ operator: '>', description: this.getOutputText('GREATER_THAN', 'TEXT_GREATER_THAN', 'Greater than') },
{ operator: '>=', description: this.getOutputText('GREATER_THAN_OR_EQUAL_TO', 'TEXT_GREATER_THAN_OR_EQUAL_TO', 'Greater than or equal to') },
{ operator: '<>', description: this.getOutputText('NOT_EQUAL_TO', 'TEXT_NOT_EQUAL_TO', 'Not equal to') }
];
/** Get the available operator option values to populate the operator select dropdown list */
protected getOperatorOptionValues(): OperatorDetail[] {
if (this.columnFilter?.compoundOperatorList) {
return this.columnFilter.compoundOperatorList;
} else {
return [
{ operator: '', description: '' },
{ operator: '=', description: this.getOutputText('EQUAL_TO', 'TEXT_EQUAL_TO', 'Equal to') },
{ operator: '<', description: this.getOutputText('LESS_THAN', 'TEXT_LESS_THAN', 'Less than') },
{ operator: '<=', description: this.getOutputText('LESS_THAN_OR_EQUAL_TO', 'TEXT_LESS_THAN_OR_EQUAL_TO', 'Less than or equal to') },
{ operator: '>', description: this.getOutputText('GREATER_THAN', 'TEXT_GREATER_THAN', 'Greater than') },
{ operator: '>=', description: this.getOutputText('GREATER_THAN_OR_EQUAL_TO', 'TEXT_GREATER_THAN_OR_EQUAL_TO', 'Greater than or equal to') },
{ operator: '<>', description: this.getOutputText('NOT_EQUAL_TO', 'TEXT_NOT_EQUAL_TO', 'Not equal to') }
];
}
}

/** Get Locale, Translated or a Default Text if first two aren't detected */
Expand All @@ -259,7 +265,7 @@ export class CompoundDateFilter implements Filter {
$($headerElm).empty();

// create the DOM Select dropdown for the Operator
const selectOperatorHtmlString = buildSelectOperatorHtmlString(this.getOptionValues());
const selectOperatorHtmlString = buildSelectOperatorHtmlString(this.getOperatorOptionValues());
this.$selectOperatorElm = $(selectOperatorHtmlString);
this.$filterInputElm = this.buildDatePickerInput(searchTerm);
const $filterContainerElm = $(`<div class="form-group search-filter filter-${columnId}"></div>`);
Expand Down
60 changes: 33 additions & 27 deletions packages/common/src/filters/compoundInputFilter.ts
Expand Up @@ -8,6 +8,7 @@ import {
FilterCallback,
GridOption,
Locale,
OperatorDetail,
SlickGrid,
} from '../interfaces/index';
import { buildSelectOperatorHtmlString } from './filterUtilities';
Expand Down Expand Up @@ -158,35 +159,40 @@ export class CompoundInputFilter implements Filter {
return `<input type="${this._inputType || 'text'}" class="form-control compound-input filter-${columnId}" role="presentation" autocomplete="off" placeholder="${placeholder}" /><span></span>`;
}

protected getOptionValues(): { operator: OperatorString, description: string }[] {
/** Get the available operator option values to populate the operator select dropdown list */
protected getOperatorOptionValues(): OperatorDetail[] {
const type = (this.columnDef.type && this.columnDef.type) ? this.columnDef.type : FieldType.string;
let optionValues = [];

switch (type) {
case FieldType.string:
case FieldType.text:
case FieldType.readonly:
case FieldType.password:
optionValues = [
{ operator: '' as OperatorString, description: this.getOutputText('CONTAINS', 'TEXT_CONTAINS', 'Contains') },
{ operator: '<>' as OperatorString, description: this.getOutputText('NOT_CONTAINS', 'TEXT_NOT_CONTAINS', 'Not Contains') },
{ operator: '=' as OperatorString, description: this.getOutputText('EQUALS', 'TEXT_EQUALS', 'Equals') },
{ operator: '!=' as OperatorString, description: this.getOutputText('NOT_EQUAL_TO', 'TEXT_NOT_EQUAL_TO', 'Not equal to') },
{ operator: 'a*' as OperatorString, description: this.getOutputText('STARTS_WITH', 'TEXT_STARTS_WITH', 'Starts with') },
{ operator: '*z' as OperatorString, description: this.getOutputText('ENDS_WITH', 'TEXT_ENDS_WITH', 'Ends with') },
];
break;
default:
optionValues = [
{ operator: '' as OperatorString, description: '' },
{ operator: '=' as OperatorString, description: this.getOutputText('EQUAL_TO', 'TEXT_EQUAL_TO', 'Equal to') },
{ operator: '<' as OperatorString, description: this.getOutputText('LESS_THAN', 'TEXT_LESS_THAN', 'Less than') },
{ operator: '<=' as OperatorString, description: this.getOutputText('LESS_THAN_OR_EQUAL_TO', 'TEXT_LESS_THAN_OR_EQUAL_TO', 'Less than or equal to') },
{ operator: '>' as OperatorString, description: this.getOutputText('GREATER_THAN', 'TEXT_GREATER_THAN', 'Greater than') },
{ operator: '>=' as OperatorString, description: this.getOutputText('GREATER_THAN_OR_EQUAL_TO', 'TEXT_GREATER_THAN_OR_EQUAL_TO', 'Greater than or equal to') },
{ operator: '<>' as OperatorString, description: this.getOutputText('NOT_EQUAL_TO', 'TEXT_NOT_EQUAL_TO', 'Not equal to') }
];
break;
if (this.columnFilter?.compoundOperatorList) {
return this.columnFilter.compoundOperatorList;
} else {
switch (type) {
case FieldType.string:
case FieldType.text:
case FieldType.readonly:
case FieldType.password:
optionValues = [
{ operator: '' as OperatorString, description: this.getOutputText('CONTAINS', 'TEXT_CONTAINS', 'Contains') },
{ operator: '<>' as OperatorString, description: this.getOutputText('NOT_CONTAINS', 'TEXT_NOT_CONTAINS', 'Not Contains') },
{ operator: '=' as OperatorString, description: this.getOutputText('EQUALS', 'TEXT_EQUALS', 'Equals') },
{ operator: '!=' as OperatorString, description: this.getOutputText('NOT_EQUAL_TO', 'TEXT_NOT_EQUAL_TO', 'Not equal to') },
{ operator: 'a*' as OperatorString, description: this.getOutputText('STARTS_WITH', 'TEXT_STARTS_WITH', 'Starts with') },
{ operator: '*z' as OperatorString, description: this.getOutputText('ENDS_WITH', 'TEXT_ENDS_WITH', 'Ends with') },
];
break;
default:
optionValues = [
{ operator: '' as OperatorString, description: '' },
{ operator: '=' as OperatorString, description: this.getOutputText('EQUAL_TO', 'TEXT_EQUAL_TO', 'Equal to') },
{ operator: '<' as OperatorString, description: this.getOutputText('LESS_THAN', 'TEXT_LESS_THAN', 'Less than') },
{ operator: '<=' as OperatorString, description: this.getOutputText('LESS_THAN_OR_EQUAL_TO', 'TEXT_LESS_THAN_OR_EQUAL_TO', 'Less than or equal to') },
{ operator: '>' as OperatorString, description: this.getOutputText('GREATER_THAN', 'TEXT_GREATER_THAN', 'Greater than') },
{ operator: '>=' as OperatorString, description: this.getOutputText('GREATER_THAN_OR_EQUAL_TO', 'TEXT_GREATER_THAN_OR_EQUAL_TO', 'Greater than or equal to') },
{ operator: '<>' as OperatorString, description: this.getOutputText('NOT_EQUAL_TO', 'TEXT_NOT_EQUAL_TO', 'Not equal to') }
];
break;
}
}

return optionValues;
Expand All @@ -210,7 +216,7 @@ export class CompoundInputFilter implements Filter {
$($headerElm).empty();

// create the DOM Select dropdown for the Operator
const selectOperatorHtmlString = buildSelectOperatorHtmlString(this.getOptionValues());
const selectOperatorHtmlString = buildSelectOperatorHtmlString(this.getOperatorOptionValues());
this.$selectOperatorElm = $(selectOperatorHtmlString);
this.$filterInputElm = $(this.buildInputHtmlString());
const $filterContainerElm = $(`<div class="form-group search-filter filter-${columnId}"></div>`);
Expand Down
29 changes: 17 additions & 12 deletions packages/common/src/filters/compoundSliderFilter.ts
Expand Up @@ -6,6 +6,7 @@ import {
FilterCallback,
GridOption,
Locale,
OperatorDetail,
SlickGrid,
} from '../interfaces/index';
import { Constants } from '../constants';
Expand Down Expand Up @@ -204,17 +205,21 @@ export class CompoundSliderFilter implements Filter {
return `<div class="input-group-addon input-group-append slider-value"><span class="input-group-text ${this._elementRangeOutputId}">${defaultValue}</span></div>`;
}

/** Get the available operator option values */
protected getOptionValues(): { operator: OperatorString, description: string }[] {
return [
{ operator: '', description: '' },
{ operator: '=', description: this.getOutputText('EQUAL_TO', 'TEXT_EQUAL_TO', 'Equal to') },
{ operator: '<', description: this.getOutputText('LESS_THAN', 'TEXT_LESS_THAN', 'Less than') },
{ operator: '<=', description: this.getOutputText('LESS_THAN_OR_EQUAL_TO', 'TEXT_LESS_THAN_OR_EQUAL_TO', 'Less than or equal to') },
{ operator: '>', description: this.getOutputText('GREATER_THAN', 'TEXT_GREATER_THAN', 'Greater than') },
{ operator: '>=', description: this.getOutputText('GREATER_THAN_OR_EQUAL_TO', 'TEXT_GREATER_THAN_OR_EQUAL_TO', 'Greater than or equal to') },
{ operator: '<>', description: this.getOutputText('NOT_EQUAL_TO', 'TEXT_NOT_EQUAL_TO', 'Not equal to') }
];
/** Get the available operator option values to populate the operator select dropdown list */
protected getOperatorOptionValues(): OperatorDetail[] {
if (this.columnFilter?.compoundOperatorList) {
return this.columnFilter.compoundOperatorList;
} else {
return [
{ operator: '', description: '' },
{ operator: '=', description: this.getOutputText('EQUAL_TO', 'TEXT_EQUAL_TO', 'Equal to') },
{ operator: '<', description: this.getOutputText('LESS_THAN', 'TEXT_LESS_THAN', 'Less than') },
{ operator: '<=', description: this.getOutputText('LESS_THAN_OR_EQUAL_TO', 'TEXT_LESS_THAN_OR_EQUAL_TO', 'Less than or equal to') },
{ operator: '>', description: this.getOutputText('GREATER_THAN', 'TEXT_GREATER_THAN', 'Greater than') },
{ operator: '>=', description: this.getOutputText('GREATER_THAN_OR_EQUAL_TO', 'TEXT_GREATER_THAN_OR_EQUAL_TO', 'Greater than or equal to') },
{ operator: '<>', description: this.getOutputText('NOT_EQUAL_TO', 'TEXT_NOT_EQUAL_TO', 'Not equal to') }
];
}
}

/** Get Locale, Translated or a Default Text if first two aren't detected */
Expand Down Expand Up @@ -246,7 +251,7 @@ export class CompoundSliderFilter implements Filter {
this._currentValue = +searchTermInput;

// create the DOM Select dropdown for the Operator
const selectOperatorHtmlString = buildSelectOperatorHtmlString(this.getOptionValues());
const selectOperatorHtmlString = buildSelectOperatorHtmlString(this.getOperatorOptionValues());
this.$selectOperatorElm = $(selectOperatorHtmlString);
this.$filterInputElm = $(this.buildTemplateHtmlString());
const $filterContainerElm = $(`<div class="form-group slider-container search-filter filter-${columnId}"></div>`);
Expand Down
7 changes: 5 additions & 2 deletions packages/common/src/interfaces/columnFilter.interface.ts
@@ -1,4 +1,4 @@
import { FieldType, OperatorString, OperatorType, } from '../enums/index';
import { FieldType, OperatorString, OperatorType, SearchTerm, } from '../enums/index';
import {
CollectionCustomStructure,
CollectionFilterBy,
Expand All @@ -7,8 +7,8 @@ import {
Column,
Filter,
MultipleSelectOption,
OperatorDetail,
} from './index';
import { SearchTerm } from '../enums/searchTerm.type';
import { Observable, Subject } from '../services/rxjsFacade';

export interface ColumnFilter {
Expand All @@ -30,6 +30,9 @@ export interface ColumnFilter {
/** Column Definition */
columnDef?: Column;

/** Optional operator list to override the full list of Compound Operator select dropdown list. */
compoundOperatorList?: OperatorDetail[];

/** Custom Filter */
customFilter?: Filter;

Expand Down
1 change: 1 addition & 0 deletions packages/common/src/interfaces/index.ts
Expand Up @@ -109,6 +109,7 @@ export * from './multiColumnSort.interface';
export * from './multipleSelectOption.interface';
export * from './onEventArgs.interface';
export * from './onValidationErrorResult.interface';
export * from './operatorDetail.interface';
export * from './pagination.interface';
export * from './paginationChangedArgs.interface';
export * from './pagingInfo.interface';
Expand Down
7 changes: 7 additions & 0 deletions packages/common/src/interfaces/operatorDetail.interface.ts
@@ -0,0 +1,7 @@
import { OperatorString, OperatorType } from '../enums/index';

/** Operator with its Description */
export interface OperatorDetail {
operator: OperatorString | OperatorType;
description: string;
}

0 comments on commit 3e8d2cb

Please sign in to comment.