mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-07-28 18:24:38 -05:00
Refactor query params service
This commit is contained in:
@@ -10,13 +10,14 @@ import { PaperlessDocument } from '../data/paperless-document'
|
||||
import { PaperlessSavedView } from '../data/paperless-saved-view'
|
||||
import { SETTINGS_KEYS } from '../data/paperless-uisettings'
|
||||
import { DOCUMENT_LIST_SERVICE } from '../data/storage-keys'
|
||||
import { generateParams, parseQueryParams } from '../utils/query-params'
|
||||
import { DocumentService, DOCUMENT_SORT_FIELDS } from './rest/document.service'
|
||||
import { SettingsService } from './settings.service'
|
||||
|
||||
/**
|
||||
* Captures the current state of the list view.
|
||||
*/
|
||||
interface ListViewState {
|
||||
export interface ListViewState {
|
||||
/**
|
||||
* Title of the document list view. Either "Documents" (localized) or the name of a saved view.
|
||||
*/
|
||||
@@ -32,7 +33,7 @@ interface ListViewState {
|
||||
/**
|
||||
* Total amount of documents with the current filter rules. Used to calculate the number of pages.
|
||||
*/
|
||||
collectionSize: number
|
||||
collectionSize?: number
|
||||
|
||||
/**
|
||||
* Currently selected sort field.
|
||||
@@ -85,6 +86,32 @@ export class DocumentListViewService {
|
||||
return this.activeListViewState.title
|
||||
}
|
||||
|
||||
constructor(
|
||||
private documentService: DocumentService,
|
||||
private settings: SettingsService,
|
||||
private router: Router
|
||||
) {
|
||||
let documentListViewConfigJson = localStorage.getItem(
|
||||
DOCUMENT_LIST_SERVICE.CURRENT_VIEW_CONFIG
|
||||
)
|
||||
if (documentListViewConfigJson) {
|
||||
try {
|
||||
let savedState: ListViewState = JSON.parse(documentListViewConfigJson)
|
||||
// Remove null elements from the restored state
|
||||
Object.keys(savedState).forEach((k) => {
|
||||
if (savedState[k] == null) {
|
||||
delete savedState[k]
|
||||
}
|
||||
})
|
||||
//only use restored state attributes instead of defaults if they are not null
|
||||
let newState = Object.assign(this.defaultListViewState(), savedState)
|
||||
this.listViewStates.set(null, newState)
|
||||
} catch (e) {
|
||||
localStorage.removeItem(DOCUMENT_LIST_SERVICE.CURRENT_VIEW_CONFIG)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private defaultListViewState(): ListViewState {
|
||||
return {
|
||||
title: null,
|
||||
@@ -122,20 +149,36 @@ export class DocumentListViewService {
|
||||
if (closeCurrentView) {
|
||||
this._activeSavedViewId = null
|
||||
}
|
||||
|
||||
this.activeListViewState.filterRules = cloneFilterRules(view.filter_rules)
|
||||
this.activeListViewState.sortField = view.sort_field
|
||||
this.activeListViewState.sortReverse = view.sort_reverse
|
||||
if (this._activeSavedViewId) {
|
||||
this.activeListViewState.title = view.name
|
||||
}
|
||||
|
||||
this.reduceSelectionToFilter()
|
||||
|
||||
if (!this.router.routerState.snapshot.url.includes('/view/')) {
|
||||
this.router.navigate([], {
|
||||
queryParams: { view: view.id },
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
reload(onFinish?) {
|
||||
loadFromQueryParams(queryParams) {
|
||||
let newState: ListViewState = parseQueryParams(queryParams)
|
||||
this.activeListViewState.filterRules = newState.filterRules
|
||||
this.activeListViewState.sortField = newState.sortField
|
||||
this.activeListViewState.sortReverse = newState.sortReverse
|
||||
this.activeListViewState.currentPage = newState.currentPage
|
||||
this.reload(null, false)
|
||||
}
|
||||
|
||||
reload(onFinish?, updateQueryParams: boolean = true) {
|
||||
this.isReloading = true
|
||||
this.error = null
|
||||
let activeListViewState = this.activeListViewState
|
||||
|
||||
this.documentService
|
||||
.listFiltered(
|
||||
activeListViewState.currentPage,
|
||||
@@ -149,6 +192,19 @@ export class DocumentListViewService {
|
||||
this.isReloading = false
|
||||
activeListViewState.collectionSize = result.count
|
||||
activeListViewState.documents = result.results
|
||||
|
||||
if (updateQueryParams && !this._activeSavedViewId) {
|
||||
let base = ['/documents']
|
||||
this.router.navigate(base, {
|
||||
queryParams: generateParams(
|
||||
activeListViewState.filterRules,
|
||||
activeListViewState.sortField,
|
||||
activeListViewState.sortReverse,
|
||||
activeListViewState.currentPage
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
if (onFinish) {
|
||||
onFinish()
|
||||
}
|
||||
@@ -191,6 +247,7 @@ export class DocumentListViewService {
|
||||
) {
|
||||
this.activeListViewState.sortField = 'created'
|
||||
}
|
||||
this._activeSavedViewId = null
|
||||
this.activeListViewState.filterRules = filterRules
|
||||
this.reload()
|
||||
this.reduceSelectionToFilter()
|
||||
@@ -202,6 +259,7 @@ export class DocumentListViewService {
|
||||
}
|
||||
|
||||
set sortField(field: string) {
|
||||
this._activeSavedViewId = null
|
||||
this.activeListViewState.sortField = field
|
||||
this.reload()
|
||||
this.saveDocumentListView()
|
||||
@@ -212,6 +270,7 @@ export class DocumentListViewService {
|
||||
}
|
||||
|
||||
set sortReverse(reverse: boolean) {
|
||||
this._activeSavedViewId = null
|
||||
this.activeListViewState.sortReverse = reverse
|
||||
this.reload()
|
||||
this.saveDocumentListView()
|
||||
@@ -237,6 +296,8 @@ export class DocumentListViewService {
|
||||
}
|
||||
|
||||
set currentPage(page: number) {
|
||||
if (this.activeListViewState.currentPage == page) return
|
||||
this._activeSavedViewId = null
|
||||
this.activeListViewState.currentPage = page
|
||||
this.reload()
|
||||
this.saveDocumentListView()
|
||||
@@ -273,6 +334,10 @@ export class DocumentListViewService {
|
||||
}
|
||||
}
|
||||
|
||||
quickFilter(filterRules: FilterRule[]) {
|
||||
this.filterRules = filterRules
|
||||
}
|
||||
|
||||
getLastPage(): number {
|
||||
return Math.ceil(this.collectionSize / this.currentPageSize)
|
||||
}
|
||||
@@ -431,29 +496,4 @@ export class DocumentListViewService {
|
||||
documentIndexInCurrentView(documentID: number): number {
|
||||
return this.documents.map((d) => d.id).indexOf(documentID)
|
||||
}
|
||||
|
||||
constructor(
|
||||
private documentService: DocumentService,
|
||||
private settings: SettingsService
|
||||
) {
|
||||
let documentListViewConfigJson = localStorage.getItem(
|
||||
DOCUMENT_LIST_SERVICE.CURRENT_VIEW_CONFIG
|
||||
)
|
||||
if (documentListViewConfigJson) {
|
||||
try {
|
||||
let savedState: ListViewState = JSON.parse(documentListViewConfigJson)
|
||||
// Remove null elements from the restored state
|
||||
Object.keys(savedState).forEach((k) => {
|
||||
if (savedState[k] == null) {
|
||||
delete savedState[k]
|
||||
}
|
||||
})
|
||||
//only use restored state attributes instead of defaults if they are not null
|
||||
let newState = Object.assign(this.defaultListViewState(), savedState)
|
||||
this.listViewStates.set(null, newState)
|
||||
} catch (e) {
|
||||
localStorage.removeItem(DOCUMENT_LIST_SERVICE.CURRENT_VIEW_CONFIG)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,163 +0,0 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { ParamMap, Params, Router } from '@angular/router'
|
||||
import { FilterRule } from '../data/filter-rule'
|
||||
import { FilterRuleType, FILTER_RULE_TYPES } from '../data/filter-rule-type'
|
||||
import { PaperlessSavedView } from '../data/paperless-saved-view'
|
||||
import { DocumentListViewService } from './document-list-view.service'
|
||||
|
||||
const SORT_FIELD_PARAMETER = 'sort'
|
||||
const SORT_REVERSE_PARAMETER = 'reverse'
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class QueryParamsService {
|
||||
constructor(private router: Router, private list: DocumentListViewService) {}
|
||||
|
||||
private filterParams: Params = {}
|
||||
private sortParams: Params = {}
|
||||
|
||||
updateFilterRules(
|
||||
filterRules: FilterRule[],
|
||||
updateQueryParams: boolean = true
|
||||
) {
|
||||
this.filterParams = filterRulesToQueryParams(filterRules)
|
||||
if (updateQueryParams) this.updateQueryParams()
|
||||
}
|
||||
|
||||
set sortField(field: string) {
|
||||
this.sortParams[SORT_FIELD_PARAMETER] = field
|
||||
this.updateQueryParams()
|
||||
}
|
||||
|
||||
set sortReverse(reverse: boolean) {
|
||||
if (!reverse) this.sortParams[SORT_REVERSE_PARAMETER] = undefined
|
||||
else this.sortParams[SORT_REVERSE_PARAMETER] = reverse
|
||||
this.updateQueryParams()
|
||||
}
|
||||
|
||||
get params(): Params {
|
||||
return {
|
||||
...this.sortParams,
|
||||
...this.filterParams,
|
||||
}
|
||||
}
|
||||
|
||||
private updateQueryParams() {
|
||||
// if we were on a saved view we navigate 'away' to /documents
|
||||
let base = []
|
||||
if (this.router.routerState.snapshot.url.includes('/view/'))
|
||||
base = ['/documents']
|
||||
|
||||
this.router.navigate(base, {
|
||||
queryParams: this.params,
|
||||
})
|
||||
}
|
||||
|
||||
public parseQueryParams(queryParams: ParamMap) {
|
||||
let filterRules = filterRulesFromQueryParams(queryParams)
|
||||
if (
|
||||
filterRules.length ||
|
||||
queryParams.has(SORT_FIELD_PARAMETER) ||
|
||||
queryParams.has(SORT_REVERSE_PARAMETER)
|
||||
) {
|
||||
this.list.filterRules = filterRules
|
||||
this.list.sortField = queryParams.get(SORT_FIELD_PARAMETER)
|
||||
this.list.sortReverse =
|
||||
queryParams.has(SORT_REVERSE_PARAMETER) ||
|
||||
(!queryParams.has(SORT_FIELD_PARAMETER) &&
|
||||
!queryParams.has(SORT_REVERSE_PARAMETER))
|
||||
this.list.reload()
|
||||
} else if (
|
||||
filterRules.length == 0 &&
|
||||
!queryParams.has(SORT_FIELD_PARAMETER)
|
||||
) {
|
||||
// this is navigating to /documents so we need to update the params from the list
|
||||
this.updateFilterRules(this.list.filterRules, false)
|
||||
this.sortParams[SORT_FIELD_PARAMETER] = this.list.sortField
|
||||
this.sortParams[SORT_REVERSE_PARAMETER] = this.list.sortReverse
|
||||
this.router.navigate([], {
|
||||
queryParams: this.params,
|
||||
replaceUrl: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
updateFromView(view: PaperlessSavedView) {
|
||||
if (!this.router.routerState.snapshot.url.includes('/view/')) {
|
||||
// navigation for /documents?view=
|
||||
this.router.navigate([], {
|
||||
queryParams: { view: view.id },
|
||||
})
|
||||
}
|
||||
// make sure params are up-to-date
|
||||
this.updateFilterRules(view.filter_rules, false)
|
||||
this.sortParams[SORT_FIELD_PARAMETER] = this.list.sortField
|
||||
this.sortParams[SORT_REVERSE_PARAMETER] = this.list.sortReverse
|
||||
}
|
||||
|
||||
navigateWithFilterRules(filterRules: FilterRule[]) {
|
||||
this.updateFilterRules(filterRules)
|
||||
this.router.navigate(['/documents'], {
|
||||
queryParams: this.params,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function filterRulesToQueryParams(filterRules: FilterRule[]): Object {
|
||||
if (filterRules) {
|
||||
let params = {}
|
||||
for (let rule of filterRules) {
|
||||
let ruleType = FILTER_RULE_TYPES.find((t) => t.id == rule.rule_type)
|
||||
if (ruleType.multi) {
|
||||
params[ruleType.filtervar] = params[ruleType.filtervar]
|
||||
? params[ruleType.filtervar] + ',' + rule.value
|
||||
: rule.value
|
||||
} else if (ruleType.isnull_filtervar && rule.value == null) {
|
||||
params[ruleType.isnull_filtervar] = true
|
||||
} else {
|
||||
params[ruleType.filtervar] = rule.value
|
||||
}
|
||||
}
|
||||
return params
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export function filterRulesFromQueryParams(queryParams: ParamMap) {
|
||||
const allFilterRuleQueryParams: string[] = FILTER_RULE_TYPES.map(
|
||||
(rt) => rt.filtervar
|
||||
)
|
||||
.concat(FILTER_RULE_TYPES.map((rt) => rt.isnull_filtervar))
|
||||
.filter((rt) => rt !== undefined)
|
||||
|
||||
// transform query params to filter rules
|
||||
let filterRulesFromQueryParams: FilterRule[] = []
|
||||
allFilterRuleQueryParams
|
||||
.filter((frqp) => queryParams.has(frqp))
|
||||
.forEach((filterQueryParamName) => {
|
||||
const rule_type: FilterRuleType = FILTER_RULE_TYPES.find(
|
||||
(rt) =>
|
||||
rt.filtervar == filterQueryParamName ||
|
||||
rt.isnull_filtervar == filterQueryParamName
|
||||
)
|
||||
const isNullRuleType = rule_type.isnull_filtervar == filterQueryParamName
|
||||
const valueURIComponent: string = queryParams.get(filterQueryParamName)
|
||||
const filterQueryParamValues: string[] = rule_type.multi
|
||||
? valueURIComponent.split(',')
|
||||
: [valueURIComponent]
|
||||
|
||||
filterRulesFromQueryParams = filterRulesFromQueryParams.concat(
|
||||
// map all values to filter rules
|
||||
filterQueryParamValues.map((val) => {
|
||||
return {
|
||||
rule_type: rule_type.id,
|
||||
value: isNullRuleType ? null : val,
|
||||
}
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
return filterRulesFromQueryParams
|
||||
}
|
@@ -11,7 +11,7 @@ import { CorrespondentService } from './correspondent.service'
|
||||
import { DocumentTypeService } from './document-type.service'
|
||||
import { TagService } from './tag.service'
|
||||
import { PaperlessDocumentSuggestions } from 'src/app/data/paperless-document-suggestions'
|
||||
import { filterRulesToQueryParams } from '../query-params.service'
|
||||
import { queryParamsFromFilterRules } from '../../utils/query-params'
|
||||
import { StoragePathService } from './storage-path.service'
|
||||
|
||||
export const DOCUMENT_SORT_FIELDS = [
|
||||
@@ -91,7 +91,7 @@ export class DocumentService extends AbstractPaperlessService<PaperlessDocument>
|
||||
pageSize,
|
||||
sortField,
|
||||
sortReverse,
|
||||
Object.assign(extraParams, filterRulesToQueryParams(filterRules))
|
||||
Object.assign(extraParams, queryParamsFromFilterRules(filterRules))
|
||||
).pipe(
|
||||
map((results) => {
|
||||
results.results.forEach((doc) => this.addObservablesToDocument(doc))
|
||||
|
Reference in New Issue
Block a user