diff --git a/src-ui/src/app/components/document-list/document-list.component.html b/src-ui/src/app/components/document-list/document-list.component.html index 18c4a2fcc..7fd1dc7fc 100644 --- a/src-ui/src/app/components/document-list/document-list.component.html +++ b/src-ui/src/app/components/document-list/document-list.component.html @@ -117,7 +117,7 @@
- +
diff --git a/src-ui/src/app/components/document-list/document-list.component.spec.ts b/src-ui/src/app/components/document-list/document-list.component.spec.ts index 87a6ee0a1..5dc9516a7 100644 --- a/src-ui/src/app/components/document-list/document-list.component.spec.ts +++ b/src-ui/src/app/components/document-list/document-list.component.spec.ts @@ -147,21 +147,21 @@ describe('DocumentListComponent', () => { }) it('should show score sort fields on fulltext queries', () => { - documentListService.filterRules = [ + documentListService.setFilterRules([ { rule_type: FILTER_HAS_TAGS_ANY, value: '10', }, - ] + ]) fixture.detectChanges() expect(component.getSortFields()).toEqual(documentListService.sortFields) - documentListService.filterRules = [ + documentListService.setFilterRules([ { rule_type: FILTER_FULLTEXT_QUERY, value: 'foo', }, - ] + ]) fixture.detectChanges() expect(component.getSortFields()).toEqual( documentListService.sortFieldsFullText @@ -170,12 +170,12 @@ describe('DocumentListComponent', () => { it('should determine if filtered, support reset', () => { fixture.detectChanges() - documentListService.filterRules = [ + documentListService.setFilterRules([ { rule_type: FILTER_HAS_TAGS_ANY, value: '10', }, - ] + ]) documentListService.isReloading = false fixture.detectChanges() expect(component.isFiltered).toBeTruthy() @@ -185,6 +185,20 @@ describe('DocumentListComponent', () => { expect(fixture.nativeElement.textContent.match(/Reset/g)).toHaveLength(1) }) + it('should apply filter rule changes via list service', () => { + const setFilterRulesSpy = jest.spyOn(documentListService, 'setFilterRules') + const rules = [{ rule_type: FILTER_HAS_TAGS_ANY, value: '10' }] + component.onFilterRulesChange(rules) + expect(setFilterRulesSpy).toHaveBeenCalledWith(rules) + }) + + it('should reset filter rules to page one via list service', () => { + const setFilterRulesSpy = jest.spyOn(documentListService, 'setFilterRules') + const rules = [{ rule_type: FILTER_HAS_TAGS_ANY, value: '10' }] + component.onFilterRulesReset(rules) + expect(setFilterRulesSpy).toHaveBeenCalledWith(rules, true) + }) + it('should load saved view from URL', () => { const view: SavedView = { id: 10, @@ -217,7 +231,7 @@ describe('DocumentListComponent', () => { .spyOn(activatedRoute, 'paramMap', 'get') .mockReturnValue(of(convertToParamMap(queryParams))) activatedRoute.snapshot.queryParams = queryParams - fixture.detectChanges() + component.ngOnInit() expect(getSavedViewSpy).toHaveBeenCalledWith(view.id) expect(activateSavedViewSpy).toHaveBeenCalledWith( view, diff --git a/src-ui/src/app/components/document-list/document-list.component.ts b/src-ui/src/app/components/document-list/document-list.component.ts index d2d21ee17..c0dd8f80a 100644 --- a/src-ui/src/app/components/document-list/document-list.component.ts +++ b/src-ui/src/app/components/document-list/document-list.component.ts @@ -212,6 +212,14 @@ export class DocumentListComponent this.list.setSort(event.column, event.reverse) } + onFilterRulesChange(filterRules: FilterRule[]) { + this.list.setFilterRules(filterRules) + } + + onFilterRulesReset(filterRules: FilterRule[]) { + this.list.setFilterRules(filterRules, true) + } + get isBulkEditing(): boolean { return this.list.selected.size > 0 } @@ -300,7 +308,7 @@ export class DocumentListComponent if (this.list.selected.size > 0) { this.list.selectNone() } else if (this.isFiltered) { - this.filterEditor.resetSelected() + this.resetFilters() } }) 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 39e58aefd..bf5240f1b 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 @@ -2107,6 +2107,22 @@ describe('FilterEditorComponent', () => { expect(component.filterRules).toEqual(rules) }) + it('should emit reset filter rules when resetting', () => { + const rules = [{ rule_type: FILTER_HAS_TAGS_ANY, value: '2' }] + component.unmodifiedFilterRules = rules + component.filterRules = [ + { rule_type: FILTER_DOES_NOT_HAVE_TAG, value: '2' }, + ] + + const resetFilterRulesSpy = jest.spyOn(component.resetFilterRules, 'next') + const filterRulesChangeSpy = jest.spyOn(component.filterRulesChange, 'next') + + component.resetSelected() + + expect(resetFilterRulesSpy).toHaveBeenCalledWith(rules) + expect(filterRulesChangeSpy).not.toHaveBeenCalled() + }) + it('should support resetting text field', () => { component.textFilter = 'foo' component.resetTextField() diff --git a/src-ui/src/app/components/document-list/filter-editor/filter-editor.component.ts b/src-ui/src/app/components/document-list/filter-editor/filter-editor.component.ts index 55bb67d15..b717c13fc 100644 --- a/src-ui/src/app/components/document-list/filter-editor/filter-editor.component.ts +++ b/src-ui/src/app/components/document-list/filter-editor/filter-editor.component.ts @@ -1101,6 +1101,9 @@ export class FilterEditorComponent @Output() filterRulesChange = new EventEmitter() + @Output() + resetFilterRules = new EventEmitter() + @Input() set selectionData(selectionData: SelectionData) { this.tagDocumentCounts = selectionData?.selected_tags ?? null @@ -1244,7 +1247,7 @@ export class FilterEditorComponent this.textFilterTarget = TEXT_FILTER_TARGET_TITLE_CONTENT this.documentService.searchQuery = '' this.filterRules = this._unmodifiedFilterRules - this.updateRules() + this.resetFilterRules.next(this.filterRules) } toggleTag(tagId: number) { diff --git a/src-ui/src/app/services/document-list-view.service.spec.ts b/src-ui/src/app/services/document-list-view.service.spec.ts index fdbfa2069..6258c42b2 100644 --- a/src-ui/src/app/services/document-list-view.service.spec.ts +++ b/src-ui/src/app/services/document-list-view.service.spec.ts @@ -164,7 +164,7 @@ describe('DocumentListViewService', () => { value: tags__id__in, }, ] - documentListViewService.filterRules = filterRulesAny + documentListViewService.setFilterRules(filterRulesAny) let req = httpTestingController.expectOne( `${environment.apiBaseUrl}documents/?page=1&page_size=50&ordering=-created&truncate_content=true&tags__id__in=${tags__id__in}` ) @@ -178,7 +178,7 @@ describe('DocumentListViewService', () => { ) expect(req.request.method).toEqual('GET') // reset the list - documentListViewService.filterRules = [] + documentListViewService.setFilterRules([]) req = httpTestingController.expectOne( `${environment.apiBaseUrl}documents/?page=1&page_size=50&ordering=-created&truncate_content=true` ) @@ -210,7 +210,7 @@ describe('DocumentListViewService', () => { value: tags__id__in, }, ] - documentListViewService.filterRules = filterRulesAny + documentListViewService.setFilterRules(filterRulesAny) let req = httpTestingController.expectOne( `${environment.apiBaseUrl}documents/?page=1&page_size=50&ordering=-created&truncate_content=true&tags__id__in=${tags__id__in}` ) @@ -218,7 +218,7 @@ describe('DocumentListViewService', () => { req.flush('Generic error', { status: 404, statusText: 'Unexpected error' }) expect(documentListViewService.error).toEqual('Generic error') // reset the list - documentListViewService.filterRules = [] + documentListViewService.setFilterRules([]) req = httpTestingController.expectOne( `${environment.apiBaseUrl}documents/?page=1&page_size=50&ordering=-created&truncate_content=true` ) @@ -295,13 +295,41 @@ describe('DocumentListViewService', () => { }) it('should use filter rules to update query params', () => { - documentListViewService.filterRules = filterRules + documentListViewService.setFilterRules(filterRules) const req = httpTestingController.expectOne( `${environment.apiBaseUrl}documents/?page=${documentListViewService.currentPage}&page_size=${documentListViewService.pageSize}&ordering=-created&truncate_content=true&tags__id__all=${tags__id__all}` ) expect(req.request.method).toEqual('GET') }) + it('should support setting filter rules and resetting to page one', () => { + documentListViewService.currentPage = 2 + let req = httpTestingController.expectOne((request) => + request.urlWithParams.startsWith( + `${environment.apiBaseUrl}documents/?page=2&page_size=50&ordering=-created&truncate_content=true` + ) + ) + expect(req.request.method).toEqual('GET') + req.flush(full_results) + req = httpTestingController.expectOne( + `${environment.apiBaseUrl}documents/selection_data/` + ) + req.flush([]) + + documentListViewService.setFilterRules(filterRules, true) + + const filteredReqs = httpTestingController.match( + `${environment.apiBaseUrl}documents/?page=1&page_size=50&ordering=-created&truncate_content=true&tags__id__all=${tags__id__all}` + ) + expect(filteredReqs).toHaveLength(1) + filteredReqs[0].flush(full_results) + req = httpTestingController.expectOne( + `${environment.apiBaseUrl}documents/selection_data/` + ) + req.flush([]) + expect(documentListViewService.currentPage).toEqual(1) + }) + it('should support quick filter', () => { documentListViewService.quickFilter(filterRules) const req = httpTestingController.expectOne( @@ -336,7 +364,7 @@ describe('DocumentListViewService', () => { req = httpTestingController.expectOne( `${environment.apiBaseUrl}documents/?page=1&page_size=50&ordering=-added&truncate_content=true&tags__id__all=9` ) - documentListViewService.filterRules = [] + documentListViewService.setFilterRules([]) req = httpTestingController.expectOne( `${environment.apiBaseUrl}documents/?page=1&page_size=50&ordering=-added&truncate_content=true` ) @@ -348,7 +376,7 @@ describe('DocumentListViewService', () => { }) it('should support navigating next / previous', () => { - documentListViewService.filterRules = [] + documentListViewService.setFilterRules([]) let req = httpTestingController.expectOne( `${environment.apiBaseUrl}documents/?page=1&page_size=50&ordering=-created&truncate_content=true` ) @@ -558,7 +586,7 @@ describe('DocumentListViewService', () => { req.flush(full_results) expect(documentListViewService.selected.size).toEqual(6) - documentListViewService.filterRules = filterRules + documentListViewService.setFilterRules(filterRules) httpTestingController.expectOne( `${environment.apiBaseUrl}documents/?page=1&page_size=50&ordering=-created&truncate_content=true&tags__id__all=9` ) @@ -592,7 +620,7 @@ describe('DocumentListViewService', () => { documentListViewService.loadSavedView(view2) expect(documentListViewService.sortField).toEqual('score') - documentListViewService.filterRules = [] + documentListViewService.setFilterRules([]) expect(documentListViewService.sortField).toEqual('created') httpTestingController.expectOne( `${environment.apiBaseUrl}documents/?page=1&page_size=50&ordering=-created&truncate_content=true` diff --git a/src-ui/src/app/services/document-list-view.service.ts b/src-ui/src/app/services/document-list-view.service.ts index 0bc43b782..6989db8ed 100644 --- a/src-ui/src/app/services/document-list-view.service.ts +++ b/src-ui/src/app/services/document-list-view.service.ts @@ -342,7 +342,7 @@ export class DocumentListViewService { }) } - set filterRules(filterRules: FilterRule[]) { + setFilterRules(filterRules: FilterRule[], resetPage: boolean = false) { if ( !isFullTextFilterRule(filterRules) && this.activeListViewState.sortField == 'score' @@ -350,6 +350,9 @@ export class DocumentListViewService { this.activeListViewState.sortField = 'created' } this.activeListViewState.filterRules = filterRules + if (resetPage) { + this.activeListViewState.currentPage = 1 + } this.reload() this.reduceSelectionToFilter() this.saveDocumentListView() @@ -479,7 +482,7 @@ export class DocumentListViewService { quickFilter(filterRules: FilterRule[]) { this._activeSavedViewId = null - this.filterRules = filterRules + this.setFilterRules(filterRules) this.router.navigate(['documents']) }