Support running tasks

This commit is contained in:
shamoon
2025-02-25 11:08:21 -08:00
parent 1c7c703e5f
commit acbb18034a
14 changed files with 455 additions and 200 deletions

View File

@@ -1736,7 +1736,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
<context context-type="linenumber">83</context>
<context context-type="linenumber">87</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
@@ -3543,7 +3543,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
<context context-type="linenumber">79</context>
<context context-type="linenumber">83</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
@@ -4101,15 +4101,15 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
<context context-type="linenumber">165</context>
<context context-type="linenumber">175</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
<context context-type="linenumber">189</context>
<context context-type="linenumber">209</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
<context context-type="linenumber">213</context>
<context context-type="linenumber">243</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/toast/toast.component.html</context>
@@ -4396,7 +4396,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
<context context-type="linenumber">125</context>
<context context-type="linenumber">129</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.html</context>
@@ -4992,11 +4992,18 @@
<context context-type="linenumber">72</context>
</context-group>
</trans-unit>
<trans-unit id="235571817610183244" datatype="html">
<source>Web UI</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
<context context-type="linenumber">76</context>
</context-group>
</trans-unit>
<trans-unit id="3553216189604488439" datatype="html">
<source>Modified</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
<context context-type="linenumber">87</context>
<context context-type="linenumber">91</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/data/document.ts</context>
@@ -5007,70 +5014,70 @@
<source>Custom Field</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
<context context-type="linenumber">91</context>
<context context-type="linenumber">95</context>
</context-group>
</trans-unit>
<trans-unit id="8696908693776094667" datatype="html">
<source>Consumption Started</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
<context context-type="linenumber">98</context>
<context context-type="linenumber">102</context>
</context-group>
</trans-unit>
<trans-unit id="7858311467093621703" datatype="html">
<source>Document Added</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
<context context-type="linenumber">102</context>
<context context-type="linenumber">106</context>
</context-group>
</trans-unit>
<trans-unit id="7955486237346046731" datatype="html">
<source>Document Updated</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
<context context-type="linenumber">106</context>
<context context-type="linenumber">110</context>
</context-group>
</trans-unit>
<trans-unit id="9172233176401579786" datatype="html">
<source>Scheduled</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
<context context-type="linenumber">110</context>
<context context-type="linenumber">114</context>
</context-group>
</trans-unit>
<trans-unit id="5502398334173581061" datatype="html">
<source>Assignment</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
<context context-type="linenumber">117</context>
<context context-type="linenumber">121</context>
</context-group>
</trans-unit>
<trans-unit id="6234812824772766804" datatype="html">
<source>Removal</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
<context context-type="linenumber">121</context>
<context context-type="linenumber">125</context>
</context-group>
</trans-unit>
<trans-unit id="4206419737792796794" datatype="html">
<source>Webhook</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
<context context-type="linenumber">129</context>
<context context-type="linenumber">133</context>
</context-group>
</trans-unit>
<trans-unit id="3138206142174978019" datatype="html">
<source>Create new workflow</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
<context context-type="linenumber">225</context>
<context context-type="linenumber">229</context>
</context-group>
</trans-unit>
<trans-unit id="5996779210524133604" datatype="html">
<source>Edit workflow</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
<context context-type="linenumber">229</context>
<context context-type="linenumber">233</context>
</context-group>
</trans-unit>
<trans-unit id="6381578200008167206" datatype="html">
@@ -5560,7 +5567,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
<context context-type="linenumber">231</context>
<context context-type="linenumber">261</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/mail/mail.component.html</context>
@@ -6014,39 +6021,54 @@
<context context-type="linenumber">146</context>
</context-group>
</trans-unit>
<trans-unit id="9127131074422113272" datatype="html">
<source>Run Task</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
<context context-type="linenumber">166</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
<context context-type="linenumber">200</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
<context context-type="linenumber">234</context>
</context-group>
</trans-unit>
<trans-unit id="4089509911694721896" datatype="html">
<source>Last Updated</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
<context context-type="linenumber">163</context>
<context context-type="linenumber">173</context>
</context-group>
</trans-unit>
<trans-unit id="46628344485199198" datatype="html">
<source>Classifier</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
<context context-type="linenumber">168</context>
<context context-type="linenumber">178</context>
</context-group>
</trans-unit>
<trans-unit id="6096684179126491743" datatype="html">
<source>Last Trained</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
<context context-type="linenumber">187</context>
<context context-type="linenumber">207</context>
</context-group>
</trans-unit>
<trans-unit id="6427836860962380759" datatype="html">
<source>Sanity Checker</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
<context context-type="linenumber">192</context>
<context context-type="linenumber">212</context>
</context-group>
</trans-unit>
<trans-unit id="6578747070254776938" datatype="html">
<source>Last Run</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
<context context-type="linenumber">211</context>
<context context-type="linenumber">241</context>
</context-group>
</trans-unit>
<trans-unit id="6732151329960766506" datatype="html">
@@ -9692,28 +9714,28 @@
<source>Connecting...</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/upload-documents.service.ts</context>
<context context-type="linenumber">42</context>
<context context-type="linenumber">43</context>
</context-group>
</trans-unit>
<trans-unit id="1245343823699368872" datatype="html">
<source>Uploading...</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/upload-documents.service.ts</context>
<context context-type="linenumber">54</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit id="7446520539098045935" datatype="html">
<source>Upload complete, waiting...</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/upload-documents.service.ts</context>
<context context-type="linenumber">57</context>
<context context-type="linenumber">58</context>
</context-group>
</trans-unit>
<trans-unit id="1405142710727603568" datatype="html">
<source>HTTP error: <x id="PH" equiv-text="error.status"/> <x id="PH_1" equiv-text="error.statusText"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/upload-documents.service.ts</context>
<context context-type="linenumber">70</context>
<context context-type="linenumber">71</context>
</context-group>
</trans-unit>
<trans-unit id="2119857572761283468" datatype="html">

View File

@@ -144,7 +144,7 @@
<div class="card-body">
<dl class="card-text">
<dt i18n>Search Index</dt>
<dd>
<dd class="d-flex align-items-center">
<div class="badge text-uppercase bg-info text-dark" [ngbPopover]="indexStatus" triggers="mouseenter:mouseleave">
{{status.tasks.index_status}}
@if (status.tasks.index_status === 'OK') {
@@ -157,6 +157,16 @@
<i-bs name="exclamation-triangle-fill" class="text-danger ms-2 lh-1"></i-bs>
}
</div>
@if (currentUserIsSuperUser) {
@if (isRunning(PaperlessTaskName.IndexOptimize)) {
<div class="spinner-border spinner-border-sm ms-2" role="status"></div>
} @else {
<div class="badge cursor-pointer bg-info btn-outline-secondary ms-2" (click)="runTask(PaperlessTaskName.IndexOptimize)">
<i-bs name="play-fill"></i-bs>&nbsp;
<ng-container i18n>Run Task</ng-container>
</div>
}
}
</dd>
<ng-template #indexStatus>
@if (status.tasks.index_status === 'OK') {
@@ -166,7 +176,7 @@
}
</ng-template>
<dt i18n>Classifier</dt>
<dd>
<dd class="d-flex align-items-center">
<div class="badge text-uppercase bg-info text-dark" [ngbPopover]="classifierStatus" triggers="mouseenter:mouseleave">
{{status.tasks.classifier_status}}
@if (status.tasks.classifier_status === 'OK') {
@@ -181,6 +191,16 @@
[class.text-warning]="status.tasks.classifier_status === SystemStatusItemStatus.WARNING"></i-bs>
}
</div>
@if (currentUserIsSuperUser) {
@if (isRunning(PaperlessTaskName.TrainClassifier)) {
<div class="spinner-border spinner-border-sm ms-2" role="status"></div>
} @else {
<div class="badge cursor-pointer bg-info btn-outline-secondary ms-2" (click)="runTask(PaperlessTaskName.TrainClassifier)">
<i-bs name="play-fill"></i-bs>&nbsp;
<ng-container i18n>Run Task</ng-container>
</div>
}
}
</dd>
<ng-template #classifierStatus>
@if (status.tasks.classifier_status === 'OK') {
@@ -190,7 +210,7 @@
}
</ng-template>
<dt i18n>Sanity Checker</dt>
<dd>
<dd class="d-flex align-items-center">
<div class="badge text-uppercase bg-info text-dark" [ngbPopover]="sanityCheckerStatus" triggers="mouseenter:mouseleave">
{{status.tasks.sanity_check_status}}
@if (status.tasks.sanity_check_status === 'OK') {
@@ -205,6 +225,16 @@
[class.text-warning]="status.tasks.sanity_check_status === SystemStatusItemStatus.WARNING"></i-bs>
}
</div>
@if (currentUserIsSuperUser) {
@if (isRunning(PaperlessTaskName.SanityCheck)) {
<div class="spinner-border spinner-border-sm ms-2" role="status"></div>
} @else {
<div class="badge cursor-pointer bg-info btn-outline-secondary ms-2" (click)="runTask(PaperlessTaskName.SanityCheck)">
<i-bs name="play-fill"></i-bs>&nbsp;
<ng-container i18n>Run Task</ng-container>
</div>
}
}
</dd>
<ng-template #sanityCheckerStatus>
@if (status.tasks.sanity_check_status === 'OK') {

View File

@@ -7,12 +7,17 @@ import {
NgbProgressbarModule,
} from '@ng-bootstrap/ng-bootstrap'
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
import { PaperlessTaskName } from 'src/app/data/paperless-task'
import {
SystemStatus,
SystemStatusItemStatus,
} from 'src/app/data/system-status'
import { CustomDatePipe } from 'src/app/pipes/custom-date.pipe'
import { FileSizePipe } from 'src/app/pipes/file-size.pipe'
import { PermissionsService } from 'src/app/services/permissions.service'
import { SystemStatusService } from 'src/app/services/system-status.service'
import { TasksService } from 'src/app/services/tasks.service'
import { ToastService } from 'src/app/services/toast.service'
@Component({
selector: 'pngx-system-status-dialog',
@@ -30,13 +35,24 @@ import { FileSizePipe } from 'src/app/pipes/file-size.pipe'
})
export class SystemStatusDialogComponent {
public SystemStatusItemStatus = SystemStatusItemStatus
public PaperlessTaskName = PaperlessTaskName
public status: SystemStatus
public copied: boolean = false
private runningTasks: Set<PaperlessTaskName> = new Set()
get currentUserIsSuperUser(): boolean {
return this.permissionsService.isSuperUser()
}
constructor(
public activeModal: NgbActiveModal,
private clipboard: Clipboard
private clipboard: Clipboard,
private statusService: SystemStatusService,
private tasksService: TasksService,
private toastService: ToastService,
private permissionsService: PermissionsService
) {}
public close() {
@@ -56,4 +72,30 @@ export class SystemStatusDialogComponent {
const now = new Date()
return now.getTime() - date.getTime() > hours * 60 * 60 * 1000
}
public isRunning(taskName: PaperlessTaskName): boolean {
return this.runningTasks.has(taskName)
}
public runTask(taskName: PaperlessTaskName) {
this.runningTasks.add(taskName)
this.toastService.showInfo(`Task ${taskName} started`)
this.tasksService.run(taskName).subscribe({
next: () => {
this.runningTasks.delete(taskName)
this.statusService.get().subscribe({
next: (status) => {
this.status = status
},
})
},
error: (err) => {
this.runningTasks.delete(taskName)
this.toastService.showError(
`Failed to start task ${taskName}, see the logs for more details`,
err
)
},
})
}
}

View File

@@ -10,6 +10,7 @@ export enum PaperlessTaskName {
ConsumeFile = 'consume_file',
TrainClassifier = 'train_classifier',
SanityCheck = 'check_sanity',
IndexOptimize = 'index_optimize',
}
export enum PaperlessTaskStatus {

View File

@@ -132,4 +132,19 @@ describe('TasksService', () => {
expect(tasksService.queuedFileTasks).toHaveLength(1)
expect(tasksService.startedFileTasks).toHaveLength(1)
})
it('supports running tasks', () => {
tasksService.run(PaperlessTaskName.SanityCheck).subscribe((res) => {
expect(res).toEqual({
result: 'success',
})
})
const req = httpTestingController.expectOne(
`${environment.apiBaseUrl}tasks/run/`
)
expect(req.request.method).toEqual('POST')
req.flush({
result: 'success',
})
})
})

View File

@@ -1,6 +1,6 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Subject } from 'rxjs'
import { Observable, Subject } from 'rxjs'
import { first, takeUntil } from 'rxjs/operators'
import {
PaperlessTask,
@@ -14,6 +14,7 @@ import { environment } from 'src/environments/environment'
})
export class TasksService {
private baseUrl: string = environment.apiBaseUrl
private endpoint: string = 'tasks'
public loading: boolean
@@ -55,7 +56,7 @@ export class TasksService {
this.http
.get<PaperlessTask[]>(
`${this.baseUrl}tasks/?task_name=consume_file&acknowledged=false`
`${this.baseUrl}${this.endpoint}/?task_name=consume_file&acknowledged=false`
)
.pipe(takeUntil(this.unsubscribeNotifer), first())
.subscribe((r) => {
@@ -80,4 +81,13 @@ export class TasksService {
public cancelPending(): void {
this.unsubscribeNotifer.next(true)
}
public run(taskName: PaperlessTaskName): Observable<any> {
return this.http.post<any>(
`${environment.apiBaseUrl}${this.endpoint}/run/`,
{
task_name: taskName,
}
)
}
}

View File

@@ -107,6 +107,7 @@ import {
personFillLock,
personLock,
personSquare,
playFill,
plus,
plusCircle,
questionCircle,
@@ -311,6 +312,7 @@ const icons = {
personFillLock,
personLock,
personSquare,
playFill,
plus,
plusCircle,
questionCircle,