mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	infinite scroll for search results
This commit is contained in:
		| @@ -1,9 +1,7 @@ | ||||
| import { Component, Input, OnInit } from '@angular/core'; | ||||
| import { DomSanitizer } from '@angular/platform-browser'; | ||||
| import { PaperlessDocument } from 'src/app/data/paperless-document'; | ||||
| import { PaperlessTag } from 'src/app/data/paperless-tag'; | ||||
| import { DocumentService } from 'src/app/services/rest/document.service'; | ||||
| import { SearchResultHighlightedText } from 'src/app/services/rest/search.service'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'app-document-card-large', | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| import { Component, Input, OnInit } from '@angular/core'; | ||||
| import { SearchResultHighlightedText } from 'src/app/services/rest/search.service'; | ||||
| import { SearchHitHighlight } from 'src/app/data/search-result'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'app-result-hightlight', | ||||
| @@ -11,7 +11,7 @@ export class ResultHightlightComponent implements OnInit { | ||||
|   constructor() { } | ||||
|  | ||||
|   @Input() | ||||
|   highlights: SearchResultHighlightedText[][] | ||||
|   highlights: SearchHitHighlight[][] | ||||
|  | ||||
|   ngOnInit(): void { | ||||
|   } | ||||
|   | ||||
| @@ -3,12 +3,11 @@ | ||||
|  | ||||
| <p>Search string: <i>{{query}}</i></p> | ||||
|  | ||||
| <div [class.result-content-searching]="searching"> | ||||
| <app-document-card-large *ngFor="let result of results" | ||||
|     [document]="result.document" | ||||
|     [details]="result.highlights"> | ||||
| <div [class.result-content-searching]="searching" infiniteScroll (scrolled)="onScroll()"> | ||||
|     <p>{{resultCount}} result(s)</p> | ||||
|     <app-document-card-large *ngFor="let result of results" | ||||
|         [document]="result.document" | ||||
|         [details]="result.highlights"> | ||||
|  | ||||
| </app-document-card-large> | ||||
| </div> | ||||
|  | ||||
| <p *ngIf="results.length == 0" class="mx-auto">No results</p> | ||||
| </div> | ||||
| @@ -1,6 +1,7 @@ | ||||
| import { Component, OnInit } from '@angular/core'; | ||||
| import { ActivatedRoute } from '@angular/router'; | ||||
| import { SearchResult, SearchService } from 'src/app/services/rest/search.service'; | ||||
| import { SearchHit } from 'src/app/data/search-result'; | ||||
| import { SearchService } from 'src/app/services/rest/search.service'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'app-search', | ||||
| @@ -9,24 +10,50 @@ import { SearchResult, SearchService } from 'src/app/services/rest/search.servic | ||||
| }) | ||||
| export class SearchComponent implements OnInit { | ||||
|    | ||||
|   results: SearchResult[] = [] | ||||
|   results: SearchHit[] = [] | ||||
|  | ||||
|   query: string = "" | ||||
|  | ||||
|   searching = false | ||||
|  | ||||
|   currentPage = 1 | ||||
|  | ||||
|   pageCount = 1 | ||||
|  | ||||
|   resultCount | ||||
|  | ||||
|   constructor(private searchService: SearchService, private route: ActivatedRoute) { } | ||||
|  | ||||
|   ngOnInit(): void { | ||||
|     this.route.queryParamMap.subscribe(paramMap => { | ||||
|       this.query = paramMap.get('query') | ||||
|       this.searching = true | ||||
|       this.searchService.search(this.query).subscribe(result => { | ||||
|         this.results = result | ||||
|         this.searching = false | ||||
|       }) | ||||
|       this.currentPage = 1 | ||||
|       this.loadPage() | ||||
|     }) | ||||
|      | ||||
|   } | ||||
|  | ||||
|   loadPage(append: boolean = false) { | ||||
|     this.searchService.search(this.query, this.currentPage).subscribe(result => { | ||||
|       if (append) { | ||||
|         this.results.push(...result.results) | ||||
|       } else { | ||||
|         this.results = result.results | ||||
|       } | ||||
|       this.pageCount = result.page_count | ||||
|       this.searching = false | ||||
|       this.resultCount = result.count | ||||
|     }) | ||||
|   } | ||||
|  | ||||
|   onScroll() { | ||||
|     console.log(this.currentPage) | ||||
|     console.log(this.pageCount) | ||||
|     if (this.currentPage < this.pageCount) { | ||||
|       this.currentPage += 1 | ||||
|       this.loadPage(true) | ||||
|     } | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
							
								
								
									
										27
									
								
								src-ui/src/app/data/search-result.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src-ui/src/app/data/search-result.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| import { PaperlessDocument } from './paperless-document' | ||||
|  | ||||
| export class SearchHitHighlight { | ||||
|   text?: string | ||||
|   term?: number | ||||
| } | ||||
|  | ||||
| export interface SearchHit { | ||||
|   id?: number | ||||
|   title?: string | ||||
|   score?: number | ||||
|   rank?: number | ||||
|  | ||||
|   highlights?: SearchHitHighlight[][] | ||||
|   document?: PaperlessDocument | ||||
| } | ||||
|  | ||||
| export interface SearchResult { | ||||
|  | ||||
|   count?: number | ||||
|   page?: number | ||||
|   page_count?: number | ||||
|  | ||||
|   results?: SearchHit[] | ||||
|  | ||||
|  | ||||
| } | ||||
| @@ -2,27 +2,9 @@ import { HttpClient, HttpParams } from '@angular/common/http'; | ||||
| import { Injectable } from '@angular/core'; | ||||
| import { Observable } from 'rxjs'; | ||||
| import { PaperlessDocument } from 'src/app/data/paperless-document'; | ||||
| import { SearchResult } from 'src/app/data/search-result'; | ||||
| import { environment } from 'src/environments/environment'; | ||||
|  | ||||
| export class SearchResultHighlightedText { | ||||
|   text?: string | ||||
|   term?: number | ||||
|  | ||||
|   toString(): string { | ||||
|     return this.text | ||||
|   } | ||||
| } | ||||
|  | ||||
| export class SearchResult { | ||||
|   id?: number | ||||
|   title?: string | ||||
|   content?: string | ||||
|  | ||||
|   score?: number | ||||
|   highlights?: SearchResultHighlightedText[][] | ||||
|  | ||||
|   document?: PaperlessDocument | ||||
| } | ||||
|  | ||||
| @Injectable({ | ||||
|   providedIn: 'root' | ||||
| @@ -31,8 +13,12 @@ export class SearchService { | ||||
|    | ||||
|   constructor(private http: HttpClient) { } | ||||
|  | ||||
|   search(query: string): Observable<SearchResult[]> { | ||||
|     return this.http.get<SearchResult[]>(`${environment.apiBaseUrl}search/`, {params: new HttpParams().set('query', query)}) | ||||
|   search(query: string, page?: number): Observable<SearchResult> { | ||||
|     let httpParams = new HttpParams().set('query', query) | ||||
|     if (page) { | ||||
|       httpParams = httpParams.set('page', page.toString()) | ||||
|     } | ||||
|     return this.http.get<SearchResult>(`${environment.apiBaseUrl}search/`, {params: httpParams}) | ||||
|   } | ||||
|  | ||||
|   autocomplete(term: string): Observable<string[]> { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Jonas Winkler
					Jonas Winkler