2 * ========================LICENSE_START=================================
5 * Copyright (C) 2021 Nordix Foundation
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ========================LICENSE_END===================================
20 import { Component, OnInit, ViewChild } from "@angular/core";
21 import { FormControl, FormGroup } from "@angular/forms";
22 import { MatPaginator } from "@angular/material/paginator";
23 import { Sort } from "@angular/material/sort";
24 import { MatTableDataSource } from "@angular/material/table";
25 import { EMPTY, forkJoin, Subscription, timer } from "rxjs";
26 import { BehaviorSubject } from "rxjs/BehaviorSubject";
27 import { mergeMap, finalize, map, tap, switchMap } from "rxjs/operators";
28 import { JobInfo } from "@interfaces/producer.types";
29 import { ProducerService } from "@services/ei/producer.service";
30 import { UiService } from "@services/ui/ui.service";
32 export interface Job {
42 selector: "nrcp-jobs-list",
43 templateUrl: "./jobs-list.component.html",
44 styleUrls: ["./jobs-list.component.scss"],
46 export class JobsListComponent implements OnInit {
47 @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
48 jobsDataSource: MatTableDataSource<Job>;
52 private jobsSubject$ = new BehaviorSubject<Job[]>([]);
53 private refresh$ = new BehaviorSubject("");
54 private loadingSubject$ = new BehaviorSubject<boolean>(false);
55 private polling$ = new BehaviorSubject(0);
56 public loading$ = this.loadingSubject$.asObservable();
57 subscription: Subscription;
58 checked: boolean = false;
59 firstTime: boolean = true;
61 constructor(private producerService: ProducerService, private ui: UiService) {
62 this.jobForm = new FormGroup({
63 jobId: new FormControl(""),
64 typeId: new FormControl(""),
65 owner: new FormControl(""),
66 targetUri: new FormControl(""),
67 prodId: new FormControl(""),
72 this.subscription = this.dataSubscription();
74 this.jobsSubject$.subscribe((data) => {
75 this.jobsDataSource = new MatTableDataSource<Job>(data);
76 this.jobsDataSource.paginator = this.paginator;
78 this.jobsDataSource.filterPredicate = ((data: Job, filter) => {
79 let searchTerms = JSON.parse(filter);
81 this.isDataIncluding(data.targetUri, searchTerms.targetUri) &&
82 this.isDataIncluding(data.jobId, searchTerms.jobId) &&
83 this.isDataIncluding(data.owner, searchTerms.owner) &&
84 this.isDataIncluding(data.typeId, searchTerms.typeId) &&
85 this.isDataIncluding(data.prodId, searchTerms.prodId)
87 }) as (data: Job, filter: any) => boolean;
90 this.jobForm.valueChanges.subscribe((value) => {
91 this.jobsDataSource.filter = JSON.stringify(value);
94 this.ui.darkModeState.subscribe((isDark) => {
95 this.darkMode = isDark;
99 dataSubscription(): Subscription {
101 const jobs$ = this.producerService.getProducerIds().pipe(
102 tap((data) => (prodId = data)),
103 mergeMap((prodIds) =>
104 forkJoin(prodIds.map((id) => this.producerService.getJobsForProducer(id)))
106 finalize(() => this.loadingSubject$.next(false))
109 const refreshedJobs$ = this.refresh$.pipe(
111 timer(0, 10000).pipe(
113 this.loadingSubject$.next(true);
115 switchMap((_) => jobs$),
116 map((response) => this.extractJobs(prodId, response))
123 switchMap((value) => {
124 let pollCondition = value == 0 || this.checked;
125 return pollCondition ? refreshedJobs$ : EMPTY;
132 this.subscription.unsubscribe();
136 this.jobForm.get("jobId").setValue("");
137 this.jobForm.get("typeId").setValue("");
138 this.jobForm.get("owner").setValue("");
139 this.jobForm.get("targetUri").setValue("");
140 this.jobForm.get("prodId").setValue("");
143 sortJobs(sort: Sort) {
144 const data = this.jobsDataSource.data;
145 data.sort((a: Job, b: Job) => {
146 const isAsc = sort.direction === "asc";
147 switch (sort.active) {
149 return this.compare(a.jobId, b.jobId, isAsc);
151 return this.compare(a.typeId, b.typeId, isAsc);
153 return this.compare(a.owner, b.owner, isAsc);
155 return this.compare(a.targetUri, b.targetUri, isAsc);
157 return this.compare(a.prodId, b.prodId, isAsc);
162 this.jobsDataSource.data = data;
165 stopPolling(checked) {
166 this.checked = checked;
167 this.polling$.next(this.jobs().length);
170 compare(a: any, b: any, isAsc: boolean) {
171 return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
174 stopSort(event: any) {
175 event.stopPropagation();
178 isDataIncluding(data: string, filter: string): boolean {
179 const transformedFilter = filter.trim().toLowerCase();
180 return data.toLowerCase().includes(transformedFilter);
183 getJobTypeId(job: Job): string {
187 return "< No type >";
190 getJobOwner(job: Job): string {
194 return "< No owner >";
197 public jobs(): Job[] {
198 return this.jobsSubject$.value;
201 private extractJobs(prodId: number[], res: JobInfo[][]) {
204 prodId.forEach((element, index) => {
205 let jobs = res[index];
206 jobList = jobList.concat(jobs.map((job) => this.createJob(element, job)));
208 this.jobsSubject$.next(jobList);
209 if (this.firstTime && jobList.length > 0) {
210 this.polling$.next(jobList.length);
211 this.firstTime = false;
216 createJobList(prodId: any[], result: JobInfo[][]) {
218 prodId.forEach((element, index) => {
219 let jobs = result[index];
220 jobList = jobList.concat(jobs.map((job) => this.createJob(element, job)));
225 createJob(element: any, job: JobInfo): any {
226 let infoJob = <Job>{};
227 infoJob.jobId = job.info_job_identity;
228 infoJob.typeId = job.info_type_identity;
229 infoJob.owner = job.owner;
230 infoJob.targetUri = job.target_uri;
231 infoJob.prodId = element;
236 this.refresh$.next("");