Retry action, basic frontend, cleanup handler

This commit is contained in:
shamoon
2024-11-07 17:31:28 -08:00
parent a2e4977201
commit 62b470f691
10 changed files with 168 additions and 38 deletions

View File

@@ -81,6 +81,11 @@
</td>
<td scope="row">
<div class="btn-group" role="group">
@if (task.status === PaperlessTaskStatus.Failed) {
<button class="btn btn-sm btn-outline-primary" (click)="retryTask(task); $event.stopPropagation();" *pngxIfPermissions="{ action: PermissionAction.Change, type: PermissionType.PaperlessTask }">
<i-bs name="arrow-repeat"></i-bs>&nbsp;<ng-container i18n>Retry</ng-container>
</button>
}
<button class="btn btn-sm btn-outline-secondary" (click)="dismissTask(task); $event.stopPropagation();" *pngxIfPermissions="{ action: PermissionAction.Change, type: PermissionType.PaperlessTask }">
<i-bs name="check"></i-bs>&nbsp;<ng-container i18n>Dismiss</ng-container>
</button>

View File

@@ -31,6 +31,8 @@ import { PermissionsGuard } from 'src/app/guards/permissions.guard'
import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
import { FormsModule } from '@angular/forms'
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'
import { ToastService } from 'src/app/services/toast.service'
import { of, throwError } from 'rxjs'
const tasks: PaperlessTask[] = [
{
@@ -115,6 +117,7 @@ describe('TasksComponent', () => {
let modalService: NgbModal
let router: Router
let httpTestingController: HttpTestingController
let toastService: ToastService
let reloadSpy
beforeEach(async () => {
@@ -152,6 +155,7 @@ describe('TasksComponent', () => {
httpTestingController = TestBed.inject(HttpTestingController)
modalService = TestBed.inject(NgbModal)
router = TestBed.inject(Router)
toastService = TestBed.inject(ToastService)
fixture = TestBed.createComponent(TasksComponent)
component = fixture.componentInstance
jest.useFakeTimers()
@@ -289,4 +293,20 @@ describe('TasksComponent', () => {
jest.advanceTimersByTime(6000)
expect(reloadSpy).toHaveBeenCalledTimes(2)
})
it('should retry a task, show toast on error or success', () => {
const retrySpy = jest.spyOn(tasksService, 'retryTask')
const toastInfoSpy = jest.spyOn(toastService, 'showInfo')
const toastErrorSpy = jest.spyOn(toastService, 'showError')
retrySpy.mockReturnValueOnce(of({ task_id: '123' }))
component.retryTask(tasks[0])
expect(retrySpy).toHaveBeenCalledWith(tasks[0])
expect(toastInfoSpy).toHaveBeenCalledWith('Retrying task...')
retrySpy.mockReturnValueOnce(throwError(() => new Error('test')))
component.retryTask(tasks[0])
expect(toastErrorSpy).toHaveBeenCalledWith(
'Failed to retry task',
new Error('test')
)
})
})

View File

@@ -2,10 +2,11 @@ import { Component, OnInit, OnDestroy } from '@angular/core'
import { Router } from '@angular/router'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { first } from 'rxjs'
import { PaperlessTask } from 'src/app/data/paperless-task'
import { PaperlessTask, PaperlessTaskStatus } 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 { ToastService } from 'src/app/services/toast.service'
@Component({
selector: 'pngx-tasks',
@@ -16,6 +17,7 @@ export class TasksComponent
extends ComponentWithPermissions
implements OnInit, OnDestroy
{
public PaperlessTaskStatus = PaperlessTaskStatus
public activeTab: string
public selectedTasks: Set<number> = new Set()
public togggleAll: boolean = false
@@ -35,6 +37,7 @@ export class TasksComponent
constructor(
public tasksService: TasksService,
private modalService: NgbModal,
private toastService: ToastService,
private readonly router: Router
) {
super()
@@ -83,6 +86,17 @@ export class TasksComponent
this.router.navigate(['documents', task.related_document])
}
retryTask(task: PaperlessTask) {
this.tasksService.retryTask(task).subscribe({
next: () => {
this.toastService.showInfo($localize`Retrying task...`)
},
error: (e) => {
this.toastService.showError($localize`Failed to retry task`, e)
},
})
}
expandTask(task: PaperlessTask) {
this.expandedTask = this.expandedTask == task.id ? undefined : task.id
}

View File

@@ -118,4 +118,29 @@ describe('TasksService', () => {
expect(tasksService.queuedFileTasks).toHaveLength(1)
expect(tasksService.startedFileTasks).toHaveLength(1)
})
it('should call retry task api endpoint', () => {
const task = {
id: 1,
type: PaperlessTaskType.File,
status: PaperlessTaskStatus.Failed,
acknowledged: false,
task_id: '1234',
task_file_name: 'file1.pdf',
date_created: new Date(),
}
tasksService.retryTask(task).subscribe()
const reloadSpy = jest.spyOn(tasksService, 'reload')
const req = httpTestingController.expectOne(
`${environment.apiBaseUrl}tasks/${task.id}/retry/`
)
expect(req.request.method).toEqual('POST')
expect(req.request.body).toEqual({
task_id: task.id,
})
req.flush({ task_id: 12345 })
expect(reloadSpy).toHaveBeenCalled()
httpTestingController.expectOne(`${environment.apiBaseUrl}tasks/`).flush([])
})
})

View File

@@ -1,7 +1,7 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Subject } from 'rxjs'
import { first, takeUntil } from 'rxjs/operators'
import { Observable, Subject } from 'rxjs'
import { first, takeUntil, tap } from 'rxjs/operators'
import {
PaperlessTask,
PaperlessTaskStatus,
@@ -73,6 +73,20 @@ export class TasksService {
})
}
public retryTask(task: PaperlessTask): Observable<any> {
return this.http
.post(`${this.baseUrl}tasks/${task.id}/retry/`, {
task_id: task.id,
})
.pipe(
takeUntil(this.unsubscribeNotifer),
first(),
tap(() => {
this.reload()
})
)
}
public cancelPending(): void {
this.unsubscribeNotifer.next(true)
}