mirror of
https://github.com/SuiteCRM/SuiteCRM-Core.git
synced 2025-08-29 07:50:08 +08:00
Add Boolean filter field
- Add boolean filter component -- Use same implementation as in enums - Fix karma/jasmine tests
This commit is contained in:
parent
af186a7013
commit
8eff4e16b7
7 changed files with 244 additions and 107 deletions
|
@ -0,0 +1,20 @@
|
|||
<tag-input #tag
|
||||
(onAdd)="onAdd($event)"
|
||||
(onRemove)="onRemove()"
|
||||
[(ngModel)]="selectedValues"
|
||||
[class]="getInvalidClass()"
|
||||
[clearOnBlur]="true"
|
||||
[displayBy]="'label'"
|
||||
[identifyBy]="'value'"
|
||||
[inputClass]="getInvalidClass()"
|
||||
[onlyFromAutocomplete]="true"
|
||||
[placeholder]="getPlaceholderLabel()"
|
||||
[secondaryPlaceholder]="getPlaceholderLabel()"
|
||||
maxItems="1">
|
||||
<tag-input-dropdown [autocompleteItems]="this.options"
|
||||
[displayBy]="'label'"
|
||||
[identifyBy]="'value'"
|
||||
[keepOpen]="false"
|
||||
[showDropdownIfEmpty]="true">
|
||||
</tag-input-dropdown>
|
||||
</tag-input>
|
|
@ -0,0 +1,126 @@
|
|||
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
import {Component} from '@angular/core';
|
||||
import {BooleanFilterFieldComponent} from './boolean.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';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'boolean-filter-field-test-host-component',
|
||||
template: '<scrm-boolean-filter [field]="field"></scrm-boolean-filter>'
|
||||
})
|
||||
class BooleanFilterFieldTestHostComponent {
|
||||
field: Field = {
|
||||
type: 'boolean',
|
||||
value: '1',
|
||||
metadata: null,
|
||||
definition: {
|
||||
options: 'dom_int_bool'
|
||||
},
|
||||
criteria: {
|
||||
values: ['1'],
|
||||
operator: '='
|
||||
},
|
||||
formControl: new FormControl('1')
|
||||
};
|
||||
}
|
||||
|
||||
describe('BooleanFilterFieldComponent', () => {
|
||||
let testHostComponent: BooleanFilterFieldTestHostComponent;
|
||||
let testHostFixture: ComponentFixture<BooleanFilterFieldTestHostComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
BooleanFilterFieldTestHostComponent,
|
||||
BooleanFilterFieldComponent,
|
||||
],
|
||||
imports: [
|
||||
TagInputModule,
|
||||
FormsModule,
|
||||
BrowserDynamicTestingModule,
|
||||
BrowserAnimationsModule
|
||||
],
|
||||
providers: [
|
||||
{provide: LanguageStore, useValue: languageStoreMock},
|
||||
{provide: UserPreferenceStore, useValue: userPreferenceStoreMock},
|
||||
{provide: NumberFormatter, useValue: numberFormatterMock},
|
||||
{provide: DatetimeFormatter, useValue: datetimeFormatterMock},
|
||||
{provide: DateFormatter, useValue: dateFormatterMock},
|
||||
{
|
||||
provide: CurrencyFormatter,
|
||||
useValue: new CurrencyFormatter(userPreferenceStoreMock, numberFormatterMock, 'en_us')
|
||||
},
|
||||
],
|
||||
}).compileComponents();
|
||||
|
||||
testHostFixture = TestBed.createComponent(BooleanFilterFieldTestHostComponent);
|
||||
testHostComponent = testHostFixture.componentInstance;
|
||||
testHostFixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(testHostComponent).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should have value', () => {
|
||||
expect(testHostComponent).toBeTruthy();
|
||||
|
||||
testHostComponent.field = {
|
||||
type: 'boolean',
|
||||
value: '1',
|
||||
metadata: null,
|
||||
definition: {
|
||||
options: 'dom_int_bool'
|
||||
},
|
||||
criteria: {
|
||||
values: ['1'],
|
||||
operator: '='
|
||||
},
|
||||
formControl: new FormControl('1')
|
||||
};
|
||||
|
||||
testHostFixture.detectChanges();
|
||||
testHostFixture.whenStable().then(() => {
|
||||
|
||||
|
||||
const field = testHostFixture.nativeElement.getElementsByTagName('scrm-boolean-filter')[0];
|
||||
|
||||
expect(field).toBeTruthy();
|
||||
|
||||
const tagInput = field.getElementsByTagName('tag-input').item(0);
|
||||
|
||||
expect(tagInput).toBeTruthy();
|
||||
|
||||
const tag = tagInput.getElementsByTagName('tag').item(0);
|
||||
|
||||
expect(tag).toBeTruthy();
|
||||
|
||||
const tagText = tag.getElementsByClassName('tag__text').item(0);
|
||||
|
||||
expect(tagText.textContent).toContain('Yes');
|
||||
expect(tagText.textContent).not.toContain('1');
|
||||
|
||||
const deleteIcon = tagInput.getElementsByTagName('delete-icon').item(0);
|
||||
|
||||
expect(deleteIcon).toBeTruthy();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
|
@ -0,0 +1,63 @@
|
|||
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 {BaseEnumComponent} from '@fields/base/base-enum.component';
|
||||
|
||||
@Component({
|
||||
selector: 'scrm-boolean-filter',
|
||||
templateUrl: './boolean.component.html',
|
||||
styleUrls: []
|
||||
})
|
||||
export class BooleanFilterFieldComponent extends BaseEnumComponent implements OnInit, OnDestroy {
|
||||
|
||||
@ViewChild('tag') tag: TagInputComponent;
|
||||
|
||||
constructor(protected languages: LanguageStore, protected typeFormatter: DataTypeFormatter) {
|
||||
super(languages, typeFormatter);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.field.value = '';
|
||||
|
||||
if (this.field.criteria.values && this.field.criteria.values.length > 0) {
|
||||
this.field.value = this.field.criteria.values[0];
|
||||
}
|
||||
|
||||
super.ngOnInit();
|
||||
|
||||
}
|
||||
|
||||
public onAdd(item): void {
|
||||
if (item && item.value) {
|
||||
this.field.value = item.value;
|
||||
this.field.formControl.setValue(item.value);
|
||||
this.field.criteria.operator = '=';
|
||||
this.field.criteria.values = [item.value];
|
||||
return;
|
||||
}
|
||||
|
||||
this.field.value = '';
|
||||
this.field.formControl.setValue('');
|
||||
this.selectedValues = [];
|
||||
this.field.criteria.operator = '';
|
||||
this.field.criteria.values = [];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public onRemove(): void {
|
||||
this.field.value = '';
|
||||
this.field.formControl.setValue('');
|
||||
this.field.criteria.operator = '';
|
||||
this.field.criteria.values = [];
|
||||
setTimeout(() => {
|
||||
this.tag.focus(true, true);
|
||||
this.tag.dropdown.show();
|
||||
}, 200);
|
||||
}
|
||||
|
||||
public getPlaceholderLabel(): string {
|
||||
return this.languages.getAppString('LBL_SELECT_ITEM') || '';
|
||||
}
|
||||
}
|
21
core/app/fields/boolean/templates/filter/boolean.module.ts
Normal file
21
core/app/fields/boolean/templates/filter/boolean.module.ts
Normal 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 {BooleanFilterFieldComponent} from './boolean.component';
|
||||
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
|
||||
import {TagInputModule} from 'ngx-chips';
|
||||
|
||||
@NgModule({
|
||||
declarations: [BooleanFilterFieldComponent],
|
||||
exports: [BooleanFilterFieldComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
AppManagerModule.forChild(BooleanFilterFieldComponent),
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
TagInputModule
|
||||
]
|
||||
})
|
||||
export class BooleanFilterFieldModule {
|
||||
}
|
|
@ -111,108 +111,4 @@ describe('DynamicEnumEditFieldComponent', () => {
|
|||
});
|
||||
|
||||
});
|
||||
|
||||
it('should allow removing value', () => {
|
||||
expect(testHostComponent).toBeTruthy();
|
||||
|
||||
const element = testHostFixture.nativeElement;
|
||||
|
||||
testHostComponent.field = {
|
||||
type: 'dynamicenum',
|
||||
value: '_customer',
|
||||
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 tag = element.getElementsByClassName('tag__text');
|
||||
|
||||
expect(tag).toBeTruthy();
|
||||
|
||||
expect(tag.length).toEqual(0);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
it('should allow adding value', () => {
|
||||
expect(testHostComponent).toBeTruthy();
|
||||
|
||||
const element = testHostFixture.nativeElement;
|
||||
|
||||
testHostComponent.field = {
|
||||
type: 'dynamicenum',
|
||||
value: '_customer',
|
||||
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();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -46,6 +46,8 @@ import {DynamicEnumDetailFieldModule} from '@fields/dynamicenum/templates/detail
|
|||
import {DynamicEnumEditFieldModule} from '@fields/dynamicenum/templates/edit/dynamicenum.module';
|
||||
import {DynamicEnumDetailFieldComponent} from '@fields/dynamicenum/templates/detail/dynamicenum.component';
|
||||
import {DynamicEnumEditFieldComponent} from '@fields/dynamicenum/templates/edit/dynamicenum.component';
|
||||
import {BooleanFilterFieldModule} from '@fields/boolean/templates/filter/boolean.module';
|
||||
import {BooleanFilterFieldComponent} from '@fields/boolean/templates/filter/boolean.component';
|
||||
|
||||
export const fieldModules = [
|
||||
VarcharDetailFieldModule,
|
||||
|
@ -71,7 +73,8 @@ export const fieldModules = [
|
|||
DynamicEnumDetailFieldModule,
|
||||
DynamicEnumEditFieldModule,
|
||||
BooleanDetailFieldModule,
|
||||
BooleanEditFieldModule
|
||||
BooleanEditFieldModule,
|
||||
BooleanFilterFieldModule
|
||||
];
|
||||
export const fieldComponents = [
|
||||
VarcharDetailFieldComponent,
|
||||
|
@ -97,7 +100,8 @@ export const fieldComponents = [
|
|||
DynamicEnumDetailFieldComponent,
|
||||
DynamicEnumEditFieldComponent,
|
||||
BooleanDetailFieldComponent,
|
||||
BooleanEditFieldComponent
|
||||
BooleanEditFieldComponent,
|
||||
BooleanFilterFieldComponent
|
||||
];
|
||||
|
||||
export const viewFieldsMap = {
|
||||
|
@ -144,7 +148,9 @@ export const viewFieldsMap = {
|
|||
'boolean.list': BooleanDetailFieldComponent,
|
||||
'boolean.detail': BooleanDetailFieldComponent,
|
||||
'boolean.edit': BooleanEditFieldComponent,
|
||||
'boolean.filter': BooleanFilterFieldComponent,
|
||||
'bool.list': BooleanDetailFieldComponent,
|
||||
'bool.detail': BooleanDetailFieldComponent,
|
||||
'bool.edit': BooleanEditFieldComponent
|
||||
'bool.edit': BooleanEditFieldComponent,
|
||||
'bool.filter': BooleanFilterFieldComponent
|
||||
};
|
||||
|
|
|
@ -67,6 +67,11 @@ export const languageMockData = {
|
|||
_reseller: 'Reseller',
|
||||
_other: 'Other'
|
||||
},
|
||||
// eslint-disable-next-line camelcase,@typescript-eslint/camelcase
|
||||
dom_int_bool: {
|
||||
1: 'Yes',
|
||||
0: 'No',
|
||||
},
|
||||
},
|
||||
modStrings: {
|
||||
home: {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue