]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-list.service.ts
import 15.2.5
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / shared / services / task-list.service.ts
1 import { Injectable, OnDestroy } from '@angular/core';
2
3 import { Observable, Subscription } from 'rxjs';
4
5 import { ExecutingTask } from '../models/executing-task';
6 import { SummaryService } from './summary.service';
7 import { TaskMessageService } from './task-message.service';
8
9 @Injectable()
10 export class TaskListService implements OnDestroy {
11 summaryDataSubscription: Subscription;
12
13 getUpdate: () => Observable<object>;
14 preProcessing: (_: any) => any[];
15 setList: (_: any[]) => void;
16 onFetchError: (error: any) => void;
17 taskFilter: (task: ExecutingTask) => boolean;
18 itemFilter: (item: any, task: ExecutingTask) => boolean;
19 builders: object;
20
21 constructor(
22 private taskMessageService: TaskMessageService,
23 private summaryService: SummaryService
24 ) {}
25
26 /**
27 * @param {() => Observable<object>} getUpdate Method that calls the api and
28 * returns that without subscribing.
29 * @param {(_: any) => any[]} preProcessing Method executed before merging
30 * Tasks with Items
31 * @param {(_: any[]) => void} setList Method used to update array of item in the component.
32 * @param {(error: any) => void} onFetchError Method called when there were
33 * problems while fetching data.
34 * @param {(task: ExecutingTask) => boolean} taskFilter callback used in tasks_array.filter()
35 * @param {(item, task: ExecutingTask) => boolean} itemFilter callback used in
36 * items_array.filter()
37 * @param {object} builders
38 * object with builders for each type of task.
39 * You can also use a 'default' one.
40 * @memberof TaskListService
41 */
42 init(
43 getUpdate: () => Observable<object>,
44 preProcessing: (_: any) => any[],
45 setList: (_: any[]) => void,
46 onFetchError: (error: any) => void,
47 taskFilter: (task: ExecutingTask) => boolean,
48 itemFilter: (item: any, task: ExecutingTask) => boolean,
49 builders: object
50 ) {
51 this.getUpdate = getUpdate;
52 this.preProcessing = preProcessing;
53 this.setList = setList;
54 this.onFetchError = onFetchError;
55 this.taskFilter = taskFilter;
56 this.itemFilter = itemFilter;
57 this.builders = builders || {};
58
59 this.summaryDataSubscription = this.summaryService.subscribe((summary) => {
60 this.getUpdate().subscribe((resp: any) => {
61 this.updateData(resp, summary['executing_tasks'].filter(this.taskFilter));
62 }, this.onFetchError);
63 }, this.onFetchError);
64 }
65
66 private updateData(resp: any, tasks: ExecutingTask[]) {
67 const data: any[] = this.preProcessing ? this.preProcessing(resp) : resp;
68 this.addMissing(data, tasks);
69 data.forEach((item) => {
70 const executingTasks = tasks.filter((task) => this.itemFilter(item, task));
71 item.cdExecuting = this.getTaskAction(executingTasks);
72 });
73 this.setList(data);
74 }
75
76 private addMissing(data: any[], tasks: ExecutingTask[]) {
77 const defaultBuilder = this.builders['default'];
78 tasks.forEach((task) => {
79 const existing = data.find((item) => this.itemFilter(item, task));
80 const builder = this.builders[task.name];
81 if (!existing && (builder || defaultBuilder)) {
82 data.push(builder ? builder(task.metadata) : defaultBuilder(task.metadata));
83 }
84 });
85 }
86
87 private getTaskAction(tasks: ExecutingTask[]): string {
88 if (tasks.length === 0) {
89 return undefined;
90 }
91 return tasks
92 .map((task) => {
93 const progress = task.progress ? ` ${task.progress}%` : '';
94 return this.taskMessageService.getRunningText(task) + '...' + progress;
95 })
96 .join(', ');
97 }
98
99 ngOnDestroy() {
100 if (this.summaryDataSubscription) {
101 this.summaryDataSubscription.unsubscribe();
102 }
103 }
104 }