From 18a21c8796772fab295df182763f59700333e9ab Mon Sep 17 00:00:00 2001 From: ychacon Date: Thu, 8 Apr 2021 08:31:36 +0200 Subject: [PATCH] Polling mechanism to get jobs Issue-ID: NONRTRIC-475 Signed-off-by: ychacon Change-Id: Icd2a3b0bc1f069e0a161aca5df413758122522c6 --- .../ei-coordinator.component.spec.ts | 4 +- .../app/ei-coordinator/ei-coordinator.component.ts | 2 +- .../jobs-list/jobs-list.component.spec.ts | 535 ++++++++++++++------- .../jobs-list/jobs-list.component.ts | 171 ++++--- 4 files changed, 465 insertions(+), 247 deletions(-) diff --git a/webapp-frontend/src/app/ei-coordinator/ei-coordinator.component.spec.ts b/webapp-frontend/src/app/ei-coordinator/ei-coordinator.component.spec.ts index ed45171..38e3fa5 100644 --- a/webapp-frontend/src/app/ei-coordinator/ei-coordinator.component.spec.ts +++ b/webapp-frontend/src/app/ei-coordinator/ei-coordinator.component.spec.ts @@ -104,7 +104,7 @@ describe('EICoordinatorComponent', () => { let refreshButton = await loader.getHarness(MatButtonHarness.with({ selector: '#refreshButton' })); const jobsComponent: JobsListComponent = fixture.debugElement.query(By.directive(JobsListComponent)).componentInstance; - spyOn(jobsComponent, 'loadJobs'); + spyOn(jobsComponent, 'refreshDataClick'); spyOn(jobsComponent, 'clearFilter'); const prodsComponent: ProducersListComponent = fixture.debugElement.query(By.directive(ProducersListComponent)).componentInstance; @@ -113,7 +113,7 @@ describe('EICoordinatorComponent', () => { await refreshButton.click(); - expect(jobsComponent.loadJobs).toHaveBeenCalled(); + expect(jobsComponent.refreshDataClick).toHaveBeenCalled(); expect(jobsComponent.clearFilter).toHaveBeenCalled(); expect(prodsComponent.loadProducers).toHaveBeenCalled(); expect(prodsComponent.clearFilter).toHaveBeenCalled(); diff --git a/webapp-frontend/src/app/ei-coordinator/ei-coordinator.component.ts b/webapp-frontend/src/app/ei-coordinator/ei-coordinator.component.ts index 15a9b4a..64cbbd2 100644 --- a/webapp-frontend/src/app/ei-coordinator/ei-coordinator.component.ts +++ b/webapp-frontend/src/app/ei-coordinator/ei-coordinator.component.ts @@ -50,7 +50,7 @@ export class EICoordinatorComponent implements OnInit { } refreshTables() { - this.jobComponent.loadJobs(); + this.jobComponent.refreshDataClick(); this.jobComponent.clearFilter(); this.producersList.loadProducers(); this.producersList.clearFilter(); diff --git a/webapp-frontend/src/app/ei-coordinator/jobs-list/jobs-list.component.spec.ts b/webapp-frontend/src/app/ei-coordinator/jobs-list/jobs-list.component.spec.ts index 28412a5..927ab9d 100644 --- a/webapp-frontend/src/app/ei-coordinator/jobs-list/jobs-list.component.spec.ts +++ b/webapp-frontend/src/app/ei-coordinator/jobs-list/jobs-list.component.spec.ts @@ -17,78 +17,89 @@ * limitations under the License. * ========================LICENSE_END=================================== */ -import { HarnessLoader } from '@angular/cdk/testing'; -import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; -import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; -import { MatInputHarness } from '@angular/material/input/testing'; -import { MatPaginatorModule } from '@angular/material/paginator'; -import { MatSortModule } from '@angular/material/sort'; -import { MatSortHarness } from '@angular/material/sort/testing'; -import { MatPaginatorHarness } from '@angular/material/paginator/testing'; -import { MatTableModule } from '@angular/material/table'; -import { MatTableHarness } from '@angular/material/table/testing'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { of } from 'rxjs/observable/of'; -import { EIJob } from '@interfaces/ei.types'; -import { EIService } from '@services/ei/ei.service'; -import { UiService } from '@services/ui/ui.service'; - -import { Job, JobsListComponent } from './jobs-list.component'; +import { HarnessLoader } from "@angular/cdk/testing"; +import { TestbedHarnessEnvironment } from "@angular/cdk/testing/testbed"; +import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core"; +import { + async, + ComponentFixture, + discardPeriodicTasks, + fakeAsync, + TestBed, + tick, +} from "@angular/core/testing"; +import { FormsModule, ReactiveFormsModule } from "@angular/forms"; +import { MatFormFieldModule } from "@angular/material/form-field"; +import { MatInputModule } from "@angular/material/input"; +import { MatInputHarness } from "@angular/material/input/testing"; +import { MatPaginatorModule } from "@angular/material/paginator"; +import { MatSortModule } from "@angular/material/sort"; +import { MatSortHarness } from "@angular/material/sort/testing"; +import { MatPaginatorHarness } from "@angular/material/paginator/testing"; +import { MatTableModule } from "@angular/material/table"; +import { MatTableHarness } from "@angular/material/table/testing"; +import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; +import { of } from "rxjs/observable/of"; +import { EIJob } from "@interfaces/ei.types"; +import { EIService } from "@services/ei/ei.service"; +import { UiService } from "@services/ui/ui.service"; + +import { Job, JobsListComponent } from "./jobs-list.component"; +import { Subscription } from "rxjs"; let component: JobsListComponent; let fixture: ComponentFixture; const eijob1 = { - ei_job_identity: 'job1', - ei_type_identity: 'type1', - owner: 'owner1', - target_uri: 'http://one' + ei_job_identity: "job1", + ei_type_identity: "type1", + owner: "owner1", + target_uri: "http://one", } as EIJob; const eijob2 = { - ei_job_identity: 'job2', - ei_type_identity: 'type2', - owner: 'owner2', - target_uri: 'http://two' + ei_job_identity: "job2", + ei_type_identity: "type2", + owner: "owner2", + target_uri: "http://two", } as EIJob; const job1 = { - jobId: 'job1', - typeId: 'type1', - owner: 'owner1', - targetUri: 'http://one', - prodId: 'producer1' + jobId: "job1", + typeId: "type1", + owner: "owner1", + targetUri: "http://one", + prodId: "producer1", } as Job; const job2 = { - jobId: 'job2', - typeId: 'type2', - owner: 'owner2', - targetUri: 'http://two', - prodId: 'producer1' + jobId: "job2", + typeId: "type2", + owner: "owner2", + targetUri: "http://two", + prodId: "producer1", } as Job; const job3 = { - jobId: 'job1', - typeId: 'type1', - owner: 'owner1', - targetUri: 'http://one', - prodId: 'producer2' + jobId: "job1", + typeId: "type1", + owner: "owner1", + targetUri: "http://one", + prodId: "producer2", } as Job; const job4 = { - jobId: 'job2', - typeId: 'type2', - owner: 'owner2', - targetUri: 'http://two', - prodId: 'producer2' + jobId: "job2", + typeId: "type2", + owner: "owner2", + targetUri: "http://two", + prodId: "producer2", } as Job; -describe('JobsListComponent', () => { +describe("JobsListComponent", () => { let loader: HarnessLoader; beforeEach(async(() => { - const spy = jasmine.createSpyObj('EIService', ['getProducerIds', 'getJobsForProducer']); + const spy = jasmine.createSpyObj("EIService", [ + "getProducerIds", + "getJobsForProducer", + ]); TestBed.configureTestingModule({ imports: [ @@ -99,14 +110,11 @@ describe('JobsListComponent', () => { ReactiveFormsModule, BrowserAnimationsModule, MatFormFieldModule, - MatInputModule + MatInputModule, ], schemas: [CUSTOM_ELEMENTS_SCHEMA], declarations: [JobsListComponent], - providers: [ - { provide: EIService, useValue: spy }, - UiService - ] + providers: [{ provide: EIService, useValue: spy }, UiService], }) .compileComponents() .then(() => { @@ -116,181 +124,350 @@ describe('JobsListComponent', () => { }); })); - const expectedJob1Row = { jobId: 'job1', prodId: 'producer1', typeId: 'type1', owner: 'owner1', targetUri: 'http://one' }; + const expectedJob1Row = { + jobId: "job1", + prodId: "producer1", + typeId: "type1", + owner: "owner1", + targetUri: "http://one", + }; - it('should create', () => { + it("should create", () => { expect(component).toBeTruthy(); }); - describe('#content', () => { - - it('should loadJobs', () => { + describe("#content", () => { + it("should loadJobs", fakeAsync(() => { setServiceSpy(); - component.loadJobs(); + const newSub: Subscription = component.dataSubscription(); + tick(0); + const actualJobs: Job[] = component.jobs(); expect(actualJobs.length).toEqual(4); expect(actualJobs).toEqual([job1, job2, job3, job4]); - }); + newSub.unsubscribe(); + })); - it('should contain job table with correct columns', async () => { + it("should contain job table with correct columns", fakeAsync(() => { setServiceSpy(); - let jobsTable = await loader.getHarness(MatTableHarness.with({ selector: '#jobsTable' })); - let headerRow = (await jobsTable.getHeaderRows())[0]; - let headers = await headerRow.getCellTextByColumnName(); + component.ngOnInit(); + tick(0); + + loader + .getHarness(MatTableHarness.with({ selector: "#jobsTable" })) + .then((loadTable) => { + loadTable.getHeaderRows().then((headerRow) => { + headerRow[0].getCellTextByColumnName().then((header) => { + expect(header).toEqual({ + jobId: "Job ID", + prodId: "Producer ID", + typeId: "Type ID", + owner: "Owner", + targetUri: "Target URI", + }); + }); + }); + }); - expect(headers).toEqual({ jobId: 'Job ID', prodId: 'Producer ID', typeId: 'Type ID', owner: 'Owner', targetUri: 'Target URI' }); - }); + discardPeriodicTasks(); + })); - it('should set correct dark mode from UIService', () => { + it("should set correct dark mode from UIService", fakeAsync(() => { setServiceSpy(); component.ngOnInit(); + tick(0); + const uiService: UiService = TestBed.inject(UiService); expect(component.darkMode).toBeTruthy(); uiService.darkModeState.next(false); fixture.detectChanges(); expect(component.darkMode).toBeFalsy(); - }); + discardPeriodicTasks(); + })); }); - describe('#jobsTable', () => { - - it('should contain data after initialization', async () => { + describe("#jobsTable", () => { + it("should contain data after initialization", fakeAsync(() => { setServiceSpy(); component.ngOnInit(); + tick(0); + const expectedJobRows = [ expectedJob1Row, - { jobId: 'job2', prodId: 'producer1', typeId: 'type2', owner: 'owner2', targetUri: 'http://two' }, - { jobId: 'job1', prodId: 'producer2', typeId: 'type1', owner: 'owner1', targetUri: 'http://one' }, - { jobId: 'job2', prodId: 'producer2', typeId: 'type2', owner: 'owner2', targetUri: 'http://two' } + { + jobId: "job2", + prodId: "producer1", + typeId: "type2", + owner: "owner2", + targetUri: "http://two", + }, + { + jobId: "job1", + prodId: "producer2", + typeId: "type1", + owner: "owner1", + targetUri: "http://one", + }, + { + jobId: "job2", + prodId: "producer2", + typeId: "type2", + owner: "owner2", + targetUri: "http://two", + }, ]; - let jobsTable = await loader.getHarness(MatTableHarness.with({ selector: '#jobsTable' })); - let jobRows = await jobsTable.getRows(); - expect(jobRows.length).toEqual(4); - jobRows.forEach(row => { - row.getCellTextByColumnName().then(values => { - expect(expectedJobRows).toContain(jasmine.objectContaining(values)); - }); - }); - }); - it('should display default values for non required properties ', async () => { + loader + .getHarness(MatTableHarness.with({ selector: "#jobsTable" })) + .then((loadTable) => { + loadTable.getRows().then((jobRows) => { + expect(jobRows.length).toEqual(4); + jobRows.forEach((row) => { + row.getCellTextByColumnName().then((values) => { + expect(expectedJobRows).toContain( + jasmine.objectContaining(values) + ); + }); + }); + }); + }); + discardPeriodicTasks(); + })); + it("should display default values for non required properties ", fakeAsync(() => { const jobMissingProperties = { - "ei_job_identity": "job1", - "ei_job_data": { - "jobparam2": "value2_job2", - "jobparam3": "value3_job2", - "jobparam1": "value1_job2" + ei_job_identity: "job1", + ei_job_data: { + jobparam2: "value2_job2", + jobparam3: "value3_job2", + jobparam1: "value1_job2", }, - "target_uri": "http://one" + target_uri: "http://one", } as EIJob; let eiServiceSpy = TestBed.inject(EIService) as jasmine.SpyObj; - eiServiceSpy.getProducerIds.and.returnValue(of(['producer1'])); - eiServiceSpy.getJobsForProducer.and.returnValue(of([jobMissingProperties])); + eiServiceSpy.getProducerIds.and.returnValue(of(["producer1"])); + eiServiceSpy.getJobsForProducer.and.returnValue( + of([jobMissingProperties]) + ); component.ngOnInit(); - const expectedJobRow = { jobId: 'job1', prodId: 'producer1', typeId: '< No type >', owner: '< No owner >', targetUri: 'http://one' }; - let jobsTable = await loader.getHarness(MatTableHarness.with({ selector: '#jobsTable' })); - let jobRows = await jobsTable.getRows(); - expect(await jobRows[0].getCellTextByColumnName()).toEqual(expectedJobRow); - }); + tick(0); + const expectedJobRow = { + jobId: "job1", + prodId: "producer1", + typeId: "< No type >", + owner: "< No owner >", + targetUri: "http://one", + }; + + loader + .getHarness(MatTableHarness.with({ selector: "#jobsTable" })) + .then((loadTable) => { + loadTable.getRows().then((jobRows) => { + jobRows[0].getCellTextByColumnName().then((value) => { + expect(expectedJobRow).toContain(jasmine.objectContaining(value)); + }); + }); + }); + discardPeriodicTasks(); + })); - it('filtering', async () => { + it("filtering", fakeAsync(() => { setServiceSpy(); component.ngOnInit(); - let jobsTable = await loader.getHarness(MatTableHarness.with({ selector: '#jobsTable' })); - - let idFilterInput = await loader.getHarness(MatInputHarness.with({ selector: '#jobIdFilter' })); - await idFilterInput.setValue("1"); - let jobRows = await jobsTable.getRows(); - expect(jobRows.length).toEqual(2); - expect(await jobRows[0].getCellTextByColumnName()).toEqual(expectedJob1Row); - - idFilterInput.setValue(''); - let typeIdFilterInput = await loader.getHarness(MatInputHarness.with({ selector: '#jobTypeIdFilter' })); - await typeIdFilterInput.setValue("1"); - jobRows = await jobsTable.getRows(); - expect(jobRows.length).toEqual(2); - - typeIdFilterInput.setValue(''); - let ownerFilterInput = await loader.getHarness(MatInputHarness.with({ selector: '#jobOwnerFilter' })); - await ownerFilterInput.setValue("1"); - jobRows = await jobsTable.getRows(); - expect(jobRows.length).toEqual(2); - expect(await jobRows[0].getCellTextByColumnName()).toEqual(expectedJob1Row); - - ownerFilterInput.setValue(''); - let targetUriFilterInput = await loader.getHarness(MatInputHarness.with({ selector: '#jobTargetUriFilter' })); - await targetUriFilterInput.setValue("one"); - jobRows = await jobsTable.getRows(); - expect(jobRows.length).toEqual(2); - expect(await jobRows[0].getCellTextByColumnName()).toEqual(expectedJob1Row); - }); + tick(0); + + loader + .getHarness(MatTableHarness.with({ selector: "#jobsTable" })) + .then((loadTable) => { + loader + .getHarness(MatInputHarness.with({ selector: "#jobIdFilter" })) + .then((idFilter) => { + idFilter.setValue("1"); + loadTable.getRows().then((jobRows) => { + expect(jobRows.length).toEqual(2); + jobRows[0].getCellTextByColumnName().then((value) => { + expect(expectedJob1Row).toContain( + jasmine.objectContaining(value) + ); + }); + }); + idFilter.setValue(""); + }); + loader + .getHarness(MatInputHarness.with({ selector: "#jobTypeIdFilter" })) + .then((typeIdFilter) => { + typeIdFilter.setValue("1"); + loadTable.getRows().then((jobRows) => { + expect(jobRows.length).toEqual(2); + jobRows[0].getCellTextByColumnName().then((value) => { + expect(expectedJob1Row).toContain( + jasmine.objectContaining(value) + ); + }); + }); + typeIdFilter.setValue(""); + }); + loader + .getHarness(MatInputHarness.with({ selector: "#jobOwnerFilter" })) + .then((ownerFilter) => { + ownerFilter.setValue("1"); + loadTable.getRows().then((jobRows) => { + expect(jobRows.length).toEqual(2); + jobRows[0].getCellTextByColumnName().then((value) => { + expect(expectedJob1Row).toContain( + jasmine.objectContaining(value) + ); + }); + }); + ownerFilter.setValue(""); + }); + loader + .getHarness( + MatInputHarness.with({ selector: "#jobTargetUriFilter" }) + ) + .then((targetUriFilter) => { + targetUriFilter.setValue("1"); + loadTable.getRows().then((jobRows) => { + expect(jobRows.length).toEqual(2); + jobRows[0].getCellTextByColumnName().then((value) => { + expect(expectedJob1Row).toContain( + jasmine.objectContaining(value) + ); + }); + }); + targetUriFilter.setValue(""); + }); + }); - describe('#sorting', () => { + discardPeriodicTasks(); + })); - it('should verify sort functionality on the table', async () => { + describe("#sorting", () => { + it("should verify sort functionality on the table", fakeAsync(() => { setServiceSpy(); - const sort = await loader.getHarness(MatSortHarness); - let headers = await sort.getSortHeaders({ sortDirection: '' }); - expect(headers.length).toBe(5); - - await headers[0].click(); - expect(await headers[0].isActive()).toBe(true); - expect(await headers[0].getSortDirection()).toBe('asc'); - - await headers[0].click(); - expect(await headers[0].getSortDirection()).toBe('desc'); - - }); + tick(0); + + loader.getHarness(MatSortHarness).then((sort) => { + sort.getSortHeaders({ sortDirection: "" }).then((headers) => { + expect(headers.length).toBe(5); + + headers[0].click().then((_) => { + headers[0].isActive().then((active) => { + expect(active).toBe(true); + }); + headers[0].getSortDirection().then((direction) => { + expect(direction).toBe("asc"); + }); + }); + headers[0].click().then((_) => { + headers[0].getSortDirection().then((direction) => { + expect(direction).toBe("desc"); + }); + }); + }); + }); + discardPeriodicTasks(); + })); - it('should sort table asc and desc by first header', async () => { + it("should sort table asc and desc by first header", fakeAsync(() => { setServiceSpy(); - const sort = await loader.getHarness(MatSortHarness); - let jobsTable = await loader.getHarness(MatTableHarness.with({ selector: '#jobsTable' })); - const firstHeader = (await sort.getSortHeaders())[0]; - expect(await firstHeader.getSortDirection()).toBe(''); - - await firstHeader.click(); - expect(await firstHeader.getSortDirection()).toBe('asc'); - let jobRows = await jobsTable.getRows(); - jobRows = await jobsTable.getRows(); - expect(await jobRows[0].getCellTextByColumnName()).toEqual(expectedJob1Row); - - await firstHeader.click(); - expect(await firstHeader.getSortDirection()).toBe('desc'); - jobRows = await jobsTable.getRows(); - expect(await jobRows[jobRows.length - 1].getCellTextByColumnName()).toEqual(expectedJob1Row); - }); + tick(0); + + loader.getHarness(MatSortHarness).then((sort) => { + loader + .getHarness(MatTableHarness.with({ selector: "#jobsTable" })) + .then((loadTable) => { + sort.getSortHeaders().then((headers) => { + headers[0].click().then((_) => { + headers[0].getSortDirection().then((direction) => { + expect(direction).toBe(""); + }); + }); + headers[0].click().then((_) => { + headers[0].getSortDirection().then((direction) => { + expect(direction).toBe("asc"); + }); + }); + loadTable.getRows().then((jobRows) => { + jobRows[0].getCellTextByColumnName().then((value) => { + expect(expectedJob1Row).toContain( + jasmine.objectContaining(value) + ); + }); + }); + headers[0].click().then((_) => { + headers[0].getSortDirection().then((direction) => { + expect(direction).toBe("desc"); + }); + }); + loadTable.getRows().then((jobRows) => { + jobRows[jobRows.length - 1] + .getCellTextByColumnName() + .then((value) => { + expect(expectedJob1Row).toContain( + jasmine.objectContaining(value) + ); + }); + }); + }); + }); + }); + discardPeriodicTasks(); + })); }); - describe('#paging', () => { - it('should work properly on the table', async () => { - let eiServiceSpy = TestBed.inject(EIService) as jasmine.SpyObj; - eiServiceSpy.getProducerIds.and.returnValue(of(['producer1', 'producer2'])); - eiServiceSpy.getJobsForProducer.and.returnValue(of([eijob1, eijob2, eijob1])); - - const paging = await loader.getHarness(MatPaginatorHarness); - await paging.setPageSize(5); - - let jobsTable = await loader.getHarness(MatTableHarness.with({ selector: '#jobsTable' })); - let jobRows = await jobsTable.getRows(); - expect(jobRows.length).toEqual(5); + describe("#paging", () => { + it("should work properly on the table", fakeAsync(() => { + let eiServiceSpy = TestBed.inject( + EIService + ) as jasmine.SpyObj; + eiServiceSpy.getProducerIds.and.returnValue( + of(["producer1", "producer2"]) + ); + eiServiceSpy.getJobsForProducer.and.returnValue( + of([eijob1, eijob2, eijob1]) + ); + tick(0); + + loader.getHarness(MatPaginatorHarness).then((paging) => { + paging.setPageSize(5); + + loader + .getHarness(MatTableHarness.with({ selector: "#jobsTable" })) + .then((loadTable) => { + loadTable.getRows().then((jobRows) => { + expect(jobRows.length).toEqual(5); + }); + paging.goToNextPage(); + loadTable.getRows().then((jobRows) => { + expect(jobRows.length).toEqual(1); + jobRows[0].getCellTextByColumnName().then((value) => { + const expectedRow = { + jobId: "job1", + prodId: "producer2", + typeId: "type1", + owner: "owner1", + targetUri: "http://one", + }; + expect(expectedRow).toContain( + jasmine.objectContaining(value) + ); + }); + }); + }); + }); - await paging.goToNextPage(); - jobRows = await jobsTable.getRows(); - expect(jobRows.length).toEqual(1); - const expectedRow = { jobId: 'job1', prodId: 'producer2', typeId: 'type1', owner: 'owner1', targetUri: 'http://one' }; - expect(await jobRows[jobRows.length - 1].getCellTextByColumnName()).toEqual(expectedRow); - }); + discardPeriodicTasks(); + })); }); }); }); function setServiceSpy() { let eiServiceSpy = TestBed.inject(EIService) as jasmine.SpyObj; - eiServiceSpy.getProducerIds.and.returnValue(of(['producer1', 'producer2'])); + eiServiceSpy.getProducerIds.and.returnValue(of(["producer1", "producer2"])); eiServiceSpy.getJobsForProducer.and.returnValue(of([eijob1, eijob2])); } diff --git a/webapp-frontend/src/app/ei-coordinator/jobs-list/jobs-list.component.ts b/webapp-frontend/src/app/ei-coordinator/jobs-list/jobs-list.component.ts index 7fea537..58e437a 100644 --- a/webapp-frontend/src/app/ei-coordinator/jobs-list/jobs-list.component.ts +++ b/webapp-frontend/src/app/ei-coordinator/jobs-list/jobs-list.component.ts @@ -17,17 +17,27 @@ * 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 { + forkJoin, + Subscription, + timer, +} from "rxjs"; +import { BehaviorSubject } from "rxjs/BehaviorSubject"; +import { + mergeMap, + finalize, + map, + tap, + switchMap, +} from "rxjs/operators"; +import { EIJob } from "@interfaces/ei.types"; +import { EIService } from "@services/ei/ei.service"; +import { UiService } from "@services/ui/ui.service"; export interface Job { jobId: string; @@ -39,51 +49,52 @@ 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; jobForm: FormGroup; - private loadingSubject = new BehaviorSubject(false); + darkMode: boolean; + private jobsSubject = new BehaviorSubject([]); + private refresh$ = new BehaviorSubject(""); + private loadingSubject = new BehaviorSubject(false); public loading$ = this.loadingSubject.asObservable(); + subscription: Subscription; - constructor( - private eiSvc: EIService, - private ui: UiService - ) { + constructor(private eiSvc: EIService, 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.subscription = this.dataSubscription(); + this.jobsSubject.subscribe((data) => { this.jobsDataSource = new MatTableDataSource(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,31 +103,60 @@ export class JobsListComponent implements OnInit { }); } + dataSubscription(): Subscription { + let prodId = []; + const jobs$ = this.eiSvc.getProducerIds().pipe( + tap((data) => (prodId = data)), + mergeMap((prodIds) => + forkJoin(prodIds.map((id) => this.eiSvc.getJobsForProducer(id))) + ), + finalize(() => this.loadingSubject.next(false)) + ); + + return this.refresh$ + .pipe( + switchMap((_) => + timer(0, 10000).pipe( + tap((_) => { + this.loadingSubject.next(true); + }), + switchMap((_) => jobs$), + map((response) => this.extractJobs(prodId, response)) + ) + ) + ) + .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; @@ -139,42 +179,40 @@ export class JobsListComponent implements OnInit { if (eiJob.typeId) { return eiJob.typeId; } - return '< No type >'; + return "< No type >"; } getJobOwner(eiJob: Job): string { if (eiJob.owner) { return eiJob.owner; } - return '< No owner >'; + return "< No owner >"; } public jobs(): Job[] { 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: EIJob[][]) { + console.log(res.length); + let jobList = []; + prodId.forEach((element, index) => { + let jobs = res[index]; + jobList = jobList.concat(jobs.map((job) => this.createJob(element, job))); }); + this.jobsSubject.next(jobList); + return jobList; } + createJobList(prodId: any[], result: EIJob[][]) { 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 = {}; eiJob.jobId = job.ei_job_identity; @@ -185,4 +223,7 @@ export class JobsListComponent implements OnInit { return eiJob; } + refreshDataClick() { + this.refresh$.next(""); + } } -- 2.16.6