diff --git a/src-ui/messages.xlf b/src-ui/messages.xlf index 999413c35..73b67b5b3 100644 --- a/src-ui/messages.xlf +++ b/src-ui/messages.xlf @@ -255,7 +255,7 @@ src/app/components/admin/trash/trash.component.ts - 127 + 124 src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.html @@ -607,42 +607,42 @@ Error retrieving config src/app/components/admin/config/config.component.ts - 81 + 76 Invalid JSON src/app/components/admin/config/config.component.ts - 107 + 102 Configuration updated src/app/components/admin/config/config.component.ts - 151 + 146 An error occurred updating configuration src/app/components/admin/config/config.component.ts - 156 + 151 File successfully updated src/app/components/admin/config/config.component.ts - 178 + 173 An error occurred uploading file src/app/components/admin/config/config.component.ts - 183 + 178 @@ -1392,7 +1392,7 @@ src/app/components/common/confirm-dialog/confirm-dialog.component.ts - 44 + 47 src/app/components/common/edit-dialog/correspondent-edit-dialog/correspondent-edit-dialog.component.html @@ -1810,7 +1810,7 @@ src/app/components/admin/tasks/tasks.component.ts - 124 + 122 @@ -1873,56 +1873,56 @@ Dismiss selected src/app/components/admin/tasks/tasks.component.ts - 77 + 75 Dismiss all src/app/components/admin/tasks/tasks.component.ts - 78 + 76 Confirm Dismiss All src/app/components/admin/tasks/tasks.component.ts - 121 + 119 Dismiss all tasks? src/app/components/admin/tasks/tasks.component.ts - 122 + 120 queued src/app/components/admin/tasks/tasks.component.ts - 207 + 205 started src/app/components/admin/tasks/tasks.component.ts - 209 + 207 completed src/app/components/admin/tasks/tasks.component.ts - 211 + 209 failed src/app/components/admin/tasks/tasks.component.ts - 213 + 211 @@ -2005,11 +2005,11 @@ src/app/components/admin/trash/trash.component.ts - 68 + 65 src/app/components/admin/trash/trash.component.ts - 97 + 94 src/app/components/admin/users-groups/users-groups.component.html @@ -2125,7 +2125,7 @@ src/app/components/manage/management-list/management-list.component.ts - 225 + 216 src/app/components/manage/saved-views/saved-views.component.html @@ -2151,37 +2151,37 @@ Confirm delete src/app/components/admin/trash/trash.component.ts - 64 + 61 src/app/components/admin/trash/trash.component.ts - 91 + 88 src/app/components/manage/management-list/management-list.component.ts - 221 + 212 src/app/components/manage/management-list/management-list.component.ts - 338 + 329 This operation will permanently delete this document. src/app/components/admin/trash/trash.component.ts - 65 + 62 This operation cannot be undone. src/app/components/admin/trash/trash.component.ts - 66 + 63 src/app/components/admin/trash/trash.component.ts - 95 + 92 src/app/components/admin/users-groups/users-groups.component.ts @@ -2193,7 +2193,7 @@ src/app/components/manage/custom-fields/custom-fields.component.ts - 93 + 89 src/app/components/manage/mail/mail.component.ts @@ -2205,25 +2205,25 @@ src/app/components/manage/management-list/management-list.component.ts - 340 + 331 src/app/components/manage/workflows/workflows.component.ts - 124 + 119 Document deleted src/app/components/admin/trash/trash.component.ts - 75 + 72 Error deleting document src/app/components/admin/trash/trash.component.ts - 80 + 77 src/app/components/document-detail/document-detail.component.ts @@ -2234,56 +2234,56 @@ This operation will permanently delete the selected documents. src/app/components/admin/trash/trash.component.ts - 93 + 90 This operation will permanently delete all documents in the trash. src/app/components/admin/trash/trash.component.ts - 94 + 91 Document(s) deleted src/app/components/admin/trash/trash.component.ts - 105 + 102 Error deleting document(s) src/app/components/admin/trash/trash.component.ts - 112 + 109 Document restored src/app/components/admin/trash/trash.component.ts - 125 + 122 Error restoring document src/app/components/admin/trash/trash.component.ts - 135 + 132 Document(s) restored src/app/components/admin/trash/trash.component.ts - 145 + 142 Error restoring document(s) src/app/components/admin/trash/trash.component.ts - 151 + 148 @@ -2532,7 +2532,7 @@ src/app/components/manage/custom-fields/custom-fields.component.ts - 95 + 91 src/app/components/manage/mail/mail.component.ts @@ -2544,11 +2544,11 @@ src/app/components/manage/management-list/management-list.component.ts - 342 + 333 src/app/components/manage/workflows/workflows.component.ts - 126 + 121 @@ -3095,14 +3095,14 @@ Confirmation src/app/components/common/confirm-dialog/confirm-dialog.component.ts - 20 + 23 Confirm src/app/components/common/confirm-dialog/confirm-dialog.component.ts - 32 + 35 src/app/components/common/permissions-dialog/permissions-dialog.component.html @@ -3271,22 +3271,22 @@ Saved field "". src/app/components/common/custom-fields-dropdown/custom-fields-dropdown.component.ts - 124 + 119 src/app/components/manage/custom-fields/custom-fields.component.ts - 75 + 71 Error saving field. src/app/components/common/custom-fields-dropdown/custom-fields-dropdown.component.ts - 133 + 128 src/app/components/manage/custom-fields/custom-fields.component.ts - 83 + 79 @@ -3597,14 +3597,14 @@ Create new custom field src/app/components/common/edit-dialog/custom-field-edit-dialog/custom-field-edit-dialog.component.ts - 87 + 79 Edit custom field src/app/components/common/edit-dialog/custom-field-edit-dialog/custom-field-edit-dialog.component.ts - 91 + 83 @@ -3625,14 +3625,14 @@ Create new item src/app/components/common/edit-dialog/edit-dialog.component.ts - 111 + 116 Edit item src/app/components/common/edit-dialog/edit-dialog.component.ts - 115 + 120 @@ -4168,14 +4168,14 @@ Create new storage path src/app/components/common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component.ts - 63 + 56 Edit storage path src/app/components/common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component.ts - 67 + 60 @@ -4961,7 +4961,7 @@ Not assigned src/app/components/common/filterable-dropdown/filterable-dropdown.component.ts - 370 + 373 Filter drop down element to filter for documents with no correspondent/type/tag assigned @@ -4969,7 +4969,7 @@ Open filter src/app/components/common/filterable-dropdown/filterable-dropdown.component.ts - 486 + 488 @@ -7950,28 +7950,28 @@ Confirm delete field src/app/components/manage/custom-fields/custom-fields.component.ts - 91 + 87 This operation will permanently delete this field. src/app/components/manage/custom-fields/custom-fields.component.ts - 92 + 88 Deleted field src/app/components/manage/custom-fields/custom-fields.component.ts - 101 + 97 Error deleting field. src/app/components/manage/custom-fields/custom-fields.component.ts - 107 + 103 @@ -8231,7 +8231,7 @@ src/app/components/manage/management-list/management-list.component.ts - 325 + 316 @@ -8314,7 +8314,7 @@ Automatic src/app/components/manage/management-list/management-list.component.ts - 125 + 116 src/app/data/matching-model.ts @@ -8325,7 +8325,7 @@ None src/app/components/manage/management-list/management-list.component.ts - 127 + 118 src/app/data/matching-model.ts @@ -8336,70 +8336,70 @@ Successfully created . src/app/components/manage/management-list/management-list.component.ts - 178 + 169 Error occurred while creating . src/app/components/manage/management-list/management-list.component.ts - 183 + 174 Successfully updated . src/app/components/manage/management-list/management-list.component.ts - 198 + 189 Error occurred while saving . src/app/components/manage/management-list/management-list.component.ts - 203 + 194 Associated documents will not be deleted. src/app/components/manage/management-list/management-list.component.ts - 223 + 214 Error while deleting element src/app/components/manage/management-list/management-list.component.ts - 239 + 230 Permissions updated successfully src/app/components/manage/management-list/management-list.component.ts - 318 + 309 This operation will permanently delete all objects. src/app/components/manage/management-list/management-list.component.ts - 339 + 330 Objects deleted successfully src/app/components/manage/management-list/management-list.component.ts - 353 + 344 Error deleting objects src/app/components/manage/management-list/management-list.component.ts - 359 + 350 @@ -8455,21 +8455,21 @@ Saved view "" deleted. src/app/components/manage/saved-views/saved-views.component.ts - 113 + 110 Views saved successfully. src/app/components/manage/saved-views/saved-views.component.ts - 138 + 135 Error while saving views. src/app/components/manage/saved-views/saved-views.component.ts - 143 + 140 @@ -8539,63 +8539,63 @@ Saved workflow "". src/app/components/manage/workflows/workflows.component.ts - 87 + 82 Error saving workflow. src/app/components/manage/workflows/workflows.component.ts - 95 + 90 Confirm delete workflow src/app/components/manage/workflows/workflows.component.ts - 122 + 117 This operation will permanently delete this workflow. src/app/components/manage/workflows/workflows.component.ts - 123 + 118 Deleted workflow src/app/components/manage/workflows/workflows.component.ts - 132 + 127 Error deleting workflow. src/app/components/manage/workflows/workflows.component.ts - 137 + 132 Enabled workflow src/app/components/manage/workflows/workflows.component.ts - 148 + 143 Disabled workflow src/app/components/manage/workflows/workflows.component.ts - 149 + 144 Error toggling workflow. src/app/components/manage/workflows/workflows.component.ts - 155 + 150 diff --git a/src-ui/src/app/components/admin/config/config.component.ts b/src-ui/src/app/components/admin/config/config.component.ts index 63e66d456..acc644412 100644 --- a/src-ui/src/app/components/admin/config/config.component.ts +++ b/src-ui/src/app/components/admin/config/config.component.ts @@ -17,9 +17,9 @@ import { } from 'src/app/data/paperless-config' import { ConfigService } from 'src/app/services/config.service' import { ToastService } from 'src/app/services/toast.service' -import { ComponentWithPermissions } from '../../with-permissions/with-permissions.component' import { DirtyComponent, dirtyCheck } from '@ngneat/dirty-check-forms' import { SettingsService } from 'src/app/services/settings.service' +import { LoadingComponentWithPermissions } from '../../loading-component/loading.component' @Component({ selector: 'pngx-config', @@ -27,7 +27,7 @@ import { SettingsService } from 'src/app/services/settings.service' styleUrl: './config.component.scss', }) export class ConfigComponent - extends ComponentWithPermissions + extends LoadingComponentWithPermissions implements OnInit, OnDestroy, DirtyComponent { public readonly ConfigOptionType = ConfigOptionType @@ -45,15 +45,11 @@ export class ConfigComponent return PaperlessConfigOptions.filter((o) => o.category === category) } - public loading: boolean = false - initialConfig: PaperlessConfig store: BehaviorSubject storeSub: Subscription isDirty$: Observable - private unsubscribeNotifier: Subject = new Subject() - constructor( private configService: ConfigService, private toastService: ToastService, @@ -67,7 +63,6 @@ export class ConfigComponent } ngOnInit(): void { - this.loading = true this.configService .getConfig() .pipe(takeUntil(this.unsubscribeNotifier)) diff --git a/src-ui/src/app/components/admin/logs/logs.component.html b/src-ui/src/app/components/admin/logs/logs.component.html index 7d2c5f092..efdba66d0 100644 --- a/src-ui/src/app/components/admin/logs/logs.component.html +++ b/src-ui/src/app/components/admin/logs/logs.component.html @@ -17,7 +17,7 @@ } - @if (isLoading || !logFiles.length) { + @if (loading || !logFiles.length) {
@if (!logFiles.length) { @@ -30,7 +30,7 @@
- @if (isLoading && logFiles.length) { + @if (loading && logFiles.length) {
Loading... diff --git a/src-ui/src/app/components/admin/logs/logs.component.ts b/src-ui/src/app/components/admin/logs/logs.component.ts index 1b2dbef3e..508f7b3b7 100644 --- a/src-ui/src/app/components/admin/logs/logs.component.ts +++ b/src-ui/src/app/components/admin/logs/logs.component.ts @@ -3,22 +3,28 @@ import { ElementRef, OnInit, ViewChild, - OnDestroy, ChangeDetectorRef, + OnDestroy, } from '@angular/core' -import { Subject, takeUntil } from 'rxjs' +import { takeUntil } from 'rxjs' import { LogService } from 'src/app/services/rest/log.service' +import { LoadingComponentWithPermissions } from '../../loading-component/loading.component' @Component({ selector: 'pngx-logs', templateUrl: './logs.component.html', styleUrls: ['./logs.component.scss'], }) -export class LogsComponent implements OnInit, OnDestroy { +export class LogsComponent + extends LoadingComponentWithPermissions + implements OnInit, OnDestroy +{ constructor( private logService: LogService, private changedetectorRef: ChangeDetectorRef - ) {} + ) { + super() + } public logs: string[] = [] @@ -26,22 +32,17 @@ export class LogsComponent implements OnInit, OnDestroy { public activeLog: string - private unsubscribeNotifier: Subject = new Subject() - - public isLoading: boolean = false - public autoRefreshInterval: any @ViewChild('logContainer') logContainer: ElementRef ngOnInit(): void { - this.isLoading = true this.logService .list() .pipe(takeUntil(this.unsubscribeNotifier)) .subscribe((result) => { this.logFiles = result - this.isLoading = false + this.loading = false if (this.logFiles.length > 0) { this.activeLog = this.logFiles[0] this.reloadLogs() @@ -51,25 +52,24 @@ export class LogsComponent implements OnInit, OnDestroy { } ngOnDestroy(): void { - this.unsubscribeNotifier.next(true) - this.unsubscribeNotifier.complete() + super.ngOnDestroy() clearInterval(this.autoRefreshInterval) } reloadLogs() { - this.isLoading = true + this.loading = true this.logService .get(this.activeLog) .pipe(takeUntil(this.unsubscribeNotifier)) .subscribe({ next: (result) => { this.logs = result - this.isLoading = false + this.loading = false this.scrollToBottom() }, error: () => { this.logs = [] - this.isLoading = false + this.loading = false }, }) } diff --git a/src-ui/src/app/components/admin/tasks/tasks.component.ts b/src-ui/src/app/components/admin/tasks/tasks.component.ts index 6539b3692..f88490a05 100644 --- a/src-ui/src/app/components/admin/tasks/tasks.component.ts +++ b/src-ui/src/app/components/admin/tasks/tasks.component.ts @@ -12,7 +12,7 @@ import { import { PaperlessTask } from 'src/app/data/paperless-task' import { TasksService } from 'src/app/services/tasks.service' import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component' -import { ComponentWithPermissions } from '../../with-permissions/with-permissions.component' +import { LoadingComponentWithPermissions } from '../../loading-component/loading.component' export enum TaskTab { Queued = 'queued', @@ -37,7 +37,7 @@ const FILTER_TARGETS = [ styleUrls: ['./tasks.component.scss'], }) export class TasksComponent - extends ComponentWithPermissions + extends LoadingComponentWithPermissions implements OnInit, OnDestroy { public activeTab: TaskTab @@ -70,8 +70,6 @@ export class TasksComponent : FILTER_TARGETS.slice(0, 1) } - private unsubscribeNotifier: Subject = new Subject() - get dismissButtonText(): string { return this.selectedTasks.size > 0 ? $localize`Dismiss selected` @@ -101,9 +99,9 @@ export class TasksComponent } ngOnDestroy() { + super.ngOnDestroy() this.tasksService.cancelPending() clearInterval(this.autoRefreshInterval) - this.unsubscribeNotifier.next(this) } dismissTask(task: PaperlessTask) { diff --git a/src-ui/src/app/components/admin/trash/trash.component.html b/src-ui/src/app/components/admin/trash/trash.component.html index a148f2033..d03d8d98e 100644 --- a/src-ui/src/app/components/admin/trash/trash.component.html +++ b/src-ui/src/app/components/admin/trash/trash.component.html @@ -38,7 +38,7 @@ - @if (isLoading) { + @if (loading) {
@@ -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 @@ - @if (isLoading) { + @if (loading) {
@@ -109,7 +109,7 @@
-@if (!isLoading) { +@if (!loading) {
@if (collectionSize > 0) {
diff --git a/src-ui/src/app/components/manage/management-list/management-list.component.ts b/src-ui/src/app/components/manage/management-list/management-list.component.ts index 50ae1c86b..164b2fa52 100644 --- a/src-ui/src/app/components/manage/management-list/management-list.component.ts +++ b/src-ui/src/app/components/manage/management-list/management-list.component.ts @@ -39,8 +39,8 @@ import { import { ToastService } from 'src/app/services/toast.service' import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component' import { EditDialogMode } from '../../common/edit-dialog/edit-dialog.component' -import { ComponentWithPermissions } from '../../with-permissions/with-permissions.component' import { PermissionsDialogComponent } from '../../common/permissions-dialog/permissions-dialog.component' +import { LoadingComponentWithPermissions } from '../../loading-component/loading.component' export interface ManagementListColumn { key: string @@ -56,7 +56,7 @@ export interface ManagementListColumn { @Directive() export abstract class ManagementListComponent - extends ComponentWithPermissions + extends LoadingComponentWithPermissions implements OnInit, OnDestroy { constructor( @@ -86,8 +86,6 @@ export abstract class ManagementListComponent public sortField: string public sortReverse: boolean - public isLoading: boolean = false - private nameFilterDebounce: Subject protected unsubscribeNotifier: Subject = new Subject() protected _nameFilter: string @@ -95,8 +93,6 @@ export abstract class ManagementListComponent public selectedObjects: Set = new Set() public togggleAll: boolean = false - public reveal: boolean = false - ngOnInit(): void { this.reloadData() @@ -115,11 +111,6 @@ export abstract class ManagementListComponent }) } - ngOnDestroy() { - this.unsubscribeNotifier.next(true) - this.unsubscribeNotifier.complete() - } - getMatching(o: MatchingModel) { if (o.matching_algorithm == MATCH_AUTO) { return $localize`Automatic` @@ -141,7 +132,7 @@ export abstract class ManagementListComponent } reloadData(extraParams: { [key: string]: any } = null) { - this.isLoading = true + this.loading = true this.clearSelection() this.service .listFiltered( @@ -163,7 +154,7 @@ export abstract class ManagementListComponent ) .subscribe(() => { this.reveal = true - this.isLoading = false + this.loading = false }) } diff --git a/src-ui/src/app/components/manage/saved-views/saved-views.component.ts b/src-ui/src/app/components/manage/saved-views/saved-views.component.ts index dc09c71e4..ba72cb6e5 100644 --- a/src-ui/src/app/components/manage/saved-views/saved-views.component.ts +++ b/src-ui/src/app/components/manage/saved-views/saved-views.component.ts @@ -3,11 +3,11 @@ import { FormControl, FormGroup } from '@angular/forms' import { SavedView } from 'src/app/data/saved-view' import { SavedViewService } from 'src/app/services/rest/saved-view.service' import { SettingsService } from 'src/app/services/settings.service' -import { ComponentWithPermissions } from '../../with-permissions/with-permissions.component' import { DisplayMode } from 'src/app/data/document' -import { BehaviorSubject, Observable, Subject, Subscription } from 'rxjs' +import { BehaviorSubject, Observable, takeUntil } from 'rxjs' import { dirtyCheck } from '@ngneat/dirty-check-forms' import { ToastService } from 'src/app/services/toast.service' +import { LoadingComponentWithPermissions } from '../../loading-component/loading.component' @Component({ selector: 'pngx-saved-views', @@ -15,7 +15,7 @@ import { ToastService } from 'src/app/services/toast.service' styleUrl: './saved-views.component.scss', }) export class SavedViewsComponent - extends ComponentWithPermissions + extends LoadingComponentWithPermissions implements OnInit, OnDestroy { DisplayMode = DisplayMode @@ -27,11 +27,7 @@ export class SavedViewsComponent }) private store: BehaviorSubject - private storeSub: Subscription public isDirty$: Observable - private isDirty: boolean = false - private unsubscribeNotifier: Subject = new Subject() - private savePending: boolean = false get displayFields() { return this.settings.allDisplayFields @@ -56,9 +52,7 @@ export class SavedViewsComponent ngOnDestroy(): void { this.settings.organizingSidebarSavedViews = false - this.unsubscribeNotifier.next(this) - this.unsubscribeNotifier.complete() - this.storeSub.unsubscribe() + super.ngOnDestroy() } private initialize() { @@ -93,9 +87,12 @@ export class SavedViewsComponent } this.store = new BehaviorSubject(storeData) - this.storeSub = this.store.asObservable().subscribe((state) => { - this.savedViewsForm.patchValue(state, { emitEvent: false }) - }) + this.store + .asObservable() + .pipe(takeUntil(this.unsubscribeNotifier)) + .subscribe((state) => { + this.savedViewsForm.patchValue(state, { emitEvent: false }) + }) // Initialize dirtyCheck this.isDirty$ = dirtyCheck(this.savedViewsForm, this.store.asObservable()) diff --git a/src-ui/src/app/components/manage/workflows/workflows.component.ts b/src-ui/src/app/components/manage/workflows/workflows.component.ts index 106b99485..1c04ff5d1 100644 --- a/src-ui/src/app/components/manage/workflows/workflows.component.ts +++ b/src-ui/src/app/components/manage/workflows/workflows.component.ts @@ -1,7 +1,6 @@ import { Component, OnInit } from '@angular/core' import { WorkflowService } from 'src/app/services/rest/workflow.service' -import { ComponentWithPermissions } from '../../with-permissions/with-permissions.component' -import { delay, Subject, takeUntil, tap } from 'rxjs' +import { delay, takeUntil, tap } from 'rxjs' import { Workflow } from 'src/app/data/workflow' import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { ToastService } from 'src/app/services/toast.service' @@ -12,6 +11,7 @@ import { } from '../../common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component' import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component' import { EditDialogMode } from '../../common/edit-dialog/edit-dialog.component' +import { LoadingComponentWithPermissions } from '../../loading-component/loading.component' @Component({ selector: 'pngx-workflows', @@ -19,16 +19,11 @@ import { EditDialogMode } from '../../common/edit-dialog/edit-dialog.component' styleUrls: ['./workflows.component.scss'], }) export class WorkflowsComponent - extends ComponentWithPermissions + extends LoadingComponentWithPermissions implements OnInit { public workflows: Workflow[] = [] - private unsubscribeNotifier: Subject = new Subject() - - public loading: boolean = false - public reveal: boolean = false - constructor( private workflowService: WorkflowService, public permissionsService: PermissionsService,