+
{{log}}
diff --git a/src-ui/src/app/components/manage/logs/logs.component.ts b/src-ui/src/app/components/manage/logs/logs.component.ts
index 2da52e950..e2fc2ab0b 100644
--- a/src-ui/src/app/components/manage/logs/logs.component.ts
+++ b/src-ui/src/app/components/manage/logs/logs.component.ts
@@ -4,7 +4,9 @@ import {
OnInit,
AfterViewChecked,
ViewChild,
+ OnDestroy,
} from '@angular/core'
+import { Subject, takeUntil } from 'rxjs'
import { LogService } from 'src/app/services/rest/log.service'
@Component({
@@ -12,40 +14,60 @@ import { LogService } from 'src/app/services/rest/log.service'
templateUrl: './logs.component.html',
styleUrls: ['./logs.component.scss'],
})
-export class LogsComponent implements OnInit, AfterViewChecked {
+export class LogsComponent implements OnInit, AfterViewChecked, OnDestroy {
constructor(private logService: LogService) {}
- logs: string[] = []
+ public logs: string[] = []
- logFiles: string[] = []
+ public logFiles: string[] = []
- activeLog: string
+ public activeLog: string
+
+ private unsubscribeNotifier: Subject
= new Subject()
+
+ public isLoading: boolean = false
@ViewChild('logContainer') logContainer: ElementRef
ngOnInit(): void {
- this.logService.list().subscribe((result) => {
- this.logFiles = result
- if (this.logFiles.length > 0) {
- this.activeLog = this.logFiles[0]
- this.reloadLogs()
- }
- })
+ this.isLoading = true
+ this.logService
+ .list()
+ .pipe(takeUntil(this.unsubscribeNotifier))
+ .subscribe((result) => {
+ this.logFiles = result
+ this.isLoading = false
+ if (this.logFiles.length > 0) {
+ this.activeLog = this.logFiles[0]
+ this.reloadLogs()
+ }
+ })
}
ngAfterViewChecked() {
this.scrollToBottom()
}
+ ngOnDestroy(): void {
+ this.unsubscribeNotifier.next(true)
+ this.unsubscribeNotifier.complete()
+ }
+
reloadLogs() {
- this.logService.get(this.activeLog).subscribe({
- next: (result) => {
- this.logs = result
- },
- error: () => {
- this.logs = []
- },
- })
+ this.isLoading = true
+ this.logService
+ .get(this.activeLog)
+ .pipe(takeUntil(this.unsubscribeNotifier))
+ .subscribe({
+ next: (result) => {
+ this.logs = result
+ this.isLoading = false
+ },
+ error: () => {
+ this.logs = []
+ this.isLoading = false
+ },
+ })
}
getLogLevel(log: string) {
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 377bafbea..b0fba8962 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
@@ -24,6 +24,12 @@
+
+
+
+ Loading...
+ |
+
{{ object.name }} |
{{ getMatching(object) }} |
@@ -69,7 +75,7 @@
-
+
0">{collectionSize, plural, =1 {One {{typeName}}} other {{{collectionSize || 0}} total {{typeNamePlural}}}}
20" class="ms-auto" [pageSize]="25" [collectionSize]="collectionSize" [(page)]="page" [maxSize]="5" (pageChange)="reloadData()" size="sm" aria-label="Pagination">
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 cfe82ec45..c4e2ef0ea 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
@@ -7,7 +7,7 @@ import {
} from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { Subject, Subscription } from 'rxjs'
-import { debounceTime, distinctUntilChanged } from 'rxjs/operators'
+import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators'
import {
MatchingModel,
MATCHING_ALGORITHMS,
@@ -76,8 +76,10 @@ export abstract class ManagementListComponent
public sortField: string
public sortReverse: boolean
+ public isLoading: boolean = false
+
private nameFilterDebounce: Subject
- private subscription: Subscription
+ private unsubscribeNotifier: Subject = new Subject()
private _nameFilter: string
ngOnInit(): void {
@@ -85,8 +87,12 @@ export abstract class ManagementListComponent
this.nameFilterDebounce = new Subject()
- this.subscription = this.nameFilterDebounce
- .pipe(debounceTime(400), distinctUntilChanged())
+ this.nameFilterDebounce
+ .pipe(
+ takeUntil(this.unsubscribeNotifier),
+ debounceTime(400),
+ distinctUntilChanged()
+ )
.subscribe((title) => {
this._nameFilter = title
this.page = 1
@@ -95,7 +101,8 @@ export abstract class ManagementListComponent
}
ngOnDestroy() {
- this.subscription.unsubscribe()
+ this.unsubscribeNotifier.next(true)
+ this.unsubscribeNotifier.complete()
}
getMatching(o: MatchingModel) {
@@ -119,6 +126,7 @@ export abstract class ManagementListComponent
}
reloadData() {
+ this.isLoading = true
this.service
.listFiltered(
this.page,
@@ -128,9 +136,11 @@ export abstract class ManagementListComponent
this._nameFilter,
true
)
+ .pipe(takeUntil(this.unsubscribeNotifier))
.subscribe((c) => {
this.data = c.results
this.collectionSize = c.count
+ this.isLoading = false
})
}
@@ -192,19 +202,22 @@ export abstract class ManagementListComponent
activeModal.componentInstance.btnCaption = $localize`Delete`
activeModal.componentInstance.confirmClicked.subscribe(() => {
activeModal.componentInstance.buttonsEnabled = false
- this.service.delete(object).subscribe({
- next: () => {
- activeModal.close()
- this.reloadData()
- },
- error: (error) => {
- activeModal.componentInstance.buttonsEnabled = true
- this.toastService.showError(
- $localize`Error while deleting element`,
- error
- )
- },
- })
+ this.service
+ .delete(object)
+ .pipe(takeUntil(this.unsubscribeNotifier))
+ .subscribe({
+ next: () => {
+ activeModal.close()
+ this.reloadData()
+ },
+ error: (error) => {
+ activeModal.componentInstance.buttonsEnabled = true
+ this.toastService.showError(
+ $localize`Error while deleting element`,
+ error
+ )
+ },
+ })
})
}
diff --git a/src-ui/src/app/components/manage/tasks/tasks.component.ts b/src-ui/src/app/components/manage/tasks/tasks.component.ts
index b4dcbcc21..01b5669cd 100644
--- a/src-ui/src/app/components/manage/tasks/tasks.component.ts
+++ b/src-ui/src/app/components/manage/tasks/tasks.component.ts
@@ -1,7 +1,7 @@
import { Component, OnInit, OnDestroy } from '@angular/core'
import { Router } from '@angular/router'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
-import { Subject, first } from 'rxjs'
+import { first } from 'rxjs'
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'
@@ -18,7 +18,6 @@ export class TasksComponent
{
public activeTab: string
public selectedTasks: Set = new Set()
- private unsubscribeNotifer = new Subject()
public expandedTask: number
public pageSize: number = 25
@@ -43,7 +42,7 @@ export class TasksComponent
}
ngOnDestroy() {
- this.unsubscribeNotifer.next(true)
+ this.tasksService.cancelPending()
}
dismissTask(task: PaperlessTask) {
diff --git a/src-ui/src/app/services/document-list-view.service.spec.ts b/src-ui/src/app/services/document-list-view.service.spec.ts
index 2a63e21c9..5fcfd5327 100644
--- a/src-ui/src/app/services/document-list-view.service.spec.ts
+++ b/src-ui/src/app/services/document-list-view.service.spec.ts
@@ -103,6 +103,7 @@ describe('DocumentListViewService', () => {
})
afterEach(() => {
+ documentListViewService.cancelPending()
httpTestingController.verify()
sessionStorage.clear()
})
@@ -425,4 +426,13 @@ describe('DocumentListViewService', () => {
})
expect(documentListViewService.selected.size).toEqual(3)
})
+
+ it('should cancel on reload the list', () => {
+ const cancelSpy = jest.spyOn(documentListViewService, 'cancelPending')
+ documentListViewService.reload()
+ httpTestingController.expectOne(
+ `${environment.apiBaseUrl}documents/?page=1&page_size=50&ordering=-created&truncate_content=true&tags__id__all=9`
+ )
+ expect(cancelSpy).toHaveBeenCalled()
+ })
})
diff --git a/src-ui/src/app/services/document-list-view.service.ts b/src-ui/src/app/services/document-list-view.service.ts
index ab8556c33..4fb2cda02 100644
--- a/src-ui/src/app/services/document-list-view.service.ts
+++ b/src-ui/src/app/services/document-list-view.service.ts
@@ -1,6 +1,6 @@
import { Injectable } from '@angular/core'
import { ParamMap, Router } from '@angular/router'
-import { Observable, first } from 'rxjs'
+import { Observable, Subject, first, takeUntil } from 'rxjs'
import { FilterRule } from '../data/filter-rule'
import {
filterRulesDiffer,
@@ -82,6 +82,8 @@ export class DocumentListViewService {
currentPageSize: number = this.settings.get(SETTINGS_KEYS.DOCUMENT_LIST_SIZE)
+ private unsubscribeNotifier: Subject = new Subject()
+
private listViewStates: Map = new Map()
private _activeSavedViewId: number = null
@@ -143,6 +145,10 @@ export class DocumentListViewService {
return this.listViewStates.get(this._activeSavedViewId)
}
+ public cancelPending(): void {
+ this.unsubscribeNotifier.next(true)
+ }
+
activateSavedView(view: PaperlessSavedView) {
this.rangeSelectionAnchorIndex = this.lastRangeSelectionToIndex = null
if (view) {
@@ -210,6 +216,7 @@ export class DocumentListViewService {
}
reload(onFinish?, updateQueryParams: boolean = true) {
+ this.cancelPending()
this.isReloading = true
this.error = null
let activeListViewState = this.activeListViewState
@@ -222,6 +229,7 @@ export class DocumentListViewService {
activeListViewState.filterRules,
{ truncate_content: true }
)
+ .pipe(takeUntil(this.unsubscribeNotifier))
.subscribe({
next: (result) => {
this.initialized = true
diff --git a/src-ui/src/app/services/tasks.service.ts b/src-ui/src/app/services/tasks.service.ts
index 9dfd118e7..662dd1015 100644
--- a/src-ui/src/app/services/tasks.service.ts
+++ b/src-ui/src/app/services/tasks.service.ts
@@ -1,6 +1,7 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
-import { first } from 'rxjs/operators'
+import { Subject } from 'rxjs'
+import { first, takeUntil } from 'rxjs/operators'
import {
PaperlessTask,
PaperlessTaskStatus,
@@ -14,10 +15,12 @@ import { environment } from 'src/environments/environment'
export class TasksService {
private baseUrl: string = environment.apiBaseUrl
- loading: boolean
+ public loading: boolean
private fileTasks: PaperlessTask[] = []
+ private unsubscribeNotifer: Subject = new Subject()
+
public get total(): number {
return this.fileTasks.length
}
@@ -51,7 +54,7 @@ export class TasksService {
this.http
.get(`${this.baseUrl}tasks/`)
- .pipe(first())
+ .pipe(takeUntil(this.unsubscribeNotifer), first())
.subscribe((r) => {
this.fileTasks = r.filter((t) => t.type == PaperlessTaskType.File) // they're all File tasks, for now
this.loading = false
@@ -63,9 +66,13 @@ export class TasksService {
.post(`${this.baseUrl}acknowledge_tasks/`, {
tasks: [...task_ids],
})
- .pipe(first())
+ .pipe(takeUntil(this.unsubscribeNotifer), first())
.subscribe((r) => {
this.reload()
})
}
+
+ public cancelPending(): void {
+ this.unsubscribeNotifer.next(true)
+ }
}