mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-09 09:58:20 -05:00
Enhancement: auto-focus default select field in custom field dropdown (#7961)
This commit is contained in:
parent
f0ad073bb2
commit
71e2565386
@ -41,7 +41,7 @@
|
|||||||
<option value="false" i18n>False</option>
|
<option value="false" i18n>False</option>
|
||||||
</select>
|
</select>
|
||||||
} @else if (getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.Select) {
|
} @else if (getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.Select) {
|
||||||
<ng-select
|
<ng-select #fieldSelects
|
||||||
class="paperless-input-select rounded-end"
|
class="paperless-input-select rounded-end"
|
||||||
[items]="getSelectOptionsForField(atom.field)"
|
[items]="getSelectOptionsForField(atom.field)"
|
||||||
[(ngModel)]="atom.value"
|
[(ngModel)]="atom.value"
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
import {
|
||||||
|
ComponentFixture,
|
||||||
|
fakeAsync,
|
||||||
|
TestBed,
|
||||||
|
tick,
|
||||||
|
} from '@angular/core/testing'
|
||||||
import {
|
import {
|
||||||
CustomFieldQueriesModel,
|
CustomFieldQueriesModel,
|
||||||
CustomFieldsQueryDropdownComponent,
|
CustomFieldsQueryDropdownComponent,
|
||||||
@ -20,6 +25,8 @@ import {
|
|||||||
CustomFieldQueryAtom,
|
CustomFieldQueryAtom,
|
||||||
CustomFieldQueryElement,
|
CustomFieldQueryElement,
|
||||||
} from 'src/app/utils/custom-field-query-element'
|
} from 'src/app/utils/custom-field-query-element'
|
||||||
|
import { NgSelectModule } from '@ng-select/ng-select'
|
||||||
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||||
|
|
||||||
const customFields = [
|
const customFields = [
|
||||||
{
|
{
|
||||||
@ -44,7 +51,13 @@ describe('CustomFieldsQueryDropdownComponent', () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [CustomFieldsQueryDropdownComponent],
|
declarations: [CustomFieldsQueryDropdownComponent],
|
||||||
imports: [NgbDropdownModule, NgxBootstrapIconsModule.pick(allIcons)],
|
imports: [
|
||||||
|
NgbDropdownModule,
|
||||||
|
NgxBootstrapIconsModule.pick(allIcons),
|
||||||
|
NgSelectModule,
|
||||||
|
FormsModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
],
|
||||||
providers: [
|
providers: [
|
||||||
provideHttpClient(withInterceptorsFromDi()),
|
provideHttpClient(withInterceptorsFromDi()),
|
||||||
provideHttpClientTesting(),
|
provideHttpClientTesting(),
|
||||||
@ -181,6 +194,15 @@ describe('CustomFieldsQueryDropdownComponent', () => {
|
|||||||
expect(component.name).toBe('test_title')
|
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', () => {
|
describe('CustomFieldQueriesModel', () => {
|
||||||
let model: CustomFieldQueriesModel
|
let model: CustomFieldQueriesModel
|
||||||
|
|
||||||
|
@ -4,9 +4,12 @@ import {
|
|||||||
Input,
|
Input,
|
||||||
OnDestroy,
|
OnDestroy,
|
||||||
Output,
|
Output,
|
||||||
|
QueryList,
|
||||||
ViewChild,
|
ViewChild,
|
||||||
|
ViewChildren,
|
||||||
} from '@angular/core'
|
} from '@angular/core'
|
||||||
import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap'
|
import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap'
|
||||||
|
import { NgSelectComponent } from '@ng-select/ng-select'
|
||||||
import { Subject, first, takeUntil } from 'rxjs'
|
import { Subject, first, takeUntil } from 'rxjs'
|
||||||
import { CustomField, CustomFieldDataType } from 'src/app/data/custom-field'
|
import { CustomField, CustomFieldDataType } from 'src/app/data/custom-field'
|
||||||
import {
|
import {
|
||||||
@ -184,6 +187,8 @@ export class CustomFieldsQueryDropdownComponent implements OnDestroy {
|
|||||||
|
|
||||||
@ViewChild('dropdown') dropdown: NgbDropdown
|
@ViewChild('dropdown') dropdown: NgbDropdown
|
||||||
|
|
||||||
|
@ViewChildren(NgSelectComponent) fieldSelects!: QueryList<NgSelectComponent>
|
||||||
|
|
||||||
private _selectionModel: CustomFieldQueriesModel
|
private _selectionModel: CustomFieldQueriesModel
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
@ -227,16 +232,32 @@ export class CustomFieldsQueryDropdownComponent implements OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public onOpenChange(open: boolean) {
|
public onOpenChange(open: boolean) {
|
||||||
if (open && this.selectionModel.queries.length === 0) {
|
if (open) {
|
||||||
this.selectionModel.addExpression()
|
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 {
|
public get isActive(): boolean {
|
||||||
return (
|
return this.selectionModel.isValid()
|
||||||
(this.selectionModel.queries[0] as CustomFieldQueryExpression)?.value
|
|
||||||
?.length > 0
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private getFields() {
|
private getFields() {
|
||||||
|
@ -101,7 +101,10 @@ import {
|
|||||||
CustomFieldQueryLogicalOperator,
|
CustomFieldQueryLogicalOperator,
|
||||||
CustomFieldQueryOperator,
|
CustomFieldQueryOperator,
|
||||||
} from 'src/app/data/custom-field-query'
|
} 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[] = [
|
const tags: Tag[] = [
|
||||||
{
|
{
|
||||||
@ -1441,15 +1444,12 @@ describe('FilterEditorComponent', () => {
|
|||||||
By.css('button')
|
By.css('button')
|
||||||
)
|
)
|
||||||
customFieldToggleButton.triggerEventHandler('click')
|
customFieldToggleButton.triggerEventHandler('click')
|
||||||
|
tick()
|
||||||
fixture.detectChanges()
|
fixture.detectChanges()
|
||||||
const customFieldButtons = customFieldsQueryDropdown.queryAll(
|
const expression = component.customFieldQueriesModel
|
||||||
By.css('button')
|
.queries[0] as CustomFieldQueryExpression
|
||||||
)
|
const atom = expression.value[0] as CustomFieldQueryAtom
|
||||||
customFieldButtons[1].triggerEventHandler('click')
|
atom.field = custom_fields[0].id
|
||||||
fixture.detectChanges()
|
|
||||||
const query = component.customFieldQueriesModel
|
|
||||||
.queries[0] as CustomFieldQueryAtom
|
|
||||||
query.field = custom_fields[0].id
|
|
||||||
const fieldSelect: NgSelectComponent = customFieldsQueryDropdown.queryAll(
|
const fieldSelect: NgSelectComponent = customFieldsQueryDropdown.queryAll(
|
||||||
By.directive(NgSelectComponent)
|
By.directive(NgSelectComponent)
|
||||||
)[0].componentInstance
|
)[0].componentInstance
|
||||||
|
Loading…
x
Reference in New Issue
Block a user