mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-11-04 03:27:12 -05:00 
			
		
		
		
	Toggle functionality for tasks list
This commit is contained in:
		
							parent
							
								
									5c980c31be
								
							
						
					
					
						commit
						f88e070455
					
				
							
								
								
									
										83
									
								
								src-ui/src/app/components/manage/tasks/tasks.component.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								src-ui/src/app/components/manage/tasks/tasks.component.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,83 @@
 | 
				
			|||||||
 | 
					<app-page-header title="File Tasks" i18n-title>
 | 
				
			||||||
 | 
					  <div class="btn-toolbar col col-md-auto">
 | 
				
			||||||
 | 
					    <button class="btn btn-sm btn-outline-secondary me-2" (click)="clearSelection()" [hidden]="selectedTasks.size == 0">
 | 
				
			||||||
 | 
					      <svg class="sidebaricon" fill="currentColor">
 | 
				
			||||||
 | 
					        <use xlink:href="assets/bootstrap-icons.svg#x"/>
 | 
				
			||||||
 | 
					      </svg> <ng-container i18n>Clear selection</ng-container>
 | 
				
			||||||
 | 
					    </button>
 | 
				
			||||||
 | 
					    <button class="btn btn-sm btn-outline-primary me-4" (click)="dismissMany()" [disabled]="tasksService.total == 0">
 | 
				
			||||||
 | 
					      <svg class="sidebaricon" fill="currentColor">
 | 
				
			||||||
 | 
					        <use xlink:href="assets/bootstrap-icons.svg#check2-all"/>
 | 
				
			||||||
 | 
					      </svg> <ng-container i18n>{{dismissButtonText}}</ng-container>
 | 
				
			||||||
 | 
					    </button>
 | 
				
			||||||
 | 
					    <button class="btn btn-sm btn-outline-primary" (click)="tasksService.reload()">
 | 
				
			||||||
 | 
					      <svg class="sidebaricon" fill="currentColor">
 | 
				
			||||||
 | 
					        <use xlink:href="assets/bootstrap-icons.svg#arrow-clockwise"/>
 | 
				
			||||||
 | 
					      </svg> <ng-container i18n>Refresh</ng-container>
 | 
				
			||||||
 | 
					    </button>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					</app-page-header>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<ng-container *ngIf="!tasksService.completed && tasksService.loading">
 | 
				
			||||||
 | 
					  <div class="spinner-border spinner-border-sm fw-normal ms-2 me-auto" role="status"></div>
 | 
				
			||||||
 | 
					  <div class="visually-hidden" i18n>Loading...</div>
 | 
				
			||||||
 | 
					</ng-container>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<ng-template let-tasks="tasks" #tasksTemplate>
 | 
				
			||||||
 | 
					  <table class="table table-striped align-middle border shadow-sm">
 | 
				
			||||||
 | 
					    <thead>
 | 
				
			||||||
 | 
					      <tr>
 | 
				
			||||||
 | 
					        <th>
 | 
				
			||||||
 | 
					          <div class="form-check">
 | 
				
			||||||
 | 
					            <input type="checkbox" class="form-check-input" id="all-tasks" [disabled]="currentTasks.length == 0" (click)="toggleAll($event); $event.stopPropagation();">
 | 
				
			||||||
 | 
					            <label class="form-check-label" for="all-tasks"></label>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </th>
 | 
				
			||||||
 | 
					        <th scope="col" i18n>Name</th>
 | 
				
			||||||
 | 
					        <th scope="col" i18n>Created</th>
 | 
				
			||||||
 | 
					        <th scope="col" i18n>Actions</th>
 | 
				
			||||||
 | 
					      </tr>
 | 
				
			||||||
 | 
					    </thead>
 | 
				
			||||||
 | 
					    <tbody>
 | 
				
			||||||
 | 
					      <tr *ngFor="let task of tasks">
 | 
				
			||||||
 | 
					        <td>
 | 
				
			||||||
 | 
					          <div class="form-check">
 | 
				
			||||||
 | 
					            <input type="checkbox" class="form-check-input" id="task{{task.id}}" [checked]="selectedTasks.has(task.id)" (click)="toggleSelected(task, $event); $event.stopPropagation();">
 | 
				
			||||||
 | 
					            <label class="form-check-label" for="task{{task.id}}"></label>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </td>
 | 
				
			||||||
 | 
					        <td scope="row">{{ task.name }}</td>
 | 
				
			||||||
 | 
					        <td scope="row">{{ task.created | customDate:'medium' }}</td>
 | 
				
			||||||
 | 
					        <td scope="row">
 | 
				
			||||||
 | 
					          <button class="btn btn-sm btn-outline-secondary" (click)="dismissTask(task)">
 | 
				
			||||||
 | 
					            <svg class="sidebaricon" fill="currentColor">
 | 
				
			||||||
 | 
					              <use xlink:href="assets/bootstrap-icons.svg#check"/>
 | 
				
			||||||
 | 
					            </svg> <ng-container i18n>Dismiss</ng-container>
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					        </td>
 | 
				
			||||||
 | 
					      </tr>
 | 
				
			||||||
 | 
					    </tbody>
 | 
				
			||||||
 | 
					  </table>
 | 
				
			||||||
 | 
					</ng-template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<ul ngbNav #nav="ngbNav" [(activeId)]="activeTab" class="nav-tabs">
 | 
				
			||||||
 | 
					  <li ngbNavItem="incomplete">
 | 
				
			||||||
 | 
					    <a ngbNavLink i18n>Incomplete <span class="badge bg-secondary ms-1">{{tasksService.incomplete.length}}</span></a>
 | 
				
			||||||
 | 
					    <ng-template ngbNavContent>
 | 
				
			||||||
 | 
					      <ng-container [ngTemplateOutlet]="tasksTemplate" [ngTemplateOutletContext]="{tasks:tasksService.incomplete}"></ng-container>
 | 
				
			||||||
 | 
					    </ng-template>
 | 
				
			||||||
 | 
					  </li>
 | 
				
			||||||
 | 
					  <li ngbNavItem="completed">
 | 
				
			||||||
 | 
					    <a ngbNavLink i18n>Completed <span class="badge bg-secondary ms-1">{{tasksService.completed.length}}</span></a>
 | 
				
			||||||
 | 
					    <ng-template ngbNavContent>
 | 
				
			||||||
 | 
					      <ng-container [ngTemplateOutlet]="tasksTemplate" [ngTemplateOutletContext]="{tasks:tasksService.completed}"></ng-container>
 | 
				
			||||||
 | 
					    </ng-template>
 | 
				
			||||||
 | 
					  </li>
 | 
				
			||||||
 | 
					  <li ngbNavItem="failed">
 | 
				
			||||||
 | 
					    <a ngbNavLink i18n>Failed <span class="badge bg-secondary ms-1">{{tasksService.failed.length}}</span></a>
 | 
				
			||||||
 | 
					    <ng-template ngbNavContent>
 | 
				
			||||||
 | 
					      <ng-container [ngTemplateOutlet]="tasksTemplate" [ngTemplateOutletContext]="{tasks:tasksService.failed}"></ng-container>
 | 
				
			||||||
 | 
					    </ng-template>
 | 
				
			||||||
 | 
					  </li>
 | 
				
			||||||
 | 
					</ul>
 | 
				
			||||||
 | 
					<div [ngbNavOutlet]="nav"></div>
 | 
				
			||||||
							
								
								
									
										75
									
								
								src-ui/src/app/components/manage/tasks/tasks.component.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								src-ui/src/app/components/manage/tasks/tasks.component.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,75 @@
 | 
				
			|||||||
 | 
					import { Component, OnInit, OnDestroy } from '@angular/core'
 | 
				
			||||||
 | 
					import { takeUntil, Subject } from 'rxjs'
 | 
				
			||||||
 | 
					import { PaperlessTask } from 'src/app/data/paperless-task'
 | 
				
			||||||
 | 
					import { TasksService } from 'src/app/services/tasks.service'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Component({
 | 
				
			||||||
 | 
					  selector: 'app-tasks',
 | 
				
			||||||
 | 
					  templateUrl: './tasks.component.html',
 | 
				
			||||||
 | 
					  styleUrls: ['./tasks.component.scss'],
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					export class TasksComponent implements OnInit, OnDestroy {
 | 
				
			||||||
 | 
					  public activeTab: string
 | 
				
			||||||
 | 
					  public selectedTasks: Set<number> = new Set()
 | 
				
			||||||
 | 
					  private unsubscribeNotifer = new Subject()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  get dismissButtonText(): string {
 | 
				
			||||||
 | 
					    return this.selectedTasks.size > 0
 | 
				
			||||||
 | 
					      ? $localize`Dismiss selected`
 | 
				
			||||||
 | 
					      : $localize`Dismiss all`
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  constructor(public tasksService: TasksService) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ngOnInit() {
 | 
				
			||||||
 | 
					    this.tasksService.reload()
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ngOnDestroy() {
 | 
				
			||||||
 | 
					    this.unsubscribeNotifer.next(true)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  dismissTask(task: PaperlessTask) {
 | 
				
			||||||
 | 
					    throw new Error('Not implemented' + task)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  dismissMany() {
 | 
				
			||||||
 | 
					    throw new Error('Not implemented')
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  toggleSelected(task: PaperlessTask) {
 | 
				
			||||||
 | 
					    this.selectedTasks.has(task.id)
 | 
				
			||||||
 | 
					      ? this.selectedTasks.delete(task.id)
 | 
				
			||||||
 | 
					      : this.selectedTasks.add(task.id)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  get currentTasks(): PaperlessTask[] {
 | 
				
			||||||
 | 
					    let tasks: PaperlessTask[]
 | 
				
			||||||
 | 
					    switch (this.activeTab) {
 | 
				
			||||||
 | 
					      case 'incomplete':
 | 
				
			||||||
 | 
					        tasks = this.tasksService.incomplete
 | 
				
			||||||
 | 
					        break
 | 
				
			||||||
 | 
					      case 'completed':
 | 
				
			||||||
 | 
					        tasks = this.tasksService.completed
 | 
				
			||||||
 | 
					        break
 | 
				
			||||||
 | 
					      case 'failed':
 | 
				
			||||||
 | 
					        tasks = this.tasksService.failed
 | 
				
			||||||
 | 
					        break
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					        break
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return tasks
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  toggleAll(event: PointerEvent) {
 | 
				
			||||||
 | 
					    if ((event.target as HTMLInputElement).checked) {
 | 
				
			||||||
 | 
					      this.selectedTasks = new Set(this.currentTasks.map((t) => t.id))
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      this.clearSelection()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  clearSelection() {
 | 
				
			||||||
 | 
					    this.selectedTasks = new Set()
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										89
									
								
								src-ui/src/app/services/tasks.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src-ui/src/app/services/tasks.service.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,89 @@
 | 
				
			|||||||
 | 
					import { HttpClient } from '@angular/common/http'
 | 
				
			||||||
 | 
					import { Injectable } from '@angular/core'
 | 
				
			||||||
 | 
					import { Observable } from 'rxjs'
 | 
				
			||||||
 | 
					import { first, map } from 'rxjs/operators'
 | 
				
			||||||
 | 
					import { PaperlessTask } from 'src/app/data/paperless-task'
 | 
				
			||||||
 | 
					import { environment } from 'src/environments/environment'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface TasksAPIResponse {
 | 
				
			||||||
 | 
					  total: number
 | 
				
			||||||
 | 
					  incomplete: Array<PaperlessTask>
 | 
				
			||||||
 | 
					  completed: Array<PaperlessTask>
 | 
				
			||||||
 | 
					  failed: Array<PaperlessTask>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Injectable({
 | 
				
			||||||
 | 
					  providedIn: 'root',
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					export class TasksService {
 | 
				
			||||||
 | 
					  private baseUrl: string = environment.apiBaseUrl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  loading: boolean
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public total: number
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private incompleteTasks: PaperlessTask[] = []
 | 
				
			||||||
 | 
					  public get incomplete(): PaperlessTask[] {
 | 
				
			||||||
 | 
					    return this.incompleteTasks
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private completedTasks: PaperlessTask[] = []
 | 
				
			||||||
 | 
					  public get completed(): PaperlessTask[] {
 | 
				
			||||||
 | 
					    return this.completedTasks
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private failedTasks: PaperlessTask[] = []
 | 
				
			||||||
 | 
					  public get failed(): PaperlessTask[] {
 | 
				
			||||||
 | 
					    return this.failedTasks
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  constructor(private http: HttpClient) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public reload() {
 | 
				
			||||||
 | 
					    this.loading = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.http
 | 
				
			||||||
 | 
					      .get<TasksAPIResponse>(`${this.baseUrl}consumption_tasks/`)
 | 
				
			||||||
 | 
					      .pipe(first())
 | 
				
			||||||
 | 
					      .subscribe((r) => {
 | 
				
			||||||
 | 
					        this.total = r.total
 | 
				
			||||||
 | 
					        this.incompleteTasks = r.incomplete
 | 
				
			||||||
 | 
					        this.completedTasks = r.completed
 | 
				
			||||||
 | 
					        this.failedTasks = r.failed
 | 
				
			||||||
 | 
					        this.loading = false
 | 
				
			||||||
 | 
					        return true
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // private savedViews: PaperlessSavedView[] = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // get allViews() {
 | 
				
			||||||
 | 
					  //   return this.savedViews
 | 
				
			||||||
 | 
					  // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // get sidebarViews() {
 | 
				
			||||||
 | 
					  //   return this.savedViews.filter((v) => v.show_in_sidebar)
 | 
				
			||||||
 | 
					  // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // get dashboardViews() {
 | 
				
			||||||
 | 
					  //   return this.savedViews.filter((v) => v.show_on_dashboard)
 | 
				
			||||||
 | 
					  // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // create(o: PaperlessSavedView) {
 | 
				
			||||||
 | 
					  //   return super.create(o).pipe(tap(() => this.reload()))
 | 
				
			||||||
 | 
					  // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // update(o: PaperlessSavedView) {
 | 
				
			||||||
 | 
					  //   return super.update(o).pipe(tap(() => this.reload()))
 | 
				
			||||||
 | 
					  // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // patchMany(objects: PaperlessSavedView[]): Observable<PaperlessSavedView[]> {
 | 
				
			||||||
 | 
					  //   return combineLatest(objects.map((o) => super.patch(o))).pipe(
 | 
				
			||||||
 | 
					  //     tap(() => this.reload())
 | 
				
			||||||
 | 
					  //   )
 | 
				
			||||||
 | 
					  // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // delete(o: PaperlessSavedView) {
 | 
				
			||||||
 | 
					  //   return super.delete(o).pipe(tap(() => this.reload()))
 | 
				
			||||||
 | 
					  // }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user