Enhancement: use patch instead of put for frontend document changes (#9744)

This commit is contained in:
shamoon 2025-04-22 12:58:28 -07:00 committed by GitHub
parent 2abf38f98e
commit cbaceb95af
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 54 additions and 31 deletions

View File

@ -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
)
})

View File

@ -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()
}

View File

@ -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}/`
)

View File

@ -189,13 +189,13 @@ export class DocumentService extends AbstractPaperlessService<Document> {
return this.http.get<number>(this.getResourceUrl(null, 'next_asn'))
}
update(o: Document): Observable<Document> {
patch(o: Document): Observable<Document> {
// 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) {