mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-09-01 01:46:16 +00:00
Feature: customizable fields display for documents, saved views & dashboard widgets (#6439)
This commit is contained in:
@@ -6,23 +6,38 @@ import {
|
||||
QueryList,
|
||||
ViewChildren,
|
||||
} from '@angular/core'
|
||||
import { Params, Router } from '@angular/router'
|
||||
import { Router } from '@angular/router'
|
||||
import { Subject, takeUntil } from 'rxjs'
|
||||
import { Document } from 'src/app/data/document'
|
||||
import {
|
||||
DEFAULT_DASHBOARD_DISPLAY_FIELDS,
|
||||
DEFAULT_DASHBOARD_VIEW_PAGE_SIZE,
|
||||
DEFAULT_DISPLAY_FIELDS,
|
||||
DisplayField,
|
||||
DisplayMode,
|
||||
Document,
|
||||
} from 'src/app/data/document'
|
||||
import { SavedView } from 'src/app/data/saved-view'
|
||||
import { ConsumerStatusService } from 'src/app/services/consumer-status.service'
|
||||
import { DocumentService } from 'src/app/services/rest/document.service'
|
||||
import { Tag } from 'src/app/data/tag'
|
||||
import {
|
||||
FILTER_CORRESPONDENT,
|
||||
FILTER_DOCUMENT_TYPE,
|
||||
FILTER_FULLTEXT_MORELIKE,
|
||||
FILTER_HAS_TAGS_ALL,
|
||||
FILTER_STORAGE_PATH,
|
||||
} from 'src/app/data/filter-rule-type'
|
||||
import { OpenDocumentsService } from 'src/app/services/open-documents.service'
|
||||
import { DocumentListViewService } from 'src/app/services/document-list-view.service'
|
||||
import { ComponentWithPermissions } from 'src/app/components/with-permissions/with-permissions.component'
|
||||
import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { queryParamsFromFilterRules } from 'src/app/utils/query-params'
|
||||
import { PermissionsService } from 'src/app/services/permissions.service'
|
||||
import {
|
||||
PermissionAction,
|
||||
PermissionType,
|
||||
PermissionsService,
|
||||
} from 'src/app/services/permissions.service'
|
||||
import { CustomFieldsService } from 'src/app/services/rest/custom-fields.service'
|
||||
import { CustomField, CustomFieldDataType } from 'src/app/data/custom-field'
|
||||
import { SettingsService } from 'src/app/services/settings.service'
|
||||
|
||||
@Component({
|
||||
selector: 'pngx-saved-view-widget',
|
||||
@@ -33,8 +48,14 @@ export class SavedViewWidgetComponent
|
||||
extends ComponentWithPermissions
|
||||
implements OnInit, OnDestroy
|
||||
{
|
||||
public DisplayMode = DisplayMode
|
||||
public DisplayField = DisplayField
|
||||
public CustomFieldDataType = CustomFieldDataType
|
||||
|
||||
loading: boolean = true
|
||||
|
||||
private customFields: CustomField[] = []
|
||||
|
||||
constructor(
|
||||
private documentService: DocumentService,
|
||||
private router: Router,
|
||||
@@ -42,7 +63,9 @@ export class SavedViewWidgetComponent
|
||||
private consumerStatusService: ConsumerStatusService,
|
||||
public openDocumentsService: OpenDocumentsService,
|
||||
public documentListViewService: DocumentListViewService,
|
||||
public permissionsService: PermissionsService
|
||||
public permissionsService: PermissionsService,
|
||||
private settingsService: SettingsService,
|
||||
private customFieldService: CustomFieldsService
|
||||
) {
|
||||
super()
|
||||
}
|
||||
@@ -60,14 +83,44 @@ export class SavedViewWidgetComponent
|
||||
mouseOnPreview = false
|
||||
popoverHidden = true
|
||||
|
||||
displayMode: DisplayMode
|
||||
|
||||
displayFields: DisplayField[] = DEFAULT_DASHBOARD_DISPLAY_FIELDS
|
||||
|
||||
ngOnInit(): void {
|
||||
this.reload()
|
||||
this.displayMode = this.savedView.display_mode ?? DisplayMode.TABLE
|
||||
this.consumerStatusService
|
||||
.onDocumentConsumptionFinished()
|
||||
.pipe(takeUntil(this.unsubscribeNotifier))
|
||||
.subscribe(() => {
|
||||
this.reload()
|
||||
})
|
||||
|
||||
if (
|
||||
this.permissionsService.currentUserCan(
|
||||
PermissionAction.View,
|
||||
PermissionType.CustomField
|
||||
)
|
||||
) {
|
||||
this.customFieldService
|
||||
.listAll()
|
||||
.pipe(takeUntil(this.unsubscribeNotifier))
|
||||
.subscribe((customFields) => {
|
||||
this.customFields = customFields.results
|
||||
})
|
||||
}
|
||||
|
||||
if (this.savedView.display_fields) {
|
||||
this.displayFields = this.savedView.display_fields
|
||||
}
|
||||
|
||||
// filter by perms etc
|
||||
this.displayFields = this.displayFields.filter(
|
||||
(field) =>
|
||||
this.settingsService.allDisplayFields.find((f) => f.id === field) !==
|
||||
undefined
|
||||
)
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
@@ -80,7 +133,7 @@ export class SavedViewWidgetComponent
|
||||
this.documentService
|
||||
.listFiltered(
|
||||
1,
|
||||
10,
|
||||
this.savedView.page_size ?? DEFAULT_DASHBOARD_VIEW_PAGE_SIZE,
|
||||
this.savedView.sort_field,
|
||||
this.savedView.sort_reverse,
|
||||
this.savedView.filter_rules,
|
||||
@@ -103,15 +156,52 @@ export class SavedViewWidgetComponent
|
||||
}
|
||||
}
|
||||
|
||||
clickTag(tag: Tag, event: MouseEvent) {
|
||||
event.preventDefault()
|
||||
event.stopImmediatePropagation()
|
||||
clickTag(tagID: number, event: MouseEvent = null) {
|
||||
event?.preventDefault()
|
||||
event?.stopImmediatePropagation()
|
||||
|
||||
this.list.quickFilter([
|
||||
{ rule_type: FILTER_HAS_TAGS_ALL, value: tag.id.toString() },
|
||||
{ rule_type: FILTER_HAS_TAGS_ALL, value: tagID.toString() },
|
||||
])
|
||||
}
|
||||
|
||||
clickCorrespondent(correspondentId: number, event: MouseEvent = null) {
|
||||
event?.preventDefault()
|
||||
event?.stopImmediatePropagation()
|
||||
|
||||
this.list.quickFilter([
|
||||
{ rule_type: FILTER_CORRESPONDENT, value: correspondentId.toString() },
|
||||
])
|
||||
}
|
||||
|
||||
clickDocType(docTypeId: number, event: MouseEvent = null) {
|
||||
event?.preventDefault()
|
||||
event?.stopImmediatePropagation()
|
||||
|
||||
this.list.quickFilter([
|
||||
{ rule_type: FILTER_DOCUMENT_TYPE, value: docTypeId.toString() },
|
||||
])
|
||||
}
|
||||
|
||||
clickStoragePath(storagePathId: number, event: MouseEvent = null) {
|
||||
event?.preventDefault()
|
||||
event?.stopImmediatePropagation()
|
||||
|
||||
this.list.quickFilter([
|
||||
{ rule_type: FILTER_STORAGE_PATH, value: storagePathId.toString() },
|
||||
])
|
||||
}
|
||||
|
||||
clickMoreLike(documentID: number) {
|
||||
this.list.quickFilter([
|
||||
{ rule_type: FILTER_FULLTEXT_MORELIKE, value: documentID.toString() },
|
||||
])
|
||||
}
|
||||
|
||||
openDocumentDetail(document: Document) {
|
||||
this.router.navigate(['documents', document.id])
|
||||
}
|
||||
|
||||
getPreviewUrl(document: Document): string {
|
||||
return this.documentService.getPreviewUrl(document.id)
|
||||
}
|
||||
@@ -161,14 +251,11 @@ export class SavedViewWidgetComponent
|
||||
}, 300)
|
||||
}
|
||||
|
||||
getCorrespondentQueryParams(correspondentId: number): Params {
|
||||
return correspondentId !== undefined
|
||||
? queryParamsFromFilterRules([
|
||||
{
|
||||
rule_type: FILTER_CORRESPONDENT,
|
||||
value: correspondentId.toString(),
|
||||
},
|
||||
])
|
||||
: null
|
||||
public getColumnTitle(field: DisplayField): string {
|
||||
if (field.startsWith(DisplayField.CUSTOM_FIELD)) {
|
||||
const id = field.split('_')[2]
|
||||
return this.customFields.find((f) => f.id === parseInt(id))?.name
|
||||
}
|
||||
return DEFAULT_DISPLAY_FIELDS.find((f) => f.id === field)?.name
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user