From 063a3f1741d0cb20d5ee80590339fec54ab1acdd Mon Sep 17 00:00:00 2001 From: Barath Kumar R Date: Tue, 29 Dec 2020 16:35:09 +0530 Subject: [PATCH] Bug 1383 Error when consulting NS instance's topology * SOL006 Descriptor topology changes Change-Id: I79afb00dfb54ce2c9dc02c0c4b7bbe435b07a915 Signed-off-by: Barath Kumar R --- src/app/dashboard/DashboardComponent.ts | 47 +- .../ns-instances/NSInstancesComponent.ts | 14 +- .../ns-primitive/NSPrimitiveComponent.html | 6 +- .../ns-primitive/NSPrimitiveComponent.ts | 94 ++- .../ns-topology/NSTopologyComponent.html | 4 - .../ns-topology/NSTopologyComponent.ts | 178 ++-- .../vnf-instances/VNFInstancesComponent.ts | 2 +- src/app/layouts/header/HeaderComponent.html | 14 +- src/app/layouts/header/HeaderComponent.ts | 23 +- .../ns-packages/NSPackagesComponent.ts | 10 +- .../ns-composer/NSComposerComponent.html | 93 +-- .../ns-composer/NSComposerComponent.ts | 677 ++++++++------- .../vnf-composer/VNFComposerComponent.html | 191 ++--- .../vnf-composer/VNFComposerComponent.ts | 787 ++++++++++-------- .../vnf-packages/VNFPackagesComponent.ts | 30 +- .../clone-package/ClonePackageComponent.ts | 34 +- .../compose-packages/ComposePackages.ts | 63 +- .../ConfirmationTopologyComponent.html | 6 +- src/app/utilities/delete/DeleteComponent.ts | 4 +- .../NsPackagesActionComponent.ts | 2 +- .../VNFPackagesActionComponent.ts | 2 +- src/assets/i18n/de.json | 12 +- src/assets/i18n/en.json | 12 +- src/assets/i18n/es.json | 12 +- src/assets/i18n/pt.json | 12 +- src/assets/scss/app.scss | 3 + src/models/CommonModel.ts | 12 +- src/models/NSDModel.ts | 84 +- src/models/NSInstanceModel.ts | 18 +- src/models/VNFDModel.ts | 246 +++--- src/services/AuthenticationService.ts | 2 + src/services/SharedService.ts | 8 +- 32 files changed, 1405 insertions(+), 1297 deletions(-) diff --git a/src/app/dashboard/DashboardComponent.ts b/src/app/dashboard/DashboardComponent.ts index 8df0e7c..56b79a4 100644 --- a/src/app/dashboard/DashboardComponent.ts +++ b/src/app/dashboard/DashboardComponent.ts @@ -34,7 +34,6 @@ import { SDNControllerModel } from 'SDNControllerModel'; import { SharedService } from 'SharedService'; import { ProjectRoleMappings, UserDetail } from 'UserModel'; import { VimAccountDetails } from 'VimAccountModel'; -import { VNFDDetails } from 'VNFDModel'; import { VNFInstanceDetails } from 'VNFInstanceModel'; /** @@ -189,13 +188,13 @@ export class DashboardComponent implements OnInit { /** Get all the projects @public */ public getUserAccessedProjects(): void { - this.projectService.getUserProjects().subscribe((projects: UserDetail) => { + this.projectService.getUserProjects().subscribe((projects: UserDetail): void => { const projectList: {}[] = projects.project_role_mappings; this.projectList = projectList.filter( - (thing: ProjectRoleMappings, i: number, arr: []) => arr - .findIndex((t: ProjectRoleMappings) => t.project_name === thing.project_name) === i + (thing: ProjectRoleMappings, i: number, arr: []): boolean => arr + .findIndex((t: ProjectRoleMappings): boolean => t.project_name === thing.project_name) === i ); - }, (error: Error) => { + }, (error: Error): void => { // TODO: Handle failure }); } @@ -203,14 +202,14 @@ export class DashboardComponent implements OnInit { /** Fetching all the Project in dashboard @public */ public getAllProjects(): void { this.isProjectsLoadingResults = true; - this.restService.getResource(environment.PROJECTS_URL).subscribe((projectsData: ProjectDetails[]) => { + this.restService.getResource(environment.PROJECTS_URL).subscribe((projectsData: ProjectDetails[]): void => { this.allProjectList = []; - projectsData.forEach((projectData: ProjectDetails) => { + projectsData.forEach((projectData: ProjectDetails): void => { const projectDataObj: ProjectData = this.generateProjectData(projectData); this.allProjectList.push(projectDataObj); }); this.isProjectsLoadingResults = false; - }, (error: ERRORDATA) => { + }, (error: ERRORDATA): void => { this.restService.handleError(error, 'get'); this.isProjectsLoadingResults = false; }); @@ -230,9 +229,9 @@ export class DashboardComponent implements OnInit { /** Function to check admin privilege @public */ public checkAdminPrivilege(): void { if (!this.isAdmin) { - this.projectService.getCurrentProjectDetails().subscribe((projectDetails: {}) => { + this.projectService.getCurrentProjectDetails().subscribe((projectDetails: {}): void => { this.currentProjectDetails = projectDetails; - }, (error: Error) => { + }, (error: Error): void => { // TODO: Handle failure }); } @@ -241,9 +240,9 @@ export class DashboardComponent implements OnInit { /** Get VNFD Package details @public */ public getVnfdPackageCount(): void { this.vnfdPackageCountSub = this.restService.getResource(environment.VNFPACKAGESCONTENT_URL) - .subscribe((vnfdPackageData: VNFDDetails[]) => { + .subscribe((vnfdPackageData: []): void => { this.vnfdPackageCount = vnfdPackageData.length; - }, (error: ERRORDATA) => { + }, (error: ERRORDATA): void => { this.restService.handleError(error, 'get'); }); } @@ -251,9 +250,9 @@ export class DashboardComponent implements OnInit { /** Get NSD Package details @public */ public getNsdPackageCount(): void { this.nsdPackageCountSub = this.restService.getResource(environment.NSDESCRIPTORSCONTENT_URL) - .subscribe((nsdPackageData: NSDDetails[]) => { + .subscribe((nsdPackageData: NSDDetails[]): void => { this.nsdPackageCount = nsdPackageData.length; - }, (error: ERRORDATA) => { + }, (error: ERRORDATA): void => { this.restService.handleError(error, 'get'); }); } @@ -262,12 +261,12 @@ export class DashboardComponent implements OnInit { public getNsInstanceCount(): void { this.isCanvasLoadingResults = true; this.nsInstanceCountSub = this.restService.getResource(environment.NSDINSTANCES_URL) - .subscribe((nsInstancesData: NSInstanceDetails[]) => { + .subscribe((nsInstancesData: NSInstanceDetails[]): void => { this.nsInstancesDataArr = nsInstancesData; this.nsInstanceCount = nsInstancesData.length; this.nsInstanceChart(); this.isCanvasLoadingResults = false; - }, (error: ERRORDATA) => { + }, (error: ERRORDATA): void => { this.restService.handleError(error, 'get'); this.isCanvasLoadingResults = false; }); @@ -275,7 +274,7 @@ export class DashboardComponent implements OnInit { /** Get NS Instance chart details @public */ public nsInstanceChart(): void { - this.nsInstancesDataArr.forEach((nsdInstanceData: NSDDetails) => { + this.nsInstancesDataArr.forEach((nsdInstanceData: NSDDetails): void => { const operationalStatus: string = nsdInstanceData['operational-status']; const configStatus: string = nsdInstanceData['config-status']; if (operationalStatus === 'failed' || configStatus === 'failed') { @@ -288,7 +287,7 @@ export class DashboardComponent implements OnInit { }); const now: Date = new Date(); const currentTime: number = Number((now.getTime().toString().slice(0, this.sliceLimit))); - this.createdTimes.forEach((createdTime: string) => { + this.createdTimes.forEach((createdTime: string): void => { this.noOfHours.push((Math.round((currentTime - Number(createdTime)) / this.hourConverter))); }); this.drawNsChart(); @@ -342,9 +341,9 @@ export class DashboardComponent implements OnInit { /** Get VNFD instance details @public */ public getVnfInstanceCount(): void { this.vnfInstanceCountSub = this.restService.getResource(environment.NSDINSTANCES_URL) - .subscribe((vnfInstanceData: VNFInstanceDetails[]) => { + .subscribe((vnfInstanceData: VNFInstanceDetails[]): void => { this.vnfInstanceCount = vnfInstanceData.length; - }, (error: ERRORDATA) => { + }, (error: ERRORDATA): void => { this.restService.handleError(error, 'get'); }); } @@ -352,9 +351,9 @@ export class DashboardComponent implements OnInit { /** Get VIM account details @public */ public getVimAccountCount(): void { this.vimAccountCountSub = this.restService.getResource(environment.VIMACCOUNTS_URL) - .subscribe((vimAccountData: VimAccountDetails[]) => { + .subscribe((vimAccountData: VimAccountDetails[]): void => { this.vimAccountCount = vimAccountData.length; - }, (error: ERRORDATA) => { + }, (error: ERRORDATA): void => { this.restService.handleError(error, 'get'); }); } @@ -362,9 +361,9 @@ export class DashboardComponent implements OnInit { /** Get SDN Controller Count @public */ public getSDNControllerCount(): void { this.sdnControllerCountSub = this.restService.getResource(environment.SDNCONTROLLER_URL) - .subscribe((sdnControllerData: SDNControllerModel[]) => { + .subscribe((sdnControllerData: SDNControllerModel[]): void => { this.sdnControllerCount = sdnControllerData.length; - }, (error: ERRORDATA) => { + }, (error: ERRORDATA): void => { this.restService.handleError(error, 'get'); }); } diff --git a/src/app/instances/ns-instances/NSInstancesComponent.ts b/src/app/instances/ns-instances/NSInstancesComponent.ts index 07184da..41bb384 100644 --- a/src/app/instances/ns-instances/NSInstancesComponent.ts +++ b/src/app/instances/ns-instances/NSInstancesComponent.ts @@ -124,7 +124,7 @@ export class NSInstancesComponent implements OnInit { this.generateTableColumn(); this.generateTableSettings(); this.generateData(); - this.generateDataSub = this.sharedService.dataEvent.subscribe(() => { this.generateData(); }); + this.generateDataSub = this.sharedService.dataEvent.subscribe((): void => { this.generateData(); }); } /** Generate smart table row title and filters @public */ @@ -219,9 +219,9 @@ export class NSInstancesComponent implements OnInit { /** generateData initiate the ns-instance list @public */ public generateData(): void { this.isLoadingResults = true; - this.restService.getResource(environment.NSDINSTANCES_URL).subscribe((nsdInstancesData: NSInstanceDetails[]) => { + this.restService.getResource(environment.NSDINSTANCES_URL).subscribe((nsdInstancesData: NSInstanceDetails[]): void => { this.nsInstanceData = []; - nsdInstancesData.forEach((nsdInstanceData: NSInstanceDetails) => { + nsdInstancesData.forEach((nsdInstanceData: NSInstanceDetails): void => { const nsDataObj: NSDInstanceData = { name: nsdInstanceData.name, identifier: nsdInstanceData.id, @@ -229,7 +229,7 @@ export class NSInstancesComponent implements OnInit { OperationalStatus: nsdInstanceData['operational-status'], ConfigStatus: nsdInstanceData['config-status'], DetailedStatus: nsdInstanceData['detailed-status'], - memberIndex: nsdInstanceData.nsd['constituent-vnfd'], + memberIndex: nsdInstanceData.nsd.df, nsConfig: nsdInstanceData.nsd['ns-configuration'] }; this.nsInstanceData.push(nsDataObj); @@ -239,10 +239,10 @@ export class NSInstancesComponent implements OnInit { } else { this.checkDataClass = 'dataTables_empty'; } - this.dataSource.load(this.nsInstanceData).then((data: {}) => { + this.dataSource.load(this.nsInstanceData).then((data: {}): void => { this.isLoadingResults = false; }).catch(); - }, (error: ERRORDATA) => { + }, (error: ERRORDATA): void => { this.restService.handleError(error, 'get'); this.isLoadingResults = false; }); @@ -262,7 +262,7 @@ export class NSInstancesComponent implements OnInit { /** Instantiate NS using modalservice @public */ public instantiateNS(): void { const modalRef: NgbModalRef = this.modalService.open(InstantiateNsComponent, { backdrop: 'static' }); - modalRef.result.then((result: MODALCLOSERESPONSEDATA) => { + modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => { if (result) { this.generateData(); } diff --git a/src/app/instances/ns-primitive/NSPrimitiveComponent.html b/src/app/instances/ns-primitive/NSPrimitiveComponent.html index 82e3992..2f3c155 100644 --- a/src/app/instances/ns-primitive/NSPrimitiveComponent.html +++ b/src/app/instances/ns-primitive/NSPrimitiveComponent.html @@ -31,10 +31,10 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i
- +
- +
diff --git a/src/app/instances/ns-primitive/NSPrimitiveComponent.ts b/src/app/instances/ns-primitive/NSPrimitiveComponent.ts index d5cf565..50f7707 100644 --- a/src/app/instances/ns-primitive/NSPrimitiveComponent.ts +++ b/src/app/instances/ns-primitive/NSPrimitiveComponent.ts @@ -23,14 +23,15 @@ import { AbstractControl, FormArray, FormBuilder, FormGroup, Validators } from ' import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { TranslateService } from '@ngx-translate/core'; import { NotifierService } from 'angular-notifier'; -import { APIURLHEADER, ERRORDATA, URLPARAMS } from 'CommonModel'; +import { APIURLHEADER, ERRORDATA, PRIMITIVEDATA, PRIMITIVETYPES, URLPARAMS } from 'CommonModel'; import { DataService } from 'DataService'; import { environment } from 'environment'; -import { KDUPRIMITIVELEVEL, NSData, VDUPRIMITIVELEVEL } from 'NSDModel'; +import { KDUPRIMITIVELEVEL, NSData, VDUPRIMITIVELEVEL, VNFPROFILE } from 'NSDModel'; import { NSPrimitiveParams } from 'NSInstanceModel'; import { RestService } from 'RestService'; import { SharedService } from 'SharedService'; import { isNullOrUndefined } from 'util'; +import { CONFIGPRIMITIVE, DF, VDUCONFIG, VDUPROFILE, VNFCONFIG, VNFD } from 'VNFDModel'; /** * Creating component @@ -76,13 +77,13 @@ export class NSPrimitiveComponent implements OnInit { public primitiveList: {}[]; /** Contains objects that is used to hold types of primitive @public */ - public primitiveTypeList: {}[] = []; + public primitiveTypeList: PRIMITIVETYPES[] = []; /** Model value used to hold selected primitive type @public */ public primitiveType: string; /** Contains list of VDU primitive lists @public */ - public vduList: {}[]; + public vduList: VDUPROFILE[]; /** Contains list of KDU primitive lists @public */ public kduList: {}[]; @@ -137,12 +138,15 @@ export class NSPrimitiveComponent implements OnInit { ]; } + /** convenience getter for easy access to form fields */ + get f(): FormGroup['controls'] { return this.primitiveForm.controls; } + /** * Lifecyle Hooks the trigger before component is instantiate */ public ngOnInit(): void { /** Setting up initial value for NSD */ - this.dataService.currentMessage.subscribe((event: NSData) => { + this.dataService.currentMessage.subscribe((event: NSData): void => { if (event.identifier !== undefined || event.identifier !== '' || event.identifier !== null) { this.nsdId = event.identifier; } @@ -150,14 +154,11 @@ export class NSPrimitiveComponent implements OnInit { this.initializeForm(); } - /** convenience getter for easy access to form fields */ - get f(): FormGroup['controls'] { return this.primitiveForm.controls; } - /** initialize Forms @public */ public initializeForm(): void { this.primitiveForm = this.formBuilder.group({ primitive: [null, [Validators.required]], - vnf_member_index: [null, [Validators.required]], + member_vnf_index: [null, [Validators.required]], vdu_id: [null, [Validators.required]], kdu_name: [null, [Validators.required]], primitive_params: this.formBuilder.array([this.primitiveParamsBuilder()]) @@ -194,7 +195,7 @@ export class NSPrimitiveComponent implements OnInit { this.objectPrimitiveParams = {}; this.sharedService.cleanForm(this.primitiveForm); if (this.primitiveForm.invalid) { return; } // Proceed, onces form is valid - this.primitiveForm.value.primitive_params.forEach((params: NSPrimitiveParams) => { + this.primitiveForm.value.primitive_params.forEach((params: NSPrimitiveParams): void => { if (params.primitive_params_name !== null && params.primitive_params_value !== '') { this.objectPrimitiveParams[params.primitive_params_name] = params.primitive_params_value; } @@ -206,17 +207,17 @@ export class NSPrimitiveComponent implements OnInit { }; if (this.primitiveType === 'VNF_Primitive') { // tslint:disable-next-line: no-string-literal - primitiveParamsPayLoads['vnf_member_index'] = this.primitiveForm.value.vnf_member_index; + primitiveParamsPayLoads['member_vnf_index'] = this.primitiveForm.value.member_vnf_index; } if (this.primitiveType === 'VDU_Primitive') { // tslint:disable-next-line: no-string-literal - primitiveParamsPayLoads['vnf_member_index'] = this.primitiveForm.value.vnf_member_index; + primitiveParamsPayLoads['member_vnf_index'] = this.primitiveForm.value.member_vnf_index; // tslint:disable-next-line: no-string-literal primitiveParamsPayLoads['vdu_id'] = this.primitiveForm.value.vdu_id; } if (this.primitiveType === 'KDU_Primitive') { // tslint:disable-next-line: no-string-literal - primitiveParamsPayLoads['vnf_member_index'] = this.primitiveForm.value.vnf_member_index; + primitiveParamsPayLoads['member_vnf_index'] = this.primitiveForm.value.member_vnf_index; // tslint:disable-next-line: no-string-literal primitiveParamsPayLoads['kdu_name'] = this.primitiveForm.value.kdu_name; } @@ -224,23 +225,23 @@ export class NSPrimitiveComponent implements OnInit { url: environment.NSDINSTANCES_URL + '/' + this.nsdId + '/action' }; this.isLoadingResults = true; - this.restService.postResource(apiURLHeader, primitiveParamsPayLoads).subscribe((result: {}) => { + this.restService.postResource(apiURLHeader, primitiveParamsPayLoads).subscribe((result: {}): void => { this.activeModal.dismiss(); this.notifierService.notify('success', this.translateService.instant('PAGE.NSPRIMITIVE.EXECUTEDSUCCESSFULLY')); this.isLoadingResults = false; - }, (error: ERRORDATA) => { + }, (error: ERRORDATA): void => { this.isLoadingResults = false; this.restService.handleError(error, 'post'); }); } /** Primitive type change event @public */ - public primitiveTypeChange(data: { value: string }): void { + public primitiveTypeChange(data: PRIMITIVETYPES): void { this.primitiveList = []; this.primitiveParameter = []; this.initializeForm(); if (data.value === 'NS_Primitive') { this.getNSInfo(this.params.name); - this.setUpdateValueandValidation('vnf_member_index'); + this.setUpdateValueandValidation('member_vnf_index'); } if (data.value === 'VNF_Primitive' || data.value === 'KDU_Primitive' || data.value === 'NS_Primitive') { this.setUpdateValueandValidation('vdu_id'); @@ -250,11 +251,11 @@ export class NSPrimitiveComponent implements OnInit { } } /** Member index change event */ - public indexChange(data: {}, getType?: string): void { + public indexChange(data: VNFPROFILE, getType?: string): void { this.getFormControl('vdu_id').setValue(null); this.getFormControl('kdu_name').setValue(null); - if (data) { - this.getVnfdInfo(data['vnfd-id-ref'], getType); + if (data['vnfd-id'] !== null) { + this.getVnfdInfo(data['vnfd-id'], getType); } else { this.primitiveList = []; this.getFormControl('primitive').setValue(null); @@ -266,7 +267,7 @@ export class NSPrimitiveComponent implements OnInit { this.primitiveList = data[selectedType + '-configuration']['config-primitive']; } /** Primivtive change event */ - public primitiveChange(data: { parameter: {}[] }): void { + public primitiveChange(data: PRIMITIVEDATA): void { this.primitiveParameter = []; const formArr: FormArray = this.getFormControl('primitive_params') as FormArray; formArr.controls = []; @@ -276,11 +277,13 @@ export class NSPrimitiveComponent implements OnInit { } } /** Generate vdu section @public */ - public generateVDUData(vduData: VDUPRIMITIVELEVEL): VDUPRIMITIVELEVEL { + public generateVDUData(vduData: VDUPROFILE, vduConfig: VDUCONFIG[]): VDUPROFILE { + const getVDUConfig: VDUCONFIG = vduConfig.filter((itemData: VDUCONFIG): boolean => + itemData.id === vduData['vdu-configuration-id'])[0]; return { id: vduData.id, - name: vduData.name, - 'vdu-configuration': vduData['vdu-configuration'] + name: vduData.id, + 'vdu-configuration': getVDUConfig }; } /** Generate kdu section @public */ @@ -297,13 +300,13 @@ export class NSPrimitiveComponent implements OnInit { this.getFormControl(formName).updateValueAndValidity(); } /** Update primitive value based on parameter */ - private updatePrimitive(primitive: { parameter: {}[] }): void { + private updatePrimitive(primitive: PRIMITIVEDATA): void { if (primitive.parameter) { this.primitiveParameter = primitive.parameter; } else { this.primitiveParameter = []; const formArr: AbstractControl[] = this.getControls(); - formArr.forEach((formGp: FormGroup) => { + formArr.forEach((formGp: FormGroup): void => { formGp.controls.primitive_params_name.setValidators([]); formGp.controls.primitive_params_name.updateValueAndValidity(); formGp.controls.primitive_params_value.setValidators([]); @@ -316,24 +319,33 @@ export class NSPrimitiveComponent implements OnInit { this.primitiveList = []; this.primitiveParameter = []; this.getFormControl('primitive').setValue(null); - const apiUrl: string = environment.VNFPACKAGES_URL + '?short-name=' + vnfdRef; + const apiUrl: string = environment.VNFPACKAGES_URL + '?product-name=' + vnfdRef; this.isLoadingResults = true; this.restService.getResource(apiUrl) - .subscribe((vnfdInfo: {}) => { - if (vnfdInfo[0]['vnf-configuration'] !== undefined && vnfdInfo[0]['vnf-configuration']) { + .subscribe((vnfdInfo: VNFD[]): void => { + const vnfInstances: VNFD = vnfdInfo[0]; + if (!isNullOrUndefined(vnfInstances.df) && !isNullOrUndefined(vnfInstances['vnf-configuration'])) { this.getFormControl('vdu_id').setValidators([]); this.getFormControl('kdu_name').setValidators([]); - this.primitiveList = vnfdInfo[0]['vnf-configuration']['config-primitive']; + vnfInstances.df.forEach((df: DF): void => { + if (df['vnf-configuration-id'] !== undefined) { + const vnfprimitiveList: VNFCONFIG = vnfInstances['vnf-configuration'] + .filter((itemData: VNFCONFIG): boolean => itemData.id === df['vnf-configuration-id'])[0]; + this.primitiveList = vnfprimitiveList['config-primitive']; + } + }); } if (getType === 'VDU_Primitive') { this.kduList = []; this.vduList = []; this.primitiveList = []; - if (!isNullOrUndefined(vnfdInfo[0].vdu)) { - vnfdInfo[0].vdu.forEach((vduData: VDUPRIMITIVELEVEL) => { - if (vduData['vdu-configuration']) { - const vduDataObj: VDUPRIMITIVELEVEL = this.generateVDUData(vduData); - this.vduList.push(vduDataObj); + if (!isNullOrUndefined(vnfInstances.df) && !isNullOrUndefined(vnfInstances['vdu-configuration'])) { + vnfInstances.df.forEach((df: DF): void => { + if (df['vdu-profile'] !== undefined) { + df['vdu-profile'].forEach((element: VDUPROFILE): void => { + const vduDataObj: VDUPROFILE = this.generateVDUData(element, vnfInstances['vdu-configuration']); + this.vduList.push(vduDataObj); + }); } }); } @@ -342,8 +354,8 @@ export class NSPrimitiveComponent implements OnInit { this.kduList = []; this.vduList = []; this.primitiveList = []; - if (!isNullOrUndefined(vnfdInfo[0].kdu)) { - vnfdInfo[0].kdu.forEach((kduData: KDUPRIMITIVELEVEL) => { + if (!isNullOrUndefined(vnfInstances.kdu)) { + vnfInstances.kdu.forEach((kduData: KDUPRIMITIVELEVEL): void => { if (kduData['kdu-configuration']) { const kduDataObj: KDUPRIMITIVELEVEL = this.generateKDUData(kduData); this.kduList.push(kduDataObj); @@ -352,7 +364,7 @@ export class NSPrimitiveComponent implements OnInit { } } this.isLoadingResults = false; - }, (error: ERRORDATA) => { + }, (error: ERRORDATA): void => { this.isLoadingResults = false; this.restService.handleError(error, 'get'); }); @@ -362,10 +374,10 @@ export class NSPrimitiveComponent implements OnInit { this.primitiveList = []; this.primitiveParameter = []; this.getFormControl('primitive').setValue(null); - const apiUrl: string = environment.NSDESCRIPTORS_URL + '?short-name=' + nsdRef; + const apiUrl: string = environment.NSDESCRIPTORS_URL + '?name=' + nsdRef; this.isLoadingResults = true; this.restService.getResource(apiUrl) - .subscribe((nsdInfo: {}) => { + .subscribe((nsdInfo: {}): void => { if (!isNullOrUndefined(nsdInfo[0]['ns-configuration'])) { this.primitiveList = !isNullOrUndefined(nsdInfo[0]['ns-configuration']['config-primitive']) ? nsdInfo[0]['ns-configuration']['config-primitive'] : []; @@ -373,7 +385,7 @@ export class NSPrimitiveComponent implements OnInit { this.primitiveList = []; } this.isLoadingResults = false; - }, (error: ERRORDATA) => { + }, (error: ERRORDATA): void => { this.isLoadingResults = false; this.restService.handleError(error, 'get'); }); diff --git a/src/app/instances/ns-topology/NSTopologyComponent.html b/src/app/instances/ns-topology/NSTopologyComponent.html index 0a3051c..d500535 100644 --- a/src/app/instances/ns-topology/NSTopologyComponent.html +++ b/src/app/instances/ns-topology/NSTopologyComponent.html @@ -61,10 +61,6 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i
- - - - diff --git a/src/app/instances/ns-topology/NSTopologyComponent.ts b/src/app/instances/ns-topology/NSTopologyComponent.ts index 44c6309..668f251 100644 --- a/src/app/instances/ns-topology/NSTopologyComponent.ts +++ b/src/app/instances/ns-topology/NSTopologyComponent.ts @@ -27,7 +27,7 @@ import { ERRORDATA } from 'CommonModel'; import * as d3 from 'd3'; import { environment } from 'environment'; import * as HttpStatus from 'http-status-codes'; -import { VNFDCONNECTIONPOINTREF } from 'NSDModel'; +import { CCI, DF, VLC, VNFPROFILE } from 'NSDModel'; import { COMPOSERNODES, CONNECTIONPOINT, NSD, NSDVLD, NSINFO, NSInstanceDetails, NSINSTANCENODES, VLINFO, VNFRINFO } from 'NSInstanceModel'; import { GRAPHDETAILS, Tick, TickPath } from 'NSTopologyModel'; import { RestService } from 'src/services/RestService'; @@ -159,7 +159,7 @@ export class NSTopologyComponent { this.force.stop(); } this.forceSimulationActive = alreadyFixedIsActive; - this.nodes.forEach((d: COMPOSERNODES) => { + this.nodes.forEach((d: COMPOSERNODES): void => { d.fx = (alreadyFixedIsActive) ? null : d.x; d.fy = (alreadyFixedIsActive) ? null : d.y; }); @@ -211,49 +211,48 @@ export class NSTopologyComponent { } /** Prepare all the information for node creation @private */ private generateData(): void { - this.restService.getResource(environment.NSINSTANCESCONTENT_URL + '/' + this.nsIdentifier).subscribe((nsData: NSInstanceDetails) => { - this.nsData = nsData; - this.nsInfo = { - nsInstanceID: nsData._id, - nsName: nsData.name, - nsOperationalStatus: nsData['operational-status'], - nsConfigStatus: nsData['config-status'], - nsDetailedStatus: nsData['detailed-status'], - nsResourceOrchestrator: nsData['resource-orchestrator'] - }; - if (this.nsData['constituent-vnfr-ref'] !== undefined) { - this.generateVNFRCPNodes(); - } - if (this.nsData.vld !== undefined) { - this.generateVLDNetworkNodes(); - } - setTimeout(() => { - this.pushAllNodes(); - this.generateVNFDCP(); - this.generateVLDCP(); + this.restService.getResource(environment.NSINSTANCESCONTENT_URL + '/' + this.nsIdentifier) + .subscribe((nsData: NSInstanceDetails): void => { + this.nsData = nsData; + this.nsInfo = { + nsInstanceID: nsData._id, + nsName: nsData.name, + nsOperationalStatus: nsData['operational-status'], + nsConfigStatus: nsData['config-status'], + nsDetailedStatus: nsData['detailed-status'], + nsResourceOrchestrator: nsData['resource-orchestrator'] + }; + if (this.nsData['constituent-vnfr-ref'] !== undefined) { + this.generateVNFRCPNodes(); + } + if (this.nsData.vld !== undefined) { + this.generateVLDNetworkNodes(); + } + setTimeout((): void => { + this.pushAllNodes(); + this.generateVNFDCP(); + this.generateVLDCP(); + this.isLoadingResults = false; + this.createNode(this.nodes, this.links); + }, this.TIMEOUT); + }, (error: ERRORDATA): void => { this.isLoadingResults = false; - this.createNode(this.nodes, this.links); - }, this.TIMEOUT); - }, (error: ERRORDATA) => { - this.isLoadingResults = false; - if (error.error.status === HttpStatus.NOT_FOUND || error.error.status === HttpStatus.UNAUTHORIZED) { - this.router.navigateByUrl('404', { skipLocationChange: true }).catch(); - } else { - this.restService.handleError(error, 'get'); - } - }); + if (error.error.status === HttpStatus.NOT_FOUND || error.error.status === HttpStatus.UNAUTHORIZED) { + this.router.navigateByUrl('404', { skipLocationChange: true }).catch(); + } else { + this.restService.handleError(error, 'get'); + } + }); } - /** Fetching all the VNFR Information @private */ private generateVNFRCPNodes(): void { - this.nsData['constituent-vnfr-ref'].forEach((vnfdrID: string) => { - this.restService.getResource(environment.VNFINSTANCES_URL + '/' + vnfdrID).subscribe((vndfrDetail: NSD) => { + this.nsData['constituent-vnfr-ref'].forEach((vnfdrID: string): void => { + this.restService.getResource(environment.VNFINSTANCES_URL + '/' + vnfdrID).subscribe((vndfrDetail: NSD): void => { this.nodes.push({ id: vndfrDetail['vnfd-ref'] + ':' + vndfrDetail['member-vnf-index-ref'], nodeTypeRef: 'vnfd', cp: vndfrDetail['connection-point'], vdur: vndfrDetail.vdur, - vld: vndfrDetail.vld, nsID: vndfrDetail['nsr-id-ref'], vnfdID: vndfrDetail['vnfd-id'], vimID: vndfrDetail['vim-account-id'], @@ -264,7 +263,7 @@ export class NSTopologyComponent { selectorId: 'nsInst-' + vndfrDetail.id }); // Fetching all the connection point of VNF & Interface - vndfrDetail['connection-point'].forEach((cp: CONNECTIONPOINT) => { + vndfrDetail['connection-point'].forEach((cp: CONNECTIONPOINT): void => { this.nodes.push({ id: cp.name + ':' + vndfrDetail['member-vnf-index-ref'], vndfCPRef: vndfrDetail['vnfd-ref'] + ':' + vndfrDetail['member-vnf-index-ref'], @@ -272,32 +271,29 @@ export class NSTopologyComponent { name: cp.name }); }); - }, (error: ERRORDATA) => { + }, (error: ERRORDATA): void => { this.restService.handleError(error, 'get'); }); }); } - /** Fetching all the VLD/Network Information @private */ private generateVLDNetworkNodes(): void { this.nsdData = this.nsData.nsd; - this.nsdData.vld.forEach((ref: NSDVLD) => { + this.nsdData['virtual-link-desc'].forEach((ref: NSDVLD): void => { this.nodes.push({ id: ref.id, nodeTypeRef: 'vld', - name: ref.name, + name: ref.id, type: ref.type, - vnfdCP: ref['vnfd-connection-point-ref'], + vnfdCP: this.nsdData.df, vimNetworkName: ref['vim-network-name'], - shortName: ref['short-name'], selectorId: 'nsInst-' + ref.id }); }); } - /** Pushing connection points of path/links nodes @private */ private pushAllNodes(): void { - this.nodes.forEach((nodeList: NSINSTANCENODES) => { + this.nodes.forEach((nodeList: NSINSTANCENODES): void => { if (nodeList.nodeTypeRef === 'vnfd') { this.vnfdNodes.push(nodeList); } else if (nodeList.nodeTypeRef === 'vld') { @@ -307,13 +303,12 @@ export class NSTopologyComponent { } }); } - /** Get CP position based on vndf @private */ private generateVNFDCP(): void { - this.vnfdNodes.forEach((list: NSINSTANCENODES) => { - const vndfPos: number = this.nodes.map((e: NSINSTANCENODES) => { return e.id; }).indexOf(list.id); + this.vnfdNodes.forEach((list: NSINSTANCENODES): void => { + const vndfPos: number = this.nodes.map((e: NSINSTANCENODES): string => { return e.id; }).indexOf(list.id); this.cpCount = 0; - this.nodes.forEach((res: NSINSTANCENODES) => { + this.nodes.forEach((res: NSINSTANCENODES): void => { if (res.nodeTypeRef === 'cp' && res.vndfCPRef === list.id) { this.links.push({ source: this.nodes[vndfPos], target: this.nodes[this.cpCount] }); } @@ -321,44 +316,49 @@ export class NSTopologyComponent { }); }); } - /** Get CP position based on vld @private */ private generateVLDCP(): void { let vldPos: number = 0; - this.vldNodes.forEach((list: NSINSTANCENODES) => { + this.vldNodes.forEach((list: NSINSTANCENODES): void => { if (!isNullOrUndefined(list.vnfdCP)) { - list.vnfdCP.forEach((cpRef: VNFDCONNECTIONPOINTREF) => { - this.cpCount = 0; - this.nodes.forEach((res: NSINSTANCENODES) => { - if (res.nodeTypeRef === 'cp' && res.id === cpRef['vnfd-connection-point-ref'] + ':' + cpRef['member-vnf-index-ref']) { - this.links.push({ source: this.nodes[vldPos], target: this.nodes[this.cpCount] }); - } - this.cpCount++; + list.vnfdCP.forEach((cpRef: DF): void => { + cpRef['vnf-profile'].forEach((vnfProfile: VNFPROFILE): void => { + vnfProfile['virtual-link-connectivity'].forEach((resultVLC: VLC, index: number): void => { + resultVLC['constituent-cpd-id'].forEach((resultCCI: CCI): void => { + this.cpCount = 0; + this.nodes.forEach((res: NSINSTANCENODES): void => { + if (res.nodeTypeRef === 'cp' && + res.id === resultCCI['constituent-cpd-id'] + ':' + resultCCI['constituent-base-element-id']) { + this.links.push({ source: this.nodes[vldPos], target: this.nodes[this.cpCount] }); + } + this.cpCount++; + }); + }); + }); }); }); vldPos++; } }); } - /** Node is created and render at D3 region @private */ private createNode(nodes: NSINSTANCENODES[], links: {}[]): void { const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr(); d3.selectAll('svg#graphContainer > *').remove(); - d3.select(window).on('keydown', () => { this.keyDown(); }); - d3.select(window).on('keyup', () => { this.keyUp(); }); + d3.select(window).on('keydown', (): void => { this.keyDown(); }); + d3.select(window).on('keyup', (): void => { this.keyUp(); }); this.svg = d3.select('#graphContainer') .attr('oncontextmenu', 'return false;') .attr('width', graphContainerAttr.width) .attr('height', graphContainerAttr.height); this.force = d3.forceSimulation() .force('charge', d3.forceManyBody().strength(graphContainerAttr.strength)) - .force('link', d3.forceLink().id((d: TickPath) => d.id).distance(graphContainerAttr.distance)) + .force('link', d3.forceLink().id((d: TickPath): string => d.id).distance(graphContainerAttr.distance)) .force('center', d3.forceCenter(graphContainerAttr.width / graphContainerAttr.forcex, graphContainerAttr.height / graphContainerAttr.forcey)) .force('x', d3.forceX(graphContainerAttr.width / graphContainerAttr.forcex)) .force('y', d3.forceY(graphContainerAttr.height / graphContainerAttr.forcey)) - .on('tick', () => { this.tick(); }); + .on('tick', (): void => { this.tick(); }); // handles to link and node element groups this.path = this.svg.append('svg:g').selectAll('path'); this.network = this.svg.append('svg:g').selectAll('network'); @@ -366,12 +366,11 @@ export class NSTopologyComponent { this.circle = this.svg.append('svg:g').selectAll('circle'); this.restart(nodes, links); } - /** Update force layout (called automatically each iteration) @private */ private tick(): void { const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr(); // draw directed edges with proper padding from node centers - this.path.attr('class', 'link').attr('d', (d: Tick) => { + this.path.attr('class', 'link').attr('d', (d: Tick): string => { const deltaX: number = d.target.x - d.source.x; const deltaY: number = d.target.y - d.source.y; const dist: number = Math.sqrt(deltaX * deltaX + deltaY * deltaY); @@ -385,29 +384,27 @@ export class NSTopologyComponent { const targetY: number = d.target.y - (targetPadding * normY); return `M${sourceX},${sourceY}L${targetX},${targetY}`; }); - this.network.attr('transform', (t: TickPath) => `translate(${t.x},${t.y})`); - this.square.attr('transform', (t: TickPath) => `translate(${t.x},${t.y})`); - this.circle.attr('transform', (t: TickPath) => `translate(${t.x},${t.y})`); + this.network.attr('transform', (t: TickPath): string => `translate(${t.x},${t.y})`); + this.square.attr('transform', (t: TickPath): string => `translate(${t.x},${t.y})`); + this.circle.attr('transform', (t: TickPath): string => `translate(${t.x},${t.y})`); } - /** Update graph (called when needed) @private */ private restart(nodes: NSINSTANCENODES[], links: {}[]): void { const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr(); this.path = this.path.data(links); const vnfdNodes: {}[] = []; const vldNodes: {}[] = []; const cpNodes: {}[] = []; // NB: Nodes are known by id, not by index! - nodes.forEach((nodeList: NSINSTANCENODES) => { + nodes.forEach((nodeList: NSINSTANCENODES): void => { if (nodeList.nodeTypeRef === 'vnfd') { vnfdNodes.push(nodeList); } else if (nodeList.nodeTypeRef === 'vld') { vldNodes.push(nodeList); } else if (nodeList.nodeTypeRef === 'cp') { cpNodes.push(nodeList); } }); - this.square = this.square.data(vnfdNodes, (d: { id: number }) => d.id); - this.network = this.network.data(vldNodes, (d: { id: number }) => d.id); - this.circle = this.circle.data(cpNodes, (d: { id: number }) => d.id); + this.square = this.square.data(vnfdNodes, (d: COMPOSERNODES): string => d.id); + this.network = this.network.data(vldNodes, (d: COMPOSERNODES): string => d.id); + this.circle = this.circle.data(cpNodes, (d: COMPOSERNODES): string => d.id); this.resetAndCreateNodes(); this.force.nodes(nodes).force('link').links(links); //Set the graph in motion this.force.alphaTarget(graphContainerAttr.alphaTarget).restart(); } - /** Rest and create nodes @private */ private resetAndCreateNodes(): void { this.path.exit().remove(); @@ -424,7 +421,6 @@ export class NSTopologyComponent { this.path = gPath.merge(this.path); this.circle = this.gCircle.merge(this.circle); } - /** Events handles when Shift Click to perform create cp @private */ // tslint:disable-next-line: no-any private singleClick(nodeSelected: any, d: COMPOSERNODES): void { @@ -470,16 +466,16 @@ export class NSTopologyComponent { .style('opacity', 1) .attr('x', graphContainerAttr.imageX) .attr('y', graphContainerAttr.imageY) - .attr('id', (d: COMPOSERNODES) => { return d.selectorId; }) + .call(this.onDragDrop()) + .attr('id', (d: COMPOSERNODES): string => { return d.selectorId; }) .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight) .attr('xlink:href', 'assets/images/VNFD.svg') - .on('click', (d: COMPOSERNODES) => { this.singleClick(this.gSquare, d); this.onNodeClickToggleSidebar(); }); + .on('click', (d: COMPOSERNODES): void => { this.singleClick(this.gSquare, d); this.onNodeClickToggleSidebar(); }); this.gSquare.append('svg:text') .attr('class', 'node_text') .attr('y', graphContainerAttr.textY) - .text((d: COMPOSERNODES) => d.id); + .text((d: COMPOSERNODES): string => d.id); } - /** Settings all the network attributes of nodes @private */ private getgNetwork(): void { const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr(); @@ -489,16 +485,16 @@ export class NSTopologyComponent { .style('opacity', 1) .attr('x', graphContainerAttr.imageX) .attr('y', graphContainerAttr.imageY) - .attr('id', (d: COMPOSERNODES) => { return d.selectorId; }) + .call(this.onDragDrop()) + .attr('id', (d: COMPOSERNODES): string => { return d.selectorId; }) .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight) .attr('xlink:href', 'assets/images/VL.svg') - .on('click', (d: COMPOSERNODES) => { this.singleClick(this.gNetwork, d); this.onNodeClickToggleSidebar(); }); + .on('click', (d: COMPOSERNODES): void => { this.singleClick(this.gNetwork, d); this.onNodeClickToggleSidebar(); }); this.gNetwork.append('svg:text') .attr('class', 'node_text') .attr('y', graphContainerAttr.textY) - .text((d: COMPOSERNODES) => d.name); + .text((d: COMPOSERNODES): string => d.name); } - /** Settings all the connection point attributes of nodes @private */ private getgCircle(): void { const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr(); @@ -508,14 +504,22 @@ export class NSTopologyComponent { .style('opacity', 1) .attr('x', graphContainerAttr.imageX) .attr('y', graphContainerAttr.imageY) + .call(this.onDragDrop()) .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight) .attr('xlink:href', 'assets/images/CP.svg'); this.gCircle.append('svg:text') .attr('class', 'node_text') .attr('y', graphContainerAttr.textY) - .text((d: COMPOSERNODES) => d.name); + .text((d: COMPOSERNODES): string => d.name); + } + /** drag event @private */ + // tslint:disable-next-line: no-any + private onDragDrop(): any { + return d3.drag().filter(this.dragFilter) + .on('start', this.dragstarted) + .on('drag', this.dragged) + .on('end', this.dragended); } - /** Key press event @private */ private keyDown(): void { const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr(); @@ -545,6 +549,10 @@ export class NSTopologyComponent { this.svg.classed('ctrl', false); } } + /** Events handles when to drag using filter for the keys @private */ + private dragFilter(): boolean { + return d3.event.ctrlKey && !d3.event.button; + } /** Events handles when dragstarted @private */ private dragstarted(d: COMPOSERNODES): void { d.fx = d.x; diff --git a/src/app/instances/vnf-instances/VNFInstancesComponent.ts b/src/app/instances/vnf-instances/VNFInstancesComponent.ts index d829ee2..fdfe9fa 100644 --- a/src/app/instances/vnf-instances/VNFInstancesComponent.ts +++ b/src/app/instances/vnf-instances/VNFInstancesComponent.ts @@ -141,7 +141,7 @@ export class VNFInstancesComponent implements OnInit { this.isLoadingResults = true; this.restService.getResource(environment.VNFINSTANCES_URL).subscribe((vnfInstancesData: VNFInstanceDetails[]) => { this.vnfInstanceData = []; - vnfInstancesData.forEach((vnfInstanceData: VNFInstanceDetails) => { + vnfInstancesData.forEach((vnfInstanceData: VNFInstanceDetails): void => { const vnfDataObj: {} = { VNFD: vnfInstanceData['vnfd-ref'], diff --git a/src/app/layouts/header/HeaderComponent.html b/src/app/layouts/header/HeaderComponent.html index a9ff5ac..c7b3bae 100644 --- a/src/app/layouts/header/HeaderComponent.html +++ b/src/app/layouts/header/HeaderComponent.html @@ -15,13 +15,16 @@ limitations under the License. Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in) --> -Here is a newer {{'APPVERSION' | translate}} {{PACKAGEVERSION}} - of OSM! + + {{'NEWVERSIONTAG' | translate:{appVersion: sharedService.osmVersion} }} + +
short-name{{(virtualLink.shortName)?virtualLink.shortName:'-'}}
Name {{(virtualLink.name)?virtualLink.name:'-'}}
- - + + - - + +
{{'PAGE.NSPACKAGE.NSCOMPOSE.MEMBER-VNF-INDEX' | translate}}{{ vnfData['member-vnf-index'] }}id{{ vnfData.id }}
{{'PAGE.NSPACKAGE.NSCOMPOSE.VNFD-ID-REF' | translate}}{{ vnfData['vnfd-id-ref'] }}vnfd-id{{ vnfData['vnfd-id'] }}
@@ -154,20 +127,24 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i - - + + + + + + - - + + - - + + - - + +
{{'PAGE.NSPACKAGE.NSCOMPOSE.VLD-ID' | translate}}{{ vlDetails['name'] }}id{{ vnfData.id }}
vnfd-id{{ vnfData['vnfd-id'] }}
{{'PAGE.NSPACKAGE.NSCOMPOSE.VNFD-CP-REF' | translate}}{{ cpData['vnfd-connection-point-ref'] }}constituent-base-element-id{{ cpData['constituent-base-element-id'] }}
{{'MEMBERINDEX' | translate}}{{ cpData['member-vnf-index-ref'] }}constituent-cpd-id{{ cpData['constituent-cpd-id'] }}
{{'PAGE.NSPACKAGE.NSCOMPOSE.VNFD-ID-REF' | translate}}{{ cpData['vnfd-id-ref'] }}virtual-link-profile-id{{ virtualLinkProfileID }}
@@ -211,9 +188,9 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i
  • + container="body" ngbTooltip="{{ list['product-name'] }}"> -  {{ list['short-name'] }} +  {{ list['product-name'] }}
diff --git a/src/app/packages/ns-packages/ns-composer/NSComposerComponent.ts b/src/app/packages/ns-packages/ns-composer/NSComposerComponent.ts index 687f4fa..7ef8394 100644 --- a/src/app/packages/ns-packages/ns-composer/NSComposerComponent.ts +++ b/src/app/packages/ns-packages/ns-composer/NSComposerComponent.ts @@ -18,7 +18,6 @@ /** * @file NS Compose Component */ -// tslint:disable: no-increment-decrement import { HttpHeaders } from '@angular/common/http'; import { Component, ElementRef, Injector, ViewChild, ViewEncapsulation } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; @@ -32,11 +31,20 @@ import { DataService } from 'DataService'; import { environment } from 'environment'; import * as HttpStatus from 'http-status-codes'; import * as jsyaml from 'js-yaml'; -import { COMPOSERNODES, CONSTITUENTVNFD, GRAPHDETAILS, NSDDetails, Tick, TickPath, VLD, VNFDCONNECTIONPOINTREF } from 'NSDModel'; +import { + CCI, + COMPOSERNODES, + DF, + GRAPHDETAILS, + NSData, + NSDATACREATION, + NSDDetails, + Tick, TickPath, VLC, VLD, VNFPROFILE +} from 'NSDModel'; import { RestService } from 'RestService'; import { SharedService } from 'SharedService'; import { isNullOrUndefined } from 'util'; -import { VNFData, VNFDDetails } from 'VNFDModel'; +import { VNFD, VNFData } from 'VNFDModel'; /** * Creating component @@ -57,14 +65,11 @@ export class NSComposerComponent { /** dataService to pass the data from one component to another @public */ public dataService: DataService; /** Contains VNFD Informations @public */ - public vnfdPackageDetails: VNFData = { identifier: '', shortName: '', vendor: '', description: '', version: '', id: '', name: '' }; + public nsPackageDetails: NSData = { id: '', name: '', description: '', version: '', designer: '' }; /** Contains VL Details @public */ - public vlDetails: VLD = { - name: '', - 'mgmt-network': true, - 'vim-network-name': '', - type: '', - id: '' + public virtualLinkDesc: VLD = { + id: '', + 'mgmt-network': true }; /** Contains the information of the type of modification @public */ public putType: string; @@ -87,19 +92,21 @@ export class NSComposerComponent { /** Contains the node information of VNF @public */ public vnfNodes: {}[] = []; /** contains the VNF Details @public */ - public vnfData: CONSTITUENTVNFD; + public vnfData: VNFPROFILE; + /** contains the Virtual Link connectivity Details @public */ + public virtualLinkProfileID: string; /** Need to show the VNF Details @public */ public isShowVNFDetails: boolean = false; /** Contains the node information of CP @public */ public cpNodes: {}[] = []; /** Need to show the CP Details */ - public cpData: VNFDCONNECTIONPOINTREF; + public cpData: CCI; /** Need to show the VNF Details @public */ public isShowCPDetails: boolean = false; /** random number count @public */ public randomNumberLength: number; /** Contains the vnfd information @public */ - public vnfList: VNFDDetails[] = []; + public vnfList: VNFD[] = []; /** Add the activeclass for the selected @public */ public activeClass: string = 'active'; /** Add the fixed class for the freeze @public */ @@ -109,7 +116,7 @@ export class NSComposerComponent { /** Give the message for the loading @public */ public message: string = 'PLEASEWAIT'; /** Get VNF selected node @public */ - public getVNFSelectedData: VNFDDetails[]; + public getVNFSelectedData: VNFD; /** Assign the forcesimulation active @public */ public forceSimulationActive: boolean = false; /** Assign pinned class for the button when freezed @public */ @@ -145,26 +152,14 @@ export class NSComposerComponent { private force: any; /** Contains all the selected node @private */ private selectedNode: COMPOSERNODES[] = []; - /** variables used for CP @private */ - private iConnectionPointRef: number = 0; /** Contains the connected point @private */ private connectionPoint: string; - /** Contains all the NSD information @private */ - private nsd: string; - /** Contains all the VNFD information @private */ - private vnfd: string; /** Contains id of the node @private */ private identifier: string; - /** Variables used for cp @private */ - private jConnectionPointRef: number = 0; /** Contains copy of NSD information @private */ private nsdCopy: string; /** Contains the VNFD copy @private */ private vnfdCopy: string; - /** Contains name of the node @private */ - private name: string; - /** Contains member vnf index value of the node @private */ - private memberVnfIndexValue: number = 0; /** Contains path information of the node */ // tslint:disable-next-line:no-any private path: any; @@ -198,8 +193,8 @@ export class NSComposerComponent { private setVnfdName: string; /** Contains all methods related to shared @private */ private sharedService: SharedService; - /** Contains selected node VLD objects @private */ - private selectedVLDResult: VLD; + /** Contains selected node VNF profile objects @private */ + private selectedVNFProfile: VNFPROFILE[]; constructor(injector: Injector) { this.injector = injector; @@ -234,106 +229,107 @@ export class NSComposerComponent { } /** On clicking redirect to NS edit page @public */ public onEdit(): void { - this.router.navigate(['/packages/ns/edit/', this.identifier]).catch(() => { + this.router.navigate(['/packages/ns/edit/', this.identifier]).catch((): void => { // Catch Navigation Error }); } /** Events handles drop at D3 region @public */ public drop(ev: DragEvent): void { - event.preventDefault(); - this.name = ev.dataTransfer.getData('text'); - if (this.name === 'vl') { + ev.preventDefault(); + const getDropedName: string = ev.dataTransfer.getData('text'); + if (getDropedName === 'vl') { this.svg.selectAll('*').remove(); this.vldropComposer(); } else { this.svg.selectAll('*').remove(); - this.vnfd = ev.dataTransfer.getData('text'); - this.vnfdropComposer(); + const vnfdName: string = ev.dataTransfer.getData('text'); + this.vnfdropComposer(vnfdName); } } /** Drop VL Composer Data @public */ public vldropComposer(): void { this.randomNumberLength = CONSTANTNUMBER.randomNumber; - const generateId: string = 'ns_vl_' + this.randomString( - this.randomNumberLength, - '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' - ); - if (this.nsData.vld !== undefined) { - this.nsData.vld.push({ - 'vim-network-name': 'PUBLIC', - name: generateId, - 'mgmt-network': true, - type: 'ELAN', - id: generateId - }); - } else { - Object.assign(this.nsData, { - vld: [{ - 'vim-network-name': 'PUBLIC', - name: generateId, - 'mgmt-network': true, - type: 'ELAN', - id: generateId - }] - }); + const generateId: string = 'ns_vl_' + this.sharedService.randomString(); + if (this.nsData['virtual-link-desc'] === undefined) { + this.nsData['virtual-link-desc'] = []; } + this.nsData['virtual-link-desc'].push({ + id: generateId, + 'mgmt-network': false + }); this.putType = 'nsdadd'; this.addData(environment.NSDESCRIPTORS_URL, this.identifier, this.nsData, this.putType); } /** Drop VNFD Composer Data @public */ - public vnfdropComposer(): void { - if (this.nsData['constituent-vnfd'] !== undefined) { - this.nsData['constituent-vnfd'].push({ - 'vnfd-id-ref': this.vnfd, - 'member-vnf-index': ++this.memberVnfIndexValue + public vnfdropComposer(vnfdName: string): void { + const vnfID: string = 'ns_vnfd_' + this.sharedService.randomString(); + if (this.nsData.df.length > 0) { + this.addVNFDID(vnfdName); + this.nsData.df.forEach((res: DF): void => { + if (res['vnf-profile'] === undefined) { + res['vnf-profile'] = []; + } + res['vnf-profile'].push({ + id: vnfID, + 'virtual-link-connectivity': [], + 'vnfd-id': vnfdName + }); }); } else { - Object.assign(this.nsData, { - 'constituent-vnfd': [{ - 'vnfd-id-ref': this.vnfd, - 'member-vnf-index': ++this.memberVnfIndexValue + Object.assign(this.nsData.df, { + id: 'default-df', + 'vnf-profile': [{ + id: vnfID, + 'virtual-link-connectivity': [], + 'vnfd-id': vnfdName }] }); } this.putType = 'vnfdadd'; this.addData(environment.NSDESCRIPTORS_URL, this.identifier, this.nsData, this.putType); } + /** Add the VNFD-ID while drop VNFD if not exists @public */ + public addVNFDID(vnfdName: string): void { + const vnfdIDArray: string[] = this.nsData['vnfd-id']; + if (vnfdIDArray !== undefined) { + if (vnfdIDArray.indexOf(vnfdName) === -1) { + vnfdIDArray.push(vnfdName); + } + } else { + Object.assign(this.nsData, { + 'vnfd-id': [vnfdName] + }); + } + } /** Events handles allow drop on D3 region @public */ public allowDrop(ev: DragEvent): void { ev.preventDefault(); } /** Save NSD Information @public */ public saveNSD(): void { - if (this.vnfdPackageDetails.shortName !== undefined) { - this.nsData['short-name'] = this.vnfdPackageDetails.shortName; - } - if (this.vnfdPackageDetails.vendor !== undefined) { - this.nsData.vendor = this.vnfdPackageDetails.vendor; + if (this.nsPackageDetails.id !== undefined) { + this.nsData.id = this.nsPackageDetails.id; } - if (this.vnfdPackageDetails.description !== undefined) { - this.nsData.description = this.vnfdPackageDetails.description; + if (this.nsPackageDetails.name !== undefined) { + this.nsData.name = this.nsPackageDetails.name; } - if (this.vnfdPackageDetails.version !== undefined) { - this.nsData.version = this.vnfdPackageDetails.version; + if (this.nsPackageDetails.description !== undefined) { + this.nsData.description = this.nsPackageDetails.description; } - if (this.vnfdPackageDetails.id !== undefined) { - this.nsData.id = this.vnfdPackageDetails.id; + if (this.nsPackageDetails.version !== undefined) { + this.nsData.version = this.nsPackageDetails.version; } - if (this.vnfdPackageDetails.name !== undefined) { - this.nsData.name = this.vnfdPackageDetails.name; + if (this.nsPackageDetails.designer !== undefined) { + this.nsData.designer = this.nsPackageDetails.designer; } this.putType = 'nsdUpdate'; this.addData(environment.NSDESCRIPTORS_URL, this.identifier, this.nsData, this.putType); } /** Save Virtual Link @public */ public saveVL(vlid: string): void { - this.nsData.vld.forEach((result: VLD) => { + this.nsData['virtual-link-desc'].forEach((result: VLD): void => { if (result.id === vlid) { - result.name = this.vlDetails.name; - result['mgmt-network'] = !isNullOrUndefined(this.vlDetails['mgmt-network']) ? this.vlDetails['mgmt-network'] : true; - result['vim-network-name'] = !isNullOrUndefined(this.vlDetails['vim-network-name']) ? this.vlDetails['vim-network-name'] : ''; - result.type = this.vlDetails.type; - result.id = this.vlDetails.id; + result['mgmt-network'] = !isNullOrUndefined(this.virtualLinkDesc['mgmt-network']) ? this.virtualLinkDesc['mgmt-network'] : true; } }); this.putType = 'vlUpdate'; @@ -367,18 +363,17 @@ export class NSComposerComponent { url: apiURL + '/' + identifier + '/nsd_content', httpOptions: { headers: this.headers } }; - const nsData: {} = {}; - nsData['nsd:nsd-catalog'] = {}; - nsData['nsd:nsd-catalog'].nsd = []; - nsData['nsd:nsd-catalog'].nsd.push(data); - const descriptorInfo: string = jsyaml.dump(nsData, {sortKeys: true}); + const nsData: NSDATACREATION = { nsd: { nsd: [] } }; + nsData.nsd.nsd = []; + nsData.nsd.nsd.push(data); + const descriptorInfo: string = jsyaml.dump(nsData, { sortKeys: true }); this.sharedService.targzFile({ packageType: 'nsd', id: this.identifier, descriptor: descriptorInfo }) .then((content: ArrayBuffer): void => { - this.restService.putResource(apiURLHeader, content).subscribe((res: {}) => { + this.restService.putResource(apiURLHeader, content).subscribe((res: {}): void => { this.generateData(); this.notifierService.notify('success', this.translateService.instant(successMessage)); this.isLoadingResults = false; - }, (error: ERRORDATA) => { + }, (error: ERRORDATA): void => { this.generateData(); this.restService.handleError(error, 'put'); this.isLoadingResults = false; @@ -393,7 +388,7 @@ export class NSComposerComponent { const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' }); modalRef.componentInstance.topologyType = 'Info'; modalRef.componentInstance.topologytitle = this.translateService.instant('PAGE.TOPOLOGY.INFO'); - modalRef.result.then((result: MODALCLOSERESPONSEDATA) => { + modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => { if (result) { // empty } @@ -408,7 +403,7 @@ export class NSComposerComponent { this.force.stop(); } this.forceSimulationActive = alreadyFixedIsActive; - this.nodes.forEach((d: COMPOSERNODES) => { + this.nodes.forEach((d: COMPOSERNODES): void => { d.fx = (alreadyFixedIsActive) ? null : d.x; d.fy = (alreadyFixedIsActive) ? null : d.y; }); @@ -430,9 +425,9 @@ export class NSComposerComponent { } /** Prepare the information of the VNFD @private */ private generateVNFData(): void { - this.restService.getResource(environment.VNFPACKAGESCONTENT_URL).subscribe((vnfdPackageData: VNFDDetails[]) => { + this.restService.getResource(environment.VNFPACKAGESCONTENT_URL).subscribe((vnfdPackageData: VNFD[]): void => { this.vnfList = vnfdPackageData; - }, (error: ERRORDATA) => { + }, (error: ERRORDATA): void => { this.restService.handleError(error, 'get'); }); } @@ -440,32 +435,29 @@ export class NSComposerComponent { private generateDataNSDTopology(): void { this.nodes = []; this.links = []; - this.iConnectionPointRef = 0; - this.jConnectionPointRef = 0; - this.restService.getResource(environment.NSDESCRIPTORSCONTENT_URL + '/' + this.identifier).subscribe((nsData: NSDDetails) => { + this.restService.getResource(environment.NSDESCRIPTORSCONTENT_URL + '/' + this.identifier).subscribe((nsData: NSDDetails): void => { delete nsData._admin; delete nsData._id; delete nsData._links; this.nsData = nsData; - this.vnfdPackageDetails.shortName = nsData['short-name']; - this.vnfdPackageDetails.vendor = nsData.vendor; - this.vnfdPackageDetails.description = nsData.description; - this.vnfdPackageDetails.version = nsData.version; - this.vnfdPackageDetails.id = nsData.id; - this.vnfdPackageDetails.name = nsData.name; - if (nsData.vld !== undefined) { + this.generateNSInfo(nsData); + if (nsData['virtual-link-desc'] !== undefined) { /** Details of the VL */ this.nsDataVLD(nsData); } - if (nsData['constituent-vnfd'] !== undefined) { - /** Details of the VNFD */ - this.nsDataConstituentVNFD(nsData); + if (this.nsData.df.length > 0) { + this.nsData.df.forEach((res: DF): void => { + if (res['vnf-profile'] !== undefined) { + /** Details of the VNFD */ + this.nsDataConstituentVNFD(nsData); + } + }); } - if (nsData.vld !== undefined) { + if (nsData.df.length > 0) { this.nsDataVLDLinkCreation(nsData); } this.separateAndCreatenode(); - }, (error: ERRORDATA) => { + }, (error: ERRORDATA): void => { if (error.error.status === HttpStatus.NOT_FOUND || error.error.status === HttpStatus.UNAUTHORIZED) { this.router.navigateByUrl('404', { skipLocationChange: true }).catch(); } else { @@ -475,78 +467,88 @@ export class NSComposerComponent { this.isShowNSDDetails = false; }); } - /** nsData-vld undefined Call this function @private */ + /** Generate the NS Package Information */ + private generateNSInfo(nsData: NSDDetails): void { + this.nsPackageDetails.id = nsData.id; + this.nsPackageDetails.name = nsData.name; + this.nsPackageDetails.description = nsData.description; + this.nsPackageDetails.version = nsData.version; + this.nsPackageDetails.designer = nsData.designer; + } + /** nsData VL node creation function @private */ private nsDataVLD(nsData: NSDDetails): void { - nsData.vld.forEach((res: VLD) => { + nsData['virtual-link-desc'].forEach((res: VLD): void => { this.nodes.push({ id: res.id, reflexive: false, type: 'vld', name: res.id, selectorId: res.id }); - this.nsd = res.id; - if (res['vnfd-connection-point-ref'] !== undefined) { - res['vnfd-connection-point-ref'].forEach((result: VNFDCONNECTIONPOINTREF) => { - this.nodes.push( - { - id: this.nsd + ++this.iConnectionPointRef + ':' + result['vnfd-connection-point-ref'], - reflexive: false, - type: 'ns', - name: result['vnfd-connection-point-ref'], - nodeIndex: result['member-vnf-index-ref'], - selectorId: result['vnfd-connection-point-ref'] + '_' + result['member-vnf-index-ref'] + '-osm-' + this.nsd - }); - }); - } }); } - /** nsData constituent-vnfd undefined Call this function @private */ + /** nsData VNFD node creation function @private */ private nsDataConstituentVNFD(nsData: NSDDetails): void { - nsData['constituent-vnfd'].forEach((res: CONSTITUENTVNFD) => { - this.nodes.push( - { - id: res['vnfd-id-ref'] + ':' + res['member-vnf-index'], - reflexive: false, - type: 'vnfd', - name: res['vnfd-id-ref'], - nodeIndex: res['member-vnf-index'], - selectorId: res['vnfd-id-ref'] + '_' + res['member-vnf-index'] - }); - this.vnfd = res['vnfd-id-ref']; - this.memberVnfIndexValue = res['member-vnf-index']; + nsData.df.forEach((resDF: DF): void => { + resDF['vnf-profile'].forEach((resVNF: VNFPROFILE): void => { + this.nodes.push( + { + id: resVNF['vnfd-id'] + ':' + resVNF.id, + reflexive: false, + type: 'vnfd', + name: resVNF['vnfd-id'], + nodeIndex: resVNF.id, + selectorId: resVNF['vnfd-id'] + '_' + resVNF.id + }); + if (resVNF['virtual-link-connectivity'] !== undefined) { + this.nsDataCP(resVNF, resVNF.id); + } + }); }); } - - /** nsData-vld undefined Call this function @private */ - private nsDataVLDLinkCreation(nsData: NSDDetails): void { - nsData.vld.forEach((res: VLD) => { - this.nsdCopy = res.id; - if (res['vnfd-connection-point-ref'] !== undefined) { - this.nsDataVNFDConnectionPointRefrence(res); - } + /** nsData CP node creation function @private */ + private nsDataCP(resVNF: VNFPROFILE, vnfID: string): void { + resVNF['virtual-link-connectivity'].forEach((resultVLC: VLC, index: number): void => { + resultVLC['constituent-cpd-id'].forEach((resultCCI: CCI): void => { + this.nodes.push( + { + id: vnfID + ':' + resultCCI['constituent-base-element-id'] + index + ':' + resultCCI['constituent-cpd-id'], + reflexive: false, + type: 'ns', + name: resultCCI['constituent-cpd-id'], + nodeIndex: resultCCI['constituent-base-element-id'], + selectorId: 'osm-' + resultCCI['constituent-cpd-id'] + '-' + vnfID + resultCCI['constituent-base-element-id'] + index + }); + }); }); } - /** nsData-vnfd-connection-point-ref undefined Call this function @private */ - private nsDataVNFDConnectionPointRefrence(res: VLD): void { - res['vnfd-connection-point-ref'].forEach((result: VNFDCONNECTIONPOINTREF) => { - this.connectionPoint = this.nsdCopy + ++this.jConnectionPointRef + ':' + result['vnfd-connection-point-ref']; - this.vnfdCopy = result['vnfd-id-ref'] + ':' + result['member-vnf-index-ref']; - const connectionPointPos: number = this.nodes.map((e: COMPOSERNODES) => { return e.id; }).indexOf(this.connectionPoint); - const nsdPos: number = this.nodes.map((e: COMPOSERNODES) => { return e.id; }).indexOf(this.nsdCopy); - const vnfdPos: number = this.nodes.map((e: COMPOSERNODES) => { return e.id; }).indexOf(this.vnfdCopy); - this.links.push( - { - source: this.nodes[connectionPointPos], - target: this.nodes[nsdPos] - }, - { - source: this.nodes[connectionPointPos], - target: this.nodes[vnfdPos] + /** nsData Link node creation function @private */ + private nsDataVLDLinkCreation(nsData: NSDDetails): void { + nsData.df.forEach((resDF: DF): void => { + if (resDF['vnf-profile'] !== undefined) { + resDF['vnf-profile'].forEach((resVNF: VNFPROFILE): void => { + this.nsdCopy = resVNF['vnfd-id'] + ':' + resVNF.id; + if (resVNF['virtual-link-connectivity'] !== undefined) { + this.nsDataVNFDConnectionPointRefrence(resVNF); + } }); + } }); } - /** Generate random string @private */ - private randomString(length: number, chars: string): string { - let result: string = ''; - for (let randomStringRef: number = length; randomStringRef > 0; --randomStringRef) { - result += chars[Math.floor(Math.random() * chars.length)]; - } - return result; + /** nsDataVNFDConnectionPointRefrence undefined Call this function @private */ + private nsDataVNFDConnectionPointRefrence(resVNF: VNFPROFILE): void { + resVNF['virtual-link-connectivity'].forEach((resultVLC: VLC, index: number): void => { + resultVLC['constituent-cpd-id'].forEach((resultCCI: CCI): void => { + this.vnfdCopy = resultVLC['virtual-link-profile-id']; + this.connectionPoint = resVNF.id + ':' + resultCCI['constituent-base-element-id'] + index + ':' + resultCCI['constituent-cpd-id']; + const connectionPointPos: number = this.nodes.map((e: COMPOSERNODES): string => { return e.id; }).indexOf(this.connectionPoint); + const nsdPos: number = this.nodes.map((e: COMPOSERNODES): string => { return e.id; }).indexOf(this.nsdCopy); + const vnfdPos: number = this.nodes.map((e: COMPOSERNODES): string => { return e.id; }).indexOf(this.vnfdCopy); + this.links.push( + { + source: this.nodes[connectionPointPos], + target: this.nodes[nsdPos] + }, + { + source: this.nodes[connectionPointPos], + target: this.nodes[vnfdPos] + }); + }); + }); } /** Separate and create node @private */ private separateAndCreatenode(): void { @@ -581,7 +583,7 @@ export class NSComposerComponent { /** Separate the nodes along with its tyep @private */ private seprateNodes(node: COMPOSERNODES[]): void { this.vlNodes = []; this.vnfNodes = []; this.cpNodes = []; - node.forEach((nodeList: COMPOSERNODES) => { + node.forEach((nodeList: COMPOSERNODES): void => { if (nodeList.type === 'vld') { this.vlNodes.push(nodeList); } else if (nodeList.type === 'vnfd') { @@ -595,21 +597,20 @@ export class NSComposerComponent { private createnode(node: COMPOSERNODES[]): void { const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr(); d3.selectAll('svg#graphContainer > *').remove(); - d3.select(window).on('keydown', () => { this.keyDown(); }); - d3.select(window).on('keyup', () => { this.keyUp(); }); + d3.select(window).on('keydown', (): void => { this.keyDown(); }); + d3.select(window).on('keyup', (): void => { this.keyUp(); }); this.svg = d3.select('#graphContainer') .attr('oncontextmenu', 'return false;') - .attr('width', graphContainerAttr.width) - .attr('height', graphContainerAttr.height) - .on('mousemove', () => { this.mousemove(); }); + .attr('viewBox', `0 0 ${graphContainerAttr.width} ${graphContainerAttr.height}`) + .on('mousemove', (): void => { this.mousemove(); }); this.force = d3.forceSimulation() .force('charge', d3.forceManyBody().strength(graphContainerAttr.strength)) - .force('link', d3.forceLink().id((d: TickPath) => d.id).distance(graphContainerAttr.distance)) + .force('link', d3.forceLink().id((d: TickPath): string => d.id).distance(graphContainerAttr.distance)) .force('center', d3.forceCenter(graphContainerAttr.width / graphContainerAttr.forcex, graphContainerAttr.height / graphContainerAttr.forcey)) .force('x', d3.forceX(graphContainerAttr.width / graphContainerAttr.forcex)) .force('y', d3.forceY(graphContainerAttr.height / graphContainerAttr.forcey)) - .on('tick', () => { this.tick(); }); + .on('tick', (): void => { this.tick(); }); this.dragLine = this.svg.append('svg:path').attr('class', 'link dragline hidden').attr('d', 'M0,0L0,0'); this.path = this.svg.append('svg:g').selectAll('path'); this.vlNode = this.svg.append('svg:g').selectAll('vlnode'); @@ -622,7 +623,7 @@ export class NSComposerComponent { private tick(): void { const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr(); // draw directed edges with proper padding from node centers - this.path.attr('class', 'link').attr('d', (d: Tick) => { + this.path.attr('class', 'link').attr('d', (d: Tick): string => { const deltaX: number = d.target.x - d.source.x; const deltaY: number = d.target.y - d.source.y; const dist: number = Math.sqrt(deltaX * deltaX + deltaY * deltaY); @@ -635,18 +636,18 @@ export class NSComposerComponent { const targetX: number = d.target.x - (targetPadding * normX); const targetY: number = d.target.y - (targetPadding * normY); return `M${sourceX},${sourceY}L${targetX},${targetY}`; - }).on('dblclick', (d: Tick) => { this.getDeleteLinkConfirmation(d); }); - this.vlNode.attr('transform', (t: TickPath) => `translate(${t.x},${t.y})`); - this.vnfdnode.attr('transform', (t: TickPath) => `translate(${t.x},${t.y})`); - this.cpnode.attr('transform', (t: TickPath) => `translate(${t.x},${t.y})`); + }).on('dblclick', (d: Tick): void => { this.getDeleteLinkConfirmation(d); }); + this.vlNode.attr('transform', (t: TickPath): string => `translate(${t.x},${t.y})`); + this.vnfdnode.attr('transform', (t: TickPath): string => `translate(${t.x},${t.y})`); + this.cpnode.attr('transform', (t: TickPath): string => `translate(${t.x},${t.y})`); } /** Update graph (called when needed) at D3 region @private */ private restart(node: COMPOSERNODES[]): void { const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr(); this.path = this.path.data(this.links); - this.vlNode = this.vlNode.data(this.vlNodes, (d: COMPOSERNODES) => d.id); - this.vnfdnode = this.vnfdnode.data(this.vnfNodes, (d: COMPOSERNODES) => d.id); - this.cpnode = this.cpnode.data(this.cpNodes, (d: COMPOSERNODES) => d.id); + this.vlNode = this.vlNode.data(this.vlNodes, (d: COMPOSERNODES): string => d.id); + this.vnfdnode = this.vnfdnode.data(this.vnfNodes, (d: COMPOSERNODES): string => d.id); + this.cpnode = this.cpnode.data(this.cpNodes, (d: COMPOSERNODES): string => d.id); this.resetAndCreateNodes(); this.force.nodes(node).force('link').links(this.links); this.force.alphaTarget(graphContainerAttr.alphaTarget).restart(); @@ -679,17 +680,18 @@ export class NSComposerComponent { .style('opacity', 1) .attr('x', graphContainerAttr.imageX) .attr('y', graphContainerAttr.imageY) - .attr('id', (d: COMPOSERNODES) => { return d.selectorId; }) + .call(this.onDragDrop()) + .attr('id', (d: COMPOSERNODES): string => { return d.selectorId; }) .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight) .attr('xlink:href', 'assets/images/VL.svg') - .on('mousedown', (d: COMPOSERNODES) => { this.mouseDown(d); }) - .on('mouseup', (d: COMPOSERNODES) => { this.mouseUp(d); }) - .on('click', (d: COMPOSERNODES) => { this.singleClick(this.vlNode, d); this.onNodeClickToggleSidebar(); }) - .on('dblclick', (d: COMPOSERNODES) => { this.getDeleteConfirmation(d); this.onNodedblClickToggleSidebar(); }); + .on('mousedown', (d: COMPOSERNODES): void => { this.mouseDown(d); }) + .on('mouseup', (d: COMPOSERNODES): void => { this.mouseUp(d); }) + .on('click', (d: COMPOSERNODES): void => { this.singleClick(this.vlNode, d); this.onNodeClickToggleSidebar(); }) + .on('dblclick', (d: COMPOSERNODES): void => { this.getDeleteConfirmation(d); this.onNodedblClickToggleSidebar(); }); this.gvlNode.append('svg:text') .attr('class', 'node_text') .attr('y', graphContainerAttr.textY) - .text((d: COMPOSERNODES) => d.id); + .text((d: COMPOSERNODES): string => d.id); } /** Setting all the VNFD nodes @private */ private getVNFDNodes(): void { @@ -700,17 +702,18 @@ export class NSComposerComponent { .style('opacity', 1) .attr('x', graphContainerAttr.imageX) .attr('y', graphContainerAttr.imageY) - .attr('id', (d: COMPOSERNODES) => { return d.selectorId; }) + .call(this.onDragDrop()) + .attr('id', (d: COMPOSERNODES): string => { return d.selectorId; }) .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight) .attr('xlink:href', 'assets/images/VNFD.svg') - .on('mousedown', (d: COMPOSERNODES) => { this.mouseDown(d); }) - .on('mouseup', (d: COMPOSERNODES) => { this.mouseUp(d); }) - .on('click', (d: COMPOSERNODES) => { this.singleClick(this.vnfdnode, d); this.onNodeClickToggleSidebar(); }) - .on('dblclick', (d: COMPOSERNODES) => { this.getDeleteConfirmation(d); this.onNodedblClickToggleSidebar(); }); + .on('mousedown', (d: COMPOSERNODES): void => { this.mouseDown(d); }) + .on('mouseup', (d: COMPOSERNODES): void => { this.mouseUp(d); }) + .on('click', (d: COMPOSERNODES): void => { this.singleClick(this.vnfdnode, d); this.onNodeClickToggleSidebar(); }) + .on('dblclick', (d: COMPOSERNODES): void => { this.getDeleteConfirmation(d); this.onNodedblClickToggleSidebar(); }); this.gvnfdNode.append('svg:text') .attr('class', 'node_text') .attr('y', graphContainerAttr.textY) - .text((d: COMPOSERNODES) => d.id); + .text((d: COMPOSERNODES): string => d.name); } /** Setting all the CP nodes @private */ private getCPNodes(): void { @@ -721,17 +724,18 @@ export class NSComposerComponent { .style('opacity', 1) .attr('x', graphContainerAttr.imageX) .attr('y', graphContainerAttr.imageY) - .attr('id', (d: COMPOSERNODES) => { return d.selectorId; }) + .call(this.onDragDrop()) + .attr('id', (d: COMPOSERNODES): string => { return d.selectorId; }) .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight) .attr('xlink:href', 'assets/images/CP.svg') - .on('mousedown', (d: COMPOSERNODES) => { this.mouseDown(d); }) - .on('mouseup', (d: COMPOSERNODES) => { this.mouseUp(d); }) - .on('click', (d: COMPOSERNODES) => { this.singleClick(this.cpnode, d); this.onNodeClickToggleSidebar(); }) - .on('dblclick', (d: COMPOSERNODES) => { this.getDeleteConfirmation(d); this.onNodedblClickToggleSidebar(); }); + .on('mousedown', (d: COMPOSERNODES): void => { this.mouseDown(d); }) + .on('mouseup', (d: COMPOSERNODES): void => { this.mouseUp(d); }) + .on('click', (d: COMPOSERNODES): void => { this.singleClick(this.cpnode, d); this.onNodeClickToggleSidebar(); }) + .on('dblclick', (d: COMPOSERNODES): void => { this.getDeleteConfirmation(d); this.onNodedblClickToggleSidebar(); }); this.gcpNode.append('svg:text') .attr('class', 'node_text') .attr('y', graphContainerAttr.textY) - .text((d: COMPOSERNODES) => d.id); + .text((d: COMPOSERNODES): string => d.name); } /** Events handles when mousemove it will capture the selected node data @private */ private mousemove(): void { @@ -740,41 +744,43 @@ export class NSComposerComponent { `M${this.mousedownNode.x},${this.mousedownNode.y}L${d3.mouse(d3.event.currentTarget)[0]},${d3.mouse(d3.event.currentTarget)[1]}`); } /** Get confirmation Before Deleting the Link in Topology @private */ - private getAddConfirmation(mouseData: COMPOSERNODES, getNsData: NSDDetails, addType: string, getVLDIndex: number): void { + private getAddConfirmation(mouseData: COMPOSERNODES, getNsData: NSDDetails, addType: string, getVLDIndex: string): void { let findVNFName: string = ''; let findVLDID: string = ''; if (mouseData.type === 'vld') { findVNFName = this.mouseupNode.name; findVLDID = this.mousedownNode.id; + this.vlName = this.mousedownNode.name; } else { findVNFName = this.mousedownNode.name; findVLDID = this.mouseupNode.id; + this.vlName = this.mouseupNode.name; + } + if (getNsData['vnfd-id'] !== undefined) { + getNsData['vnfd-id'].forEach((resVNFid: string): void => { + if (resVNFid === findVNFName) { + this.getVNFSelectedData = this.vnfList.filter((vnfList: VNFD): boolean => vnfList.id === findVNFName)[0]; + this.setVnfdConnectionPointRef = this.getVNFSelectedData['mgmt-cp']; + this.setVnfdName = this.getVNFSelectedData['product-name']; + this.selectedVNFProfile = getNsData.df[0]['vnf-profile']; + } + }); } - getNsData.vld.forEach((result: VLD) => { - if (result.id === findVLDID) { - this.vlName = result.name; - this.getVNFSelectedData = this.vnfList.filter((vnfList: VNFDDetails) => vnfList.id === findVNFName); - this.setVnfdConnectionPointRef = this.getVNFSelectedData[0]['mgmt-interface'].cp; - this.setVnfdName = this.getVNFSelectedData[0].name; - this.selectedVLDResult = result; - } - }); if (this.vlName !== undefined && this.setVnfdName !== undefined && this.setVnfdConnectionPointRef !== undefined) { const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' }); modalRef.componentInstance.topologyType = 'Add'; - modalRef.componentInstance.cpDetails = this.getVNFSelectedData[0]['connection-point']; + modalRef.componentInstance.cpDetails = this.getVNFSelectedData['ext-cpd']; this.translateService.get('PAGE.TOPOLOGY.ADDINGCP', { vlname: '' + this.vlName + '', vnfdname: '' + this.setVnfdName + '', cpname: '' + this.setVnfdConnectionPointRef + '' - }).subscribe((res: string) => { + }).subscribe((res: string): void => { modalRef.componentInstance.topologyname = res; }); modalRef.componentInstance.topologytitle = this.translateService.instant('PAGE.TOPOLOGY.CONNECTIONPOINT'); - modalRef.result.then((result: MODALCLOSERESPONSEWITHCP) => { + modalRef.result.then((result: MODALCLOSERESPONSEWITHCP): void => { if (result) { - this.nsData = getNsData; - this.generateCPForVNF(this.selectedVLDResult, result.connection_point, getVLDIndex); + this.generateCPForVNF(this.selectedVNFProfile, result.connection_point, getVLDIndex); this.addData(environment.NSDESCRIPTORS_URL, this.identifier, getNsData, addType); } else { this.deselectPath(); @@ -785,26 +791,32 @@ export class NSComposerComponent { this.notifierService.notify('error', this.translateService.instant('ERROR')); } } - /** Generate connection point for vnf using vld @private */ - private generateCPForVNF(result: VLD, cp: string, getVLDIndex: number): void { - if (result['vnfd-connection-point-ref'] !== undefined) { - result['vnfd-connection-point-ref'].push({ - 'member-vnf-index-ref': getVLDIndex, - 'vnfd-connection-point-ref': cp, - 'vnfd-id-ref': this.getVNFSelectedData[0].name + private generateCPForVNF(result: VNFPROFILE[], cp: string, getVLDIndex: string): void { + if (result !== undefined) { + result.forEach((resultVNFPROFILE: VNFPROFILE, index: number): void => { + if (getVLDIndex === resultVNFPROFILE.id) { + resultVNFPROFILE['virtual-link-connectivity'].push({ + 'constituent-cpd-id': [{ + 'constituent-base-element-id': getVLDIndex, + 'constituent-cpd-id': cp + }], + 'virtual-link-profile-id': this.vlName + }); + } }); } else { Object.assign(result, { - 'vnfd-connection-point-ref': [{ - 'member-vnf-index-ref': getVLDIndex, - 'vnfd-connection-point-ref': cp, - 'vnfd-id-ref': this.getVNFSelectedData[0].name + 'virtual-link-connectivity': [{ + 'constituent-cpd-id': [{ + 'constituent-base-element-id': getVLDIndex, + 'constituent-cpd-id': cp + }], + 'virtual-link-profile-id': this.vlName }] }); } } - /** Events handles when mousedown click it will capture the selected node data @private */ private mouseDown(d: COMPOSERNODES): void { event.preventDefault(); @@ -827,12 +839,12 @@ export class NSComposerComponent { this.mouseupNode = d; if (this.mousedownNode.type === 'vld' && this.mouseupNode.type === 'vnfd') { const getOldVLDIndex: string[] = this.mouseupNode.id.split(':'); - const setOldVLDindex: number = +getOldVLDIndex[1]; + const setOldVLDindex: string = getOldVLDIndex[1]; this.putType = 'cpAdded'; this.getAddConfirmation(this.mousedownNode, this.nsData, this.putType, setOldVLDindex); } else if (this.mousedownNode.type === 'vnfd' && this.mouseupNode.type === 'vld') { const getOldVLDIndex: string[] = this.mousedownNode.id.split(':'); - const setOldVLDindex: number = +getOldVLDIndex[1]; + const setOldVLDindex: string = getOldVLDIndex[1]; this.putType = 'cpAdded'; this.getAddConfirmation(this.mousedownNode, this.nsData, this.putType, setOldVLDindex); } else if (this.mousedownNode.type === 'vnfd' && this.mouseupNode.type === 'ns') { @@ -894,27 +906,39 @@ export class NSComposerComponent { this.deselectAllNodes(); nodeSeleced.select('#' + d.selectorId).classed(this.activeClass, !alreadyIsActive); if (d.type === 'vld' && !alreadyIsActive) { - this.nsData.vld.forEach((result: VLD) => { + this.nsData['virtual-link-desc'].forEach((result: VLD): void => { if (result.id === d.id) { this.showRightSideInfo(false, true, false, false); - this.vlDetails = result; + this.virtualLinkDesc = result; } }); } else if (d.type === 'vnfd' && !alreadyIsActive) { - this.nsData['constituent-vnfd'].forEach((result: CONSTITUENTVNFD) => { - if (result['member-vnf-index'] === d.nodeIndex && result['vnfd-id-ref'] === d.name) { - this.showRightSideInfo(false, false, true, false); - this.vnfData = result; + this.nsData.df.forEach((res: DF): void => { + if (res['vnf-profile'] !== undefined) { + res['vnf-profile'].forEach((resVNF: VNFPROFILE): void => { + if (resVNF.id === d.nodeIndex && resVNF['vnfd-id'] === d.name) { + this.showRightSideInfo(false, false, true, false); + this.vnfData = resVNF; + } + }); } }); } else if (d.type === 'ns' && !alreadyIsActive) { - this.nsData.vld.forEach((result: VLD) => { - if (result['vnfd-connection-point-ref'] !== undefined) { - result['vnfd-connection-point-ref'].forEach((resultCP: VNFDCONNECTIONPOINTREF) => { - if (resultCP['member-vnf-index-ref'] === d.nodeIndex && resultCP['vnfd-connection-point-ref'] === d.name) { - this.cpData = resultCP; - this.vlDetails = result; - this.showRightSideInfo(false, false, false, true); + this.nsData.df.forEach((resultDF: DF): void => { + if (resultDF['vnf-profile'] !== undefined) { + resultDF['vnf-profile'].forEach((resVNF: VNFPROFILE): void => { + if (resVNF['virtual-link-connectivity'] !== undefined) { + resVNF['virtual-link-connectivity'].forEach((resultVLC: VLC, index: number): void => { + resultVLC['constituent-cpd-id'].forEach((resultCCI: CCI): void => { + const connectionPointID: string = resVNF.id + ':' + resultCCI['constituent-base-element-id'] + index + ':' + resultCCI['constituent-cpd-id']; + if (connectionPointID === d.id) { + this.cpData = resultCCI; + this.vnfData = resVNF; + this.virtualLinkProfileID = resultVLC['virtual-link-profile-id']; + this.showRightSideInfo(false, false, false, true); + } + }); + }); } }); } @@ -927,9 +951,9 @@ export class NSComposerComponent { private getDeleteLinkConfirmation(d: Tick): void { const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' }); modalRef.componentInstance.topologyType = 'Delete'; - modalRef.componentInstance.topologyname = this.translateService.instant('PAGE.TOPOLOGY.LINK'); + modalRef.componentInstance.topologyname = this.translateService.instant('PAGE.TOPOLOGY.LINK') + ' - ' + d.source.id; modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.LINK'; - modalRef.result.then((result: MODALCLOSERESPONSEDATA) => { + modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => { if (result) { this.doubleClickLink(d); } @@ -938,20 +962,32 @@ export class NSComposerComponent { /** Events handles when Double Click to Delete the link @private */ private doubleClickLink(d: Tick): void { let getID: string = ''; - if (d.target.type === 'vld') { - getID = d.target.id; - } else if (d.source.type === 'vld') { + let getName: string = ''; + let getNodeIndex: string; + if (d.source.type === 'ns') { getID = d.source.id; + getName = d.source.name; + getNodeIndex = d.source.nodeIndex; } - this.nodes.forEach((res: COMPOSERNODES) => { - if (res.id === getID) { - if (this.nsData.vld !== undefined) { - this.nsData.vld.forEach((vldresult: VLD) => { - if (vldresult.id === getID) { - delete vldresult['vnfd-connection-point-ref']; - } - }); - } + /** Split the selected node of connectionpoint */ + const selectedNode: string[] = getID.split(':'); + this.nsData.df.forEach((resultDF: DF): void => { + if (resultDF['vnf-profile'] !== undefined) { + resultDF['vnf-profile'].forEach((elementVNF: VNFPROFILE): void => { + const selectedVNFProfileID: string = selectedNode[0]; + /** If VNF ID is equal to selected VNFProfile ID check the VLC of CCI to match the id and name to remove the VLC index */ + if (selectedVNFProfileID === elementVNF.id) { + elementVNF['virtual-link-connectivity'].forEach((elementVLC: VLC, index: number): void => { + const posCCI: number = elementVLC['constituent-cpd-id'].findIndex((e: CCI): boolean => { + const getCID: string = elementVNF.id + ':' + e['constituent-base-element-id'] + index + ':' + e['constituent-cpd-id']; + return getID === getCID; + }); + if (posCCI !== -1) { + elementVNF['virtual-link-connectivity'].splice(index, 1); + } + }); + } + }); } }); this.putType = 'linkdelete'; @@ -969,7 +1005,7 @@ export class NSComposerComponent { } else if (d.type === 'ns') { modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.CONNECTIONPOINT'; } - modalRef.result.then((result: MODALCLOSERESPONSEDATA) => { + modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => { if (result) { this.doubleClick(d); } @@ -978,72 +1014,95 @@ export class NSComposerComponent { /** Events handles when Double Click to Delete @private */ private doubleClick(d: COMPOSERNODES): void { const deletedNode: COMPOSERNODES = d; - this.nodes.forEach((res: COMPOSERNODES) => { + this.nodes.forEach((res: COMPOSERNODES, i: number): void => { if (res.id === d.id) { if (deletedNode.type === 'vld') { - const pos: number = this.nsData.vld.map((e: VLD) => { return e.id; }).indexOf(d.id); - this.nsData.vld.splice(pos, 1); + /** Remove the virtual-link-desc related to VL */ + const pos: number = this.nsData['virtual-link-desc'].map((e: VLD): string => { return e.id; }).indexOf(d.id); + this.nsData['virtual-link-desc'].splice(pos, 1); + /** Remove the virtual-link-connectivity between VL and VNFD */ + this.nsData.df.forEach((resultDF: DF): void => { + if (resultDF['vnf-profile'] !== undefined) { + resultDF['vnf-profile'].forEach((resVNF: VNFPROFILE): void => { + const getVLArray: number[] = resVNF['virtual-link-connectivity'].map((e: VLC, index: number): number => { + if (e['virtual-link-profile-id'] === d.id) { + return index; + } + }); + if (getVLArray.length > 0) { + getVLArray.forEach((removeIndex: number): void => { + const index: string = removeIndex.toString(); + resVNF['virtual-link-connectivity'].splice(resVNF['virtual-link-connectivity'][index], 1); + }); + } + }); + } + }); this.putType = 'nsddelete'; } else if (deletedNode.type === 'vnfd') { - const constituentVNFD: string[] = []; - if (this.nsData['constituent-vnfd'] !== undefined) { - this.nsData['constituent-vnfd'].forEach((ref: CONSTITUENTVNFD) => { - constituentVNFD.push(ref['vnfd-id-ref'] + ':' + ref['member-vnf-index']); - }); - } - const pos: number = constituentVNFD.map((e: string) => { return e; }).indexOf(d.id); - this.nsData['constituent-vnfd'].splice(pos, 1); - const getCP: string[] = d.id.split(':'); - const memberVnfIndexRef: number = +getCP[1]; - const vnfdIDRef: string = getCP[0]; - if (this.nsData.vld !== undefined) { - this.nsData.vld.forEach((resf: VLD) => { - if (resf['vnfd-connection-point-ref'] !== undefined) { - resf['vnfd-connection-point-ref'].forEach((connectionPoint: VNFDCONNECTIONPOINTREF, index: number) => { - if (+connectionPoint['member-vnf-index-ref'] === memberVnfIndexRef && connectionPoint['vnfd-id-ref'] === vnfdIDRef) { - resf['vnfd-connection-point-ref'].splice(index, 1); - } + this.nsData.df.forEach((resultDF: DF): void => { + if (resultDF['vnf-profile'] !== undefined) { + /** Remove the vnf-profile related to VNFD */ + const posVNF: number = resultDF['vnf-profile'].findIndex((e: VNFPROFILE): boolean => { + return e['vnfd-id'] === d.name && e.id === d.nodeIndex; + }); + resultDF['vnf-profile'].splice(posVNF, 1); + /** Check the VNFD exists in any vnf-profile */ + const isVNFDExists: boolean = resultDF['vnf-profile'].some((e: VNFPROFILE): boolean => { + return e['vnfd-id'] === d.name; + }); + /** If VNFD not exists in the vnf-profile remove from vnfd-id */ + if (!isVNFDExists) { + const posVNFD: number = this.nsData['vnfd-id'].findIndex((e: string): boolean => { + return e === d.name; }); + this.nsData['vnfd-id'].splice(posVNFD, 1); } - }); - } + } + }); this.putType = 'vnfddelete'; } else if (deletedNode.type === 'ns') { - const getCP: string[] = d.selectorId.split('-osm-'); - const memberVnfIndexRef: number = d.nodeIndex; - const vnfdIDRef: string = getCP[getCP.length - 1]; - if (this.nsData.vld !== undefined) { - this.nsData.vld.forEach((resf: VLD) => { - if (resf['vnfd-connection-point-ref'] !== undefined && resf.id === vnfdIDRef) { - resf['vnfd-connection-point-ref'].forEach((connectionPoint: VNFDCONNECTIONPOINTREF, index: number) => { - if (connectionPoint['member-vnf-index-ref'] === memberVnfIndexRef) { - resf['vnfd-connection-point-ref'].splice(index, 1); - } - }); - } - }); - } + /** Split the selected node */ + const selectedNode: string[] = d.id.split(':'); + this.nsData.df.forEach((resultDF: DF): void => { + if (resultDF['vnf-profile'] !== undefined) { + resultDF['vnf-profile'].forEach((elementVNF: VNFPROFILE): void => { + const selectedVNFProfileID: string = selectedNode[0]; + /** If VNF ID is equal to selected VNFProfile ID check the VLC of CCI to match the id and name to remove the VLC index */ + if (selectedVNFProfileID === elementVNF.id) { + elementVNF['virtual-link-connectivity'].forEach((elementVLC: VLC, index: number): void => { + const posCCI: number = elementVLC['constituent-cpd-id'].findIndex((e: CCI): boolean => { + const getID: string = elementVNF.id + ':' + e['constituent-base-element-id'] + index + ':' + e['constituent-cpd-id']; + return d.id === getID; + }); + if (posCCI !== -1) { + elementVNF['virtual-link-connectivity'].splice(index, 1); + } + }); + } + }); + } + }); this.putType = 'nsdelete'; } this.addData(environment.NSDESCRIPTORS_URL, this.identifier, this.nsData, this.putType); } }); } + /** drag event @private */ + // tslint:disable-next-line: no-any + private onDragDrop(): any { + return d3.drag().filter(this.dragFilter) + .on('start', this.dragstarted) + .on('drag', this.dragged) + .on('end', this.dragended); + } /** Key press event @private */ private keyDown(): void { const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr(); if (this.lastKeyDown !== -1) { return; } this.lastKeyDown = d3.event.keyCode; if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) { - this.gvlNode.call(d3.drag() - .on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended) - ); - this.gvnfdNode.call(d3.drag() - .on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended) - ); - this.gcpNode.call(d3.drag() - .on('start', this.dragstarted).on('drag', this.dragged).on('end', this.dragended) - ); this.svg.classed('ctrl', true); } } @@ -1058,6 +1117,10 @@ export class NSComposerComponent { this.svg.classed('ctrl', false); } } + /** Events handles when to drag using filter for the keys @private */ + private dragFilter(): boolean { + return d3.event.ctrlKey && !d3.event.button; + } /** Events handles when dragstarted @private */ private dragstarted(d: COMPOSERNODES): void { d.fx = d.x; diff --git a/src/app/packages/ns-packages/vnf-composer/VNFComposerComponent.html b/src/app/packages/ns-packages/vnf-composer/VNFComposerComponent.html index 2aa8f12..a947069 100644 --- a/src/app/packages/ns-packages/vnf-composer/VNFComposerComponent.html +++ b/src/app/packages/ns-packages/vnf-composer/VNFComposerComponent.html @@ -21,9 +21,12 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i