diff --git a/src-ui/src/app/components/document-detail/document-detail.component.spec.ts b/src-ui/src/app/components/document-detail/document-detail.component.spec.ts index 345d488eb..5b94c4922 100644 --- a/src-ui/src/app/components/document-detail/document-detail.component.spec.ts +++ b/src-ui/src/app/components/document-detail/document-detail.component.spec.ts @@ -456,11 +456,11 @@ describe('DocumentDetailComponent', () => { initNormally() component.title = 'Foo Bar' const closeSpy = jest.spyOn(component, 'close') - const updateSpy = jest.spyOn(documentService, 'update') + const patchSpy = jest.spyOn(documentService, 'patch') const toastSpy = jest.spyOn(toastService, 'showInfo') - updateSpy.mockImplementation((o) => of(doc)) + patchSpy.mockImplementation((o) => of(doc)) component.save(true) - expect(updateSpy).toHaveBeenCalled() + expect(patchSpy).toHaveBeenCalled() expect(closeSpy).toHaveBeenCalled() expect(toastSpy).toHaveBeenCalledWith( 'Document "Doc 3" saved successfully.' @@ -471,11 +471,11 @@ describe('DocumentDetailComponent', () => { initNormally() component.title = 'Foo Bar' const closeSpy = jest.spyOn(component, 'close') - const updateSpy = jest.spyOn(documentService, 'update') + const patchSpy = jest.spyOn(documentService, 'patch') const toastSpy = jest.spyOn(toastService, 'showInfo') - updateSpy.mockImplementation((o) => of(doc)) + patchSpy.mockImplementation((o) => of(doc)) component.save() - expect(updateSpy).toHaveBeenCalled() + expect(patchSpy).toHaveBeenCalled() expect(closeSpy).not.toHaveBeenCalled() expect(toastSpy).toHaveBeenCalledWith( 'Document "Doc 3" saved successfully.' @@ -487,12 +487,12 @@ describe('DocumentDetailComponent', () => { initNormally() component.title = 'Foo Bar' const closeSpy = jest.spyOn(component, 'close') - const updateSpy = jest.spyOn(documentService, 'update') + const patchSpy = jest.spyOn(documentService, 'patch') const toastSpy = jest.spyOn(toastService, 'showError') const error = new Error('failed to save') - updateSpy.mockImplementation(() => throwError(() => error)) + patchSpy.mockImplementation(() => throwError(() => error)) component.save() - expect(updateSpy).toHaveBeenCalled() + expect(patchSpy).toHaveBeenCalled() expect(closeSpy).not.toHaveBeenCalled() expect(toastSpy).toHaveBeenCalledWith( 'Error saving document "Doc 3"', @@ -505,13 +505,13 @@ describe('DocumentDetailComponent', () => { initNormally() component.title = 'Foo Bar' const closeSpy = jest.spyOn(component, 'close') - const updateSpy = jest.spyOn(documentService, 'update') + const patchSpy = jest.spyOn(documentService, 'patch') const toastSpy = jest.spyOn(toastService, 'showInfo') - updateSpy.mockImplementation(() => + patchSpy.mockImplementation(() => throwError(() => new Error('failed to save')) ) component.save(true) - expect(updateSpy).toHaveBeenCalled() + expect(patchSpy).toHaveBeenCalled() expect(closeSpy).toHaveBeenCalled() expect(toastSpy).toHaveBeenCalledWith( 'Document "Doc 3" saved successfully.' @@ -522,8 +522,8 @@ describe('DocumentDetailComponent', () => { initNormally() const nextDocId = 100 component.title = 'Foo Bar' - const updateSpy = jest.spyOn(documentService, 'update') - updateSpy.mockReturnValue(of(doc)) + const patchSpy = jest.spyOn(documentService, 'patch') + patchSpy.mockReturnValue(of(doc)) const nextSpy = jest.spyOn(documentListViewService, 'getNext') nextSpy.mockReturnValue(of(nextDocId)) const closeSpy = jest.spyOn(openDocumentsService, 'closeDocument') @@ -531,7 +531,7 @@ describe('DocumentDetailComponent', () => { const navigateSpy = jest.spyOn(router, 'navigate') component.saveEditNext() - expect(updateSpy).toHaveBeenCalled() + expect(patchSpy).toHaveBeenCalled() expect(navigateSpy).toHaveBeenCalledWith(['documents', nextDocId]) expect }) @@ -541,12 +541,12 @@ describe('DocumentDetailComponent', () => { initNormally() component.title = 'Foo Bar' const closeSpy = jest.spyOn(component, 'close') - const updateSpy = jest.spyOn(documentService, 'update') + const patchSpy = jest.spyOn(documentService, 'patch') const toastSpy = jest.spyOn(toastService, 'showError') const error = new Error('failed to save') - updateSpy.mockImplementation(() => throwError(() => error)) + patchSpy.mockImplementation(() => throwError(() => error)) component.saveEditNext() - expect(updateSpy).toHaveBeenCalled() + expect(patchSpy).toHaveBeenCalled() expect(closeSpy).not.toHaveBeenCalled() expect(toastSpy).toHaveBeenCalledWith('Error saving document', error) }) @@ -965,10 +965,10 @@ describe('DocumentDetailComponent', () => { expect(fixture.debugElement.nativeElement.textContent).toContain( customFields[1].name ) - const updateSpy = jest.spyOn(documentService, 'update') + const patchSpy = jest.spyOn(documentService, 'patch') component.save(true) - expect(updateSpy.mock.lastCall[0].custom_fields).toHaveLength(2) - expect(updateSpy.mock.lastCall[0].custom_fields[1]).toEqual({ + expect(patchSpy.mock.lastCall[0].custom_fields).toHaveLength(2) + expect(patchSpy.mock.lastCall[0].custom_fields[1]).toEqual({ field: customFields[1].id, value: null, }) @@ -985,9 +985,9 @@ describe('DocumentDetailComponent', () => { expect( fixture.debugElement.query(By.css('form')).nativeElement.textContent ).not.toContain('Field 1') - const updateSpy = jest.spyOn(documentService, 'update') + const patchSpy = jest.spyOn(documentService, 'patch') component.save(true) - expect(updateSpy.mock.lastCall[0].custom_fields).toHaveLength( + expect(patchSpy.mock.lastCall[0].custom_fields).toHaveLength( initialLength - 1 ) }) diff --git a/src-ui/src/app/components/document-detail/document-detail.component.ts b/src-ui/src/app/components/document-detail/document-detail.component.ts index 2f5b179b8..dac5f5de0 100644 --- a/src-ui/src/app/components/document-detail/document-detail.component.ts +++ b/src-ui/src/app/components/document-detail/document-detail.component.ts @@ -784,6 +784,7 @@ export class DocumentDetailComponent this.title = doc.title this.updateFormForCustomFields() this.documentForm.patchValue(doc) + this.documentForm.markAsPristine() this.openDocumentService.setDirty(doc, false) }, error: () => { @@ -794,11 +795,30 @@ export class DocumentDetailComponent }) } + private getChangedFields(): any { + const changes = { + id: this.document.id, + } + Object.keys(this.documentForm.controls).forEach((key) => { + if (this.documentForm.get(key).dirty) { + if (key === 'permissions_form') { + changes['owner'] = + this.documentForm.get('permissions_form').value['owner'] + changes['set_permissions'] = + this.documentForm.get('permissions_form').value['set_permissions'] + } else { + changes[key] = this.documentForm.get(key).value + } + } + }) + return changes + } + save(close: boolean = false) { this.networkActive = true ;(document.activeElement as HTMLElement)?.dispatchEvent(new Event('change')) this.documentsService - .update(this.document) + .patch(this.getChangedFields()) .pipe(first()) .subscribe({ next: (docValues) => { @@ -852,7 +872,7 @@ export class DocumentDetailComponent this.networkActive = true this.store.next(this.documentForm.value) this.documentsService - .update(this.document) + .patch(this.getChangedFields()) .pipe( switchMap((updateResult) => { return this.documentListViewService @@ -1303,6 +1323,8 @@ export class DocumentDetailComponent created: new Date(), }) this.updateFormForCustomFields(true) + this.documentForm.get('custom_fields').markAsDirty() + this.documentForm.updateValueAndValidity() } public removeField(fieldInstance: CustomFieldInstance) { @@ -1311,6 +1333,7 @@ export class DocumentDetailComponent 1 ) this.updateFormForCustomFields(true) + this.documentForm.get('custom_fields').markAsDirty() this.documentForm.updateValueAndValidity() } diff --git a/src-ui/src/app/services/rest/document.service.spec.ts b/src-ui/src/app/services/rest/document.service.spec.ts index 84f7f6f8a..9480e2816 100644 --- a/src-ui/src/app/services/rest/document.service.spec.ts +++ b/src-ui/src/app/services/rest/document.service.spec.ts @@ -268,15 +268,15 @@ describe(`DocumentService`, () => { expect(req.request.method).toEqual('GET') }) - it('should pass remove_inbox_tags setting to update', () => { - subscription = service.update(documents[0]).subscribe() + it('should pass remove_inbox_tags setting to patch', () => { + subscription = service.patch(documents[0]).subscribe() let req = httpTestingController.expectOne( `${environment.apiBaseUrl}${endpoint}/${documents[0].id}/` ) expect(req.request.body.remove_inbox_tags).toEqual(false) settingsService.set(SETTINGS_KEYS.DOCUMENT_EDITING_REMOVE_INBOX_TAGS, true) - subscription = service.update(documents[0]).subscribe() + subscription = service.patch(documents[0]).subscribe() req = httpTestingController.expectOne( `${environment.apiBaseUrl}${endpoint}/${documents[0].id}/` ) diff --git a/src-ui/src/app/services/rest/document.service.ts b/src-ui/src/app/services/rest/document.service.ts index 0c6c8cfa6..9cdb86280 100644 --- a/src-ui/src/app/services/rest/document.service.ts +++ b/src-ui/src/app/services/rest/document.service.ts @@ -189,13 +189,13 @@ export class DocumentService extends AbstractPaperlessService { return this.http.get(this.getResourceUrl(null, 'next_asn')) } - update(o: Document): Observable { + patch(o: Document): Observable { // we want to only set created_date - o.created = undefined + delete o.created o.remove_inbox_tags = !!this.settingsService.get( SETTINGS_KEYS.DOCUMENT_EDITING_REMOVE_INBOX_TAGS ) - return super.update(o) + return super.patch(o) } uploadDocument(formData) {