mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-09 09:58:20 -05:00
Merge pull request #4055 from paperless-ngx/feature-frontend-handle-slowness
Enhancement: frontend better handle slow backend requests
This commit is contained in:
commit
e3352ea426
@ -1,5 +1,5 @@
|
|||||||
<div class="btn-group w-100" ngbDropdown role="group">
|
<div class="btn-group w-100" ngbDropdown role="group">
|
||||||
<button class="btn btn-sm" id="dropdown{{title}}" ngbDropdownToggle [ngClass]="dateBefore || dateAfter ? 'btn-primary' : 'btn-outline-primary'">
|
<button class="btn btn-sm" id="dropdown{{title}}" ngbDropdownToggle [ngClass]="dateBefore || dateAfter ? 'btn-primary' : 'btn-outline-primary'" [disabled]="disabled">
|
||||||
{{title}}
|
{{title}}
|
||||||
<app-clearable-badge [selected]="isActive" (cleared)="reset()"></app-clearable-badge><span class="visually-hidden">selected</span>
|
<app-clearable-badge [selected]="isActive" (cleared)="reset()"></app-clearable-badge><span class="visually-hidden">selected</span>
|
||||||
</button>
|
</button>
|
||||||
|
@ -85,6 +85,9 @@ export class DateDropdownComponent implements OnInit, OnDestroy {
|
|||||||
@Output()
|
@Output()
|
||||||
datesSet = new EventEmitter<DateSelection>()
|
datesSet = new EventEmitter<DateSelection>()
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
disabled: boolean = false
|
||||||
|
|
||||||
get isActive(): boolean {
|
get isActive(): boolean {
|
||||||
return (
|
return (
|
||||||
this.relativeDate !== null ||
|
this.relativeDate !== null ||
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<div class="btn-group w-100" ngbDropdown role="group">
|
<div class="btn-group w-100" ngbDropdown role="group">
|
||||||
<button class="btn btn-sm" id="dropdown{{title}}" ngbDropdownToggle [ngClass]="isActive ? 'btn-primary' : 'btn-outline-primary'">
|
<button class="btn btn-sm" id="dropdown{{title}}" ngbDropdownToggle [ngClass]="isActive ? 'btn-primary' : 'btn-outline-primary'" [disabled]="disabled">
|
||||||
<svg class="toolbaricon" fill="currentColor">
|
<svg class="toolbaricon" fill="currentColor">
|
||||||
<use xlink:href="assets/bootstrap-icons.svg#person-fill-lock" />
|
<use xlink:href="assets/bootstrap-icons.svg#person-fill-lock" />
|
||||||
</svg>
|
</svg>
|
||||||
|
@ -4,11 +4,10 @@ import {
|
|||||||
OnDestroy,
|
OnDestroy,
|
||||||
OnInit,
|
OnInit,
|
||||||
QueryList,
|
QueryList,
|
||||||
ViewChild,
|
|
||||||
ViewChildren,
|
ViewChildren,
|
||||||
} from '@angular/core'
|
} from '@angular/core'
|
||||||
import { Router } from '@angular/router'
|
import { Router } from '@angular/router'
|
||||||
import { Subscription } from 'rxjs'
|
import { Subject, takeUntil } from 'rxjs'
|
||||||
import { PaperlessDocument } from 'src/app/data/paperless-document'
|
import { PaperlessDocument } from 'src/app/data/paperless-document'
|
||||||
import { PaperlessSavedView } from 'src/app/data/paperless-saved-view'
|
import { PaperlessSavedView } from 'src/app/data/paperless-saved-view'
|
||||||
import { ConsumerStatusService } from 'src/app/services/consumer-status.service'
|
import { ConsumerStatusService } from 'src/app/services/consumer-status.service'
|
||||||
@ -49,7 +48,7 @@ export class SavedViewWidgetComponent
|
|||||||
|
|
||||||
documents: PaperlessDocument[] = []
|
documents: PaperlessDocument[] = []
|
||||||
|
|
||||||
subscription: Subscription
|
unsubscribeNotifier: Subject<any> = new Subject()
|
||||||
|
|
||||||
@ViewChildren('popover') popovers: QueryList<NgbPopover>
|
@ViewChildren('popover') popovers: QueryList<NgbPopover>
|
||||||
popover: NgbPopover
|
popover: NgbPopover
|
||||||
@ -59,15 +58,17 @@ export class SavedViewWidgetComponent
|
|||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.reload()
|
this.reload()
|
||||||
this.subscription = this.consumerStatusService
|
this.consumerStatusService
|
||||||
.onDocumentConsumptionFinished()
|
.onDocumentConsumptionFinished()
|
||||||
.subscribe((status) => {
|
.pipe(takeUntil(this.unsubscribeNotifier))
|
||||||
|
.subscribe(() => {
|
||||||
this.reload()
|
this.reload()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.subscription.unsubscribe()
|
this.unsubscribeNotifier.next(true)
|
||||||
|
this.unsubscribeNotifier.complete()
|
||||||
}
|
}
|
||||||
|
|
||||||
reload() {
|
reload() {
|
||||||
@ -81,6 +82,7 @@ export class SavedViewWidgetComponent
|
|||||||
this.savedView.filter_rules,
|
this.savedView.filter_rules,
|
||||||
{ truncate_content: true }
|
{ truncate_content: true }
|
||||||
)
|
)
|
||||||
|
.pipe(takeUntil(this.unsubscribeNotifier))
|
||||||
.subscribe((result) => {
|
.subscribe((result) => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.documents = result.results
|
this.documents = result.results
|
||||||
|
@ -185,7 +185,7 @@ export class DocumentListComponent
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
// unsubscribes all
|
this.list.cancelPending()
|
||||||
this.unsubscribeNotifier.next(this)
|
this.unsubscribeNotifier.next(this)
|
||||||
this.unsubscribeNotifier.complete()
|
this.unsubscribeNotifier.complete()
|
||||||
}
|
}
|
||||||
|
@ -2,16 +2,23 @@
|
|||||||
|
|
||||||
</app-page-header>
|
</app-page-header>
|
||||||
|
|
||||||
|
|
||||||
<ul ngbNav #nav="ngbNav" [(activeId)]="activeLog" (activeIdChange)="reloadLogs()" class="nav-tabs">
|
<ul ngbNav #nav="ngbNav" [(activeId)]="activeLog" (activeIdChange)="reloadLogs()" class="nav-tabs">
|
||||||
<li *ngFor="let logFile of logFiles" [ngbNavItem]="logFile">
|
<li *ngFor="let logFile of logFiles" [ngbNavItem]="logFile">
|
||||||
<a ngbNavLink>{{logFile}}.log</a>
|
<a ngbNavLink>{{logFile}}.log</a>
|
||||||
</li>
|
</li>
|
||||||
|
<div *ngIf="isLoading && !logFiles.length" class="pb-2">
|
||||||
|
<div class="spinner-border spinner-border-sm me-2" role="status"></div>
|
||||||
|
<ng-container i18n>Loading...</ng-container>
|
||||||
|
</div>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div [ngbNavOutlet]="nav" class="mt-2"></div>
|
<div [ngbNavOutlet]="nav" class="mt-2"></div>
|
||||||
|
|
||||||
<div class="bg-dark p-3 text-light font-monospace log-container" #logContainer>
|
<div class="bg-dark p-3 text-light font-monospace log-container" #logContainer>
|
||||||
|
<div *ngIf="isLoading && logFiles.length">
|
||||||
|
<div class="spinner-border spinner-border-sm me-2" role="status"></div>
|
||||||
|
<ng-container i18n>Loading...</ng-container>
|
||||||
|
</div>
|
||||||
<p
|
<p
|
||||||
class="m-0 p-0 log-entry-{{getLogLevel(log)}}"
|
class="m-0 p-0 log-entry-{{getLogLevel(log)}}"
|
||||||
*ngFor="let log of logs">{{log}}</p>
|
*ngFor="let log of logs">{{log}}</p>
|
||||||
|
@ -4,7 +4,9 @@ import {
|
|||||||
OnInit,
|
OnInit,
|
||||||
AfterViewChecked,
|
AfterViewChecked,
|
||||||
ViewChild,
|
ViewChild,
|
||||||
|
OnDestroy,
|
||||||
} from '@angular/core'
|
} from '@angular/core'
|
||||||
|
import { Subject, takeUntil } from 'rxjs'
|
||||||
import { LogService } from 'src/app/services/rest/log.service'
|
import { LogService } from 'src/app/services/rest/log.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -12,40 +14,60 @@ import { LogService } from 'src/app/services/rest/log.service'
|
|||||||
templateUrl: './logs.component.html',
|
templateUrl: './logs.component.html',
|
||||||
styleUrls: ['./logs.component.scss'],
|
styleUrls: ['./logs.component.scss'],
|
||||||
})
|
})
|
||||||
export class LogsComponent implements OnInit, AfterViewChecked {
|
export class LogsComponent implements OnInit, AfterViewChecked, OnDestroy {
|
||||||
constructor(private logService: LogService) {}
|
constructor(private logService: LogService) {}
|
||||||
|
|
||||||
logs: string[] = []
|
public logs: string[] = []
|
||||||
|
|
||||||
logFiles: string[] = []
|
public logFiles: string[] = []
|
||||||
|
|
||||||
activeLog: string
|
public activeLog: string
|
||||||
|
|
||||||
|
private unsubscribeNotifier: Subject<any> = new Subject()
|
||||||
|
|
||||||
|
public isLoading: boolean = false
|
||||||
|
|
||||||
@ViewChild('logContainer') logContainer: ElementRef
|
@ViewChild('logContainer') logContainer: ElementRef
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.logService.list().subscribe((result) => {
|
this.isLoading = true
|
||||||
this.logFiles = result
|
this.logService
|
||||||
if (this.logFiles.length > 0) {
|
.list()
|
||||||
this.activeLog = this.logFiles[0]
|
.pipe(takeUntil(this.unsubscribeNotifier))
|
||||||
this.reloadLogs()
|
.subscribe((result) => {
|
||||||
}
|
this.logFiles = result
|
||||||
})
|
this.isLoading = false
|
||||||
|
if (this.logFiles.length > 0) {
|
||||||
|
this.activeLog = this.logFiles[0]
|
||||||
|
this.reloadLogs()
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewChecked() {
|
ngAfterViewChecked() {
|
||||||
this.scrollToBottom()
|
this.scrollToBottom()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.unsubscribeNotifier.next(true)
|
||||||
|
this.unsubscribeNotifier.complete()
|
||||||
|
}
|
||||||
|
|
||||||
reloadLogs() {
|
reloadLogs() {
|
||||||
this.logService.get(this.activeLog).subscribe({
|
this.isLoading = true
|
||||||
next: (result) => {
|
this.logService
|
||||||
this.logs = result
|
.get(this.activeLog)
|
||||||
},
|
.pipe(takeUntil(this.unsubscribeNotifier))
|
||||||
error: () => {
|
.subscribe({
|
||||||
this.logs = []
|
next: (result) => {
|
||||||
},
|
this.logs = result
|
||||||
})
|
this.isLoading = false
|
||||||
|
},
|
||||||
|
error: () => {
|
||||||
|
this.logs = []
|
||||||
|
this.isLoading = false
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
getLogLevel(log: string) {
|
getLogLevel(log: string) {
|
||||||
|
@ -24,6 +24,12 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
<tr *ngIf="isLoading">
|
||||||
|
<td colspan="5">
|
||||||
|
<div class="spinner-border spinner-border-sm me-2" role="status"></div>
|
||||||
|
<ng-container i18n>Loading...</ng-container>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr *ngFor="let object of data">
|
<tr *ngFor="let object of data">
|
||||||
<td scope="row">{{ object.name }}</td>
|
<td scope="row">{{ object.name }}</td>
|
||||||
<td scope="row" class="d-none d-sm-table-cell">{{ getMatching(object) }}</td>
|
<td scope="row" class="d-none d-sm-table-cell">{{ getMatching(object) }}</td>
|
||||||
@ -69,7 +75,7 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<div class="d-flex">
|
<div class="d-flex" *ngIf="!isLoading">
|
||||||
<div i18n *ngIf="collectionSize > 0">{collectionSize, plural, =1 {One {{typeName}}} other {{{collectionSize || 0}} total {{typeNamePlural}}}}</div>
|
<div i18n *ngIf="collectionSize > 0">{collectionSize, plural, =1 {One {{typeName}}} other {{{collectionSize || 0}} total {{typeNamePlural}}}}</div>
|
||||||
<ngb-pagination *ngIf="collectionSize > 20" class="ms-auto" [pageSize]="25" [collectionSize]="collectionSize" [(page)]="page" [maxSize]="5" (pageChange)="reloadData()" size="sm" aria-label="Pagination"></ngb-pagination>
|
<ngb-pagination *ngIf="collectionSize > 20" class="ms-auto" [pageSize]="25" [collectionSize]="collectionSize" [(page)]="page" [maxSize]="5" (pageChange)="reloadData()" size="sm" aria-label="Pagination"></ngb-pagination>
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,7 +7,7 @@ import {
|
|||||||
} from '@angular/core'
|
} from '@angular/core'
|
||||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||||
import { Subject, Subscription } from 'rxjs'
|
import { Subject, Subscription } from 'rxjs'
|
||||||
import { debounceTime, distinctUntilChanged } from 'rxjs/operators'
|
import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators'
|
||||||
import {
|
import {
|
||||||
MatchingModel,
|
MatchingModel,
|
||||||
MATCHING_ALGORITHMS,
|
MATCHING_ALGORITHMS,
|
||||||
@ -76,8 +76,10 @@ export abstract class ManagementListComponent<T extends ObjectWithId>
|
|||||||
public sortField: string
|
public sortField: string
|
||||||
public sortReverse: boolean
|
public sortReverse: boolean
|
||||||
|
|
||||||
|
public isLoading: boolean = false
|
||||||
|
|
||||||
private nameFilterDebounce: Subject<string>
|
private nameFilterDebounce: Subject<string>
|
||||||
private subscription: Subscription
|
private unsubscribeNotifier: Subject<any> = new Subject()
|
||||||
private _nameFilter: string
|
private _nameFilter: string
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
@ -85,8 +87,12 @@ export abstract class ManagementListComponent<T extends ObjectWithId>
|
|||||||
|
|
||||||
this.nameFilterDebounce = new Subject<string>()
|
this.nameFilterDebounce = new Subject<string>()
|
||||||
|
|
||||||
this.subscription = this.nameFilterDebounce
|
this.nameFilterDebounce
|
||||||
.pipe(debounceTime(400), distinctUntilChanged())
|
.pipe(
|
||||||
|
takeUntil(this.unsubscribeNotifier),
|
||||||
|
debounceTime(400),
|
||||||
|
distinctUntilChanged()
|
||||||
|
)
|
||||||
.subscribe((title) => {
|
.subscribe((title) => {
|
||||||
this._nameFilter = title
|
this._nameFilter = title
|
||||||
this.page = 1
|
this.page = 1
|
||||||
@ -95,7 +101,8 @@ export abstract class ManagementListComponent<T extends ObjectWithId>
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.subscription.unsubscribe()
|
this.unsubscribeNotifier.next(true)
|
||||||
|
this.unsubscribeNotifier.complete()
|
||||||
}
|
}
|
||||||
|
|
||||||
getMatching(o: MatchingModel) {
|
getMatching(o: MatchingModel) {
|
||||||
@ -119,6 +126,7 @@ export abstract class ManagementListComponent<T extends ObjectWithId>
|
|||||||
}
|
}
|
||||||
|
|
||||||
reloadData() {
|
reloadData() {
|
||||||
|
this.isLoading = true
|
||||||
this.service
|
this.service
|
||||||
.listFiltered(
|
.listFiltered(
|
||||||
this.page,
|
this.page,
|
||||||
@ -128,9 +136,11 @@ export abstract class ManagementListComponent<T extends ObjectWithId>
|
|||||||
this._nameFilter,
|
this._nameFilter,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
|
.pipe(takeUntil(this.unsubscribeNotifier))
|
||||||
.subscribe((c) => {
|
.subscribe((c) => {
|
||||||
this.data = c.results
|
this.data = c.results
|
||||||
this.collectionSize = c.count
|
this.collectionSize = c.count
|
||||||
|
this.isLoading = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,19 +202,22 @@ export abstract class ManagementListComponent<T extends ObjectWithId>
|
|||||||
activeModal.componentInstance.btnCaption = $localize`Delete`
|
activeModal.componentInstance.btnCaption = $localize`Delete`
|
||||||
activeModal.componentInstance.confirmClicked.subscribe(() => {
|
activeModal.componentInstance.confirmClicked.subscribe(() => {
|
||||||
activeModal.componentInstance.buttonsEnabled = false
|
activeModal.componentInstance.buttonsEnabled = false
|
||||||
this.service.delete(object).subscribe({
|
this.service
|
||||||
next: () => {
|
.delete(object)
|
||||||
activeModal.close()
|
.pipe(takeUntil(this.unsubscribeNotifier))
|
||||||
this.reloadData()
|
.subscribe({
|
||||||
},
|
next: () => {
|
||||||
error: (error) => {
|
activeModal.close()
|
||||||
activeModal.componentInstance.buttonsEnabled = true
|
this.reloadData()
|
||||||
this.toastService.showError(
|
},
|
||||||
$localize`Error while deleting element`,
|
error: (error) => {
|
||||||
error
|
activeModal.componentInstance.buttonsEnabled = true
|
||||||
)
|
this.toastService.showError(
|
||||||
},
|
$localize`Error while deleting element`,
|
||||||
})
|
error
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Component, OnInit, OnDestroy } from '@angular/core'
|
import { Component, OnInit, OnDestroy } from '@angular/core'
|
||||||
import { Router } from '@angular/router'
|
import { Router } from '@angular/router'
|
||||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
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 { PaperlessTask } from 'src/app/data/paperless-task'
|
||||||
import { TasksService } from 'src/app/services/tasks.service'
|
import { TasksService } from 'src/app/services/tasks.service'
|
||||||
import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component'
|
import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component'
|
||||||
@ -18,7 +18,6 @@ export class TasksComponent
|
|||||||
{
|
{
|
||||||
public activeTab: string
|
public activeTab: string
|
||||||
public selectedTasks: Set<number> = new Set()
|
public selectedTasks: Set<number> = new Set()
|
||||||
private unsubscribeNotifer = new Subject()
|
|
||||||
public expandedTask: number
|
public expandedTask: number
|
||||||
|
|
||||||
public pageSize: number = 25
|
public pageSize: number = 25
|
||||||
@ -43,7 +42,7 @@ export class TasksComponent
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.unsubscribeNotifer.next(true)
|
this.tasksService.cancelPending()
|
||||||
}
|
}
|
||||||
|
|
||||||
dismissTask(task: PaperlessTask) {
|
dismissTask(task: PaperlessTask) {
|
||||||
|
@ -103,6 +103,7 @@ describe('DocumentListViewService', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
documentListViewService.cancelPending()
|
||||||
httpTestingController.verify()
|
httpTestingController.verify()
|
||||||
sessionStorage.clear()
|
sessionStorage.clear()
|
||||||
})
|
})
|
||||||
@ -425,4 +426,13 @@ describe('DocumentListViewService', () => {
|
|||||||
})
|
})
|
||||||
expect(documentListViewService.selected.size).toEqual(3)
|
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()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { ParamMap, Router } from '@angular/router'
|
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 { FilterRule } from '../data/filter-rule'
|
||||||
import {
|
import {
|
||||||
filterRulesDiffer,
|
filterRulesDiffer,
|
||||||
@ -82,6 +82,8 @@ export class DocumentListViewService {
|
|||||||
|
|
||||||
currentPageSize: number = this.settings.get(SETTINGS_KEYS.DOCUMENT_LIST_SIZE)
|
currentPageSize: number = this.settings.get(SETTINGS_KEYS.DOCUMENT_LIST_SIZE)
|
||||||
|
|
||||||
|
private unsubscribeNotifier: Subject<any> = new Subject()
|
||||||
|
|
||||||
private listViewStates: Map<number, ListViewState> = new Map()
|
private listViewStates: Map<number, ListViewState> = new Map()
|
||||||
|
|
||||||
private _activeSavedViewId: number = null
|
private _activeSavedViewId: number = null
|
||||||
@ -143,6 +145,10 @@ export class DocumentListViewService {
|
|||||||
return this.listViewStates.get(this._activeSavedViewId)
|
return this.listViewStates.get(this._activeSavedViewId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public cancelPending(): void {
|
||||||
|
this.unsubscribeNotifier.next(true)
|
||||||
|
}
|
||||||
|
|
||||||
activateSavedView(view: PaperlessSavedView) {
|
activateSavedView(view: PaperlessSavedView) {
|
||||||
this.rangeSelectionAnchorIndex = this.lastRangeSelectionToIndex = null
|
this.rangeSelectionAnchorIndex = this.lastRangeSelectionToIndex = null
|
||||||
if (view) {
|
if (view) {
|
||||||
@ -210,6 +216,7 @@ export class DocumentListViewService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
reload(onFinish?, updateQueryParams: boolean = true) {
|
reload(onFinish?, updateQueryParams: boolean = true) {
|
||||||
|
this.cancelPending()
|
||||||
this.isReloading = true
|
this.isReloading = true
|
||||||
this.error = null
|
this.error = null
|
||||||
let activeListViewState = this.activeListViewState
|
let activeListViewState = this.activeListViewState
|
||||||
@ -222,6 +229,7 @@ export class DocumentListViewService {
|
|||||||
activeListViewState.filterRules,
|
activeListViewState.filterRules,
|
||||||
{ truncate_content: true }
|
{ truncate_content: true }
|
||||||
)
|
)
|
||||||
|
.pipe(takeUntil(this.unsubscribeNotifier))
|
||||||
.subscribe({
|
.subscribe({
|
||||||
next: (result) => {
|
next: (result) => {
|
||||||
this.initialized = true
|
this.initialized = true
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { HttpClient } from '@angular/common/http'
|
import { HttpClient } from '@angular/common/http'
|
||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { first } from 'rxjs/operators'
|
import { Subject } from 'rxjs'
|
||||||
|
import { first, takeUntil } from 'rxjs/operators'
|
||||||
import {
|
import {
|
||||||
PaperlessTask,
|
PaperlessTask,
|
||||||
PaperlessTaskStatus,
|
PaperlessTaskStatus,
|
||||||
@ -14,10 +15,12 @@ import { environment } from 'src/environments/environment'
|
|||||||
export class TasksService {
|
export class TasksService {
|
||||||
private baseUrl: string = environment.apiBaseUrl
|
private baseUrl: string = environment.apiBaseUrl
|
||||||
|
|
||||||
loading: boolean
|
public loading: boolean
|
||||||
|
|
||||||
private fileTasks: PaperlessTask[] = []
|
private fileTasks: PaperlessTask[] = []
|
||||||
|
|
||||||
|
private unsubscribeNotifer: Subject<any> = new Subject()
|
||||||
|
|
||||||
public get total(): number {
|
public get total(): number {
|
||||||
return this.fileTasks.length
|
return this.fileTasks.length
|
||||||
}
|
}
|
||||||
@ -51,7 +54,7 @@ export class TasksService {
|
|||||||
|
|
||||||
this.http
|
this.http
|
||||||
.get<PaperlessTask[]>(`${this.baseUrl}tasks/`)
|
.get<PaperlessTask[]>(`${this.baseUrl}tasks/`)
|
||||||
.pipe(first())
|
.pipe(takeUntil(this.unsubscribeNotifer), first())
|
||||||
.subscribe((r) => {
|
.subscribe((r) => {
|
||||||
this.fileTasks = r.filter((t) => t.type == PaperlessTaskType.File) // they're all File tasks, for now
|
this.fileTasks = r.filter((t) => t.type == PaperlessTaskType.File) // they're all File tasks, for now
|
||||||
this.loading = false
|
this.loading = false
|
||||||
@ -63,9 +66,13 @@ export class TasksService {
|
|||||||
.post(`${this.baseUrl}acknowledge_tasks/`, {
|
.post(`${this.baseUrl}acknowledge_tasks/`, {
|
||||||
tasks: [...task_ids],
|
tasks: [...task_ids],
|
||||||
})
|
})
|
||||||
.pipe(first())
|
.pipe(takeUntil(this.unsubscribeNotifer), first())
|
||||||
.subscribe((r) => {
|
.subscribe((r) => {
|
||||||
this.reload()
|
this.reload()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public cancelPending(): void {
|
||||||
|
this.unsubscribeNotifer.next(true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user