mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-02-16 00:19:32 -06:00
Make content edits target a specific version
This commit is contained in:
@@ -740,6 +740,18 @@ describe('DocumentDetailComponent', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('save should target currently selected version', () => {
|
||||||
|
initNormally()
|
||||||
|
component.selectedVersionId = 10
|
||||||
|
const patchSpy = jest.spyOn(documentService, 'patch')
|
||||||
|
patchSpy.mockReturnValue(of(doc))
|
||||||
|
|
||||||
|
component.save()
|
||||||
|
|
||||||
|
expect(patchSpy).toHaveBeenCalled()
|
||||||
|
expect(patchSpy.mock.calls[0][1]).toEqual(10)
|
||||||
|
})
|
||||||
|
|
||||||
it('should show toast error on save if error occurs', () => {
|
it('should show toast error on save if error occurs', () => {
|
||||||
currentUserHasObjectPermissions = true
|
currentUserHasObjectPermissions = true
|
||||||
initNormally()
|
initNormally()
|
||||||
|
|||||||
@@ -1079,7 +1079,7 @@ export class DocumentDetailComponent
|
|||||||
this.networkActive = true
|
this.networkActive = true
|
||||||
;(document.activeElement as HTMLElement)?.dispatchEvent(new Event('change'))
|
;(document.activeElement as HTMLElement)?.dispatchEvent(new Event('change'))
|
||||||
this.documentsService
|
this.documentsService
|
||||||
.patch(this.getChangedFields())
|
.patch(this.getChangedFields(), this.selectedVersionId)
|
||||||
.pipe(first())
|
.pipe(first())
|
||||||
.subscribe({
|
.subscribe({
|
||||||
next: (docValues) => {
|
next: (docValues) => {
|
||||||
@@ -1134,7 +1134,7 @@ export class DocumentDetailComponent
|
|||||||
this.networkActive = true
|
this.networkActive = true
|
||||||
this.store.next(this.documentForm.value)
|
this.store.next(this.documentForm.value)
|
||||||
this.documentsService
|
this.documentsService
|
||||||
.patch(this.getChangedFields())
|
.patch(this.getChangedFields(), this.selectedVersionId)
|
||||||
.pipe(
|
.pipe(
|
||||||
switchMap((updateResult) => {
|
switchMap((updateResult) => {
|
||||||
this.savedViewService.maybeRefreshDocumentCounts()
|
this.savedViewService.maybeRefreshDocumentCounts()
|
||||||
|
|||||||
@@ -298,6 +298,14 @@ describe(`DocumentService`, () => {
|
|||||||
expect(req.request.body.remove_inbox_tags).toEqual(true)
|
expect(req.request.body.remove_inbox_tags).toEqual(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should pass selected version to patch when provided', () => {
|
||||||
|
subscription = service.patch(documents[0], 123).subscribe()
|
||||||
|
const req = httpTestingController.expectOne(
|
||||||
|
`${environment.apiBaseUrl}${endpoint}/${documents[0].id}/?version=123`
|
||||||
|
)
|
||||||
|
expect(req.request.method).toEqual('PATCH')
|
||||||
|
})
|
||||||
|
|
||||||
it('should call appropriate api endpoint for getting audit log', () => {
|
it('should call appropriate api endpoint for getting audit log', () => {
|
||||||
subscription = service.getHistory(documents[0].id).subscribe()
|
subscription = service.getHistory(documents[0].id).subscribe()
|
||||||
const req = httpTestingController.expectOne(
|
const req = httpTestingController.expectOne(
|
||||||
|
|||||||
@@ -227,11 +227,14 @@ export class DocumentService extends AbstractPaperlessService<Document> {
|
|||||||
return this.http.get<number>(this.getResourceUrl(null, 'next_asn'))
|
return this.http.get<number>(this.getResourceUrl(null, 'next_asn'))
|
||||||
}
|
}
|
||||||
|
|
||||||
patch(o: Document): Observable<Document> {
|
patch(o: Document, versionID: number = null): Observable<Document> {
|
||||||
o.remove_inbox_tags = !!this.settingsService.get(
|
o.remove_inbox_tags = !!this.settingsService.get(
|
||||||
SETTINGS_KEYS.DOCUMENT_EDITING_REMOVE_INBOX_TAGS
|
SETTINGS_KEYS.DOCUMENT_EDITING_REMOVE_INBOX_TAGS
|
||||||
)
|
)
|
||||||
return super.patch(o)
|
this.clearCache()
|
||||||
|
return this.http.patch<Document>(this.getResourceUrl(o.id), o, {
|
||||||
|
params: versionID ? { version: versionID.toString() } : {},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadDocument(formData) {
|
uploadDocument(formData) {
|
||||||
|
|||||||
@@ -499,6 +499,43 @@ class TestDocumentVersioningApi(DirectoriesMixin, APITestCase):
|
|||||||
self.assertEqual(root.content, "root-content")
|
self.assertEqual(root.content, "root-content")
|
||||||
self.assertEqual(v1.content, "v1-content")
|
self.assertEqual(v1.content, "v1-content")
|
||||||
|
|
||||||
|
def test_patch_content_updates_selected_version_content(self) -> None:
|
||||||
|
root = Document.objects.create(
|
||||||
|
title="root",
|
||||||
|
checksum="root",
|
||||||
|
mime_type="application/pdf",
|
||||||
|
content="root-content",
|
||||||
|
)
|
||||||
|
v1 = Document.objects.create(
|
||||||
|
title="v1",
|
||||||
|
checksum="v1",
|
||||||
|
mime_type="application/pdf",
|
||||||
|
root_document=root,
|
||||||
|
content="v1-content",
|
||||||
|
)
|
||||||
|
v2 = Document.objects.create(
|
||||||
|
title="v2",
|
||||||
|
checksum="v2",
|
||||||
|
mime_type="application/pdf",
|
||||||
|
root_document=root,
|
||||||
|
content="v2-content",
|
||||||
|
)
|
||||||
|
|
||||||
|
resp = self.client.patch(
|
||||||
|
f"/api/documents/{root.id}/?version={v1.id}",
|
||||||
|
{"content": "edited-v1"},
|
||||||
|
format="json",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(resp.status_code, status.HTTP_200_OK)
|
||||||
|
self.assertEqual(resp.data["content"], "edited-v1")
|
||||||
|
root.refresh_from_db()
|
||||||
|
v1.refresh_from_db()
|
||||||
|
v2.refresh_from_db()
|
||||||
|
self.assertEqual(v1.content, "edited-v1")
|
||||||
|
self.assertEqual(v2.content, "v2-content")
|
||||||
|
self.assertEqual(root.content, "root-content")
|
||||||
|
|
||||||
def test_retrieve_returns_latest_version_content(self) -> None:
|
def test_retrieve_returns_latest_version_content(self) -> None:
|
||||||
root = Document.objects.create(
|
root = Document.objects.create(
|
||||||
title="root",
|
title="root",
|
||||||
|
|||||||
@@ -859,13 +859,17 @@ class DocumentViewSet(
|
|||||||
def update(self, request, *args, **kwargs):
|
def update(self, request, *args, **kwargs):
|
||||||
partial = kwargs.pop("partial", False)
|
partial = kwargs.pop("partial", False)
|
||||||
root_doc = self.get_object()
|
root_doc = self.get_object()
|
||||||
|
content_doc = (
|
||||||
|
self._resolve_file_doc(root_doc, request)
|
||||||
|
if "version" in request.query_params
|
||||||
|
else self._get_latest_doc_for_root(root_doc)
|
||||||
|
)
|
||||||
content_updated = "content" in request.data
|
content_updated = "content" in request.data
|
||||||
updated_content = request.data.get("content") if content_updated else None
|
updated_content = request.data.get("content") if content_updated else None
|
||||||
latest_doc = self._get_latest_doc_for_root(root_doc)
|
|
||||||
|
|
||||||
data = request.data.copy()
|
data = request.data.copy()
|
||||||
serializer_partial = partial
|
serializer_partial = partial
|
||||||
if content_updated and latest_doc.id != root_doc.id:
|
if content_updated and content_doc.id != root_doc.id:
|
||||||
if updated_content is None:
|
if updated_content is None:
|
||||||
raise ValidationError({"content": ["This field may not be null."]})
|
raise ValidationError({"content": ["This field may not be null."]})
|
||||||
data.pop("content", None)
|
data.pop("content", None)
|
||||||
@@ -879,15 +883,18 @@ class DocumentViewSet(
|
|||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
self.perform_update(serializer)
|
self.perform_update(serializer)
|
||||||
|
|
||||||
if content_updated and latest_doc.id != root_doc.id:
|
if content_updated and content_doc.id != root_doc.id:
|
||||||
latest_doc.content = updated_content
|
content_doc.content = updated_content
|
||||||
latest_doc.save(update_fields=["content", "modified"])
|
content_doc.save(update_fields=["content", "modified"])
|
||||||
|
|
||||||
if getattr(root_doc, "_prefetched_objects_cache", None):
|
if getattr(root_doc, "_prefetched_objects_cache", None):
|
||||||
root_doc._prefetched_objects_cache = {}
|
root_doc._prefetched_objects_cache = {}
|
||||||
|
|
||||||
refreshed_doc = self.get_queryset().get(pk=root_doc.pk)
|
refreshed_doc = self.get_queryset().get(pk=root_doc.pk)
|
||||||
response = Response(self.get_serializer(refreshed_doc).data)
|
response_data = self.get_serializer(refreshed_doc).data
|
||||||
|
if "version" in request.query_params and "content" in response_data:
|
||||||
|
response_data["content"] = content_doc.content
|
||||||
|
response = Response(response_data)
|
||||||
|
|
||||||
from documents import index
|
from documents import index
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user