From 71e25653861c2d9228577e90c729a845145fe53c Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 18 Oct 2024 22:35:57 -0700 Subject: [PATCH] Enhancement: auto-focus default select field in custom field dropdown (#7961) --- ...ustom-fields-query-dropdown.component.html | 2 +- ...om-fields-query-dropdown.component.spec.ts | 26 +++++++++++++-- .../custom-fields-query-dropdown.component.ts | 33 +++++++++++++++---- .../filter-editor.component.spec.ts | 18 +++++----- 4 files changed, 61 insertions(+), 18 deletions(-) diff --git a/src-ui/src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html b/src-ui/src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html index 9da2886f4..9cc095d7d 100644 --- a/src-ui/src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html +++ b/src-ui/src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html @@ -41,7 +41,7 @@ } @else if (getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.Select) { - { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [CustomFieldsQueryDropdownComponent], - imports: [NgbDropdownModule, NgxBootstrapIconsModule.pick(allIcons)], + imports: [ + NgbDropdownModule, + NgxBootstrapIconsModule.pick(allIcons), + NgSelectModule, + FormsModule, + ReactiveFormsModule, + ], providers: [ provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting(), @@ -181,6 +194,15 @@ describe('CustomFieldsQueryDropdownComponent', () => { expect(component.name).toBe('test_title') }) + it('should add a default atom on open and focus the select field', fakeAsync(() => { + expect(component.selectionModel.queries.length).toBe(0) + component.onOpenChange(true) + fixture.detectChanges() + tick() + expect(component.selectionModel.queries.length).toBe(1) + expect(window.document.activeElement.tagName).toBe('INPUT') + })) + describe('CustomFieldQueriesModel', () => { let model: CustomFieldQueriesModel diff --git a/src-ui/src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.ts b/src-ui/src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.ts index 011ae1bc1..dbd269b3b 100644 --- a/src-ui/src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.ts +++ b/src-ui/src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.ts @@ -4,9 +4,12 @@ import { Input, OnDestroy, Output, + QueryList, ViewChild, + ViewChildren, } from '@angular/core' import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap' +import { NgSelectComponent } from '@ng-select/ng-select' import { Subject, first, takeUntil } from 'rxjs' import { CustomField, CustomFieldDataType } from 'src/app/data/custom-field' import { @@ -184,6 +187,8 @@ export class CustomFieldsQueryDropdownComponent implements OnDestroy { @ViewChild('dropdown') dropdown: NgbDropdown + @ViewChildren(NgSelectComponent) fieldSelects!: QueryList + private _selectionModel: CustomFieldQueriesModel @Input() @@ -227,16 +232,32 @@ export class CustomFieldsQueryDropdownComponent implements OnDestroy { } public onOpenChange(open: boolean) { - if (open && this.selectionModel.queries.length === 0) { - this.selectionModel.addExpression() + if (open) { + if (this.selectionModel.queries.length === 0) { + this.selectionModel.addAtom( + new CustomFieldQueryAtom([ + null, + CustomFieldQueryOperator.Exists, + 'true', + ]) + ) + } + if ( + this.selectionModel.queries.length === 1 && + ( + (this.selectionModel.queries[0] as CustomFieldQueryExpression) + ?.value[0] as CustomFieldQueryAtom + )?.field === null + ) { + setTimeout(() => { + this.fieldSelects.first?.focus() + }, 0) + } } } public get isActive(): boolean { - return ( - (this.selectionModel.queries[0] as CustomFieldQueryExpression)?.value - ?.length > 0 - ) + return this.selectionModel.isValid() } private getFields() { diff --git a/src-ui/src/app/components/document-list/filter-editor/filter-editor.component.spec.ts b/src-ui/src/app/components/document-list/filter-editor/filter-editor.component.spec.ts index 19a53f76c..402465d1b 100644 --- a/src-ui/src/app/components/document-list/filter-editor/filter-editor.component.spec.ts +++ b/src-ui/src/app/components/document-list/filter-editor/filter-editor.component.spec.ts @@ -101,7 +101,10 @@ import { CustomFieldQueryLogicalOperator, CustomFieldQueryOperator, } from 'src/app/data/custom-field-query' -import { CustomFieldQueryAtom } from 'src/app/utils/custom-field-query-element' +import { + CustomFieldQueryAtom, + CustomFieldQueryExpression, +} from 'src/app/utils/custom-field-query-element' const tags: Tag[] = [ { @@ -1441,15 +1444,12 @@ describe('FilterEditorComponent', () => { By.css('button') ) customFieldToggleButton.triggerEventHandler('click') + tick() fixture.detectChanges() - const customFieldButtons = customFieldsQueryDropdown.queryAll( - By.css('button') - ) - customFieldButtons[1].triggerEventHandler('click') - fixture.detectChanges() - const query = component.customFieldQueriesModel - .queries[0] as CustomFieldQueryAtom - query.field = custom_fields[0].id + const expression = component.customFieldQueriesModel + .queries[0] as CustomFieldQueryExpression + const atom = expression.value[0] as CustomFieldQueryAtom + atom.field = custom_fields[0].id const fieldSelect: NgSelectComponent = customFieldsQueryDropdown.queryAll( By.directive(NgSelectComponent) )[0].componentInstance