diff --git a/src-ui/src/app/components/admin/tasks/tasks.component.html b/src-ui/src/app/components/admin/tasks/tasks.component.html index 116d35f89..b8e4f3ff5 100644 --- a/src-ui/src/app/components/admin/tasks/tasks.component.html +++ b/src-ui/src/app/components/admin/tasks/tasks.component.html @@ -11,6 +11,9 @@ +
diff --git a/src-ui/src/app/components/admin/tasks/tasks.component.spec.ts b/src-ui/src/app/components/admin/tasks/tasks.component.spec.ts index 962895295..7a0034ea1 100644 --- a/src-ui/src/app/components/admin/tasks/tasks.component.spec.ts +++ b/src-ui/src/app/components/admin/tasks/tasks.component.spec.ts @@ -295,6 +295,7 @@ describe('TasksComponent', () => { const headerText = header.nativeElement.textContent expect(headerText).toContain('Dismiss visible') + expect(headerText).toContain('Dismiss all') expect(headerText).toContain('Auto refresh') expect(headerText).not.toContain('All types') expect(headerText).not.toContain('All sources') @@ -495,6 +496,19 @@ describe('TasksComponent', () => { expect(dismissSpy).toHaveBeenCalledWith(new Set([467, 466])) }) + it('should support dismiss all tasks', () => { + let modal: NgbModalRef + modalService.activeInstances.subscribe((m) => (modal = m[m.length - 1])) + const dismissSpy = jest.spyOn(tasksService, 'dismissAllTasks') + + component.dismissAllTasks() + + expect(modal).not.toBeUndefined() + expect(modal.componentInstance.messageBold).toBe('Dismiss all 7 tasks?') + modal.componentInstance.confirmClicked.emit() + expect(dismissSpy).toHaveBeenCalled() + }) + it('should dismiss the currently visible scoped and filtered tasks', () => { component.setSection(TaskSection.InProgress) component.setTaskType(PaperlessTaskType.SanityCheck) 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 884ede0d6..4aff56c6d 100644 --- a/src-ui/src/app/components/admin/tasks/tasks.component.ts +++ b/src-ui/src/app/components/admin/tasks/tasks.component.ts @@ -334,6 +334,34 @@ export class TasksComponent } } + dismissAllTasks() { + if (this.totalTasks === 0) { + return + } + + let modal = this.modalService.open(ConfirmDialogComponent, { + backdrop: 'static', + }) + modal.componentInstance.title = $localize`Confirm Dismiss All` + modal.componentInstance.messageBold = $localize`Dismiss all ${this.totalTasks} tasks?` + modal.componentInstance.btnClass = 'btn-warning' + modal.componentInstance.btnCaption = $localize`Dismiss` + modal.componentInstance.confirmClicked.pipe(first()).subscribe(() => { + modal.componentInstance.buttonsEnabled = false + modal.close() + this.tasksService.dismissAllTasks().subscribe({ + next: () => { + this.reloadPage(false) + }, + error: (e) => { + this.toastService.showError($localize`Error dismissing tasks`, e) + modal.componentInstance.buttonsEnabled = true + }, + }) + this.clearSelection() + }) + } + expandTask(task: PaperlessTask) { this.expandedTask = this.expandedTask == task.id ? undefined : task.id } diff --git a/src-ui/src/app/services/tasks.service.spec.ts b/src-ui/src/app/services/tasks.service.spec.ts index 3cc35232d..1ae217543 100644 --- a/src-ui/src/app/services/tasks.service.spec.ts +++ b/src-ui/src/app/services/tasks.service.spec.ts @@ -80,6 +80,27 @@ describe('TasksService', () => { .flush({ count: 0, results: [] }) }) + it('calls acknowledge_tasks api endpoint on dismiss all and reloads', () => { + tasksService.dismissAllTasks().subscribe() + const req = httpTestingController.expectOne( + `${environment.apiBaseUrl}tasks/acknowledge/` + ) + expect(req.request.method).toEqual('POST') + expect(req.request.body).toEqual({ + all: true, + }) + req.flush([]) + // reload is then called + httpTestingController + .expectOne( + (req: HttpRequest) => + req.url === `${environment.apiBaseUrl}tasks/` && + req.params.get('acknowledged') === 'false' && + req.params.get('page_size') === '1000' + ) + .flush({ count: 0, results: [] }) + }) + it('groups mixed task types by status when reloading', () => { expect(tasksService.total).toEqual(0) const mockTasks = [ diff --git a/src-ui/src/app/services/tasks.service.ts b/src-ui/src/app/services/tasks.service.ts index 1eb5e0837..a3ae283ed 100644 --- a/src-ui/src/app/services/tasks.service.ts +++ b/src-ui/src/app/services/tasks.service.ts @@ -116,6 +116,20 @@ export class TasksService { ) } + public dismissAllTasks(): Observable { + return this.http + .post(`${this.baseUrl}tasks/acknowledge/`, { + all: true, + }) + .pipe( + first(), + takeUntil(this.unsubscribeNotifer), + tap(() => { + this.reload() + }) + ) + } + public cancelPending(): void { this.unsubscribeNotifer.next(true) }