mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-11-03 03:16:10 -06:00 
			
		
		
		
	more like this searching
This commit is contained in:
		@@ -24,6 +24,12 @@
 | 
			
		||||
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <button type="button" class="btn btn-sm btn-outline-primary mr-2" (click)="moreLike()">
 | 
			
		||||
        <svg class="buttonicon" fill="currentColor">
 | 
			
		||||
            <use xlink:href="assets/bootstrap-icons.svg#three-dots" />
 | 
			
		||||
        </svg>
 | 
			
		||||
        <span class="d-none d-lg-inline"> More like this</span>
 | 
			
		||||
    </button>
 | 
			
		||||
 | 
			
		||||
    <button type="button" class="btn btn-sm btn-outline-primary" (click)="close()">
 | 
			
		||||
        <svg class="buttonicon" fill="currentColor">
 | 
			
		||||
 
 | 
			
		||||
@@ -168,6 +168,10 @@ export class DocumentDetailComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  moreLike() {
 | 
			
		||||
    this.router.navigate(["search"], {queryParams: {more_like:this.document.id}})
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  hasNext() {
 | 
			
		||||
    return this.documentListViewService.hasNext(this.documentId)
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,12 @@
 | 
			
		||||
 | 
			
		||||
        <div class="d-flex justify-content-between align-items-center">
 | 
			
		||||
          <div class="btn-group">
 | 
			
		||||
            <a routerLink="/search" [queryParams]="{'more_like': document.id}" class="btn btn-sm btn-outline-secondary">
 | 
			
		||||
              <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-three-dots" viewBox="0 0 16 16">
 | 
			
		||||
                <path fill-rule="evenodd" d="M3 9.5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z"/>
 | 
			
		||||
              </svg>
 | 
			
		||||
              More like this
 | 
			
		||||
            </a>
 | 
			
		||||
            <a routerLink="/documents/{{document.id}}" class="btn btn-sm btn-outline-secondary">
 | 
			
		||||
              <svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-pencil" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
                <path fill-rule="evenodd" d="M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168l10-10zM11.207 2.5L13.5 4.793 14.793 3.5 12.5 1.207 11.207 2.5zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293l6.5-6.5zm-9.761 5.175l-.106.106-1.528 3.821 3.821-1.528.106-.106A.5.5 0 0 1 5 12.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.468-.325z"/>
 | 
			
		||||
@@ -45,10 +51,13 @@
 | 
			
		||||
              </svg>
 | 
			
		||||
              Download
 | 
			
		||||
            </a>
 | 
			
		||||
            <ngb-progressbar [type]="searchScoreClass" [value]="searchScore" style="width: 100px; height: 5px; margin: 10px;" [max]="1"></ngb-progressbar>
 | 
			
		||||
            
 | 
			
		||||
          </div>
 | 
			
		||||
          
 | 
			
		||||
          <small class="text-muted">Created: {{document.created | date}}</small>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,19 @@ export class DocumentCardLargeComponent implements OnInit {
 | 
			
		||||
  @Output()
 | 
			
		||||
  clickCorrespondent = new EventEmitter<number>()
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  searchScore: number
 | 
			
		||||
 | 
			
		||||
  get searchScoreClass() {
 | 
			
		||||
    if (this.searchScore > 0.7) {
 | 
			
		||||
      return "success"
 | 
			
		||||
    } else if (this.searchScore > 0.3) {
 | 
			
		||||
      return "warning"
 | 
			
		||||
    } else {
 | 
			
		||||
      return "danger"
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnInit(): void {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
.match {
 | 
			
		||||
    color: black;
 | 
			
		||||
    background-color: orange;
 | 
			
		||||
    background-color: rgb(255, 211, 66);
 | 
			
		||||
}
 | 
			
		||||
@@ -3,7 +3,12 @@
 | 
			
		||||
 | 
			
		||||
<div *ngIf="errorMessage" class="alert alert-danger">Invalid search query: {{errorMessage}}</div>
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
<p *ngIf="more_like">
 | 
			
		||||
    Showing documents similar to
 | 
			
		||||
    <a routerLink="/documents/{{more_like}}">{{more_like_doc?.original_file_name}}</a>
 | 
			
		||||
</p>
 | 
			
		||||
 | 
			
		||||
<p *ngIf="query">
 | 
			
		||||
    Search string: <i>{{query}}</i>
 | 
			
		||||
    <ng-container *ngIf="correctedQuery">
 | 
			
		||||
        - Did you mean "<a [routerLink]="" (click)="searchCorrectedQuery()">{{correctedQuery}}</a>"?
 | 
			
		||||
@@ -15,7 +20,8 @@
 | 
			
		||||
    <p>{{resultCount}} result(s)</p>
 | 
			
		||||
    <app-document-card-large *ngFor="let result of results"
 | 
			
		||||
        [document]="result.document"
 | 
			
		||||
        [details]="result.highlights">
 | 
			
		||||
        [details]="result.highlights"
 | 
			
		||||
        [searchScore]="result.score / maxScore">
 | 
			
		||||
 | 
			
		||||
</app-document-card-large>
 | 
			
		||||
</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,9 @@
 | 
			
		||||
import { Component, OnInit } from '@angular/core';
 | 
			
		||||
import { ActivatedRoute, Router } from '@angular/router';
 | 
			
		||||
import { PaperlessDocument } from 'src/app/data/paperless-document';
 | 
			
		||||
import { PaperlessDocumentType } from 'src/app/data/paperless-document-type';
 | 
			
		||||
import { SearchHit } from 'src/app/data/search-result';
 | 
			
		||||
import { DocumentService } from 'src/app/services/rest/document.service';
 | 
			
		||||
import { SearchService } from 'src/app/services/rest/search.service';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
@@ -14,6 +17,10 @@ export class SearchComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
  query: string = ""
 | 
			
		||||
 | 
			
		||||
  more_like: number
 | 
			
		||||
 | 
			
		||||
  more_like_doc: PaperlessDocument
 | 
			
		||||
 | 
			
		||||
  searching = false
 | 
			
		||||
 | 
			
		||||
  currentPage = 1
 | 
			
		||||
@@ -26,11 +33,23 @@ export class SearchComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
  errorMessage: string
 | 
			
		||||
 | 
			
		||||
  constructor(private searchService: SearchService, private route: ActivatedRoute, private router: Router) { }
 | 
			
		||||
  get maxScore() {
 | 
			
		||||
    return this.results?.length > 0 ? this.results[0].score : 100
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  constructor(private searchService: SearchService, private route: ActivatedRoute, private router: Router, private documentService: DocumentService) { }
 | 
			
		||||
 | 
			
		||||
  ngOnInit(): void {
 | 
			
		||||
    this.route.queryParamMap.subscribe(paramMap => {
 | 
			
		||||
      this.query = paramMap.get('query')
 | 
			
		||||
      this.more_like = paramMap.has('more_like') ? +paramMap.get('more_like') : null
 | 
			
		||||
      if (this.more_like) {
 | 
			
		||||
        this.documentService.get(this.more_like).subscribe(r => {
 | 
			
		||||
          this.more_like_doc = r
 | 
			
		||||
        })
 | 
			
		||||
      } else {
 | 
			
		||||
        this.more_like_doc = null
 | 
			
		||||
      }
 | 
			
		||||
      this.searching = true
 | 
			
		||||
      this.currentPage = 1
 | 
			
		||||
      this.loadPage()
 | 
			
		||||
@@ -39,13 +58,14 @@ export class SearchComponent implements OnInit {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  searchCorrectedQuery() {
 | 
			
		||||
    this.router.navigate(["search"], {queryParams: {query: this.correctedQuery}})
 | 
			
		||||
    this.router.navigate(["search"], {queryParams: {query: this.correctedQuery, more_like: this.more_like}})
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  loadPage(append: boolean = false) {
 | 
			
		||||
    this.errorMessage = null
 | 
			
		||||
    this.correctedQuery = null
 | 
			
		||||
    this.searchService.search(this.query, this.currentPage).subscribe(result => {
 | 
			
		||||
 | 
			
		||||
    this.searchService.search(this.query, this.currentPage, this.more_like).subscribe(result => {
 | 
			
		||||
      if (append) {
 | 
			
		||||
        this.results.push(...result.results)
 | 
			
		||||
      } else {
 | 
			
		||||
 
 | 
			
		||||
@@ -15,11 +15,17 @@ export class SearchService {
 | 
			
		||||
  
 | 
			
		||||
  constructor(private http: HttpClient, private documentService: DocumentService) { }
 | 
			
		||||
 | 
			
		||||
  search(query: string, page?: number): Observable<SearchResult> {
 | 
			
		||||
    let httpParams = new HttpParams().set('query', query)
 | 
			
		||||
  search(query: string, page?: number, more_like?: number): Observable<SearchResult> {
 | 
			
		||||
    let httpParams = new HttpParams()
 | 
			
		||||
    if (query) {
 | 
			
		||||
      httpParams = httpParams.set('query', query)
 | 
			
		||||
    }
 | 
			
		||||
    if (page) {
 | 
			
		||||
      httpParams = httpParams.set('page', page.toString())
 | 
			
		||||
    }
 | 
			
		||||
    if (more_like) {
 | 
			
		||||
      httpParams = httpParams.set('more_like', more_like.toString())
 | 
			
		||||
    }
 | 
			
		||||
    return this.http.get<SearchResult>(`${environment.apiBaseUrl}search/`, {params: httpParams}).pipe(
 | 
			
		||||
      map(result => {
 | 
			
		||||
        result.results.forEach(hit => this.documentService.addObservablesToDocument(hit.document))
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user