From 96f4924911d3e6fd44d61f372bd37d63a5afafa1 Mon Sep 17 00:00:00 2001
From: jonaswinkler <17569239+jonaswinkler@users.noreply.github.com>
Date: Sat, 15 May 2021 18:48:39 +0200
Subject: [PATCH] frontend support for fulltext sorting
---
src-ui/messages.xlf | 8 ++++
.../document-list/document-list.component.ts | 6 +--
src-ui/src/app/data/filter-rule.ts | 6 +++
.../services/document-list-view.service.ts | 39 ++++++++++++++++---
.../src/app/services/rest/document.service.ts | 5 +++
5 files changed, 56 insertions(+), 8 deletions(-)
diff --git a/src-ui/messages.xlf b/src-ui/messages.xlf
index 68fe2703a..037ef0b17 100644
--- a/src-ui/messages.xlf
+++ b/src-ui/messages.xlf
@@ -1889,6 +1889,14 @@
23
+
+ Search score
+
+ src/app/services/rest/document.service.ts
+ 28
+
+ Score is a value returned by the full text search engine and specifies how well a result matches the given query
+
Create new item
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 13a827e97..79adb99d0 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
@@ -2,14 +2,14 @@ import { Component, OnDestroy, OnInit, QueryList, ViewChild, ViewChildren } from
import { ActivatedRoute, Router } from '@angular/router';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { Subscription } from 'rxjs';
-import { FilterRule } from 'src/app/data/filter-rule';
+import { FilterRule, isFullTextFilterRule } from 'src/app/data/filter-rule';
import { FILTER_FULLTEXT_MORELIKE } from 'src/app/data/filter-rule-type';
import { PaperlessDocument } from 'src/app/data/paperless-document';
import { PaperlessSavedView } from 'src/app/data/paperless-saved-view';
import { SortableDirective, SortEvent } from 'src/app/directives/sortable.directive';
import { ConsumerStatusService } from 'src/app/services/consumer-status.service';
import { DocumentListViewService } from 'src/app/services/document-list-view.service';
-import { DOCUMENT_SORT_FIELDS } from 'src/app/services/rest/document.service';
+import { DOCUMENT_SORT_FIELDS, DOCUMENT_SORT_FIELDS_FULLTEXT } from 'src/app/services/rest/document.service';
import { SavedViewService } from 'src/app/services/rest/saved-view.service';
import { ToastService } from 'src/app/services/toast.service';
import { FilterEditorComponent } from './filter-editor/filter-editor.component';
@@ -52,7 +52,7 @@ export class DocumentListComponent implements OnInit, OnDestroy {
}
getSortFields() {
- return DOCUMENT_SORT_FIELDS
+ return isFullTextFilterRule(this.list.filterRules) ? DOCUMENT_SORT_FIELDS_FULLTEXT : DOCUMENT_SORT_FIELDS
}
onSort(event: SortEvent) {
diff --git a/src-ui/src/app/data/filter-rule.ts b/src-ui/src/app/data/filter-rule.ts
index 82d8498f3..5a0ed7368 100644
--- a/src-ui/src/app/data/filter-rule.ts
+++ b/src-ui/src/app/data/filter-rule.ts
@@ -1,3 +1,5 @@
+import { FILTER_FULLTEXT_MORELIKE, FILTER_FULLTEXT_QUERY } from "./filter-rule-type"
+
export function cloneFilterRules(filterRules: FilterRule[]): FilterRule[] {
if (filterRules) {
let newRules: FilterRule[] = []
@@ -10,6 +12,10 @@ export function cloneFilterRules(filterRules: FilterRule[]): FilterRule[] {
}
}
+export function isFullTextFilterRule(filterRules: FilterRule[]): boolean {
+ return filterRules.find(r => r.rule_type == FILTER_FULLTEXT_QUERY || r.rule_type == FILTER_FULLTEXT_MORELIKE) != null
+}
+
export interface FilterRule {
rule_type: number
value: string
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 aa82190d7..4e1a8aad4 100644
--- a/src-ui/src/app/services/document-list-view.service.ts
+++ b/src-ui/src/app/services/document-list-view.service.ts
@@ -1,28 +1,53 @@
import { Injectable } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Observable } from 'rxjs';
-import { cloneFilterRules, FilterRule } from '../data/filter-rule';
-import { FILTER_FULLTEXT_MORELIKE, FILTER_FULLTEXT_QUERY } from '../data/filter-rule-type';
+import { cloneFilterRules, FilterRule, isFullTextFilterRule } from '../data/filter-rule';
import { PaperlessDocument } from '../data/paperless-document';
import { PaperlessSavedView } from '../data/paperless-saved-view';
import { DOCUMENT_LIST_SERVICE } from '../data/storage-keys';
import { DocumentService } from './rest/document.service';
import { SettingsService, SETTINGS_KEYS } from './settings.service';
+/**
+ * Captures the current state of the list view.
+ */
interface ListViewState {
+ /**
+ * Title of the document list view. Either "Documents" (localized) or the name of a saved view.
+ */
title?: string
+ /**
+ * Current paginated list of documents displayed.
+ */
documents?: PaperlessDocument[]
currentPage: number
+
+ /**
+ * Total amount of documents with the current filter rules. Used to calculate the number of pages.
+ */
collectionSize: number
+ /**
+ * Currently selected sort field.
+ */
sortField: string
+
+ /**
+ * True if the list is sorted in reverse.
+ */
sortReverse: boolean
+ /**
+ * Filter rules for the current list view.
+ */
filterRules: FilterRule[]
+ /**
+ * Contains the IDs of all selected documents.
+ */
selected?: Set
}
@@ -134,10 +159,10 @@ export class DocumentListViewService {
}
set filterRules(filterRules: FilterRule[]) {
- this.activeListViewState.filterRules = filterRules
- if (filterRules.find(r => (r.rule_type == FILTER_FULLTEXT_QUERY || r.rule_type == FILTER_FULLTEXT_MORELIKE))) {
- this.activeListViewState.currentPage = 1
+ if (!isFullTextFilterRule(filterRules) && this.activeListViewState.sortField == "score") {
+ this.activeListViewState.sortField = "created"
}
+ this.activeListViewState.filterRules = filterRules
this.reload()
this.reduceSelectionToFilter()
this.saveDocumentListView()
@@ -213,6 +238,10 @@ export class DocumentListViewService {
this._activeSavedViewId = null
this.activeListViewState.filterRules = filterRules
this.activeListViewState.currentPage = 1
+ if (isFullTextFilterRule(filterRules)) {
+ this.activeListViewState.sortField = "score"
+ this.activeListViewState.sortReverse = false
+ }
this.reduceSelectionToFilter()
this.saveDocumentListView()
if (this.router.url == "/documents") {
diff --git a/src-ui/src/app/services/rest/document.service.ts b/src-ui/src/app/services/rest/document.service.ts
index 712b0492f..c6bc61dc8 100644
--- a/src-ui/src/app/services/rest/document.service.ts
+++ b/src-ui/src/app/services/rest/document.service.ts
@@ -23,6 +23,11 @@ export const DOCUMENT_SORT_FIELDS = [
{ field: 'modified', name: $localize`Modified` }
]
+export const DOCUMENT_SORT_FIELDS_FULLTEXT = [
+ ...DOCUMENT_SORT_FIELDS,
+ { field: 'score', name: $localize`:Score is a value returned by the full text search engine and specifies how well a result matches the given query:Search score` }
+]
+
export interface SelectionDataItem {
id: number
document_count: number