Update frontend for new custom_fields API spec
This commit is contained in:
parent
99d1de543c
commit
59a08ff2a2
@ -92,7 +92,7 @@ describe('CustomFieldsDropdownComponent', () => {
|
||||
CustomFieldsDropdownComponent.prototype as any,
|
||||
'updateUnusedFields'
|
||||
)
|
||||
component.existingFields = [{ field: fields[1] } as any]
|
||||
component.existingFields = [{ field: fields[1].id } as any]
|
||||
component.onOpenClose()
|
||||
expect(updateSpy).toHaveBeenCalled()
|
||||
expect(component.unusedFields).toEqual([fields[0]])
|
||||
|
@ -34,7 +34,10 @@ export class CustomFieldsDropdownComponent implements OnDestroy {
|
||||
existingFields: PaperlessCustomFieldInstance[] = []
|
||||
|
||||
@Output()
|
||||
added = new EventEmitter()
|
||||
added: EventEmitter<PaperlessCustomField> = new EventEmitter()
|
||||
|
||||
@Output()
|
||||
created: EventEmitter<PaperlessCustomField> = new EventEmitter()
|
||||
|
||||
private customFields: PaperlessCustomField[] = []
|
||||
public unusedFields: PaperlessCustomField[]
|
||||
@ -84,9 +87,18 @@ export class CustomFieldsDropdownComponent implements OnDestroy {
|
||||
})
|
||||
}
|
||||
|
||||
public getCustomFieldFromInstance(
|
||||
instance: PaperlessCustomFieldInstance
|
||||
): PaperlessCustomField {
|
||||
return this.customFields.find((f) => f.id === instance.field)
|
||||
}
|
||||
|
||||
private updateUnusedFields() {
|
||||
this.unusedFields = this.customFields.filter(
|
||||
(f) => !this.existingFields?.find((e) => e.field.id === f.id)
|
||||
(f) =>
|
||||
!this.existingFields?.find(
|
||||
(e) => this.getCustomFieldFromInstance(e)?.id === f.id
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@ -108,6 +120,7 @@ export class CustomFieldsDropdownComponent implements OnDestroy {
|
||||
this.toastService.showInfo($localize`Saved field "${newField.name}".`)
|
||||
this.customFieldsService.clearCache()
|
||||
this.getFields()
|
||||
this.created.emit(newField)
|
||||
})
|
||||
modal.componentInstance.failed
|
||||
.pipe(takeUntil(this.unsubscribeNotifier))
|
||||
|
@ -54,6 +54,7 @@
|
||||
[documentId]="documentId"
|
||||
[disabled]="!userIsOwner"
|
||||
[existingFields]="document?.custom_fields"
|
||||
(created)="refreshCustomFields()"
|
||||
(added)="addField($event)">
|
||||
</pngx-custom-fields-dropdown>
|
||||
|
||||
@ -94,7 +95,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul ngbNav #nav="ngbNav" class="nav-underline flex-nowrap flex-md-wrap overflow-x-scroll" (navChange)="onNavChange($event)" [(activeId)]="activeNavID">
|
||||
<ul ngbNav #nav="ngbNav" class="nav-underline flex-nowrap flex-md-wrap overflow-auto" (navChange)="onNavChange($event)" [(activeId)]="activeNavID">
|
||||
<li [ngbNavItem]="DocumentDetailNavIDs.Details">
|
||||
<a ngbNavLink i18n>Details</a>
|
||||
<ng-template ngbNavContent>
|
||||
@ -113,11 +114,11 @@
|
||||
<ng-container *ngFor="let fieldInstance of document?.custom_fields; let i = index">
|
||||
<div [formGroup]="customFieldFormFields.controls[i]">
|
||||
<!-- TODO: boolean + URL -->
|
||||
<pngx-input-text formControlName="value" *ngIf="fieldInstance.field.data_type === PaperlessCustomFieldDataType.String" [title]="fieldInstance.field.name" [removable]="true" (removed)="removeField(fieldInstance)" [horizontal]="true"></pngx-input-text>
|
||||
<pngx-input-date formControlName="value" *ngIf="fieldInstance.field.data_type === PaperlessCustomFieldDataType.Date" [title]="fieldInstance.field.name" [removable]="true" (removed)="removeField(fieldInstance)" [horizontal]="true"></pngx-input-date>
|
||||
<pngx-input-number formControlName="value" *ngIf="fieldInstance.field.data_type === PaperlessCustomFieldDataType.Integer" [title]="fieldInstance.field.name" [removable]="true" (removed)="removeField(fieldInstance)" [horizontal]="true" [showAdd]="false"></pngx-input-number>
|
||||
<pngx-input-check formControlName="value" *ngIf="fieldInstance.field.data_type === PaperlessCustomFieldDataType.Boolean" [title]="fieldInstance.field.name" [removable]="true" (removed)="removeField(fieldInstance)" [horizontal]="true"></pngx-input-check>
|
||||
<pngx-input-url formControlName="value" *ngIf="fieldInstance.field.data_type === PaperlessCustomFieldDataType.Url" [title]="fieldInstance.field.name" [removable]="true" (removed)="removeField(fieldInstance)" [horizontal]="true"></pngx-input-url>
|
||||
<pngx-input-text formControlName="value" *ngIf="getCustomFieldFromInstance(fieldInstance)?.data_type === PaperlessCustomFieldDataType.String" [title]="getCustomFieldFromInstance(fieldInstance)?.name" [removable]="true" (removed)="removeField(fieldInstance)" [horizontal]="true"></pngx-input-text>
|
||||
<pngx-input-date formControlName="value" *ngIf="getCustomFieldFromInstance(fieldInstance)?.data_type === PaperlessCustomFieldDataType.Date" [title]="getCustomFieldFromInstance(fieldInstance)?.name" [removable]="true" (removed)="removeField(fieldInstance)" [horizontal]="true"></pngx-input-date>
|
||||
<pngx-input-number formControlName="value" *ngIf="getCustomFieldFromInstance(fieldInstance)?.data_type === PaperlessCustomFieldDataType.Integer" [title]="getCustomFieldFromInstance(fieldInstance)?.name" [removable]="true" (removed)="removeField(fieldInstance)" [horizontal]="true" [showAdd]="false"></pngx-input-number>
|
||||
<pngx-input-check formControlName="value" *ngIf="getCustomFieldFromInstance(fieldInstance)?.data_type === PaperlessCustomFieldDataType.Boolean" [title]="getCustomFieldFromInstance(fieldInstance)?.name" [removable]="true" (removed)="removeField(fieldInstance)" [horizontal]="true"></pngx-input-check>
|
||||
<pngx-input-url formControlName="value" *ngIf="getCustomFieldFromInstance(fieldInstance)?.data_type === PaperlessCustomFieldDataType.Url" [title]="getCustomFieldFromInstance(fieldInstance)?.name" [removable]="true" (removed)="removeField(fieldInstance)" [horizontal]="true"></pngx-input-url>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
@ -69,6 +69,7 @@ import { DocumentDetailComponent } from './document-detail.component'
|
||||
import { ShareLinksDropdownComponent } from '../common/share-links-dropdown/share-links-dropdown.component'
|
||||
import { CustomFieldsDropdownComponent } from '../common/custom-fields-dropdown/custom-fields-dropdown.component'
|
||||
import { PaperlessCustomFieldDataType } from 'src/app/data/paperless-custom-field'
|
||||
import { CustomFieldsService } from 'src/app/services/rest/custom-fields.service'
|
||||
|
||||
const doc: PaperlessDocument = {
|
||||
id: 3,
|
||||
@ -98,12 +99,7 @@ const doc: PaperlessDocument = {
|
||||
],
|
||||
custom_fields: [
|
||||
{
|
||||
field: {
|
||||
id: 0,
|
||||
name: 'Field 1',
|
||||
data_type: PaperlessCustomFieldDataType.String,
|
||||
created: new Date(),
|
||||
},
|
||||
field: 0,
|
||||
document: 3,
|
||||
created: new Date(),
|
||||
value: 'custom foo bar',
|
||||
@ -111,6 +107,21 @@ const doc: PaperlessDocument = {
|
||||
],
|
||||
}
|
||||
|
||||
const customFields = [
|
||||
{
|
||||
id: 0,
|
||||
name: 'Field 1',
|
||||
data_type: PaperlessCustomFieldDataType.String,
|
||||
created: new Date(),
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: 'Custom Field 2',
|
||||
data_type: PaperlessCustomFieldDataType.Integer,
|
||||
created: new Date(),
|
||||
},
|
||||
]
|
||||
|
||||
describe('DocumentDetailComponent', () => {
|
||||
let component: DocumentDetailComponent
|
||||
let fixture: ComponentFixture<DocumentDetailComponent>
|
||||
@ -122,6 +133,7 @@ describe('DocumentDetailComponent', () => {
|
||||
let toastService: ToastService
|
||||
let documentListViewService: DocumentListViewService
|
||||
let settingsService: SettingsService
|
||||
let customFieldsService: CustomFieldsService
|
||||
|
||||
let currentUserCan = true
|
||||
let currentUserHasObjectPermissions = true
|
||||
@ -215,6 +227,7 @@ describe('DocumentDetailComponent', () => {
|
||||
}),
|
||||
},
|
||||
},
|
||||
CustomFieldsService,
|
||||
{
|
||||
provide: PermissionsService,
|
||||
useValue: {
|
||||
@ -250,6 +263,7 @@ describe('DocumentDetailComponent', () => {
|
||||
toastService = TestBed.inject(ToastService)
|
||||
documentListViewService = TestBed.inject(DocumentListViewService)
|
||||
settingsService = TestBed.inject(SettingsService)
|
||||
customFieldsService = TestBed.inject(CustomFieldsService)
|
||||
fixture = TestBed.createComponent(DocumentDetailComponent)
|
||||
component = fixture.componentInstance
|
||||
})
|
||||
@ -306,6 +320,13 @@ describe('DocumentDetailComponent', () => {
|
||||
it('should load already-opened document via param', () => {
|
||||
jest.spyOn(documentService, 'get').mockReturnValueOnce(of(doc))
|
||||
jest.spyOn(openDocumentsService, 'getOpenDocument').mockReturnValue(doc)
|
||||
jest.spyOn(customFieldsService, 'listAll').mockReturnValue(
|
||||
of({
|
||||
count: customFields.length,
|
||||
all: customFields.map((f) => f.id),
|
||||
results: customFields,
|
||||
})
|
||||
)
|
||||
fixture.detectChanges() // calls ngOnInit
|
||||
expect(component.document).toEqual(doc)
|
||||
})
|
||||
@ -816,29 +837,26 @@ describe('DocumentDetailComponent', () => {
|
||||
it('should display custom fields', () => {
|
||||
initNormally()
|
||||
expect(fixture.debugElement.nativeElement.textContent).toContain(
|
||||
doc.custom_fields[0].field.name
|
||||
customFields[0].name
|
||||
)
|
||||
})
|
||||
|
||||
it('should support add custom field, correctly send via post', () => {
|
||||
const field = {
|
||||
id: 1,
|
||||
name: 'Custom Field 2',
|
||||
data_type: PaperlessCustomFieldDataType.Integer,
|
||||
}
|
||||
initNormally()
|
||||
const initialLength = doc.custom_fields.length
|
||||
expect(component.customFieldFormFields).toHaveLength(initialLength)
|
||||
component.addField(field)
|
||||
component.addField(customFields[1])
|
||||
fixture.detectChanges()
|
||||
expect(component.document.custom_fields).toHaveLength(initialLength + 1)
|
||||
expect(component.customFieldFormFields).toHaveLength(initialLength + 1)
|
||||
expect(fixture.debugElement.nativeElement.textContent).toContain(field.name)
|
||||
expect(fixture.debugElement.nativeElement.textContent).toContain(
|
||||
customFields[1].name
|
||||
)
|
||||
const updateSpy = jest.spyOn(documentService, 'update')
|
||||
component.save(true)
|
||||
expect(updateSpy.mock.lastCall[0].custom_fields).toHaveLength(2)
|
||||
expect(updateSpy.mock.lastCall[0].custom_fields[1]).toEqual({
|
||||
field,
|
||||
field: customFields[1].id,
|
||||
value: null,
|
||||
})
|
||||
})
|
||||
@ -869,6 +887,13 @@ describe('DocumentDetailComponent', () => {
|
||||
jest
|
||||
.spyOn(openDocumentsService, 'openDocument')
|
||||
.mockReturnValueOnce(of(true))
|
||||
jest.spyOn(customFieldsService, 'listAll').mockReturnValue(
|
||||
of({
|
||||
count: customFields.length,
|
||||
all: customFields.map((f) => f.id),
|
||||
results: customFields,
|
||||
})
|
||||
)
|
||||
fixture.detectChanges()
|
||||
}
|
||||
})
|
||||
|
@ -68,6 +68,7 @@ import {
|
||||
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,
|
||||
@ -140,6 +141,7 @@ export class DocumentDetailComponent
|
||||
|
||||
ogDate: Date
|
||||
|
||||
customFields: PaperlessCustomField[]
|
||||
public readonly PaperlessCustomFieldDataType = PaperlessCustomFieldDataType
|
||||
|
||||
@ViewChild('nav') nav: NgbNav
|
||||
@ -173,6 +175,7 @@ export class DocumentDetailComponent
|
||||
private storagePathService: StoragePathService,
|
||||
private permissionsService: PermissionsService,
|
||||
private userService: UserService,
|
||||
private customFieldsService: CustomFieldsService,
|
||||
private http: HttpClient
|
||||
) {
|
||||
super()
|
||||
@ -239,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),
|
||||
@ -836,16 +841,32 @@ export class DocumentDetailComponent
|
||||
this.documentListViewService.quickFilter(filterRules)
|
||||
}
|
||||
|
||||
updateFormForCustomFields(emitEvent: boolean = false) {
|
||||
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)
|
||||
}
|
||||
|
||||
private updateFormForCustomFields(emitEvent: boolean = false) {
|
||||
this.customFieldFormFields.clear({ emitEvent: false })
|
||||
this.document.custom_fields?.forEach((fieldInstance) => {
|
||||
this.customFieldFormFields.push(
|
||||
new FormGroup({
|
||||
field: new FormGroup({
|
||||
id: new FormControl(fieldInstance.field.id),
|
||||
name: new FormControl(fieldInstance.field.name),
|
||||
data_type: new FormControl(fieldInstance.field.data_type),
|
||||
}),
|
||||
field: new FormControl(
|
||||
this.getCustomFieldFromInstance(fieldInstance)?.id
|
||||
),
|
||||
value: new FormControl(fieldInstance.value),
|
||||
}),
|
||||
{ emitEvent }
|
||||
@ -853,9 +874,9 @@ export class DocumentDetailComponent
|
||||
})
|
||||
}
|
||||
|
||||
addField(field: PaperlessCustomField) {
|
||||
public addField(field: PaperlessCustomField) {
|
||||
this.document.custom_fields.push({
|
||||
field,
|
||||
field: field.id,
|
||||
value: null,
|
||||
document: this.documentId,
|
||||
created: new Date(),
|
||||
@ -863,11 +884,12 @@ export class DocumentDetailComponent
|
||||
this.updateFormForCustomFields(true)
|
||||
}
|
||||
|
||||
removeField(fieldInstance: PaperlessCustomFieldInstance) {
|
||||
public removeField(fieldInstance: PaperlessCustomFieldInstance) {
|
||||
this.document.custom_fields.splice(
|
||||
this.document.custom_fields.indexOf(fieldInstance),
|
||||
1
|
||||
)
|
||||
this.updateFormForCustomFields(true)
|
||||
this.documentForm.updateValueAndValidity()
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ import { PaperlessCustomField } from './paperless-custom-field'
|
||||
|
||||
export interface PaperlessCustomFieldInstance extends ObjectWithId {
|
||||
document: number // PaperlessDocument
|
||||
field: PaperlessCustomField
|
||||
field: number // PaperlessCustomField
|
||||
created: Date
|
||||
value?: any
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user