From 6f900cc45d7dd7f97430812b86b5c1d1693c8ae3 Mon Sep 17 00:00:00 2001 From: Ittay Stern Date: Wed, 29 Aug 2018 17:01:32 +0300 Subject: merge from ecomp a88f0072 - Modern UI Issue-ID: VID-378 Change-Id: Ibcb23dd27f550cf32ce2fe0239f0f496ae014ff6 Signed-off-by: Ittay Stern --- .../InstantiationStatus.module.ts | 9 +- .../InstantiationStatus.routing.ts | 19 ++ .../auditInfoModal/auditInfoModal.component.html | 84 ------- .../auditInfoModal/auditInfoModal.component.scss | 159 ------------- .../auditInfoModal.component.service.ts | 0 .../auditInfoModal/auditInfoModal.component.ts | 83 ------- .../instantiationStatus.component.html | 60 +++-- .../instantiationStatus.component.service.spec.ts | 118 ++++++++-- .../instantiationStatus.component.service.ts | 136 +++++++++-- .../instantiationStatus.component.spec.ts | 251 ++++++++++++++++----- .../instantiationStatus.component.ts | 170 ++++++++++---- 11 files changed, 585 insertions(+), 504 deletions(-) create mode 100644 vid-webpack-master/src/app/instantiationStatus/InstantiationStatus.routing.ts delete mode 100644 vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.html delete mode 100644 vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.scss delete mode 100644 vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.service.ts delete mode 100644 vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.ts (limited to 'vid-webpack-master/src/app/instantiationStatus') diff --git a/vid-webpack-master/src/app/instantiationStatus/InstantiationStatus.module.ts b/vid-webpack-master/src/app/instantiationStatus/InstantiationStatus.module.ts index 01db0f187..6d14b149d 100644 --- a/vid-webpack-master/src/app/instantiationStatus/InstantiationStatus.module.ts +++ b/vid-webpack-master/src/app/instantiationStatus/InstantiationStatus.module.ts @@ -1,33 +1,30 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { InputsModule } from '../modules/inputs.module'; import { DataTableModule } from 'angular2-datatable'; import { BootstrapModalModule } from 'ng2-bootstrap-modal'; import { TooltipModule } from 'ngx-tooltip'; import { InstantiationStatusComponent } from './instantiationStatus.component'; import { InstantiationStatusComponentService } from './instantiationStatus.component.service'; import { SharedModule } from '../shared/shared.module'; -import { AngularSvgIconModule } from 'angular-svg-icon'; import { ContextMenuModule, ContextMenuService } from 'ngx-contextmenu'; import {ModalModule, PopoverModule} from 'ngx-bootstrap'; -import {AuditInfoModalComponent} from "./auditInfoModal/auditInfoModal.component"; +import {SdcUiComponentsModule} from "onap-ui-angular"; @NgModule({ imports: [ CommonModule, FormsModule, ReactiveFormsModule, + SdcUiComponentsModule, BootstrapModalModule, DataTableModule, TooltipModule, ModalModule, - InputsModule, - AngularSvgIconModule, ContextMenuModule, SharedModule.forRoot(), PopoverModule.forRoot()], - declarations: [InstantiationStatusComponent, AuditInfoModalComponent], + declarations: [InstantiationStatusComponent, ], providers: [InstantiationStatusComponentService, ContextMenuService] }) export class InstantiationStatusModule { } diff --git a/vid-webpack-master/src/app/instantiationStatus/InstantiationStatus.routing.ts b/vid-webpack-master/src/app/instantiationStatus/InstantiationStatus.routing.ts new file mode 100644 index 000000000..6991eefef --- /dev/null +++ b/vid-webpack-master/src/app/instantiationStatus/InstantiationStatus.routing.ts @@ -0,0 +1,19 @@ +import {Route} from "@angular/router"; +import {FlagsResolve} from "../shared/resolvers/flag/flag.resolver"; +import {InstantiationStatusComponent} from "./instantiationStatus.component"; + +export const InstantiationStatusRoutes: Route[] = [ + { + path: 'instantiationStatus', + children: [ + { + path: '', + component: InstantiationStatusComponent, + resolve: { + flags: FlagsResolve + }, + } + ] + } +]; + diff --git a/vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.html b/vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.html deleted file mode 100644 index 9386af347..000000000 --- a/vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.html +++ /dev/null @@ -1,84 +0,0 @@ - diff --git a/vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.scss b/vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.scss deleted file mode 100644 index 27b271496..000000000 --- a/vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.scss +++ /dev/null @@ -1,159 +0,0 @@ -.templatebody.modal-open{ - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1040; - background-color: #000; - opacity: 0.5; -} -.modal{ - - #audit-info-modal { - - .modal-content{ - border-radius: 0px; - border: none; - .modal-header{ - background: #009FDB; - font-size: 24px; - color: #ffffff; - .close{ - font-size: 32px; - font-weight: 200; - color: #ffffff; - text-shadow: none; - filter: none; - opacity: 1; - &:hover{ - color: #d2d2d2; - } - } - .modal-title{ - - } - } - .modal-body{ - padding: 0px; - margin: 0px; - display: flex; - .left-panel{ - background: #f2f2f2; - border-right: 1px solid #D2D2D2; - padding-right: 0px; - .row:first-child{ - border-bottom: 1px solid #D2D2D2; - height: 50px; - font-size: 12px; - line-height: 50px; - padding-left: 30px; - font-weight: 700; - margin-right: 0px; - } - .service-model{ - padding-left: 30px; - padding-top: 15px; - } - } - .right-panel{ - padding: 30px 30px 15px 30px; - .row{ - margin: 0px; - } - .table-title{ - font-size: 12px; - text-transform: uppercase; - font-weight: bold; - } - .no-result{ - margin-bottom: 20px; - text-align: center; - border: 1px solid #d2d2d2; - padding: 20px; - margin-top: -23px; - } - - .table-bordered{ - width: 100%; - margin-top: 10px; - font-family: OpenSans-Semibold; - font-size: 12px; - overflow-x: auto; - display: block; - color: #5A5A5A; - - thead { - position: sticky; - top: 0; - z-index: 100; - display: block; - background: rgb(242, 242, 242); - border-bottom: 1px solid #d2d2d2; - tr { - display: flex; - th { - flex-grow: 1; - border-right: 1px solid #d2d2d2; - &:last-child{ - border-right: none; - } - } - } - } - - tbody { - border: none !important; - max-height: 152px; - display: block; - - tr { - display: flex; - border-bottom: 1px solid #d2d2d2; - &:last-child{ - border-bottom: none; - } - td { - border: none; - border-right: 1px solid #d2d2d2; - &:last-child{ - border-right: none; - } - } - } - } - - th { - background: #f2f2f2; - font-family: OpenSans-Semibold; - color: #000000; - font-weight: bold; - border: none; - } - - tr.odd { - background-color: rgb(242, 242, 242); - } - - tr:hover { - background: #e1e1e1; - } - } - } - } - .modal-footer{ - margin: 0px; - .cancel{ - width: 120px; - height: 36px; - background: #009fdb; - border-radius: 2px; - font-family: OpenSans-Regular; - font-size: 14px; - color: #ffffff; - line-height: 16px; - } - } - } - } -} diff --git a/vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.service.ts b/vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.service.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.ts b/vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.ts deleted file mode 100644 index 1cff97f5b..000000000 --- a/vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.ts +++ /dev/null @@ -1,83 +0,0 @@ -import {Component, ViewChild} from '@angular/core'; -import {Subject} from 'rxjs/Subject'; -import {ModalDirective} from 'ngx-bootstrap' -import {Constants} from '../../shared/utils/constants'; -import {ModelInformationItem} from '../../shared/components/model-information/model-information.component'; -import {ServiceModel} from '../../shared/models/serviceModel'; -import {ServiceInfoService} from '../../shared/server/serviceInfo/serviceInfo.service'; -import {ServiceInfoModel} from '../../shared/server/serviceInfo/serviceInfo.model'; -import {AuditStatus} from '../../shared/server/serviceInfo/AuditStatus.model'; -import {IframeService} from "../../shared/utils/iframe.service"; - -@Component({ - selector: 'audit-info-modal', - templateUrl: './auditInfoModal.component.html', - styleUrls: ['./auditInfoModal.component.scss'] -}) -export class AuditInfoModalComponent { - static openModal: Subject = new Subject(); - @ViewChild('auditInfoModal') public auditInfoModal: ModalDirective; - title: string = Constants.AuditInfoModal.TITLE; - modelInfoItems: Array = []; - serviceModel: ServiceModel; - serviceModelName: string; - vidInfoData: Array = []; - msoInfoData: Array = []; - parentElementClassName = 'content'; - isLoading = true; - - constructor(private _serviceInfoService: ServiceInfoService, private _iframeService : IframeService) { - AuditInfoModalComponent.openModal.subscribe((jobData: ServiceInfoModel) => { - this.initializeProperties(); - if (jobData) { - this.openAuditInfoModal(jobData); - _iframeService.addClassOpenModal(this.parentElementClassName); - this.serviceModelName = jobData.serviceModelName ? jobData.serviceModelName : ''; - this.auditInfoModal.show(); - } else { - _iframeService.removeClassCloseModal(this.parentElementClassName); - this.auditInfoModal.hide(); - } - }) - } - - initializeProperties() : void { - this.modelInfoItems = null; - this.vidInfoData = []; - this.msoInfoData = []; - this.isLoading = true; - } - - openAuditInfoModal(jobData: ServiceInfoModel): void { - this.modelInfoItems = this.createModelInformationItems(jobData); - this.initAuditInfoData(jobData['jobId']); - this.auditInfoModal.show(); - } - - initAuditInfoData(jobId: string) { - this._serviceInfoService.getJobAuditStatus(jobId) - .subscribe((res: Array>) => { - this.vidInfoData = res[0]; - this.msoInfoData = res[1]; - this.isLoading = false; - }); - } - - createModelInformationItems(serviceModel: ServiceInfoModel): Array { - return [ - new ModelInformationItem('Subscriber name', 'subscriberName', [serviceModel.subscriberName]), - new ModelInformationItem('Service type', 'serviceType', [serviceModel.serviceType]), - new ModelInformationItem('Service model version', 'serviceModelVersion', [serviceModel.serviceModelVersion]), - new ModelInformationItem('Service instance name', 'serviceInstanceName', [serviceModel.serviceInstanceName], '', true), - new ModelInformationItem('Service instance ID', 'serviceInstanceId', [serviceModel.serviceInstanceId]), - new ModelInformationItem('Requestor User ID', 'userId', [serviceModel.userId]), - ]; - } - - onCancelClick() { - this._iframeService.removeClassCloseModal(this.parentElementClassName); - this.initializeProperties(); - this.auditInfoModal.hide(); - } -} - diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.html b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.html index e0641d03b..212981aaf 100644 --- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.html +++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.html @@ -3,7 +3,7 @@
- Instantiation Status + Instantiation Status User ID + Action Model Name Instance Name Model version @@ -40,8 +41,9 @@ - + + @@ -55,37 +57,32 @@ - - + + + + - -
diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.spec.ts b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.spec.ts index c9f434e99..4848d8e99 100644 --- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.spec.ts +++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.spec.ts @@ -1,5 +1,6 @@ import {getTestBed, TestBed} from '@angular/core/testing'; import { + COMPLETED_WITH_ERRORS, INPROGRESS, InstantiationStatusComponentService, PAUSE, @@ -10,24 +11,64 @@ import { X_O } from './instantiationStatus.component.service'; import {ServiceInfoModel} from '../shared/server/serviceInfo/serviceInfo.model'; -import { Observable } from 'rxjs/Rx'; +import {AaiService} from "../shared/services/aaiService/aai.service"; +import {MsoService} from "../shared/services/msoService/mso.service"; +import {NgRedux} from "@angular-redux/store"; +import {HttpClientTestingModule} from "@angular/common/http/testing"; +import {FeatureFlagsService} from "../shared/services/featureFlag/feature-flags.service"; +import {DrawingBoardModes} from "../drawingBoard/service-planning/drawing-board.modes"; +import {RouterTestingModule} from "@angular/router/testing"; +import {of} from "rxjs"; +import {UrlTree} from "@angular/router"; +class MockAppStore { + + getState() { + return { + global: { + flags: { + 'FLAG_1902_NEW_VIEW_EDIT': true, + + } + } + } + } + + dispatch() { + + } +} describe('Instantiation Status Service', () => { let injector; + let aaiService: AaiService; + let msoService: MsoService; let service: InstantiationStatusComponentService; - beforeEach(() => { + + beforeAll(done => (async () => { TestBed.configureTestingModule({ - imports: [], - providers: [InstantiationStatusComponentService] + imports: [ + HttpClientTestingModule, + RouterTestingModule, + ], + providers: [ + InstantiationStatusComponentService, + AaiService, + MsoService, + FeatureFlagsService, + {provide: NgRedux, useClass: MockAppStore}] }); + await TestBed.compileComponents(); injector = getTestBed(); + aaiService = injector.get(AaiService); + msoService = injector.get(MsoService); service = injector.get(InstantiationStatusComponentService); - }); - it('generateServiceInfoDataMapping should return mapping of arrays', (done: DoneFn) => { - let data : Array = generateServiceInfoData(); + })().then(done).catch(done.fail)); + + test('generateServiceInfoDataMapping should return mapping of arrays', () => { + let data : ServiceInfoModel[] = generateServiceInfoData(); let result = service.generateServiceInfoDataMapping(data); expect(result['1']).toBeDefined(); @@ -37,53 +78,81 @@ describe('Instantiation Status Service', () => { expect(result['1'].length).toEqual(2); expect(result['2'].length).toEqual(2); expect(result['3'].length).toEqual(1); - done(); }); - it('generateServiceInfoDataMapping if array is empty should return empty object', (done: DoneFn) => { + test('generateServiceInfoDataMapping if array is empty should return empty object', () => { let result = service.generateServiceInfoDataMapping([]); expect(result['1']).not.toBeDefined(); expect(result['2']).not.toBeDefined(); expect(result['3']).not.toBeDefined(); - done(); }); - it('convertObjectToArray', (done: DoneFn) => { + test('convertObjectToArray', () => { - spyOn(service, 'convertObjectToArray').and.returnValue( - Observable.of([]) + jest.spyOn(service, 'convertObjectToArray').mockReturnValue( + of([]) ); - let data : Array = generateServiceInfoData(); + let data : ServiceInfoModel[] = generateServiceInfoData(); service.convertObjectToArray(data).subscribe((result) => { expect(result).toBeDefined(); - done(); }); }); - it('getStatusTooltip should return status popover', (done: DoneFn) => { + test('click on "Open" button should open new view edit' , ()=>{ + const item = { + serviceModelId : 'serviceModelId', + serviceInstanceId : 'serviceInstanceId', + serviceType : 'serviceType', + subscriberId : 'subscriberId' + }; + let params:UrlTree = service.getNewViewEditUrlTree(item, DrawingBoardModes.VIEW); + expect(params.toString().startsWith('/servicePlanning/VIEW')).toBeTruthy(); + expect(params.queryParams).toEqual( + { + serviceModelId: item.serviceModelId, + serviceInstanceId: item.serviceInstanceId, + serviceType : item.serviceType, + subscriberId : item.subscriberId + }); + }); + + test('build the View Edit url' , ()=>{ + const item = { + serviceModelId : '28aeb8f6-5620-4148-8bfb-a5fb406f0309', + }; + let serviceModelUrl: string = '/servicePlanning/EDIT?serviceModelId=28aeb8f6-5620-4148-8bfb-a5fb406f0309'; + let suffix:string = '../../serviceModels.htm#'; + let tree:UrlTree = service.getNewViewEditUrlTree(item, DrawingBoardModes.EDIT); + let result = service.getViewEditUrl(tree); + expect (suffix + serviceModelUrl).toEqual(result); + }); + + test('getStatusTooltip should return status popover', () => { let result : ServiceStatus = service.getStatus('pending'); - expect(result.tooltip).toEqual('Pending: The service will automatically be sent for instantiation as soon as possible.'); + expect(result.tooltip).toEqual('Pending: The action required will be sent as soon as possible.'); result = service.getStatus('IN_PROGRESS'); - expect(result.tooltip).toEqual('In-progress: the service is in process of instantiation.'); + expect(result.tooltip).toEqual('In-progress: the service is in process of the action required.'); result = service.getStatus('PAUSED'); expect(result.tooltip).toEqual('Paused: Service has paused and waiting for your action.\n Select actions from the menu to the right.'); result = service.getStatus('FAILED'); - expect(result.tooltip).toEqual('Failed: Service instantiation has failed, load the service to see the error returned.'); + expect(result.tooltip).toEqual('Failed: All planned actions have failed.'); result = service.getStatus('COMPLETED'); - expect(result.tooltip).toEqual('Completed successfully: Service is successfully instantiated.'); + expect(result.tooltip).toEqual('Completed successfully: Service is successfully instantiated, updated or deleted.'); result = service.getStatus('STOPPED'); expect(result.tooltip).toEqual('Stopped: Due to previous failure, will not be instantiated.'); - done(); + + result = service.getStatus('COMPLETED_WITH_ERRORS'); + expect(result.tooltip).toEqual('Completed with errors: some of the planned actions where successfully committed while other have not.\n Open the service to check it out.'); }); - it('getStatusTooltip should return correct icon per job status', (done: DoneFn) => { + test('getStatusTooltip should return correct icon per job status', () => { let result : ServiceStatus = service.getStatus('pending'); expect(result.iconClassName).toEqual(PENDING); @@ -101,9 +170,10 @@ describe('Instantiation Status Service', () => { result = service.getStatus('STOPPED'); expect(result.iconClassName).toEqual(STOPED); - done(); - }); + result = service.getStatus('COMPLETED_WITH_ERRORS'); + expect(result.iconClassName).toEqual(COMPLETED_WITH_ERRORS); + }); function generateServiceInfoData(){ return JSON.parse(JSON.stringify([ diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts index 293397cc9..0e4451ca8 100644 --- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts +++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts @@ -1,23 +1,38 @@ import {Injectable} from '@angular/core'; import {ServiceInfoModel, ServiceInfoUiModel} from '../shared/server/serviceInfo/serviceInfo.model'; -import {isNullOrUndefined} from "util"; -import { Observable } from 'rxjs/Observable'; -import 'rxjs/observable/of'; - +import * as _ from 'lodash'; +import {Observable} from 'rxjs/Observable'; +import {NgRedux} from "@angular-redux/store"; +import {AppState} from "../shared/store/reducers"; +import {AaiService} from "../shared/services/aaiService/aai.service"; +import {ServiceModel} from "../shared/models/serviceModel"; +import {FeatureFlagsService, Features} from "../shared/services/featureFlag/feature-flags.service"; +import {DrawingBoardModes} from "../drawingBoard/service-planning/drawing-board.modes"; +import {updateDrawingBoardStatus} from "../shared/storeUtil/utils/global/global.actions"; +import {Router, UrlTree} from "@angular/router"; +import {of} from "rxjs"; +import {MsoService} from "../shared/services/msoService/mso.service"; export let PENDING : string = "pending"; -export let INPROGRESS : string = "inprogress"; +export let INPROGRESS : string = "in_progress"; export let PAUSE : string = "pause"; -export let X_O : string = "X_o"; -export let SUCCESS_CIRCLE : string = "success+Circle"; -export let STOPED : string = "stoped"; +export let X_O : string = "x-circle-o"; +export let SUCCESS_CIRCLE : string = "success-circle-o"; +export let STOPED : string = "stop"; +export let COMPLETED_WITH_ERRORS : string = "success_with_warning"; @Injectable() export class InstantiationStatusComponentService { - generateServiceInfoDataMapping(arr: Array) : { [serviceInstanceId: string]: Array}{ - let serviceInfoData: { [serviceInstanceId: string]: Array; } = {}; + constructor( private _aaiService: AaiService, + private _msoService: MsoService, + private _router : Router, + private _store: NgRedux) { + } + + generateServiceInfoDataMapping(arr: ServiceInfoModel[]) : { [serviceInstanceId: string]: ServiceInfoModel[]}{ + let serviceInfoData: { [serviceInstanceId: string]: ServiceInfoModel[]; } = {}; for(let item of arr){ - if(isNullOrUndefined(serviceInfoData[item.templateId])){ + if(_.isNil(serviceInfoData[item.templateId])){ serviceInfoData[item.templateId] = [item]; }else { serviceInfoData[item.templateId].push(item); @@ -26,7 +41,7 @@ export class InstantiationStatusComponentService { return serviceInfoData; } - convertObjectToArray(arr: Array) : Observable>{ + convertObjectToArray(arr: ServiceInfoModel[]) : Observable{ const obj = this.generateServiceInfoDataMapping(arr); let index:number = 0; let result = []; @@ -40,25 +55,108 @@ export class InstantiationStatusComponentService { } console.log(result); - return Observable.of(result); + return of(result); + } + + isDrawingBoardViewEdit(serviceModel: ServiceModel): boolean { + if (!_.isNil(serviceModel.vidNotions) && !_.isNil(serviceModel.vidNotions.viewEditUI) + && serviceModel.vidNotions.viewEditUI !== 'legacy'){ + return true; + } + return false; + } + + open(item: ServiceInfoModel): void { + if (FeatureFlagsService.getFlagState(Features.FLAG_1902_VNF_GROUPING, this._store)) { + this._aaiService.getServiceModelById(item['serviceModelId']).subscribe((result)=>{ + const serviceModel = new ServiceModel(result); + + if (this.isDrawingBoardViewEdit(serviceModel)) { + this.navigateToNewViewEdit(item, DrawingBoardModes.EDIT); + return; + } + + this.navigateToNewViewOnlyOrOldEditView(item); + + }); + } + + /*this else is here only to save time in case we don't need to retrieve service model + it can be removed once it service model is always needed, and it doesn't save time*/ + else { + this.navigateToNewViewOnlyOrOldEditView(item); + } + } + + navigateToNewViewOnlyOrOldEditView(item: ServiceInfoModel) { + if (FeatureFlagsService.getFlagState(Features.FLAG_1902_NEW_VIEW_EDIT, this._store)) { + this.navigateToNewViewEdit(item, DrawingBoardModes.VIEW); + } + else { + this.navigateToOldViewEdit(item); + } + } + + navigateToOldViewEdit(item: ServiceInfoModel) { + let query = + `subscriberId=${item.subscriberId}&` + + `subscriberName=${item.subscriberName}&` + + `serviceType=${item.serviceType}&` + + `serviceInstanceId=${item.serviceInstanceId}`; + + this._store.dispatch(updateDrawingBoardStatus(DrawingBoardModes.OLD_VIEW_EDIT)); + window.parent.location.assign('../../serviceModels.htm#/instantiate?' + query); + } + + navigateToNewViewEdit(item: ServiceInfoModel, mode: DrawingBoardModes): void{ + this._store.dispatch(updateDrawingBoardStatus(mode)); + const viewEditUrlTree:UrlTree = this.getNewViewEditUrlTree(item, mode); + this._router.navigateByUrl(viewEditUrlTree); + window.parent.location.assign(this.getViewEditUrl(viewEditUrlTree)); + } + + getNewViewEditUrlTree(item: ServiceInfoModel, mode: DrawingBoardModes): UrlTree { + return this._router.createUrlTree( + ['/servicePlanning/' + mode], + { + queryParams: + { + serviceModelId: item.serviceModelId, + serviceInstanceId: item.serviceInstanceId, + serviceType : item.serviceType, + subscriberId : item.subscriberId, + jobId: item.jobId + } + }); + } + + getViewEditUrl(viewEditUrlTree:UrlTree): string { + return '../../serviceModels.htm#' + viewEditUrlTree.toString(); + } getStatus(status : string) : ServiceStatus { switch(status.toUpperCase()) { case 'PENDING' : - return new ServiceStatus(PENDING, '#009FDB', 'Pending: The service will automatically be sent for instantiation as soon as possible.'); + return new ServiceStatus(PENDING, 'primary', 'Pending: The action required will be sent as soon as possible.'); case 'IN_PROGRESS' : - return new ServiceStatus(INPROGRESS, '#009FDB', 'In-progress: the service is in process of instantiation.'); + return new ServiceStatus(INPROGRESS, 'primary', 'In-progress: the service is in process of the action required.'); case 'PAUSED' : - return new ServiceStatus(PAUSE, '#009FDB', 'Paused: Service has paused and waiting for your action.\n Select actions from the menu to the right.'); + return new ServiceStatus(PAUSE, 'primary', 'Paused: Service has paused and waiting for your action.\n Select actions from the menu to the right.'); case 'FAILED' : - return new ServiceStatus(X_O, '#D02B2B', 'Failed: Service instantiation has failed, load the service to see the error returned.'); + return new ServiceStatus(X_O, 'error', 'Failed: All planned actions have failed.'); case 'COMPLETED' : - return new ServiceStatus(SUCCESS_CIRCLE, '#53AD15', 'Completed successfully: Service is successfully instantiated.'); + return new ServiceStatus(SUCCESS_CIRCLE, 'success', 'Completed successfully: Service is successfully instantiated, updated or deleted.'); case 'STOPPED' : - return new ServiceStatus(STOPED, '#D02B2B', 'Stopped: Due to previous failure, will not be instantiated.'); + return new ServiceStatus(STOPED, 'error', 'Stopped: Due to previous failure, will not be instantiated.'); + case 'COMPLETED_WITH_ERRORS' : + return new ServiceStatus(COMPLETED_WITH_ERRORS, 'success', 'Completed with errors: some of the planned actions where successfully committed while other have not.\n Open the service to check it out.'); } } + + retry(item: ServiceInfoModel): void { + this.navigateToNewViewEdit(item, DrawingBoardModes.RETRY_EDIT); + } } diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.spec.ts b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.spec.ts index 00b6a9945..53dfcc1f2 100644 --- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.spec.ts +++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.spec.ts @@ -1,88 +1,227 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; import {InstantiationStatusComponent} from './instantiationStatus.component'; import {ServiceInfoService} from '../shared/server/serviceInfo/serviceInfo.service'; import {InstantiationStatusComponentService} from './instantiationStatus.component.service'; -import { ContextMenuModule, ContextMenuService } from 'ngx-contextmenu'; +import {ContextMenuModule, ContextMenuService} from 'ngx-contextmenu'; import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core'; -import { HttpClientTestingModule } from '@angular/common/http/testing'; -import { ScrollToModule } from '@nicky-lenaers/ngx-scroll-to'; -import { ConfigurationService } from '../services/configuration.service'; -import { LogService } from '../shared/utils/log/log.service'; +import {HttpClientTestingModule} from '@angular/common/http/testing'; +import {ScrollToModule} from '@nicky-lenaers/ngx-scroll-to'; +import {ConfigurationService} from '../shared/services/configuration.service'; +import {LogService} from '../shared/utils/log/log.service'; +import {NgRedux} from '@angular-redux/store'; +import {RouterTestingModule} from '@angular/router/testing'; +import {CapitalizeAndFormatPipe} from "../shared/pipes/capitalize/capitalize-and-format.pipe"; +import {AaiService} from "../shared/services/aaiService/aai.service"; +import {MsoService} from "../shared/services/msoService/mso.service"; +import {FeatureFlagsService} from "../shared/services/featureFlag/feature-flags.service"; +import {JobStatus, ServiceAction} from "../shared/models/serviceInstanceActions"; +import each from 'jest-each'; +import {ServiceInfoModel} from "../shared/server/serviceInfo/serviceInfo.model"; +import { TooltipModule } from 'ngx-tooltip'; + +class MockAppStore { + + getState() { + return { + global: { + flags: { + 'FLAG_1902_NEW_VIEW_EDIT': true + } + } + } + } + + dispatch() { + + } +} describe('Instantiation Status Component', () => { let component: InstantiationStatusComponent; let fixture: ComponentFixture; - let enableDeleteItems = [ - { jobStatus:"PENDING" }, - { jobStatus:"STOPPED" }]; - let disableDeleteItems = [ - { jobStatus:"COMPLETED" }, - { jobStatus:"FAILED" }, - {jobStatus:"IN_PROGRESS"}, - {jobStatus:"UnknownOne"}]; - +let item = new ServiceInfoModel(); + beforeAll(done => (async () => { - beforeEach(async(() => { TestBed.configureTestingModule({ - imports: [HttpClientTestingModule, ContextMenuModule, ScrollToModule.forRoot()], - providers: [ServiceInfoService, InstantiationStatusComponentService, ContextMenuService, ConfigurationService, LogService], - declarations: [InstantiationStatusComponent], + imports: [ + HttpClientTestingModule, + ContextMenuModule, + ScrollToModule.forRoot(), + RouterTestingModule, + TooltipModule + ], + providers: [ + ServiceInfoService, + InstantiationStatusComponentService, + AaiService, + MsoService, + ContextMenuService, + FeatureFlagsService, + ConfigurationService, + LogService, + {provide: NgRedux, useClass: MockAppStore} + ], + declarations: [InstantiationStatusComponent, CapitalizeAndFormatPipe], schemas: [ CUSTOM_ELEMENTS_SCHEMA ] - }).compileComponents(); - })); + }); + await TestBed.compileComponents(); - beforeEach(() => { fixture = TestBed.createComponent(InstantiationStatusComponent); component = fixture.componentInstance; fixture.detectChanges(); - }); + })().then(done).catch(done.fail)); + - it('component should initialize basic parameters', (done: DoneFn) => { + test('component should initialize basic parameters', () => { component.TIMER_TIME_IN_SECONDS = 2; expect(component.TIMER_TIME_IN_SECONDS).toEqual(2); expect(component.dataIsReady).toBeFalsy(); expect(component.lastUpdatedDate).toBeNull(); - done(); }); - it('component constructor should call activateInterval and ngOnInit', (done: DoneFn) => { + test('component constructor should call activateInterval and ngOnInit', () => { component.refreshData(); expect(component.dataIsReady).toBeFalsy(); - done(); }); - it('stopped and pending status isDeleteEnabled button should be enabled, not allowed delete statuses isDeleteEnabled button should be disabled', (done: DoneFn) => { - enableDeleteItems.forEach((item) => { - let isDeleteEnabled: boolean = component.isDeleteEnabled(item); - expect(isDeleteEnabled).toBeTruthy(); - }); + const enableDeleteItemsDataProvider = [ + ['INSTANTIATE action PENDING job status',JobStatus.PENDING , ServiceAction.INSTANTIATE], + ['DELETE action PENDING job status',JobStatus.PENDING , ServiceAction.DELETE], + ['UPDATE action PENDING job status',JobStatus.PENDING , ServiceAction.UPDATE], + ['INSTANTIATE action STOPPED job status',JobStatus.STOPPED , ServiceAction.INSTANTIATE]]; + each(enableDeleteItemsDataProvider).test('delete item should enable for %s', (desc, jobStatus, action ) => { + item.action=action; + item.jobStatus=jobStatus; + let isDeleteEnabled: boolean = component.isDeleteEnabled(item); + expect(isDeleteEnabled).toBeTruthy(); + }); - disableDeleteItems.forEach((item) => { - let isDeleteEnabled: boolean = component.isDeleteEnabled(item); - expect(isDeleteEnabled).toBeFalsy(); - }); - done(); + const disableDeleteItemsDataProvider = [ + [ 'INSTANTIATE action COMPLETED job status', JobStatus.COMPLETED , ServiceAction.INSTANTIATE], + [ 'INSTANTIATE action FAILED job status', JobStatus.FAILED , ServiceAction.INSTANTIATE], + [ 'INSTANTIATE action IN_PROGRESS job status', JobStatus.IN_PROGRESS, ServiceAction.INSTANTIATE], + [ 'INSTANTIATE action COMPLETED_WITH_ERRORS job status', JobStatus.COMPLETED_WITH_ERRORS, ServiceAction.INSTANTIATE], + [ 'DELETE action IN_PROGRESS job status', JobStatus.IN_PROGRESS, ServiceAction.DELETE], + [ 'DELETE action COMPLETED_WITH_ERRORS job status',JobStatus.COMPLETED_WITH_ERRORS, ServiceAction.DELETE], + [ 'UPDATE action IN_PROGRESS job status', JobStatus.IN_PROGRESS, ServiceAction.UPDATE], + [ 'UPDATE action COMPLETED_WITH_ERRORS job status', JobStatus.COMPLETED_WITH_ERRORS, ServiceAction.UPDATE], + [ 'INSTANTIATE action UNKNOWN job status', "UNKNOWN", ServiceAction.INSTANTIATE]]; + each(disableDeleteItemsDataProvider).test('delete item should disable for %s', (desc,jobStatus, action ) => { + item.action=action; + item.jobStatus=jobStatus; + let isDeleteEnabled: boolean = component.isDeleteEnabled(item); + expect(isDeleteEnabled).toBeFalsy(); }); - it('[COMPLETED, FAILED, STOPPED] status isHideEnable button should be enabled, [IN_PROGRESS, PAUSE, PENDING] status isHideEnable button should be disabled', (done: DoneFn) => { - const enableHideItems = [ - { jobStatus:"COMPLETED" }, - { jobStatus:"FAILED" }, - { jobStatus:"STOPPED" }]; - enableHideItems.forEach((item) => { - let isDeleteEnabled: boolean = component.isHideEnabled(item); - expect(isDeleteEnabled).toBeTruthy(); - }); + const enableHideItemsDataProvider = [ + ['instantiate action job status COMPLETED',JobStatus.COMPLETED, ServiceAction.INSTANTIATE ], + ['instantiate action job status FAILED',JobStatus.FAILED, ServiceAction.INSTANTIATE ], + ['instantiate action job status STOPPED', JobStatus.STOPPED, ServiceAction.INSTANTIATE ], + ['instantiate action job status COMPLETED_WITH_ERRORS', JobStatus.COMPLETED_WITH_ERRORS, ServiceAction.INSTANTIATE ], + ['delete action job status COMPLETED', JobStatus.COMPLETED, ServiceAction.DELETE ], + ['delete action job status FAILED', JobStatus.FAILED, ServiceAction.DELETE ], + ['delete action job status STOPPED',JobStatus.STOPPED, ServiceAction.DELETE ], + ['delete action job status COMPLETED_WITH_ERRORS', JobStatus.COMPLETED_WITH_ERRORS, ServiceAction.DELETE ], + ['update action job status COMPLETED', JobStatus.COMPLETED, ServiceAction.UPDATE ], + ['update action job status FAILED',JobStatus.FAILED, ServiceAction.UPDATE ], + ['update action job status STOPPED', JobStatus.STOPPED, ServiceAction.UPDATE ], + ['update action job status COMPLETED_WITH_ERRORS', JobStatus.COMPLETED_WITH_ERRORS, ServiceAction.UPDATE ]]; + each(enableHideItemsDataProvider).test('hide item should be enabled for %s', (desc, jobStatus, action ) => { + item.action=action; + item.jobStatus=jobStatus; + let isHideEnabled: boolean = component.isHideEnabled(item); + expect(isHideEnabled).toBeTruthy(); + }); - const disableHideItems = [ - { jobStatus:"IN_PROGRESS" }, - { jobStatus:"PAUSE" }, - { jobStatus:"PENDING" }, - { jobStatus:"NOT_MATTER"}]; - disableHideItems.forEach((item) => { - let isDeleteEnabled: boolean = component.isHideEnabled(item); - expect(isDeleteEnabled).toBeFalsy(); - }); - done(); + const disableHideItemsDataProvider = [ + ['action instantiate job status IN_PROGRESS',JobStatus.IN_PROGRESS , ServiceAction.INSTANTIATE], + ['action instantiate job status PAUSE',JobStatus.PAUSE, ServiceAction.INSTANTIATE], + ['action instantiate job status PENDING', JobStatus.PENDING, ServiceAction.INSTANTIATE ], + ['action instantiate job status UNKNOWN', "UNKNOWN", ServiceAction.INSTANTIATE], + ['update instantiate job status IN_PROGRESS', JobStatus.IN_PROGRESS , ServiceAction.UPDATE], + ['update instantiate job status PAUSE', JobStatus.PAUSE, ServiceAction.UPDATE], + ['update instantiate job status PENDING', JobStatus.PENDING, ServiceAction.UPDATE ], + ['update instantiate job status UNKNOWN',"UNKNOWN", ServiceAction.UPDATE], + ['delete instantiate job status IN_PROGRESS',JobStatus.IN_PROGRESS , ServiceAction.DELETE], + ['delete instantiate job status PAUSE', JobStatus.PAUSE, ServiceAction.DELETE], + ['delete instantiate job status PENDING', JobStatus.PENDING, ServiceAction.DELETE ], + ['delete instantiate job status UNKNOWN', "UNKNOWN", ServiceAction.DELETE]]; + each(disableHideItemsDataProvider).test('hide item should disable for %s', (desc, jobStatus, action ) => { + item.action=action; + item.jobStatus=jobStatus; + let isHideEnabled: boolean = component.isHideEnabled(item); + expect(isHideEnabled).toBeFalsy(); + }); + + const enableAuditItemsDataProvider = [ + ['instantiate action UNKNOWN job status', "UNKNOWN", ServiceAction.INSTANTIATE ], + ['delete action JobStatus IN_PROGRESS', JobStatus.IN_PROGRESS, ServiceAction.DELETE ], + ['delete action JobStatus PAUSE', JobStatus.PAUSE, ServiceAction.DELETE ], + ['delete action JobStatus FAILED', JobStatus.FAILED, ServiceAction.DELETE ], + ['delete action JobStatus COMPLETED', JobStatus.COMPLETED, ServiceAction.DELETE ], + ['delete action JobStatus COMPLETED_WITH_ERRORS', JobStatus.COMPLETED_WITH_ERRORS, ServiceAction.DELETE ], + ['update action JobStatus IN_PROGRESS', JobStatus.IN_PROGRESS, ServiceAction.UPDATE ], + ['update action JobStatus PAUSE', JobStatus.PAUSE, ServiceAction.UPDATE ], + ['update action JobStatus COMPLETED', JobStatus.COMPLETED, ServiceAction.UPDATE ], + ['update action JobStatus FAILED', JobStatus.FAILED, ServiceAction.UPDATE ], + ['update action JobStatus COMPLETED_WITH_ERRORS', JobStatus.COMPLETED_WITH_ERRORS, ServiceAction.UPDATE ]]; + + each(enableAuditItemsDataProvider).test('audit item should be enabled for %s', (desc, jobStatus, action ) => { + item.action=action; + item.jobStatus=jobStatus; + const isAuditEnabled: boolean = component.isAuditInfoEnabled(item); + expect(isAuditEnabled).toBeTruthy(); + }); + + const disableAuditItemsDataProvider = [ + ['Job status STOPPED action update', JobStatus.STOPPED, ServiceAction.UPDATE ], + ['Job status PENDING action update', JobStatus.PENDING, ServiceAction.UPDATE ], + ['Job status UNKNOWN action update', "UNKNOWN", ServiceAction.UPDATE], + ['Job status STOPPED action delete',JobStatus.STOPPED, ServiceAction.DELETE], + ['Job status PENDING action delete', JobStatus.PENDING, ServiceAction.DELETE ], + ['Job status UNKNOWN action delete', "UNKNOWN", ServiceAction.DELETE]]; + each(disableAuditItemsDataProvider).test('audit item should be disabled for %s', (desc, jobStatus, action ) => { + item.action=action; + item.jobStatus=jobStatus; + let isAuditEnabled: boolean = component.isAuditInfoEnabled(item); + expect(isAuditEnabled).toBeFalsy(); + }); + + const enableOpenItemsDataProvider = [ + ['action instantiate job status PAUSE', JobStatus.PAUSE, ServiceAction.INSTANTIATE ], + ['action instantiate job status COMPLETED', JobStatus.COMPLETED, ServiceAction.INSTANTIATE ], + ['action instantiate job status COMPLETED_WITH_ERRORS', JobStatus.COMPLETED_WITH_ERRORS, ServiceAction.INSTANTIATE ], + ['action delete job status PENDING', JobStatus.PENDING, ServiceAction.DELETE ], + ['action delete job status FAILED', JobStatus.FAILED, ServiceAction.DELETE ], + ['action delete job status COMPLETED_WITH_ERRORS', JobStatus.COMPLETED_WITH_ERRORS, ServiceAction.DELETE ], + ['action update job status PENDING', JobStatus.PENDING, ServiceAction.UPDATE ], + ['action update job status PAUSE', JobStatus.PAUSE, ServiceAction.UPDATE ], + ['action update job status COMPLETED', JobStatus.COMPLETED, ServiceAction.UPDATE ], + ['action update job status FAILED', JobStatus.FAILED, ServiceAction.UPDATE ], + ['action update job status COMPLETED_WITH_ERRORS', JobStatus.COMPLETED_WITH_ERRORS, ServiceAction.UPDATE ]]; + each(enableOpenItemsDataProvider).test('open item should be enabled for %s', (desc, jobStatus, action ) => { + item.action=action; + item.jobStatus=jobStatus; + let isOpenEnabled: boolean = component.isOpenEnabled(item); + expect(isOpenEnabled).toBeTruthy(); }); + + const disableOpenItemsDataProvider = [ + ['action instantiate job status STOPPED', JobStatus.STOPPED, ServiceAction.INSTANTIATE], + ['action instantiate job status FAILED', JobStatus.FAILED, ServiceAction.INSTANTIATE], + ['action instantiate job status UNKNOWN', "UNKNOWN", ServiceAction.INSTANTIATE], + ['action update job status STOPPED', JobStatus.STOPPED, ServiceAction.UPDATE ], + ['action update job status IN_PROGRESS', JobStatus.IN_PROGRESS, ServiceAction.UPDATE ], + ['action update job status UNKNOWN', "UNKNOWN", ServiceAction.UPDATE], + ['action delete job status COMPLETED', JobStatus.COMPLETED, ServiceAction.DELETE], + ['action delete job status PAUSE', JobStatus.PAUSE, ServiceAction.DELETE], + ['action delete job status IN_PROGRESS', JobStatus.IN_PROGRESS, ServiceAction.DELETE ], + ['action delete job status UNKNOWN',"UNKNOWN", ServiceAction.DELETE]]; + each(disableOpenItemsDataProvider).test('open item should be disabled for %s', (desc, jobStatus, action ) => { + item.action=action; + item.jobStatus=jobStatus; + let isOpenEnabled: boolean = component.isOpenEnabled(item); + expect(isOpenEnabled).toBeFalsy(); + }); + }); diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts index ed45ce43c..f3f651960 100644 --- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts +++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts @@ -1,40 +1,97 @@ -import {AfterViewChecked, Component, ViewChild} from '@angular/core'; +import {Component, ViewChild} from '@angular/core'; import {ServiceInfoService} from '../shared/server/serviceInfo/serviceInfo.service'; import {ServiceInfoModel} from '../shared/server/serviceInfo/serviceInfo.model'; import {InstantiationStatusComponentService} from './instantiationStatus.component.service'; import {ContextMenuComponent, ContextMenuService} from 'ngx-contextmenu'; -import {AuditInfoModalComponent} from "./auditInfoModal/auditInfoModal.component"; +import {AuditInfoModalComponent} from "../shared/components/auditInfoModal/auditInfoModal.component"; import * as _ from 'lodash'; import {ScrollToConfigOptions, ScrollToService} from '@nicky-lenaers/ngx-scroll-to'; -import {ConfigurationService} from "../services/configuration.service"; +import {ConfigurationService} from "../shared/services/configuration.service"; import {LogService} from '../shared/utils/log/log.service'; - +import {AppState} from "../shared/store/reducers"; +import {NgRedux} from '@angular-redux/store'; +import {JobStatus, ServiceAction} from "../shared/models/serviceInstanceActions"; +import {DrawingBoardModes} from "../drawingBoard/service-planning/drawing-board.modes"; + +export interface MenuAction{ + name: string; + dataTestId: string; + className: string; + tooltip?: string; + click(item: ServiceInfoModel): void; + enabled (item?: ServiceInfoModel): boolean; + visible (item?: ServiceInfoModel): boolean; +} @Component({ selector : 'instantiation-status', templateUrl : './instantiationStatus.component.html', styleUrls : ['./instantiationStatus.component.scss'] }) -export class InstantiationStatusComponent implements AfterViewChecked{ - +export class InstantiationStatusComponent { TIMER_TIME_IN_SECONDS : number = 0; timer = null; dataIsReady : boolean = false; scroll : boolean = false; lastUpdatedDate: Date = null; - currentJobId: string = null; instantiationStatusComponentService: InstantiationStatusComponentService; configurationService : ConfigurationService; - serviceInfoData: Array = null; + serviceInfoData: ServiceInfoModel[] = null; @ViewChild(ContextMenuComponent) public contextMenu: ContextMenuComponent; + public contextMenuActions: Array = [ + { + name: "Redeploy", + dataTestId: "context-menu-retry", + className: "fa-repeat", + click: (item: ServiceInfoModel) => this.retryItem(item), + enabled: () => true, + visible: (item: ServiceInfoModel) => item.isRetryEnabled, + }, + { + name: "Open", + dataTestId: "context-menu-open", + className: "fa-external-link", + click: (item: ServiceInfoModel) => this.instantiationStatusComponentService.open(item), + enabled: (item: ServiceInfoModel) => this.isOpenEnabled(item), + visible: () => true, + }, + { + name: "Audit info", + dataTestId: "context-menu-audit-info", + className: "fa-info-circle", + click: (item: ServiceInfoModel) => this.auditInfo(item), + enabled: (item: ServiceInfoModel) => this.isAuditInfoEnabled(item), + visible: () => true, + }, + { + name: "Delete", + dataTestId: "context-menu-remove", + className: "fa-trash-o", + click: (item: ServiceInfoModel) => this.deleteItem(item), + enabled: (item: ServiceInfoModel) => this.isDeleteEnabled(item), + visible: () => true, + }, + { + name: "Hide request", + dataTestId: "context-menu-hide", + className: "fa-eye-slash", + tooltip: "Hide this service from this table", + click: (item: ServiceInfoModel) => this.hideItem(item), + enabled: (item: ServiceInfoModel) => this.isHideEnabled(item), + visible: () => true, + } + ]; + + flags: any; constructor(private _serviceInfoService: ServiceInfoService, private _instantiationStatusComponentService : InstantiationStatusComponentService, private _contextMenuService: ContextMenuService, private _configurationService : ConfigurationService, private _scrollToService: ScrollToService, - private _logService : LogService) { + private _logService : LogService, + private _store: NgRedux) { this.instantiationStatusComponentService = _instantiationStatusComponentService; this.configurationService = this._configurationService; this.configurationService.getConfiguration("refreshTimeInstantiationDashboard").subscribe(response => { @@ -58,61 +115,73 @@ export class InstantiationStatusComponent implements AfterViewChecked{ refreshData(): void { this.dataIsReady = false; - this._serviceInfoService.getServicesJobInfo(true) - .subscribe((res: Array) => { + this._serviceInfoService.getServicesJobInfo(true, this.lastUpdatedDate === null) + .subscribe((res: ServiceInfoModel[]) => { this._instantiationStatusComponentService.convertObjectToArray(res).subscribe((res) => { this._logService.info('refresh instantiation status table', res); this.dataIsReady = true; this.lastUpdatedDate = new Date(); if (!_.isEqual(this.serviceInfoData, res)) { this.serviceInfoData = res; - this.scroll = true; + this.scrollToElement(this.findFirstVisibleJob()); } }); }) } - ngAfterViewChecked(){ - if (this.scroll) { - this.scrollToElement(); - this.scroll = false; - } + trackByFn(index: number, item: ServiceInfoModel){ + return _.isNil(item) ? null : item.jobId; } - - - isDeleteEnabled(item):boolean { - return _.includes(['PENDING', 'STOPPED'], item.jobStatus); - } - - deleteItem(item): void { + deleteItem(item: ServiceInfoModel): void { this._serviceInfoService.deleteJob(item.jobId).subscribe(() => { this.refreshData(); }); } - hideItem(item): void { + hideItem(item: ServiceInfoModel): void { this._serviceInfoService.hideJob(item.jobId).subscribe(() => { this.refreshData(); }); } + + retryItem(item: ServiceInfoModel) : void { + if (item.isRetryEnabled) { + this._instantiationStatusComponentService.retry(item); + } + } auditInfo(jobData : ServiceInfoModel): void { AuditInfoModalComponent.openModal.next(jobData); + } + isOpenEnabled(item: ServiceInfoModel):boolean { + switch(item.action) { + case ServiceAction.DELETE: + return _.includes([ JobStatus.PENDING, JobStatus.COMPLETED_WITH_ERRORS, JobStatus.FAILED], item.jobStatus); + case ServiceAction.UPDATE: + return _.includes([JobStatus.PENDING, JobStatus.PAUSE, JobStatus.COMPLETED_WITH_ERRORS, JobStatus.COMPLETED, JobStatus.FAILED], item.jobStatus); + default: + return _.includes([JobStatus.COMPLETED, JobStatus.PAUSE, JobStatus.COMPLETED_WITH_ERRORS], item.jobStatus); + } } - isOpenVisible(item):boolean { - return _.includes(['COMPLETED', 'PAUSE'], item.jobStatus); + isAuditInfoEnabled(item: ServiceInfoModel): boolean { + if(item.action === ServiceAction.DELETE || item.action=== ServiceAction.UPDATE) { + return _.includes([JobStatus.FAILED, JobStatus.IN_PROGRESS, JobStatus.COMPLETED_WITH_ERRORS, JobStatus.PAUSE, JobStatus.COMPLETED], item.jobStatus); + } + return true;// ServiceAction.INSTANTIATE } - open(item): void { - let query = - `subscriberId=${item['subscriberName']}&` + - `serviceType=${item['serviceType']}&` + - `serviceInstanceId=${item['serviceInstanceId']}`; + isDeleteEnabled(item: ServiceInfoModel):boolean { + if( item.action === ServiceAction.DELETE || item.action === ServiceAction.UPDATE){ + return _.includes([JobStatus.PENDING], item.jobStatus); + } + return _.includes([JobStatus.PENDING, JobStatus.STOPPED], item.jobStatus); + } - window.parent.location.assign('../../serviceModels.htm#/instantiate?' + query); + isHideEnabled(item: ServiceInfoModel):boolean { + return _.includes([JobStatus.COMPLETED, JobStatus.FAILED, JobStatus.STOPPED, JobStatus.COMPLETED_WITH_ERRORS], item.jobStatus); } public onContextMenu($event: MouseEvent, item: any): void { @@ -129,17 +198,36 @@ export class InstantiationStatusComponent implements AfterViewChecked{ return './' + imageName + '.svg'; } - isHideEnabled(item: any):boolean { - return _.includes(['COMPLETED', 'FAILED', 'STOPPED'], item.jobStatus); + private getHeaderHeaderClientRect(): ClientRect { + const element = document.querySelector("#instantiation-status thead") as HTMLElement; + return element.getBoundingClientRect(); } - scrollToElement() { - if(this.currentJobId){ + + findFirstVisibleJob(): HTMLElement { + const elements : any = document.querySelectorAll('#instantiation-status tr'); + const headerRect = this.getHeaderHeaderClientRect(); + if (headerRect) { + const topEdge = headerRect.bottom; + for (let i = 0; i < elements.length; i++) { + if (elements[i].getBoundingClientRect().top >= topEdge) + return elements[i]; + } + } + return null; + } + + scrollToElement(currentJob: HTMLElement) { + if (currentJob) { const config: ScrollToConfigOptions = { - target: this.currentJobId, - duration: 50, - offset: -35 //header height + target: currentJob, + duration: 0, + offset: -1 * (this.getHeaderHeaderClientRect().height + 2), }; - this._scrollToService.scrollTo(config); + + // wait after render + setTimeout(() => { + this._scrollToService.scrollTo(config); + }, 0) } } } -- cgit 1.2.3-korg