]> git.ipfire.org Git - thirdparty/paperless-ngx.git/commitdiff
Enhancement: auto-focus default select field in custom field dropdown (#7961)
authorshamoon <4887959+shamoon@users.noreply.github.com>
Sat, 19 Oct 2024 05:35:57 +0000 (22:35 -0700)
committerGitHub <noreply@github.com>
Sat, 19 Oct 2024 05:35:57 +0000 (22:35 -0700)
src-ui/src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html
src-ui/src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.spec.ts
src-ui/src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.ts
src-ui/src/app/components/document-list/filter-editor/filter-editor.component.spec.ts

index 9da2886f4170e998a887833df4ad568843d3aaa2..9cc095d7d5cc7525f64eb22fe6cfd06c3711c2c5 100644 (file)
@@ -41,7 +41,7 @@
       <option value="false" i18n>False</option>
     </select>
   } @else if (getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.Select) {
-    <ng-select
+    <ng-select #fieldSelects
       class="paperless-input-select rounded-end"
       [items]="getSelectOptionsForField(atom.field)"
       [(ngModel)]="atom.value"
index e6199c696965c1ff400b5d57c7330cd1af0b9e1c..9b42ff4e6075e5bd649bb5d44e245cac288121e7 100644 (file)
@@ -1,4 +1,9 @@
-import { ComponentFixture, TestBed } from '@angular/core/testing'
+import {
+  ComponentFixture,
+  fakeAsync,
+  TestBed,
+  tick,
+} from '@angular/core/testing'
 import {
   CustomFieldQueriesModel,
   CustomFieldsQueryDropdownComponent,
@@ -20,6 +25,8 @@ import {
   CustomFieldQueryAtom,
   CustomFieldQueryElement,
 } from 'src/app/utils/custom-field-query-element'
+import { NgSelectModule } from '@ng-select/ng-select'
+import { FormsModule, ReactiveFormsModule } from '@angular/forms'
 
 const customFields = [
   {
@@ -44,7 +51,13 @@ describe('CustomFieldsQueryDropdownComponent', () => {
   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
 
index 011ae1bc19c06a3ba5b98189d845560c242936c7..dbd269b3b60539449b77b9e736607d14669495c1 100644 (file)
@@ -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<NgSelectComponent>
+
   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() {
index 19a53f76c6c70f758618879d8d5fa9ea4cbf9104..402465d1bbc664303137c97d4a554d5cf39d8b8c 100644 (file)
@@ -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