Updated Control Panel for changed ECS NBI
[portal/nonrtric-controlpanel.git] / webapp-frontend / src / app / ei-coordinator / jobs-list / jobs-list.component.ts
index 7fea537..f06202c 100644 (file)
  * limitations under the License.
  * ========================LICENSE_END===================================
  */
-import { Component, OnInit, ViewChild } from '@angular/core';
-import { FormControl, FormGroup } from '@angular/forms';
-import { MatPaginator } from '@angular/material/paginator';
-import { Sort } from '@angular/material/sort';
-import { MatTableDataSource } from '@angular/material/table';
-import { forkJoin } from 'rxjs';
-import { BehaviorSubject } from 'rxjs/BehaviorSubject';
-import { mergeMap, finalize, tap } from 'rxjs/operators';
-import { EIJob } from '@interfaces/ei.types';
-import { EIService } from '@services/ei/ei.service';
-import { UiService } from '@services/ui/ui.service';
+import { Component, OnInit, ViewChild } from "@angular/core";
+import { FormControl, FormGroup } from "@angular/forms";
+import { MatPaginator } from "@angular/material/paginator";
+import { Sort } from "@angular/material/sort";
+import { MatTableDataSource } from "@angular/material/table";
+import { EMPTY, forkJoin, Subscription, timer } from "rxjs";
+import { BehaviorSubject } from "rxjs/BehaviorSubject";
+import { mergeMap, finalize, map, tap, switchMap } from "rxjs/operators";
+import { JobInfo } from "@interfaces/producer.types";
+import { ProducerService } from "@services/ei/producer.service";
+import { UiService } from "@services/ui/ui.service";
 
 export interface Job {
   jobId: string;
@@ -39,51 +39,55 @@ export interface Job {
 }
 
 @Component({
-  selector: 'nrcp-jobs-list',
-  templateUrl: './jobs-list.component.html',
-  styleUrls: ['./jobs-list.component.scss']
+  selector: "nrcp-jobs-list",
+  templateUrl: "./jobs-list.component.html",
+  styleUrls: ["./jobs-list.component.scss"],
 })
 export class JobsListComponent implements OnInit {
-
   @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
-
-  darkMode: boolean;
   jobsDataSource: MatTableDataSource<Job>;
   jobForm: FormGroup;
-  private loadingSubject = new BehaviorSubject<boolean>(false);
-  private jobsSubject = new BehaviorSubject<Job[]>([]);
-  public loading$ = this.loadingSubject.asObservable();
-
-  constructor(
-    private eiSvc: EIService,
-    private ui: UiService
-  ) {
+  darkMode: boolean;
+
+  private jobsSubject$ = new BehaviorSubject<Job[]>([]);
+  private refresh$ = new BehaviorSubject("");
+  private loadingSubject$ = new BehaviorSubject<boolean>(false);
+  private polling$ = new BehaviorSubject(0);
+  public loading$ = this.loadingSubject$.asObservable();
+  subscription: Subscription;
+  checked: boolean = false;
+  firstTime: boolean = true;
+
+  constructor(private producerService: ProducerService, private ui: UiService) {
     this.jobForm = new FormGroup({
-      jobId: new FormControl(''),
-      typeId: new FormControl(''),
-      owner: new FormControl(''),
-      targetUri: new FormControl(''),
-      prodId: new FormControl('')
+      jobId: new FormControl(""),
+      typeId: new FormControl(""),
+      owner: new FormControl(""),
+      targetUri: new FormControl(""),
+      prodId: new FormControl(""),
     });
   }
 
   ngOnInit(): void {
-    this.loadJobs();
-    this.jobsSubject.subscribe((data) => {
+    this.subscription = this.dataSubscription();
+
+    this.jobsSubject$.subscribe((data) => {
       this.jobsDataSource = new MatTableDataSource<Job>(data);
       this.jobsDataSource.paginator = this.paginator;
 
       this.jobsDataSource.filterPredicate = ((data: Job, filter) => {
         let searchTerms = JSON.parse(filter);
-        return this.isDataIncluding(data.targetUri, searchTerms.targetUri)
-          && this.isDataIncluding(data.jobId, searchTerms.jobId)
-          && this.isDataIncluding(data.owner, searchTerms.owner)
-          && this.isDataIncluding(data.typeId, searchTerms.typeId)
-          && this.isDataIncluding(data.prodId, searchTerms.prodId);
+        return (
+          this.isDataIncluding(data.targetUri, searchTerms.targetUri) &&
+          this.isDataIncluding(data.jobId, searchTerms.jobId) &&
+          this.isDataIncluding(data.owner, searchTerms.owner) &&
+          this.isDataIncluding(data.typeId, searchTerms.typeId) &&
+          this.isDataIncluding(data.prodId, searchTerms.prodId)
+        );
       }) as (data: Job, filter: any) => boolean;
     });
 
-    this.jobForm.valueChanges.subscribe(value => {
+    this.jobForm.valueChanges.subscribe((value) => {
       this.jobsDataSource.filter = JSON.stringify(value);
     });
 
@@ -92,36 +96,77 @@ export class JobsListComponent implements OnInit {
     });
   }
 
+  dataSubscription(): Subscription {
+    let prodId = [];
+    const jobs$ = this.producerService.getProducerIds().pipe(
+      tap((data) => (prodId = data)),
+      mergeMap((prodIds) =>
+        forkJoin(prodIds.map((id) => this.producerService.getJobsForProducer(id)))
+      ),
+      finalize(() => this.loadingSubject$.next(false))
+    );
+
+    const refreshedJobs$ = this.refresh$.pipe(
+      switchMap((_) =>
+        timer(0, 10000).pipe(
+          tap((_) => {
+            this.loadingSubject$.next(true);
+          }),
+          switchMap((_) => jobs$),
+          map((response) => this.extractJobs(prodId, response))
+        )
+      )
+    );
+
+    return this.polling$
+      .pipe(
+        switchMap((value) => {
+          let pollCondition = value == 0 || this.checked;
+          return pollCondition ? refreshedJobs$ : EMPTY;
+        })
+      )
+      .subscribe();
+  }
+
   ngOnDestroy() {
-    if (!this.jobsSubject) this.jobsSubject.unsubscribe();
-    if (!this.loadingSubject) this.loadingSubject.unsubscribe();
-    if (!this.ui.darkModeState) this.ui.darkModeState.unsubscribe();
+    this.subscription.unsubscribe();
   }
 
   clearFilter() {
-    this.jobForm.get('jobId').setValue('');
-    this.jobForm.get('typeId').setValue('');
-    this.jobForm.get('owner').setValue('');
-    this.jobForm.get('targetUri').setValue('');
-    this.jobForm.get('prodId').setValue('');
+    this.jobForm.get("jobId").setValue("");
+    this.jobForm.get("typeId").setValue("");
+    this.jobForm.get("owner").setValue("");
+    this.jobForm.get("targetUri").setValue("");
+    this.jobForm.get("prodId").setValue("");
   }
 
   sortJobs(sort: Sort) {
-    const data = this.jobsDataSource.data
+    const data = this.jobsDataSource.data;
     data.sort((a: Job, b: Job) => {
-      const isAsc = sort.direction === 'asc';
+      const isAsc = sort.direction === "asc";
       switch (sort.active) {
-        case 'jobId': return this.compare(a.jobId, b.jobId, isAsc);
-        case 'typeId': return this.compare(a.typeId, b.typeId, isAsc);
-        case 'owner': return this.compare(a.owner, b.owner, isAsc);
-        case 'targetUri': return this.compare(a.targetUri, b.targetUri, isAsc);
-        case 'prodId': return this.compare(a.prodId, b.prodId, isAsc);
-        default: return 0;
+        case "jobId":
+          return this.compare(a.jobId, b.jobId, isAsc);
+        case "typeId":
+          return this.compare(a.typeId, b.typeId, isAsc);
+        case "owner":
+          return this.compare(a.owner, b.owner, isAsc);
+        case "targetUri":
+          return this.compare(a.targetUri, b.targetUri, isAsc);
+        case "prodId":
+          return this.compare(a.prodId, b.prodId, isAsc);
+        default:
+          return 0;
       }
     });
     this.jobsDataSource.data = data;
   }
 
+  stopPolling(checked) {
+    this.checked = checked;
+    this.polling$.next(this.jobs().length);
+  }
+
   compare(a: any, b: any, isAsc: boolean) {
     return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
   }
@@ -135,54 +180,59 @@ export class JobsListComponent implements OnInit {
     return data.toLowerCase().includes(transformedFilter);
   }
 
-  getJobTypeId(eiJob: Job): string {
-    if (eiJob.typeId) {
-      return eiJob.typeId;
+  getJobTypeId(job: Job): string {
+    if (job.typeId) {
+      return job.typeId;
     }
-    return '< No type >';
+    return "< No type >";
   }
 
-  getJobOwner(eiJob: Job): string {
-    if (eiJob.owner) {
-      return eiJob.owner;
+  getJobOwner(job: Job): string {
+    if (job.owner) {
+      return job.owner;
     }
-    return '< No owner >';
+    return "< No owner >";
   }
 
   public jobs(): Job[] {
-    return this.jobsSubject.value;
+    return this.jobsSubject$.value;
   }
 
-  loadJobs() {
-    this.loadingSubject.next(true);
-    let jobs = [];
-    let prodId = [];
-    this.eiSvc.getProducerIds().pipe(
-      tap(data => prodId = data),
-      mergeMap(prodIds =>
-        forkJoin(prodIds.map(id => this.eiSvc.getJobsForProducer(id)))),
-      finalize(() => this.loadingSubject.next(false))
-    ).subscribe(result => {
-      jobs = this.createJobList(prodId, result);
-      this.jobsSubject.next(jobs);
+  private extractJobs(prodId: number[], res: JobInfo[][]) {
+    this.clearFilter();
+    let jobList = [];
+    prodId.forEach((element, index) => {
+      let jobs = res[index];
+      jobList = jobList.concat(jobs.map((job) => this.createJob(element, job)));
     });
+    this.jobsSubject$.next(jobList);
+    if (this.firstTime && jobList.length > 0) {
+      this.polling$.next(jobList.length);
+      this.firstTime = false;
+    }
+    return jobList;
   }
-  createJobList(prodId: any[], result: EIJob[][]) {
+
+  createJobList(prodId: any[], result: JobInfo[][]) {
     let jobList = [];
     prodId.forEach((element, index) => {
       let jobs = result[index];
-      jobList = jobList.concat(jobs.map(job => this.createJob(element, job)));
+      jobList = jobList.concat(jobs.map((job) => this.createJob(element, job)));
     });
     return jobList;
   }
-  createJob(element: any, job: EIJob): any {
-    let eiJob = <Job>{};
-    eiJob.jobId = job.ei_job_identity;
-    eiJob.typeId = job.ei_type_identity;
-    eiJob.owner = job.owner;
-    eiJob.targetUri = job.target_uri;
-    eiJob.prodId = element;
-    return eiJob;
+
+  createJob(element: any, job: JobInfo): any {
+    let infoJob = <Job>{};
+    infoJob.jobId = job.info_job_identity;
+    infoJob.typeId = job.info_type_identity;
+    infoJob.owner = job.owner;
+    infoJob.targetUri = job.target_uri;
+    infoJob.prodId = element;
+    return infoJob;
   }
 
+  refreshDataClick() {
+    this.refresh$.next("");
+  }
 }