mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-07-28 18:24:38 -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:
@@ -46,6 +46,7 @@ import {
|
||||
FILTER_OWNER_ANY,
|
||||
FILTER_OWNER_DOES_NOT_INCLUDE,
|
||||
FILTER_OWNER_ISNULL,
|
||||
FILTER_CUSTOM_FIELDS,
|
||||
} from 'src/app/data/filter-rule-type'
|
||||
import { PaperlessCorrespondent } from 'src/app/data/paperless-correspondent'
|
||||
import { PaperlessDocumentType } from 'src/app/data/paperless-document-type'
|
||||
@@ -240,6 +241,18 @@ describe('FilterEditorComponent', () => {
|
||||
expect(component.textFilterTarget).toEqual('asn') // TEXT_FILTER_TARGET_ASN
|
||||
}))
|
||||
|
||||
it('should ingest text filter rules for custom fields', fakeAsync(() => {
|
||||
expect(component.textFilter).toEqual(null)
|
||||
component.filterRules = [
|
||||
{
|
||||
rule_type: FILTER_CUSTOM_FIELDS,
|
||||
value: 'foo',
|
||||
},
|
||||
]
|
||||
expect(component.textFilter).toEqual('foo')
|
||||
expect(component.textFilterTarget).toEqual('custom-fields') // TEXT_FILTER_TARGET_CUSTOM_FIELDS
|
||||
}))
|
||||
|
||||
it('should ingest text filter rules for doc asn is null', fakeAsync(() => {
|
||||
expect(component.textFilterTarget).toEqual('title-content')
|
||||
expect(component.textFilterModifier).toEqual('equals') // TEXT_FILTER_MODIFIER_EQUALS
|
||||
@@ -956,12 +969,30 @@ describe('FilterEditorComponent', () => {
|
||||
])
|
||||
}))
|
||||
|
||||
it('should convert user input to correct filter rules on full text query', fakeAsync(() => {
|
||||
it('should convert user input to correct filter rules on custom fields query', fakeAsync(() => {
|
||||
component.textFilterInput.nativeElement.value = 'foo'
|
||||
component.textFilterInput.nativeElement.dispatchEvent(new Event('input'))
|
||||
const textFieldTargetDropdown = fixture.debugElement.queryAll(
|
||||
By.directive(NgbDropdownItem)
|
||||
)[3]
|
||||
textFieldTargetDropdown.triggerEventHandler('click') // TEXT_FILTER_TARGET_CUSTOM_FIELDS
|
||||
fixture.detectChanges()
|
||||
tick(400)
|
||||
expect(component.textFilterTarget).toEqual('custom-fields')
|
||||
expect(component.filterRules).toEqual([
|
||||
{
|
||||
rule_type: FILTER_CUSTOM_FIELDS,
|
||||
value: 'foo',
|
||||
},
|
||||
])
|
||||
}))
|
||||
|
||||
it('should convert user input to correct filter rules on full text query', fakeAsync(() => {
|
||||
component.textFilterInput.nativeElement.value = 'foo'
|
||||
component.textFilterInput.nativeElement.dispatchEvent(new Event('input'))
|
||||
const textFieldTargetDropdown = fixture.debugElement.queryAll(
|
||||
By.directive(NgbDropdownItem)
|
||||
)[4]
|
||||
textFieldTargetDropdown.triggerEventHandler('click') // TEXT_FILTER_TARGET_ASN
|
||||
fixture.detectChanges()
|
||||
tick(400)
|
||||
|
@@ -48,6 +48,7 @@ import {
|
||||
FILTER_OWNER_DOES_NOT_INCLUDE,
|
||||
FILTER_OWNER_ISNULL,
|
||||
FILTER_OWNER_ANY,
|
||||
FILTER_CUSTOM_FIELDS,
|
||||
} from 'src/app/data/filter-rule-type'
|
||||
import {
|
||||
FilterableDropdownSelectionModel,
|
||||
@@ -74,6 +75,7 @@ const TEXT_FILTER_TARGET_TITLE_CONTENT = 'title-content'
|
||||
const TEXT_FILTER_TARGET_ASN = 'asn'
|
||||
const TEXT_FILTER_TARGET_FULLTEXT_QUERY = 'fulltext-query'
|
||||
const TEXT_FILTER_TARGET_FULLTEXT_MORELIKE = 'fulltext-morelike'
|
||||
const TEXT_FILTER_TARGET_CUSTOM_FIELDS = 'custom-fields'
|
||||
|
||||
const TEXT_FILTER_MODIFIER_EQUALS = 'equals'
|
||||
const TEXT_FILTER_MODIFIER_NULL = 'is null'
|
||||
@@ -204,6 +206,10 @@ export class FilterEditorComponent implements OnInit, OnDestroy {
|
||||
name: $localize`Title & content`,
|
||||
},
|
||||
{ id: TEXT_FILTER_TARGET_ASN, name: $localize`ASN` },
|
||||
{
|
||||
id: TEXT_FILTER_TARGET_CUSTOM_FIELDS,
|
||||
name: $localize`Custom fields`,
|
||||
},
|
||||
{
|
||||
id: TEXT_FILTER_TARGET_FULLTEXT_QUERY,
|
||||
name: $localize`Advanced search`,
|
||||
@@ -321,6 +327,10 @@ export class FilterEditorComponent implements OnInit, OnDestroy {
|
||||
this._textFilter = rule.value
|
||||
this.textFilterTarget = TEXT_FILTER_TARGET_ASN
|
||||
break
|
||||
case FILTER_CUSTOM_FIELDS:
|
||||
this._textFilter = rule.value
|
||||
this.textFilterTarget = TEXT_FILTER_TARGET_CUSTOM_FIELDS
|
||||
break
|
||||
case FILTER_FULLTEXT_QUERY:
|
||||
let allQueryArgs = rule.value.split(',')
|
||||
let textQueryArgs = []
|
||||
@@ -552,6 +562,15 @@ export class FilterEditorComponent implements OnInit, OnDestroy {
|
||||
})
|
||||
}
|
||||
}
|
||||
if (
|
||||
this._textFilter &&
|
||||
this.textFilterTarget == TEXT_FILTER_TARGET_CUSTOM_FIELDS
|
||||
) {
|
||||
filterRules.push({
|
||||
rule_type: FILTER_CUSTOM_FIELDS,
|
||||
value: this._textFilter,
|
||||
})
|
||||
}
|
||||
if (
|
||||
this._textFilter &&
|
||||
this.textFilterTarget == TEXT_FILTER_TARGET_FULLTEXT_QUERY
|
||||
|
Reference in New Issue
Block a user