mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-09-25 10:50:32 +00:00
Hook up to the filter bar
This commit is contained in:
@@ -17,6 +17,12 @@
|
||||
}
|
||||
</select>
|
||||
}
|
||||
@if (advancedSearchEditorAvailable) {
|
||||
<button class="btn btn-sm btn-outline-primary" type="button" (click)="openAdvancedSearchEditor()"
|
||||
title="Edit query" i18n-title [disabled]="disabled">
|
||||
<i-bs name="sliders"></i-bs>
|
||||
</button>
|
||||
}
|
||||
@if (_textFilter) {
|
||||
<button class="btn btn-link btn-sm px-2 position-absolute top-0 end-0 z-10" (click)="resetTextField()" aria-label="Clear search" i18n-aria-label>
|
||||
<i-bs width="1em" height="1em" name="x"></i-bs>
|
||||
|
||||
@@ -12,6 +12,8 @@ import {
|
||||
NgbDatepickerModule,
|
||||
NgbDropdownItem,
|
||||
NgbDropdownModule,
|
||||
NgbModal,
|
||||
NgbModalRef,
|
||||
NgbTypeaheadModule,
|
||||
} from '@ng-bootstrap/ng-bootstrap'
|
||||
import { NgSelectComponent, NgSelectModule } from '@ng-select/ng-select'
|
||||
@@ -2515,4 +2517,45 @@ describe('FilterEditorComponent', () => {
|
||||
|
||||
expect(component.textFilter).toEqual('help ')
|
||||
})
|
||||
|
||||
it('should open the advanced search editor with the current query and apply the result', () => {
|
||||
const modalService: NgbModal = TestBed.inject(NgbModal)
|
||||
let modal: NgbModalRef
|
||||
modalService.activeInstances.subscribe(
|
||||
(instances) => (modal = instances[0])
|
||||
)
|
||||
component.textFilterTarget = 'fulltext-query'
|
||||
component.updateTextFilter('title:invoice')
|
||||
fixture.detectChanges()
|
||||
|
||||
const editorButton = fixture.debugElement.query(
|
||||
By.css('button[title="Edit query"]')
|
||||
)
|
||||
expect(editorButton).not.toBeNull()
|
||||
editorButton.triggerEventHandler('click')
|
||||
fixture.detectChanges()
|
||||
|
||||
expect(modal.componentInstance.query).toEqual('title:invoice')
|
||||
|
||||
const rulesSpy = jest.spyOn(component.filterRulesChange, 'next')
|
||||
modal.componentInstance.queryApplied.emit('title:invoice AND NOT tag:paid')
|
||||
expect(component.textFilter).toEqual('title:invoice AND NOT tag:paid')
|
||||
expect(documentService.searchQuery).toEqual(
|
||||
'title:invoice AND NOT tag:paid'
|
||||
)
|
||||
expect(rulesSpy).toHaveBeenCalledWith([
|
||||
{
|
||||
rule_type: FILTER_FULLTEXT_QUERY,
|
||||
value: 'title:invoice AND NOT tag:paid',
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
it('should not offer the advanced search editor for other targets', () => {
|
||||
component.textFilterTarget = 'title-content'
|
||||
fixture.detectChanges()
|
||||
expect(
|
||||
fixture.debugElement.query(By.css('button[title="Edit query"]'))
|
||||
).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -15,12 +15,13 @@ import {
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||
import {
|
||||
NgbDropdownModule,
|
||||
NgbModal,
|
||||
NgbTypeahead,
|
||||
NgbTypeaheadModule,
|
||||
} from '@ng-bootstrap/ng-bootstrap'
|
||||
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
|
||||
import { TourNgBootstrap } from 'ngx-ui-tour-ng-bootstrap'
|
||||
import { Observable, Subject, from } from 'rxjs'
|
||||
import { first, Observable, Subject, from } from 'rxjs'
|
||||
import {
|
||||
catchError,
|
||||
debounceTime,
|
||||
@@ -121,6 +122,7 @@ import {
|
||||
PermissionsFilterDropdownComponent,
|
||||
PermissionsSelectionModel,
|
||||
} from '../../common/permissions-filter-dropdown/permissions-filter-dropdown.component'
|
||||
import { AdvancedSearchDialogComponent } from '../../common/advanced-search-dialog/advanced-search-dialog.component'
|
||||
import { LoadingComponentWithPermissions } from '../../loading-component/loading.component'
|
||||
|
||||
const TEXT_FILTER_TARGET_TITLE = 'title'
|
||||
@@ -286,6 +288,7 @@ export class FilterEditorComponent
|
||||
permissionsService = inject(PermissionsService)
|
||||
private customFieldService = inject(CustomFieldsService)
|
||||
private searchService = inject(SearchService)
|
||||
private modalService = inject(NgbModal)
|
||||
|
||||
generateFilterName() {
|
||||
if (this.filterRules.length == 1) {
|
||||
@@ -1372,6 +1375,23 @@ export class FilterEditorComponent
|
||||
}
|
||||
}
|
||||
|
||||
get advancedSearchEditorAvailable(): boolean {
|
||||
return this.textFilterTarget === TEXT_FILTER_TARGET_FULLTEXT_QUERY
|
||||
}
|
||||
|
||||
openAdvancedSearchEditor() {
|
||||
const modal = this.modalService.open(AdvancedSearchDialogComponent, {
|
||||
backdrop: 'static',
|
||||
size: 'lg',
|
||||
})
|
||||
modal.componentInstance.query = this._textFilter ?? ''
|
||||
modal.componentInstance.queryApplied
|
||||
.pipe(first())
|
||||
.subscribe((query: string) => {
|
||||
this.updateTextFilter(query)
|
||||
})
|
||||
}
|
||||
|
||||
textFilterKeydown(event: KeyboardEvent) {
|
||||
if (event.key == 'Enter') {
|
||||
if (event.defaultPrevented) {
|
||||
|
||||
@@ -148,6 +148,7 @@ import {
|
||||
send,
|
||||
shop,
|
||||
slashCircle,
|
||||
sliders,
|
||||
sliders2Vertical,
|
||||
sortAlphaDown,
|
||||
sortAlphaUpAlt,
|
||||
@@ -397,6 +398,7 @@ const icons = {
|
||||
send,
|
||||
slashCircle,
|
||||
shop,
|
||||
sliders,
|
||||
sliders2Vertical,
|
||||
sortAlphaDown,
|
||||
sortAlphaUpAlt,
|
||||
|
||||
Reference in New Issue
Block a user