Merge pull request #881 from paperless-ngx/feature-fix-saved-view-query-params

Feature / fix saved view & sort field query params
This commit is contained in:
Quinn Casey
2022-05-06 12:45:22 -07:00
committed by GitHub
12 changed files with 242 additions and 124 deletions

View File

@@ -22,6 +22,7 @@ import {
RemoteVersionService,
AppRemoteVersion,
} from 'src/app/services/rest/remote-version.service'
import { QueryParamsService } from 'src/app/services/query-params.service'
@Component({
selector: 'app-app-frame',
@@ -37,7 +38,8 @@ export class AppFrameComponent {
public savedViewService: SavedViewService,
private list: DocumentListViewService,
private meta: Meta,
private remoteVersionService: RemoteVersionService
private remoteVersionService: RemoteVersionService,
private queryParamsService: QueryParamsService
) {
this.remoteVersionService
.checkForUpdates()
@@ -92,7 +94,7 @@ export class AppFrameComponent {
search() {
this.closeMenu()
this.list.quickFilter([
this.queryParamsService.navigateWithFilterRules([
{
rule_type: FILTER_FULLTEXT_QUERY,
value: (this.searchField.value as string).trim(),

View File

@@ -3,11 +3,11 @@ import { Router } from '@angular/router'
import { Subscription } from 'rxjs'
import { PaperlessDocument } from 'src/app/data/paperless-document'
import { PaperlessSavedView } from 'src/app/data/paperless-saved-view'
import { DocumentListViewService } from 'src/app/services/document-list-view.service'
import { ConsumerStatusService } from 'src/app/services/consumer-status.service'
import { DocumentService } from 'src/app/services/rest/document.service'
import { PaperlessTag } from 'src/app/data/paperless-tag'
import { FILTER_HAS_TAGS_ALL } from 'src/app/data/filter-rule-type'
import { QueryParamsService } from 'src/app/services/query-params.service'
@Component({
selector: 'app-saved-view-widget',
@@ -18,7 +18,7 @@ export class SavedViewWidgetComponent implements OnInit, OnDestroy {
constructor(
private documentService: DocumentService,
private router: Router,
private list: DocumentListViewService,
private queryParamsService: QueryParamsService,
private consumerStatusService: ConsumerStatusService
) {}
@@ -60,13 +60,14 @@ export class SavedViewWidgetComponent implements OnInit, OnDestroy {
if (this.savedView.show_in_sidebar) {
this.router.navigate(['view', this.savedView.id])
} else {
this.list.loadSavedView(this.savedView, true)
this.router.navigate(['documents'])
this.router.navigate(['documents'], {
queryParams: { view: this.savedView.id },
})
}
}
clickTag(tag: PaperlessTag) {
this.list.quickFilter([
this.queryParamsService.navigateWithFilterRules([
{ rule_type: FILTER_HAS_TAGS_ALL, value: tag.id.toString() },
])
}

View File

@@ -35,6 +35,7 @@ import {
import { PaperlessDocumentSuggestions } from 'src/app/data/paperless-document-suggestions'
import { FILTER_FULLTEXT_MORELIKE } from 'src/app/data/filter-rule-type'
import { normalizeDateStr } from 'src/app/utils/date'
import { QueryParamsService } from 'src/app/services/query-params.service'
@Component({
selector: 'app-document-detail',
@@ -114,7 +115,8 @@ export class DocumentDetailComponent
private documentListViewService: DocumentListViewService,
private documentTitlePipe: DocumentTitlePipe,
private toastService: ToastService,
private settings: SettingsService
private settings: SettingsService,
private queryParamsService: QueryParamsService
) {
this.titleSubject
.pipe(
@@ -446,7 +448,7 @@ export class DocumentDetailComponent
}
moreLike() {
this.documentListViewService.quickFilter([
this.queryParamsService.navigateWithFilterRules([
{
rule_type: FILTER_FULLTEXT_MORELIKE,
value: this.documentId.toString(),

View File

@@ -38,7 +38,7 @@
<div ngbDropdown class="btn-group ms-2 flex-fill">
<button class="btn btn-outline-primary btn-sm" id="dropdownBasic1" ngbDropdownToggle i18n>Sort</button>
<div ngbDropdownMenu aria-labelledby="dropdownBasic1" class="shadow dropdown-menu-right">
<div class="w-100 d-flex btn-group-toggle pb-2 mb-1 border-bottom" ngbRadioGroup [(ngModel)]="list.sortReverse">
<div class="w-100 d-flex btn-group-toggle pb-2 mb-1 border-bottom" ngbRadioGroup [(ngModel)]="listSort">
<label ngbButtonLabel class="btn-outline-primary btn-sm mx-2 flex-fill">
<input ngbButton type="radio" class="btn btn-check btn-sm" [value]="false">
<svg class="toolbaricon" fill="currentColor">
@@ -53,7 +53,7 @@
</label>
</div>
<div>
<button *ngFor="let f of getSortFields()" ngbDropdownItem (click)="list.sortField = f.field"
<button *ngFor="let f of getSortFields()" ngbDropdownItem (click)="setSortField(f.field)"
[class.active]="list.sortField == f.field">{{f.name}}
</button>
</div>
@@ -64,7 +64,7 @@
<button class="btn btn-sm btn-outline-primary dropdown-toggle flex-fill" ngbDropdownToggle i18n>Views</button>
<div class="dropdown-menu shadow dropdown-menu-right" ngbDropdownMenu>
<ng-container *ngIf="!list.activeSavedViewId">
<button ngbDropdownItem *ngFor="let view of savedViewService.allViews" (click)="loadViewConfig(view)">{{view.name}}</button>
<button ngbDropdownItem *ngFor="let view of savedViewService.allViews" (click)="loadViewConfig(view.id)">{{view.name}}</button>
<div class="dropdown-divider" *ngIf="savedViewService.allViews.length > 0"></div>
</ng-container>

View File

@@ -9,20 +9,9 @@ import {
} from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import {
filter,
first,
map,
Subject,
Subscription,
switchMap,
takeUntil,
} from 'rxjs'
import { filter, first, map, Subject, switchMap, takeUntil } from 'rxjs'
import { FilterRule, isFullTextFilterRule } from 'src/app/data/filter-rule'
import {
FILTER_FULLTEXT_MORELIKE,
FILTER_RULE_TYPES,
} from 'src/app/data/filter-rule-type'
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 {
@@ -32,7 +21,10 @@ import {
import { ConsumerStatusService } from 'src/app/services/consumer-status.service'
import { DocumentListViewService } from 'src/app/services/document-list-view.service'
import {
DocumentService,
filterRulesFromQueryParams,
QueryParamsService,
} from 'src/app/services/query-params.service'
import {
DOCUMENT_SORT_FIELDS,
DOCUMENT_SORT_FIELDS_FULLTEXT,
} from 'src/app/services/rest/document.service'
@@ -49,13 +41,13 @@ import { SaveViewConfigDialogComponent } from './save-view-config-dialog/save-vi
export class DocumentListComponent implements OnInit, OnDestroy, AfterViewInit {
constructor(
public list: DocumentListViewService,
private documentService: DocumentService,
public savedViewService: SavedViewService,
public route: ActivatedRoute,
private router: Router,
private toastService: ToastService,
private modalService: NgbModal,
private consumerStatusService: ConsumerStatusService
private consumerStatusService: ConsumerStatusService,
private queryParamsService: QueryParamsService
) {}
@ViewChild('filterEditor')
@@ -83,8 +75,26 @@ export class DocumentListComponent implements OnInit, OnDestroy, AfterViewInit {
: DOCUMENT_SORT_FIELDS
}
set listSort(reverse: boolean) {
this.list.sortReverse = reverse
this.queryParamsService.sortField = this.list.sortField
this.queryParamsService.sortReverse = reverse
}
get listSort(): boolean {
return this.list.sortReverse
}
setSortField(field: string) {
this.list.sortField = field
this.queryParamsService.sortField = field
this.queryParamsService.sortReverse = this.listSort
}
onSort(event: SortEvent) {
this.list.setSort(event.column, event.reverse)
this.queryParamsService.sortField = event.column
this.queryParamsService.sortReverse = event.reverse
}
get isBulkEditing(): boolean {
@@ -109,60 +119,39 @@ export class DocumentListComponent implements OnInit, OnDestroy, AfterViewInit {
this.route.paramMap
.pipe(
filter((params) => params.has('id')), // only on saved view
filter((params) => params.has('id')), // only on saved view e.g. /view/id
switchMap((params) => {
return this.savedViewService
.getCached(+params.get('id'))
.pipe(map((view) => ({ params, view })))
.pipe(map((view) => ({ view })))
})
)
.pipe(takeUntil(this.unsubscribeNotifier))
.subscribe(({ view, params }) => {
.subscribe(({ view }) => {
if (!view) {
this.router.navigate(['404'])
return
}
this.list.activateSavedView(view)
this.list.reload()
this.queryParamsService.updateFromView(view)
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
filter(() => !this.route.snapshot.paramMap.has('id')), // only when not on /view/id
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 = []
if (queryParams.has('view')) {
// loading a saved view on /documents
this.loadViewConfig(parseInt(queryParams.get('view')))
} else {
this.list.activateSavedView(null)
this.queryParamsService.parseQueryParams(queryParams)
this.unmodifiedFilterRules = []
}
})
}
@@ -171,17 +160,7 @@ export class DocumentListComponent implements OnInit, OnDestroy, AfterViewInit {
.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,
})
this.queryParamsService.updateFilterRules(filterRules)
},
})
}
@@ -192,9 +171,15 @@ export class DocumentListComponent implements OnInit, OnDestroy, AfterViewInit {
this.unsubscribeNotifier.complete()
}
loadViewConfig(view: PaperlessSavedView) {
this.list.loadSavedView(view)
this.list.reload()
loadViewConfig(viewId: number) {
this.savedViewService
.getCached(viewId)
.pipe(first())
.subscribe((view) => {
this.list.loadSavedView(view)
this.list.reload()
this.queryParamsService.updateFromView(view)
})
}
saveViewConfig() {
@@ -282,7 +267,7 @@ export class DocumentListComponent implements OnInit, OnDestroy, AfterViewInit {
}
clickMoreLike(documentID: number) {
this.list.quickFilter([
this.queryParamsService.navigateWithFilterRules([
{ rule_type: FILTER_FULLTEXT_MORELIKE, value: documentID.toString() },
])
}

View File

@@ -3,7 +3,7 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { FILTER_CORRESPONDENT } from 'src/app/data/filter-rule-type'
import { PaperlessCorrespondent } from 'src/app/data/paperless-correspondent'
import { CustomDatePipe } from 'src/app/pipes/custom-date.pipe'
import { DocumentListViewService } from 'src/app/services/document-list-view.service'
import { QueryParamsService } from 'src/app/services/query-params.service'
import { CorrespondentService } from 'src/app/services/rest/correspondent.service'
import { ToastService } from 'src/app/services/toast.service'
import { CorrespondentEditDialogComponent } from '../../common/edit-dialog/correspondent-edit-dialog/correspondent-edit-dialog.component'
@@ -20,7 +20,7 @@ export class CorrespondentListComponent extends ManagementListComponent<Paperles
correspondentsService: CorrespondentService,
modalService: NgbModal,
toastService: ToastService,
list: DocumentListViewService,
queryParamsService: QueryParamsService,
private datePipe: CustomDatePipe
) {
super(
@@ -28,7 +28,7 @@ export class CorrespondentListComponent extends ManagementListComponent<Paperles
modalService,
CorrespondentEditDialogComponent,
toastService,
list,
queryParamsService,
FILTER_CORRESPONDENT,
$localize`correspondent`,
[

View File

@@ -2,7 +2,7 @@ import { Component } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { FILTER_DOCUMENT_TYPE } from 'src/app/data/filter-rule-type'
import { PaperlessDocumentType } from 'src/app/data/paperless-document-type'
import { DocumentListViewService } from 'src/app/services/document-list-view.service'
import { QueryParamsService } from 'src/app/services/query-params.service'
import { DocumentTypeService } from 'src/app/services/rest/document-type.service'
import { ToastService } from 'src/app/services/toast.service'
import { DocumentTypeEditDialogComponent } from '../../common/edit-dialog/document-type-edit-dialog/document-type-edit-dialog.component'
@@ -18,14 +18,14 @@ export class DocumentTypeListComponent extends ManagementListComponent<Paperless
documentTypeService: DocumentTypeService,
modalService: NgbModal,
toastService: ToastService,
list: DocumentListViewService
queryParamsService: QueryParamsService
) {
super(
documentTypeService,
modalService,
DocumentTypeEditDialogComponent,
toastService,
list,
queryParamsService,
FILTER_DOCUMENT_TYPE,
$localize`document type`,
[]

View File

@@ -18,7 +18,7 @@ import {
SortableDirective,
SortEvent,
} from 'src/app/directives/sortable.directive'
import { DocumentListViewService } from 'src/app/services/document-list-view.service'
import { QueryParamsService } from 'src/app/services/query-params.service'
import { AbstractNameFilterService } from 'src/app/services/rest/abstract-name-filter-service'
import { ToastService } from 'src/app/services/toast.service'
import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component'
@@ -42,7 +42,7 @@ export abstract class ManagementListComponent<T extends ObjectWithId>
private modalService: NgbModal,
private editDialogComponent: any,
private toastService: ToastService,
private list: DocumentListViewService,
private queryParamsService: QueryParamsService,
protected filterRuleType: number,
public typeName: string,
public extraColumns: ManagementListColumn[]
@@ -140,7 +140,7 @@ export abstract class ManagementListComponent<T extends ObjectWithId>
}
filterDocuments(object: ObjectWithId) {
this.list.quickFilter([
this.queryParamsService.navigateWithFilterRules([
{ rule_type: this.filterRuleType, value: object.id.toString() },
])
}

View File

@@ -2,7 +2,7 @@ import { Component } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { FILTER_HAS_TAGS_ALL } from 'src/app/data/filter-rule-type'
import { PaperlessTag } from 'src/app/data/paperless-tag'
import { DocumentListViewService } from 'src/app/services/document-list-view.service'
import { QueryParamsService } from 'src/app/services/query-params.service'
import { TagService } from 'src/app/services/rest/tag.service'
import { ToastService } from 'src/app/services/toast.service'
import { TagEditDialogComponent } from '../../common/edit-dialog/tag-edit-dialog/tag-edit-dialog.component'
@@ -18,14 +18,14 @@ export class TagListComponent extends ManagementListComponent<PaperlessTag> {
tagService: TagService,
modalService: NgbModal,
toastService: ToastService,
list: DocumentListViewService
queryParamsService: QueryParamsService
) {
super(
tagService,
modalService,
TagEditDialogComponent,
toastService,
list,
queryParamsService,
FILTER_HAS_TAGS_ALL,
$localize`tag`,
[