From 3dbc9d9fc18651addefc0ee3bec0fdf86e23c670 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Wed, 11 Dec 2024 01:56:53 -0800 Subject: [PATCH] Basic frontend --- .../saved-views/saved-views.component.spec.ts | 12 +++ .../services/rest/document.service.spec.ts | 82 +++++++++++++++++-- .../src/app/services/rest/document.service.ts | 32 +++++++- 3 files changed, 116 insertions(+), 10 deletions(-) diff --git a/src-ui/src/app/components/manage/saved-views/saved-views.component.spec.ts b/src-ui/src/app/components/manage/saved-views/saved-views.component.spec.ts index 9ff50f1bc..9372c94ff 100644 --- a/src-ui/src/app/components/manage/saved-views/saved-views.component.spec.ts +++ b/src-ui/src/app/components/manage/saved-views/saved-views.component.spec.ts @@ -11,6 +11,7 @@ import { SavedView } from 'src/app/data/saved-view' import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive' import { PermissionsGuard } from 'src/app/guards/permissions.guard' import { PermissionsService } from 'src/app/services/permissions.service' +import { CustomFieldsService } from 'src/app/services/rest/custom-fields.service' import { SavedViewService } from 'src/app/services/rest/saved-view.service' import { ToastService } from 'src/app/services/toast.service' import { ConfirmButtonComponent } from '../../common/confirm-button/confirm-button.component' @@ -60,6 +61,17 @@ describe('SavedViewsComponent', () => { currentUserCan: () => true, }, }, + { + provide: CustomFieldsService, + useValue: { + listAll: () => + of({ + all: [], + count: 0, + results: [], + }), + }, + }, PermissionsGuard, provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting(), 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 72610abee..dd4df41f8 100644 --- a/src-ui/src/app/services/rest/document.service.spec.ts +++ b/src-ui/src/app/services/rest/document.service.spec.ts @@ -4,7 +4,8 @@ import { provideHttpClientTesting, } from '@angular/common/http/testing' import { TestBed } from '@angular/core/testing' -import { Subscription } from 'rxjs' +import { of, Subscription } from 'rxjs' +import { CustomFieldDataType } from 'src/app/data/custom-field' import { DOCUMENT_SORT_FIELDS, DOCUMENT_SORT_FIELDS_FULLTEXT, @@ -14,12 +15,15 @@ import { SETTINGS_KEYS } from 'src/app/data/ui-settings' import { environment } from 'src/environments/environment' import { PermissionsService } from '../permissions.service' import { SettingsService } from '../settings.service' +import { CustomFieldsService } from './custom-fields.service' import { DocumentService } from './document.service' let httpTestingController: HttpTestingController let service: DocumentService let subscription: Subscription let settingsService: SettingsService +let permissionsService: PermissionsService +let customFieldsService: CustomFieldsService const endpoint = 'documents' const documents = [ @@ -55,8 +59,29 @@ beforeEach(() => { }) httpTestingController = TestBed.inject(HttpTestingController) - service = TestBed.inject(DocumentService) settingsService = TestBed.inject(SettingsService) + customFieldsService = TestBed.inject(CustomFieldsService) + permissionsService = TestBed.inject(PermissionsService) + jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(true) + jest.spyOn(customFieldsService, 'listAll').mockReturnValue( + of({ + all: [1, 2, 3], + count: 3, + results: [ + { + id: 1, + name: 'Custom Field 1', + data_type: CustomFieldDataType.String, + }, + { + id: 2, + name: 'Custom Field 2', + data_type: CustomFieldDataType.Integer, + }, + ], + }) + ) + service = TestBed.inject(DocumentService) }) describe(`DocumentService`, () => { @@ -289,18 +314,25 @@ describe(`DocumentService`, () => { it('should construct sort fields respecting permissions', () => { expect( service.sortFields.find((f) => f.field === 'correspondent__name') - ).toBeUndefined() + ).not.toBeUndefined() expect( service.sortFields.find((f) => f.field === 'document_type__name') - ).toBeUndefined() + ).not.toBeUndefined() + expect( + service.sortFields.find((f) => f.field === 'owner') + ).not.toBeUndefined() - const permissionsService: PermissionsService = - TestBed.inject(PermissionsService) - jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(true) + jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(false) service['setupSortFields']() - expect(service.sortFields).toEqual(DOCUMENT_SORT_FIELDS) + const fields = DOCUMENT_SORT_FIELDS.filter( + (f) => + ['correspondent__name', 'document_type__name', 'owner'].indexOf( + f.field + ) === -1 + ) + expect(service.sortFields).toEqual(fields) expect(service.sortFieldsFullText).toEqual([ - ...DOCUMENT_SORT_FIELDS, + ...fields, ...DOCUMENT_SORT_FIELDS_FULLTEXT, ]) @@ -311,6 +343,38 @@ it('should construct sort fields respecting permissions', () => { ).toBeUndefined() }) +it('should include custom fields in sort fields if user has permission', () => { + const permissionsService: PermissionsService = + TestBed.inject(PermissionsService) + jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(true) + + service['customFields'] = [ + { + id: 1, + name: 'Custom Field 1', + data_type: CustomFieldDataType.String, + }, + { + id: 2, + name: 'Custom Field 2', + data_type: CustomFieldDataType.Integer, + }, + ] + + service['setupSortFields']() + expect(service.sortFields).toEqual([ + ...DOCUMENT_SORT_FIELDS, + { + field: 'custom_field_1', + name: 'Custom Field 1', + }, + { + field: 'custom_field_2', + name: 'Custom Field 2', + }, + ]) +}) + afterEach(() => { subscription?.unsubscribe() httpTestingController.verify() diff --git a/src-ui/src/app/services/rest/document.service.ts b/src-ui/src/app/services/rest/document.service.ts index a703f0388..d9ae04563 100644 --- a/src-ui/src/app/services/rest/document.service.ts +++ b/src-ui/src/app/services/rest/document.service.ts @@ -3,6 +3,7 @@ import { Injectable } from '@angular/core' import { Observable } from 'rxjs' import { map, tap } from 'rxjs/operators' import { AuditLogEntry } from 'src/app/data/auditlog-entry' +import { CustomField } from 'src/app/data/custom-field' import { DOCUMENT_SORT_FIELDS, DOCUMENT_SORT_FIELDS_FULLTEXT, @@ -22,6 +23,7 @@ import { import { SettingsService } from '../settings.service' import { AbstractPaperlessService } from './abstract-paperless-service' import { CorrespondentService } from './correspondent.service' +import { CustomFieldsService } from './custom-fields.service' import { DocumentTypeService } from './document-type.service' import { StoragePathService } from './storage-path.service' import { TagService } from './tag.service' @@ -55,6 +57,8 @@ export class DocumentService extends AbstractPaperlessService { return this._sortFieldsFullText } + private customFields: CustomField[] = [] + constructor( http: HttpClient, private correspondentService: CorrespondentService, @@ -62,14 +66,40 @@ export class DocumentService extends AbstractPaperlessService { private tagService: TagService, private storagePathService: StoragePathService, private permissionsService: PermissionsService, - private settingsService: SettingsService + private settingsService: SettingsService, + private customFieldService: CustomFieldsService ) { super(http, 'documents') + if ( + this.permissionsService.currentUserCan( + PermissionAction.View, + PermissionType.CustomField + ) + ) { + this.customFieldService.listAll().subscribe((fields) => { + this.customFields = fields.results + this.setupSortFields() + }) + } + this.setupSortFields() } private setupSortFields() { this._sortFields = [...DOCUMENT_SORT_FIELDS] + if ( + this.permissionsService.currentUserCan( + PermissionAction.View, + PermissionType.CustomField + ) + ) { + this.customFields.forEach((field) => { + this._sortFields.push({ + field: `custom_field_${field.id}`, + name: field.name, + }) + }) + } let excludes = [] if ( !this.permissionsService.currentUserCan(