]> git.ipfire.org Git - thirdparty/paperless-ngx.git/commitdiff
Feature: improve history display of object names etc (#7102)
authorshamoon <4887959+shamoon@users.noreply.github.com>
Thu, 27 Jun 2024 02:52:08 +0000 (19:52 -0700)
committerGitHub <noreply@github.com>
Thu, 27 Jun 2024 02:52:08 +0000 (02:52 +0000)
src-ui/src/app/components/document-history/document-history.component.html
src-ui/src/app/components/document-history/document-history.component.spec.ts
src-ui/src/app/components/document-history/document-history.component.ts

index c63a1223cc75fa375ff8ab28e0eb0c163d086833..edb04532388304f658bba59427c5d78843c00668 100644 (file)
@@ -48,7 +48,7 @@
                                     @if (change.key === 'content') {
                                         <code class="text-primary">{{ change.value[1]?.substring(0,100) }}...</code>
                                     } @else {
-                                        <code class="text-primary">{{ change.value[1] }}</code>
+                                        <code class="text-primary">{{ getPrettyName(change.key, change.value[1]) | async }}</code>
                                     }
                                 </li>
                             }
index 90108a9719028eb7a419dd36fe7a997e59db9042..57133ed74fae71ace7294a6ff9555c61aab8a455 100644 (file)
@@ -9,11 +9,20 @@ import { CustomDatePipe } from 'src/app/pipes/custom-date.pipe'
 import { DatePipe } from '@angular/common'
 import { NgbCollapseModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'
 import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
+import { CorrespondentService } from 'src/app/services/rest/correspondent.service'
+import { DocumentTypeService } from 'src/app/services/rest/document-type.service'
+import { StoragePathService } from 'src/app/services/rest/storage-path.service'
+import { UserService } from 'src/app/services/rest/user.service'
+import { DataType } from 'src/app/data/datatype'
 
 describe('DocumentHistoryComponent', () => {
   let component: DocumentHistoryComponent
   let fixture: ComponentFixture<DocumentHistoryComponent>
   let documentService: DocumentService
+  let correspondentService: CorrespondentService
+  let documentTypeService: DocumentTypeService
+  let storagePathService: StoragePathService
+  let userService: UserService
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
@@ -29,6 +38,10 @@ describe('DocumentHistoryComponent', () => {
 
     fixture = TestBed.createComponent(DocumentHistoryComponent)
     documentService = TestBed.inject(DocumentService)
+    correspondentService = TestBed.inject(CorrespondentService)
+    documentTypeService = TestBed.inject(DocumentTypeService)
+    storagePathService = TestBed.inject(StoragePathService)
+    userService = TestBed.inject(UserService)
     component = fixture.componentInstance
   })
 
@@ -55,4 +68,91 @@ describe('DocumentHistoryComponent', () => {
     fixture.detectChanges()
     expect(getHistorySpy).toHaveBeenCalledWith(1)
   })
+
+  it('getPrettyName should return the correspondent name', () => {
+    const correspondentId = '1'
+    const correspondentName = 'John Doe'
+    const getCachedSpy = jest
+      .spyOn(correspondentService, 'getCached')
+      .mockReturnValue(of({ name: correspondentName }))
+    component
+      .getPrettyName(DataType.Correspondent, correspondentId)
+      .subscribe((result) => {
+        expect(result).toBe(correspondentName)
+      })
+    expect(getCachedSpy).toHaveBeenCalledWith(parseInt(correspondentId))
+    // no correspondent found
+    getCachedSpy.mockReturnValue(of(null))
+    component
+      .getPrettyName(DataType.Correspondent, correspondentId)
+      .subscribe((result) => {
+        expect(result).toBe(correspondentId)
+      })
+  })
+
+  it('getPrettyName should return the document type name', () => {
+    const documentTypeId = '1'
+    const documentTypeName = 'Invoice'
+    const getCachedSpy = jest
+      .spyOn(documentTypeService, 'getCached')
+      .mockReturnValue(of({ name: documentTypeName }))
+    component
+      .getPrettyName(DataType.DocumentType, documentTypeId)
+      .subscribe((result) => {
+        expect(result).toBe(documentTypeName)
+      })
+    expect(getCachedSpy).toHaveBeenCalledWith(parseInt(documentTypeId))
+    // no document type found
+    getCachedSpy.mockReturnValue(of(null))
+    component
+      .getPrettyName(DataType.DocumentType, documentTypeId)
+      .subscribe((result) => {
+        expect(result).toBe(documentTypeId)
+      })
+  })
+
+  it('getPrettyName should return the storage path path', () => {
+    const storagePathId = '1'
+    const storagePath = '/path/to/storage'
+    const getCachedSpy = jest
+      .spyOn(storagePathService, 'getCached')
+      .mockReturnValue(of({ path: storagePath }))
+    component
+      .getPrettyName(DataType.StoragePath, storagePathId)
+      .subscribe((result) => {
+        expect(result).toBe(storagePath)
+      })
+    expect(getCachedSpy).toHaveBeenCalledWith(parseInt(storagePathId))
+    // no storage path found
+    getCachedSpy.mockReturnValue(of(null))
+    component
+      .getPrettyName(DataType.StoragePath, storagePathId)
+      .subscribe((result) => {
+        expect(result).toBe(storagePathId)
+      })
+  })
+
+  it('getPrettyName should return the owner username', () => {
+    const ownerId = '1'
+    const ownerUsername = 'user1'
+    const getCachedSpy = jest
+      .spyOn(userService, 'getCached')
+      .mockReturnValue(of({ username: ownerUsername }))
+    component.getPrettyName('owner', ownerId).subscribe((result) => {
+      expect(result).toBe(ownerUsername)
+    })
+    expect(getCachedSpy).toHaveBeenCalledWith(parseInt(ownerId))
+    // no user found
+    getCachedSpy.mockReturnValue(of(null))
+    component.getPrettyName('owner', ownerId).subscribe((result) => {
+      expect(result).toBe(ownerId)
+    })
+  })
+
+  it('getPrettyName should return the value as is for other types', () => {
+    const id = '123'
+    component.getPrettyName('other', id).subscribe((result) => {
+      expect(result).toBe(id)
+    })
+  })
 })
index 7870c1714431fac502871a359e37f054ec0461bc..934ddab56f9639d0cf6e94c9fc130c93cc30851d 100644 (file)
@@ -1,6 +1,12 @@
 import { Component, Input, OnInit } from '@angular/core'
+import { Observable, first, map, of } from 'rxjs'
 import { AuditLogAction, AuditLogEntry } from 'src/app/data/auditlog-entry'
+import { DataType } from 'src/app/data/datatype'
+import { CorrespondentService } from 'src/app/services/rest/correspondent.service'
+import { DocumentTypeService } from 'src/app/services/rest/document-type.service'
 import { DocumentService } from 'src/app/services/rest/document.service'
+import { StoragePathService } from 'src/app/services/rest/storage-path.service'
+import { UserService } from 'src/app/services/rest/user.service'
 
 @Component({
   selector: 'pngx-document-history',
@@ -20,7 +26,13 @@ export class DocumentHistoryComponent implements OnInit {
   public loading: boolean = true
   public entries: AuditLogEntry[] = []
 
-  constructor(private documentService: DocumentService) {}
+  constructor(
+    private documentService: DocumentService,
+    private correspondentService: CorrespondentService,
+    private storagePathService: StoragePathService,
+    private documentTypeService: DocumentTypeService,
+    private userService: UserService
+  ) {}
 
   ngOnInit(): void {
     if (this._documentId) {
@@ -33,4 +45,31 @@ export class DocumentHistoryComponent implements OnInit {
         })
     }
   }
+
+  getPrettyName(type: DataType | string, id: string): Observable<string> {
+    switch (type) {
+      case DataType.Correspondent:
+        return this.correspondentService.getCached(parseInt(id, 10)).pipe(
+          first(),
+          map((correspondent) => correspondent?.name ?? id)
+        )
+      case DataType.DocumentType:
+        return this.documentTypeService.getCached(parseInt(id, 10)).pipe(
+          first(),
+          map((documentType) => documentType?.name ?? id)
+        )
+      case DataType.StoragePath:
+        return this.storagePathService.getCached(parseInt(id, 10)).pipe(
+          first(),
+          map((storagePath) => storagePath?.path ?? id)
+        )
+      case 'owner':
+        return this.userService.getCached(parseInt(id, 10)).pipe(
+          first(),
+          map((user) => user?.username ?? id)
+        )
+      default:
+        return of(id)
+    }
+  }
 }