From 56588d1e8851623f657265883cf84f9794d247e2 Mon Sep 17 00:00:00 2001 From: Ghislain B Date: Mon, 28 Sep 2020 09:41:17 -0400 Subject: [PATCH] feat(styling): add description to Compound Filter Operators (#588) - also change Compound Filter styling --- .../modules/angular-slickgrid/constants.ts | 6 ++ .../editors/autoCompleteEditor.ts | 10 +- .../__tests__/compoundDateFilter.spec.ts | 55 +++++++++++ .../__tests__/compoundInputFilter.spec.ts | 96 ++++++++++++++----- .../__tests__/compoundSliderFilter.spec.ts | 94 +++++++++++++++--- .../filters/compoundDateFilter.ts | 56 ++++++----- .../filters/compoundInputFilter.ts | 68 +++++++------ .../filters/compoundSliderFilter.ts | 63 +++++++----- .../filters/filterUtilities.ts | 11 +++ .../models/autocompleteOption.interface.ts | 5 +- .../models/locale.interface.ts | 18 ++++ .../angular-slickgrid/services/utilities.ts | 17 ++++ .../styles/_variables-theme-material.scss | 1 + .../styles/_variables-theme-salesforce.scss | 1 + .../angular-slickgrid/styles/_variables.scss | 5 +- .../styles/slick-plugins.scss | 35 ++++--- .../styles/ui-autocomplete.scss | 18 ++++ src/assets/i18n/en.json | 8 +- src/assets/i18n/fr.json | 10 +- 19 files changed, 437 insertions(+), 140 deletions(-) create mode 100644 src/app/modules/angular-slickgrid/filters/filterUtilities.ts diff --git a/src/app/modules/angular-slickgrid/constants.ts b/src/app/modules/angular-slickgrid/constants.ts index 98d2e8fe8..e2c0b5804 100644 --- a/src/app/modules/angular-slickgrid/constants.ts +++ b/src/app/modules/angular-slickgrid/constants.ts @@ -15,6 +15,7 @@ export class Constants { TEXT_COMMANDS: 'Commands', TEXT_COPY: 'Copy', TEXT_EQUALS: 'Equals', + TEXT_EQUAL_TO: 'Equal to', TEXT_ENDS_WITH: 'Ends With', TEXT_EXPAND_ALL_GROUPS: 'Expand all Groups', TEXT_EXPORT_TO_CSV: 'Export in CSV format', @@ -22,6 +23,8 @@ export class Constants { TEXT_EXPORT_TO_EXCEL: 'Export to Excel', TEXT_FORCE_FIT_COLUMNS: 'Force fit columns', TEXT_FREEZE_COLUMNS: 'Freeze Columns', + TEXT_GREATER_THAN: 'Greater than', + TEXT_GREATER_THAN_OR_EQUAL_TO: 'Greater than or equal to', TEXT_GROUP_BY: 'Group By', TEXT_HIDE_COLUMN: 'Hide Column', TEXT_ITEMS: 'items', @@ -29,6 +32,9 @@ export class Constants { TEXT_OF: 'of', TEXT_OK: 'OK', TEXT_LAST_UPDATE: 'Last Update', + TEXT_LESS_THAN: 'Less than', + TEXT_LESS_THAN_OR_EQUAL_TO: 'Less than or equal to', + TEXT_NOT_EQUAL_TO: 'Not equal to', TEXT_PAGE: 'Page', TEXT_REFRESH_DATASET: 'Refresh Dataset', TEXT_REMOVE_FILTER: 'Remove Filter', diff --git a/src/app/modules/angular-slickgrid/editors/autoCompleteEditor.ts b/src/app/modules/angular-slickgrid/editors/autoCompleteEditor.ts index 26becf308..674f15409 100644 --- a/src/app/modules/angular-slickgrid/editors/autoCompleteEditor.ts +++ b/src/app/modules/angular-slickgrid/editors/autoCompleteEditor.ts @@ -405,7 +405,15 @@ export class AutoCompleteEditor implements Editor { } } - this._$editorElm.on('focus', () => this._$editorElm.select()); + this._$editorElm.on('focus', () => { + this._$editorElm.select(); + + // we could optionally trigger a search to open the AutoComplete search list + if (this.editorOptions.openSearchListOnFocus) { + this._$editorElm.autocomplete('search', this._$editorElm.val()); + } + }); + setTimeout(() => this.focus(), 50); } } diff --git a/src/app/modules/angular-slickgrid/filters/__tests__/compoundDateFilter.spec.ts b/src/app/modules/angular-slickgrid/filters/__tests__/compoundDateFilter.spec.ts index 6ab30790a..fa02b3c6c 100644 --- a/src/app/modules/angular-slickgrid/filters/__tests__/compoundDateFilter.spec.ts +++ b/src/app/modules/angular-slickgrid/filters/__tests__/compoundDateFilter.spec.ts @@ -10,6 +10,10 @@ const containerId = 'demo-container'; // define a
container to simulate the grid container const template = `
`; +function removeExtraSpaces(textS: string) { + return `${textS}`.replace(/\s+/g, ' '); +} + const gridOptionMock = { enableFiltering: true, enableFilterTrimWhiteSpace: true, @@ -54,12 +58,24 @@ describe('CompoundDateFilter', () => { EQUALS: 'Equals', ENDS_WITH: 'Ends With', STARTS_WITH: 'Starts With', + EQUAL_TO: 'Equal to', + LESS_THAN: 'Less than', + LESS_THAN_OR_EQUAL_TO: 'Less than or equal to', + GREATER_THAN: 'Greater than', + GREATER_THAN_OR_EQUAL_TO: 'Greater than or equal to', + NOT_EQUAL_TO: 'Not equal to', }); translate.setTranslation('fr', { CONTAINS: 'Contient', EQUALS: 'Égale', ENDS_WITH: 'Se termine par', STARTS_WITH: 'Commence par', + EQUAL_TO: 'Égal à', + LESS_THAN: 'Plus petit que', + LESS_THAN_OR_EQUAL_TO: 'Plus petit ou égal à', + GREATER_THAN: 'Plus grand que', + GREATER_THAN_OR_EQUAL_TO: 'Plus grand ou égal à', + NOT_EQUAL_TO: 'Non égal à', }); translate.setDefaultLang('en'); translate.use('en'); @@ -334,4 +350,43 @@ describe('CompoundDateFilter', () => { expect(filterInputElm.value).toBe('2000-01-01T05:00:00.000Z'); expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: '<=', searchTerms: ['2000-01-01T05:00:00.000Z'], shouldTriggerQuery: true }); }); + + it('should have default English text with operator dropdown options related to dates', () => { + mockColumn.outputType = null; + filterArguments.searchTerms = ['2000-01-01T05:00:00.000Z']; + + filter.init(filterArguments); + const filterOperatorElm = divContainer.querySelectorAll('.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('<= Less than or equal to'); + expect(removeExtraSpaces(filterOperatorElm[0][4].textContent)).toBe('> Greater than'); + expect(removeExtraSpaces(filterOperatorElm[0][5].textContent)).toBe('>= Greater than or equal to'); + expect(removeExtraSpaces(filterOperatorElm[0][6].textContent)).toBe('<> Not equal to'); + }); + + describe('with French I18N translations', () => { + beforeEach(() => { + gridOptionMock.enableTranslate = true; + translate.use('fr'); + }); + + it('should have French text translated with operator dropdown options related to dates', () => { + mockColumn.outputType = null; + filterArguments.searchTerms = ['2000-01-01T05:00:00.000Z']; + + filter.init(filterArguments); + const filterOperatorElm = divContainer.querySelectorAll('.input-group-prepend.operator select'); + + expect(filterOperatorElm[0][0].title).toBe(''); + expect(removeExtraSpaces(filterOperatorElm[0][1].textContent)).toBe('= Égal à'); + expect(removeExtraSpaces(filterOperatorElm[0][2].textContent)).toBe('< Plus petit que'); + expect(removeExtraSpaces(filterOperatorElm[0][3].textContent)).toBe('<= Plus petit ou égal à'); + expect(removeExtraSpaces(filterOperatorElm[0][4].textContent)).toBe('> Plus grand que'); + expect(removeExtraSpaces(filterOperatorElm[0][5].textContent)).toBe('>= Plus grand ou égal à'); + expect(removeExtraSpaces(filterOperatorElm[0][6].textContent)).toBe('<> Non égal à'); + }); + }); }); diff --git a/src/app/modules/angular-slickgrid/filters/__tests__/compoundInputFilter.spec.ts b/src/app/modules/angular-slickgrid/filters/__tests__/compoundInputFilter.spec.ts index 7d198b359..557c1b07f 100644 --- a/src/app/modules/angular-slickgrid/filters/__tests__/compoundInputFilter.spec.ts +++ b/src/app/modules/angular-slickgrid/filters/__tests__/compoundInputFilter.spec.ts @@ -1,5 +1,6 @@ import { TestBed } from '@angular/core/testing'; import { TranslateModule, TranslateService } from '@ngx-translate/core'; + import { Column, FilterArguments, FieldType, GridOption, OperatorType } from '../../models'; import { Filters } from '..'; import { CompoundInputFilter } from '../compoundInputFilter'; @@ -9,6 +10,10 @@ const containerId = 'demo-container'; // define a
container to simulate the grid container const template = `
`; +function removeExtraSpaces(textS: string) { + return `${textS}`.replace(/\s+/g, ' '); +} + const gridOptionMock = { enableFiltering: true, } as GridOption; @@ -52,12 +57,24 @@ describe('CompoundInputFilter', () => { EQUALS: 'Equals', ENDS_WITH: 'Ends With', STARTS_WITH: 'Starts With', + EQUAL_TO: 'Equal to', + LESS_THAN: 'Less than', + LESS_THAN_OR_EQUAL_TO: 'Less than or equal to', + GREATER_THAN: 'Greater than', + GREATER_THAN_OR_EQUAL_TO: 'Greater than or equal to', + NOT_EQUAL_TO: 'Not equal to', }); translate.setTranslation('fr', { CONTAINS: 'Contient', EQUALS: 'Égale', ENDS_WITH: 'Se termine par', STARTS_WITH: 'Commence par', + EQUAL_TO: 'Égal à', + LESS_THAN: 'Plus petit que', + LESS_THAN_OR_EQUAL_TO: 'Plus petit ou égal à', + GREATER_THAN: 'Plus grand que', + GREATER_THAN_OR_EQUAL_TO: 'Plus grand ou égal à', + NOT_EQUAL_TO: 'Non égal à', }); translate.setDefaultLang('en'); translate.use('en'); @@ -129,12 +146,12 @@ describe('CompoundInputFilter', () => { filter.init(filterArguments); filter.setValues(['9'], OperatorType.greaterThanOrEqual); - const filterSelectElm = divContainer.querySelector('.search-filter.filter-duration select'); + const filterOperatorElm = divContainer.querySelector('.search-filter.filter-duration select'); - filterSelectElm.dispatchEvent(new Event('change')); + filterOperatorElm.dispatchEvent(new Event('change')); expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: '>=', searchTerms: ['9'], shouldTriggerQuery: true }); - expect(filterSelectElm.value).toBe('>='); + expect(filterOperatorElm.value).toBe('>='); }); it('should trigger an operator change event and expect the callback to be called with the searchTerms and operator defined', () => { @@ -143,10 +160,10 @@ describe('CompoundInputFilter', () => { filter.init(filterArguments); filter.setValues(['9']); - const filterSelectElm = divContainer.querySelector('.search-filter.filter-duration select'); + const filterOperatorElm = divContainer.querySelector('.search-filter.filter-duration select'); - filterSelectElm.value = '<='; - filterSelectElm.dispatchEvent(new Event('change')); + filterOperatorElm.value = '<='; + filterOperatorElm.dispatchEvent(new Event('change')); expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: '<=', searchTerms: ['9'], shouldTriggerQuery: true }); }); @@ -223,16 +240,15 @@ describe('CompoundInputFilter', () => { filter.init(filterArguments); const filterInputElm = divContainer.querySelector('.search-filter.filter-duration input'); - const filterSelectElm = divContainer.querySelectorAll('.search-filter.filter-duration select'); + const filterOperatorElm = divContainer.querySelectorAll('.search-filter.filter-duration select'); expect(filterInputElm.value).toBe('9'); - expect(filterSelectElm[0][1].title).toBe('='); - expect(filterSelectElm[0][1].textContent).toBe('='); - expect(filterSelectElm[0][2].textContent).toBe('<'); - expect(filterSelectElm[0][3].textContent).toBe('<='); - expect(filterSelectElm[0][4].textContent).toBe('>'); - expect(filterSelectElm[0][5].textContent).toBe('>='); - expect(filterSelectElm[0][6].textContent).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('<= Less than or equal to'); + expect(removeExtraSpaces(filterOperatorElm[0][4].textContent)).toBe('> Greater than'); + expect(removeExtraSpaces(filterOperatorElm[0][5].textContent)).toBe('>= Greater than or equal to'); + expect(removeExtraSpaces(filterOperatorElm[0][6].textContent)).toBe('<> Not equal to'); }); it('should create the input filter with operator dropdown options related to strings when column definition type is FieldType.string', () => { @@ -241,16 +257,13 @@ describe('CompoundInputFilter', () => { filter.init(filterArguments); const filterInputElm = divContainer.querySelector('.search-filter.filter-duration input'); - const filterSelectElm = divContainer.querySelectorAll('.search-filter.filter-duration select'); + const filterOperatorElm = divContainer.querySelectorAll('.search-filter.filter-duration select'); expect(filterInputElm.value).toBe('xyz'); - expect(filterSelectElm[0][0].title).toBe('Contains'); - expect(filterSelectElm[0][1].title).toBe('Equals'); - expect(filterSelectElm[0][2].title).toBe('Starts With'); - expect(filterSelectElm[0][3].title).toBe('Ends With'); - expect(filterSelectElm[0][1].textContent).toBe('='); - expect(filterSelectElm[0][2].textContent).toBe('a*'); - expect(filterSelectElm[0][3].textContent).toBe('*z'); + expect(removeExtraSpaces(filterOperatorElm[0][0].textContent)).toBe(' Contains'); + expect(removeExtraSpaces(filterOperatorElm[0][1].textContent)).toBe('= Equals'); + expect(removeExtraSpaces(filterOperatorElm[0][2].textContent)).toBe('a* Starts With'); + expect(removeExtraSpaces(filterOperatorElm[0][3].textContent)).toBe('*z Ends With'); }); it('should trigger a callback with the clear filter set when calling the "clear" method', () => { @@ -282,4 +295,43 @@ describe('CompoundInputFilter', () => { expect(filterFilledElms.length).toBe(0); expect(spyCallback).toHaveBeenCalledWith(null, { columnDef: mockColumn, clearFilterTriggered: true, shouldTriggerQuery: false }); }); + + describe('with French I18N translations', () => { + beforeEach(() => { + gridOptionMock.enableTranslate = true; + translate.use('fr'); + }); + + it('should have French text translated with operator dropdown options related to numbers when column definition type is FieldType.number', () => { + mockColumn.type = FieldType.number; + filterArguments.searchTerms = ['9']; + + filter.init(filterArguments); + const filterInputElm = divContainer.querySelector('.search-filter.filter-duration input'); + const filterOperatorElm = divContainer.querySelectorAll('.search-filter.filter-duration select'); + + expect(filterInputElm.value).toBe('9'); + expect(removeExtraSpaces(filterOperatorElm[0][1].textContent)).toBe('= Égal à'); + expect(removeExtraSpaces(filterOperatorElm[0][2].textContent)).toBe('< Plus petit que'); + expect(removeExtraSpaces(filterOperatorElm[0][3].textContent)).toBe('<= Plus petit ou égal à'); + expect(removeExtraSpaces(filterOperatorElm[0][4].textContent)).toBe('> Plus grand que'); + expect(removeExtraSpaces(filterOperatorElm[0][5].textContent)).toBe('>= Plus grand ou égal à'); + expect(removeExtraSpaces(filterOperatorElm[0][6].textContent)).toBe('<> Non égal à'); + }); + + it('should have French text translated with operator dropdown options related to strings when column definition type is FieldType.string', () => { + mockColumn.type = FieldType.string; + filterArguments.searchTerms = ['xyz']; + + filter.init(filterArguments); + const filterInputElm = divContainer.querySelector('.search-filter.filter-duration input'); + const filterOperatorElm = divContainer.querySelectorAll('.search-filter.filter-duration select'); + + expect(filterInputElm.value).toBe('xyz'); + expect(removeExtraSpaces(filterOperatorElm[0][0].textContent)).toBe(' Contient'); + expect(removeExtraSpaces(filterOperatorElm[0][1].textContent)).toBe('= Égale'); + expect(removeExtraSpaces(filterOperatorElm[0][2].textContent)).toBe('a* Commence par'); + expect(removeExtraSpaces(filterOperatorElm[0][3].textContent)).toBe('*z Se termine par'); + }); + }); }); diff --git a/src/app/modules/angular-slickgrid/filters/__tests__/compoundSliderFilter.spec.ts b/src/app/modules/angular-slickgrid/filters/__tests__/compoundSliderFilter.spec.ts index 5ed57df9a..c2f21748a 100644 --- a/src/app/modules/angular-slickgrid/filters/__tests__/compoundSliderFilter.spec.ts +++ b/src/app/modules/angular-slickgrid/filters/__tests__/compoundSliderFilter.spec.ts @@ -1,4 +1,7 @@ -import { GridOption, FilterArguments, Column, OperatorType } from '../../models'; +import { TestBed } from '@angular/core/testing'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; + +import { Column, FieldType, FilterArguments, GridOption, OperatorType } from '../../models'; import { Filters } from '..'; import { CompoundSliderFilter } from '../compoundSliderFilter'; @@ -7,6 +10,10 @@ const containerId = 'demo-container'; // define a
container to simulate the grid container const template = `
`; +function removeExtraSpaces(textS: string) { + return `${textS}`.replace(/\s+/g, ' '); +} + const gridOptionMock = { enableFiltering: true, enableFilterTrimWhiteSpace: true, @@ -25,6 +32,7 @@ describe('CompoundSliderFilter', () => { let filterArguments: FilterArguments; let spyGetHeaderRow; let mockColumn: Column; + let translate: TranslateService; beforeEach(() => { divContainer = document.createElement('div'); @@ -39,7 +47,40 @@ describe('CompoundSliderFilter', () => { callback: jest.fn() }; - filter = new CompoundSliderFilter(); + TestBed.configureTestingModule({ + providers: [], + imports: [TranslateModule.forRoot()] + }); + translate = TestBed.get(TranslateService); + + translate.setTranslation('en', { + CONTAINS: 'Contains', + EQUALS: 'Equals', + ENDS_WITH: 'Ends With', + STARTS_WITH: 'Starts With', + EQUAL_TO: 'Equal to', + LESS_THAN: 'Less than', + LESS_THAN_OR_EQUAL_TO: 'Less than or equal to', + GREATER_THAN: 'Greater than', + GREATER_THAN_OR_EQUAL_TO: 'Greater than or equal to', + NOT_EQUAL_TO: 'Not equal to', + }); + translate.setTranslation('fr', { + CONTAINS: 'Contient', + EQUALS: 'Égale', + ENDS_WITH: 'Se termine par', + STARTS_WITH: 'Commence par', + EQUAL_TO: 'Égal à', + LESS_THAN: 'Plus petit que', + LESS_THAN_OR_EQUAL_TO: 'Plus petit ou égal à', + GREATER_THAN: 'Plus grand que', + GREATER_THAN_OR_EQUAL_TO: 'Plus grand ou égal à', + NOT_EQUAL_TO: 'Non égal à', + }); + translate.setDefaultLang('en'); + translate.use('en'); + + filter = new CompoundSliderFilter(translate); }); afterEach(() => { @@ -89,10 +130,10 @@ describe('CompoundSliderFilter', () => { filter.init(filterArguments); filter.setValues(9); - const filterSelectElm = divContainer.querySelector('.search-filter.filter-duration select'); + const filterOperatorElm = divContainer.querySelector('.search-filter.filter-duration select'); - filterSelectElm.value = '<='; - filterSelectElm.dispatchEvent(new Event('change')); + filterOperatorElm.value = '<='; + filterOperatorElm.dispatchEvent(new Event('change')); expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: '<=', searchTerms: ['9'], shouldTriggerQuery: true }); }); @@ -103,8 +144,8 @@ describe('CompoundSliderFilter', () => { filter.init(filterArguments); filter.setValues(['9'], OperatorType.greaterThanOrEqual); - const filterSelectElm = divContainer.querySelector('.search-filter.filter-duration select'); - filterSelectElm.dispatchEvent(new Event('change')); + const filterOperatorElm = divContainer.querySelector('.search-filter.filter-duration select'); + filterOperatorElm.dispatchEvent(new Event('change')); expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: '>=', searchTerms: ['9'], shouldTriggerQuery: true }); }); @@ -220,15 +261,38 @@ describe('CompoundSliderFilter', () => { filter.init(filterArguments); const filterInputElm = divContainer.querySelector('.input-group.search-filter.filter-duration input'); - const filterSelectElm = divContainer.querySelectorAll('.search-filter.filter-duration select'); + const filterOperatorElm = divContainer.querySelectorAll('.search-filter.filter-duration select'); expect(filterInputElm.value).toBe('9'); - expect(filterSelectElm[0][1].title).toBe('='); - expect(filterSelectElm[0][1].textContent).toBe('='); - expect(filterSelectElm[0][2].textContent).toBe('<'); - expect(filterSelectElm[0][3].textContent).toBe('<='); - expect(filterSelectElm[0][4].textContent).toBe('>'); - expect(filterSelectElm[0][5].textContent).toBe('>='); - expect(filterSelectElm[0][6].textContent).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('<= Less than or equal to'); + expect(removeExtraSpaces(filterOperatorElm[0][4].textContent)).toBe('> Greater than'); + expect(removeExtraSpaces(filterOperatorElm[0][5].textContent)).toBe('>= Greater than or equal to'); + expect(removeExtraSpaces(filterOperatorElm[0][6].textContent)).toBe('<> Not equal to'); + }); + + describe('with French I18N translations', () => { + beforeEach(() => { + gridOptionMock.enableTranslate = true; + translate.use('fr'); + }); + + it('should have French text translated with operator dropdown options related to numbers when column definition type is FieldType.number', () => { + mockColumn.type = FieldType.number; + filterArguments.searchTerms = [9]; + + filter.init(filterArguments); + const filterInputElm = divContainer.querySelector('.input-group.search-filter.filter-duration input'); + const filterOperatorElm = divContainer.querySelectorAll('.search-filter.filter-duration select'); + + expect(filterInputElm.value).toBe('9'); + expect(removeExtraSpaces(filterOperatorElm[0][1].textContent)).toBe('= Égal à'); + expect(removeExtraSpaces(filterOperatorElm[0][2].textContent)).toBe('< Plus petit que'); + expect(removeExtraSpaces(filterOperatorElm[0][3].textContent)).toBe('<= Plus petit ou égal à'); + expect(removeExtraSpaces(filterOperatorElm[0][4].textContent)).toBe('> Plus grand que'); + expect(removeExtraSpaces(filterOperatorElm[0][5].textContent)).toBe('>= Plus grand ou égal à'); + expect(removeExtraSpaces(filterOperatorElm[0][6].textContent)).toBe('<> Non égal à'); + }); }); }); diff --git a/src/app/modules/angular-slickgrid/filters/compoundDateFilter.ts b/src/app/modules/angular-slickgrid/filters/compoundDateFilter.ts index d2aca5747..eb28e1b83 100644 --- a/src/app/modules/angular-slickgrid/filters/compoundDateFilter.ts +++ b/src/app/modules/angular-slickgrid/filters/compoundDateFilter.ts @@ -3,6 +3,7 @@ import { TranslateService } from '@ngx-translate/core'; import Flatpickr from 'flatpickr'; import { BaseOptions as FlatpickrBaseOptions } from 'flatpickr/dist/types/options'; +import { Constants } from '../constants'; import { Column, ColumnFilter, @@ -12,11 +13,13 @@ import { FieldType, FlatpickrOption, GridOption, + Locale, OperatorString, OperatorType, SearchTerm, } from './../models/index'; -import { mapFlatpickrDateFormatWithFieldType, mapOperatorToShorthandDesignation } from '../services/utilities'; +import { buildSelectOperatorHtmlString } from './filterUtilities'; +import { getTranslationPrefix, mapFlatpickrDateFormatWithFieldType, mapOperatorToShorthandDesignation } from '../services/utilities'; // use Flatpickr from import or 'require', whichever works first declare function require(name: string): any; @@ -68,6 +71,11 @@ export class CompoundDateFilter implements Filter { return this._flatpickrOptions || {}; } + /** Getter for the single Locale texts provided by the user in main file or else use default English locales via the Constants */ + get locales(): Locale { + return this.gridOptions.locales || Constants.locales; + } + /** Getter for the Filter Operator */ get operator(): OperatorType | OperatorString { return this._operator || this.columnFilter.operator || this.defaultOperator; @@ -188,17 +196,17 @@ export class CompoundDateFilter implements Filter { wrap: true, closeOnSelect: true, locale: (currentLocale !== 'en') ? this.loadFlatpickrLocale(currentLocale) : 'en', - onChange: (selectedDates: Date[] | Date, dateStr: string, instance: any) => { + onChange: (selectedDates: Date[] | Date, dateStr: string) => { this._currentValue = dateStr; this._currentDate = Array.isArray(selectedDates) && selectedDates[0]; // when using the time picker, we can simulate a keyup event to avoid multiple backend request // since backend request are only executed after user start typing, changing the time should be treated the same way + let customEvent: CustomEvent | undefined; if (pickerOptions.enableTime) { - this.onTriggerEvent(new CustomEvent('keyup')); - } else { - this.onTriggerEvent(undefined); + customEvent = new CustomEvent('keyup'); } + this.onTriggerEvent(customEvent); } }; @@ -219,28 +227,27 @@ export class CompoundDateFilter implements Filter { return $filterInputElm; } - private buildSelectOperatorHtmlString() { - const optionValues = this.getOptionValues(); - let optionValueString = ''; - optionValues.forEach((option) => { - optionValueString += ``; - }); - - return ``; - } - private getOptionValues(): { operator: OperatorString, description: string }[] { return [ - { operator: '' as OperatorString, description: '' }, - { operator: '=' as OperatorString, description: '=' }, - { operator: '<' as OperatorString, description: '<' }, - { operator: '<=' as OperatorString, description: '<=' }, - { operator: '>' as OperatorString, description: '>' }, - { operator: '>=' as OperatorString, description: '>=' }, - { operator: '<>' as OperatorString, description: '<>' } + { 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 */ + private getOutputText(translationKey: string, localeText: string, defaultText: string): string { + if (this.gridOptions && this.gridOptions.enableTranslate && this.translate && this.translate.instant) { + const translationPrefix = getTranslationPrefix(this.gridOptions); + return this.translate.instant(`${translationPrefix}${translationKey}`); + } + return this.locales && this.locales[localeText] || defaultText; + } + /** * Create the DOM element */ @@ -250,7 +257,8 @@ export class CompoundDateFilter implements Filter { $($headerElm).empty(); // create the DOM Select dropdown for the Operator - this.$selectOperatorElm = $(this.buildSelectOperatorHtmlString()); + const selectOperatorHtmlString = buildSelectOperatorHtmlString(this.getOptionValues()); + this.$selectOperatorElm = $(selectOperatorHtmlString); this.$filterInputElm = this.buildDatePickerInput(searchTerm); const $filterContainerElm = $(`
`); const $containerInputGroup = $(`
`); @@ -317,7 +325,7 @@ export class CompoundDateFilter implements Filter { this.callback(e, { columnDef: this.columnDef, clearFilterTriggered: this._clearFilterTriggered, shouldTriggerQuery: this._shouldTriggerQuery }); this.$filterElm.removeClass('filled'); } else { - const selectedOperator = this.$selectOperatorElm.find('option:selected').text(); + const selectedOperator = this.$selectOperatorElm.find('option:selected').val(); (this._currentValue) ? this.$filterElm.addClass('filled') : this.$filterElm.removeClass('filled'); this.callback(e, { columnDef: this.columnDef, searchTerms: (this._currentValue ? [this._currentValue] : null), operator: selectedOperator || '', shouldTriggerQuery: this._shouldTriggerQuery }); } diff --git a/src/app/modules/angular-slickgrid/filters/compoundInputFilter.ts b/src/app/modules/angular-slickgrid/filters/compoundInputFilter.ts index 54b4545fb..c3792f827 100644 --- a/src/app/modules/angular-slickgrid/filters/compoundInputFilter.ts +++ b/src/app/modules/angular-slickgrid/filters/compoundInputFilter.ts @@ -14,6 +14,7 @@ import { SearchTerm, } from './../models/index'; import { Constants } from './../constants'; +import { buildSelectOperatorHtmlString } from './filterUtilities'; import { getTranslationPrefix, mapOperatorToShorthandDesignation } from '../services/utilities'; // using external non-typed js libraries @@ -35,11 +36,6 @@ export class CompoundInputFilter implements Filter { constructor(protected translate: TranslateService) { } - /** Getter for the Grid Options pulled through the Grid Object */ - private get gridOptions(): GridOption { - return (this.grid && this.grid.getOptions) ? this.grid.getOptions() : {}; - } - /** Getter for the Column Filter */ get columnFilter(): ColumnFilter { return this.columnDef && this.columnDef.filter || {}; @@ -50,6 +46,11 @@ export class CompoundInputFilter implements Filter { return OperatorType.empty; } + /** Getter for the Grid Options pulled through the Grid Object */ + private get gridOptions(): GridOption { + return (this.grid && this.grid.getOptions) ? this.grid.getOptions() : {}; + } + /** Getter of input type (text, number, password) */ get inputType() { return this._inputType; @@ -60,6 +61,11 @@ export class CompoundInputFilter implements Filter { this._inputType = type; } + /** Getter for the single Locale texts provided by the user in main file or else use default English locales via the Constants */ + get locales(): Locale { + return this.gridOptions.locales || Constants.locales; + } + /** Getter of the Operator to use when doing the filter comparing */ get operator(): OperatorType | OperatorString { return this._operator || this.defaultOperator; @@ -84,9 +90,6 @@ export class CompoundInputFilter implements Filter { this.operator = args.operator; this.searchTerms = (args.hasOwnProperty('searchTerms') ? args.searchTerms : []) || []; - // get locales provided by user in forRoot or else use default English locales via the Constants - this._locales = this.gridOptions && this.gridOptions.locales || Constants.locales; - // filter input can only have 1 search term, so we will use the 1st array index if it exist const searchTerm = (Array.isArray(this.searchTerms) && this.searchTerms.length >= 0) ? this.searchTerms[0] : ''; @@ -155,18 +158,7 @@ export class CompoundInputFilter implements Filter { return ``; } - private buildSelectOperatorHtmlString() { - const optionValues = this.getOptionValues(); - let optionValueString = ''; - optionValues.forEach((option) => { - optionValueString += ``; - }); - - return ``; - } - private getOptionValues(): { operator: OperatorString, description: string }[] { - const translationPrefix = getTranslationPrefix(this.gridOptions); const type = (this.columnDef.type && this.columnDef.type) ? this.columnDef.type : FieldType.string; let optionValues = []; @@ -176,25 +168,21 @@ export class CompoundInputFilter implements Filter { case FieldType.readonly: case FieldType.password: optionValues = [ - { operator: '' as OperatorString, description: this.translate && this.translate.currentLang && this.translate.instant && this.translate.instant(`${translationPrefix}CONTAINS`) || this._locales && this._locales.TEXT_CONTAINS }, - { operator: '=' as OperatorString, description: this.translate && this.translate.currentLang && this.translate.instant && this.translate.instant(`${translationPrefix}EQUALS`) || this._locales && this._locales.TEXT_EQUALS }, - { operator: 'a*' as OperatorString, description: this.translate && this.translate.currentLang && this.translate.instant && this.translate.instant(`${translationPrefix}STARTS_WITH`) || this._locales && this._locales.TEXT_STARTS_WITH }, - { operator: '*z' as OperatorString, description: this.translate && this.translate.currentLang && this.translate.instant && this.translate.instant(`${translationPrefix}ENDS_WITH`) || this._locales && this._locales.TEXT_ENDS_WITH }, - /* - { operator: 'IN' as OperatorString, description: this.translate && this.translate.currentLang && this.translate.instant && this.translate.instant(`${translationPrefix}IN_COLLECTION_SEPERATED_BY_COMMA`) }, - { operator: 'NIN' as OperatorString, description: this.translate && this.translate.currentLang && this.translate.instant && this.translate.instant(`${translationPrefix}NOT_IN_COLLECTION_SEPERATED_BY_COMMA`) }, - */ + { operator: '' as OperatorString, description: this.getOutputText('CONTAINS', 'TEXT_CONTAINS', 'Contains') }, + { operator: '=' as OperatorString, description: this.getOutputText('EQUALS', 'TEXT_EQUALS', 'Equals') }, + { 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: '=' }, - { operator: '<' as OperatorString, description: '<' }, - { operator: '<=' as OperatorString, description: '<=' }, - { operator: '>' as OperatorString, description: '>' }, - { operator: '>=' as OperatorString, description: '>=' }, - { 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; } @@ -202,6 +190,15 @@ export class CompoundInputFilter implements Filter { return optionValues; } + /** Get Locale, Translated or a Default Text if first two aren't detected */ + private getOutputText(translationKey: string, localeText: string, defaultText: string): string { + if (this.gridOptions && this.gridOptions.enableTranslate && this.translate && this.translate.instant) { + const translationPrefix = getTranslationPrefix(this.gridOptions); + return this.translate.instant(`${translationPrefix}${translationKey}`); + } + return this.locales && this.locales[localeText] || defaultText; + } + /** * Create the DOM element */ @@ -211,7 +208,8 @@ export class CompoundInputFilter implements Filter { $($headerElm).empty(); // create the DOM Select dropdown for the Operator - this.$selectOperatorElm = $(this.buildSelectOperatorHtmlString()); + const selectOperatorHtmlString = buildSelectOperatorHtmlString(this.getOptionValues()); + this.$selectOperatorElm = $(selectOperatorHtmlString); this.$filterInputElm = $(this.buildInputHtmlString()); const $filterContainerElm = $(`
`); const $containerInputGroup = $(`
`); @@ -258,7 +256,7 @@ export class CompoundInputFilter implements Filter { this.callback(e, { columnDef: this.columnDef, clearFilterTriggered: this._clearFilterTriggered, shouldTriggerQuery: this._shouldTriggerQuery }); this.$filterElm.removeClass('filled'); } else { - const selectedOperator = this.$selectOperatorElm.find('option:selected').text(); + const selectedOperator = this.$selectOperatorElm.find('option:selected').val(); let value = this.$filterInputElm.val(); const enableWhiteSpaceTrim = this.gridOptions.enableFilterTrimWhiteSpace || this.columnFilter.enableTrimWhiteSpace; if (typeof value === 'string' && enableWhiteSpaceTrim) { diff --git a/src/app/modules/angular-slickgrid/filters/compoundSliderFilter.ts b/src/app/modules/angular-slickgrid/filters/compoundSliderFilter.ts index 736f6597c..b9b2464e3 100644 --- a/src/app/modules/angular-slickgrid/filters/compoundSliderFilter.ts +++ b/src/app/modules/angular-slickgrid/filters/compoundSliderFilter.ts @@ -1,14 +1,20 @@ +import { TranslateService } from '@ngx-translate/core'; + import { Column, ColumnFilter, Filter, FilterArguments, FilterCallback, + GridOption, + Locale, OperatorString, OperatorType, - SearchTerm + SearchTerm, } from './../models/index'; -import { mapOperatorToShorthandDesignation } from '../services/utilities'; +import { Constants } from '../constants'; +import { buildSelectOperatorHtmlString } from './filterUtilities'; +import { getTranslationPrefix, mapOperatorToShorthandDesignation } from '../services/utilities'; // using external non-typed js libraries declare const $: any; @@ -33,7 +39,7 @@ export class CompoundSliderFilter implements Filter { columnDef: Column; callback: FilterCallback; - constructor() { } + constructor(protected translate: TranslateService) { } /** Getter to know what would be the default operator when none is specified */ get defaultOperator(): OperatorType | OperatorString { @@ -50,10 +56,22 @@ export class CompoundSliderFilter implements Filter { return this.columnDef && this.columnDef.filter; } + /** Getter for the Grid Options pulled through the Grid Object */ + private get gridOptions(): GridOption { + return (this.grid && this.grid.getOptions) ? this.grid.getOptions() : {}; + } + + /** Getter for the single Locale texts provided by the user in main file or else use default English locales via the Constants */ + get locales(): Locale { + return this.gridOptions.locales || Constants.locales; + } + + /** Getter for the Filter Operator */ get operator(): OperatorType | OperatorString { return this._operator || this.defaultOperator; } + /** Setter for the Filter Operator */ set operator(op: OperatorType | OperatorString) { this._operator = op; } @@ -183,30 +201,28 @@ export class CompoundSliderFilter implements Filter { return `
${defaultValue}
`; } - /** Build HTML Template select dropdown (operator) */ - private buildSelectOperatorHtmlString() { - const optionValues = this.getOptionValues(); - let optionValueString = ''; - optionValues.forEach((option) => { - optionValueString += ``; - }); - - return ``; - } - /** Get the available operator option values */ private getOptionValues(): { operator: OperatorString, description: string }[] { return [ - { operator: '' as OperatorString, description: '' }, - { operator: '=' as OperatorString, description: '=' }, - { operator: '<' as OperatorString, description: '<' }, - { operator: '<=' as OperatorString, description: '<=' }, - { operator: '>' as OperatorString, description: '>' }, - { operator: '>=' as OperatorString, description: '>=' }, - { operator: '<>' as OperatorString, description: '<>' } + { 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 */ + private getOutputText(translationKey: string, localeText: string, defaultText: string): string { + if (this.gridOptions && this.gridOptions.enableTranslate && this.translate && this.translate.instant) { + const translationPrefix = getTranslationPrefix(this.gridOptions); + return this.translate.instant(`${translationPrefix}${translationKey}`); + } + return this.locales && this.locales[localeText] || defaultText; + } + /** * Create the DOM element */ @@ -227,7 +243,8 @@ export class CompoundSliderFilter implements Filter { this._currentValue = +searchTermInput; // create the DOM Select dropdown for the Operator - this.$selectOperatorElm = $(this.buildSelectOperatorHtmlString()); + const selectOperatorHtmlString = buildSelectOperatorHtmlString(this.getOptionValues()); + this.$selectOperatorElm = $(selectOperatorHtmlString); this.$filterInputElm = $(this.buildTemplateHtmlString()); const $filterContainerElm = $(`
`); this.$containerInputGroupElm = $(`
`); @@ -284,7 +301,7 @@ export class CompoundSliderFilter implements Filter { this.callback(e, { columnDef: this.columnDef, clearFilterTriggered: this._clearFilterTriggered, shouldTriggerQuery: this._shouldTriggerQuery }); } else { this.$filterElm.addClass('filled'); - const selectedOperator = this.$selectOperatorElm.find('option:selected').text(); + const selectedOperator = this.$selectOperatorElm.find('option:selected').val(); this.callback(e, { columnDef: this.columnDef, searchTerms: (value ? [value || '0'] : null), operator: selectedOperator || '', shouldTriggerQuery: this._shouldTriggerQuery }); } // reset both flags for next use diff --git a/src/app/modules/angular-slickgrid/filters/filterUtilities.ts b/src/app/modules/angular-slickgrid/filters/filterUtilities.ts new file mode 100644 index 000000000..fd97a30a7 --- /dev/null +++ b/src/app/modules/angular-slickgrid/filters/filterUtilities.ts @@ -0,0 +1,11 @@ +import { OperatorString } from '../models/operatorString'; +import { htmlEncodedStringWithPadding } from '../services/utilities'; + +export function buildSelectOperatorHtmlString(optionValues: Array<{ operator: OperatorString, description: string }>) { + let optionValueString = ''; + optionValues.forEach(option => { + optionValueString += ``; + }); + + return ``; +} diff --git a/src/app/modules/angular-slickgrid/models/autocompleteOption.interface.ts b/src/app/modules/angular-slickgrid/models/autocompleteOption.interface.ts index 88ed1dbf5..ca99e4fd1 100644 --- a/src/app/modules/angular-slickgrid/models/autocompleteOption.interface.ts +++ b/src/app/modules/angular-slickgrid/models/autocompleteOption.interface.ts @@ -35,7 +35,10 @@ export interface AutocompleteOption { /** defaults to false, force the user to start typing a value in the search input */ forceUserInput?: boolean; - /** defaults to false, will open the search list (should really only be used with a defined collection list) */ + /** + * Defaults to false, will open the search list (should really only be used with a defined collection list). + * Also note that if you wish to display even when the autoComplete is an empty string, you will need to adjust the "minLength" to 0. + */ openSearchListOnFocus?: boolean; /** diff --git a/src/app/modules/angular-slickgrid/models/locale.interface.ts b/src/app/modules/angular-slickgrid/models/locale.interface.ts index 544b9e365..ddcca81b1 100644 --- a/src/app/modules/angular-slickgrid/models/locale.interface.ts +++ b/src/app/modules/angular-slickgrid/models/locale.interface.ts @@ -38,6 +38,9 @@ export interface Locale { /** Text "Equals" shown in Compound Editors/Filters as an Operator */ TEXT_EQUALS: string; + /** Text "Equal to" shown in Compound Editors/Filters as an Operator */ + TEXT_EQUAL_TO: string; + /** Text "Expand all Grouping" displayed in the Context Menu when Grouping is enabled */ TEXT_EXPAND_ALL_GROUPS: string; @@ -59,6 +62,12 @@ export interface Locale { /** Text "Freeze Columns" shown in Header Menu (when enabled) */ TEXT_FREEZE_COLUMNS?: string; + /** Text "Greater than" shown in Compound Editors/Filters as an Operator */ + TEXT_GREATER_THAN: string; + + /** Text "Greater than or equal to" shown in Compound Editors/Filters as an Operator */ + TEXT_GREATER_THAN_OR_EQUAL_TO: string; + /** Text "Group by" shown in Export when using Grouping (when enabled) */ TEXT_GROUP_BY: string; @@ -74,6 +83,15 @@ export interface Locale { /** Text "Last Update" displayed in the Footer (when enabled) */ TEXT_LAST_UPDATE?: string; + /** Text "Less than" shown in Compound Editors/Filters as an Operator */ + TEXT_LESS_THAN: string; + + /** Text "Less than or equal to" shown in Compound Editors/Filters as an Operator */ + TEXT_LESS_THAN_OR_EQUAL_TO: string; + + /** Text "Not equal to" shown in Compound Editors/Filters as an Operator */ + TEXT_NOT_EQUAL_TO: string; + /** Text "of" displayed in the Pagination (when enabled) */ TEXT_OF?: string; diff --git a/src/app/modules/angular-slickgrid/services/utilities.ts b/src/app/modules/angular-slickgrid/services/utilities.ts index c033551bb..183e996f8 100644 --- a/src/app/modules/angular-slickgrid/services/utilities.ts +++ b/src/app/modules/angular-slickgrid/services/utilities.ts @@ -347,6 +347,23 @@ export function findOrDefault(array: any[], logic: (item: any) => boole return array.find(logic) || defaultVal; } +/** + * Encode string to html special char and add html space padding defined + * @param {string} inputStr - input string + * @param {number} paddingLength - padding to add + */ +export function htmlEncodedStringWithPadding(inputStr: string, paddingLength: number): string { + const inputStrLn = inputStr.length; + let outputStr = htmlEncode(inputStr); + + if (inputStrLn < paddingLength) { + for (let i = inputStrLn; i < paddingLength; i++) { + outputStr += ` `; + } + } + return outputStr; +} + /** * Take a number (or a string) and display it as a formatted decimal string with defined minimum and maximum decimals * @param input diff --git a/src/app/modules/angular-slickgrid/styles/_variables-theme-material.scss b/src/app/modules/angular-slickgrid/styles/_variables-theme-material.scss index 403b272c3..fe81b9a09 100644 --- a/src/app/modules/angular-slickgrid/styles/_variables-theme-material.scss +++ b/src/app/modules/angular-slickgrid/styles/_variables-theme-material.scss @@ -104,6 +104,7 @@ $autocomplete-loading-icon-width: 22px !default; $autocomplete-loading-icon-margin-left: -26px !default; $autocomplete-loading-icon-line-height: 0px !default; $autocomplete-loading-icon-vertical-align: sub !default; +$compound-filter-operator-select-border: 1px solid #{lighten($primary-color, 10%)} !default; $multiselect-icon-arrow-font-size: 16px !default; $multiselect-icon-color: $primary-color !default; $multiselect-icon-height: 16px !default; diff --git a/src/app/modules/angular-slickgrid/styles/_variables-theme-salesforce.scss b/src/app/modules/angular-slickgrid/styles/_variables-theme-salesforce.scss index 924811154..8a7dac3ca 100644 --- a/src/app/modules/angular-slickgrid/styles/_variables-theme-salesforce.scss +++ b/src/app/modules/angular-slickgrid/styles/_variables-theme-salesforce.scss @@ -118,6 +118,7 @@ $autocomplete-loading-icon-width: 22px !default; $autocomplete-loading-icon-margin-left: -26px !default; $autocomplete-loading-icon-line-height: 0px !default; $autocomplete-loading-icon-vertical-align: sub !default; +$compound-filter-operator-select-border: 1px solid #6cb6ff !default; $multiselect-icon-arrow-font-size: $icon-font-size - 4px !default; $multiselect-icon-checked-color: $highlight-color !default; $multiselect-icon-border: 1px solid #d6d4d4 !default; diff --git a/src/app/modules/angular-slickgrid/styles/_variables.scss b/src/app/modules/angular-slickgrid/styles/_variables.scss index b1e443d52..3f3893963 100644 --- a/src/app/modules/angular-slickgrid/styles/_variables.scss +++ b/src/app/modules/angular-slickgrid/styles/_variables.scss @@ -533,7 +533,10 @@ $slider-editor-focus-box-shadow: $editor-focus-box-shadow !default; /* Compound Filters */ - $compound-filter-bgcolor: #e4eacf !default; + $compound-filter-operator-select-font-family: Consolas, "Lucida Console" !default; // use a monospace font so the operator descriptions are all aligned + $compound-filter-operator-select-font-size: 14px !important !default; + $compound-filter-operator-select-border: 1px solid #{lighten($primary-color, 15%)} !default; + $compound-filter-bgcolor: #ffffff !default; $compound-filter-operator-border-radius: 4px 0 0 4px !default; $compound-filter-border-radius: 0 4px 4px 0 !default; $compound-filter-text-weight: bold !default; diff --git a/src/app/modules/angular-slickgrid/styles/slick-plugins.scss b/src/app/modules/angular-slickgrid/styles/slick-plugins.scss index a22d2b55c..5e52410c3 100644 --- a/src/app/modules/angular-slickgrid/styles/slick-plugins.scss +++ b/src/app/modules/angular-slickgrid/styles/slick-plugins.scss @@ -700,29 +700,33 @@ min-width: 25px; border: none; - select.form-control { - cursor: pointer; - -moz-appearance: none; - -webkit-appearance:none; - } - select.form-control::-ms-expand { - display: none; - } - select.form-control { - .empty { - color: #c0c0c0; - } - } - .form-control { border-radius: $compound-filter-operator-border-radius; - border-right: none; + // border-right: none; padding: $compound-filter-text-padding !important; font-size: $compound-filter-text-font-size; color: $compound-filter-text-color; font-weight: $compound-filter-text-weight; background-color: $compound-filter-bgcolor; } + + select { + font-family: $compound-filter-operator-select-font-family; + font-size: $compound-filter-operator-select-font-size; + border: $compound-filter-operator-select-border; + + &.form-control { + cursor: pointer; + -moz-appearance: none; + -webkit-appearance:none; + &:-ms-expand { + display: none; + } + .empty { + color: #c0c0c0; + } + } + } } .search-filter .operator-char3.input-group-addon { min-width: 30px; @@ -769,6 +773,7 @@ input.search-filter { background-color: $flatpickr-bgcolor; } } + .form-control[readonly], .flatpickr.form-control[readonly] { background-color: $flatpickr-bgcolor; } diff --git a/src/app/modules/angular-slickgrid/styles/ui-autocomplete.scss b/src/app/modules/angular-slickgrid/styles/ui-autocomplete.scss index cdcec6171..3e94e7e8a 100644 --- a/src/app/modules/angular-slickgrid/styles/ui-autocomplete.scss +++ b/src/app/modules/angular-slickgrid/styles/ui-autocomplete.scss @@ -7,7 +7,24 @@ .autocomplete-container { display: flex; } +.ui-widget-content { + background: none; +} +.ui-autocomplete { + .ui-menu-item { + color: $autocomplete-text-color; + .ui-state-active { + color: $autocomplete-text-color; + &:hover { + margin: 0; + border: 0; + color: $autocomplete-text-color; + } + } + } +} .ui-autocomplete { + background: none; position: absolute; z-index: $autocomplete-z-index; padding: 0; @@ -33,6 +50,7 @@ font-weight: normal; line-height: 1.42857143; white-space: nowrap; + list-style-image: none; } } } diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index ededaa3f1..470077063 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -12,21 +12,27 @@ "COPY": "Copy", "ENDS_WITH": "Ends With", "EQUALS": "Equals", + "EQUAL_TO": "Equal to", "EXPAND_ALL_GROUPS": "Expand all Groups", "EXPORT_TO_CSV": "Export in CSV format", "EXPORT_TO_EXCEL": "Export to Excel", "EXPORT_TO_TAB_DELIMITED": "Export in Text format (Tab delimited)", "EXPORT_TO_TEXT_FORMAT": "Export in Text format", - "FREEZE_COLUMNS": "Freeze Columns", "FROM_TO_OF_TOTAL_ITEMS": "{{from}}-{{to}} of {{totalItems}} items", "FORCE_FIT_COLUMNS": "Force fit columns", + "FREEZE_COLUMNS": "Freeze Columns", "INVALID_FLOAT": "The number must be valid and have a maximum of {{maxDecimal}} decimals.", + "GREATER_THAN": "Greater than", + "GREATER_THAN_OR_EQUAL_TO": "Greater than or equal to", "GROUP_BY": "Group by", "HIDE_COLUMN": "Hide Column", "IN_COLLECTION_SEPERATED_BY_COMMA": "Search items in a collection, must be separated by a comma (a,b)", "ITEMS": "items", "ITEMS_PER_PAGE": "items per page", "LAST_UPDATE": "Last Update", + "LESS_THAN": "Less than", + "LESS_THAN_OR_EQUAL_TO": "Less than or equal to", + "NOT_EQUAL_TO": "Not equal to", "NOT_IN_COLLECTION_SEPERATED_BY_COMMA": "Search items not in a collection, must be separated by a comma (a,b)", "OF": "of", "OK": "OK", diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index 8ad64d275..d87924d12 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -12,14 +12,17 @@ "COPY": "Copier", "ENDS_WITH": "Se termine par", "EQUALS": "Égale", + "EQUAL_TO": "Égal à", "EXPAND_ALL_GROUPS": "Étendre tous les groupes", "EXPORT_TO_CSV": "Exporter en format CSV", "EXPORT_TO_EXCEL": "Exporter vers Excel", "EXPORT_TO_TAB_DELIMITED": "Exporter en format texte (délimité par tabulation)", "EXPORT_TO_TEXT_FORMAT": "Exporter en format texte", - "FREEZE_COLUMNS": "Geler les colonnes", "FROM_TO_OF_TOTAL_ITEMS": "{{from}}-{{to}} de {{totalItems}} éléments", "FORCE_FIT_COLUMNS": "Ajustement forcé des colonnes", + "FREEZE_COLUMNS": "Geler les colonnes", + "GREATER_THAN": "Plus grand que", + "GREATER_THAN_OR_EQUAL_TO": "Plus grand ou égal à", "GROUP_BY": "Grouper par", "HIDE_COLUMN": "Cacher la colonne", "IN_COLLECTION_SEPERATED_BY_COMMA": "Recherche incluant certain éléments d'une collection, doit être séparé par une virgule (a,b)", @@ -27,6 +30,9 @@ "ITEMS": "éléments", "ITEMS_PER_PAGE": "éléments par page", "LAST_UPDATE": "Dernière mise à jour", + "LESS_THAN": "Plus petit que", + "LESS_THAN_OR_EQUAL_TO": "Plus petit ou égal à", + "NOT_EQUAL_TO": "Non égal à", "NOT_IN_COLLECTION_SEPERATED_BY_COMMA": "Recherche excluant certain éléments d'une collection, doit être séparé par une virgule (a,b)", "OF": "de", "OK": "Terminé", @@ -56,8 +62,8 @@ "COMPLETED": "Terminé", "CHANGE_COMPLETED_FLAG": "Changer l'indicateur terminé", "CHANGE_PRIORITY": "Changer la priorité", - "CUSTOMER_INFORMATION": "Information Client", "CUSTOM_COMMANDS": "Commandes Personnalisées", + "CUSTOMER_INFORMATION": "Information Client", "DELETE_ROW": "Supprimer la ligne", "DISABLED_COMMAND": "Commande désactivée", "FALSE": "Faux",