@@ -88,7 +88,7 @@
-@if (!isLoading) {
+@if (!loading) {
{totalDocuments, plural, =1 {One document in trash} other {{{totalDocuments || 0}} total documents in trash}}
diff --git a/src-ui/src/app/components/admin/trash/trash.component.ts b/src-ui/src/app/components/admin/trash/trash.component.ts
index 055c5fa97..5f312cc50 100644
--- a/src-ui/src/app/components/admin/trash/trash.component.ts
+++ b/src-ui/src/app/components/admin/trash/trash.component.ts
@@ -4,25 +4,26 @@ import { Document } from 'src/app/data/document'
import { ToastService } from 'src/app/services/toast.service'
import { TrashService } from 'src/app/services/trash.service'
import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component'
-import { delay, Subject, takeUntil, tap } from 'rxjs'
+import { delay, takeUntil, tap } from 'rxjs'
import { SettingsService } from 'src/app/services/settings.service'
import { SETTINGS_KEYS } from 'src/app/data/ui-settings'
import { Router } from '@angular/router'
+import { LoadingComponentWithPermissions } from '../../loading-component/loading.component'
@Component({
selector: 'pngx-trash',
templateUrl: './trash.component.html',
styleUrl: './trash.component.scss',
})
-export class TrashComponent implements OnDestroy {
+export class TrashComponent
+ extends LoadingComponentWithPermissions
+ implements OnDestroy
+{
public documentsInTrash: Document[] = []
public selectedDocuments: Set = new Set()
public allToggled: boolean = false
public page: number = 1
public totalDocuments: number
- public isLoading: boolean = false
- public reveal: boolean = false
- unsubscribeNotifier: Subject = new Subject()
constructor(
private trashService: TrashService,
@@ -31,16 +32,12 @@ export class TrashComponent implements OnDestroy {
private settingsService: SettingsService,
private router: Router
) {
+ super()
this.reload()
}
- ngOnDestroy() {
- this.unsubscribeNotifier.next()
- this.unsubscribeNotifier.complete()
- }
-
reload() {
- this.isLoading = true
+ this.loading = true
this.trashService
.getTrash(this.page)
.pipe(
@@ -48,12 +45,12 @@ export class TrashComponent implements OnDestroy {
this.documentsInTrash = r.results
this.totalDocuments = r.count
this.selectedDocuments.clear()
+ this.loading = false
}),
delay(100)
)
.subscribe(() => {
this.reveal = true
- this.isLoading = false
})
}
diff --git a/src-ui/src/app/components/common/confirm-dialog/confirm-dialog.component.ts b/src-ui/src/app/components/common/confirm-dialog/confirm-dialog.component.ts
index 2dfb6a15d..f854f4ada 100644
--- a/src-ui/src/app/components/common/confirm-dialog/confirm-dialog.component.ts
+++ b/src-ui/src/app/components/common/confirm-dialog/confirm-dialog.component.ts
@@ -1,14 +1,17 @@
import { Component, EventEmitter, Input, Output } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { interval, Subject, take } from 'rxjs'
+import { LoadingComponentWithPermissions } from '../../loading-component/loading.component'
@Component({
selector: 'pngx-confirm-dialog',
templateUrl: './confirm-dialog.component.html',
styleUrls: ['./confirm-dialog.component.scss'],
})
-export class ConfirmDialogComponent {
- constructor(public activeModal: NgbActiveModal) {}
+export class ConfirmDialogComponent extends LoadingComponentWithPermissions {
+ constructor(public activeModal: NgbActiveModal) {
+ super()
+ }
@Output()
public confirmClicked = new EventEmitter()
diff --git a/src-ui/src/app/components/common/confirm-dialog/merge-confirm-dialog/merge-confirm-dialog.component.ts b/src-ui/src/app/components/common/confirm-dialog/merge-confirm-dialog/merge-confirm-dialog.component.ts
index 1530620e1..a8f88b943 100644
--- a/src-ui/src/app/components/common/confirm-dialog/merge-confirm-dialog/merge-confirm-dialog.component.ts
+++ b/src-ui/src/app/components/common/confirm-dialog/merge-confirm-dialog/merge-confirm-dialog.component.ts
@@ -25,8 +25,6 @@ export class MergeConfirmDialogComponent
public metadataDocumentID: number = -1
- private unsubscribeNotifier: Subject = new Subject()
-
constructor(
activeModal: NgbActiveModal,
private documentService: DocumentService,
diff --git a/src-ui/src/app/components/common/custom-field-display/custom-field-display.component.ts b/src-ui/src/app/components/common/custom-field-display/custom-field-display.component.ts
index 1ab831f46..c4f05ae7f 100644
--- a/src-ui/src/app/components/common/custom-field-display/custom-field-display.component.ts
+++ b/src-ui/src/app/components/common/custom-field-display/custom-field-display.component.ts
@@ -1,25 +1,22 @@
import { getLocaleCurrencyCode } from '@angular/common'
-import {
- Component,
- Inject,
- Input,
- LOCALE_ID,
- OnDestroy,
- OnInit,
-} from '@angular/core'
-import { Subject, takeUntil } from 'rxjs'
+import { Component, Inject, Input, LOCALE_ID, OnInit } from '@angular/core'
+import { takeUntil } from 'rxjs'
import { CustomField, CustomFieldDataType } from 'src/app/data/custom-field'
import { DisplayField, Document } from 'src/app/data/document'
import { Results } from 'src/app/data/results'
import { CustomFieldsService } from 'src/app/services/rest/custom-fields.service'
import { DocumentService } from 'src/app/services/rest/document.service'
+import { LoadingComponentWithPermissions } from '../../loading-component/loading.component'
@Component({
selector: 'pngx-custom-field-display',
templateUrl: './custom-field-display.component.html',
styleUrl: './custom-field-display.component.scss',
})
-export class CustomFieldDisplayComponent implements OnInit, OnDestroy {
+export class CustomFieldDisplayComponent
+ extends LoadingComponentWithPermissions
+ implements OnInit
+{
CustomFieldDataType = CustomFieldDataType
private _document: Document
@@ -61,7 +58,6 @@ export class CustomFieldDisplayComponent implements OnInit, OnDestroy {
private docLinkDocuments: Document[] = []
- private unsubscribeNotifier: Subject = new Subject()
private defaultCurrencyCode: any
constructor(
@@ -69,6 +65,7 @@ export class CustomFieldDisplayComponent implements OnInit, OnDestroy {
private documentService: DocumentService,
@Inject(LOCALE_ID) currentLocale: string
) {
+ super()
this.defaultCurrencyCode = getLocaleCurrencyCode(currentLocale)
this.customFieldService.listAll().subscribe((r) => {
this.customFields = r.results
@@ -120,9 +117,4 @@ export class CustomFieldDisplayComponent implements OnInit, OnDestroy {
public getSelectValue(field: CustomField, id: string): string {
return field.extra_data.select_options?.find((o) => o.id === id)?.label
}
-
- ngOnDestroy(): void {
- this.unsubscribeNotifier.next(true)
- this.unsubscribeNotifier.complete()
- }
}
diff --git a/src-ui/src/app/components/common/custom-fields-dropdown/custom-fields-dropdown.component.ts b/src-ui/src/app/components/common/custom-fields-dropdown/custom-fields-dropdown.component.ts
index 652d7f3d8..f8732c4f8 100644
--- a/src-ui/src/app/components/common/custom-fields-dropdown/custom-fields-dropdown.component.ts
+++ b/src-ui/src/app/components/common/custom-fields-dropdown/custom-fields-dropdown.component.ts
@@ -10,7 +10,7 @@ import {
ViewChildren,
} from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
-import { Subject, first, takeUntil } from 'rxjs'
+import { first, takeUntil } from 'rxjs'
import { CustomField, DATA_TYPE_LABELS } from 'src/app/data/custom-field'
import { CustomFieldInstance } from 'src/app/data/custom-field-instance'
import { CustomFieldsService } from 'src/app/services/rest/custom-fields.service'
@@ -21,13 +21,14 @@ import {
PermissionType,
PermissionsService,
} from 'src/app/services/permissions.service'
+import { LoadingComponentWithPermissions } from '../../loading-component/loading.component'
@Component({
selector: 'pngx-custom-fields-dropdown',
templateUrl: './custom-fields-dropdown.component.html',
styleUrls: ['./custom-fields-dropdown.component.scss'],
})
-export class CustomFieldsDropdownComponent implements OnDestroy {
+export class CustomFieldsDropdownComponent extends LoadingComponentWithPermissions {
@Input()
documentId: number
@@ -60,8 +61,6 @@ export class CustomFieldsDropdownComponent implements OnDestroy {
public filterText: string
- private unsubscribeNotifier: Subject = new Subject()
-
get canCreateFields(): boolean {
return this.permissionsService.currentUserCan(
PermissionAction.Add,
@@ -75,14 +74,10 @@ export class CustomFieldsDropdownComponent implements OnDestroy {
private toastService: ToastService,
private permissionsService: PermissionsService
) {
+ super()
this.getFields()
}
- ngOnDestroy(): void {
- this.unsubscribeNotifier.next(this)
- this.unsubscribeNotifier.complete()
- }
-
private getFields() {
this.customFieldsService
.listAll()
diff --git a/src-ui/src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.ts b/src-ui/src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.ts
index 2233fc5c4..e10eb6972 100644
--- a/src-ui/src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.ts
+++ b/src-ui/src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.ts
@@ -2,7 +2,6 @@ import {
Component,
EventEmitter,
Input,
- OnDestroy,
Output,
QueryList,
ViewChild,
@@ -29,6 +28,7 @@ import {
CustomFieldQueryAtom,
} from 'src/app/utils/custom-field-query-element'
import { popperOptionsReenablePreventOverflow } from 'src/app/utils/popper-options'
+import { LoadingComponentWithPermissions } from '../../loading-component/loading.component'
export class CustomFieldQueriesModel {
public queries: CustomFieldQueryElement[] = []
@@ -157,7 +157,7 @@ export class CustomFieldQueriesModel {
templateUrl: './custom-fields-query-dropdown.component.html',
styleUrls: ['./custom-fields-query-dropdown.component.scss'],
})
-export class CustomFieldsQueryDropdownComponent implements OnDestroy {
+export class CustomFieldsQueryDropdownComponent extends LoadingComponentWithPermissions {
public CustomFieldQueryComponentType = CustomFieldQueryElementType
public CustomFieldQueryOperator = CustomFieldQueryOperator
public CustomFieldDataType = CustomFieldDataType
@@ -223,19 +223,13 @@ export class CustomFieldsQueryDropdownComponent implements OnDestroy {
customFields: CustomField[] = []
- private unsubscribeNotifier: Subject = new Subject()
-
constructor(protected customFieldsService: CustomFieldsService) {
+ super()
this.selectionModel = new CustomFieldQueriesModel()
this.getFields()
this.reset()
}
- ngOnDestroy(): void {
- this.unsubscribeNotifier.next(this)
- this.unsubscribeNotifier.complete()
- }
-
public onOpenChange(open: boolean) {
if (open) {
if (this.selectionModel.queries.length === 0) {
diff --git a/src-ui/src/app/components/common/edit-dialog/custom-field-edit-dialog/custom-field-edit-dialog.component.ts b/src-ui/src/app/components/common/edit-dialog/custom-field-edit-dialog/custom-field-edit-dialog.component.ts
index e39e27edd..a3392290e 100644
--- a/src-ui/src/app/components/common/edit-dialog/custom-field-edit-dialog/custom-field-edit-dialog.component.ts
+++ b/src-ui/src/app/components/common/edit-dialog/custom-field-edit-dialog/custom-field-edit-dialog.component.ts
@@ -2,7 +2,6 @@ import {
AfterViewInit,
Component,
ElementRef,
- OnDestroy,
OnInit,
QueryList,
ViewChildren,
@@ -18,7 +17,7 @@ import { CustomFieldsService } from 'src/app/services/rest/custom-fields.service
import { UserService } from 'src/app/services/rest/user.service'
import { SettingsService } from 'src/app/services/settings.service'
import { EditDialogComponent, EditDialogMode } from '../edit-dialog.component'
-import { Subject, takeUntil } from 'rxjs'
+import { takeUntil } from 'rxjs'
@Component({
selector: 'pngx-custom-field-edit-dialog',
@@ -27,15 +26,13 @@ import { Subject, takeUntil } from 'rxjs'
})
export class CustomFieldEditDialogComponent
extends EditDialogComponent
- implements OnInit, AfterViewInit, OnDestroy
+ implements OnInit, AfterViewInit
{
CustomFieldDataType = CustomFieldDataType
@ViewChildren('selectOption')
private selectOptionInputs: QueryList
- private unsubscribeNotifier: Subject = new Subject()
-
private get selectOptions(): FormArray {
return (this.objectForm.controls.extra_data as FormGroup).controls
.select_options as FormArray
@@ -78,11 +75,6 @@ export class CustomFieldEditDialogComponent
})
}
- ngOnDestroy(): void {
- this.unsubscribeNotifier.next(true)
- this.unsubscribeNotifier.complete()
- }
-
getCreateTitle() {
return $localize`Create new custom field`
}
diff --git a/src-ui/src/app/components/common/edit-dialog/edit-dialog.component.ts b/src-ui/src/app/components/common/edit-dialog/edit-dialog.component.ts
index fe4d0bf01..ba32549f3 100644
--- a/src-ui/src/app/components/common/edit-dialog/edit-dialog.component.ts
+++ b/src-ui/src/app/components/common/edit-dialog/edit-dialog.component.ts
@@ -15,6 +15,7 @@ import { UserService } from 'src/app/services/rest/user.service'
import { PermissionsFormObject } from '../input/permissions/permissions-form/permissions-form.component'
import { SettingsService } from 'src/app/services/settings.service'
import { SETTINGS_KEYS } from 'src/app/data/ui-settings'
+import { LoadingComponentWithPermissions } from '../../loading-component/loading.component'
export enum EditDialogMode {
CREATE = 0,
@@ -23,15 +24,19 @@ export enum EditDialogMode {
@Directive()
export abstract class EditDialogComponent<
- T extends ObjectWithPermissions | ObjectWithId,
-> implements OnInit
+ T extends ObjectWithPermissions | ObjectWithId,
+ >
+ extends LoadingComponentWithPermissions
+ implements OnInit
{
constructor(
protected service: AbstractPaperlessService,
private activeModal: NgbActiveModal,
private userService: UserService,
private settingsService: SettingsService
- ) {}
+ ) {
+ super()
+ }
users: User[]
diff --git a/src-ui/src/app/components/common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component.ts b/src-ui/src/app/components/common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component.ts
index 214f08f11..ae7a047bf 100644
--- a/src-ui/src/app/components/common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component.ts
+++ b/src-ui/src/app/components/common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component.ts
@@ -41,8 +41,6 @@ export class StoragePathEditDialogComponent
public loading = false
public testLoading = false
- private unsubscribeNotifier: Subject = new Subject()
-
constructor(
service: StoragePathService,
activeModal: NgbActiveModal,
@@ -54,11 +52,6 @@ export class StoragePathEditDialogComponent
this.initPathObservables()
}
- ngOnDestroy(): void {
- this.unsubscribeNotifier.next(this)
- this.unsubscribeNotifier.complete()
- }
-
getCreateTitle() {
return $localize`Create new storage path`
}
diff --git a/src-ui/src/app/components/common/filterable-dropdown/filterable-dropdown.component.ts b/src-ui/src/app/components/common/filterable-dropdown/filterable-dropdown.component.ts
index 2351dc0da..925e4f319 100644
--- a/src-ui/src/app/components/common/filterable-dropdown/filterable-dropdown.component.ts
+++ b/src-ui/src/app/components/common/filterable-dropdown/filterable-dropdown.component.ts
@@ -6,7 +6,6 @@ import {
ElementRef,
ViewChild,
OnInit,
- OnDestroy,
} from '@angular/core'
import { FilterPipe } from 'src/app/pipes/filter.pipe'
import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap'
@@ -17,6 +16,7 @@ import { SelectionDataItem } from 'src/app/services/rest/document.service'
import { ObjectWithPermissions } from 'src/app/data/object-with-permissions'
import { HotKeyService } from 'src/app/services/hot-key.service'
import { popperOptionsReenablePreventOverflow } from 'src/app/utils/popper-options'
+import { LoadingComponentWithPermissions } from '../../loading-component/loading.component'
export interface ChangedItems {
itemsToAdd: MatchingModel[]
@@ -353,7 +353,10 @@ export class FilterableDropdownSelectionModel {
templateUrl: './filterable-dropdown.component.html',
styleUrls: ['./filterable-dropdown.component.scss'],
})
-export class FilterableDropdownComponent implements OnDestroy, OnInit {
+export class FilterableDropdownComponent
+ extends LoadingComponentWithPermissions
+ implements OnInit
+{
@ViewChild('listFilterTextInput') listFilterTextInput: ElementRef
@ViewChild('dropdown') dropdown: NgbDropdown
@ViewChild('buttonItems') buttonItems: ElementRef
@@ -467,12 +470,11 @@ export class FilterableDropdownComponent implements OnDestroy, OnInit {
private keyboardIndex: number
- private unsubscribeNotifier: Subject = new Subject()
-
constructor(
private filterPipe: FilterPipe,
private hotkeyService: HotKeyService
) {
+ super()
this.selectionModelChange.subscribe((updatedModel) => {
this.modelIsDirty = updatedModel.isDirty()
})
@@ -495,11 +497,6 @@ export class FilterableDropdownComponent implements OnDestroy, OnInit {
}
}
- ngOnDestroy(): void {
- this.unsubscribeNotifier.next(true)
- this.unsubscribeNotifier.complete()
- }
-
applyClicked() {
if (this.selectionModel.isDirty()) {
this.dropdown.close()
diff --git a/src-ui/src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.ts b/src-ui/src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.ts
index a4dbaf7d6..4256bfdd7 100644
--- a/src-ui/src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.ts
+++ b/src-ui/src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnDestroy, OnInit } from '@angular/core'
+import { Component, OnInit } from '@angular/core'
import { FormControl, FormGroup } from '@angular/forms'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { ProfileService } from 'src/app/services/profile.service'
@@ -8,18 +8,21 @@ import {
SocialAccountProvider,
} from 'src/app/data/user-profile'
import { ToastService } from 'src/app/services/toast.service'
-import { Subject, takeUntil } from 'rxjs'
+import { takeUntil } from 'rxjs'
import { Clipboard } from '@angular/cdk/clipboard'
+import { LoadingComponentWithPermissions } from '../../loading-component/loading.component'
@Component({
selector: 'pngx-profile-edit-dialog',
templateUrl: './profile-edit-dialog.component.html',
styleUrls: ['./profile-edit-dialog.component.scss'],
})
-export class ProfileEditDialogComponent implements OnInit, OnDestroy {
+export class ProfileEditDialogComponent
+ extends LoadingComponentWithPermissions
+ implements OnInit
+{
public networkActive: boolean = false
public error: any
- private unsubscribeNotifier: Subject = new Subject()
public form = new FormGroup({
email: new FormControl(''),
@@ -60,7 +63,9 @@ export class ProfileEditDialogComponent implements OnInit, OnDestroy {
public activeModal: NgbActiveModal,
private toastService: ToastService,
private clipboard: Clipboard
- ) {}
+ ) {
+ super()
+ }
ngOnInit(): void {
this.networkActive = true
@@ -93,11 +98,6 @@ export class ProfileEditDialogComponent implements OnInit, OnDestroy {
})
}
- ngOnDestroy(): void {
- this.unsubscribeNotifier.next(true)
- this.unsubscribeNotifier.complete()
- }
-
get saveDisabled(): boolean {
return this.error?.password_confirm || this.error?.email_confirm
}
diff --git a/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.ts b/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.ts
index 74c3af520..fccf007b5 100644
--- a/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.ts
+++ b/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.ts
@@ -28,7 +28,6 @@ import {
} from 'src/app/data/filter-rule-type'
import { OpenDocumentsService } from 'src/app/services/open-documents.service'
import { DocumentListViewService } from 'src/app/services/document-list-view.service'
-import { ComponentWithPermissions } from 'src/app/components/with-permissions/with-permissions.component'
import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'
import {
PermissionAction,
@@ -38,6 +37,7 @@ import {
import { CustomFieldsService } from 'src/app/services/rest/custom-fields.service'
import { CustomField, CustomFieldDataType } from 'src/app/data/custom-field'
import { SettingsService } from 'src/app/services/settings.service'
+import { LoadingComponentWithPermissions } from 'src/app/components/loading-component/loading.component'
@Component({
selector: 'pngx-saved-view-widget',
@@ -45,16 +45,13 @@ import { SettingsService } from 'src/app/services/settings.service'
styleUrls: ['./saved-view-widget.component.scss'],
})
export class SavedViewWidgetComponent
- extends ComponentWithPermissions
+ extends LoadingComponentWithPermissions
implements OnInit, OnDestroy
{
public DisplayMode = DisplayMode
public DisplayField = DisplayField
public CustomFieldDataType = CustomFieldDataType
- public loading: boolean = true
- public reveal: boolean = false
-
private customFields: CustomField[] = []
constructor(
diff --git a/src-ui/src/app/components/dashboard/widgets/widget-frame/widget-frame.component.ts b/src-ui/src/app/components/dashboard/widgets/widget-frame/widget-frame.component.ts
index 2a141be7c..0ebe3b5ea 100644
--- a/src-ui/src/app/components/dashboard/widgets/widget-frame/widget-frame.component.ts
+++ b/src-ui/src/app/components/dashboard/widgets/widget-frame/widget-frame.component.ts
@@ -1,12 +1,18 @@
import { AfterViewInit, Component, Input } from '@angular/core'
+import { LoadingComponentWithPermissions } from 'src/app/components/loading-component/loading.component'
@Component({
selector: 'pngx-widget-frame',
templateUrl: './widget-frame.component.html',
styleUrls: ['./widget-frame.component.scss'],
})
-export class WidgetFrameComponent implements AfterViewInit {
- constructor() {}
+export class WidgetFrameComponent
+ extends LoadingComponentWithPermissions
+ implements AfterViewInit
+{
+ constructor() {
+ super()
+ }
@Input()
title: string
@@ -17,8 +23,6 @@ export class WidgetFrameComponent implements AfterViewInit {
@Input()
draggable: any
- public reveal: boolean = false
-
ngAfterViewInit(): void {
setTimeout(() => {
this.reveal = true
diff --git a/src-ui/src/app/components/loading-component/loading.component.spec.ts b/src-ui/src/app/components/loading-component/loading.component.spec.ts
new file mode 100644
index 000000000..091745ce9
--- /dev/null
+++ b/src-ui/src/app/components/loading-component/loading.component.spec.ts
@@ -0,0 +1,43 @@
+import { TestBed } from '@angular/core/testing'
+import { Subject } from 'rxjs'
+import { LoadingComponentWithPermissions } from './loading.component'
+import { ComponentWithPermissions } from '../with-permissions/with-permissions.component'
+import { Component } from '@angular/core'
+
+class MockComponentWithPermissions extends ComponentWithPermissions {}
+
+@Component({
+ template: '',
+})
+class MockLoadingComponent extends LoadingComponentWithPermissions {}
+
+describe('LoadingComponentWithPermissions', () => {
+ let component: LoadingComponentWithPermissions
+
+ beforeEach(async () => {
+ TestBed.configureTestingModule({
+ declarations: [LoadingComponentWithPermissions],
+ })
+ component = new MockLoadingComponent()
+ })
+
+ it('should create', () => {
+ expect(component).toBeTruthy()
+ })
+
+ it('should have loading set to true by default', () => {
+ expect(component.loading).toBeTruthy()
+ })
+
+ it('should have reveal set to false by default', () => {
+ expect(component.reveal).toBeFalsy()
+ })
+
+ it('should call next and complete on unsubscribeNotifier with itself on destroy', () => {
+ const nextSpy = jest.spyOn(component['unsubscribeNotifier'], 'next')
+ const completeSpy = jest.spyOn(component['unsubscribeNotifier'], 'complete')
+ component.ngOnDestroy()
+ expect(nextSpy).toHaveBeenCalledWith(component)
+ expect(completeSpy).toHaveBeenCalled()
+ })
+})
diff --git a/src-ui/src/app/components/loading-component/loading.component.ts b/src-ui/src/app/components/loading-component/loading.component.ts
new file mode 100644
index 000000000..dcd8340a4
--- /dev/null
+++ b/src-ui/src/app/components/loading-component/loading.component.ts
@@ -0,0 +1,23 @@
+import { Subject } from 'rxjs'
+import { ComponentWithPermissions } from '../with-permissions/with-permissions.component'
+import { Directive, OnDestroy } from '@angular/core'
+
+@Directive()
+export abstract class LoadingComponentWithPermissions
+ extends ComponentWithPermissions
+ implements OnDestroy
+{
+ public loading: boolean = true
+ public reveal: boolean = false
+
+ protected unsubscribeNotifier: Subject = new Subject()
+
+ constructor() {
+ super()
+ }
+
+ ngOnDestroy(): void {
+ this.unsubscribeNotifier.next(this)
+ this.unsubscribeNotifier.complete()
+ }
+}
diff --git a/src-ui/src/app/components/manage/custom-fields/custom-fields.component.spec.ts b/src-ui/src/app/components/manage/custom-fields/custom-fields.component.spec.ts
index 1be5484c1..c927b52da 100644
--- a/src-ui/src/app/components/manage/custom-fields/custom-fields.component.spec.ts
+++ b/src-ui/src/app/components/manage/custom-fields/custom-fields.component.spec.ts
@@ -28,6 +28,7 @@ import {
CustomFieldQueryLogicalOperator,
CustomFieldQueryOperator,
} from 'src/app/data/custom-field-query'
+import { SettingsService } from 'src/app/services/settings.service'
const fields: CustomField[] = [
{
@@ -49,6 +50,7 @@ describe('CustomFieldsComponent', () => {
let modalService: NgbModal
let toastService: ToastService
let listViewService: DocumentListViewService
+ let settingsService: SettingsService
beforeEach(() => {
TestBed.configureTestingModule({
@@ -91,6 +93,8 @@ describe('CustomFieldsComponent', () => {
modalService = TestBed.inject(NgbModal)
toastService = TestBed.inject(ToastService)
listViewService = TestBed.inject(DocumentListViewService)
+ settingsService = TestBed.inject(SettingsService)
+ settingsService.currentUser = { id: 0, username: 'test' }
fixture = TestBed.createComponent(CustomFieldsComponent)
component = fixture.componentInstance
diff --git a/src-ui/src/app/components/manage/custom-fields/custom-fields.component.ts b/src-ui/src/app/components/manage/custom-fields/custom-fields.component.ts
index 9300a0c2c..7bf4066b9 100644
--- a/src-ui/src/app/components/manage/custom-fields/custom-fields.component.ts
+++ b/src-ui/src/app/components/manage/custom-fields/custom-fields.component.ts
@@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
-import { delay, Subject, takeUntil, tap } from 'rxjs'
+import { delay, takeUntil, tap } from 'rxjs'
import { DATA_TYPE_LABELS, CustomField } from 'src/app/data/custom-field'
import { PermissionsService } from 'src/app/services/permissions.service'
import { CustomFieldsService } from 'src/app/services/rest/custom-fields.service'
@@ -8,7 +8,6 @@ import { ToastService } from 'src/app/services/toast.service'
import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component'
import { CustomFieldEditDialogComponent } from '../../common/edit-dialog/custom-field-edit-dialog/custom-field-edit-dialog.component'
import { EditDialogMode } from '../../common/edit-dialog/edit-dialog.component'
-import { ComponentWithPermissions } from '../../with-permissions/with-permissions.component'
import { DocumentListViewService } from 'src/app/services/document-list-view.service'
import { FILTER_CUSTOM_FIELDS_QUERY } from 'src/app/data/filter-rule-type'
import {
@@ -16,6 +15,7 @@ import {
CustomFieldQueryOperator,
} from 'src/app/data/custom-field-query'
import { SettingsService } from 'src/app/services/settings.service'
+import { LoadingComponentWithPermissions } from '../../loading-component/loading.component'
@Component({
selector: 'pngx-custom-fields',
@@ -23,15 +23,11 @@ import { SettingsService } from 'src/app/services/settings.service'
styleUrls: ['./custom-fields.component.scss'],
})
export class CustomFieldsComponent
- extends ComponentWithPermissions
+ extends LoadingComponentWithPermissions
implements OnInit
{
public fields: CustomField[] = []
- public loading: boolean = true
- public reveal: boolean = false
-
- private unsubscribeNotifier: Subject = new Subject()
constructor(
private customFieldsService: CustomFieldsService,
public permissionsService: PermissionsService,
diff --git a/src-ui/src/app/components/manage/management-list/management-list.component.html b/src-ui/src/app/components/manage/management-list/management-list.component.html
index 6dbe590c7..7d4647491 100644
--- a/src-ui/src/app/components/manage/management-list/management-list.component.html
+++ b/src-ui/src/app/components/manage/management-list/management-list.component.html
@@ -44,7 +44,7 @@
|