mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-07-30 18:27:45 -05:00
Feature: Implement custom fields for documents (#4502)
Adds custom fields of certain data types, attachable to documents and searchable Co-Authored-By: Trenton H <797416+stumpylog@users.noreply.github.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core'
|
||||
import { FormControl, FormGroup } from '@angular/forms'
|
||||
import { FormArray, FormControl, FormGroup } from '@angular/forms'
|
||||
import { ActivatedRoute, Router } from '@angular/router'
|
||||
import {
|
||||
NgbDateStruct,
|
||||
@@ -63,7 +63,12 @@ import { EditDialogMode } from '../common/edit-dialog/edit-dialog.component'
|
||||
import { ObjectWithId } from 'src/app/data/object-with-id'
|
||||
import { FilterRule } from 'src/app/data/filter-rule'
|
||||
import { ISODateAdapter } from 'src/app/utils/ngb-iso-date-adapter'
|
||||
import { ShareLinksDropdownComponent } from '../common/share-links-dropdown/share-links-dropdown.component'
|
||||
import {
|
||||
PaperlessCustomField,
|
||||
PaperlessCustomFieldDataType,
|
||||
} from 'src/app/data/paperless-custom-field'
|
||||
import { PaperlessCustomFieldInstance } from 'src/app/data/paperless-custom-field-instance'
|
||||
import { CustomFieldsService } from 'src/app/services/rest/custom-fields.service'
|
||||
|
||||
enum DocumentDetailNavIDs {
|
||||
Details = 1,
|
||||
@@ -120,6 +125,7 @@ export class DocumentDetailComponent
|
||||
archive_serial_number: new FormControl(),
|
||||
tags: new FormControl([]),
|
||||
permissions_form: new FormControl(null),
|
||||
custom_fields: new FormArray([]),
|
||||
})
|
||||
|
||||
previewCurrentPage: number = 1
|
||||
@@ -135,6 +141,9 @@ export class DocumentDetailComponent
|
||||
|
||||
ogDate: Date
|
||||
|
||||
customFields: PaperlessCustomField[]
|
||||
public readonly PaperlessCustomFieldDataType = PaperlessCustomFieldDataType
|
||||
|
||||
@ViewChild('nav') nav: NgbNav
|
||||
@ViewChild('pdfPreview') set pdfPreview(element) {
|
||||
// this gets called when compontent added or removed from DOM
|
||||
@@ -166,6 +175,7 @@ export class DocumentDetailComponent
|
||||
private storagePathService: StoragePathService,
|
||||
private permissionsService: PermissionsService,
|
||||
private userService: UserService,
|
||||
private customFieldsService: CustomFieldsService,
|
||||
private http: HttpClient
|
||||
) {
|
||||
super()
|
||||
@@ -232,6 +242,8 @@ export class DocumentDetailComponent
|
||||
.pipe(first(), takeUntil(this.unsubscribeNotifier))
|
||||
.subscribe((result) => (this.users = result.results))
|
||||
|
||||
this.getCustomFields()
|
||||
|
||||
this.route.paramMap
|
||||
.pipe(
|
||||
takeUntil(this.unsubscribeNotifier),
|
||||
@@ -324,6 +336,7 @@ export class DocumentDetailComponent
|
||||
owner: doc.owner,
|
||||
set_permissions: doc.permissions,
|
||||
},
|
||||
custom_fields: doc.custom_fields,
|
||||
})
|
||||
|
||||
this.isDirty$ = dirtyCheck(
|
||||
@@ -385,6 +398,8 @@ export class DocumentDetailComponent
|
||||
updateComponent(doc: PaperlessDocument) {
|
||||
this.document = doc
|
||||
this.requiresPassword = false
|
||||
// this.customFields = doc.custom_fields.concat([])
|
||||
this.updateFormForCustomFields()
|
||||
this.documentsService
|
||||
.getMetadata(doc.id)
|
||||
.pipe(first())
|
||||
@@ -433,6 +448,10 @@ export class DocumentDetailComponent
|
||||
if (!this.userCanEdit) this.documentForm.disable()
|
||||
}
|
||||
|
||||
get customFieldFormFields(): FormArray {
|
||||
return this.documentForm.get('custom_fields') as FormArray
|
||||
}
|
||||
|
||||
createDocumentType(newName: string) {
|
||||
var modal = this.modalService.open(DocumentTypeEditDialogComponent, {
|
||||
backdrop: 'static',
|
||||
@@ -510,6 +529,7 @@ export class DocumentDetailComponent
|
||||
set_permissions: doc.permissions,
|
||||
}
|
||||
this.title = doc.title
|
||||
this.updateFormForCustomFields()
|
||||
this.documentForm.patchValue(doc)
|
||||
this.openDocumentService.setDirty(doc, false)
|
||||
},
|
||||
@@ -533,6 +553,7 @@ export class DocumentDetailComponent
|
||||
close && this.close()
|
||||
this.networkActive = false
|
||||
this.error = null
|
||||
this.openDocumentService.refreshDocument(this.documentId)
|
||||
},
|
||||
error: (error) => {
|
||||
this.networkActive = false
|
||||
@@ -819,4 +840,61 @@ export class DocumentDetailComponent
|
||||
|
||||
this.documentListViewService.quickFilter(filterRules)
|
||||
}
|
||||
|
||||
private getCustomFields() {
|
||||
this.customFieldsService
|
||||
.listAll()
|
||||
.pipe(first(), takeUntil(this.unsubscribeNotifier))
|
||||
.subscribe((result) => (this.customFields = result.results))
|
||||
}
|
||||
|
||||
public refreshCustomFields() {
|
||||
this.customFieldsService.clearCache()
|
||||
this.getCustomFields()
|
||||
}
|
||||
|
||||
public getCustomFieldFromInstance(
|
||||
instance: PaperlessCustomFieldInstance
|
||||
): PaperlessCustomField {
|
||||
return this.customFields?.find((f) => f.id === instance.field)
|
||||
}
|
||||
|
||||
public getCustomFieldError(index: number) {
|
||||
const fieldError = this.error?.custom_fields?.[index]
|
||||
return fieldError?.['non_field_errors'] ?? fieldError?.['value']
|
||||
}
|
||||
|
||||
private updateFormForCustomFields(emitEvent: boolean = false) {
|
||||
this.customFieldFormFields.clear({ emitEvent: false })
|
||||
this.document.custom_fields?.forEach((fieldInstance) => {
|
||||
this.customFieldFormFields.push(
|
||||
new FormGroup({
|
||||
field: new FormControl(
|
||||
this.getCustomFieldFromInstance(fieldInstance)?.id
|
||||
),
|
||||
value: new FormControl(fieldInstance.value),
|
||||
}),
|
||||
{ emitEvent }
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
public addField(field: PaperlessCustomField) {
|
||||
this.document.custom_fields.push({
|
||||
field: field.id,
|
||||
value: null,
|
||||
document: this.documentId,
|
||||
created: new Date(),
|
||||
})
|
||||
this.updateFormForCustomFields(true)
|
||||
}
|
||||
|
||||
public removeField(fieldInstance: PaperlessCustomFieldInstance) {
|
||||
this.document.custom_fields.splice(
|
||||
this.document.custom_fields.indexOf(fieldInstance),
|
||||
1
|
||||
)
|
||||
this.updateFormForCustomFields(true)
|
||||
this.documentForm.updateValueAndValidity()
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user