- {{(document.correspondent$ | async)?.name}}:
+ {{(document.correspondent$ | async)?.name}}:
{{document.title | documentTitle}}
diff --git a/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.scss b/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.scss
index 25b80d11e..d7a1d18f7 100644
--- a/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.scss
+++ b/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.scss
@@ -76,3 +76,7 @@
text-align: left !important;
font-size: 90%;
}
+
+a {
+ cursor: pointer;
+}
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 fbb969918..9c3696aae 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
@@ -163,7 +163,7 @@
- {{(d.correspondent$ | async)?.name}}
+ {{(d.correspondent$ | async)?.name}}
|
@@ -172,7 +172,7 @@
|
- {{(d.document_type$ | async)?.name}}
+ {{(d.document_type$ | async)?.name}}
|
diff --git a/src-ui/src/app/components/document-list/document-list.component.scss b/src-ui/src/app/components/document-list/document-list.component.scss
index eb4a757be..09bffc731 100644
--- a/src-ui/src/app/components/document-list/document-list.component.scss
+++ b/src-ui/src/app/components/document-list/document-list.component.scss
@@ -53,3 +53,7 @@ $paperless-card-breakpoints: (
margin-left: 0;
}
}
+
+a {
+ cursor: pointer;
+}
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 f79247034..fac5e3535 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
@@ -1,4 +1,5 @@
import {
+ AfterViewInit,
Component,
OnDestroy,
OnInit,
@@ -8,9 +9,20 @@ import {
} from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
-import { Subscription } from 'rxjs'
+import {
+ filter,
+ first,
+ map,
+ Subject,
+ Subscription,
+ switchMap,
+ takeUntil,
+} from 'rxjs'
import { FilterRule, isFullTextFilterRule } from 'src/app/data/filter-rule'
-import { FILTER_FULLTEXT_MORELIKE } from 'src/app/data/filter-rule-type'
+import {
+ FILTER_FULLTEXT_MORELIKE,
+ FILTER_RULE_TYPES,
+} 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 {
@@ -20,6 +32,7 @@ import {
import { ConsumerStatusService } from 'src/app/services/consumer-status.service'
import { DocumentListViewService } from 'src/app/services/document-list-view.service'
import {
+ DocumentService,
DOCUMENT_SORT_FIELDS,
DOCUMENT_SORT_FIELDS_FULLTEXT,
} from 'src/app/services/rest/document.service'
@@ -33,9 +46,10 @@ import { SaveViewConfigDialogComponent } from './save-view-config-dialog/save-vi
templateUrl: './document-list.component.html',
styleUrls: ['./document-list.component.scss'],
})
-export class DocumentListComponent implements OnInit, OnDestroy {
+export class DocumentListComponent implements OnInit, OnDestroy, AfterViewInit {
constructor(
public list: DocumentListViewService,
+ private documentService: DocumentService,
public savedViewService: SavedViewService,
public route: ActivatedRoute,
private router: Router,
@@ -53,7 +67,7 @@ export class DocumentListComponent implements OnInit, OnDestroy {
unmodifiedFilterRules: FilterRule[] = []
- private consumptionFinishedSubscription: Subscription
+ private unsubscribeNotifier: Subject = new Subject()
get isFiltered() {
return this.list.filterRules?.length > 0
@@ -85,34 +99,97 @@ export class DocumentListComponent implements OnInit, OnDestroy {
if (localStorage.getItem('document-list:displayMode') != null) {
this.displayMode = localStorage.getItem('document-list:displayMode')
}
- this.consumptionFinishedSubscription = this.consumerStatusService
+
+ this.consumerStatusService
.onDocumentConsumptionFinished()
+ .pipe(takeUntil(this.unsubscribeNotifier))
.subscribe(() => {
this.list.reload()
})
- this.route.paramMap.subscribe((params) => {
- if (params.has('id')) {
- this.savedViewService.getCached(+params.get('id')).subscribe((view) => {
- if (!view) {
- this.router.navigate(['404'])
- return
- }
- this.list.activateSavedView(view)
- this.list.reload()
- this.unmodifiedFilterRules = view.filter_rules
+
+ this.route.paramMap
+ .pipe(
+ filter((params) => params.has('id')), // only on saved view
+ switchMap((params) => {
+ return this.savedViewService
+ .getCached(+params.get('id'))
+ .pipe(map((view) => ({ params, view })))
})
- } else {
+ )
+ .pipe(takeUntil(this.unsubscribeNotifier))
+ .subscribe(({ view, params }) => {
+ if (!view) {
+ this.router.navigate(['404'])
+ return
+ }
+ this.list.activateSavedView(view)
+ this.list.reload()
+ this.unmodifiedFilterRules = view.filter_rules
+ })
+
+ const allFilterRuleQueryParams: string[] = FILTER_RULE_TYPES.map(
+ (rt) => rt.filtervar
+ )
+
+ this.route.queryParamMap
+ .pipe(
+ filter(() => !this.route.snapshot.paramMap.has('id')), // only when not on saved view
+ takeUntil(this.unsubscribeNotifier)
+ )
+ .subscribe((queryParams) => {
+ // transform query params to filter rules
+ let filterRulesFromQueryParams: FilterRule[] = []
+ allFilterRuleQueryParams
+ .filter((frqp) => queryParams.has(frqp))
+ .forEach((filterQueryParamName) => {
+ const filterQueryParamValues: string[] = queryParams
+ .get(filterQueryParamName)
+ .split(',')
+
+ filterRulesFromQueryParams = filterRulesFromQueryParams.concat(
+ // map all values to filter rules
+ filterQueryParamValues.map((val) => {
+ return {
+ rule_type: FILTER_RULE_TYPES.find(
+ (rt) => rt.filtervar == filterQueryParamName
+ ).id,
+ value: val,
+ }
+ })
+ )
+ })
+
this.list.activateSavedView(null)
+ this.list.filterRules = filterRulesFromQueryParams
this.list.reload()
this.unmodifiedFilterRules = []
- }
- })
+ })
+ }
+
+ ngAfterViewInit(): void {
+ this.filterEditor.filterRulesChange
+ .pipe(takeUntil(this.unsubscribeNotifier))
+ .subscribe({
+ next: (filterRules) => {
+ const params =
+ this.documentService.filterRulesToQueryParams(filterRules)
+
+ // if we were on a saved view we navigate 'away' to /documents
+ let base = []
+ if (this.route.snapshot.paramMap.has('id')) base = ['/documents']
+
+ this.router.navigate(base, {
+ relativeTo: this.route,
+ queryParams: params,
+ })
+ },
+ })
}
ngOnDestroy() {
- if (this.consumptionFinishedSubscription) {
- this.consumptionFinishedSubscription.unsubscribe()
- }
+ // unsubscribes all
+ this.unsubscribeNotifier.next(this)
+ this.unsubscribeNotifier.complete()
}
loadViewConfig(view: PaperlessSavedView) {
@@ -128,12 +205,15 @@ export class DocumentListComponent implements OnInit, OnDestroy {
sort_field: this.list.sortField,
sort_reverse: this.list.sortReverse,
}
- this.savedViewService.patch(savedView).subscribe((result) => {
- this.toastService.showInfo(
- $localize`View "${this.list.activeSavedViewTitle}" saved successfully.`
- )
- this.unmodifiedFilterRules = this.list.filterRules
- })
+ this.savedViewService
+ .patch(savedView)
+ .pipe(first())
+ .subscribe((result) => {
+ this.toastService.showInfo(
+ $localize`View "${this.list.activeSavedViewTitle}" saved successfully.`
+ )
+ this.unmodifiedFilterRules = this.list.filterRules
+ })
}
}
@@ -142,7 +222,7 @@ export class DocumentListComponent implements OnInit, OnDestroy {
backdrop: 'static',
})
modal.componentInstance.defaultName = this.filterEditor.generateFilterName()
- modal.componentInstance.saveClicked.subscribe((formValue) => {
+ modal.componentInstance.saveClicked.pipe(first()).subscribe((formValue) => {
modal.componentInstance.buttonsEnabled = false
let savedView: PaperlessSavedView = {
name: formValue.name,
@@ -153,18 +233,21 @@ export class DocumentListComponent implements OnInit, OnDestroy {
sort_field: this.list.sortField,
}
- this.savedViewService.create(savedView).subscribe(
- () => {
- modal.close()
- this.toastService.showInfo(
- $localize`View "${savedView.name}" created successfully.`
- )
- },
- (error) => {
- modal.componentInstance.error = error.error
- modal.componentInstance.buttonsEnabled = true
- }
- )
+ this.savedViewService
+ .create(savedView)
+ .pipe(first())
+ .subscribe({
+ next: () => {
+ modal.close()
+ this.toastService.showInfo(
+ $localize`View "${savedView.name}" created successfully.`
+ )
+ },
+ error: (error) => {
+ modal.componentInstance.error = error.error
+ modal.componentInstance.buttonsEnabled = 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 a77ce2509..fa07649af 100644
--- a/src-ui/src/app/services/document-list-view.service.ts
+++ b/src-ui/src/app/services/document-list-view.service.ts
@@ -143,8 +143,8 @@ export class DocumentListViewService {
activeListViewState.sortReverse,
activeListViewState.filterRules
)
- .subscribe(
- (result) => {
+ .subscribe({
+ next: (result) => {
this.isReloading = false
activeListViewState.collectionSize = result.count
activeListViewState.documents = result.results
@@ -153,7 +153,7 @@ export class DocumentListViewService {
}
this.rangeSelectionAnchorIndex = this.lastRangeSelectionToIndex = null
},
- (error) => {
+ error: (error) => {
this.isReloading = false
if (activeListViewState.currentPage != 1 && error.status == 404) {
// this happens when applying a filter: the current page might not be available anymore due to the reduced result set.
@@ -162,8 +162,8 @@ export class DocumentListViewService {
} else {
this.error = error.error
}
- }
- )
+ },
+ })
}
set filterRules(filterRules: FilterRule[]) {
@@ -249,20 +249,11 @@ export class DocumentListViewService {
}
quickFilter(filterRules: FilterRule[]) {
- 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') {
- this.reload()
- } else {
- this.router.navigate(['documents'])
- }
+ const params = this.documentService.filterRulesToQueryParams(filterRules)
+ this.router.navigate(['/documents'], {
+ relativeTo: this.route,
+ queryParams: params,
+ })
}
getLastPage(): number {
diff --git a/src-ui/src/app/services/rest/document.service.ts b/src-ui/src/app/services/rest/document.service.ts
index e22e17ea8..d06282bb8 100644
--- a/src-ui/src/app/services/rest/document.service.ts
+++ b/src-ui/src/app/services/rest/document.service.ts
@@ -57,7 +57,7 @@ export class DocumentService extends AbstractPaperlessService
super(http, 'documents')
}
- private filterRulesToQueryParams(filterRules: FilterRule[]) {
+ public filterRulesToQueryParams(filterRules: FilterRule[]): Object {
if (filterRules) {
let params = {}
for (let rule of filterRules) {
|