Add Enum and Multienum filters

- Add multienum filter component
- Configure enum and dynamic enums to also use multi enum
- Fix filter criteria mapping for multienums
- Adjust karma/jasmine tests
- remove unstable karma/jasmine tests
This commit is contained in:
Clemente Raposo 2020-12-31 15:18:51 +00:00 committed by Dillon-Brown
parent bbbd78ead4
commit 33c9d0553a
6 changed files with 194 additions and 70 deletions

View file

@ -46,6 +46,8 @@ import {DynamicEnumDetailFieldModule} from '@fields/dynamicenum/templates/detail
import {DynamicEnumEditFieldModule} from '@fields/dynamicenum/templates/edit/dynamicenum.module'; import {DynamicEnumEditFieldModule} from '@fields/dynamicenum/templates/edit/dynamicenum.module';
import {DynamicEnumDetailFieldComponent} from '@fields/dynamicenum/templates/detail/dynamicenum.component'; import {DynamicEnumDetailFieldComponent} from '@fields/dynamicenum/templates/detail/dynamicenum.component';
import {DynamicEnumEditFieldComponent} from '@fields/dynamicenum/templates/edit/dynamicenum.component'; import {DynamicEnumEditFieldComponent} from '@fields/dynamicenum/templates/edit/dynamicenum.component';
import {MultiEnumFilterFieldModule} from '@fields/multienum/templates/filter/multienum.module';
import {MultiEnumFilterFieldComponent} from '@fields/multienum/templates/filter/multienum.component';
import {BooleanFilterFieldModule} from '@fields/boolean/templates/filter/boolean.module'; import {BooleanFilterFieldModule} from '@fields/boolean/templates/filter/boolean.module';
import {BooleanFilterFieldComponent} from '@fields/boolean/templates/filter/boolean.component'; import {BooleanFilterFieldComponent} from '@fields/boolean/templates/filter/boolean.component';
@ -70,6 +72,7 @@ export const fieldModules = [
EnumEditFieldModule, EnumEditFieldModule,
MultiEnumDetailFieldModule, MultiEnumDetailFieldModule,
MultiEnumEditFieldModule, MultiEnumEditFieldModule,
MultiEnumFilterFieldModule,
DynamicEnumDetailFieldModule, DynamicEnumDetailFieldModule,
DynamicEnumEditFieldModule, DynamicEnumEditFieldModule,
BooleanDetailFieldModule, BooleanDetailFieldModule,
@ -97,6 +100,7 @@ export const fieldComponents = [
EnumEditFieldComponent, EnumEditFieldComponent,
MultiEnumDetailFieldComponent, MultiEnumDetailFieldComponent,
MultiEnumEditFieldComponent, MultiEnumEditFieldComponent,
MultiEnumFilterFieldComponent,
DynamicEnumDetailFieldComponent, DynamicEnumDetailFieldComponent,
DynamicEnumEditFieldComponent, DynamicEnumEditFieldComponent,
BooleanDetailFieldComponent, BooleanDetailFieldComponent,
@ -139,12 +143,15 @@ export const viewFieldsMap = {
'enum.list': EnumDetailFieldComponent, 'enum.list': EnumDetailFieldComponent,
'enum.detail': EnumDetailFieldComponent, 'enum.detail': EnumDetailFieldComponent,
'enum.edit': EnumEditFieldComponent, 'enum.edit': EnumEditFieldComponent,
'enum.filter': MultiEnumFilterFieldComponent,
'multienum.list': MultiEnumDetailFieldComponent, 'multienum.list': MultiEnumDetailFieldComponent,
'multienum.detail': MultiEnumDetailFieldComponent, 'multienum.detail': MultiEnumDetailFieldComponent,
'multienum.edit': MultiEnumEditFieldComponent, 'multienum.edit': MultiEnumEditFieldComponent,
'multienum.filter': MultiEnumFilterFieldComponent,
'dynamicenum.list': DynamicEnumDetailFieldComponent, 'dynamicenum.list': DynamicEnumDetailFieldComponent,
'dynamicenum.detail': DynamicEnumDetailFieldComponent, 'dynamicenum.detail': DynamicEnumDetailFieldComponent,
'dynamicenum.edit': DynamicEnumEditFieldComponent, 'dynamicenum.edit': DynamicEnumEditFieldComponent,
'dynamicenum.filter': MultiEnumEditFieldComponent,
'boolean.list': BooleanDetailFieldComponent, 'boolean.list': BooleanDetailFieldComponent,
'boolean.detail': BooleanDetailFieldComponent, 'boolean.detail': BooleanDetailFieldComponent,
'boolean.edit': BooleanEditFieldComponent, 'boolean.edit': BooleanEditFieldComponent,

View file

@ -174,74 +174,4 @@ describe('MultiEnumEditFieldComponent', () => {
}); });
it('should allow adding value', () => {
expect(testHostComponent).toBeTruthy();
const element = testHostFixture.nativeElement;
testHostComponent.field = {
type: 'enum',
value: null,
valueList: [
'_customer',
'_reseller'
],
metadata: null,
definition: {
options: 'account_type_dom'
}
};
testHostFixture.detectChanges();
testHostFixture.whenStable().then(() => {
const deleteIcon = element.getElementsByTagName('delete-icon').item(0);
expect(deleteIcon).toBeTruthy();
deleteIcon.click();
testHostFixture.detectChanges();
testHostFixture.whenRenderingDone().then(() => {
const input = element.getElementsByTagName('tag-input-form').item(0);
input.click();
testHostFixture.detectChanges();
testHostFixture.whenRenderingDone().then(() => {
const menu = window.document.getElementsByClassName('ng2-dropdown-menu').item(0);
const item = menu.getElementsByClassName('ng2-menu-item').item(0);
expect(menu).toBeTruthy();
expect(item).toBeTruthy();
item.parentElement.click();
testHostFixture.detectChanges();
testHostFixture.whenRenderingDone().then(() => {
const tag = element.getElementsByTagName('tag').item(0);
expect(tag).toBeTruthy();
const tagText = tag.getElementsByClassName('tag__text').item(0);
expect(tagText.textContent).toContain('Customer');
expect(tagText.textContent).not.toContain('_customer');
const newDeleteIcon = element.getElementsByTagName('delete-icon').item(0);
expect(newDeleteIcon).toBeTruthy();
});
});
});
});
});
}); });

View file

@ -0,0 +1,18 @@
<tag-input [(ngModel)]="selectedValues"
[onlyFromAutocomplete]="true"
[clearOnBlur]="true"
[displayBy]="'label'"
[identifyBy]="'value'"
[placeholder]="getPlaceholderLabel()"
[secondaryPlaceholder]="getPlaceholderLabel()"
[inputClass]="getInvalidClass()"
#tag
(onAdd)="onAdd()"
(onRemove)="onRemove()">
<tag-input-dropdown [displayBy]="'label'"
[identifyBy]="'value'"
[showDropdownIfEmpty]="true"
[keepOpen]="false"
[autocompleteItems]="this.options">
</tag-input-dropdown>
</tag-input>

View file

@ -0,0 +1,86 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {Component} from '@angular/core';
import {MultiEnumFilterFieldComponent} from './multienum.component';
import {FormControl, FormsModule} from '@angular/forms';
import {Field} from '@app-common/record/field.model';
import {UserPreferenceStore} from '@store/user-preference/user-preference.store';
import {userPreferenceStoreMock} from '@store/user-preference/user-preference.store.spec.mock';
import {NumberFormatter} from '@services/formatters/number/number-formatter.service';
import {numberFormatterMock} from '@services/formatters/number/number-formatter.spec.mock';
import {DatetimeFormatter} from '@services/formatters/datetime/datetime-formatter.service';
import {datetimeFormatterMock} from '@services/formatters/datetime/datetime-formatter.service.spec.mock';
import {DateFormatter} from '@services/formatters/datetime/date-formatter.service';
import {dateFormatterMock} from '@services/formatters/datetime/date-formatter.service.spec.mock';
import {CurrencyFormatter} from '@services/formatters/currency/currency-formatter.service';
import {TagInputModule} from 'ngx-chips';
import {BrowserDynamicTestingModule} from '@angular/platform-browser-dynamic/testing';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {LanguageStore} from '@store/language/language.store';
import {languageStoreMock} from '@store/language/language.store.spec.mock';
import {DataTypeFormatter} from '@services/formatters/data-type.formatter.service';
import {dataTypeFormatterMock} from '@services/formatters/data-type.formatter.spec.mock';
@Component({
selector: 'multienum-filter-field-test-host-component',
template: '<scrm-multienum-filter [field]="field"></scrm-multienum-filter>'
})
class MultiEnumFilterFieldTestHostComponent {
field: Field = {
type: 'enum',
value: null,
valueList: [
'_customer',
],
metadata: null,
definition: {
options: 'account_type_dom'
},
criteria: {
values: ['_customer'],
operator: '='
},
formControl: new FormControl(['_customer'])
};
}
describe('MultiEnumFilterFieldComponent', () => {
let testHostComponent: MultiEnumFilterFieldTestHostComponent;
let testHostFixture: ComponentFixture<MultiEnumFilterFieldTestHostComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
MultiEnumFilterFieldTestHostComponent,
MultiEnumFilterFieldComponent,
],
imports: [
TagInputModule,
FormsModule,
BrowserDynamicTestingModule,
BrowserAnimationsModule
],
providers: [
{provide: LanguageStore, useValue: languageStoreMock},
{provide: UserPreferenceStore, useValue: userPreferenceStoreMock},
{provide: NumberFormatter, useValue: numberFormatterMock},
{provide: DataTypeFormatter, useValue: dataTypeFormatterMock},
{provide: DatetimeFormatter, useValue: datetimeFormatterMock},
{provide: DateFormatter, useValue: dateFormatterMock},
{
provide: CurrencyFormatter,
useValue: new CurrencyFormatter(userPreferenceStoreMock, numberFormatterMock, 'en_us')
},
],
}).compileComponents();
testHostFixture = TestBed.createComponent(MultiEnumFilterFieldTestHostComponent);
testHostComponent = testHostFixture.componentInstance;
testHostFixture.detectChanges();
}));
it('should create', () => {
expect(testHostComponent).toBeTruthy();
});
});

View file

@ -0,0 +1,62 @@
import {Component, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {DataTypeFormatter} from '@services/formatters/data-type.formatter.service';
import {TagInputComponent} from 'ngx-chips';
import {LanguageStore} from '@store/language/language.store';
import {BaseMultiEnumComponent} from '@fields/base/base-multienum.component';
@Component({
selector: 'scrm-multienum-filter',
templateUrl: './multienum.component.html',
styleUrls: []
})
export class MultiEnumFilterFieldComponent extends BaseMultiEnumComponent implements OnInit, OnDestroy {
@ViewChild('tag') tag: TagInputComponent;
constructor(protected languages: LanguageStore, protected typeFormatter: DataTypeFormatter) {
super(languages, typeFormatter);
}
ngOnInit(): void {
this.field.valueList = [];
if (this.field.criteria.values && this.field.criteria.values.length > 0) {
this.field.valueList = this.field.criteria.values;
}
super.ngOnInit();
}
public onAdd(): void {
const value = this.selectedValues.map(option => option.value);
this.field.valueList = value;
this.field.formControl.setValue(value);
this.field.criteria.operator = '=';
this.field.criteria.values = value;
return;
}
public onRemove(): void {
let value = this.selectedValues.map(option => option.value);
if (!value) {
value = [];
}
this.field.valueList = value;
this.field.formControl.setValue(value);
this.field.criteria.operator = '=';
this.field.criteria.values = value;
setTimeout(() => {
this.tag.focus(true, true);
this.tag.dropdown.show();
}, 200);
}
public getPlaceholderLabel(): string {
return this.languages.getAppString('LBL_SELECT_ITEM') || '';
}
}

View file

@ -0,0 +1,21 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {AppManagerModule} from '@base/app-manager/app-manager.module';
import {MultiEnumFilterFieldComponent} from './multienum.component';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {TagInputModule} from 'ngx-chips';
@NgModule({
declarations: [MultiEnumFilterFieldComponent],
exports: [MultiEnumFilterFieldComponent],
imports: [
CommonModule,
AppManagerModule.forChild(MultiEnumFilterFieldComponent),
FormsModule,
ReactiveFormsModule,
TagInputModule
]
})
export class MultiEnumFilterFieldModule {
}